localdisk

PHP とか Java とか Web とか好きなことを書きます。

足りないインフラ力をAnsibleでまかなう

2014/01/22 追記あり

このエントリを書いたあと、いくつかアドバイスを頂いた。ありがとうございます。それを受けていくつか playbook を修正しています。


僕の感想。


みんなブログ書くといい。


Vagrant の使用には慣れたものの、年末 Chef に挫折。インフラ力の高まりは感じただけで終わってしまったのだった。いや、ここで諦めてはいけない。他の選択肢を検討に入れてみよう。Puppet …も難しそうだ。 Chef に挫折したことを考えると勝算は低い。
なので Ansible に挑戦してみた。

読むのが面倒な人のためのまとめ

Ansible は Chef/Puppet とくらべて

  • サーバーに Ansible をインストールする必要がない
  • サーバーの構成を定義する Playbook は YAML 形式で記述するので Ruby 力の低い人も安心

という利点があり、Chef に挫折した自分でも丸一日の学習でなんとかなるので学習コストはかなり低いと言える。
しかし、この手のツール全てに言えることだけど Chef/Puppet/Ansible を使ったからと言って低いインフラ力が高くなるわけではないし*1、実際は状況に合わせたこまめなメンテナンスが必要になる。こまめなメンテナンスや調整は高いインフラ力を必要とするわけで、結局のところVagrant 使って開発用のサーバを作って一人で開発するという使い方であればあんまり必要ないと思う。

結論:得意なやつに任せろ。

目標

Ansible を使用して速やかにサーバ環境を作成する。デプロイに関しては考えない。
実益を兼ねて以下のアプリケーションをインストールできるまで頑張りたい。

前提

以後の作業は以下のバージョンで進めていきます

インストール

インストールのページを見るに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/configVagrant の情報が追記される。

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 モジュールを使用するよう変更した。

なんのことはない。簡単である。

*1:少しはましになるとは思う

*2:Windows isn’t supported for the control machine

*3:2014/01/19 現在の stable は 2.8.4