鯖構築運用雑記

管理してる鯖関連とか技術とかの雑記をメモしておく。

Ansible 2.2 on CentOS 5.11 構築のお話

ことの始まり

ちょっとした環境で Ansible を動かしたい衝動に駆られたので、 Ansibleが動くように構築。

すげぇ苦労したし、色々なこと見聞きしました。超感謝。

前半だけ読めば、とりあえず構築はできるはず。
後半は、私が格闘した2日間の成果です。

構築したい環境

Ansible Host side

  • CentOS 5.11 (minimum install)
    • OpenSSL 1.0.1 (Python 2.7 及び Ansible 2.2で必要なため)
    • Python 2.7.12
      • virtualenv
      • Ansible 2.2.1

OpenSSL と Python 2.7 はソースコンパイルでインストールします。

OpenSSLに関しては、yumでインストールできないため、
Python2.7 は、既存Python2.4を汚したくない(別ディレクトリにインストールする)ためです。

検証構築なので、基本rootでの動作確認のみです。一般ユーザの場合はもしかしたら…?

Ansibe Client side

Ansibleはエージェントレスのため、基本的には何も入れなくて済むと思ったのですが、残念ながら…
下の方にも書いてあるので、ご参照ください。

構築手順

CentOS 5.11 に関して

CentOS 5.11 は、netinstall (ftp.riken.jp 経由)で構築済みとし、初回セットアップ時に、

を無効化した状態を用意しました。

インストール後、下記コマンドを実行。どう見ても適当

# yum update
# yum groupinstall "Development tools"

OpenSSL 1.0.2 導入

これを入れないと、Ansible の構築がコケる。
さらに、脆弱性が大量に見つかっているので、なんとかしたほうが良さそうなものの一つ。

Ansible の構築に必要なライブラリが同梱されている、OpenSSL 1.0.2 を、先人の知恵を借りつつ、 ソースから気合と根性で入れる。

linux - Compiling Python 2.7.12 with non-system Openssl on Centos 5 - Stack Overflow

# cd /tmp 
# wget --no-check-certificate https://www.openssl.org/source/openssl-1.0.2k.tar.gz
# tar zxfv openssl-1.0.2k.tar.gz
# cd openssl-1.0.2k
# ./config shared --prefix=/usr/local/ 
# make && make install

導入後、openssl versionでバージョンが上がっていることを確認できます。

# openssl version
OpenSSL 1.0.2k  26 Jan 2017

また、以下の環境変数が構築と、ansible 実行時に必要なので、.bashrc等に追記しておきます。

# echo 'export LDFLAGS="-L/usr/local/lib64/"' >> ~/.bashrc
# echo 'export LD_LIBRARY_PATH="/usr/local/lib64/"' >> ~/.bashrc
# echo 'export CPPFLAGS="-I/usr/local/include -I/usr/local/include/openssl"' >> ~/.bashrc
# source ~/.bashrc

Python 2.7 導入

既存のPythonを汚したくないので、今回はソースからビルドインストールします。

必要なパッケージのインストール

まずは、python のインストールに必要なパッケージをインストール。

# yum install zlib-devel ncurses-devel sqlite-devel openssl-devel tk-devel bzip2-devel gdbm-devel readline-devel gcc python-devel python-setuptools

何が必要で何が不要かはよく分からんが、とりあえず入れておこうという大作戦です。
もしかしたら、いらないのが続発するかもしれません。

python2.7 の準備

ソースを落とす → configure → make && make altinstall といういつもの流れで行きます。

# wget --no-check-certificate https://www.python.org/ftp/python/2.7.12/Python-2.7.12.tar.xz
# xz -dv Python-2.7.12.tar.xz && tar xf Python-2.7.12.tar 
# cd ./Python-2.7.12
# ./configure --prefix=/opt/python2.7 --enable-unicode=ucs4 --enable-shared
# make && make altinstall

最後に、おまじないをかけて、実行できるようにします
(おまじないの訳はコケた所を参照。)

# ln -s /opt/python2.7/lib/libpython2.7.so.1.0 /lib64/

# /opt/python2.7/bin/python2.7 -V
Python 2.7.12

OpenSSL 1.0.2 & python2.7.12 の確認

下記コマンドを実行し、OpenSSLのバージョンが新しいかを確認する。

# /opt/python2.7/bin/python2.7 -c "import ssl; print ssl.OPENSSL_VERSION;"
OpenSSL 1.0.2k  26 Jan 2017

結果が、OpenSSL 0.9.8 等の場合は、OpenSSL の導入がミスってるかも知れないので確認を。

virtualenv導入 & セットアップ

/opt/python2.7/bin/python2.7と入力するのもいいですが、なんやかんや面倒くさいので、virtualenvを導入します。

なお、先人の知恵より、virtualenvは1.10.1以上を導入します。
更に、python2.7 で使用するので、virtualenvの setup.py/opt/python2.7/bin/python2.7 で実行します。

qiita.com

# wget --no-check-certificate http://pypi.python.org/packages/source/v/virtualenv/virtualenv-1.10.1.tar.gz
# tar zvfx virtualenv-1.10.1.tar.gz 
# cd ./virtualenv-1.10.1
# /opt/python2.7/bin/python2.7 setup.py install

すべて完遂すると、--version コマンドで確認できます。

# /opt/python2.7/bin/virtualenv --version
1.10.1

最後に、任意のディレクトリにvirtualenvの初期化とactivateを実行します。

# /opt/python2.7/bin/virtualenv /your/filepath/name --python=/opt/python2.7/bin/python2.7
# cd /your/filepath/name
# source ./bin/activate

(name) # python -V
Python 2.7.12

activateをすると、シェルの前に (name)と表示されます。
無効化は、deactivateコマンドでおkです。

Ansible 導入

ここまでくれば、ほぼ勝ったも同然です。

必要パッケージ導入

この先でコケないために、必要なパッケージを予め入れます。

# yum install epel-release
# yum install pkgconfig libffi-devel

epel-release が嫌な方は、rpmが用意されているみたいなので、そちらからどうぞ。

ansible install from pip

通常通り、pipからansibleを導入します。

# pip install markupsafe six packaging appdirs ansible

その他、コケるものは、エラーログを参考にしつつ、とにかく入れてください。

完走すると、次のように確認が取れるはずです。

# pip freeze
Jinja2==2.8.1
MarkupSafe==1.0
PyYAML==3.12
ansible==2.2.1.0
appdirs==1.4.3
asn1crypto==0.21.1
cffi==1.9.1
cryptography==1.8.1
enum34==1.1.6
idna==2.5
ipaddress==1.0.18
packaging==16.8
paramiko==2.1.2
pyasn1==0.2.3
pycparser==2.17
pycrypto==2.6.1
pyparsing==2.2.0
six==1.10.0
wsgiref==0.1.2

# ansible --version
ansible 2.2.1.0
  config file = 
  configured module search path = Default w/o overrides
  

Ansible 実行

パッケージインストール(ホスト・クライアントともに)

今回は、ホストもクライアントもCentOS5 であるため、先人の知恵により、
下記パッケージをホスト・クライアントともに導入する。(さもなくば動かない)

qiita.com

# yum -y install python-simplejson
# pip install --upgrade setuptools

でないと、ping すら通らない。
(コケた所参照)

pingテスト

まずは、自身に対して

# ansible localhost -m ping
 [WARNING]: Host file not found: /etc/ansible/hosts

 [WARNING]: provided hosts list is empty, only localhost is available

localhost | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}

次に、IP を自身(172.16.1.34)に設定したもの。予め hosts ファイルを用意しておく。

パスワードも毎回聞く形にする。(--ask-pass)

# echo "172.16.1.34" > hosts

# ansible -i hosts 172.16.1.34 -m ping -u root --ask-pass
SSH password: 
172.16.1.34 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}

そして、外にあるCentOS5 に対してping テスト。先ほどと同様にする。

# ansible -i hosts 172.16.1.35 -m ping -u root --ask-pass
SSH password: 
172.16.1.35 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}

コケたところ

pythonを入れたのにライブラリ不足で動かない

# /opt/python2.7/bin/python2.7 -V
/opt/python2.7/bin/python2.7: error while loading shared libraries: libpython2.7.so.1.0: cannot open shared object file: No such file or directory

先人の知恵通りの動作をしたので、この通り対策します。原因は、libpython2.7.so.1.0が読み込めなかっただけです。

# ln -s /opt/python2.7/lib/libpython2.7.so.1.0 /lib64/

# /opt/python2.7/bin/python2.7 -V
Python 2.7.12

Ansible インストールでコケる①

pipが完走しない場合が多発しますが、 エラーログに表示されている不足パッケージをyum ないし pipで導入すればおkです。

例↓

# pip install ansible
Downloading/unpacking ansible

 (中略)

Perhaps you should add the directory containing `libffi.pc'

to the PKG_CONFIG_PATH environment variable

No package 'libffi' found

Package libffi was not found in the pkg-config search path.

(中略)

distutils.errors.DistutilsError: Setup script exited with error: command 'gcc' failed with exit status 1

----------------------------------------
Cleaning up...
Command /root/ansible/bin/python2.7 -c "import setuptools;__file__='/root/ansible/build/cryptography/setup.py';exec(compile(open(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" install --record /tmp/pip-29MwMi-record/install-record.txt --single-version-externally-managed --install-headers /root/ansible/include/site/python2.7 failed with error code 1 in /root/ansible/build/cryptography
Traceback (most recent call last):
  File "/root/ansible/bin/pip", line 9, in <module>
    load_entry_point('pip==1.4.1', 'console_scripts', 'pip')()
  File "/root/ansible/lib/python2.7/site-packages/pip/__init__.py", line 148, in main
    return command.main(args[1:], options)
  File "/root/ansible/lib/python2.7/site-packages/pip/basecommand.py", line 169, in main
    text = '\n'.join(complete_log)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 61: ordinal not in range(128)

上記の場合は、libffiが足りないので、入れてあげましょう。

# yum install epel-release
# yum install libffi-devel

その他、引っかかったって入れたものは次の通り。

  • six
  • packaging
  • appdirs
  • cryptography

事故らないように、最初に入れておくと良さそう。

# pip install six packaging appdirs cryptography

Ansible がコケる②

CentOS 5.11 のデフォルトでインストールされているOpenSSLは、 0.9.8系のため、
最終目標である Ansible で必要な cryptography のインストールでコケる。

# pip install cryptography

(略)

build/temp.linux-x86_64-2.7/_openssl.c:682: error: parameter name omitted

build/temp.linux-x86_64-2.7/_openssl.c:73316: error: expected ‘{’ at end of input

error: command 'gcc' failed with exit status 1

----------------------------------------
Cleaning up...
Command /root/ansible/bin/python2.7 -c "import setuptools;__file__='/root/ansible/build/cryptography/setup.py';exec(compile(open(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" install --record /tmp/pip-4ZVpYs-record/install-record.txt --single-version-externally-managed --install-headers /root/ansible/include/site/python2.7 failed with error code 1 in /root/ansible/build/cryptography
Traceback (most recent call last):
  File "/root/ansible/bin/pip", line 9, in <module>
    load_entry_point('pip==1.4.1', 'console_scripts', 'pip')()
  File "/root/ansible/lib/python2.7/site-packages/pip/__init__.py", line 148, in main
    return command.main(args[1:], options)
  File "/root/ansible/lib/python2.7/site-packages/pip/basecommand.py", line 169, in main
    text = '\n'.join(complete_log)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 84: ordinal not in range(128)

とまあ、完全にopenssl.cがエラーを吐いていたり、
openssl/cms.hがnot found 吐いたりと多彩な場合があるのですが、
原因はおそらく、openssl のバージョンが古いせいです。

なので、OpenSSL 1.0.2のインストールが必須となる。

これを入れると、これまで動いていたアプリが動かなくなる可能性がなきにしもあらずなので、
そのあたりは要検証と自己責任でお願いしたい。

Ansible で CentOS5 に対して実行が飛ばない①

先人の知恵により、下記の症状が出ることは知られている。

# ansible -i hosts 172.16.1.36 -m ping -u root --ask-pass
SSH password: 
172.16.1.36 | FAILED! => {
    "changed": false, 
    "failed": true, 
    "module_stderr": "", 
    "module_stdout": "Traceback (most recent call last):\r\n  File \"/root/.ansible/tmp/ansible-tmp-1489213797.79-3750923784101/ping.py\", line 133, in ?\r\n    exitcode = invoke_module(module, zipped_mod, ANSIBALLZ_PARAMS)\r\n  File \"/root/.ansible/tmp/ansible-tmp-1489213797.79-3750923784101/ping.py\", line 38, in invoke_module\r\n    (stdout, stderr) = p.communicate(json_params)\r\n  File \"/usr/lib64/python2.4/subprocess.py\", line 1050, in communicate\r\n    stdout, stderr = self._communicate_with_poll(input)\r\n  File \"/usr/lib64/python2.4/subprocess.py\", line 1113, in _communicate_with_poll\r\n    input_offset += os.write(fd, chunk)\r\nOSError: [Errno 32] Broken pipe\r\n", 
    "msg": "MODULE FAILURE"
}

解決策は、クライアント側のサーバに、python-simplejsonパッケージをyumで導入すること。

# yum install python-simplejson

(name)# ansible -i hosts 172.16.1.36 -m ping -u root --ask-pass
SSH password: 

paramiko: The authenticity of host '172.16.1.36' can't be established.
The ssh-rsa key fingerprint is 98ac62cd827891c07b412449fc1e6f1a.
Are you sure you want to continue connecting (yes/no)?
yes
172.16.1.36 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}

Ansible で CentOS5にPingが飛ばない②

(name)# ansible -i hosts 172.16.1.36 -m ping -u root --ask-pass
SSH password: 
No handlers could be found for logger "paramiko.transport"
172.16.1.36 | UNREACHABLE! => {
    "changed": false, 
    "msg": "(setuptools 0.9.8 (/root/ansible/lib/python2.7/site-packages), Requirement.parse('setuptools>=11.3'))", 
    "unreachable": true
}

というわけで、setuptoolsが古すぎて動かないそうなので、とにかくupgradeしましょう

github.com

(name) # pip install --upgrade setuptools
(ansible)[root@localhost ansible]# ansible -i hosts 172.16.1.36 -m ping -u root --ask-pass
SSH password: 

paramiko: The authenticity of host '172.16.1.36' can't be established.

172.16.1.36 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}

まとめ

手元の環境では、playbookでファイルの生成(echoしたものの書き出し)が成功した ところまでは確認済みです。

他の何処かで事故るかは未検証なので、その辺りは事故ってからまた修正・検証します。

検証中に新しくコケた部分を見つけたのは内緒。

何かコケても、ログをよく見て対処するなり先人の知恵を拝借するなりしてみてください。