Web Pencil

AnsibleでLAMP環境構築

Ansibleを使用して、LAMP環境をプロビジョニングします。

とりあえず、流れを分かりやすくするため、今回はymlを1つのファイルで書いてます。
行っている内容は、ざっくり書くと以下になります。

– 基本パッケージのインストール(wget,ntp,libselinux-python,rsync,unzip,vim)
– SELinux無効化
– iptabes停止処理
– リポジトリの追加(epel,remi)
– Apache2.2 インストール、チューニング
– mysql5.5 インストール、チューニング
– localtimeの変更
– PHP5.6 & 各種モジュールのインストール、設定変更

環境は以前のブログで書いたMac-PCのVagrant環境を使用しています。
Vagrant+Virtualbox使い方(Mac PCにて)

最終的なディレクトリ構造は以下です。各ファイルの説明を個別にしていきます。

$ tree
.
├── Vagrantfile  # Vagrantファイル
├── ansible
│   ├── httpd_conf_tuning.sh  # Apache初期設定スクリプト(自作Shell:サーバ側で動きます。)
│   ├── my.cnf.local          # my.cnf設定ファイルテンプレート
│   └── playbook.yml          # Ansible設定ファイル
├── check_add_repository.sh   # リポジトリ追加チェック。(冪等性は保つが、処理が先に進まないのを防ぐ為、独自チェックスクリプトを作成)
├── hosts                     # 対象サーバ指定ファイル
└── provision-script
    └── start-setting.sh      # Ansible起動時設定ファイル
Ansibleインストール

まずは、Ansibleをインストールします。

$ brew install ansible
Vagrantプロビジョニング呼び出し設定
$ vim Vagrantfile

Vagrantファイル内容

Vagrant.configure("2") do |config|
  config.vm.box = "bento/centos-6.7"
  config.vm.network "private_network", ip: "192.168.33.22"
  config.vm.provision "ansible" do |ansible|
    ansible.playbook = "./ansible/playbook.yml"
    ansible.inventory_path = "hosts"
    ansible.limit = 'all'
  end
end
Ansible起動時設定ファイル作成
vim ./provision-script/start-setting.sh
#!/bin/bash

PYTHONUNBUFFERED=1 ansible-playbook -c local /vagrant/ansible/playbook.yml

-c はコネクションの指定オプション。以下3つの中から選択します。
・local
・ssh
・paramiko

今回は、サーバ内のlocalで動かすので、localを指定しています。
sshは、別環境からSSH接続で使う場合に指定します。
paramikoは、ファイルの転送に必ずSFTPを使おうとします。
paramikoはsshのpythonライブラリで、ansibleが何も指定しないと、デフォルトで使おうとします。
SFTPを閉じている場合は、sshを指定します。
local or paramikoで、基本よさげです。

PYTHONUNBUFFERED=1と記述することで、
Pythonのstdin, stdout, stderr のバッファを強制的に無効にすることができるため、
playbook内の途中のタスク結果も見れます。

ansible設定ファイル作成
$ mkdir ansible
$ vim ./ansible/playbook.yml

playbook.ymlの最終的なものを先に貼っておきます。
下の方で内容を個別に解説していきます。

- hosts: web
  user: vagrant
  sudo: yes
  vars:
        mysql_root_pw: "mysqlrootpwd9999"

  handlers:
    - name: restart apache
      service: name=httpd state=restarted enabled=yes
    - name: mysql setup
      service: name=mysqld state=started enabled=yes
    - name: mysql set password
      command: mysqladmin -u root password "{{ mysql_root_pw }}"
    - name: restart mysqld
      service: name=mysqld state=restarted
  tasks:
    - name: check install basepackage
      shell: "which vim"
      register: which_result
      ignore_errors: true
      changed_when: false
    - name: Install basepackage
      when: which_result.rc == 1
      with_items:
        - wget
        - ntp
        - libselinux-python
        - rsync
        - unzip
        - vim
      yum: name={{ item }} state=present

    - name: check selinux
      shell: "getenforce | grep Permissive"
      register: check_selinux_result
      ignore_errors: true
      changed_when: false
    - name: SELinux Disable
      when: check_selinux_result.rc != 0
      command: setenforce 0
      ignore_errors: true

    - name: check selinux config
      shell: "grep \"^SELINUX=disabled\" /etc/selinux/config"
      register: check_selinux_config_result
      ignore_errors: true
      changed_when: false
    - name: edit selinux config
      when: check_selinux_config_result.rc == 1
      replace: dest=/etc/selinux/config regexp="^SELINUX=permissive" replace="SELINUX=disabled" backup=yes
##      command: sed -i -e "s/^SELINUX=permissive/SELINUX=disabled/g" /etc/selinux/config
##      replace: dest=/etc/selinux/config regexp="SELINUX=permissive" replace="SELINUX=disabled" backup=yes     (ansibleのreplaceモジュールで置換パターン)

    - name: stop iptabes
      service: name=iptables state=stopped

    - name: check add repository
      shell: "sh /vagrant/check_add_repository.sh"
      register: check_add_repository_result
      ignore_errors: true
      changed_when: false
    - name : add repository
      when: check_add_repository_result.stdout == "0"
      with_items:
        - http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
        - http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
      yum: name={{item}}

    - name: yum install apache
      yum: name=httpd state=latest

    - name: apache tuning check
      shell: "ls /etc/httpd/conf/httpd.conf_org"
      register: apache_tuning_check
      ignore_errors: true
      changed_when: false
    - name: apache tuning
      when: apache_tuning_check.rc != 0
      command: sh /vagrant/ansible/httpd_conf_tuning.sh

    - name: started apache
      action: service name=httpd state=started enabled=yes
      notify: restart apache

    - name: yum install mysql
      with_items:
        - {name: mysql,        repo: remi}
        - {name: mysql-server, repo: remi}
        - {name: mysql-devel,  repo: remi}
      yum: name="{{item.name}}" enablerepo="{{item.repo}}" state=present

    - name: my.cnf edit
      copy:
        src=./my.cnf.local
        dest=/etc/my.cnf

    - name: started mysqld
      action: service name=mysqld state=started enabled=yes
      notify: mysql set password

    - name: started ntpd
      action: service name=ntpd state=started enabled=yes

    - name: check localtime Tokyo
      shell: "date | grep JST"
      register: check_localtime_Tokyo_result
      ignore_errors: true
      changed_when: false
    - name: localtime Tokyo set
      when: check_localtime_Tokyo_result.rc != 0
      shell: cp -fp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

    - name: Install php56
      with_items:
        - php56-php
        - php56-php-mysqlnd
        - php56-php-common
        - php56-php-devel
        - php56-php-gd
        - php56-php-mbstring
        - php56-php-mcrypt
        - php56-php-xml
      yum: name={{ item }} state=present

    - name: php56 path profile check
      command: "grep remi /etc/profile"
      register: php_profile_check_result
      ignore_errors: true
      changed_when: false
    - name: php56 add path
      when: php_profile_check_result.rc != 0
      shell: "cat /opt/remi/php56/enable >> /etc/profile"

    - name: check symbolic link php.ini
      shell: "ls /etc/php.ini"
      register: phpini_result
      ignore_errors: true
      changed_when: false

    - name: create symbolic link php.ini
      when: phpini_result.rc != 0
      shell: "ln -s /opt/remi/php56/root/etc/php.ini /etc/php.ini"
      ignore_errors: true
      changed_when: false

    - name: edit php.ini time_zone set Asia Tokyo
      replace: dest=/opt/remi/php56/root/etc/php.ini regexp="^;date.timezone =" replace="date.timezone = \"Asia/Tokyo\"" backup=yes
      ignore_errors: true

playbook.ymlを個別解説

接続情報等の設定

- hosts: web
  user: vagrant
  sudo: yes
  vars:
        mysql_root_pw: "mysqlrootpwd9999"

hosts: web で接続先を指定しています。webは任意の名前で、hostsファイルに記載したものになります。
hostsファイルの中身

[web]
192.168.33.22

ホスト接続先ユーザーの指定で、vagrantユーザーを指定しています。
sudoを有効化し、playbookすべてをsudoで実行しています。(sudo: no で接続ユーザーで実行されます。)
vars:で変数を定義をしています。mysqlのrootパスワードを定義しています。

ハンドラの設定

function的な感じでしょうか。
以下のようにして、ハンドラを定義していきます。

  handlers:
    - name: restart apache
      service: name=httpd state=restarted enabled=yes
    - name: mysql setup
      service: name=mysqld state=started enabled=yes
    - name: mysql set password
      command: mysqladmin -u root password "{{ mysql_root_pw }}"
    - name: restart mysqld
      service: name=mysqld state=restarted
実行タイミングについて
notify: restart apache

と記述すると、以下のハンドラが呼び出すことができます。
※ ただし、Ansibleを実行し、タスクが”CHANGED”を返したときだけ実行されるのに注意!!!

タスクの設定
基本パッケージインストールチェック&インストール処理
  tasks:
    - name: check install basepackage
      shell: "which vim"
      register: which_result
      ignore_errors: true
      changed_when: false
    - name: Install basepackage
      when: which_result.rc == 1
      with_items:
        - wget
        - ntp
        - libselinux-python
        - rsync
        - unzip
        - vim
      yum: name={{ item }} state=present

1. まず、which vimを実行し、インストールされているかチェックしています。
チェックをしなくても、冪等性は確保できているのですが、ansible実行の際、NGが出ないようにするため、チェックを入れるようにしてみました。

2. register: which_result の指定により、チェック用のコマンド(which vim)の終了ステータスをwhich_resultという変数に保持しています。

3. コマンドの終了ステータスが異常(0以外)でも処理を継続するためにignore_errors: trueを指定しています。

4. when: which_result.rc == 1 と指定することで、インストールチェックにより、wgetがインストールされていない場合(リターンコード1)は、パッケージのインストールを行うようにしています。

5. with_itemsで、以下パッケージ配列にすることができます。
以下のパッケージをyumでインストールを行うようにしています。
with_items:
– wget
– ntp
– libselinux-python
– rsync
– unzip
– vim

なんでlibselinux-pythonをインストールしているの?
▼ Answer
最近のRed Hat系のディストリビューションではデフォルトでSELinuxが有効になっているため、ansibleのファイル操作系モジュールでエラーになるのを避けるためにlibselinux-pythonをインストールしています。

6. インストール方法は、以下のように、yumでインストールします。
配列(with_items)に入ったものを{{ item }}で取得し、loopしているイメージです。
yum: name={{ item }} state=present

因に、stateに設定できるものは以下があります。
present #インストール
latest #更新
absent #削除

SElinux無効チェック&無効化処理(一時的に無効化する)
    - name: check selinux
      shell: "getenforce | grep Permissive"
      register: check_selinux_result
      ignore_errors: true
      changed_when: false
    - name: SELinux Disable
      when: check_selinux_result.rc != 0
      command: setenforce 0
      ignore_errors: true

getenforce | grep Permissive コマンドを投げ、結果のリターンコードを判定し、
0以外だったら、setenforce 0コマンドを投げ、SElinuxを無効化しています。

SElinux設定ファイル書き換えチェック&書き換え処理(永続的に無効化する)
    - name: check selinux config
      shell: "grep \"^SELINUX=disabled\" /etc/selinux/config"
      register: check_selinux_config_result
      ignore_errors: true
      changed_when: false
    - name: edit selinux config
      when: check_selinux_config_result.rc == 1
      replace: dest=/etc/selinux/config regexp="^SELINUX=permissive" replace="SELINUX=disabled" backup=yes
##      command: sed -i -e "s/^SELINUX=permissive/SELINUX=disabled/g" /etc/selinux/config
##      replace: dest=/etc/selinux/config regexp="^SELINUX=permissive" replace="SELINUX=disabled" backup=yes

grep \”^SELINUX=disabled\” /etc/selinux/config コマンドで、設定ファイルに無効化の記述があるか、確認しています。
記述が無かった場合(リターンコードが1の場合)は、置換処理を行っています。
以下はansibleのreplaceモジュールで置換する方法です。

replace: dest=/etc/selinux/config regexp="^SELINUX=permissive" replace="SELINUX=disabled" backup=yes

以下は、commandモジュールで置換する方法で、どちらを使用しても置換できます。

command: sed -i -e "s/^SELINUX=permissive/SELINUX=disabled/g" /etc/selinux/config
iptables停止処理
    - name: stop iptabes
      service: name=iptables state=stopped

serviceモジュールを使用し、iptablesを停止しています。

リポジトリ追加チェック&リポジトリ追加処理
    - name: check add repository
      shell: "sh /vagrant/check_add_repository.sh"
      register: check_add_repository_result
      ignore_errors: true
      changed_when: false
    - name : add repository
      when: check_add_repository_result.stdout == "0"
      with_items:
        - http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
        - http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
      yum: name={{item}}

1. リポジトリチェックを行うシェルを実行します。
check_add_repository.shの内容

#!/bin/bash

ls /etc/yum.repos.d/remi* > ./repo_check.txt
ls /etc/yum.repos.d/epel* >> ./repo_check.txt
repo_count=`cat ./repo_check.txt | wc -l`

echo $repo_count

rm -f ./repo_check.txt

exit 0

2. 標準出力した数値が、”0”だったら、with_itemsに記載しているリポジトリをインストールします。

Apacheインストール&チューニングチェック&チューニング&Apache起動
    - name: yum install apache
      yum: name=httpd state=latest
    - name: apache tuning check
      shell: "ls /etc/httpd/conf/httpd.conf_org"
      register: apache_tuning_check
      ignore_errors: true
      changed_when: false
    - name: apache tuning
      when: apache_tuning_check.rc != 0
      command: sh /vagrant/ansible/httpd_conf_tuning.sh

    - name: started apache
      action: service name=httpd state=started enabled=yes
      notify: restart apache

1. yumでapacheをインストールしています。
2. チューニングチェックとして、ls /etc/httpd/conf/httpd.conf_orgコマンドでファイルが存在するかチェックしています。
3. /etc/httpd/conf/httpd.conf_orgファイルが存在しなかった場合、apacheのチューニング(httpd.confの修正)を行います。
httpd.confの修正は以下のシェルで行っています。
/vagrant/ansible/httpd_conf_tuning.shの内容

#!/bin/bash

cp -fp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf_org

sed -i 's/^ServerTokens OS/ServerTokens ProductOnly/' /etc/httpd/conf/httpd.conf
sed -i 's/^ServerSignature On/ServerSignature Off/' /etc/httpd/conf/httpd.conf
sed -i 's/#ServerName www.example.com:80/ServerName www.example.com:80/' /etc/httpd/conf/httpd.conf

cat << _EOF_ >> /etc/httpd/conf/httpd.conf

#####################################################################
NameVirtualHost *:80
Include /etc/httpd/conf/vhosts/*.conf
#####################################################################

_EOF_

mkdir /etc/httpd/conf/vhosts

cat << _EOF_ >> /etc/httpd/conf/vhosts/00_dummy.conf
<VirtualHost *:80>
    ServerName dummy
    ServerSignature Off
    <Location />
        Order deny,allow
        Deny from All
    </Location>
</VirtualHost>

_EOF_

exit 0

4. Apacheの起動設定をしています。
以下で、起動設定をon(chkconfigをon)にしています。

      action: service name=httpd state=started enabled=yes

以下のnotify属性を書くことで、chkconfigに変更があった場合(デフォルトoffなので、onになった場合)は、Apacheをrestartをするようにしています。(初期設定時のみ動くことを想定しています。)

      notify: restart apache

実行内容はハンドラで記載の通り、Ansibleのserviceモジュールで、Apacheを再起動しています。

MySQLインストール&チューニング&MySQL起動
    - name: yum install mysql
      with_items:
        - {name: mysql,        repo: remi}
        - {name: mysql-server, repo: remi}
        - {name: mysql-devel,  repo: remi}
      yum: name="{{item.name}}" enablerepo="{{item.repo}}" state=present

    - name: my.cnf edit
      copy:
        src=./my.cnf.local
        dest=/etc/my.cnf

    - name: started mysqld
      action: service name=mysqld state=started enabled=yes
      notify: mysql set password

1. mysql,mysql-server,mysql-develをremiリポジトリからyumでインストールしています。
2. my.cnfの変更を行っています。あらかじめ用意しておいたmy.cnf.localを/etc/my.cnfにコピーしています。
▼my.cnf.localの内容

[mysqld]
character-set-server = utf8
skip-character-set-client-handshake = 1
max_connect_errors = 999999999

datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock

symbolic-links=0

user=mysql

[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

[mysql]
default-character-set = utf8

!includedir /etc/my.cnf.d

3. 起動設定をon(chkconfigをon)にしています。
4. chkconfigに変更があった場合(デフォルトoffなので、onになった場合)は、mysqlのrootパスワードを変更しています。(初期設定時のみ動くことを想定しています。)
実行内容はハンドラで記載の通り、Ansibleのcommandモジュールでmysqladmin -u root password “{{ mysql_root_pw }}”を投げています。
“{{ mysql_root_pw }}”はvarsで変数の定義をしていますので、mysqlrootpwd9999が入ります。

NTPDの起動設定
    - name: started ntpd
      action: service name=ntpd state=started enabled=yes

ntpdを起動し、chkconfigの設定をonにしています。
▼stateのオプション
(started|stopped|restarted|reloaded)
started=サービス開始
stopped=サービス停止
restarted=サービス再起動
reloaded=サービス再読み込み

▼enabledのオプション(chkconfig)
(yes|no)
yes=chkconfig ntpd on
no=chkconfig ntpd off

タイムゾーンのチェック&タイムゾーンを変更
    - name: check localtime Tokyo
      shell: "date | grep JST"
      register: check_localtime_Tokyo_result
      ignore_errors: true
      changed_when: false
    - name: localtime Tokyo set
      when: check_localtime_Tokyo_result.rc != 0
      shell: cp -fp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

1. date | grep JSTでタイムゾーンがJSTになっているかチェックします。
2. 上記コマンドのリターンコードが0以外だったら、(タイムゾーンがJSTではなかったら)、
/usr/share/zoneinfo/Asia/Tokyoを/etc/localtimeにコピーします。

PHP,その他PHPモジュールのインストール
    - name: Install php56
      with_items:
        - php56-php
        - php56-php-mysqlnd
        - php56-php-common
        - php56-php-devel
        - php56-php-gd
        - php56-php-mbstring
        - php56-php-mcrypt
        - php56-php-xml
      yum: name={{ item }} state=present

yumで、PHP,その他PHPモジュールをインストールしています。

パスの追加
    - name: php56 path profile check
      command: "grep remi /etc/profile"
      register: php_profile_check_result
      ignore_errors: true
      changed_when: false
    - name: php56 add path
      when: php_profile_check_result.rc != 0
      shell: "cat /opt/remi/php56/enable >> /etc/profile"

/etc/profileにremiの記述が無かった場合、
/opt/remi/php56/enableの内容を/etc/profileに追記しています。

php.iniシンボリックリンク存在チェック&シンボリックリンク作成処理
    - name: check symbolic link php.ini
      shell: "ls /etc/php.ini"
      register: phpini_result
      ignore_errors: true
      changed_when: false

    - name: create symbolic link php.ini
      when: phpini_result.rc != 0
      shell: "ln -s /opt/remi/php56/root/etc/php.ini /etc/php.ini"
      ignore_errors: true
      changed_when: false

1. /etc/php.iniが存在するか確認します。
2. 存在しない場合は、シンボリックリンクを作成します。

php.iniのdate.timezone変更処理
    - name: edit php.ini time_zone set Asia Tokyo
      replace: dest=/opt/remi/php56/root/etc/php.ini regexp="^;date.timezone =" replace="date.timezone = \"Asia/Tokyo\"" backup=yes
      ignore_errors: true

php.iniのdate.timezoneを”Asia/Tokyo”に変更しています。

実行結果

vagrant up時(初回時)のansibleの実行結果
failedが表示されてちょっと気持ちが悪いですが、正常な動きです。

PLAY [web] ******************************************************************** 

GATHERING FACTS *************************************************************** 
ok: [192.168.33.22]

TASK: [check install basepackage] ********************************************* 
failed: [192.168.33.22] => {"changed": false, "cmd": "which vim", "delta": "0:00:00.005449", "end": "2016-03-22 08:53:57.474031", "rc": 1, "start": "2016-03-22 08:53:57.468582", "stdout_lines": []}
stderr: which: no vim in (/sbin:/bin:/usr/sbin:/usr/bin)
...ignoring

TASK: [Install basepackage] *************************************************** 
changed: [192.168.33.22] => (item=wget,ntp,libselinux-python,rsync,unzip,vim)

TASK: [check selinux] ********************************************************* 
ok: [192.168.33.22]

TASK: [SELinux Disable] ******************************************************* 
skipping: [192.168.33.22]

TASK: [check selinux config] ************************************************** 
failed: [192.168.33.22] => {"changed": false, "cmd": "grep \"^SELINUX=disabled\" /etc/selinux/config", "delta": "0:00:00.003773", "end": "2016-03-22 08:54:36.116050", "rc": 1, "start": "2016-03-22 08:54:36.112277", "stdout_lines": []}
...ignoring

TASK: [edit selinux config] *************************************************** 
changed: [192.168.33.22]

TASK: [stop iptabes] ********************************************************** 
ok: [192.168.33.22]

TASK: [check add repository] ************************************************** 
ok: [192.168.33.22]

TASK: [add repository] ******************************************************** 
changed: [192.168.33.22] => (item=http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm,http://rpms.famillecollet.com/enterprise/remi-release-6.rpm)

TASK: [yum install apache] **************************************************** 
changed: [192.168.33.22]

TASK: [apache tuning check] *************************************************** 
failed: [192.168.33.22] => {"changed": false, "cmd": "ls /etc/httpd/conf/httpd.conf_org", "delta": "0:00:00.007893", "end": "2016-03-22 08:54:53.278608", "rc": 2, "start": "2016-03-22 08:54:53.270715", "stdout_lines": []}
stderr: ls: cannot access /etc/httpd/conf/httpd.conf_org: そのようなファイルやディレクトリはありません
...ignoring

TASK: [apache tuning] ********************************************************* 
changed: [192.168.33.22]

TASK: [started apache] ******************************************************** 
changed: [192.168.33.22]

TASK: [yum install mysql] ***************************************************** 
changed: [192.168.33.22] => (item={'repo': 'remi', 'name': 'mysql'})
changed: [192.168.33.22] => (item={'repo': 'remi', 'name': 'mysql-server'})
changed: [192.168.33.22] => (item={'repo': 'remi', 'name': 'mysql-devel'})

TASK: [my.cnf edit] *********************************************************** 
changed: [192.168.33.22]

TASK: [started mysqld] ******************************************************** 
changed: [192.168.33.22]

TASK: [started ntpd] ********************************************************** 
changed: [192.168.33.22]

TASK: [check localtime Tokyo] ************************************************* 
failed: [192.168.33.22] => {"changed": false, "cmd": "date | grep JST", "delta": "0:00:00.004957", "end": "2016-03-22 08:57:14.829182", "rc": 1, "start": "2016-03-22 08:57:14.824225", "stdout_lines": []}
...ignoring

TASK: [localtime Tokyo set] *************************************************** 
changed: [192.168.33.22]

TASK: [Install php56] ********************************************************* 
changed: [192.168.33.22] => (item=php56-php,php56-php-mysqlnd,php56-php-common,php56-php-devel,php56-php-gd,php56-php-mbstring,php56-php-mcrypt,php56-php-xml)

TASK: [php56 path profile check] ********************************************** 
failed: [192.168.33.22] => {"changed": false, "cmd": ["grep", "remi", "/etc/profile"], "delta": "0:00:00.006957", "end": "2016-03-22 17:58:52.800186", "rc": 1, "start": "2016-03-22 17:58:52.793229", "stdout_lines": []}
...ignoring

TASK: [php56 add path] ******************************************************** 
changed: [192.168.33.22]

TASK: [check symbolic link php.ini] ******************************************* 
failed: [192.168.33.22] => {"changed": false, "cmd": "ls /etc/php.ini", "delta": "0:00:00.003978", "end": "2016-03-22 17:58:53.173817", "rc": 2, "start": "2016-03-22 17:58:53.169839", "stdout_lines": []}
stderr: ls: cannot access /etc/php.ini: そのようなファイルやディレクトリはありません
...ignoring

TASK: [create symbolic link php.ini] ****************************************** 
ok: [192.168.33.22]

TASK: [edit php.ini time_zone set Asia Tokyo] ********************************* 
changed: [192.168.33.22]

NOTIFIED: [restart apache] **************************************************** 
changed: [192.168.33.22]

NOTIFIED: [mysql set password] ************************************************ 
changed: [192.168.33.22]

PLAY RECAP ******************************************************************** 
192.168.33.22              : ok=27   changed=16   unreachable=0    failed=0   

もう一度、ansibleを実行してみた結果
[ok]か[skipping]しか出ないようになります。

$ ansible-playbook -i hosts ansible/playbook.yml --private-key /Users/tarai/work/test_centos2/.vagrant/machines/default/virtualbox/private_key

PLAY [web] ******************************************************************** 

GATHERING FACTS *************************************************************** 
ok: [192.168.33.22]

TASK: [check install basepackage] ********************************************* 
ok: [192.168.33.22]

TASK: [Install basepackage] *************************************************** 
skipping: [192.168.33.22]

TASK: [check selinux] ********************************************************* 
ok: [192.168.33.22]

TASK: [SELinux Disable] ******************************************************* 
skipping: [192.168.33.22]

TASK: [check selinux config] ************************************************** 
ok: [192.168.33.22]

TASK: [edit selinux config] *************************************************** 
skipping: [192.168.33.22]

TASK: [stop iptabes] ********************************************************** 
ok: [192.168.33.22]

TASK: [check add repository] ************************************************** 
ok: [192.168.33.22]

TASK: [add repository] ******************************************************** 
skipping: [192.168.33.22]

TASK: [yum install apache] **************************************************** 
ok: [192.168.33.22]

TASK: [apache tuning check] *************************************************** 
ok: [192.168.33.22]

TASK: [apache tuning] ********************************************************* 
skipping: [192.168.33.22]

TASK: [started apache] ******************************************************** 
ok: [192.168.33.22]

TASK: [yum install mysql] ***************************************************** 
ok: [192.168.33.22] => (item={'repo': 'remi', 'name': 'mysql'})
ok: [192.168.33.22] => (item={'repo': 'remi', 'name': 'mysql-server'})
ok: [192.168.33.22] => (item={'repo': 'remi', 'name': 'mysql-devel'})

TASK: [my.cnf edit] *********************************************************** 
ok: [192.168.33.22]

TASK: [started mysqld] ******************************************************** 
ok: [192.168.33.22]

TASK: [started ntpd] ********************************************************** 
ok: [192.168.33.22]

TASK: [check localtime Tokyo] ************************************************* 
ok: [192.168.33.22]

TASK: [localtime Tokyo set] *************************************************** 
skipping: [192.168.33.22]

TASK: [Install php56] ********************************************************* 
ok: [192.168.33.22] => (item=php56-php,php56-php-mysqlnd,php56-php-common,php56-php-devel,php56-php-gd,php56-php-mbstring,php56-php-mcrypt,php56-php-xml)

TASK: [php56 path profile check] ********************************************** 
ok: [192.168.33.22]

TASK: [php56 add path] ******************************************************** 
skipping: [192.168.33.22]

TASK: [check symbolic link php.ini] ******************************************* 
ok: [192.168.33.22]

TASK: [create symbolic link php.ini] ****************************************** 
skipping: [192.168.33.22]

TASK: [edit php.ini time_zone set Asia Tokyo] ********************************* 
ok: [192.168.33.22]

PLAY RECAP ******************************************************************** 
192.168.33.22              : ok=18   changed=0    unreachable=0    failed=0   

これで、LAMP環境が簡単に構築できます!
今回、検証も含め、色々なAnsibleモジュールをバラバラに使用してみましたが、今後は奇麗に統一させようと思います。
0から作成は結構しんどい作業になりましたが、一度しっかりしたものを作っておけば、後々がかなり楽になるかと思います。
イメージなどのバックアップが取れない環境では、環境をソースで管理できるので、再構築がとっても楽になります。

Red Hatが買収した注目のAnsible!
使いこなしましょう!