Minimal インストールの CentOS 6.4 に最新版の ansible をインストールする

ansible の最新版を GitHub から取得してインストールする。
CentOS 6.4 を minimal インストールし、「Minimal インストールの CentOS 6.4 に最新版の git をインストールする」にて git を使用可能にした状態を前提にする。

ansible を使用するには以下の方法があるようで、ここでは make install をやってみる。いろいろ方法があって公式インストール手順もなんか落ち着かない感じ(最後にとってつけたように「make install」ももちろんできるよ、みたいに書かれていたり)。2015年2月13日時点では yum や pip でインストールされるのは 1.8.2 で GitHub 上の最新版は 1.9 になっている。初めて使うなら全ての機能を使いたいし最新版にしておきたい。

  1. yum install ansible でEPELリポジトリ上のRPM版 ansible をインストールする
  2. pip install ansible でインストールする
  3. GitHub からソースを取得してインストールせずに環境変数だけ設定して使用する(./hacking/env-setup)
  4. GitHub からソースを取得して make install でインストールする★今回選択した方法
  5. GitHub からソースを取得して RPM を作成してインストールする

パッケージ追加

ansible の動作用にパッケージを追加する。minimal インストールだと ssh クライアントすら入らないので追加が必要。

openssh-clients
# yum install openssh-clients
# rpm -qa | grep openssh-clients
openssh-clients-5.3p1-104.el6_6.1.x86_64

CentOS 6.4 に標準で含まれる openssh-clients は「openssh-clients-5.3p1-84.1.el6.x86_64」である。理由は以下に記載するが、必ず最新の openssh-clients をインストールする。今回確認したのは「openssh-clients-5.3p1-104.el6_6.1.x86_64」である。すでにインストールされていた場合にも最新版に yum update する。

RHEL6系でansibleを使うならrecord_host_keysをFalseにすると速くなる」の記事を一部引用する。

ansibleは各ホストとの接続にはsshと使います。この時、sshにはControlPersistという機能に対応していることが必要で、opensshならバージョン5.6以上が対象です。ansibleのデフォルトの動作では、PATH上のsshコマンドがControlPersistに対応していればsshを使い、そうでない場合はparamikoというpythonsshライブラリが用いられるようになっています。

RHEL6系のopensshはバージョン5.3の為、何も設定せずに使うとparamikoが用いられます。

RHEL 6(CentOS 6)系の ssh は ControlPersist という機能に対応しておらず、ansible は openssh のPython実装である Paramiko を使用して各サーバと接続することになる。実際に 5.3p1-81.1 のまま ansible を使用すると、確かに Paramiko が使用された。

この Paramiko は性能上のディスアドバンテージがあるようなので、できれば素直に ssh コマンドを使って欲しい。RHEL6系だから自分で最新版の openssh をビルドしなければならないかと思ったが、以下のページの情報によれば対応が 5.3p1-100 あたりで入ったようだ。5.3p1-104 であれば ansible は Paramiko ではなく ssh コマンドを使用してくれた。

sshpass

openssh-clients の最新版(ControlPersist対応)を使用することで、ansible は ssh コマンドを使用するようになるのだが、これだけだと以下のエラーが発生してしまう。

# ansible all -m ping --ask-pass
SSH password: 
127.0.0.1 | FAILED => to use the 'ssh' connection type with passwords, you must install the sshpass program

エラーメッセージの通り、sshpass コマンドを使えるようにする必要がある。この sshpass はEPELリポジトリからインストールできる。

EPELリポジトリを登録するためのRPMをインストールする。リポジトリの情報取得の接続に https を使用するため、nss パッケージを更新しておく。古いバージョンだと「Error: Cannot retrieve metalink for repository: epel. Please verify its path and try again」エラーが発生し、リポジトリにアクセスできない。

# cd /tmp
# yum update nss

# wget http://ftp-srv2.kddilabs.jp/Linux/distributions/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm
# yum localinstall epel-release-6-8.noarch.rpm

sshpass をインストール。

# yum --enablerepo=epel install sshpass
# rpm -qa | grep sshpass
sshpass-1.05-1.el6.x86_64
python-setuptools, python-devel

easy_install と pip を使用可能にするためのパッケージを追加。

# yum install python-setuptools python-devel

pip, Pythonの依存モジュールをインストール

pip を使用可能にする。

# easy_install pip
  (中略)
Installed /usr/lib/python2.6/site-packages/pip-6.0.8-py2.6.egg
Processing dependencies for pip
Finished processing dependencies for pip

ansible が依存するPythonのモジュールをインストールする。

# pip install paramiko PyYAML Jinja2 httplib2
  (中略)
Successfully installed Jinja2-2.7.3 PyYAML-3.11 ecdsa-0.13 httplib2-0.9 markupsafe-0.23 paramiko-1.15.2 pycrypto-2.6.1

ansibleのファイル取得・インストール

GitHub から最新版の ansible を取得する。

# mkdir /persistent/ansible
# cd /persistent/ansible
# git clone git://github.com/ansible/ansible.git --recursive

インストール!

# cd ansible
# make install

動作確認

実行ファイルの配置とバージョンの確認。

# which ansible
/usr/bin/ansible

# which ansible-playbook 
/usr/bin/ansible-playbook

# ansible --version
ansible 1.9
  configured module search path = None

自ホストへの ssh 接続確認。
失敗。ホストキーの確認がでる(known_hostsにない)と sshpass は対応できないらしい。

# cd /tmp

# echo "127.0.0.1" > ansible_hosts
# export ANSIBLE_HOSTS=/tmp/ansible_hosts

# ansible all -m ping --ask-pass
SSH password: (password)
127.0.0.1 | FAILED => Using a SSH password instead of a key is not possible 
because Host Key checking is enabled and sshpass does not support this.  
Please add this host's fingerprint to your known_hosts file to manage this host.

対処方法は5つある。何れも結局は known_hosts にエントリが追加されるだけである。

  1. ssh 127.0.0.1 を実行して自分で known_hosts に登録する
  2. ssh-keyscan でホストキーを known_hosts に登録する
  3. 環境変数 ANSIBLE_SSH_ARGS を使用して ansible が使用する ssh に -o StrictHostKeyChecking=no オプションを渡す
  4. ansible の設定ファイル (/etc/ansible/ansible.cfg) の host_key_checking を false にする
  5. ssh の config で対象ホスト向けの StrictHostKeyChecking を no にする

ssh 127.0.0.1 を使用する場合の操作。

# ssh 127.0.0.1
The authenticity of host '127.0.0.1 (127.0.0.1)' can't be established.
RSA key fingerprint is e5:7a:48:ca:6a:bb:d5:19:ee:4f:01:14:e2:7b:fa:82.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '127.0.0.1' (RSA) to the list of known hosts.
root@127.0.0.1's password: (password)
Last login: Sat Feb 14 14:27:06 2015 from localhost

ssh-keyscan を使用する場合の操作。

# ssh-keyscan 127.0.0.1 >> ~/.ssh/known_hosts

環境変数 ANSIBLE_SSH_ARGS を使用する場合の操作。
ansible が本来設定する ControlPersist の設定などがされなくなるので、known_hosts にエントリを登録したら unset すること。

# export ANSIBLE_SSH_ARGS="-o StrictHostKeyChecking=no"

/etc/ansible/ansible.cfg で host_key_checking を false にする場合の定義。

[defaults]
host_key_checking=false

ssh の config で対象ホスト向けの StrictHostKeyChecking を no にする場合の /root/.ssh/config の定義。

Host 127.0.0.1
  StrictHostKeyChecking no


上記の何れかの対処を行った後に自ホストへの ssh 接続確認。
成功!

# ansible all -m ping --ask-pass
SSH password: (password)
127.0.0.1 | success >> {
    "changed": false, 
    "ping": "pong"
}

/etc/ansible/hosts ファイル作成

動作確認では /tmp/ansible_hosts を作成していたが、毎回指定するのは不便なのでデフォルトで読む /etc/ansible/hosts を作成する。

# mkdir /etc/ansible
# echo "127.0.0.1" >> /etc/ansible/hosts

環境変数 ANSIBLE_HOSTS を指定せずに自ホストへの ssh 接続確認。
成功!

# ansible all -m ping --ask-pass 
SSH password: (password)
127.0.0.1 | success >> {
    "changed": false, 
    "ping": "pong"
}

最後に ping だけでなく uptime などのコマンドも投げてみる。

# ansible all -m command -a "uptime" --ask-pass
SSH password: (password)
127.0.0.1 | success | rc=0 >>
 06:20:20 up 16:27,  2 users,  load average: 0.06, 0.01, 0.00

その他のメモ

ssh コマンドではなく Paramiko を使うことを明示的に指示する場合

-c paramiko をつければよい。

# ansible all -m ping --ask-pass -c paramiko
Paramiko を使用して known_hosts ファイルがない場合

Paramiko で接続すると、ホストキーが known_hosts に登録されていない場合にも対応できる。
ただし、known_hosts ファイル自体がないと 「OSError: [Errno 2] No such file or directory」エラーとなる。
touch でファイルを存在させておけば、yes 回答で素直に登録してくれる。

# ansible all -m ping --ask-pass -c paramiko
SSH password: 

paramiko: The authenticity of host '127.0.0.1' can't be established.
The ssh-rsa key fingerprint is e57a48ca6abbd519ee4f0114e27bfa82.
Are you sure you want to continue connecting (yes/no)?
yes
Traceback (most recent call last):
  File "/usr/lib/python2.6/site-packages/ansible-1.9-py2.6.egg/ansible/runner/connection_plugins/paramiko_ssh.py", line 393, in close
    key_stat = os.stat(self.keyfile)
OSError: [Errno 2] No such file or directory: '/root/.ssh/known_hosts'
127.0.0.1 | success >> {
    "changed": false, 
    "ping": "pong"
}
known_hostsにエントリを追加しないようにする

-o UserKnownHostsFile=/dev/null オプションも追加すればよい。

export ANSIBLE_SSH_ARGS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"

環境変数 ANSIBLE_SSH_ARGS を設定すると、ansible が使用する ControlPersist の設定が入らなくなり、接続が維持されなくなる。
known_hosts にも登録せず、かつ、ControlPersist を使うという場合には自分で ControlPersist の設定を加える。

# CPOPTS="-o ControlPath=~/.ansible/cp/ansible-ssh-%h-%p-%r -o ControlMaster=auto -o ControlPersist=60s"
# export ANSIBLE_SSH_ARGS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null $CPOPTS"