share facebook facebook2 twitter menu hatena pocket slack

2015.06.25 THU

CloudFormationで”Container Instance”が”Auto Scaling”で管理されているECSのクラスターを作成してみた

鈴木 宏康

WRITTEN BY鈴木 宏康

0VMOC1BrD6dDB4DA-2A883

テンプレートは下記の通りです。

{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Parameters": {
        "ProjectName": {
            "Type": "String",
            "Default": "Cloudpack"
        },
        "RoleName": {
            "Type": "String",
            "Default": "Ecs"
        },
        "KeyName": {
            "Type": "AWS::EC2::KeyPair::KeyName"
        },
        "InstanceType": {
            "Type": "String",
            "Default": "t2.micro"
        },
        "CommonSecurityGroup": {
            "Type": "AWS::EC2::SecurityGroup::Id"
        },
        "VpcId": {
            "Type": "AWS::EC2::VPC::Id"
        },
        "Az1VpcZoneIdentifier": {
            "Type": "AWS::EC2::Subnet::Id"
        },
        "Az2VpcZoneIdentifier": {
            "Type": "AWS::EC2::Subnet::Id"
        },
        "DesiredCapacity": {
            "Type": "String",
            "Default": "0"
        }
    },
    "Mappings": {
        "RegionMapping": {
            "us-east-1": { "ImageId": "ami-5f59ac34" },
            "us-west-2": { "ImageId": "ami-c188b0f1" },
            "eu-west-1": { "ImageId": "ami-3db4ca4a" },
            "ap-northeast-1": { "ImageId": "ami-ca01d8ca" },
            "ap-southeast-2": { "ImageId": "ami-5b5d2661" }
        }
    },
    "Resources": {
        "Cluster": {
            "Type": "AWS::ECS::Cluster"
        },
        "RoleSecurityGroup": {
            "Type": "AWS::EC2::SecurityGroup",
            "Properties": {
                "GroupDescription": { "Fn::Join" : [ "", [
                    { "Ref": "ProjectName" },
                    { "Ref": "RoleName" }
                ] ] },
                "VpcId": { "Ref": "VpcId" },
                "SecurityGroupIngress": [],
                "SecurityGroupEgress": [],
                "Tags": [ {
                    "Key": "Name",
                    "Value": { "Fn::Join" : [ "", [
                        { "Ref": "ProjectName" },
                        { "Ref": "RoleName" },
                        "Instance"
                    ] ] }
                } ]
            }
        },
        "Role": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [ {
                        "Effect": "Allow",
                        "Principal": { "Service": [ "ec2.amazonaws.com" ] },
                        "Action": [ "sts:AssumeRole" ]
                    } ]
                },
                "Path": "/",
                "Policies": [ {
                    "PolicyName": { "Fn::Join" : [ "", [
                        { "Ref": "ProjectName" },
                        "Ecs"
                    ] ] },
                    "PolicyDocument": {
                        "Version" : "2012-10-17",
                        "Statement": [ {
                            "Effect": "Allow",
                            "Action": [
                                "ecs:CreateCluster",
                                "ecs:DeregisterContainerInstance",
                                "ecs:DiscoverPollEndpoint",
                                "ecs:Poll",
                                "ecs:RegisterContainerInstance",
                                "ecs:Submit*"
                            ],
                            "Resource": [ "*" ]
                        } ]
                    }
                } ]
            }
        },
        "InstanceProfile": {
            "Type": "AWS::IAM::InstanceProfile",
            "Properties": {
                "Path": "/",
                "Roles": [ {
                    "Ref": "Role"
                } ]
            }
        },
        "LaunchConfiguration": {
            "Type": "AWS::AutoScaling::LaunchConfiguration",
            "Properties": {
                "AssociatePublicIpAddress": "true",
                "KeyName": { "Ref": "KeyName" },
                "ImageId": { "Fn::FindInMap": [ "RegionMapping", { "Ref": "AWS::Region" }, "ImageId" ] },
                "InstanceType": { "Ref": "InstanceType" },
                "IamInstanceProfile": { "Ref": "InstanceProfile" },
                "SecurityGroups": [
                    { "Ref": "CommonSecurityGroup" },
                    { "Ref": "RoleSecurityGroup" }
                ],
                "UserData": { "Fn::Base64": { "Fn::Join" : [ "n", [
                    "#!/bin/bash",
                    "yum -y update",
                    "grubby --default-kernel | grep `uname -r` || reboot",
                    { "Fn::Join" : [ "", [
                        "echo ECS_CLUSTER=",
                        { "Ref": "Cluster" },
                        " >> /etc/ecs/ecs.config"
                    ] ] }
                ] ] } }
            }
        },
        "AutoScalingGroup": {
            "Type": "AWS::AutoScaling::AutoScalingGroup",
            "Properties": {
                "LaunchConfigurationName": { "Ref": "LaunchConfiguration" },
                "MinSize": "0",
                "MaxSize": "4",
                "DesiredCapacity": { "Ref": "DesiredCapacity" },
                "Cooldown": "0",
                "VPCZoneIdentifier": [
                    { "Ref" : "Az1VpcZoneIdentifier" },
                    { "Ref" : "Az2VpcZoneIdentifier" }
                ],
                "Tags": [ {
                    "Key": "Name",
                    "Value": { "Fn::Join" : [ "", [
                        { "Ref": "ProjectName" },
                        { "Ref": "RoleName" }
                    ] ] },
                    "PropagateAtLaunch": "true"
                } ]
            },
            "UpdatePolicy": {
                "AutoScalingRollingUpdate": {
                    "MaxBatchSize": "1",
                    "MinInstancesInService": "1"
                }
            }
        }
    },
    "Outputs": {
        "Cluster": {
            "Value":  { "Ref": "Cluster" }
        },
        "Role": {
            "Value":  { "Ref": "Role" }
        },
        "RoleSecurityGroup": {
            "Value":  { "Ref": "RoleSecurityGroup" }
        }
    }
}

以下、ポイントとなります。

▼CloudFormationのスタックが作られるリージョンのECSイメージが勝手に利用されるように

AMI名が”amzn-ami-2015.03.c-amazon-ecs-optimized”のものを
次のように設定しています。

"RegionMapping": {
    "us-east-1": { "ImageId": "ami-5f59ac34" },
    "us-west-2": { "ImageId": "ami-c188b0f1" },
    "eu-west-1": { "ImageId": "ami-3db4ca4a" },
    "ap-northeast-1": { "ImageId": "ami-ca01d8ca" },
    "ap-southeast-2": { "ImageId": "ami-5b5d2661" }
}

▼ ECSのエージェントが動作するためのポリシーをIAMロールに指定

“ecs:*”的な操作を許可してます。

"Action": [
    "ecs:CreateCluster",
    "ecs:DeregisterContainerInstance",
    "ecs:DiscoverPollEndpoint",
    "ecs:Poll",
    "ecs:RegisterContainerInstance",
    "ecs:Submit*"
]

▼ ECSクラスター名を”/etc/ecs/ecs.config”に登録

これやっとかないとECSクラスターに登録されません!

"UserData": { "Fn::Base64": { "Fn::Join" : [ "n", [
    "#!/bin/bash",
    "yum -y update",
    "grubby --default-kernel | grep `uname -r` || reboot",
    { "Fn::Join" : [ "", [
        "echo ECS_CLUSTER=",
        { "Ref": "Cluster" },
        " >> /etc/ecs/ecs.config"
    ] ] }
] ] } }

CloudFormationのスタック作成時のパラメータはこんな感じです。
(既にVPCやSubnetが存在する前提です)

2015-06-18_23-04-54

スタックが作成し終わると、次のような”Auto Scaling”の”Launch Configuration”が
作られていることを確認できます。(“User Data”も設定されています)

2015-06-18_23-36-52

“Auto Scaling Group”でインスタンスが二つ起動していることも確認できました。

2015-06-18_23-32-44

ということで、ECSクラスターに登録されたEC2も二つになっていました。

2015-06-19_07-52-20

元記事はこちら

CloudFormationで”Container Instance”が”Auto Scaling”で管理されているECSのクラスターを作成してみた

鈴木 宏康

鈴木 宏康

愛知県生まれ。東京工業大学大学院修士課程修了。在学時より、ベンチャー企業でインターネットに関する業務に携わり、現在はクラウド(主にAmazon Web Services)上での開発・運用を軸とした事業の、業務の中心として活躍。