先日の記事があまり盛り上がらないので、新しい記事書きます。
KumogataとCloudInit+cfn-initの連携について。
cfn-initはAmazon Linuxべったりな気がして使うのに抵抗があったんですが、パッケージになってますね。 Kumogataのリポジトリ内にCentOS/Ubuntu+CloudInit+cfn-initのPackerテンプレートを置きました。
サンプルテンプレート
Parameters do Password do NoEcho true Type "String" end end Resources do myEC2Instance do Type "AWS::EC2::Instance" Properties do ImageId "ami-XXXXXXXX" InstanceType "m1.large" KeyName "your_key_name" UserData do Fn__Base64 (<<-EOS).fn_join #!/bin/bash /opt/aws/bin/cfn-init -s <%= Ref "AWS::StackName" %> -r myEC2Instance --region <%= Ref "AWS::Region" %> EOS end end Metadata do AWS__CloudFormation__Init do config do packages do yum({"httpd"=>[]}) end services do sysvinit do httpd do enabled "true" ensureRunning "true" end end end commands do any_name do # `test` だとRubyのビルトインメソッドと競合します… command (<<-EOS).fn_join echo <%= Ref "Password" %> > /tmp/my-password EOS end end end # config end # AWS__CloudFormation__Init end # Metadata end end
だいたいこんな感じで使えます。
cfn-signal
を使って同期を取りながらプロビジョニングするのがいいんでしょうけど、手軽に使いたいならこういう書き方もありかなと。
_join() String#fn_join()
Fn::Join
まわりを書くのがものすごくだるかったので、String#fn_join()
というビルトイン関数を追加しました。
これを使うとRubyのコードが以下のように変換されます。
UserData do Fn__Base64 (<<-EOS).fn_join #!/bin/bash /opt/aws/bin/cfn-init -s <%= Ref "AWS::StackName" %> -r myEC2Instance --region <%= Ref "AWS::Region" %> EOS end
"UserData": { "Fn::Base64": { "Fn::Join": [ "", [ "#!/bin/bash\n/opt/aws/bin/cfn-init -s ", { "Ref": "AWS::StackName" }, " -r myEC2Instance --region ", { "Ref": "AWS::Region" }, "\n" ] ] } }
作り始めた当初は「Rubyのjoinでいいじゃん」とか思っていたんですが、テンプレートのメタ情報をサーバ内で取得しようと思うと、Fn::ほげほげは必要ですね。 パスワードをUserDataに書くわけにもいかないし。
公式のテンプレートを読んだりすると、カジュアルにUserDataにパスワードが出力されてたりするんですが、大丈夫なんだろうか… あと、スタックを保持する場合、後からパスワード等のメタ情報を取得できそうですが、その辺のケアも気になるところ。
デモ
Please try it out!