この記事はZOZOテクノロジーズ #2 Advent Calendar 2019 14日目の記事になります。
昨日は、@_sa_chi_03さんの「ZOZOTOWNのメールマガジンの仕組みについて」でした。
まえがき
ZOZOテクノロジーズ SREチームのテックリード光野と申します。普段はAWSを使って、より安全でより手がかからず、お金もかからない。でも速い。そんないい感じのネットワーク構築に邁進しています。
さて、この記事ではAWS re:Invent 2019で発表されたEC2 Image Builderを扱います。EC2 Image Builderは、指定したレシピを元にEC2のカスタムイメージを作成することができるサービスです。任意もしくは定期的なタイミングでAMIを更新することができます。
AutoScalingグループと合わせれば、毎日最新のセキュリティパッチのあたったAMIを作っておいて、インスタンス入れ替え、なんて事が簡単にできます。幸せです。
この投稿では、EC2 Image Builderで作成したAMI IDを機械的に参照できるよう工夫してみたいと思います。
本文
目標:CloudFormationテンプレートで動的参照
弊社ではインフラの管理にCloudFormationを多用しています。
例えば、CloudFormationでAutoScalingの起動設定を作成する場合、次のように記述します。
AWSTemplateFormatVersion: 2010-09-09
Resources:
AutoScalingLaunchConfiguration:
Type: 'AWS::AutoScaling::LaunchConfiguration'
Properties:
ImageId: 'ami-0ab292e52c1d6ac8c' # Ubuntu 18.04 LTS
InstanceType: 'm5.large'
# 最低限の記述です。実際にはセキュリティグループなどが必要でしょう。。
ここでは、ImageId
を可変にし、CloudFormation実行のタイミングで、常にImage Builderが作成する最新のAMI IDを参照するようにします。
組み合わせ
CloudFormationではSSMのParameter Storeに登録した値を動的に参照することができます。
AWSTemplateFormatVersion: 2010-09-09
Resources:
AutoScalingLaunchConfiguration:
Type: 'AWS::AutoScaling::LaunchConfiguration'
Properties:
ImageId: "{{resolve:ssm:oreore-image-with-eib:1}}"
InstanceType: 'm5.large'
or
AWSTemplateFormatVersion: 2010-09-09
Parameters:
AMI:
Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
Default: 'oreore-image-with-eib'
Resources:
AutoScalingLaunchConfiguration:
Type: 'AWS::AutoScaling::LaunchConfiguration'
Properties:
ImageId: !Ref AMI
InstanceType: 'm5.large'
パラメータからの指定であれば、バージョン番号の入力を省略できるため、常に最新〜という指定が叶えられそうです。他方、EC2 Image BuilderはSNSに対応しているため、SNS経由でなんとかParameter Storeまで値を届けられそうな気がします。
作ったもの
ここではUserが手動でCloudFormationを更新します。
Lambdaに設定したスクリプトは以下のとおりです。Rubyが好きなので.rbです。
# coding: utf-8
require 'json'
require 'aws-sdk-ssm'
def lambda_handler(event:, context:)
message = JSON.parse(event['Records'][0]['Sns']['Message'])
puts message # debug用
client = Aws::SSM::Client.new
resp = client.put_parameter({
name: 'oreore-image-with-eib',
value: message['outputResources']['amis'][0]['image'],
type: 'String',
overwrite: true
})
{ statusCode: 200, body: JSON.generate('OK') }
end
CloudFormartionのテンプレートは上で掲載したものを使います。
AWSTemplateFormatVersion: 2010-09-09
Parameters:
AMI:
Type: 'AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>'
Default: 'oreore-image-with-eib'
Resources:
AutoScalingLaunchConfiguration:
Type: 'AWS::AutoScaling::LaunchConfiguration'
Properties:
ImageId: !Ref AMI
InstanceType: 'm5.large'
結果
しっかり反映されました!
あとがき
EC2 Image BuilderからParameter Storeを通じて、動的に最新のAMIを得ることができました。
AWSのサービスは一つ新しいものが増えると、組み合わせの楽しみがどんどん広がるので目が離せません。
CloudFormationテンプレートになってさえいればCodePipelineなどで自動化もできますし、これまで抱えていた「カスタムAMIがあればもっと効率的に色々できるけど、運用するのが面倒くさいんだよな・・・」という悩みが解決できそうでとてもワクワクしています。
明日は@murs313さんの記事になります。お楽しみに!