この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
渡辺です。
クラスメソッドのAWSチームは基本的に自分が使いやすいツールを選択するので統一されていません。 が、誰からいいね!と推しはじめると流行していく、そんな雰囲気です。
Ansible
AnsibleはChefなどと同じ構成管理ツールのひとつで、AWSチームではAnsibleを使う人が多くなってきました。Ansibleの紹介は、構成管理ツール Ansibleを使ってみるを読んでみてください。
Packer
Packerも広義には構成管理ツールですが、マシンイメージを作成するためのツールです。 AWSで言えばEBSマシンイメージを作るのに利用できます。 Packerについては、PackerでAmazon LinuxのAMI(Amazon Machine Image)を作成するを参照ください。
PackerでAnsibleによる構成管理
Packerはマシンイメージを作成するためのツールで簡単なスクリプトなどを実行することができます。 しかし、複雑な構成管理となるとChefやAnsibleなどのように多機能というわけではなく、シェルスクリプト地獄に陥ってしまうのが難点です。 そもそもシェルスクリプトだけで構成管理が可能であれば、EC2のUserDataを使えば済むわけなので、わざわざPackerを利用することもないでしょう。
builderとprovisioner
PackerではAWSのイメージを作る部分はbuilderと呼びます。 builderはAMI以外でも、VirtualBoxなどの仮想マシンイメージを作るのに利用することができます。
一方、構築用の定義はprovisionerに定義します。 シェルスクリプトを実行するのであれば、shell provisionerを指定します。 shell provisionerの他にもchefやansibleもprovisionerとして対応しているため、好きな構成管理ツールで構成を定義し、Packerでイメージを作るという使い方が出来るわけです。
というわけで、Ansibleで構成管理を行いAMIを作成してみました。
AnsibleのPlaybookの作成
AnsibleのPlaybookは、構成の定義ファイルです。 Apacheとmysql クライアントをインストールし、起動時にApacheを起動する簡単な定義ファイルを作成しました。
setup.yml
- hosts: all
sudo: yes
tasks:
- name: install Apache24 and mysql client
yum: pkg={{item}} state=installed
with_items:
- mysql
- httpd24
- name: enable httpd service
service: name=httpd enabled=yes
ポイントとしては、ec2-userでAnsibleが実行されるため、sudoをyesに設定することです。
Packerのテンプレートの作成
続けてPackerのテンプレートを作成します。
web.json
{
"variables": {
"aws_access_key": "",
"aws_secret_key": ""
},
"builders": [{
"type": "amazon-ebs",
"access_key": "{{user `aws_access_key`}}",
"secret_key": "{{user `aws_secret_key`}}",
"region": "ap-northeast-1",
"source_ami": "ami-4985b048",
"instance_type": "t2.small",
"ssh_username": "ec2-user",
"ssh_timeout": "5m",
"ami_name": "Web_{{isotime | clean_ami_name}}"
}],
"provisioners": [{
"type": "shell",
"inline": [
"sudo yum -y update",
"sudo yum -y --enablerepo=epel install ansible"
]
},{
"type": "ansible-local",
"playbook_file": "setup.yml"
}]
}
buildersにamazon-ebsを指定し、PackerがAnsibleを使い実行する環境を定義します。 Ansibleはlocalで実行する、つまりEC2インスタンスで実行され自分自身を構成する方式です。 通常のAnsibleのようにローカル環境からSSHで接続して実行する形式は現時点ではサポートされていないので注意してください。
また、AWSのアクセスキーとシークレットキーを定義する必要がありますが、このテンプレートファイルはgitなどでバージョン管理するため生情報を埋め込んではいけません。 PackerのVariablesの機能を利用し、外部のVariableファイルに定義してください。 Variableファイルは.gitignoreなどでバージョン管理外としておきます。
variables.json
{
"aws_access_key": "[YOUR_AWS_ACCESS_KEY]",
"aws_secret_key": "[YOUR_AWS_SECRET_KEY]"
}
provisionersには構成管理に必要な定義を記述していきます。 ここはansible-localを指定すれば良いのですが、実行するEC2インスタンスにAnsibleがインストールされていないとコケてしまうため、ansibleのインストールはPackerのshell provisionerでインストールしておきます。 ansible-localでの設定は、先ほど作成したsetup.ymlを指定するだけです、簡単ですね。
ビルド
ビルドはPackerコマンドで、Variableファイルをオプションで指定して実行します。
$ packer build -var-file=variables.json web.json
ビルドがはじまると、AWS環境にEC2インスタンスが作成され、環境構築がはじまります。 はじめにshell provisionerでAnsibleがインストールされ、後続のansible-local provisionerで必要なミドルウェアや環境設定が行われていきます。 構築が完了すると、AMI(マシンイメージ)が作成され、構築用に作成されたEC2インスタンスは破棄されます。
$ packer build -var-file=variables.json web.json
amazon-ebs output will be in this color.
==> amazon-ebs: Inspecting the source AMI...
==> amazon-ebs: Creating temporary keypair: packer 548e8a9c-cbff-a528-8933-c274c1a5666e
==> amazon-ebs: Creating temporary security group for this instance...
==> amazon-ebs: Authorizing SSH access on the temporary security group...
==> amazon-ebs: Launching a source AWS instance...
amazon-ebs: Instance ID: i-72c8e36b
==> amazon-ebs: Waiting for instance (i-72c8e36b) to become ready...
==> amazon-ebs: Waiting for SSH to become available...
==> amazon-ebs: Connected to SSH!
==> amazon-ebs: Provisioning with shell script: /var/folders/k4/k385q7zs26z3h5ngv4d1rwk80000gn/T/packer-shell972002311
(中略)
amazon-ebs: Complete!
==> amazon-ebs: Provisioning with Ansible...
amazon-ebs: Creating Ansible staging directory...
amazon-ebs: Creating directory: /tmp/packer-provisioner-ansible-local
amazon-ebs: Uploading main Playbook file...
amazon-ebs: Uploading inventory file...
(中略)
==> amazon-ebs: Stopping the source instance...
==> amazon-ebs: Waiting for the instance to stop...
==> amazon-ebs: Creating the AMI: Web_2014-12-15T07-15-40Z
amazon-ebs: AMI: ami-XXXXXXXXX
==> amazon-ebs: Waiting for AMI to become ready...
==> amazon-ebs: Terminating the source AWS instance...
==> amazon-ebs: Deleting temporary security group...
==> amazon-ebs: Deleting temporary keypair...
Build 'amazon-ebs' finished.
==> Builds finished. The artifacts of successful builds are:
--> amazon-ebs: AMIs were created:
最後にAMIのイメージIDが表示されるのでメモしましょう。
なお、構築を何度もしているとこのようにterminatedのインスタンスまみれになりますw
AMIの活用
Packerを利用するパターンではインスタンスを予め作りAMIとして保存してしまうため、CloudFormationとの相性が抜群に良いです。 CloudFormationで面倒なUserDataやCloudInitを利用せずに、構成管理は専門のツールを使うワケです。 また、AMIはバージョンアップ時にも残しておくことで、EC2インスタンスのバージョンも簡単に管理できますね。