前回、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の理解を深めるという目的でも起動設定はいい題材となると思い、これを書くことにしました。