AWS FargateをAWS CLIで扱いつつ、従来のAPIとの差分を調べた #reinvent

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

re:Invent 2017で発表されたAWS Fargateは、EC2を起動せずにコンテナを実行できるようにするためのElastic Container Service(ECS)の拡張機能です。

昨日、弊社諏訪からecs-cliを利用してFargateのデプロイを行う記事が投稿されていました。

ECS CLIではなく、標準の低レベルAPIを利用してデプロイを行うのはどうしたらいいのだろう、と思い調べてみると、公式ドキュメントにサンプルアプリのデプロイをAWS CLIを使って行うWalkthroughがありました。

この投稿では、walkthroughを実施して実際にFargateのタスクが動くことを確かめつつ、従来のECS APIからの変更がどのあたりにあるのか、を私なりにまとめてみることにします。

1. (Optional)ECS Clusterの作成

ECS Clusterを作成します。ECS ClusterはFargateがリリースされていない時に作ったものでもそのまま使えるので、既にClusterを作成済の人はこの手順をスキップしても問題ありません。

$ aws ecs create-cluster --cluster-name fargate-cluster --region us-east-1

{
    "cluster": {
        "status": "ACTIVE",
        "statistics": [],
        "clusterName": "fargate-cluster",
        "registeredContainerInstancesCount": 0,
        "pendingTasksCount": 0,
        "runningTasksCount": 0,
        "activeServicesCount": 0,
        "clusterArn": "arn:aws:ecs:us-east-1:123456789012:cluster/fargate-cluster"
    }
}

2. TaskDefinitionの登録

$ cat tas_definition.json
{
    "family": "sample-fargate",
    "networkMode": "awsvpc",
    "containerDefinitions": [
        {
            "name": "fargate-app",
            "image": "httpd:2.4",
            "portMappings": [
                {
                    "containerPort": 80,
                    "hostPort": 80,
                    "protocol": "tcp"
                }
            ],
            "essential": true,
            "entryPoint": [
                "sh",
        "-c"
            ],
            "command": [
                "/bin/sh -c \"echo '<html> <head> <title>Amazon ECS Sample App</title> <style>body {margin-top: 40px; background-color: #333;} </style> </head><body> <div style=color:white;text-align:center> <h1>Amazon ECS Sample App</h1> <h2>Congratulations!</h2> <p>Your application is now running on a container in Amazon ECS.</p> </div></body></html>' >  /usr/local/apache2/htdocs/index.html && httpd-foreground\""
            ]
        }
    ],
    "requiresCompatibilities": [
        "FARGATE"
    ],
    "cpu": "256",
    "memory": "512"
}

ここで注目すべきはrequiresCompatibilitiesの項目です。APIドキュメントにはこう書かれています。

The launch type required by the task. If no value is specified, it defaults to EC2.

Type: Array of strings
Valid Values: EC2 | FARGATE
Required: No

つまり、Fargateで起動するためにはrequiresCompatibilitiesFARGATEというパラメータを追加する必要があります。TypeがArray of stringsとなっているので、「EC2とFargate、どちらでも起動可能なTask」という設定も可能なようです。

その他のパラメータは以前と差はなさそうです。このtask definitionを登録してみましょう。

$ aws ecs register-task-definition --cli-input-json file://task_definition.json --region us-east-1

(output snip)

TaskDefinitionのJSONが表示されたら登録完了です。

3. Serviceの開始

それでは、登録したTaskDefinitionをServiceとして開始してみましょう。ここで気をつける部分は2つ、--launch-typeパラメータと--network-configurationです。

--launch-type"FARGATE"を指定することで、Fargateでコンテナが起動するようになります。また、Fargateは先日発表されたawsvpcネットワーキングを利用するため、--network-configurationにはENIを起動するサブネットID、紐付けるSecurityGroupのID、PublicIPのAssign有無を設定する必要があります。

それでは実行しましょう。subnetIDとSecurityGroupIDはご自身の環境のものに書き換えて実行してください。

$ aws ecs create-service \
  --cluster fargate-cluster \
  --service-name fargate-service \
  --task-definition sample-fargate:1 \
  --desired-count 1 \
  --launch-type "FARGATE" \
  --network-configuration "awsvpcConfiguration={subnets=[subnet-abcdef01],securityGroups=[sg-abcdef01],assignPublicIp=ENABLED}" \
  --region us-east-1

{
    "service": {
        "status": "ACTIVE",
        "taskDefinition": "arn:aws:ecs:us-east-1:123456789012:task-definition/sample-fargate:2",
        "pendingCount": 0,
        "launchType": "FARGATE",
        "loadBalancers": [],
        "roleArn": "arn:aws:iam::123456789012:role/aws-service-role/ecs.amazonaws.com/AWSServiceRoleForECS",
        "placementConstraints": [],
        "createdAt": 1512080838.578,
        "desiredCount": 1,
        "networkConfiguration": {
            "awsvpcConfiguration": {
                "subnets": [
                    "subnet-abcdef01"
                ],
                "securityGroups": [
                    "sg-abcdef01"
                ],
                "assignPublicIp": "ENABLED"
            }
        },
        "platformVersion": "LATEST",
        "serviceName": "fargate-service",
        "clusterArn": "arn:aws:ecs:us-east-1:123456789012:cluster/fargate-cluster",
        "serviceArn": "arn:aws:ecs:us-east-1:123456789012:service/fargate-service",
        "deploymentConfiguration": {
            "maximumPercent": 200,
            "minimumHealthyPercent": 100
        },
        "deployments": [
            {
                "status": "PRIMARY",
                "networkConfiguration": {
                    "awsvpcConfiguration": {
                        "subnets": [
                            "subnet-abcdef01"
                        ],
                        "securityGroups": [
                            "sg-abcdef01"
                        ],
                        "assignPublicIp": "ENABLED"
                    }
                },
                "pendingCount": 0,
                "launchType": "FARGATE",
                "createdAt": 1512080838.578,
                "desiredCount": 1,
                "taskDefinition": "arn:aws:ecs:us-east-1:123456789012:task-definition/sample-fargate:2",
                "updatedAt": 1512080838.578,
                "platformVersion": "1.0.0",
                "id": "ecs-svc/9223370524773937228",
                "runningCount": 0
            }
        ],
        "events": [],
        "runningCount": 0,
        "placementStrategy": []
    }
}

こんな感じのJSONが帰ってきたら成功です。その後、Taskに紐付けられたENIの画面からPublicIPを確認し、ブラウザでアクセスしてみましょう。

ENIの情報はAWS Management ConsoleのTaskの詳細画面から取得可能です。(下記画像参照)そのリンクに飛ぶとPublic IPを取得可能です。

ブラウザでアクセスしてみると、HTMLが表示できました!EC2を作らなくとも、コンテナが起動できるようになるのは本当に便利ですね。

まとめ

今回は、AWS CLIを使いながらFargateの起動方法、また従来のECSとの違いを追っていきました。API的に一番大きな違いはcreate-serviceの時に--launch-typeを指定することと、awsvpcネットワークモードでの起動が必須になったことでしょうか。