前提条件
ECSへの権限
- ECSに対してフル権限があること。
EC2への権限
- EC2に対してフル権限があること。
デフォルトVPCの存在
- デフォルトVPCが存在すること。
コマンド
VPC_ID=` \
aws ec2 describe-vpcs \
--filters Name=isDefault,Values=true \
--query 'Vpcs[].VpcId' \
--output text \
` \
&& echo ${VPC_ID}
結果(例)
vpc-xxxxxxxx
AWS CLIのバージョン
-
以下のバージョンで動作確認済
- AWS CLI 1.7.36
コマンド
aws --version
結果(例)
aws-cli/1.7.36 Python/2.7.5 Darwin/13.4.0
- 準備
=======
0.1. リージョンの決定
変数の設定
export AWS_DEFAULT_REGION='ap-northeast-1'
0.2. 変数の確認
変数の確認
aws configure list
結果(例)
Name Value Type Location
---- ----- ---- --------
profile ec2ecs_full-prjZ-mbp13 env AWS_DEFAULT_PROFILE
access_key ****************LOAQ shared-credentials-file
secret_key ****************I1O1 shared-credentials-file
region ap-northeast-1 env AWS_DEFAULT_REGION
0.3. 稼動インスタンスを確認
同一リージョンでインスタンスが起動していないことを確認します。
コマンド
aws ec2 describe-instances \
--filters Name=instance-state-name,Values=running
結果
{
"Reservations": []
}
0.4. IAMインスタンスプロファイルの決定
コマンド
aws iam list-instance-profiles \
--query 'InstanceProfiles[].InstanceProfileName'
'ecsInstanceRole' が存在しない場合は、 http://qiita.com/tcsh/items/8daed4cf04d5bc56e2a7 を実施してください。
変数の設定
IAM_INSTANCE_PROFILE_NAME='ecsInstanceRole'
コマンド
aws iam get-instance-profile \
--instance-profile-name ${IAM_INSTANCE_PROFILE_NAME}
結果
{
"InstanceProfile": {
"InstanceProfileId": "AIPAXXXXXXXXXXXXXXXXX",
"Roles": [
{
"AssumeRolePolicyDocument": {
"Version": "2008-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
},
"RoleId": "AROAXXXXXXXXXXXXXXXXX",
"CreateDate": "2015-07-05T01:23:45Z",
"RoleName": "ecsInstanceRole",
"Path": "/",
"Arn": "arn:aws:iam::XXXXXXXXXXXX:role/ecsInstanceRole"
}
],
"CreateDate": "2015-07-05T01:23:45Z",
"InstanceProfileName": "ecsInstanceRole",
"Path": "/",
"Arn": "arn:aws:iam::XXXXXXXXXXXX:instance-profile/ecsInstanceRole"
}
}
0.5. セキュリティグループの確認
まず、セキュリティグループの一覧を確認します。
コマンド
aws ec2 describe-security-groups \
--query 'SecurityGroups[].GroupName'
'ec2-http-https-ssh-global-inbound'が存在しない場合は、 http://qiita.com/tcsh/items/1d6a499b03b776355ee2 を実施してください。
利用するセキュリティグループ名を指定します。
変数の設定
VPC_SG_NAME='ec2-http-https-ssh-global-inbound'
コマンド
VPC_SG_ID=` \
aws ec2 describe-security-groups \
--filter Name=group-name,Values=${VPC_SG_NAME} \
--query 'SecurityGroups[].GroupId' \
--output text \
` \
&& echo ${VPC_SG_ID}
結果(例)
sg-xxxxxxxx
変数の設定
ARRAY_VPC_SG_ID="${VPC_SG_ID} ${ARRAY_VPC_SG_ID}" \
&& echo ${ARRAY_VPC_SG_ID}
0.6. キーペアの確認
まず、キーペアの一覧を確認します。
コマンド
aws ec2 describe-key-pairs \
--query 'KeyPairs[].KeyName'
キーペアが存在しない場合は、 http://qiita.com/tcsh/items/59303d9506ca7d13f744 を実施してください。
利用するキーペア名を指定します。
変数の設定
EC2_KEY_NAME=<キーペア名>
利用するキーペアの秘密鍵ファイルを指定します。
変数の設定
FILE_SSH_KEY=<秘密鍵ファイル>
- 事前作業
===========
1.1. インスタンスタイプの決定
変数の設定
EC2_INSTANCE_TYPE='t2.micro'
1.2. イメージIDの決定
ECSに最適化されたAMIを選択します。
変数の設定
AMZLINUX_VERSION='2015.03.d'
EC2_IMAGE_NAME="amzn-ami-${AMZLINUX_VERSION}-amazon-ecs-optimized"
コマンド
EC2_IMAGE_ID=` \
aws ec2 describe-images \
--filters Name=name,Values="${EC2_IMAGE_NAME}" \
--query 'Images[].ImageId' --output text \
` \
&& echo ${EC2_IMAGE_ID}
結果(例)
ami-XXXXXXXX
1.3. クラスタ名の決定
変数の設定
ECS_CLUSTER_NAME='handson-cluster'
同名のクラスタが存在しないことを確認します。
コマンド
aws ecs describe-clusters \
--clusters ${ECS_CLUSTER_NAME}
結果(例)
{
"clusters": [],
"failures": [
{
"reason": "MISSING",
"arn": "arn:aws:ecs:ap-northeast-1:XXXXXXXXXXXX:cluster/handson-cluster"
}
]
}
1.4. User Dataの作成
変数の設定
FILE_EC2_USERDATA="ecs-userdata-${ECS_CLUSTER_NAME}.bash"
変数の確認
cat << ETX
ECS_CLUSTER_NAME: ${ECS_CLUSTER_NAME}
FILE_EC2_USERDATA: ${FILE_EC2_USERDATA}
ETX
コマンド
cat << EOF > ${FILE_EC2_USERDATA}
#!/bin/bash
echo ECS_CLUSTER=${ECS_CLUSTER_NAME} > /etc/ecs/ecs.config
EOF
cat ${FILE_EC2_USERDATA}
- クラスタの作成
=================
2.1. クラスタの作成
変数の確認
cat << ETX
ECS_CLUSTER_NAME: ${ECS_CLUSTER_NAME}
ETX
コマンド
aws ecs create-cluster \
--cluster-name ${ECS_CLUSTER_NAME}
結果(例)
{
"cluster": {
"status": "ACTIVE",
"clusterName": "handson-cluster",
"registeredContainerInstancesCount": 0,
"pendingTasksCount": 0,
"runningTasksCount": 0,
"activeServicesCount": 0,
"clusterArn": "arn:aws:ecs:ap-northeast-1:XXXXXXXXXXXX:cluster/handson-cluster"
}
}
2.2. クラスタの確認
コマンド
aws ecs describe-clusters \
--clusters ${ECS_CLUSTER_NAME}
結果(例)
{
"clusters": [
{
"status": "ACTIVE",
"clusterName": "handson-cluster",
"registeredContainerInstancesCount": 0,
"pendingTasksCount": 0,
"runningTasksCount": 0,
"activeServicesCount": 0,
"clusterArn": "arn:aws:ecs:ap-northeast-1:XXXXXXXXXXXX:cluster/handson-cluster"
}
],
"failures": []
}
- インスタンス起動
===================
3.1. インスタンス起動
変数の確認
cat << ETX
EC2_IMAGE_ID: ${EC2_IMAGE_ID}
EC2_INSTANCE_TYPE: ${EC2_INSTANCE_TYPE}
ARRAY_VPC_SG_ID: ${ARRAY_VPC_SG_ID}
EC2_KEY_NAME: ${EC2_KEY_NAME}
FILE_EC2_USERDATA: ${FILE_EC2_USERDATA}
IAM_INSTANCE_PROFILE_NAME: ${IAM_INSTANCE_PROFILE_NAME}
ETX
コマンド
aws ec2 run-instances \
--image-id ${EC2_IMAGE_ID} \
--instance-type ${EC2_INSTANCE_TYPE} \
--security-group-ids ${ARRAY_VPC_SG_ID} \
--key-name ${EC2_KEY_NAME} \
--associate-public-ip-address \
--user-data file://${FILE_EC2_USERDATA} \
--iam-instance-profile Name=${IAM_INSTANCE_PROFILE_NAME}
結果(例)
{
"OwnerId": "XXXXXXXXXXXX",
"ReservationId": "r-xxxxxxxx",
"Groups": [],
"Instances": [
{
"Monitoring": {
"State": "disabled"
},
"PublicDnsName": "",
"RootDeviceType": "ebs",
"State": {
"Code": 0,
"Name": "pending"
},
"EbsOptimized": false,
"LaunchTime": "2015-07-05T01:23:45.678",
"PrivateIpAddress": "172.xxx.xxx.xxx",
"ProductCodes": [],
"VpcId": "vpc-xxxxxxxx",
"StateTransitionReason": "",
"InstanceId": "i-xxxxxxxx",
"ImageId": "ami-xxxxxxxx",
"PrivateDnsName": "ip-172-xxx-xxx-xxx.ap-northeast-1.compute.internal",
"KeyName": "prj08-ap-northeast-1-ec2",
"SecurityGroups": [
{
"GroupName": "ec2-http-https-ssh-global-inbound",
"GroupId": "sg-xxxxxxxx"
}
],
"ClientToken": "",
"SubnetId": "subnet-xxxxxxxx",
"InstanceType": "t2.micro",
"NetworkInterfaces": [
{
"Status": "in-use",
"MacAddress": "xx:xx:xx:xx:xx:xx",
"SourceDestCheck": true,
"VpcId": "vpc-xxxxxxxx",
"Description": "",
"NetworkInterfaceId": "eni-xxxxxxxx",
"PrivateIpAddresses": [
{
"PrivateDnsName": "ip-172-xxx-xxx-xxx.ap-northeast-1.compute.internal",
"Primary": true,
"PrivateIpAddress": "172.xxx.xxx.xxx"
}
],
"PrivateDnsName": "ip-172-xxx-xxx-xxx.ap-northeast-1.compute.internal",
"Attachment": {
"Status": "attaching",
"DeviceIndex": 0,
"DeleteOnTermination": true,
"AttachmentId": "eni-attach-xxxxxxxx",
"AttachTime": "2015-07-05T01:23:45.678Z"
},
"Groups": [
{
"GroupName": "ec2-http-https-ssh-global-inbound",
"GroupId": "sg-xxxxxxxx"
}
],
"SubnetId": "subnet-xxxxxxxx",
"OwnerId": "XXXXXXXXXXXX",
"PrivateIpAddress": "172.xxx.xxx.xxx"
}
],
"SourceDestCheck": true,
"Placement": {
"Tenancy": "handson-cluster",
"GroupName": "",
"AvailabilityZone": "ap-northeast-1a"
},
"Hypervisor": "xen",
"BlockDeviceMappings": [],
"Architecture": "x86_64",
"StateReason": {
"Message": "pending",
"Code": "pending"
},
"IamInstanceProfile": {
"Id": "AIPAXXXXXXXXXXXXXXXXX",
"Arn": "arn:aws:iam::XXXXXXXXXXXX:instance-profile/ecsInstanceRole"
},
"RootDeviceName": "/dev/xvda",
"VirtualizationType": "hvm",
"AmiLaunchIndex": 0
}
]
}
3.2. インスタンスIDの取得
起動中のインスタンスからインスタンスIDを取得します。
起動中の場合
コマンド(起動中の場合)
EC2_INSTANCE_ID=` \
aws ec2 describe-instances \
--filters Name=instance-state-name,Values=pending \
--query 'Reservations[].Instances[].InstanceId' \
--output text \
` \
&& echo ${EC2_INSTANCE_ID}
結果(例)
i-xxxxxxxx
起動完了後の場合
コマンド(起動完了後の場合)
ARRAY_EC2_INSTANCE_ID=` \
aws ec2 describe-instances \
--filters Name=instance-state-name,Values=running \
--query 'Reservations[].Instances[].InstanceId' \
--output text \
` \
&& echo ${ARRAY_EC2_INSTANCE_ID}
変数の設定
EC2_INSTANCE_ID=$(echo ${ARRAY_EC2_INSTANCE_ID} | sed 's/ .*$//') \
&& echo ${EC2_INSTANCE_ID}
結果(例)
i-xxxxxxxx
3.3 インスタンスのステータス確認
コマンド
EC2_INSTANCE_STATE=` \
aws ec2 describe-instances \
--instance-ids ${EC2_INSTANCE_ID} \
--query 'Reservations[].Instances[].State.Name' \
--output text \
` \
&& echo ${EC2_INSTANCE_STATE}
結果
running
- インスタンスの確認
=====================
4.1. パブリックIPアドレスの取得
コマンド
EC2_PUBLIC_IP=` \
aws ec2 describe-instances \
--instance-id ${EC2_INSTANCE_ID} \
--query "Reservations[].Instances[].PublicIpAddress" \
--output text \
` \
&& echo ${EC2_PUBLIC_IP}
結果(例)
54.xxx.xxx.xxx
4.2. SSHログイン
変数の確認
cat << ETX
FILE_SSH_KEY: ${FILE_SSH_KEY}
EC2_PUBLIC_IP: ${EC2_PUBLIC_IP}
ETX
コマンド
ssh -i ${FILE_SSH_KEY} ec2-user@${EC2_PUBLIC_IP}
結果(例)
The authenticity of host '54.xxx.xxx.xxx (54.xxx.xxx.xxx)' can't be established.
RSA key fingerprint is xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx.
Are you sure you want to continue connecting (yes/no)?
入力
yes
結果(例)
Warning: Permanently added '54.xxx.xxx.xxx' (RSA) to the list of known hosts.
__| __|_ )
_| ( / Amazon Linux AMI
https://aws.amazon.com/amazon-linux-ami/2015.03-release-notes/
4.3. ECSエージェントの確認
コマンド(EC2インスタンス)
ps ax |grep [a]mazon-ecs-init
結果(例)
2379 ? Ssl 0:00 /usr/libexec/amazon-ecs-init start
4.4. ECSクラスタ設定の確認
コマンド(EC2インスタンス)
cat /etc/ecs/ecs.config
結果(例)
ECS_CLUSTER='handson-cluster'
4.5. ECSメタ設定の確認
コマンド(EC2インスタンス)
echo -e "\n" \
&& curl http://localhost:51678/v1/metadata \
&& echo -e "\n"
結果(例)
{"Cluster":"\ |ECS_CLUSTER_NAME|\ ","ContainerInstanceArn":"arn:aws:ecs:\ |AWS_DEFAULT_REGION|\ :XXXXXXXXXXXX:container-instance/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx","Version":"Amazon ECS Agent - v1.2.1 (5da1555)"}
4.6. 起動ログの確認
コマンド(EC2インスタンス)
cat /var/log/ecs/ecs-init.log.*
結果
2015-07-05T08:54:04Z [INFO] pre-start
2015-07-05T08:54:05Z [INFO] start
2015-07-05T08:54:05Z [INFO] No existing agent container to remove.
2015-07-05T08:54:05Z [INFO] Starting Amazon EC2 Container Service Agent
4.7. エージェントログの確認
コマンド(EC2インスタンス)
cat /var/log/ecs/ecs-agent.log.*
結果
2015-07-05T08:54:06Z [INFO] Starting Agent: Amazon ECS Agent - v1.2.1 (5da1555)
2015-07-05T08:54:06Z [INFO] Loading configuration
2015-07-05T08:54:06Z [INFO] Checkpointing is enabled. Attempting to load state
2015-07-05T08:54:06Z [INFO] Loading state! module="statemanager"
2015-07-05T08:54:06Z [INFO] Registering Instance with ECS
2015-07-05T08:54:06Z [INFO] Registered! module="api client"
2015-07-05T08:54:06Z [INFO] Registration completed successfully. I am running as 'arn:was:ecs:ap-northeast-1:XXXXXXXXXXXX:container-instance/xxxxxxxx-xxxx-xxxx-xxxx-aa37ad9f3927' in cluster 'handson-cluster'
2015-07-05T08:54:06Z [INFO] Saving state! module="statemanager"
2015-07-05T08:54:06Z [INFO] Beginning Polling for updates
2015-07-05T08:54:06Z [INFO] Creating poll dialer module="ws client" host="ecs-a-1.ap-northeast-1.amazonaws.com"
2015-07-05T08:54:06Z [ERROR] Error getting message from ws backend module="ws client" err="websocket: close 1011 Server Error"
2015-07-05T08:54:06Z [INFO] Error from acs; backing off module="acs handler" err="websocket: close 1011 Server Error"
2015-07-05T08:54:07Z [INFO] Creating poll dialer module="ws client" host="ecs-a-1.ap-northeast-1.amazonaws.com"
2015-07-05T08:54:16Z [INFO] Saving state! module="statemanager"
2015-07-05T08:54:23Z [INFO] Handling http request module="Handlers" method="GET" from="172.xxx.xxx.xxx:34872" uri="/v1/metadata"
4.8. ログアウト
ログアウトします。
コマンド(EC2インスタンス)
exit
結果(例)
logout
Connection to 54.xxx.xxx.xxx closed.
- クラスタの確認
=================
5.1. クラスタの確認
コマンド
aws ecs describe-clusters \
--clusters ${ECS_CLUSTER_NAME}
結果(例)
{
"clusters": [
{
"status": "ACTIVE",
"clusterName": "handson-cluster",
"registeredContainerInstancesCount": 1,
"pendingTasksCount": 0,
"runningTasksCount": 0,
"activeServicesCount": 0,
"clusterArn": "arn:aws:ecs:ap-northeast-1:XXXXXXXXXXXX:cluster/handson-cluster"
}
],
"failures": []
}
5.2. コンテナインスタンスの確認
コマンド
ECS_INSTANCES=$( \
aws ecs list-container-instances \
--cluster ${ECS_CLUSTER_NAME} \
--query 'containerInstanceArns[]' \
--output text | \
sed 's|^arn:aws:ecs:.*:container-instance/||' \
) \
&& echo ${ECS_INSTANCES}
結果(例)
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
コマンド
aws ecs describe-container-instances \
--cluster ${ECS_CLUSTER_NAME} \
--container-instances "${ECS_INSTANCES}"
結果(例)
{
"failures": [],
"containerInstances": [
{
"status": "ACTIVE",
"registeredResources": [
{
"integerValue": 1024,
"longValue": 0,
"type": "INTEGER",
"name": "CPU",
"doubleValue": 0.0
},
{
"integerValue": 996,
"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": "i-xxxxxxxx",
"agentConnected": true,
"containerInstanceArn": "arn:aws:ecs:ap-northeast-1:XXXXXXXXXXXX:container-instance/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"pendingTasksCount": 0,
"remainingResources": [
{
"integerValue": 1024,
"longValue": 0,
"type": "INTEGER",
"name": "CPU",
"doubleValue": 0.0
},
{
"integerValue": 996,
"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,
"versionInfo": {
"agentVersion": "1.2.1",
"agentHash": "5da1555",
"dockerVersion": "DockerVersion: 1.6.2"
}
}
]
}