Ansible を Docker コンテナに対して適用するためのお試し環境を作った
RedHat が開発する構成管理ツールである Ansible。サーバに対して行いたい設定を Playbook と呼ばれる YAML ファイルに起こして実行できる、いわゆる IaC : Infrastructure as Code を実現できるツールだ。1台のマスター・サーバから複数のスレーブ・サーバに対して同様のセットアップ処理を行わせたりできて、とても便利だ。
しかし、そんな Ansible のスクリプトを構築していく際、試しにスクリプトを適用できるサーバをホイホイと用意するのは難しい。自前で別の PC マシンを用意するにしても、Ansible に構築させた環境を一旦削除してやり直したい時もあるだろうし、クラウドでインスタンスを払い出すにしても、お金がかかって仕方ない。
そこで今回は、Ansible スクリプトを「試し打ち」する対象に Docker コンテナを使うことにした。手元のホストマシンに必要なのは Docker の実行環境のみ。Ansible をすぐに動かし始められるサンプルプロジェクトを作ったので、紹介していく。
サンプルプロジェクトの紹介
以降で紹介していくサンプルプロジェクトは以下。
とりあえず動かしてみたい人は、README.md
のとおりにコマンドを叩いてみれば良い。
詳細説明
構成
このサンプルプロジェクトでは、以下の3つのコンテナを用意している。
ansible-server
: Ansible の実行環境 (ansible-playbook
コマンドがインストールされている)target-1
: 処理を行わせたいサーバのテイで用意した CentOS コンテナtarget-2
: 処理を行わせたいサーバのテイで用意した Debian コンテナ
これら3つのコンテナを、docker-compose
コマンドで一気に起動できるようにしてある。
$ docker-compose up -d
コンテナ3つとも docker exec
で bash
のセッションに接続できるが、メインで使用するのは ansible-server
だけだ。ansible-server
にて ansible-playbook
コマンドを実行して、target-1
サーバと target-2
サーバに同じ設定を行わせる、という関係である。
Ansible 実行環境と設定ファイル
というワケで ansible-server
コンテナに接続する。
$ docker exec -it ansible-server /bin/bash
ansible-server
コンテナは、このサンプルプロジェクトのルートディレクトリを /var/data
ディレクトリにマウントしている。Ansible の処理内容を書く Playbook ファイルや、接続先を示す Inventry (Hosts) ファイルは ./ansible/
ディレクトリに格納してある。
接続先を示す Inventry (Hosts) ファイルは、たった3行。見てもらうと分かるが、ホスト名と、それをグルーピングする名前を指定しているだけ。
./ansible/inventry-hosts.ini
[target]
target-1
target-2
そして Playbook ファイルの方は、echo
とリダイレクトを使って、/tmp/
配下にファイルを生成するだけ、というシンプルなサンプルコードを載せている。この中の hosts:
プロパティで、上のインベントリファイルでいう [target]
グループを指定している。
./ansible/playbook.yaml
- hosts: target
tasks:
- name: Make test file
shell: |
echo 'Test' > /tmp/ansible-docker-test.txt
ansible-playbook
コマンドで使用するのは以上の2つのファイルのみだ。
Ansible 実行環境から操作対象ホストへの SSH 接続
ansible-server
から、target-1
と target-2
へは、SSH 接続できる必要がある。実際に ansible-server
コンテナ内で、ssh
コマンドを叩いて確かめてみよう。
# Ansible コンテナから Target 1 コンテナに SSH できるか確認する
$$ ssh target-1
# 初回のみ `yes` と回答する
# `root@target-1's password:` にパスワードを入力する
パスワードは ./docker/target-1/Dockerfile
にて設定していて、mypassword
である。SSH 接続時に公開鍵認証方式ではなく、パスワード認証方式を利用しているサーバ、というテイにしている。この辺りは、このサンプルプロジェクトを簡素化するためにこのようにしたもので、鍵認証でも Ansible は使える。
パスワードを入力して SSH 接続すると、ansible-server
コンテナ内で、target-1
コンテナの中に入れたことになる。$ cat /etc/os-release
などを叩いてみて、CentOS 環境であることを確認して欲しい。
同様に、target-2
へも接続できる。
# Ansible コンテナから Target 2 コンテナに SSH できるか確認する
$$ ssh target-2
# 初回のみ `yes` と回答する
# `root@target-2's password:` にパスワードを入力する
パスワードは ./docker/target-2/Dockerfile
で設定しているとおり、mypassword
(target-1
のパスワードと同じ)。コチラは Debian サーバだ。
Ansible を実行してみる
操作対象のサーバと接続できることが確認できたら、実際に Ansible を実行してみよう。
# Ansible を実行する
$$ ansible-playbook -i ./ansible/inventry-hosts.ini ./ansible/playbook.yaml --ask-pass
# SSH パスワードを入力する
-i
オプションでインベントリファイル (接続先) を指定する。メインで Playbook ファイルを指定すれば、そのとおりに処理が行われていくというワケだ。ココで、今回用意した2台のサーバコンテナは、パスワードで SSH 接続するので、--ask-pass
オプションを付けて、SSH 接続時のパスワードを入力するようにしている。ココでは target-1
と target-2
で同じ値にしていた mypassword
を入力する。
すると、各コンテナの /tmp/
配下に ansible-docker-test.txt
というファイルが生成されるはずだ。
以上で Ansible を実行するところまでは試せたと思うので、あとは ./ansible/playbook.yaml
を実装していって、それぞれのコンテナに設定が加えていけるか、試していってほしい。
コンテナを停止する
立ち上げたコンテナを停止・破棄するには、次のコマンドを実行する。
$ docker-compose rm --stop --force
やっていることは $ docker rm -f 【Container ID】
を3台分繰り返したのと同じだ。
Dockerfile の準備が地味に大変だった…
ココからは、このお試しキットを作るまでのお話。
Ansible 実行環境コンテナを作る
まず ansible
コマンドや ansible-playbook
コマンドが使える環境を作りたく、Ansible の公式イメージを探したのだが、Ansible 公式では Docker イメージのメンテを止めているようだった。
- 参考 : Docker Hub
- ↑ コレは Ansible のテスト用イメージらしく
ansible
コマンドは同梱されていない
- ↑ コレは Ansible のテスト用イメージらしく
- 参考 : Docker Hub
- ↑ メンテが止まっているイメージ
メンテが止まっている Dockerfile は以下。
CentOS 7 イメージに Ansible をインストールしているだけなので、自前でやることにする。Python 関連のライブラリも指定されているが、単純に yum install ansible
だけで大丈夫そうだ。
また、操作対象ホストに ssh
コマンドで接続確認できるようにしておきたいので、yum install git
で Git とともに ssh
コマンドを入れておく。
以上のような Docker イメージで、とりあえず ansible
・ansible-playbook
・ssh
コマンドが動作する状態になった。
パスワードで SSH ログインできる CentOS 環境を作る
続いて、SSH 接続して Ansible を実行する、対象のサーバ target-1
を作る。ベースイメージは ansible-server
と同じ CentOS 7 系。
SSH 接続される環境を用意するには、yum install openssh-server
を実施しておく。その上で、Docker イメージはデフォルトでは root
ユーザしかいないので、root
ユーザで SSH ログインできるように色々設定した。
/usr/sbin/sshd -D
実行時にCould not load host key:
と怒られるので、ssh-keygen
で鍵ペアを3つ作っておいた/etc/ssh/sshd_config
にてPermitEmptyPasswords yes
と設定するchpasswd
を使ってroot
ユーザのパスワードをmypassword
に設定するDockerfile
中のecho 'root:mypassword' | chpasswd
という部分。パスワード文字列を変更したい場合はココを変える
さらに SSH 接続用に22番ポートを開放 (EXPOSE
) し、sshd
を起動しておく。
パスワードで SSH ログインできる Debian 環境を作る
同様に、root
ユーザで SSH ログインできる、Debian OS 環境を作っていく。やることは CentOS と大差ないかなーと思っていたのだが、まぁまぁ詰まった。
ネット上の文献が、以前のバージョンの Debian 向けの設定だったので、Buster (v10) に合わせた設定に変更する必要があった。
/etc/ssh/sshd_config
にてPermitRootLogin yes
と設定する/etc/pam.d/sshd
のsession required pam_loginuid.so
となっている行をrequired
からoptional
に変更する- その他必要そうな設定を適当に… (← 効果がよく分かってない)
とゆー感じ。
- 参考 : Dockerize an SSH service | Docker Documentation
- 公式のガイドだが、Ubuntu v16 向けの記述になっていて Debian v10 Buster ではこのとおりではダメだった
- 参考 : X11クライアント用のsshd専用コンテナをdockerで動かした - @znz blog
- この記事が一番参考になった (Ubuntu v18 向け)
- 参考 : bash - Why set VISIBLE=NOW in /etc/profile? - Stack Overflow
export VISIBLE=now
とかって何の意味?という記事
CentOS と違い、yum
ではなく apt-get
を使う点と、Ansible を実行するには Python がインストールされていないといけなかったので、apt-get install python
も実施しておいた (CentOS には python
コマンドが既に入っていた)。
なんやらかんやら設定して、とりあえず CentOS と同じように、root
ユーザのパスワードを入力する方式で SSH 接続できるようになった。
Docker Compose 設定ファイルを書く
これら3つのコンテナを立ち上げるため、docker-compose.yaml
ファイルを書いた。
tty: true
とすると、コンテナを起動しっぱなしで置いておけるようなので設定した。便利ねぇ〜。
以上
とりあえず Ansible の素振り・お試し環境を Docker コンテナで作ることはできたので、よきよき。