使用JavaScript创建AWS EC2实例。
#aws #javascript #node #ec2

AWS EC2是一种计算服务,可用于各种目的。 EC2是AWS提供的核心服务之一。该博客将引导我们通过创建EC2实例及其基本组件。
AWS还为不同语言提供SDK。但是我们将使用为JavaScript提供的AWS SDK。

EC2客户端

AWS EC2是AWS提供的服务之一。该博客假设您已经拥有一个AWS帐户(或具有EC2政策和许可的IAM帐户)。 AWS EC2在AWS云上提供计算服务。

要初始化EC2实例客户端,我们可以使用
来做到这一点

const client = new EC2Client({region: "us-east-1"})

这将EC2实例客户端与区域us-east-1使用。一个人可以根据他们想要托管服务器的位置选择其他区域。

证书

设置凭据是第一件事。一个人应该拥有适当的权限才能获得服务。设置凭据有不同的方法。

  1. AWS EAM的负载来自AWS EC2
  2. 来自共享凭据文件~/.aws/credentials
  3. 使用环境变量

***** aws iam角色来自AWS EC2 *****

如果我们想在现有的EC2实例上运行node.js应用程序,则Node.js应用程序可以自动从提供的现有EC2实例角色中拾取角色。一个人可以使用IAM角色到make API requests from EC2 instance.

**************************************************** 共享证书 ***************************************************

我们可以有一个具有AWS凭据初始化的文件。默认情况下,当AWS SDK启动时,它开始在基于Linux的系统中的~/.aws/credentialsC:\Users\USER_NAME\.aws\credentials中寻找默认的凭据文件。您可以从here中了解更多。

您也可以使用AWS Cli的aws configure命令来更新~/.aws/credentials文件中的凭据。当您运行aws configure流动向导会弹出。

它将要求以下内容:

  • AWS访问密钥
  • AWS Secret Acess Key
  • 和会话令牌(可选)

Screenshot 2023-04-11 at 10.36.13 PM.png

******************************************** 环境变量 ************************************

SDK将自动检测环境变量。我认为,这是向AWS SDK提供证书的最简单方法。

AWS_ACCESS_KEY_ID=<YOUR_ACCESS_KEY>

AWS_SECRET_ACCESS_KEY=<YOUR_SECRET_ACCESS_KEY>

AWS_SESSION_TOKEN=<YOUR_SESSION_TOKEN>

除此之外,还有其他添加凭据的方法。您可以找到并阅读here

ami

AMI代表Amazon Machine Image,它们是创建EC2实例的基本实体。您可以将其视为用于运行Docker容器的Docker映像。它由初始化并启动EC2实例所需的所有信息(例如操作系统,应用程序等)组成。有关更多信息,请查看official documentation

现在如何使用AWS SDK获取AMI映像ID。

const { EC2Client, DescribeImagesCommand } = require("@aws-sdk/client-ec2");

 // note: region is "us-east-1"
const client = new EC2Client({ region: "us-east-1" });

const command = new DescribeImagesCommand(params);

const start = async () => {
  try {
    const data = await client.send(command);
    console.log({ data: JSON.stringify(data.Images) });

  } catch (error) {

    console.error(error);
  }
};

在上面的代码中,我想在us-east-1区域托管我的EC2实例,因此我想知道该区域中提供的图像。

注意:如果要启动EC2实例,则该区域应存在AMI图像。

DescribeImagesCommand当我们需要验证图像是否存在在同一位置还是未弃用图像时,此CMD派上用场。

AWS虚拟私有云

aws为我们提供了一个私人网络,该网络允许我们在隔离的网络中部署实例或任何其他计算服务,这些网络可以从外部安全。每个VPC都可以由持有您的资源的子网组成。最好的事情是,一旦我们创建一个帐户,就会自动为我们创建默认的VPC。我们可以使用@aws-sdk/client-ec2 s DescribeAccountAttributesCommand获取有关默认VPC的信息。

const client = new EC2Client({ region: "us-east-1" });
const input = {
  AttributeNames: ["default-vpc"],
};
const vpc = new DescribeAccountAttributesCommand(input);
const describe = await client.send(d);
console.log({ data: JSON.stringify(describe)});

这将提供如下输出

{
  "$metadata": {
    "httpStatusCode": 200,
    "requestId": "b8d6169c-b1b2-46d3-bd3a-516b48e7e2d6",
    "attempts": 1,
    "totalRetryDelay": 0
  },
  "AccountAttributes": [
    {
      "AttributeName": "default-vpc",
      "AttributeValues": [
        {
          "AttributeValue": "vpc-00df8d4abfe081231"
        }
      ]
    }
  ]
}

由于我们定义了default-vpc的属性。我们将AttributeValue作为默认值的VPC ID。 AWS VPC是学习对于学习至关重要的核心服务之一,因为默认情况下,每个资源都在AWS VPC上启动。要注意的另一个重要的事情是资源和VPC区域和可用性区应相同

安全组

安全组充当EC2实例的防火墙,它可以控制进出实例的流量。要记住的一件事是,何时我们在EC2实例启动时未指定安全组时,将默认安全组分配给其。

默认安全组带有自己的行李,就像默认情况下所有入站流量受到限制一样。因此,我们需要明确添加规则以允许流量到我们的EC2实例,否则没有人能够从无处访问我们的实例(例如:SSH,http或https)

要使我们的实例访问外界,我们需要为TCP打开端口。但是首先,我们必须验证端口是否已经打开,但由任何其他现有的安全组

// find if we have a HTTP port already opened up
const client = new EC2Client({ region: "us-east-1" });

const sg = new DescribeSecurityGroupsCommand({
  Filters: [
    {
      Name: "egress.ip-permission.to-port",
      Values: ["80"],
    },
  ],
});

const describe = await client.send(securityG);
    console.log({ data: JSON.stringify(describe)});

,如果我们已经配置了针对端口80(TCP连接)的SG(安全组)配置的SG(安全组),则上述代码将返回对象。

输出

{
  "$metadata": {
    "httpStatusCode": 200,
    "requestId": "28e8921a-8048-4e42-b2f2-51fb0e973bbb",
    "attempts": 1,
    "totalRetryDelay": 0
  },
  "SecurityGroups": [
    {
      "Description": "Description",
      "GroupName": "Name of SG",
      "IpPermissions": [
        {
          "FromPort": 80,
          "IpProtocol": "tcp",
          "IpRanges": [{ "CidrIp": "0.0.0.0/0" }],
          "Ipv6Ranges": [{ "CidrIpv6": "::/0" }],
          "PrefixListIds": [],
          "ToPort": 80,
          "UserIdGroupPairs": []
        }
    ]
}]

这是从上面函数返回的对象。让我们看一下IpPermission对象。 IpPermission保留了确定流量进出实例的规则。

  • fromport:允许的端口范围
  • ipprotocol:它将是TCPUDP网络层协议(即,在http/1或http/2的情况下,它的TCP,而对于http/3,将是UDP,它是HTTP/3使用HTTP/3使用QUIC协议。 udp。
  • ipranges:允许IP地址的范围。对于"0.0.0.0/0",允许所有IP地址
  • ipv6ranges:允许的IP V6地址。
  • toport:端口的末端范围
  • 用户派:

如果端口不是OPEND,我们可以创建新的安全性group @todo

启动实例

一旦我们选择了端口,就可以准备启动实例。该实例可以使用RunInstancesCommand
启动

//launching an instnace

const client = new EC2Client(config);

const inputConfig = {
            MaxCount: 1,
            MinCount: 1,
            ImageId: 'ami-02f3f602d23f1659d',
            InstanceType: 't2.micro',
            SecurityGroupIds: ['SG_ID'],
            SecurityGroups: ['securityGroupName'],
            KeyName: 'name',
            TagSpecifications: [
              {
                ResourceType: "instance",
                Tags: [
                  {
                    Key: "Name",
                    Value: 'instanceName',
                  },
                ],
              },
            ],
          };

const instance = new RunInstancesCommand(inputConfig);
const response = await client.send(command);

这是启动实例所需的裸露最小配置。默认部分没有提供一个巨大的list配置。当创建帐户时,默认情况下会创建大多数配置(VPC,安全组),并且如果未提供配置,将使用相同的默认配置。

另一个有趣的属性是UserDate,它不是必需的选项,但是当我们想在启动实例时在实例上设置一些其他内容时,非常有用。例如,假设您要在实例启动后立即在实例上安装Docker,您可以通过
进行此操作

const userData = [
        `#!/bin/bash
        yum install -y docker`,
        "usermod -aG docker ec2-user",
        "service docker start",
      ].join(" && ");

const bufferString = Buffer.from(userData).toString("base64");
const instance = new RunInstancesCommand({
...inputConfig,
userData
);
const response = await client.send(command);

您还可以将用户数据作为文本而不是基本64传递,但是我在这样做时面临一些问题。另一种方法是在cloud-init中使用云初始指令。您可以使用SSH和检查logs /var/log/cloud-init-output.log进行调试,并使用“查看连接到实例”进行调试。我在运行bash脚本时遇到了一些问题,因为AWS将bash脚本视为云脚本,我不知道为什么这样做。

结论

谢谢大家走这么远。 AWS EC2是AWS的核心服务之一。我们已经介绍了EC2的各种概念,例如网络和AMI,并计划在将来涵盖其余概念。我没有介绍此博客的存储空间,因为我想简短。希望你喜欢它。

请让我知道我是否错过了任何事情,或者我错了任何问题试图纠正它