Corredor

ウェブ、プログラミングの勉強メモ。

Ansible を Docker コンテナに対して適用するためのお試し環境を作った

初めてのAnsible

初めてのAnsible

RedHat が開発する構成管理ツールである Ansible。サーバに対して行いたい設定を Playbook と呼ばれる YAML ファイルに起こして実行できる、いわゆる IaC : Infrastructure as Code を実現できるツールだ。1台のマスター・サーバから複数のスレーブ・サーバに対して同様のセットアップ処理を行わせたりできて、とても便利だ。

しかし、そんな Ansible のスクリプトを構築していく際、試しにスクリプトを適用できるサーバをホイホイと用意するのは難しい。自前で別の PC マシンを用意するにしても、Ansible に構築させた環境を一旦削除してやり直したい時もあるだろうし、クラウドでインスタンスを払い出すにしても、お金がかかって仕方ない。

そこで今回は、Ansible スクリプトを「試し打ち」する対象に Docker コンテナを使うことにした。手元のホストマシンに必要なのは Docker の実行環境のみ。Ansible をすぐに動かし始められるサンプルプロジェクトを作ったので、紹介していく。

サンプルプロジェクトの紹介

以降で紹介していくサンプルプロジェクトは以下。

github.com

とりあえず動かしてみたい人は、README.md のとおりにコマンドを叩いてみれば良い。

詳細説明

構成

このサンプルプロジェクトでは、以下の3つのコンテナを用意している。

  1. ansible-server : Ansible の実行環境 (ansible-playbook コマンドがインストールされている)
  2. target-1 : 処理を行わせたいサーバのテイで用意した CentOS コンテナ
  3. target-2 : 処理を行わせたいサーバのテイで用意した Debian コンテナ

これら3つのコンテナを、docker-compose コマンドで一気に起動できるようにしてある。

$ docker-compose up -d

コンテナ3つとも docker execbash のセッションに接続できるが、メインで使用するのは 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-1target-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-1target-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 コマンドは同梱されていない
  • 参考:Docker Hub
    • ↑ メンテが止まっているイメージ

メンテが止まっている Dockerfile は以下。

CentOS 7 イメージに Ansible をインストールしているだけなので、自前でやることにする。Python 関連のライブラリも指定されているが、単純に yum install ansible だけで大丈夫そうだ。

また、操作対象ホストに ssh コマンドで接続確認できるようにしておきたいので、yum install git で Git とともに ssh コマンドを入れておく。

以上のような Docker イメージで、とりあえず ansibleansible-playbookssh コマンドが動作する状態になった。

パスワードで 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/sshdsession required pam_loginuid.so となっている行を required から optional に変更する
  • その他必要そうな設定を適当に… (← 効果がよく分かってない)

とゆー感じ。

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 コンテナで作ることはできたので、よきよき。

入門Ansible

入門Ansible