前回、SSM Automationを通じてインスタンスの停止・起動という簡単な操作について触れました。今回は起動設定の操作、起動テンプレートの操作をAutomationで実行してみたいと思います。今回はもう少し込み入った作業になってくることもあり、より自動化のメリットが伝わりやすいのではと思っています。
本題に入る前に、改めて前回の内容を整理したいと思います。AWS CLIの操作ではアウトプットがjson形式であるためによりAPIのやりとりが明確に把握できます。AWS CLI Command Referenceを参照しながら行いたい操作のコマンドを用意し、そのAWS CLIの挙動を手がかりにAutomationの各ステップを作成します。最後にAPI Referenceを参照しながら(例:DescribeInstanceStatus)調整して完成させていくというものでした。
今回する操作は次の通りです。AMIの再起動なしでの取得、起動設定作成、AutoScalingの起動設定差し替え、AutoScalingの台数増加という内容です。起動設定について触れた後、起動テンプレートにも簡単に触れたいと思います。
起動設定によるAutoScalingの更新
まずは前回同様、AWS CLIで実行した場合を想定したコマンドと、Automationのドキュメントの全体像を提示します。その後、ここのステップとCLIコマンドを比較していきます。
↓CLIコマンド
aws ec2 describe-instances --filter "Name=tag:Name,Values=test*" //頭にtestとついたインスタンスが対象になります
aws autoscaling describe-auto-scaling-groups --auto-scaling-group-name test-as --query "AutoScalingGroups[*].Instances[*]" --output table
aws ec2 create-image --instance-id i-xxxxxxxxxx --name asano-test-image --description asano-test-for-technical-investigation --no-reboot
aws autoscaling create-launch-configuration --launch-configuration-name asano-test-image \
--image-id <image-id> \
--instance-type <instance-typexxxx> --key-name asano-key \
--security-groups {sg-xxxx,sg-xxxx} \
--block-device-mappings '[{"DeviceName":"/dev/xvda","Ebs": {"SnapshotId":"<SnapshotId>","VolumeSize":20,"VolumeType":"gp2","DeleteOnTermination":true,"Encrypted": false}}]' \
--instance-monitoring Enabled=false --iam-instance-profile arn:xxxxxxxxxxxxxxx --no-ebs-optimized --associate-public-ip-address
aws autoscaling update-auto-scaling-group --auto-scaling-group-name test-as --launch-configuration-name asano-test-image --desired-capacity 2 --min-size 2 --max-size 2
↓Automationドキュメント
description: Update AutoScaling
schemaVersion: '0.3'
assumeRole: '{{AutomationAssumeRole}}'
parameters:
AutomationAssumeRole:
type: String
description: (Optional) The ARN of the role that allows Automation to perform the actions on your behalf.
default: ''
ImageName:
type: String
description: ImageName
default: asano-test-image
mainSteps:
- name: createImage
action: 'aws:createImage'
maxAttempts: 3
onFailure: Abort
inputs:
InstanceId: i-xxxxxxxxxxxxxxx
ImageName: '{{ ImageName }}'
NoReboot: true
ImageDescription: '{{ ImageName }}'
outputs:
- Name: NewImageId
Selector: '$.Images[0].ImageId'
Type: String
- name: createTags
action: 'aws:createTags'
maxAttempts: 1
onFailure: Abort
inputs:
ResourceType: EC2
ResourceIds:
- '{{createImage.ImageId}}'
Tags:
- Key: Name
Value: '{{ ImageName }}'
- name: getImageId
action: 'aws:executeAwsApi'
inputs:
Service: ec2
Api: DescribeImages
Filters:
- Name: name
Values:
- '{{ ImageName }}'
outputs:
- Name: EBSid
Selector: '$.Images[0].BlockDeviceMappings[0].Ebs.SnapshotId'
Type: String
- name: CreateLaunchConfiguration
action: 'aws:executeAwsApi'
inputs:
Service: autoscaling
Api: CreateLaunchConfiguration
LaunchConfigurationName: '{{ ImageName }}'
ImageId: '{{createMyImage.ImageId}}'
InstanceType: t2.micro
KeyName: xxxxxxxxxxxxxxxxxxx
IamInstanceProfile: 'arn:xxxxxxxxxxxxxxxxxx'
InstanceMonitoring:
Enabled: false
EbsOptimized: false
AssociatePublicIpAddress: true
SecurityGroups:
- sg-xxxxxxxxxxxxxx
- sg-xxxxxxxxxxxxxx
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
SnapshotId: '{{getImageId.EBSid}}'
VolumeSize: 8
VolumeType: gp2
DeleteOnTermination: true
Encrypted: false
- name: UpdateAutoScaling
action: 'aws:executeAwsApi'
inputs:
Service: autoscaling
Api: UpdateAutoScalingGroup
AutoScalingGroupName: test-as
LaunchConfigurationName: '{{ ImageName }}'
DesiredCapacity: 2
MaxSize: 2
MinSize: 2
次に、ドキュメントのそれぞれのステップとCLIコマンドを対比していきます。(説明の都合上、ステップ順ではありません。)
まずは一番最後のステップ、AutoScalingの起動設定を新たに作成したものに指定し、台数を2台に増やすステップです。
aws autoscaling update-auto-scaling-group --auto-scaling-group-name test-as \
--launch-configuration-name asano-test-image \
--desired-capacity 2 --min-size 2 --max-size 2
- name: UpdateAutoScaling2
action: 'aws:executeAwsApi'
inputs:
Service: autoscaling
Api: UpdateAutoScalingGroup
AutoScalingGroupName: test-as
LaunchConfigurationName: '{{ ImageName }}'
DesiredCapacity: 2
MaxSize: 2
MinSize: 2
基本的にはAWS CLIの表記とAutomationのドキュメントはほぼ同じです。しかし、update-auto-scaling-group→UpdateAutoScalingGroupなど、微妙な違いがあります。そこはCLIを参考にしつつ大まかなコマンドを作成し、APIリファレンスを参考に細かい調整が必要です。
次にEBSのID取得のステップです。
- name: getImageId
action: 'aws:executeAwsApi'
inputs:
Service: ec2
Api: DescribeImages
Filters:
- Name: name
Values:
- '{{ ImageName }}'
outputs:
- Name: EBSid
Selector: '$.Images[0].BlockDeviceMappings[0].Ebs.SnapshotId'
Type: String
コンソールのReadonlyで確認しながらCLIで作業をしていると、コンソール上で生成したコマンドの結果を確認しながら作業することがあると思います。Automationに記述しようとしたとき、このコマンドなどが抜け落ちることがあるので、検証しながらそれらを補完して記述することが必要です。
また、このコマンドでoutputsの変数を用意し、そこに入れた情報を起動設定作成のステップに渡しています。このoutputsはどのように指定するとよいかですが、コマンドを打ちつつ、jsonファイルを見てほしいデータがjson構造の中のどこにあるかを指定するように書いていきます。
$ aws ec2 describe-images --filters "Name=name,Values=asano-test"
{
"Images": [
{
"Architecture": "x86_64",
"CreationDate": "2023-xx-xxxxxxxxx",
"ImageId": "ami-xxxxxxxxxxxxxxxx",
"ImageLocation": "xxxxxxxxxxxx/asano-test",
"ImageType": "machine",
"Public": false,
"OwnerId": "xxxxxxxxxxxxx",
"PlatformDetails": "Linux/UNIX",
"UsageOperation": "RunInstances",
"State": "available",
"BlockDeviceMappings": [
{
"DeviceName": "/dev/xvda",
"Ebs": {
"DeleteOnTermination": true,
"SnapshotId": "snap-xxxxxxxxxxxx",
"VolumeSize": 8,
"VolumeType": "gp2",
"Encrypted": false
}
}
],
"EnaSupport": true,
"Hypervisor": "xen",
"Name": "asano-test2",
"RootDeviceName": "/dev/xvda",
"RootDeviceType": "ebs",
"SriovNetSupport": "simple",
"Tags": [
{
"Key": "Name",
"Value": "asano-test"
}
],
"VirtualizationType": "hvm"
}
]
}
$
Images→BlockDeviceMappings→Ebs→SnapshotIdという構造になっており、Automationのステップではその構造に合わせてSelector: '$.Images[0].BlockDeviceMappings[0].Ebs.SnapshotId'と記述しています。
次に起動設定作成です。
- name: CreateLaunchConfiguration
action: 'aws:executeAwsApi'
inputs:
Service: autoscaling
Api: CreateLaunchConfiguration
LaunchConfigurationName: '{{ ImageName }}'
ImageId: '{{createMyImage.ImageId}}'
InstanceType: t2.micro
KeyName: test-key
IamInstanceProfile: 'arn:xxxxxxxxxxxxxxxxxx'
InstanceMonitoring:
Enabled: false
EbsOptimized: false
AssociatePublicIpAddress: true
SecurityGroups:
- sg-xxxxxxxxxxxxxx
- sg-xxxxxxxxxxxxxx
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
SnapshotId: '{{getImageId.EBSid}}'
VolumeSize: 8
VolumeType: gp2
DeleteOnTermination: true
Encrypted: false
指定する要素が多いですが、基本的にはこれまで出てきた要素の組み合わせで記述することができると思います。コンソール上では起動設定のコピーはありますが、CLIではそれは用意されていません。ですので都度起動設定の作成をする必要があります。正しくコピーしたようにできているか不安な場合はAWS CLIでdescribeのコマンドを打って結果をjsonファイルで保存し、比較するなどの手段もあります。
起動テンプレートの場合
- name: CreateLaunchTemplateVersion
action: 'aws:executeAwsApi'
inputs:
Service: ec2
Api: CreateLaunchTemplateVersion
LaunchTemplateId: lt-xxxxxxxxxxxxx
SourceVersion: '1'
LaunchTemplateData:
ImageId: '{{createMyImage.ImageId}}'
- name: UpdateLaunchTemplate
action: 'aws:executeAwsApi'
inputs:
Service: autoscaling
Api: UpdateAutoScalingGroup
AutoScalingGroupName: xxxxxxxxxxxx
LaunchTemplate:
LaunchTemplateId: lt-xxxxxxxxxxxxxxxxxx
Version: $Latest
起動テンプレートもこれまで出てきた要素の組み合わせでしかありません。
このように、AWS CLIのコマンドを用意しつつ、Automationのドキュメントを作成するという方法をご紹介しました。
最後になりますが、起動設定は徐々に使われなくなっていく傾向になると思っています。(参照)そのため、私自身検索してもなかなか起動設定のコマンドが見つからず苦戦したので、あえてこれを選択しました。また、起動設定の作成の自動化には変数やJSONの構造など、様々な要素が必要になってきます。Automationの理解を深めるという目的でも起動設定はいい題材となると思い、これを書くことにしました。