使用 AWS CLI 为 EC2 创建 Amazon ECS 任务 - Amazon Elastic Container Service

使用 AWS CLI 为 EC2 创建 Amazon ECS 任务

以下步骤帮助您在 Amazon ECS 中使用 AWS CLI 设置集群、注册任务定义、运行任务和执行其他常见方案。使用最新版本的 AWS CLI。有关如何升级到最新版本的更多信息,请参阅 Installing or updating to the latest version of the AWS CLI

注意

您可以使用双堆栈服务端点通过 IPv4 和 IPv6 从 AWS CLI、SDK 和 Amazon ECS API 与 Amazon ECS 进行交互。有关更多信息,请参阅 使用 Amazon ECS 双堆栈端点

先决条件

本教程假设以下先决条件已完成:

创建集群

默认情况下,当您启动第一个容器实例时,您的账户将收到一个 default 集群。

注意

使用为您提供的 default 群集的好处是您不必在后续命令中指定 --cluster cluster_name 选项。如果您自行创建非默认集群,您必须为您打算用于该集群的每个命令指定 --cluster cluster_name

使用以下命令自行创建具有唯一名称的集群:

aws ecs create-cluster --cluster-name MyCluster

输出:

{ "cluster": { "clusterName": "MyCluster", "status": "ACTIVE", "clusterArn": "arn:aws:ecs:region:aws_account_id:cluster/MyCluster" } }

使用 Amazon ECS AMI 启动容器实例

容器实例是已注册到集群并且将会运行 Amazon ECS 容器代理的 EC2 实例。在这一部分中,您将使用 ECS 优化版 AMI 启动一个 EC2 实例。

使用 AWS CLI 启动容器实例
  1. 使用以下命令检索您所在 AWS 区域的最新 ECS 优化版 Amazon Linux 2 AMI ID。此命令使用 AWS Systems Manager Parameter Store 来获取最新 ECS 优化版 AMI ID。该 AMI 包括预装的 Amazon ECS 容器代理和 Docker 运行时。

    aws ssm get-parameters --names /aws/service/ecs/optimized-ami/amazon-linux-2/recommended --query 'Parameters[0].Value' --output text | jq -r '.image_id'

    输出:

    ami-abcd1234
  2. 创建一个允许 SSH 访问(用来管理容器实例)和 HTTP 访问(用于 Web 服务器)的安全组。

    aws ec2 create-security-group --group-name ecs-tutorial-sg --description "ECS tutorial security group"

    输出:

    { "GroupId": "sg-abcd1234" }
  3. 通过运行以下命令,将一条入站规则添加到该安全组。

    aws ec2 authorize-security-group-ingress --group-id sg-abcd1234 --protocol tcp --port 80 --cidr 0.0.0.0/0

    输出:

    { "Return": true, "SecurityGroupRules": [ { "SecurityGroupRuleId": "sgr-efgh5678", "GroupId": "sg-abcd1234", "GroupOwnerId": "123456789012", "IsEgress": false, "IpProtocol": "tcp", "FromPort": 80, "ToPort": 80, "CidrIpv4": "0.0.0.0/0" } ] }

    现在,该安全组将允许从指定 IP 范围进行 SSH 访问以及从任何位置进行 HTTP 访问。在生产环境中,您应仅允许从您的特定 IP 地址进行 SSH 访问,并在需要时考虑限制 HTTP 访问。

  4. 创建一个 EC2 密钥对,用于对容器实例的 SSH 访问。

    aws ec2 create-key-pair --key-name ecs-tutorial-key --query 'KeyMaterial' --output text > ecs-tutorial-key.pem chmod 400 ecs-tutorial-key.pem

    该私有密钥将保存到具有恰当 SSH 访问权限的本地计算机中。

  5. 使用 ECS 优化版 AMI 启动一个 EC2 实例,并进行配置以加入您的集群。

    aws ec2 run-instances --image-id ami-abcd1234 --instance-type t3.micro --key-name ecs-tutorial-key --security-group-ids sg-abcd1234 --iam-instance-profile Name=ecsInstanceRole --user-data '#!/bin/bash echo ECS_CLUSTER=MyCluster >> /etc/ecs/ecs.config' { "Instances": [ { "InstanceId": "i-abcd1234", "ImageId": "ami-abcd1234", "State": { "Code": 0, "Name": "pending" }, "PrivateDnsName": "", "PublicDnsName": "", "StateReason": { "Code": "pending", "Message": "pending" }, "InstanceType": "t3.micro", "KeyName": "ecs-tutorial-key", "LaunchTime": "2025-01-13T10:30:00.000Z" } ] }

    此用户数据脚本会配置 Amazon ECS 代理,以将该实例注册到您的 MyCluster。该实例使用 ecsInstanceRole IAM 角色,从而为该代理提供所需的权限。

列出容器实例

在启动您的容器实例后的几分钟内,Amazon ECS 代理将向您的 MyCluster 集群注册该实例。您可以通过运行以下命令列出集群中的容器实例:

aws ecs list-container-instances --cluster MyCluster

输出:

{ "containerInstanceArns": [ "arn:aws:ecs:us-east-1:aws_account_id:container-instance/container_instance_ID" ] }

描述容器实例

在拥有某个容器实例的 ARN 或 ID 后,您就可以使用 describe-container-instances 命令获取有关该实例的有价值的信息,例如剩余的和已注册的 CPU 和内存资源。

aws ecs describe-container-instances --cluster MyCluster --container-instances container_instance_ID

输出:

{ "failures": [], "containerInstances": [ { "status": "ACTIVE", "registeredResources": [ { "integerValue": 1024, "longValue": 0, "type": "INTEGER", "name": "CPU", "doubleValue": 0.0 }, { "integerValue": 995, "longValue": 0, "type": "INTEGER", "name": "MEMORY", "doubleValue": 0.0 }, { "name": "PORTS", "longValue": 0, "doubleValue": 0.0, "stringSetValue": [ "22", "2376", "2375", "51678" ], "type": "STRINGSET", "integerValue": 0 }, { "name": "PORTS_UDP", "longValue": 0, "doubleValue": 0.0, "stringSetValue": [], "type": "STRINGSET", "integerValue": 0 } ], "ec2InstanceId": "instance_id", "agentConnected": true, "containerInstanceArn": "arn:aws:ecs:us-west-2:aws_account_id:container-instance/container_instance_ID", "pendingTasksCount": 0, "remainingResources": [ { "integerValue": 1024, "longValue": 0, "type": "INTEGER", "name": "CPU", "doubleValue": 0.0 }, { "integerValue": 995, "longValue": 0, "type": "INTEGER", "name": "MEMORY", "doubleValue": 0.0 }, { "name": "PORTS", "longValue": 0, "doubleValue": 0.0, "stringSetValue": [ "22", "2376", "2375", "51678" ], "type": "STRINGSET", "integerValue": 0 }, { "name": "PORTS_UDP", "longValue": 0, "doubleValue": 0.0, "stringSetValue": [], "type": "STRINGSET", "integerValue": 0 } ], "runningTasksCount": 0, "attributes": [ { "name": "com.amazonaws.ecs.capability.privileged-container" }, { "name": "com.amazonaws.ecs.capability.docker-remote-api.1.17" }, { "name": "com.amazonaws.ecs.capability.docker-remote-api.1.18" }, { "name": "com.amazonaws.ecs.capability.docker-remote-api.1.19" }, { "name": "com.amazonaws.ecs.capability.logging-driver.json-file" }, { "name": "com.amazonaws.ecs.capability.logging-driver.syslog" } ], "versionInfo": { "agentVersion": "1.5.0", "agentHash": "b197edd", "dockerVersion": "DockerVersion: 1.7.1" } } ] }

您也可以在 Amazon EC2 控制台中或使用 aws ec2 describe-instances --instance-id instance_id 命令查找可用于监控实例的 Amazon EC2 实例 ID。

注册任务定义

您必须首先注册一个任务定义,然后才能在 Amazon ECS 集群上运行任务。任务定义是分组在一起的一系列容器。以下示例是一个使用 nginx 映像的简单任务定义。有关可用任务定义参数的更多信息,请参阅 Amazon ECS 任务定义

{ "family": "nginx-task", "containerDefinitions": [ { "name": "nginx", "image": "public.ecr.aws/ecs-sample-image/amazon-ecs-sample:latest", "cpu": 256, "memory": 512, "essential": true, "portMappings": [ { "containerPort": 80, "hostPort": 80, "protocol": "tcp" } ] } ], "requiresCompatibilities": ["EC2"], "networkMode": "bridge" }

上述示例 JSON 可通过两种方式传递到 AWS CLI:您可以将任务定义 JSON 保存为文件并使用 --cli-input-json file://path_to_file.json 选项传递它。您也可以对 JSON 中的引号进行转义并在命令行上传递 JSON 容器定义。如果您选择在命令行上传递容器定义,您的命令还需要一个 --family 参数,该参数用于使任务定义的多个版本保持互相关联。

将 JSON 文件用于容器定义:

aws ecs register-task-definition --cli-input-json file://$HOME/tasks/nginx.json

register-task-definition 将在其完成注册后返回任务定义的说明。

{ "taskDefinition": { "taskDefinitionArn": "arn:aws:ecs:us-east-1:123456789012:task-definition/nginx-task:1", "family": "nginx-task", "revision": 1, "status": "ACTIVE", "containerDefinitions": [ { "name": "nginx", "image": "public.ecr.aws/docker/library/nginx:latest", "cpu": 256, "memory": 512, "essential": true, "portMappings": [ { "containerPort": 80, "hostPort": 80, "protocol": "tcp" } ], "environment": [], "mountPoints": [], "volumesFrom": [] } ], "volumes": [], "networkMode": "bridge", "compatibilities": [ "EC2" ], "requiresCompatibilities": [ "EC2" ] } }

列出任务定义

您可以随时使用 list-task-definitions 命令列出您的账户的任务定义。此命令的输出将显示 familyrevision 值,您可以在调用 create-service 时将这些值一起使用。

aws ecs list-task-definitions

输出:

{ "taskDefinitionArns": [ "arn:aws:ec2:us-east-1:aws_account_id:task-definition/sleep360:1", "arn:aws:ec2:us-east-1:aws_account_id:task-definition/sleep360:2", "arn:aws:ec2:us-east-1:aws_account_id:task-definition/nginx-task:1", "arn:aws:ec2:us-east-1:aws_account_id:task-definition/wordpress:3", "arn:aws:ec2:us-east-1:aws_account_id:task-definition/wordpress:4", "arn:aws:ec2:us-east-1:aws_account_id:task-definition/wordpress:5", "arn:aws:ec2:us-east-1:aws_account_id:task-definition/wordpress:6" ] }

创建服务

在为账户注册任务并启动注册到集群的容器实例后,您可以创建一个 Amazon ECS 服务,从而使用所注册的任务定义同时运行和维持所需数量的任务。在本实例中,您将 nginx:1 任务定义的单个实例放置在 MyCluster 集群中。

aws ecs create-service --cluster MyCluster --service-name nginx-service --task-definition nginx-task:1 --desired-count 1

输出:

{ "service": { "serviceArn": "arn:aws:ecs:us-east-1:aws_account_id:service/MyCluster/nginx-service", "serviceName": "nginx-service", "clusterArn": "arn:aws:ecs:us-east-1:aws_account_id:cluster/MyCluster", "taskDefinition": "arn:aws:ecs:us-east-1:aws_account_id:task-definition/nginx-task:1", "desiredCount": 1, "runningCount": 0, "pendingCount": 0, "launchType": "EC2", "status": "ACTIVE", "createdAt": "2025-01-13T10:45:00.000Z" } }

列出服务

列出您的集群的服务。您应看到您在上一部分中创建的服务。您可以记下此命令返回的服务 ID 或完整 ARN,并在稍后将其用于描述服务。

aws ecs list-services --cluster MyCluster

输出:

{ "taskArns": [ "arn:aws:ecs:us-east-1:aws_account_id:task/task_ID" ] }

描述服务

使用以下命令描述服务,以获取有关该服务的更多信息。

aws ecs describe-services --cluster MyCluster --services nginx-service

输出:

{ "services": [ { "serviceArn": "arn:aws:ecs:us-east-1:aws_account_id:service/MyCluster/nginx-service", "serviceName": "nginx-service", "clusterArn": "arn:aws:ecs:us-east-1:aws_account_id:cluster/MyCluster", "taskDefinition": "arn:aws:ecs:us-east-1:aws_account_id:task-definition/nginx-task:1", "desiredCount": 1, "runningCount": 1, "pendingCount": 0, "launchType": "EC2", "status": "ACTIVE", "createdAt": "2025-01-13T10:45:00.000Z", "events": [ { "id": "abcd1234-5678-90ab-cdef-1234567890ab", "createdAt": "2025-01-13T10:45:30.000Z", "message": "(service nginx-service) has started 1 tasks: (task abcd1234-5678-90ab-cdef-1234567890ab)." } ] } ] }

描述正在运行的任务

在描述服务后,运行以下命令可获取有关该服务中正在运行的任务的更多信息。

aws ecs list-tasks --cluster MyCluster --service-name nginx-service

输出:

{ "tasks": [ { "taskArn": "arn:aws:ecs:us-east-1:aws_account_id:task/MyCluster/abcd1234-5678-90ab-cdef-1234567890ab", "clusterArn": "arn:aws:ecs:us-east-1:aws_account_id:cluster/MyCluster", "taskDefinitionArn": "arn:aws:ecs:us-east-1:aws_account_id:task-definition/nginx-task:1", "containerInstanceArn": "arn:aws:ecs:us-east-1:aws_account_id:container-instance/MyCluster/abcd1234-5678-90ab-cdef-1234567890ab", "lastStatus": "RUNNING", "desiredStatus": "RUNNING", "containers": [ { "containerArn": "arn:aws:ecs:us-east-1:aws_account_id:container/MyCluster/abcd1234-5678-90ab-cdef-1234567890ab/abcd1234-5678-90ab-cdef-1234567890ab", "taskArn": "arn:aws:ecs:us-east-1:aws_account_id:task/MyCluster/abcd1234-5678-90ab-cdef-1234567890ab", "name": "nginx", "lastStatus": "RUNNING", "networkBindings": [ { "bindIP": "0.0.0.0", "containerPort": 80, "hostPort": 80, "protocol": "tcp" } ] } ], "createdAt": "2025-01-13T10:45:00.000Z", "startedAt": "2025-01-13T10:45:30.000Z" } ] }

测试 Web 服务器

测试 Web 服务器
  1. 通过运行以下命令,检索容器实例的公有 IP 地址。

    aws ec2 describe-instances --instance-ids i-abcd1234 --query 'Reservations[0].Instances[0].PublicIpAddress' --output text

    输出:

    203.0.113.25
  2. 检索到 IP 地址后,使用该 IP 地址运行以下 curl 命令。

    curl http://203.0.113.25

    输出:

    <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> ... </head> <body> <h1>Welcome to nginx!</h1> <p>If you can see this page, the nginx web server is successfully installed and working.</p> ... </body> </html>

    nginx 欢迎页面会确认您的服务已成功运行并且可以从互联网访问。

清理资源

要避免产生费用,请清理您在本教程中创建的资源。

清理资源
  1. 更新服务,使需要的任务数降为零,然后删除服务。

    aws ecs update-service --cluster MyCluster --service nginx-service --desired-count 0 { "service": { "serviceArn": "arn:aws:ecs:us-east-1:123456789012:service/MyCluster/nginx-service", "serviceName": "nginx-service", "desiredCount": 0, "runningCount": 1, "pendingCount": 0, "status": "ACTIVE" } }
  2. 等待正在运行的任务停止,然后再删除服务。

    aws ecs delete-service --cluster MyCluster --service nginx-service { "service": { "serviceArn": "arn:aws:ecs:us-east-1:123456789012:service/MyCluster/nginx-service", "serviceName": "nginx-service", "status": "DRAINING" } }
  3. 终止您创建的容器实例。

    aws ec2 terminate-instances --instance-ids i-abcd1234 { "TerminatingInstances": [ { "InstanceId": "i-abcd1234", "CurrentState": { "Code": 32, "Name": "shutting-down" }, "PreviousState": { "Code": 16, "Name": "running" } } ] }
  4. 清理您创建的安全组和密钥对。

    aws ec2 delete-security-group --group-id sg-abcd1234 aws ec2 delete-key-pair --key-name ecs-tutorial-key rm ecs-tutorial-key.pem
  5. 删除 Amazon ECS 集群。

    aws ecs delete-cluster --cluster MyCluster { "cluster": { "clusterArn": "arn:aws:ecs:us-east-1:123456789012:cluster/MyCluster", "clusterName": "MyCluster", "status": "INACTIVE" } }