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日
現場からは以上です