2022年12月10日土曜日

Ansibleを使ってDcokerのコンテナ環境をを操作する

今まで本ブログでは、Ansibleを使ってLinuxやWindows Serverの操作を実施してきた。Ansibleは他にも様々なモジュールが標準で含まれている。

Ansibleに含まれるモジュールは、以下コマンドで確認することができる。

# ansible-galaxy collection list
Collection                    Version
----------------------------- -------
amazon.aws                    3.5.0
ansible.netcommon             3.1.3
ansible.posix                 1.4.0
ansible.utils                 2.7.0
ansible.windows               1.12.0
arista.eos                    5.0.1

~(中略)~

community.docker              2.7.1

~(中略)~

vmware.vmware_rest            2.2.0
vultr.cloud                   1.3.0
vyos.vyos                     3.0.1
wti.remote                    1.0.4

今回は、上記に記載されているcommunity.dockerモジュールを使うことでDockerのコンテナ環境を操作することができる。今回は、Ansibleを使ってDockerのコンテナの環境を操作し、コンテナの停止、ビルド、起動を行うための手順を記載する。

環境

今回手順を確認した環境のOSは以下の通り。

  • コントロールノード
    • OS : AlmaLinux 8.5
    • Ansible : ansible [core 2.13.1]
  • DockerホストOS
    • OS : CentOS Stream release 8
    • Docker : docker-ce-20.10.14

Ansibleコントロールノード構築やLinuxサーバの事前準備の手順は、以下記事を参照いただきたい。

また、Docker上の操作対象のコンテナは以下3つとなる。各コンテナは、あらかじめDockerfileや必要な設定ファイルを準備しておく。必要な設定ファイルについては、それぞれ過去記事を参照いただきたい。

Dockerホストに対する事前準備

AnsibleでDockerを操作する場合、Dcokerホストに対して事前準備作業が必要となる。

1. pipをインストール

Dockerを利用する際はPythonパッケージのインストールが必要となるため、pipをインストールしておく。

# dnf install python3-pip

2. pipを用いてPythonパッケージをインストール

pipを用いて、以下の通りPythonパッケージをインストールする。

# python3 -m pip install docker docker-compose

もしこのモジュールをインストールしていない場合は、Playbook実行時に以下のようにPythonのモジュールが不足するといったエラーが発生する。

fatal: [dockerhost]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/libexec/platform-python"}, "can_talk_to_docker": false, "changed": false, "msg": "Failed to import the required Python library (Docker SDK for Python: docker above 5.0.0 (Python >= 3.6) or docker before 5.0.0 (Python 2.7) or docker-py (Python 2.6)) on t3027dock's Python /usr/libexec/platform-python. Please read the module documentation and install it in the appropriate location. If the required library is installed, but Ansible is using the wrong Python interpreter, please consult the documentation on ansible_python_interpreter, for example via `pip install docker` (Python >= 3.6) or `pip install docker==4.4.4` (Python 2.7) or `pip install docker-py` (Python 2.6). The error was: No module named 'docker'"}
fatal: [dockerhost]: FAILED! => {"changed": false, "msg": "Unable to load docker-compose. Try `pip install docker-compose`. Error: Traceback (most recent call last):\n  File \"/tmp/ansible_community.docker.docker_compose_payload_uyzpmc__/ansible_community.docker.docker_compose_payload.zip/ansible_collections/community/docker/plugins/modules/docker_compose.py\", line 497, in <module>\nModuleNotFoundError: No module named 'compose'\n"}

なお、Pythonパッケージについて、dockerまたはdocker-pyのどちらかをインストールすればよいらしい。ただし、両方のインストールはNGであると明確にAnsibleのマニュアルに記載されているので注意しよう。

docker-py モジュールと docker python モジュールは、同じ名前空間を使用するため、
両方インストールすると、インストールが破損します。両方のパッケージをアンインストールし、
docker-py または docker python モジュールのいずれかを再インストールしてください。
Python 2.6 のサポートが必要でない場合は、
docker モジュールをインストールすることが推奨されます。
いずれかのモジュールをアンインストールするだけでは、
もう一方のモジュールが壊れた状態になる可能性があることに注意してください。

3. Ansible実行ユーザをdockerグループに所属させる

Ansible実行時にAnsible実行ユーザがDockerにアクセスできる権限が必要となる。

# usermod -aG docker ansibleuser
# id ansibleuser
uid=2001(ansibleuser) gid=2001(ansibleuser) groups=2001(ansibleuser),990(docker)

以上でDockerホストに対する事前作業は完了となる。実際にPythonを実行してみよう。

Docker操作用Playbook

1. Playbook説明

今回のPlaybookの実行フローは以下の通り。

各タスクのモジュールと処理の説明を以下表に記載する。

タスク名 モジュール 説明
Copy Dockerfile copy 各コンテナ用のDockerfile及び必要な設定ファイルをディレクトリごとコピーする。
Copy Dockerfile template template 各コンテナ用のDockerfileについて再配置する(変数で指定したベースイメージに設定したファイルを配置する)。
Build docker image docker_image Dockerfileを用いてイメージをビルドする。
Copy docker-compose.yml template template docker-compose.ymlをコピーする。
Down container docker_compose 現在稼働しているコンテナを停止&削除(Down)する。
Up container docker_compose 新しいイメージからコンテナを作成&起動(Up)する。

実際のPlaybookは以下となる。

---
- name: Rebuild docker container
  gather_facts: false
  hosts: docker_servers

  vars:
    ansible_user: ansibleuser

    docker_config:
      image: almalinux
      tag: 8.7

    docker_container:
      - name: "{{ docker_config.image }}-postfix"
        path: container-postfix
      - name: "{{ docker_config.image }}-unbound"
        path: container-unbound
      - name: "{{ docker_config.image }}-squid"
        path: container-squid

    docker_file_path: /tmp/docker

  tasks:
    # Dockerfileコピー
    - name: Copy Dockerfile
      ansible.builtin.copy:
        src: "templates/{{ item.path }}"
        dest: "/tmp/"
        mode: 0644
      loop: "{{ docker_container }}"

    # Dockerfileテンプレートコピー
    - name: Copy Dockerfile template
      ansible.builtin.template:
        src: "templates/{{ item.path }}/Dockerfile"
        dest: "/tmp/{{ item.path }}/"
        mode: 0644
      loop: "{{ docker_container }}"

    # イメージ構築
    - name: Build docker image
      community.docker.docker_image:
        build:
          path: "/tmp/{{ item.path }}"
        source: build
        name: "{{ item.name }}"
        tag: "{{ docker_config.tag }}"
        state: present
      loop: "{{ docker_container }}"

    # docker-compose.ymlテンプレートコピー
    - name: Copy docker-compose.yml template
      ansible.builtin.template:
        src: "templates/compose/docker-compose.yml"
        dest: "/root/compose/"
        mode: 0644
      become: true

    # コンテナ停止&削除
    - name: Down container
      community.docker.docker_compose:
        project_src: /root/compose
        build: false
        # stopped: true # 停止のみ実行する場合
        state: absent
      become: true

    # コンテナ起動
    - name: Up container
      community.docker.docker_compose:
        project_src: /root/compose
        build: false
        state: present
      become: true

2. Playbook実行

# ansible-playbook -i hosts -l dockerhost docker/rebuild_docker_container.yml

PLAY [Rebuild docker container] **********************************************************************************

TASK [Copy Dockerfile] *******************************************************************************************
changed: [dockerhost] => (item={'name': 'almalinux-postfix', 'path': 'container-postfix'})
changed: [dockerhost] => (item={'name': 'almalinux-unbound', 'path': 'container-unbound'})
changed: [dockerhost] => (item={'name': 'almalinux-squid', 'path': 'container-squid'})

TASK [Copy Dockerfile template] **********************************************************************************
changed: [dockerhost] => (item={'name': 'almalinux-postfix', 'path': 'container-postfix'})
changed: [dockerhost] => (item={'name': 'almalinux-unbound', 'path': 'container-unbound'})
changed: [dockerhost] => (item={'name': 'almalinux-squid', 'path': 'container-squid'})

TASK [Build docker image] ****************************************************************************************
ok: [dockerhost] => (item={'name': 'almalinux-postfix', 'path': 'container-postfix'})
ok: [dockerhost] => (item={'name': 'almalinux-unbound', 'path': 'container-unbound'})
ok: [dockerhost] => (item={'name': 'almalinux-squid', 'path': 'container-squid'})

TASK [Copy docker-compose.yml template] **************************************************************************
changed: [dockerhost]

TASK [Down container] ********************************************************************************************
ok: [dockerhost]

TASK [Up container] **********************************************************************************************
changed: [dockerhost]

PLAY RECAP *******************************************************************************************************
dockerhost                 : ok=6    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

3. 結果確認

Playbook実行後のDcokerのコンテナイメージとコンテナの状態を比較してみよう。

まずは実行前の状態を以下に示す。イメージはAlmaLinux 8.6のみとなっており、それぞれのコンテナのタグも8.6になっていることがわかる。

# docker images
REPOSITORY          TAG       IMAGE ID       CREATED         SIZE
almalinux-unbound   8.6       fd58943ebaca   2 months ago    243MB
almalinux-squid     8.6       f6e9116750e0   2 months ago    298MB
almalinux-postfix   8.6       0ca7abe54260   2 months ago    281MB
almalinux           8.6       90516e8d258d   6 months ago    189MB

# docker ps
CONTAINER ID   IMAGE                   COMMAND                  CREATED          STATUS          PORTS                                                                              NAMES
df0976682bfe   almalinux-squid:8.6     "/usr/sbin/squid -N …"   49 minutes ago   Up 49 minutes   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp                                          almalinux-squid
553c80481ac3   almalinux-unbound:8.6   "/usr/sbin/unbound -d"   49 minutes ago   Up 49 minutes   0.0.0.0:10053->53/tcp, 0.0.0.0:10053->53/udp, :::10053->53/tcp, :::10053->53/udp   almalinux-unbound
303103b4abe8   almalinux-postfix:8.6   "/startup.sh"            49 minutes ago   Up 49 minutes   0.0.0.0:25->25/tcp, :::25->25/tcp                                                  almalinux-postfix

次に、Playbook実行後の状態を以下に示す。8.6のイメージに加えて、新たに8.7のイメージが作成されていることがわかる。また、コンテナもタグが8.7に更新されていることが確認できる。

# docker images
REPOSITORY          TAG       IMAGE ID       CREATED          SIZE
almalinux-squid     8.7       7fe03e3252a7   2 seconds ago    292MB
almalinux-unbound   8.7       bed4cd545c1f   17 seconds ago   240MB
almalinux-postfix   8.7       261591afe46c   18 minutes ago   275MB
almalinux           8.7       39f63d416992   3 days ago       190MB
almalinux-unbound   8.6       fd58943ebaca   2 months ago     243MB
almalinux-squid     8.6       f6e9116750e0   2 months ago     298MB
almalinux-postfix   8.6       0ca7abe54260   2 months ago     281MB
almalinux           8.6       90516e8d258d   6 months ago     189MB

# docker ps
CONTAINER ID   IMAGE                   COMMAND                  CREATED          STATUS          PORTS                                                                              NAMES
ec700661b92c   almalinux-unbound:8.7   "/usr/sbin/unbound -d"   25 seconds ago   Up 25 seconds   0.0.0.0:10053->53/tcp, 0.0.0.0:10053->53/udp, :::10053->53/tcp, :::10053->53/udp   almalinux-unbound
1d769e4c9ee6   almalinux-squid:8.7     "/usr/sbin/squid -N …"   25 seconds ago   Up 25 seconds   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp                                          almalinux-squid
9ff38aa8b594   almalinux-postfix:8.7   "/startup.sh"            25 seconds ago   Up 25 seconds   0.0.0.0:25->25/tcp, :::25->25/tcp                                                  almalinux-postfix

以上で、AnsibleにてDockerコンテナを操作する手順は完了となる。

参考

0 件のコメント:

コメントを投稿

人気の投稿