構成管理ツール (いわゆる Infrastructure as Code(IaC)) の中でも比較的易しいと言われる Ansible。
その Ansible の運用を省力化してくれるツールとして Ansible Tower というものがあり、そのコミュニティ管理版 (OSS版) が AWX だ。
その AWX がインストールされたサーバを作成する Playbook を作ろうとしたら意外と手間取ったので、そのメモ。
なお、インストール先は CentOS 7 である。
AWX のインストールは、 公式ビルド済み docker イメージを Docker Compose を使ってコンテナ化する方法 を使った。
11/21: 追記
docker-compose の PyPI (pip) パッケージが 1.25.0 に更新後、 CentOS 7 (正確には、 Python 2 系を使っている環境) で docker-compose のインストールや実行がうまくいかなくなった。
(commit:719a1b0 で) subprocess32 に依存するようになり、 gcc 等のビルド環境のインストールが別途必要になったためだ。
それに加え、たとえ gcc をインストールしても、依存パッケージの python2 対応が不十分なようで、 docker-compose 実行時にエラーになってしまう。
docker/compose#7030 の Issue には挙がっているが、修正されるかどうか不明なため、一つ前の 1.24.1 を使うことで回避するように、コードを修正した。
python2 ツラい。。。
しかし、 2020年にサポート切れになった後も、 CentOS 7 が生きているしばらくの間はこの辛みと付き合わなければならないようだ。
ツラい。。。
追記ここまで
まず、最終的に作成した playbook を掲載する。
AWX を docker-compose と 公式ビルド済みコンテナ を使ってインストールする Ansible Playbook
---
- hosts: all
vars:
venv_dir: /tmp/venv-awx
awx_repo: https://github.com/ansible/awx.git
awx_repo_dir: /tmp/awx
awx_version: 9.0.1
postgres_data_dir: /tmp/pgdocker
#http_proxy: http://proxy.example.com
#https_proxy: http://proxy.example.com
#no_proxy: localhost,127.0.0.1,company.example.com
envs:
http_proxy: "{{ http_proxy | default(ansible_env.http_proxy | default('')) }}"
https_proxy: "{{ https_proxy | default(ansible_env.https_proxy | default('')) }}"
no_proxy: "{{ no_proxy | default(ansible_env.no_proxy | default('localhost,127.0.0.1')) }}"
tasks:
- environment: "{{envs}}"
block:
- name: update pre-setting packages
become: yes
yum:
name:
- epel-release
- yum-utils
state: latest
- name: add docker-ce repo
become: yes
shell: "yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo"
args:
chdir: /etc/yum.repos.d
creates: docker-ce.repo
- name: remove conflict packages
become: yes
yum:
name:
# https://docs.docker.com/install/linux/docker-ce/centos/#uninstall-old-versions
- docker
- docker-engine
- docker-compose
state: absent
- name: ensure packages
become: yes
yum:
name:
- git
- python-pip
- python-virtualenv
- docker-ce
state: latest
register: result_pagkages
# to abort "Cannot uninstall 'requests'. It is a distutils installed project and thus we cannot accurately determine which files belong to it which would lead to only a partial uninstall." error
# using virtualenv to avoid the conflict of python packages between yum and pip when installing docker-compose
# -> https://github.com/docker/compose/issues/5883
#
# to abort "Unable to load docker-compose. Try `pip install docker-compose`." error
# https://www.uramiraikan.net/Works/entry-3362.html
#
# create virtualenv with --system-site-packages option
# to make use of any libraries installed in the system’s Python
# https://docs.ansible.com/ansible/latest/reference_appendices/faq.html#running-in-a-virtualenv
#
# to avoid docker/compose#7030 issue, fix docker-compose package version to 1.24.1
# https://github.com/docker/compose/issues/7030
- name: ensure pip packages
pip:
name:
- ansible
- docker-compose==1.24.1
state: present
virtualenv: "{{ venv_dir }}"
virtualenv_site_packages: yes
- block:
- name: create docker proxy settings directory
become: yes
file:
path: /etc/systemd/system/docker.service.d
state: directory
owner: root
group: root
mode: u=rwx,g=rx,o=rx
- name: create docker proxy settings
become: yes
copy:
dest: /etc/systemd/system/docker.service.d/http-proxy.conf
content: |
[Service]
Environment="HTTP_PROXY={{ envs.http_proxy }}" "HTTPS_PROXY={{ envs.https_proxy }}" "NO_PROXY={{ envs.no_proxy }}"
register: result_proxy
when: envs.http_proxy or envs.https_proxy
- block:
- name: get the current groups
command: groups
changed_when: false
register: original_groups
- name: ensure the connecting user is member of docker group
become: yes
user:
name: "{{ ansible_env.USER }}"
groups: docker
append: yes
register: result_user
# reset ssh connection for refletction the changed groups
# (`meta: reset_connection` occurs an error on current ansible version)
# https://stackoverflow.com/a/28213378
- name: kill open ssh sessions for force reconnection
shell: sleep 1; pkill -u {{ ansible_env.USER }} sshd
async: 3
poll: 2
when: result_user is changed
when: ansible_env.USER != 'root'
- name: enable and restart docker service
become: yes
systemd:
name: docker
state: restarted
enabled: yes
daemon_reload: yes
when: result_pagkages is changed or result_user is changed or result_proxy is changed
- name: git clone awx
git:
repo: '{{awx_repo}}'
dest: '{{awx_repo_dir}}'
version: '{{awx_version}}'
clone: yes
force: yes
- name: record playbook options
set_fact:
install_awx_playbook_opotions: >-
-e postgres_data_dir={{ postgres_data_dir }}
{% if envs.http_proxy or envs.https_proxy %}
-e http_proxy={{ envs.http_proxy }} -e https_proxy={{ envs.https_proxy }} -e no_proxy={{ envs.no_proxy }}
{% endif %}
- name: execute awx playbook
shell: "source {{ venv_dir+'/bin/activate' | quote }}; ansible-playbook -i inventory install.yml {{ install_awx_playbook_opotions }}"
args:
chdir: '{{awx_repo_dir}}/installer'
tags:
- inner-playbook
- name: ensure the connecting user is not member of docker group
become: yes
user:
name: "{{ ansible_env.USER }}"
groups: "{{ original_groups.stdout.split(' ') | join(',') }}"
append: no
when: result_user is changed
tags:
- revert-docker-group
$ ansible-playbook -i '[email protected],' install_awx.yml
Create the following inventory
file:
hostname
[all:vars]
ansible_ssh_user=username
#http_proxy=http://proxy:3128
#https_proxy=http://proxy:3128
#no_proxy=mycorp.org
and run below
$ ansible-playbook -i inventory install_awx.yml
一番大きなポイントは、 Python の Virtualenv を作成し、そこに pip 版 docker-compose を入れて動かしていることだ。
AWX を docker-compose でインストールするには、 docker-compose Python モジュールのインストールが必要だ。
しかし、 OS のパッケージマネージャ (yum) でインストールしているモジュールと、 上記 docker-compose Python module で、一部の依存パッケージが競合していたりすると、 pip で global な環境に docker-compose pip モジュールをインストールしようとした時に、
"Cannot uninstall 'requests'. It is a distutils installed project and thus we cannot accurately determine which files belong to it which would lead to only a partial uninstall."
などというようなエラーが発生してしまうことがある。
このため、 Virtualenv 環境を作成して、そこに docker-compose をインストールする形としている。
一方、 逆に パッケージマネージャ (yum) でインストールしているモジュールそのものに依存している場合、 単に Virtualenv を作成しただけだと、モジュール不足で動かなくなることがある。
このため、 Ansible の pip モジュール を使うときは、 virtualenv_site_packages: yes
を設定している。
"source {{ venv_dir+'/bin/activate' | quote }}; ansible-playbook -i inventory install.yml {{ install_awx_playbook_opotions }}"
最後に playbook 内で AWX のインストール playbook を実行する際は、上記のように Virtualenv を activate した状態で実行している。
ssh でログインしたユーザが docker コンテナの操作を行えるようにするため、 一時的に docker グループへ追加している。
グループを変更しても、 ホストマシンにログインし直さないと、設定が反映されず docker を操作することができない。
本来であれば、 Ansible の meta モジュールの reset_connection のアクションで ssh でのサインインが自動的にやり直されるはずなのだが、何故かうまく動かない。
このため、 ホストPC の sshd デーモンを非同期で Kill させることで、強制的に ssh の再接続を行っている。
プロキシの設定は、以下の両方が必要だ。
playbook 実行時のオプションとして ansible-playbook -i '[email protected],' -e http_proxy=http://proxy.example.com -e http_proxy=http://proxy.example.com install_awx.yml
のように設定できるほか、
その設定を省略した場合でも、 コンテナホストマシンの http_proxy 環境変数などが設定されていれば、それを使うようにしている。
docker-compose==1.25.0
の組み合わせで発生する不具合を回避。 AWX のバージョンを 9.0.1 に更新。Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?
コメント