読者です 読者をやめる 読者になる 読者になる

akiyoko blog

akiyoko の IT技術系ブログです

Ansible でさくらのVPS の環境構築を自動化 ~ハマりポイントとともに~

さくらのVPS Ansible

この投稿は Ansible Advent Calendar 2013 の16日目の記事です。


Ansible を使ってみます。2013年は「あ・ん・し・ぼ・ぉ」と読むのが流行りのようですね。

これまで、さくらのVPSを使って環境構築のテストとかしていたのですが、何度も初期設定をするのが面倒だったので Chef か何かに手を出そうと思ってたのですが、Ansible は Python製ということを聞きつけ、何か惹かれるものを感じたのでトライしてみることにしました。

さくらのVPS (CentOS 6.5) の環境構築手順は、「さくらのVPS (CentOS 6.5) にLAMP環境を構築」にまとめてあります。今回は、その手順をそのまま Ansible の playbook で実現しようと思います。

Ansible初心者ということもあり、今回かなりハマったので、ハマりポイントを最後にまとめておきました。ちなみに、Ansible 歴は2ヶ月程度です。


やりたいこと

  • Mac に Ansible をインストールする
  • さくらのVPSの環境構築を自動化する

環境

  • Mac X OS 10.9
  • Ansible 1.3.4

 

0. さくらのVPSの初期化

さくらインターネットVPSコントロールパネルから、「OS再インストール」をしておきます。
(もちろん契約した直後の状態でも大丈夫です。)

再インストールが完了したら、まず、

$ ssh root@49.xx.xx.xx

で、SSHパスワードを入れると、SSHできることを確認します。

 

1. Ansible のインストール

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

$ sudo easy_install pip
Searching for pip
 ・
 ・
Adding pip 1.4.1 to easy-install.pth file
Installing pip script to /usr/local/bin
Installing pip-2.7 script to /usr/local/bin

Installed /Library/Python/2.7/site-packages/pip-1.4.1-py2.7.egg
Processing dependencies for pip
Finished processing dependencies for pip


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

$ sudo pip install ansible
Downloading/unpacking ansible
 ・
 ・
Successfully installed ansible paramiko jinja2 PyYAML pycrypto ecdsa markupsafe
Cleaning up...

1.3.3 がインストールされました。

$ sudo pip install -U ansible
 ・
 ・
Successfully installed ansible
Cleaning up...

アップデートしたら、1.3.4 になりました。

 

2. さくらのVPSの環境構築を自動化

さくらのVPS (CentOS 6.5) にLAMP環境を構築」の手順から、

  • rootユーザでの設定
    1. rootパスワードを変更 (12/17追記)自動化の対象から外しました。
    2. SSHポート番号を変更
    3. iptablesを設定
    4. 作業用ユーザを作成
  • パスワード認証からSSH鍵認証への切り替え
    1. rootによるログイン、パスワードでのログインを禁止
  • Apache, MySQL, PHPインストール
    1. yumをアップデート
    2. remi, RPMForge, Fedora EPELリポジトリの追加
    3. Apache, MySQL, PHPをインストール

までを自動化します。
続きは・・・力尽きました。またの機会ということで。。

ソースコード

hosts

[sakura_root]
49.xx.xx.xx

[sakura]
sakura:10022

iptables.j2

*filter
:INPUT   ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT  ACCEPT [0:0]
:RH-Firewall-1-INPUT - [0:0]

-A INPUT -j RH-Firewall-1-INPUT
-A FORWARD -j RH-Firewall-1-INPUT
-A RH-Firewall-1-INPUT -i lo -j ACCEPT
-A RH-Firewall-1-INPUT -p icmp --icmp-type any -j ACCEPT
-A RH-Firewall-1-INPUT -p 50 -j ACCEPT
-A RH-Firewall-1-INPUT -p 51 -j ACCEPT
-A RH-Firewall-1-INPUT -p udp --dport 5353 -d 224.0.0.251 -j ACCEPT
-A RH-Firewall-1-INPUT -p udp -m udp --dport 631 -j ACCEPT
-A RH-Firewall-1-INPUT -p tcp -m tcp --dport 631 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# add start
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport {{ ssh_port }} -j ACCEPT
# add end

-A RH-Firewall-1-INPUT -j REJECT --reject-with icmp-host-prohibited

COMMIT

sakura_root.yml

- name: setting SakuraServer VPS by root
  hosts: sakura_root
  user: root
  vars:
    user_name: admin
    # NOTE: Password must be hashed. this is created with:
    # openssl passwd -salt salty -1 mypass
    user_password: $1$salty$WoG5tu8Y63f.rmnpDr9lz0
    ssh_port: 10022

  tasks:
    - name: change SSH port
      lineinfile: dest=/etc/ssh/sshd_config regexp="^#Port " line="Port {{ ssh_port }}" state=present

    - name: create iptables
      template: src=iptables.j2 dest=/etc/sysconfig/iptables

    - name: create user
      user: name={{ user_name }} password={{ user_password }} groups=wheel

    - name: allow wheel users to sudo
      # NOTE: Because of the ': ' on the line, fully quote or use {{':'}}.
      lineinfile: dest=/etc/sudoers regexp="^#\s*(%wheel\s+ALL=\(ALL\)\s+NOPASSWD{{':'}}\s+ALL)" line="\1" backrefs=yes state=present

    # NOTE: Combine two tasks to keep ansible access with port 22
    - name: restart sshd and restart iptables
      shell: service sshd restart && /etc/init.d/iptables restart

sakura_lamp.yml

- name: setting LAMP to SakuraServer VPS
  hosts: sakura
  user: admin
  sudo: yes
  vars:
    httpd_port: 80
    mysql_port: 3306

  tasks:
    - name: disallow root SSH access
      lineinfile: dest=/etc/ssh/sshd_config regexp="^#PermitRootLogin " line="PermitRootLogin no" state=present
      notify: restart sshd
    - name: disallow password authentication
      lineinfile: dest=/etc/ssh/sshd_config regexp="^#PasswordAuthentication " line="PasswordAuthentication no" state=present
      notify: restart sshd

    - name: update yum
      command: yum -y update

    # repository
    - name: add repository 'rpmforge-repo'
      yum: name=http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm state=present
    - name: add repository 'remi-repo'
      yum: name=http://rpms.famillecollet.com/enterprise/remi-release-6.rpm state=present

    # Apache
    - name: install apache
      yum: name=httpd enablerepo=remi,epel,rpmforge state=present
    - name: start httpd
      service: name=httpd state=started enabled=yes
    - name: add iptables rule for httpd
      lineinfile: dest=/etc/sysconfig/iptables regexp="{{ httpd_port }}" line="-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport {{ httpd_port }} -j ACCEPT" insertbefore="^# add end" state=present
      notify: restart iptables
    # PHP
    - name: install php
      yum: name={{ item }} enablerepo=remi,epel,rpmforge state=present
      with_items:
        - php
    # MySQL
    - name: install mysql
      yum: name=mysql-server enablerepo=remi,epel,rpmforge state=present
    - name: add iptables rule for mysql
      lineinfile: dest=/etc/sysconfig/iptables regexp="{{ mysql_port }}" line="-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport {{ mysql_port }} -j ACCEPT" insertbefore="^# add end" state=present
      notify: restart iptables

  handlers:
    - name: restart sshd
      service: name=sshd state=restarted

    - name: restart iptables
      service: name=iptables state=restarted

https://github.com/akiyoko/ansible-sakura
にもアップしておきました。

使い方

rootユーザでアクセスする部分(sakura_root.yml)と、ローカルからSSH公開鍵をサーバに登録する部分、作業用ユーザでアクセスする(※SSHに10022番ポートを使う)部分(sakura_lamp.yml)の3つに処理を分けています。


まずは、hostsファイルのIPアドレスを実際のものに修正してください。
(「49.xx.xx.xx」は、私が使ってるVPSサーバのIPアドレスを表しています。)

[sakura_root]
49.xx.xx.xx


sakura_root.yml を実行

$ user_password=$(openssl passwd -salt salty -1 <user password>)
$ ansible-playbook -k -c paramiko -i hosts sakura_root.yml -vv --extra-vars "user_password=$user_password"


adminで SSHログインできることを確認します。

$ ssh -p 10022 admin@49.xx.xx.xx


SSH鍵ペアを作成し、公開鍵をサーバ(さくらのVPS)に登録します。
パスフレーズ無し、鍵ファイル名は「sakura_rsa」とします。

$ ssh-keygen

$ ssh-copy-id -i ~/.ssh/sakura_rsa.pub "-p 10022 admin@49.xx.xx.xx"

$ cat <<EOF >> ~/.ssh/config
Host sakura
  Hostname 49.xx.xx.xx
  Port 10022
  User admin
  IdentityFile ~/.ssh/sakura_rsa
EOF

 

$ ssh sakura

で、VPSにパスワードなしでログインできることを確認します。


sakura_lamp.yml を実行

$ ansible-playbook sakura_lamp.yml -i hosts -vv

 

実行結果

$ user_password=$(openssl passwd -salt salty -1 mypass)
$ ansible-playbook -k -c paramiko -i hosts sakura_root.yml -vv --extra-vars "user_password=$user_password"
SSH password:

PLAY [setting SakuraServer VPS by root] ******************************************

GATHERING FACTS ***************************************************************
<49.xx.xx.xx> REMOTE_MODULE setup
ok: [49.xx.xx.xx]

TASK: [change SSH port] *******************************************************
<49.xx.xx.xx> REMOTE_MODULE lineinfile dest=/etc/ssh/sshd_config regexp="^#Port " line="Port 10022" state=present
changed: [49.xx.xx.xx] => {"changed": true, "msg": "line replaced"}

TASK: [create iptables] *******************************************************
changed: [49.xx.xx.xx] => {"changed": true, "dest": "/etc/sysconfig/iptables", "gid": 0, "group": "root", "md5sum": "6cdbbb0a154e5bf2833cd2c176eea895", "mode": "0644", "owner": "root", "size": 782, "src": "/root/.ansible/tmp/ansible-1387120673.34-191537218210939/source", "state": "file", "uid": 0}

TASK: [create user] ***********************************************************
<49.xx.xx.xx> REMOTE_MODULE user name=admin password=$1$salty$WoG5tu8Y63f.rmnpDr9lz0 groups=wheel
changed: [49.xx.xx.xx] => {"changed": true, "comment": "", "createhome": true, "group": 500, "groups": "wheel", "home": "/home/admin", "name": "admin", "password": "NOT_LOGGING_PASSWORD", "shell": "/bin/bash", "state": "present", "system": false, "uid": 500}

TASK: [allow wheel users to sudo] *********************************************
<49.xx.xx.xx> REMOTE_MODULE lineinfile dest=/etc/sudoers regexp="^#\s*(%wheel\s+ALL=\(ALL\)\s+NOPASSWD:\s+ALL)" line="\1" backrefs=yes state=present
changed: [49.xx.xx.xx] => {"changed": true, "msg": "line replaced"}

TASK: [restart sshd and restart iptables] *************************************
<49.xx.xx.xx> REMOTE_MODULE command service sshd restart && /etc/init.d/iptables restart #USE_SHELL
changed: [49.xx.xx.xx] => {"changed": true, "cmd": "service sshd restart && /etc/init.d/iptables restart ", "delta": "0:00:00.857809", "end": "2013-12-16 00:17:58.678128", "rc": 0, "start": "2013-12-16 00:17:57.820319", "stderr": "", "stdout": "Stopping sshd: [  OK  ]\r\nStarting sshd: [  OK  ]\r\niptables: Applying firewall rules: [  OK  ]"}

PLAY RECAP ********************************************************************
49.xx.xx.xx              : ok=6    changed=5    unreachable=0    failed=0
$ ansible-playbook sakura_lamp.yml -i hosts -vv

PLAY [setting LAMP to SakuraServer VPS] ***************************************

GATHERING FACTS ***************************************************************
<sakura> REMOTE_MODULE setup
ok: [sakura]

TASK: [disallow root SSH access] **********************************************
<sakura> REMOTE_MODULE lineinfile dest=/etc/ssh/sshd_config regexp="^#PermitRootLogin " line="PermitRootLogin no" state=present
changed: [sakura] => {"changed": true, "msg": "line replaced"}

TASK: [disallow password authentication] **************************************
<sakura> REMOTE_MODULE lineinfile dest=/etc/ssh/sshd_config regexp="^#PasswordAuthentication " line="PasswordAuthentication no" state=present
changed: [sakura] => {"changed": true, "msg": "line replaced"}

TASK: [update yum] ************************************************************
<sakura> REMOTE_MODULE command yum -y update
changed: [sakura] => {"changed": true, "cmd": ["yum", "-y", "update"], "delta": "0:00:05.173769", "end": "2013-12-16 21:18:19.885024", "rc": 0, "start": "2013-12-16 21:18:14.711255", "stderr": "http://ftp.kddilabs.jp/Linux/packages/fedora/epel/6/x86_64/repodata/repomd.xml: [Errno -1] repomd.xml does not match metalink for epel\nTrying other mirror.", "stdout": "Loaded plugins: fastestmirror, security\nLoading mirror speeds from cached hostfile\n * base: ftp.nara.wide.ad.jp\n * epel: ftp.kddilabs.jp\n * extras: ftp.nara.wide.ad.jp\n * updates: ftp.jaist.ac.jp\nSetting up Update Process\nNo Packages marked for Update"}

TASK: [add repository 'rpmforge-repo'] ****************************************
<sakura> REMOTE_MODULE yum name=http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm state=present
changed: [sakura] => {"changed": true, "msg": "", "rc": 0, "results": ["Loaded plugins: fastestmirror, security\nLoading mirror speeds from cached hostfile\n * base: ftp.nara.wide.ad.jp\n * epel: ftp.kddilabs.jp\n * extras: ftp.nara.wide.ad.jp\n * updates: ftp.jaist.ac.jp\nSetting up Install Process\nExamining /var/tmp/yum-root-ezGIv2/rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm: rpmforge-release-0.5.3-1.el6.rf.x86_64\nMarking /var/tmp/yum-root-ezGIv2/rpmforge-release-0.5.3-1.el6.rf.x86_64.rpm to be installed\nResolving Dependencies\n--> Running transaction check\n---> Package rpmforge-release.x86_64 0:0.5.3-1.el6.rf will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package    Arch   Version        Repository                               Size\n================================================================================\nInstalling:\n rpmforge-release\n            x86_64 0.5.3-1.el6.rf /rpmforge-release-0.5.3-1.el6.rf.x86_64  13 k\n\nTransaction Summary\n================================================================================\nInstall       1 Package(s)\n\nTotal size: 13 k\nInstalled size: 13 k\nDownloading Packages:\nRunning rpm_check_debug\nRunning Transaction Test\nTransaction Test Succeeded\nRunning Transaction\n\r  Installing : rpmforge-release-0.5.3-1.el6.rf.x86_64                       1/1 \n\r  Verifying  : rpmforge-release-0.5.3-1.el6.rf.x86_64                       1/1 \n\nInstalled:\n  rpmforge-release.x86_64 0:0.5.3-1.el6.rf                                      \n\nComplete!\n"]}

TASK: [add repository 'remi-repo'] ********************************************
<sakura> REMOTE_MODULE yum name=http://rpms.famillecollet.com/enterprise/remi-release-6.rpm state=present
changed: [sakura] => {"changed": true, "msg": "", "rc": 0, "results": ["Loaded plugins: fastestmirror, security\nLoading mirror speeds from cached hostfile\n * base: ftp.nara.wide.ad.jp\n * epel: ftp.kddilabs.jp\n * extras: ftp.nara.wide.ad.jp\n * rpmforge: ftp.kddilabs.jp\n * updates: ftp.jaist.ac.jp\nSetting up Install Process\nExamining /var/tmp/yum-root-ezGIv2/remi-release-6.rpm: remi-release-6.4-1.el6.remi.noarch\nMarking /var/tmp/yum-root-ezGIv2/remi-release-6.rpm to be installed\nResolving Dependencies\n--> Running transaction check\n---> Package remi-release.noarch 0:6.4-1.el6.remi will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package           Arch        Version               Repository            Size\n================================================================================\nInstalling:\n remi-release      noarch      6.4-1.el6.remi        /remi-release-6      3.0 k\n\nTransaction Summary\n================================================================================\nInstall       1 Package(s)\n\nTotal size: 3.0 k\nInstalled size: 3.0 k\nDownloading Packages:\nRunning rpm_check_debug\nRunning Transaction Test\nTransaction Test Succeeded\nRunning Transaction\n\r  Installing : remi-release-6.4-1.el6.remi.noarch                           1/1 \n\r  Verifying  : remi-release-6.4-1.el6.remi.noarch                           1/1 \n\nInstalled:\n  remi-release.noarch 0:6.4-1.el6.remi                                          \n\nComplete!\n"]}

TASK: [install apache] ********************************************************
<sakura> REMOTE_MODULE yum name=httpd enablerepo=remi,epel,rpmforge state=present
changed: [sakura] => {"changed": true, "msg": "", "rc": 0, "results": ["Loaded plugins: fastestmirror, security\nLoading mirror speeds from cached hostfile\n * base: ftp.nara.wide.ad.jp\n * epel: ftp.kddilabs.jp\n * extras: ftp.nara.wide.ad.jp\n * remi: remi.kazukioishi.net\n * rpmforge: ftp.kddilabs.jp\n * updates: ftp.jaist.ac.jp\nSetting up Install Process\nResolving Dependencies\n--> Running transaction check\n---> Package httpd.x86_64 0:2.2.15-29.el6.centos will be installed\n--> Processing Dependency: httpd-tools = 2.2.15-29.el6.centos for package: httpd-2.2.15-29.el6.centos.x86_64\n--> Processing Dependency: apr-util-ldap for package: httpd-2.2.15-29.el6.centos.x86_64\n--> Running transaction check\n---> Package apr-util-ldap.x86_64 0:1.3.9-3.el6_0.1 will be installed\n---> Package httpd-tools.x86_64 0:2.2.15-29.el6.centos will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package             Arch         Version                      Repository  Size\n================================================================================\nInstalling:\n httpd               x86_64       2.2.15-29.el6.centos         base       821 k\nInstalling for dependencies:\n apr-util-ldap       x86_64       1.3.9-3.el6_0.1              base        15 k\n httpd-tools         x86_64       2.2.15-29.el6.centos         base        73 k\n\nTransaction Summary\n================================================================================\nInstall       3 Package(s)\n\nTotal download size: 909 k\nInstalled size: 3.1 M\nDownloading Packages:\n--------------------------------------------------------------------------------\nTotal                                            14 MB/s | 909 kB     00:00     \nRunning rpm_check_debug\nRunning Transaction Test\nTransaction Test Succeeded\nRunning Transaction\n\r  Installing : apr-util-ldap-1.3.9-3.el6_0.1.x86_64                         1/3 \n\r  Installing : httpd-tools-2.2.15-29.el6.centos.x86_64                      2/3 \n\r  Installing : httpd-2.2.15-29.el6.centos.x86_64                            3/3 \n\r  Verifying  : httpd-2.2.15-29.el6.centos.x86_64                            1/3 \n\r  Verifying  : httpd-tools-2.2.15-29.el6.centos.x86_64                      2/3 \n\r  Verifying  : apr-util-ldap-1.3.9-3.el6_0.1.x86_64                         3/3 \n\nInstalled:\n  httpd.x86_64 0:2.2.15-29.el6.centos                                           \n\nDependency Installed:\n  apr-util-ldap.x86_64 0:1.3.9-3.el6_0.1                                        \n  httpd-tools.x86_64 0:2.2.15-29.el6.centos                                     \n\nComplete!\n"]}

TASK: [start httpd] ***********************************************************
<sakura> REMOTE_MODULE service name=httpd state=started enabled=yes
changed: [sakura] => {"changed": true, "enabled": true, "name": "httpd", "state": "started"}

TASK: [add iptables rule for httpd] *******************************************
<sakura> REMOTE_MODULE lineinfile dest=/etc/sysconfig/iptables regexp="80" line="-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT" insertbefore="^# add end" state=present
changed: [sakura] => {"changed": true, "msg": "line added"}

TASK: [install php] ***********************************************************
<sakura> REMOTE_MODULE yum name=php enablerepo=remi,epel,rpmforge state=present
changed: [sakura] => (item=php) => {"changed": true, "item": "php", "msg": "warning: rpmts_HdrFromFdno: Header V3 DSA/SHA1 Signature, key ID 00f97f56: NOKEY\nImporting GPG key 0x00F97F56:\n Userid : Remi Collet <RPMS@FamilleCollet.com>\n Package: remi-release-6.4-1.el6.remi.noarch (@/remi-release-6)\n From   : /etc/pki/rpm-gpg/RPM-GPG-KEY-remi\n", "rc": 0, "results": ["Loaded plugins: fastestmirror, security\nLoading mirror speeds from cached hostfile\n * base: ftp.nara.wide.ad.jp\n * epel: ftp.kddilabs.jp\n * extras: ftp.nara.wide.ad.jp\n * remi: remi.kazukioishi.net\n * rpmforge: ftp.kddilabs.jp\n * updates: ftp.jaist.ac.jp\nSetting up Install Process\nResolving Dependencies\n--> Running transaction check\n---> Package php.x86_64 0:5.4.23-1.el6.remi will be installed\n--> Processing Dependency: php-common(x86-64) = 5.4.23-1.el6.remi for package: php-5.4.23-1.el6.remi.x86_64\n--> Processing Dependency: php-cli(x86-64) = 5.4.23-1.el6.remi for package: php-5.4.23-1.el6.remi.x86_64\n--> Running transaction check\n---> Package php-cli.x86_64 0:5.4.23-1.el6.remi will be installed\n---> Package php-common.x86_64 0:5.4.23-1.el6.remi will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package            Arch           Version                   Repository    Size\n================================================================================\nInstalling:\n php                x86_64         5.4.23-1.el6.remi         remi         2.7 M\nInstalling for dependencies:\n php-cli            x86_64         5.4.23-1.el6.remi         remi         2.6 M\n php-common         x86_64         5.4.23-1.el6.remi         remi         927 k\n\nTransaction Summary\n================================================================================\nInstall       3 Package(s)\n\nTotal download size: 6.2 M\nInstalled size: 24 M\nDownloading Packages:\n--------------------------------------------------------------------------------\nTotal                                            11 MB/s | 6.2 MB     00:00     \nRetrieving key from file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi\nRunning rpm_check_debug\nRunning Transaction Test\nTransaction Test Succeeded\nRunning Transaction\n\r  Installing : php-common-5.4.23-1.el6.remi.x86_64                          1/3 \n\nWARNING : These php-* RPM are not official Fedora / Red Hat build and\noverrides the official ones. Don't file bugs on Fedora Project nor Red Hat.\n\nUse dedicated forums http://forums.famillecollet.com/\n\n\r  Installing : php-cli-5.4.23-1.el6.remi.x86_64                             2/3 \n\r  Installing : php-5.4.23-1.el6.remi.x86_64                                 3/3 \n\r  Verifying  : php-common-5.4.23-1.el6.remi.x86_64                          1/3 \n\r  Verifying  : php-cli-5.4.23-1.el6.remi.x86_64                             2/3 \n\r  Verifying  : php-5.4.23-1.el6.remi.x86_64                                 3/3 \n\nInstalled:\n  php.x86_64 0:5.4.23-1.el6.remi                                                \n\nDependency Installed:\n  php-cli.x86_64 0:5.4.23-1.el6.remi    php-common.x86_64 0:5.4.23-1.el6.remi   \n\nComplete!\n"]}

TASK: [install mysql] *********************************************************
<sakura> REMOTE_MODULE yum name=mysql-server enablerepo=remi,epel,rpmforge state=present
changed: [sakura] => {"changed": true, "msg": "", "rc": 0, "results": ["Loaded plugins: fastestmirror, security\nLoading mirror speeds from cached hostfile\n * base: ftp.nara.wide.ad.jp\n * epel: ftp.kddilabs.jp\n * extras: ftp.nara.wide.ad.jp\n * remi: remi.kazukioishi.net\n * rpmforge: ftp.kddilabs.jp\n * updates: ftp.jaist.ac.jp\nSetting up Install Process\nResolving Dependencies\n--> Running transaction check\n---> Package mysql-server.x86_64 0:5.5.35-1.el6.remi will be installed\n--> Processing Dependency: real-mysql-libs(x86-64) = 5.5.35-1.el6.remi for package: mysql-server-5.5.35-1.el6.remi.x86_64\n--> Processing Dependency: real-mysql(x86-64) = 5.5.35-1.el6.remi for package: mysql-server-5.5.35-1.el6.remi.x86_64\n--> Processing Dependency: perl-DBI for package: mysql-server-5.5.35-1.el6.remi.x86_64\n--> Processing Dependency: perl-DBD-MySQL for package: mysql-server-5.5.35-1.el6.remi.x86_64\n--> Processing Dependency: perl(DBI) for package: mysql-server-5.5.35-1.el6.remi.x86_64\n--> Running transaction check\n---> Package mysql.x86_64 0:5.5.35-1.el6.remi will be installed\n---> Package mysql-libs.x86_64 0:5.1.71-1.el6 will be updated\n--> Processing Dependency: libmysqlclient.so.16()(64bit) for package: 2:postfix-2.6.6-2.2.el6_1.x86_64\n--> Processing Dependency: libmysqlclient.so.16()(64bit) for package: perl-DBD-MySQL-4.013-3.el6.x86_64\n--> Processing Dependency: libmysqlclient.so.16(libmysqlclient_16)(64bit) for package: 2:postfix-2.6.6-2.2.el6_1.x86_64\n--> Processing Dependency: libmysqlclient.so.16(libmysqlclient_16)(64bit) for package: perl-DBD-MySQL-4.013-3.el6.x86_64\n---> Package mysql-libs.x86_64 0:5.5.35-1.el6.remi will be an update\n---> Package perl-DBD-MySQL.x86_64 0:4.013-3.el6 will be installed\n---> Package perl-DBI.x86_64 0:1.609-4.el6 will be installed\n--> Running transaction check\n---> Package compat-mysql51.x86_64 0:5.1.54-1.el6.remi will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package               Arch          Version                  Repository   Size\n================================================================================\nInstalling:\n mysql-server          x86_64        5.5.35-1.el6.remi        remi         10 M\nInstalling for dependencies:\n compat-mysql51        x86_64        5.1.54-1.el6.remi        remi        1.4 M\n mysql                 x86_64        5.5.35-1.el6.remi        remi        5.8 M\n perl-DBD-MySQL        x86_64        4.013-3.el6              base        134 k\n perl-DBI              x86_64        1.609-4.el6              base        705 k\nUpdating for dependencies:\n mysql-libs            x86_64        5.5.35-1.el6.remi        remi        775 k\n\nTransaction Summary\n================================================================================\nInstall       5 Package(s)\nUpgrade       1 Package(s)\n\nTotal download size: 19 M\nDownloading Packages:\n--------------------------------------------------------------------------------\nTotal                                            14 MB/s |  19 MB     00:01     \nRunning rpm_check_debug\nRunning Transaction Test\nTransaction Test Succeeded\nRunning Transaction\n\r  Installing : perl-DBI-1.609-4.el6.x86_64                                  1/7 \n\r  Updating   : mysql-libs-5.5.35-1.el6.remi.x86_64                          2/7 \n\nWARNING : This MySQL RPM is not an official Fedora / Red Hat build and it\noverrides the official one. Don't file bugs on Fedora Project nor Red Hat.\nUse dedicated forums http://forums.famillecollet.com/\n\n\r  Installing : mysql-5.5.35-1.el6.remi.x86_64                               3/7 \n\r  Installing : compat-mysql51-5.1.54-1.el6.remi.x86_64                      4/7 \n\r  Installing : perl-DBD-MySQL-4.013-3.el6.x86_64                            5/7 \n\r  Installing : mysql-server-5.5.35-1.el6.remi.x86_64                        6/7 \n\r  Cleanup    : mysql-libs-5.1.71-1.el6.x86_64                               7/7 \n\r  Verifying  : mysql-server-5.5.35-1.el6.remi.x86_64                        1/7 \n\r  Verifying  : compat-mysql51-5.1.54-1.el6.remi.x86_64                      2/7 \n\r  Verifying  : perl-DBD-MySQL-4.013-3.el6.x86_64                            3/7 \n\r  Verifying  : mysql-5.5.35-1.el6.remi.x86_64                               4/7 \n\r  Verifying  : mysql-libs-5.5.35-1.el6.remi.x86_64                          5/7 \n\r  Verifying  : perl-DBI-1.609-4.el6.x86_64                                  6/7 \n\r  Verifying  : mysql-libs-5.1.71-1.el6.x86_64                               7/7 \n\nInstalled:\n  mysql-server.x86_64 0:5.5.35-1.el6.remi                                       \n\nDependency Installed:\n  compat-mysql51.x86_64 0:5.1.54-1.el6.remi   mysql.x86_64 0:5.5.35-1.el6.remi  \n  perl-DBD-MySQL.x86_64 0:4.013-3.el6         perl-DBI.x86_64 0:1.609-4.el6     \n\nDependency Updated:\n  mysql-libs.x86_64 0:5.5.35-1.el6.remi                                         \n\nComplete!\n"]}

TASK: [add iptables rule for mysql] *******************************************
<sakura> REMOTE_MODULE lineinfile dest=/etc/sysconfig/iptables regexp="3306" line="-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT" insertbefore="^# add end" state=present
changed: [sakura] => {"changed": true, "msg": "line added"}

NOTIFIED: [restart sshd] ******************************************************
<sakura> REMOTE_MODULE service name=sshd state=restarted
changed: [sakura] => {"changed": true, "name": "sshd", "state": "started"}

NOTIFIED: [restart iptables] **************************************************
<sakura> REMOTE_MODULE service name=iptables state=restarted
changed: [sakura] => {"changed": true, "name": "iptables", "state": "started"}

PLAY RECAP ********************************************************************
sakura                     : ok=14   changed=13   unreachable=0    failed=0


インストールされたバージョンはこんな感じになりました。(日によって変わるので、冪等性は無視しちゃってますね。。)

$ httpd -v
Server version: Apache/2.2.15 (Unix)
Server built:   Aug 13 2013 17:29:28
$ php -v
PHP 5.4.23 (cli) (built: Dec 11 2013 06:48:07) 
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2013 Zend Technologies
$ mysql --version
mysql  Ver 14.14 Distrib 5.5.35, for Linux (x86_64) using readline 5.1

$ yum list installed | grep httpd
httpd.x86_64            2.2.15-29.el6.centos
httpd-tools.x86_64      2.2.15-29.el6.centos
$ yum list installed | grep php
php.x86_64              5.4.23-1.el6.remi
php-cli.x86_64          5.4.23-1.el6.remi
php-common.x86_64       5.4.23-1.el6.remi
$ yum list installed | grep mysql-server
mysql-server.x86_64     5.5.35-1.el6.remi


 

ハマったポイントを解説

正直、だいぶハマりました。

1) パスワードによるSSH接続ができない

以下のように playbook を実行しようとすると、パスワード認証を使うには「sshpass」をインストールしてね、というエラーになりました。

$ ansible-playbook -k -i hosts sakura_root.yml -vv
SSH password: 

PLAY [setting sakura server by root] ****************************************** 

GATHERING FACTS *************************************************************** 
fatal: [49.xx.xx.xx] => to use the 'ssh' connection type with passwords, you must install the sshpass program

http://lalyos.github.io/blog/2013/09/30/install-sshpass-on-mac/
という記事があったのですが、brew 入れてないので保留。。

結局、
https://github.com/ansible/ansible/issues/3564
を参考に、「-c paramiko」を付けたら上手くいくようになりました。

2) ユーザ作成時のパスワードは暗号化必須

これに気付かず、

  tasks:
    - name: create user
      user: name=admin password=mypass groups=wheel

などとしていたら、パスワードが「mypass」で設定されずに admin でログインできないという事態に陥りました。

$ openssl passwd -salt salty -1 <root new password>

としてパスワードを暗号化して、userモジュールのpasswordパラメータに渡さないといけません。

参考

3) lineinfile モジュール使用時のセミコロン「:」対応

ファイルの置換時、「:」が入っている場合にはダブルクォーテーションで全体をくくるか、セミコロンを {{':'}} で表記しなければいけません。
https://github.com/ansible/ansible/issues/1341

あとは、lineinfileのregexpでは、「(」「)」には「\」でエスケープするのもハマりポイントかもしれません(「¥」だとダメ)。

4) SSHのポート番号を変えるときは注意

Ansibleは(おそらく)taskごとに 指定のポート番号でサーバにアクセスするので、途中でポート番号を変更したり iptabls でポートを限定したりすると(厳密には sshd や iptables を再起動した以降のタイミングで)サーバにSSH接続できなくなり、以降の task が実行できなってしまいます。

具体的には、

  tasks:
    - name: change SSH port
      lineinfile: dest=/etc/ssh/sshd_config regexp="^#Port " line="Port {{ ssh_port }}" state=present
      notify: restart sshd

    - name: create iptables
      template: src=iptables.j2 dest=/etc/sysconfig/iptables
      notify: restart iptables

  handlers:
    - name: restart sshd
      service: name=sshd state=restarted

    - name: restart iptables
      service: name=iptables state=restarted

としていると、

NOTIFIED: [restart sshd] ****************************************************** 
<49.xx.xx.xx> REMOTE_MODULE service name=sshd state=restarted
changed: [49.xx.xx.xx] => {"changed": true, "name": "sshd", "state": "started"}

NOTIFIED: [restart iptables] ************************************************** 
fatal: [49.xx.xx.xx] => {'msg': 'FAILED: [Errno 61] Connection refused', 'failed': True}

で止まってしまいました。

対策としては、ソースコードを見ていただければわかるように、

    # NOTE: Combine two tasks to keep ansible access with port 22
    - name: restart sshd and restart iptables
      shell: service sshd restart && /etc/init.d/iptables restart

という処理を task として一番最後に実行することで解決しました。

5) SSHのポート番号を変えた後のアクセス

Ansibleは ~/.ssh/config のポート設定を読んでくれないらしいので、SSHのポート番号を変えた場合は「ansible_ssh_port」で指定するか、

[sakura]
sakura:10022

or

sakura ansible_ssh_port=10022

という感じで、ポートの指定を hosts ファイルに設定しておく必要があります。


(12/17追記)

6) パスワード認証でSSH接続しているユーザのパスワードを変更する

sakura_root.yaml の冒頭で、rootユーザのパスワードを変更しようと、

    - name: change root password
      user: name=root password={{ root_password }}

という処理をしてたのですが、rootでSSH接続しているので、途中でパスワード変えると、それ以降 SSHできないという罠にハマりました。当たり前と言えば当たり前ですね。。 4)と同じく、task ごとに SSH接続をし直しているのですね。


 

まとめ

Ansibleを使って CentOS 6.5 の環境構築をしましたが、一度 playbook を作ってしまえば、後は何度でも環境構築をやり直すことができます。
環境を潰しては入れ直すことが多いので、特に、初期設定を自動化できるのは、非常に助かります。
皆さんも、是非試してみてください。


参考