AWS CodeBuild と packer と ansible でプロビジョニング済みのAMIを自動生成する
AMI生成部分を自動化できたので、ちょっとだけまとめておく。
CodeBuild
- AWSのDockerで動くCIツール。
- CodeBuildの名前の通り、ソースコードをビルドする環境を簡単に作れることをウリにしている
- CircleCIなどのサービスでビルドしたり、Jenkinsを自前で用意するのと比較してそれほど違いはない
- 料金はビルド時間ごとの課金
- 一応無料枠もある
Packer
Ansible
参考ソース
AWSのブログにCodeBuildとPackerを使ったAMIビルダーの構築方法がある。
他にはクラスメソッドさんのブログにAnsibleとPackerの連携周りがある。
- AWS CodeBuild と HashiCorp Packer を用いた AMI ビルダーの構築方法
- Packer+AnsibleによるAMIの作成
- Packer 0.9の新機能 リモートからのAnsible Provisionerが追加されました
この辺りを読めばなんとなく作り方のイメージはできるようになるが、いくつかハマった点があるので補足としてまとめておく。
このリンクだけで十分な人はここから先は読まなくてもOKです。
大まかな流れ
- Ansibleのplaybookはgithubで管理しておく
- CodeBuildでビルド用のDockerを起動、事前のセットアップを行う
- ansible-vaultで使うパスワードをKMSから取ってくる
- 平文を嫌う場合、KMSに登録しておき、環境変数にセットする方法が使える
- packer build でAMIを生成する
AWSのブログと違う点
- Packer 1.2.1
- ansible provisionerを使うため、Docker環境へAnsibleのインストールする
- packerがIAM Roleを扱えるようになったため、クレデンシャルの生成は不要になった
EC2 IAMロールがなんか使えないの謎だから後で調べておくか..
— シリル@ガルパ沼🍊⚓️😈 (@d_cyrill1129) 2018年3月15日
- 環境変数 USER を設定する
クラスメソッドさんのPacker+AnsibleによるAMIの作成と違う点
- アクセスキーはIAM Roleを使うので変数を使わない
- ansible-localではなくansibleを使う
- ansibleのインストールは
buildspec.yml
で行う
クラスメソッドさんのPacker 0.9の新機能 リモートからのAnsible Provisionerが追加されましたと違う点
- vaultファイルの管理をする
本題
CodeBuildとPackerを使うため、それぞれのための設定ファイルを用意する。
CodeBuildが buildspec.yml
で Packer は任意の名前のJSON。
buildspec.yml
--- version: 0.2 phases: pre_build: commands: - echo 'Install Packer 1.2.1' - curl -qL -o packer.zip https://releases.hashicorp.com/packer/1.2.1/packer_1.2.1_linux_amd64.zip && unzip packer.zip - echo 'Install Ansible' - apt-get update -y - apt-get install -y software-properties-common - apt-add-repository ppa:ansible/ansible - apt-get update -y - apt-get install -y ansible - echo 'Validate packer json' - ./packer validate packer_ec2.json build: commands: - aws configure set region $AWS_REGION - echo "$ansible_vault_pass" > vault_password_file - echo 'Build AMI' - ./packer build packer_ec2.json post_build: commands: - echo "Build finished `date`"
packer_ec2.json
{ "variables":{ "vault_path": "vault_password_file" }, "builders": [{ "type": "amazon-ebs", "region": "ap-northeast-1", "source_ami": "ami-XXXXXX", "instance_type": "t2.micro", "ssh_username": "root", "ssh_timeout": "5m", "ami_name": "packer_{{ timestamp }}" }], "provisioners": [{ "type" : "ansible", "extra_arguments": "--vault-password-file={{user `vault_path`}}", "playbook_file" : "playbook.yml", "groups" : ["aws", "webserver"] }] }
groups
を配列で渡すと inventory file で複数のグループに属した場合と同じ扱いになる。
これは group_vars
などで設定を切り替える必要がある場合に便利。
vaultファイルは buildspec.yml
で出力したパスを extra_arguments
を使ってそのまま渡している。
IAM Role
XXXXXXXX にはアカウントIDを入れる
以下のポリシーを作成し、CodeBuildで使うIAM Roleにアタッチする。(インラインでも構わない)
{ "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Action": [ "ssm:GetParameters" ], "Resource": [ "arn:aws:ssm:ap-northeast-1:XXXXXXXX:parameter/ansible-vault-pass" ] }, { "Sid": "", "Effect": "Allow", "Action": [ "kms:Decrypt" ], "Resource": [ "arn:aws:kms:ap-northeast-1:XXXXXXXX:key/alias/aws/ss" ] } ] }
KMSからデータを取ってくるために必要。名前は適宜設定すること。
終わりに
いくつかハマりポイントはあったが、これでAMIをCodeBuildで自動的に作れるようになった。
あとはgithubのMergeにHookするとかすれば自動でAMIがどんどん作られていくので便利。
ただ、古いのを消さないと溜まり続けて課金がすごいことになりそう。大変ですね。
packer ansible provisioning 謎のソリューションによっていい感じにAMIが出来上がるんだけど、inventoryファイルとかが自動生成されてるっぽい。リモート側へはSSHのトンネリングかなこれは、イケてる振る舞いしてるけど裏側は結構頑張ってる
— シリル@ガルパ沼🍊⚓️😈 (@d_cyrill1129) 2018年3月15日
ついでにこれをCodeBuildに乗せたら失職チャンスでは…(人がいなくても勝手にAMIが生産されていく
— シリル@ガルパ沼🍊⚓️😈 (@d_cyrill1129) 2018年3月15日
AWS CodeBuildでPackerを使ってAnsibleのプロビジョニング走らせるところまではできたけど、これAutoScalingと組み合わせるの難しくない?みんなどうやってやってるんだ…????
— シリル@ガルパ沼🍊⚓️😈 (@d_cyrill1129) 2018年3月16日
現場からは以上です