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
のインストールを行います。
# 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接続の設定変更
[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デーモンの起動
# 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で実行します。
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でも指定してください。
[node]
node01
node02
node03
playbookの作成
Ansibleでは、Playbookでターゲットノードの状態を定義することで管理を行います。
定義ファイルはYAML形式で行います。ファイル名は任意ですが、今回はわかりやすいようにplaybook.yml
とします。
以下のPlaybookは、Apache(httpd)をインストールして起動した状態を定義しています。
hosts: node
で、先ほどのインベントリで定義したnodeグループに対して実行されます。
---
- 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までのフォルダパス置き換えてください。)
$ cd <BASE_DIR>/ansible-training
各ノードをビルドします。
$ docker-compose build --no-cache
各ノードを起動します。
$ docker-compose up -d
コントロールノードの動作確認
起動が出来たら、コントロールノード(ansibleコンテナ)に入りましょう。
$ docker-compose exec ansible bash
インストールしたAnsibleの動作確認を行います。
pingモジュールを使用して、localhost(コントロールノード自身)に疎通確認を行います。
$ ansible localhost -m ping
以下の通りに結果が表示されればAnsibleが正常にインストールされています。
localhost | SUCCESS => {
"changed": false,
"ping": "pong"
}
ターゲットノードを操作
各ターゲットノードに対して、SSHで接続確認を行います。
この作業で、予めターゲットノードをSSHのknown_hostsに登録します。
node0xのxはターゲットノードの番号に置き換えてください。
接続を続けるかを聞かれた場合はyesと入力して下さい。
$ 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 をセットアップします。
$ 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のインストールを実行します。
ansible node -m shell -a 'yum -y install sudo'
インストールが完了したら、再度Playbookを実行してみてください。
Ansibleは"冪等性"の概念があるため、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
さいごに
Ansibleを手軽に触ることができるように、Dockerを用いてローカル環境構築する方法と簡単なハンズオンをまとめました。
ターゲットノード数の変更したり、httpdのセットアップ以外のPlaybookを作成したりして、Ansibleの理解に役立てていただければ幸いです。
参考