足りないインフラ力をAnsibleでまかなう
2014/01/22 追記あり
このエントリを書いたあと、いくつかアドバイスを頂いた。ありがとうございます。それを受けていくつか playbook を修正しています。
@localdisk pipe('|') を使う場合は command じゃなくて shell ですね。SSH のは .ssh/config が Host にマッチしたものに適用する設定だからですね
— yteraoka (@yteraoka) 2014, 1月 19
@localdisk sourceslist への追加はapt_repository を使うと冪等性が出ていいと思います。 http://t.co/iwNDw40JUC
— shirou - しろう (@r_rudi) 2014, 1月 20
僕の感想。
自分の知らないことでも頑張ってブログに書くとできる人が色々アドバイスをくれるのでみんなもっとブログ書けばいいと思った。インターネットは優しさであふれてる。
— MATSUO Masaru (@localdisk) 2014, 1月 20
みんなブログ書くといい。
Vagrant の使用には慣れたものの、年末 Chef に挫折。インフラ力の高まりは感じただけで終わってしまったのだった。いや、ここで諦めてはいけない。他の選択肢を検討に入れてみよう。Puppet …も難しそうだ。 Chef に挫折したことを考えると勝算は低い。
なので Ansible に挑戦してみた。
読むのが面倒な人のためのまとめ
Ansible は Chef/Puppet とくらべて
という利点があり、Chef に挫折した自分でも丸一日の学習でなんとかなるので学習コストはかなり低いと言える。
しかし、この手のツール全てに言えることだけど Chef/Puppet/Ansible を使ったからと言って低いインフラ力が高くなるわけではないし*1、実際は状況に合わせたこまめなメンテナンスが必要になる。こまめなメンテナンスや調整は高いインフラ力を必要とするわけで、結局のところVagrant 使って開発用のサーバを作って一人で開発するという使い方であればあんまり必要ないと思う。
結論:得意なやつに任せろ。
目標
Ansible を使用して速やかにサーバ環境を作成する。デプロイに関しては考えない。
実益を兼ねて以下のアプリケーションをインストールできるまで頑張りたい。
前提
以後の作業は以下のバージョンで進めていきます
- Max OS 10.9.1
- VirtualBox 4.3.6
- Vagrant 1.4.3
- Python 2.7.6
- pip 1.4.1
- Ansible 1.4.4
インストール
インストールのページを見るにPythonは2.6以上が良いみたいだ。あと Windows は諦めろって書いてある。*2 もうほんと Windows では開発作業に支障がでるレベルになってて不憫である。主に仕事で使わざるを得ない自分が。
今回は Mac なので pip という Python のパッケージマネージャを使用してインストールする。
$ easy_install pip
自分のPCでは 1.4.1 がインストールされてた。
$ sudo pip install ansible
で、Enter。最初うっかり sudo
抜きでやってしまい
error: could not create '/usr/share/ansible': Permission denied
と怒られることになってしまったので注意が必要だ。うまくいくとコンソールにいろいろ出力されて最終的に
Successfully installed ansible paramiko jinja2 PyYAML httplib2 pycrypto ecdsa markupsafe
と出れば OK だと思う。
バージョンは 1.4.4 のようだ。
$ ansible --version ansible 1.4.4
接続
まずは Vagrant での接続を試してみよう。というわけで Vagrantfile を用意する。
そして起動。
$ vagrant up
ssh に登録。
$ vagrant ssh-config >> ~/.ssh/config
すると ~/.ssh/config
に Vagrant の情報が追記される。
Host node HostName 127.0.0.1 User vagrant Port 2222 UserKnownHostsFile /dev/null StrictHostKeyChecking no PasswordAuthentication no IdentityFile ~/.vagrant.d/insecure_private_key IdentitiesOnly yes LogLevel FATAL
その後に Ansible のインベントリファイルというやつを作ってやる。Ansible を適用する接続情報だと思っておけばOKだと思う。多分。ここでは hosts
というファイル名にする。
$ cat hosts
してこのような内容にしておこう
[vagrant] 192.168.33.10
そして Ansible から ping をうってみよう。
$ ansible -i hosts all -m ping
すると
192.168.33.10 | FAILED => SSH encountered an unknown error during the connection. We recommend you re-run the command using -vvvv, which will enable SSH debugging output to help diagnose the issue
繋がっ…てない。アルェー? とりあえず debug 情報を出すために -vvv オプションをつけてみる。
$ ansible -i hosts all -m ping -vvv
デバッグ情報が出てきたが…わからん。多分 ~/.ssh/config に追記された内容がおかしいような気がするので修正してみる。
Host 192.168.33.10 HostName 192.168.33.10 User vagrant Port 2222 UserKnownHostsFile /dev/null StrictHostKeyChecking no PasswordAuthentication no IdentityFile ~/.vagrant.d/insecure_private_key IdentitiesOnly yes LogLevel FATAL
Host と HostName を書き換えてみると…。
$ ansible -i hosts all -m ping 192.168.33.10 | success >> { "changed": false, "ping": "pong" }
うまくいった。理由はわからない。
playbook
Ansible では接続を定義するインベントリファイルとサーバの構成を管理する playbook というファイルが最低限必要になる。Best Practices という推奨された構成があるが、慣れてから手を付けたほうが良いように思う。
Chef をちょっと触っただけでわかった気になった自分の knife の切れ味に絶望して何もかもを放り出してしまったあの痛ましい事件を忘れてはならない。
簡単な playbook を作って実行する
playbook は yaml で記述する。ここが Ansible の良いところだと僕は思っている。Ruby 力が足りないプログラマでも優しいのだ。デザイナさんにもおすすめできるのもよい。
$ touch playbook.yml
で作って
- hosts: 192.168.33.10 user: vagrant sudo: yes tasks: - debug: msg="Hello! Ansible!"
と書いてみよう。早速実行?いや、まずはチェックだ。
$ ansible-playbook -i hosts --syntax-check playbook.yml
を実行しよう。typo があった場合は怒られるぞ。では、エラーがなかったので実行しよう。
$ ansible-playbook -i hosts --syntax-check playbook.yml PLAY [192.168.33.10] ********************************************************** GATHERING FACTS *************************************************************** ok: [192.168.33.10] TASK: [debug msg="Hello! Ansible!"] ******************************************* ok: [192.168.33.10] => { "msg": "Hello! Ansible!" } PLAY RECAP ******************************************************************** 192.168.33.10 : ok=2 changed=0 unreachable=0 failed=0
よし、では色々とインストールしていこう。
Nginx のインストール
まずは Nginx のインストールだ playbook.yml に追記してと…
tasks: - name: install nginx apt: pkg=nginx state=latest notify: restart nginx
うん?失敗する。apt-get update
しろと言ってくる。そりゃそうか。では別に pre.yml
を用意して…
- hosts: 192.168.33.10 user: vagrant sudo: yes tasks: - name: updates a server apt: update_cache=yes - name: upgrade a server apt: upgrade=full
そして実行。時間がかかるので少し待つべし。
$ ansible-playbook -i hosts pre.yml
終わったら再び
$ ansible-playbook -i hosts playbook.yml
OKだ。vagrant ssh
してバージョンを調べてみると…
vagrant@precise64:~$ nginx -v nginx version: nginx/1.1.19
古い…。仕方がないので Ubuntu 12.04 LTS に最新の Nginx をインストールする - xykの日記 を参考にして操作を playbook に落としていく。
- hosts: 192.168.33.10 user: vagrant sudo: yes tasks: - name: update sources list1 apt_repository: repo="deb http://nginx.org/packages/ubuntu/ precise nginx" - name: update sources list2 apt_repository: repo="deb-src http://nginx.org/packages/ubuntu/ precise nginx" - name: PGP Key Add apt_key: url=http://nginx.org/keys/nginx_signing.key - name: install nginx apt: pkg=nginx update_cache=yes - name: restart nginx service: name=nginx state=restarted enabled=yes
これで nginx の version が 1.4.4 になった。
sourceslist の追加が苦肉の策すぎてブログに載せるをためらうレベルだけど、誰かが教えてくれることを祈ってそのままにしておく。
(2014/01/22追記)
lineinfile モジュールの部分を apt_repository モジュールを使用するよう変更した。
MySQL のインストール
これはわりとすんなりと。今思ったけど、ファイル分けるより tag をつけたほうがいいね。
- hosts: 192.168.33.10 user: vagrant sudo: yes tasks: - name: install mysql apt: pkg=mysql-server - name: start mysql service: name=mysql state=started enabled=yes
PHP のインストール
ppa を足すときに、python-pycurl
のインストールを求められるくらいで特に引っかかるところはなかった。
- hosts: 192.168.33.10 user: vagrant sudo: yes tasks: - name: install python-pycurl apt: pkg=python-pycurl - name: add php repository apt_repository: repo='ppa:ondrej/php5' - name: install php apt: pkg={{ item }} update_cache=yes with_items: - php5 - php5-cli - php5-fpm - php-pear - php5-dev - php-apc - php5-mcrypt - php5-gd - php5-curl - php5-xdebug - php5-sqlite
Composer のインストール
command: curl -sS https://getcomposer.org/installer | php
と書くと "|" を誤認識(?)するらしく以下の様なエラーになる。
failed: [192.168.33.10] => {"changed": true, "cmd": ["curl", "-sS", "https://getcomposer.org/installer", "|", "php"], "delta": "0:00:41.804834", "end": "2014-01-19 11:42:57.120323", "rc": 6, "start": "2014-01-19 11:42:15.315489"} stderr: curl: (6) Couldn't resolve host '|'
仕方がないので vagrant-ansible-symfony2/devops/webserver.yml at master · tvieira/vagrant-ansible-symfony2 · GitHub から引用。
- hosts: 192.168.33.10 user: vagrant sudo: yes tasks: - name: install composer shell: curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin - name: move composer.phar to composer command: mv /usr/bin/composer.phar /usr/bin/composer
(2014/01/22追記)
command モジュールの部分を shell モジュールを使用するよう変更した。
Redis をインストールする
apt だと 2.2.2 とバージョンが古い。自分は詳しくないのだが、これでよいのだろうか?*3。ビルドするにはjprichardson/ansible-redis · GitHubが詳しい。
もう疲れてきた…。
HHVM のインストール
これで最後。この Playbook だけはぐぐっても見つからなかったので、このエントリでは唯一価値あるものだと思う。
- hosts: 192.168.33.10 user: vagrant sudo: yes tasks: - name: Add HHVM Key apt_key: url=http://dl.hhvm.com/conf/hhvm.gpg.key - name: Add Sources List apt_repository: repo="deb http://dl.hhvm.com/ubuntu precise main" - name: Install HHVM apt: pkg=hhvm-fastcgi update_cache=yes
(2014/01/22追記)
lineinfile モジュールの部分を apt_repository モジュールを使用するよう変更した。
なんのことはない。簡単である。