この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
AWSでのプロビジョニングは、AWS公式サイトのドキュメント(AWS CloudFormation のアーティクルとチュートリアル)等にも記述されているように、CloudFormationを中心にPuppetやChefを組み合わせるという方法が多く使われています。
しかしPuppetもChefもサーバ/クライアント構成(またはスタンドアロン)で動作するシステムであるため、サーバとクライアントの両方にソフトウェアをインストールする必要があります。またChefのCookbookは多機能である一方少々煩雑です。
もっと簡単な処理を手軽に行えたらなぁ...ということで、サーバサービス不要でYAMLで記述するプロビジョニングツールであるAnsibleを使ってみました。
Ansibleの良い所
- sshdで接続してコマンドを投入するだけなので余計なサーバサービスの導入が不要。
- YAMLなので記述が簡単、コメントも書ける。
Ansibleで出来ること
大きく二つあります。
- モジュールを使ってリモートノードに対し単発でタスクを実行する。
- Playbooksというモジュールやコマンドを組み合わせたタスクリストを記述し、リモートノードで実行する。
Ansibleのインストール
まずAnsibleをインストールするEC2インスタンスではIAM Role for EC2でPowerUsersに設定しておきます。理由はAnsibleのec2モジュールを使うときにいちいちaws_access_keyやaws_secret_keyを記述したくないからです。IAMは本当便利ですね!
AnsibleはEPELリポジトリからインストールする必要がありますが、Amazon Linux AMIは最初からEPELリポジトリへのアクセスが設定されているので、yumコマンドにてEPELリポジトリを指定してansibleをパッケージインストールします。
$ sudo yum -y install ansible --enablerepo=epel
設定と動作確認
インベントリファイルにAnsibleの管理対象ホストを記述します。FQDNでもIPアドレスでも記述可能です。まずは動作確認としてlocalhost(127.0.0.1)を記述してみました。
$ sudo vi /etc/ansible/hosts
127.0.0.1
Pingモジュールを使って動作確認してみます。
$ ansible --private-key=./.ssh/mykey.pem 127.0.0.1 -m ping
/usr/lib64/python2.6/site-packages/Crypto/Util/number.py:57: PowmInsecureWarning: Not using mpz_powm_sec. You should rebuild using libgmp >= 5 to avoid timing attack vulnerability.
_warn("Not using mpz_powm_sec. You should rebuild using libgmp >= 5 to avoid timing attack vulnerability.", PowmInsecureWarning)
127.0.0.1 | success >> {
"changed": false,
"ping": "pong"
}
Ping自体は通っていますが、Warningメッセージが出ています。出てるメッセージの通り、python-cryptoパッケージはlibgmpのバージョンを5以上にしなさいとのことですが、Amazon Linuxにインストールされているgmpパッケージは「gmp-4.3.2-1.11.amzn1.x86_64」で、gmp-5のパッケージはリポジトリにありません。この事象についてはRedhatのSolutionsにも記載がありました(number.py in python-crypto requires libgmp >=5 to avoid PowmInsecureWarning in RHEL6)将来の解消に期待したいところですが、とりあえずAnsible自体はそのまま動くので先に進みます。
Playbooksを使ってみる
AWSらしく、EC2インスタンスを作成するPlaybookを書いてみます。
$ vi makeec2.yml
- hosts:
- 127.0.0.1
connection: local
gather_facts: False
tasks:
- name: Provision a set of instances
local_action: ec2
keypair={{keypair}}
group={{group}}
instance_type={{instance_type}}
image={{image}}
region={{region}}
wait={{wait}}
register: ec2
PlaybookのSyntaxチェックを行います。ansible-playbookというコマンドを使います。
$ ansible-playbook --syntax-check ./makeec2.yml
Playbook Syntax is fine
次にPlaybookで行われるタスクを確認します。同じくansible-playbookコマンドを使います。
$ ansible-playbook --list-tasks ./makeec2.yml
playbook: ./makeec2.yml
play #1 (127.0.0.1):
Provision a set of instances
「Provision a set of instances」というタスク名(nameに記述したもの)が返ってきています。
それでは実際に動かしてみましょう!
$ ansible 127.0.0.1 -m ec2 -a "image=ami-be1c848e instance_type=t1.micro keypair=mykey group=ec2-servers region=us-west-2 wait=true" -c local
127.0.0.1 | success >> {
"changed": true,
"instance_ids": [
"i-1e9XXXXX"
],
"instances": [
{
"ami_launch_index": "0",
"architecture": "x86_64",
"dns_name": "ec2-54-201-XXX-XXX.us-west-2.compute.amazonaws.com",
"hypervisor": "xen",
"id": "i-XXXXXXXX",
"image_id": "ami-be1c848e",
"instance_type": "t1.micro",
"kernel": "aki-fc8XXXXX",
"key_name": "mykey",
"launch_time": "2013-11-18T05:29:37.000Z",
"placement": "us-west-2a",
"private_dns_name": "ip-172-31-XXX-XXX.us-west-2.compute.internal",
"private_ip": "172.31.XXX.XXX",
"public_dns_name": "ec2-54-201-XXX-XXX.us-west-2.compute.amazonaws.com",
"public_ip": "54.201.XXX.XXX",
"ramdisk": null,
"root_device_name": "/dev/sda1",
"root_device_type": "ebs",
"state": "running",
"state_code": 16,
"virtualization_type": "paravirtual"
}
]
}
出来ました!
まとめ
導入の敷居が低くYAMLで記述するため簡易で分かりやすいことがAnsibleの強みだと思います。大規模で複雑なシステムではChefのように様々なパターンに対応できるツールのほうが便利だと思いますが、小規模であったり簡易であったりするパターンでは、Ansibleも候補の一つに出来るのでは無いでしょうか。