LoginSignup
6
7

More than 1 year has passed since last update.

【Ansible on Docker】Ansibleのハンズオン環境をDockerで構築

Posted at

Ansibleのハンズオン環境をDockerを用いて構築してみたいと思います。
構成は以下の通りです。

  • コントロールノード(Ansible) x 1
  • ターゲットノード x 3

ターゲットノードは調整可能ですので、適当な数に置き換えて実施して下さい。

説明不要の方は以下を参照してください
https://github.com/Shoma-progr-0210/ansible-training

前提条件

  • Docker on Desktopがインストールされている
  • Dockerの基礎知識がある
  • Linuxコマンドの基礎知識がある

ディレクトリ構成

ansible-training
  │  docker-compose.yml
  │
  ├─ansible
  │      ansible.cfg
  │      Dockerfile
  │
  ├─node
  │      Dockerfile
  │
  └─work
          hosts
          playbook.yml

コントロールノードの構築

ansible-training
  ├─ansible
  │      ansible.cfg
  │      Dockerfile

コントロールノードのDockerfileを作成します。
今回はCentOS7のイメージを使用します。

最低限必要なものとして、sudoとSSH接続のためにopenssh-clientsをインストールしておきます。
CentOS7のイメージにはansibleが存在しないため、eptl-releaseをインストールしてから、ansibleのインストールを行います。

コントロールノードのDockerfile
# CentOS7
FROM centos:7

# system update
RUN yum -y update && yum clean all

# install sudo
RUN yum -y install sudo
# install ssh clients
RUN yum -y install openssh-clients

# install ansible
RUN yum -y install epel-release && \
yum -y install ansible && \
yum clean all

# setttings
ADD ansible.cfg /etc/ansible

ハンズオンのためにAnsibleの設定変更を行います。
そのため、同じ階層にansible.cfgを作成して、DockerfileのADDで上書き出来るようにします。

内容は、以下です。

  • デフォルトのインベントリファイルを/root/work/hostsに変更
  • ssh接続の設定変更
Ansible.cfg
[defaults]
inventory = /root/work/hosts

[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null

ターゲットノードの追加

ansible-training
  ├─node
  │      Dockerfile

ターゲットノードのDockerfileを作成します。
こちらもCentOS7のイメージを使用します。

ssh接続のためにopenssh-serverをインストールします。

その他に以下を行います。

  • SSHの公開鍵作成
  • rootのパスワード設定
  • 22番ポートの公開
  • SSHデーモンの起動
ターゲットノードのDcokerfile
# CentOS7
FROM centos:7

# install ssh server
RUN yum -y install openssh-server && yum clean all

# create Public key
RUN ssh-keygen -f /etc/ssh/ssh_host_rsa_key -N '' -t rsa
RUN ssh-keygen -f /etc/ssh/ssh_host_ecdsa_key -N '' -t ecdsa

# set to login as root
RUN sed -ri 's/^#PermitEmptyPasswords no/PermitEmptyPasswords yes/' /etc/ssh/sshd_config

# set a password for root
RUN echo "root:" | chpasswd

# expose 22 port
EXPOSE 22

# start up sshd
CMD ["/usr/sbin/sshd", "-D"]

サービスの定義(docker-compose.yml)の作成

ansible-training
  │  docker-compose.yml

サービスの定義を記述するdocker-compose.ymlを作成します。

コントロールノードはansibleです。ボリュームとして、ホストの./workをコントロールノードの/root/workと共有します。

ターゲットノードはnode0x(例の場合、xは1-3)です。
version3.4よりサポートされたExtension Fieldを用いて、ターゲットノードの定義をx-node: &nodeと書くことで、変数のように使用しています。呼び出し側は*nodeです。

ターゲットノードのportsは必要ではありませんが、ハンズオンの結果の確認で使用するために定義しています。

ターゲットノード数を調整したい場合は、servicesを調整してください。

ターゲットノードは、ハンズオンの際にsystemdでhttpdを起動するため、/sbin/initで実行します。

docker-compose.yml
version: '3.8'

x-node: &node
  build: ./node
  privileged: true
  command: /sbin/init
  tty: true

services:
  ansible:
    container_name: 'ansible'
    build: ./ansible
    tty: true
    working_dir: '/root/work'
    volumes:
      - ./work:/root/work

  node01:
    container_name: node01
    <<: *node
    ports:
      - '8081:80'
  node02:
    container_name: node02
    <<: *node
    ports:
      - '8082:80'
  node03:
    container_name: node03
    <<: *node
    ports:
      - '8083:80'

作業ディレクトリの作成

ansible-training
  └─work
          hosts
          playbook.yml

コントロールノードで作業するディレクトリを作成します。
このディレクトリをホスト側とDocker側で共有しますので、Dockerを削除しても作業内容が保存されます。

インベントリファイルの作成

hostsはAnsibleに設定するインベントリファイルです。
先ほど作成したansible.cfgでデフォルトのインベントリとして指定されおり、ターゲットノードをnodeグループとして設定しています。

docker-compose.ymlでターゲットノードを調整した場合は、hostsでも指定してください。

hosts
[node]
node01
node02
node03

playbookの作成

Ansibleでは、Playbookでターゲットノードの状態を定義することで管理を行います。
定義ファイルはYAML形式で行います。ファイル名は任意ですが、今回はわかりやすいようにplaybook.ymlとします。

以下のPlaybookは、Apache(httpd)をインストールして起動した状態を定義しています。
hosts: nodeで、先ほどのインベントリで定義したnodeグループに対して実行されます。

playbook.yml
---
- name: deploy httpd server
  hosts: node
  become: yes
  gather_facts: no
  tasks:
    - name: install httpd
      yum:
        name: httpd
        state: latest

    - name: start & enabled httpd
      service:
        name: httpd
        state: started
        enabled: yes

Ansibleハンズオン

コンテナのビルド・起動

まずは、ansible-taining配下に移動してください。
(<BASE_DIR>はansible-trainingまでのフォルダパス置き換えてください。)

ansible-trainingに移動
$ cd <BASE_DIR>/ansible-training

各ノードをビルドします。

コンテナのビルド
$ docker-compose build --no-cache

各ノードを起動します。

コンテナの起動
$ docker-compose up -d

コントロールノードの動作確認

起動が出来たら、コントロールノード(ansibleコンテナ)に入りましょう。

コントロールノードに入る
$ docker-compose exec ansible bash

インストールしたAnsibleの動作確認を行います。
pingモジュールを使用して、localhost(コントロールノード自身)に疎通確認を行います。

Ansibleの動作確認
$ ansible localhost -m ping

以下の通りに結果が表示されればAnsibleが正常にインストールされています。

確認結果
localhost | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

ターゲットノードを操作

各ターゲットノードに対して、SSHで接続確認を行います。

この作業で、予めターゲットノードをSSHのknown_hostsに登録します。

node0xのxはターゲットノードの番号に置き換えてください。

接続を続けるかを聞かれた場合はyesと入力して下さい。

SSHのknown_hostsに登録
$ ssh node0x
$ exit

pingモジュールを使用して、ターゲットノードに対して疎通確認を行います。

ターゲットノードとの疎通確認
$ ansible node -m ping

以下のように、各ターゲットノードの結果が表示されれば接続は成功です。

確認結果
node01 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
node03 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
node02 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}

Apache(httpd)をターゲットノードで起動

AnsibleはPlaybookという単位で、ターゲットノードの状態を定義することで操作を行えます。
今回は事前にhttpdのインストールと起動を行うPlaybookを作成してるので、実行しましょう。

playbook.yml を実行して、ターゲットノードに httpd をセットアップします。

Playbookの実行
$ ansible-playbook playbook.yml
実行結果
PLAY [deploy httpd server] *********************************************************************************************

TASK [install httpd] ***************************************************************************************************
fatal: [node01]: FAILED! => {"changed": false, "msg": ["Could not detect which major revision of yum is in use, which is required to determine module backend.", "You can manually specify use_backend to tell the module whether to use the yum (yum3) or dnf (yum4) backend})"]}
fatal: [node02]: FAILED! => {"changed": false, "msg": ["Could not detect which major revision of yum is in use, which is required to determine module backend.", "You can manually specify use_backend to tell the module whether to use the yum (yum3) or dnf (yum4) backend})"]}
fatal: [node03]: FAILED! => {"changed": false, "msg": ["Could not detect which major revision of yum is in use, which is required to determine module backend.", "You can manually specify use_backend to tell the module whether to use the yum (yum3) or dnf (yum4) backend})"]}

PLAY RECAP *************************************************************************************************************
node01                     : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0
node02                     : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0
node03                     : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

各ターゲットノードで、failed=1になるはずです。
エラーには色々書いてありますが、sudoがインストールされていないために、httpdのインストールで権限周りの問題が起きています。

ターゲットノードにsudoをインストールします。
Playbookを用意してもよいですが、ここではshellモジュールを使用して、直接sudoのインストールを実行します。

sudoのインストール
ansible node -m shell -a 'yum -y install sudo'

インストールが完了したら、再度Playbookを実行してみてください。

Ansibleは"冪等性"の概念があるため、Playbookの実行が途中で失敗しても、再実行することで整合性を保つことができます。切り戻しなどは必要ありません。

Playbookの再実行
$ ansible-playbook playbook.yml
実行結果
PLAY [deploy httpd server] *********************************************************************************************

TASK [install httpd] ***************************************************************************************************
changed: [node02]
changed: [node03]
changed: [node01]

TASK [start & enabled httpd] *******************************************************************************************
changed: [node03]
changed: [node01]
changed: [node02]

PLAY RECAP *************************************************************************************************************
node01                     : ok=2    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
node02                     : ok=2    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
node03                     : ok=2    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

各ターゲットノードで、ok=2 changed=2になれば成功です。

これだけで全てのターゲットノードでhttpdのセットアップが完了です。
ターゲットノードで httpd が正常に動作しているかをブラウザで確認してみましょう。

xはターゲットノードの番号に置き換えてください。

node0x: http://localhost:808x

この画面が開けば正常に動作しています。
image.png

さいごに

Ansibleを手軽に触ることができるように、Dockerを用いてローカル環境構築する方法と簡単なハンズオンをまとめました。
ターゲットノード数の変更したり、httpdのセットアップ以外のPlaybookを作成したりして、Ansibleの理解に役立てていただければ幸いです。

参考

6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7