とことんDevOps | 日本仮想化技術のDevOps技術情報メディア

DevOpsに関連する技術情報を幅広く提供していきます。

日本仮想化技術がお届けする「とことんDevOps」では、DevOpsに関する技術情報や、日々のDevOps業務の中での検証結果、TipsなどDevOpsのお役立ち情報をお届けします。
主なテーマ: DevOps、CI/CD、コンテナ開発、IaCなど
読者登録と各種SNSのフォローもよろしくお願いいたします。

Ansible Navigatorの実行環境イメージをカスタマイズする

前回に引き続き、今回もAnsibleをコンテナを使って実行する「Ansible Navigator」について取り上げます。

devops-blog.virtualtech.jp

今回は「Ansible Builder」を使ってコンテナイメージをカスタマイズして、「Ansible Navigator」でそのイメージを使ってAnsibleを実行してみたり、作成したイメージの中を覗いてみたりしようと思います。

今回も、次のブログ記事をベースにしています(ちょっとだけ味付けを変えています)。

rheb.hatenablog.com

Ansible Builderのインストール

RHELはdnf、RHEL以外やFedoraではpipを使ってインストールしますが、pipでインストールする場合はansible-navigatorをインストールした時点で依存パッケージとしてインストールされているようです。もしインストールされていない場合は次のように実行します。

$ sudo dnf install python3-pip
$ pip3 install --user ansible-builder

参考記事はDockerを使っているようですが、本記事ではコンテナランタイムは今回もPodmanを使います。インストールされていない場合はインストールします。

$ sudo dnf install podman

また、最後にAnsible Navigatorも実行しますので、インストールされていない場合は前回記事のようにインストールしてください。

devops-blog.virtualtech.jp

イメージ作成に必要なファイルを作成

参考記事に従ってイメージ作成のための各ファイルを作っていきますが、custom_ee.ymlのベースイメージのバージョン部分を書き換えました。これは以前の記事で利用していたバージョンと一緒のものを指定しています。

$ cat custom_ee.yml 
version: 1

build_arg_defaults:
  ANSIBLE_GALAXY_CLI_COLLECTION_OPTS: '-v'
  EE_BASE_IMAGE: 'quay.io/ansible/ansible-runner:stable-2.12-devel'  //書き換えた部分

ansible_config: 'ansible.cfg'

dependencies:
  galaxy: requirements.yml
  python: requirements.txt
  system: bindep.txt

additional_build_steps:
  prepend: |
    RUN whoami
    RUN cat /etc/os-release
  append:
    - RUN echo This is a post-install command!
    - RUN ls -la /etc

その他のファイルは参考記事と一緒です。

$ tree
.
├── ansible.cfg
├── bindep.txt
├── custom_ee.yml
├── requirements.txt
└── requirements.yml

イメージのビルド

次のようなコマンドでイメージを作成します。

$ ansible-builder build -f custom_ee.yml -t custom_ee:2.12
Running command:
  podman build -f context/Containerfile -t custom_ee:2.12 context
Complete! The build context can be found at: /home/fedora/ansiblebuild/context

イメージ作成には結構時間がかかるので、状況はps aux|grep ansible-builderを実行してPIDを確認し、strace -p PIDなどを実行して現在、何を実行しているかを把握してください。

イメージができているのを確認します。

$ podman image ls
REPOSITORY                       TAG                IMAGE ID      CREATED         SIZE
localhost/custom_ee              2.12               69b32027df57  23 seconds ago  1.03 GB
<none>                           <none>             afb36bc0a5e4  4 minutes ago   1.03 GB
<none>                           <none>             3ec155571a57  6 minutes ago   834 MB
quay.io/ansible/ansible-runner   stable-2.12-devel  70252e151bfc  4 months ago    816 MB
quay.io/ansible/ansible-builder  latest             b0348faa7f41  6 months ago    779 MB

作成したファイルを元にcontext/Containerfileが作成されています。

$ tree
.
├── ansible.cfg
├── bindep.txt
├── context
│   ├── _build
│   │   ├── ansible.cfg
│   │   ├── bindep.txt
│   │   ├── requirements.txt
│   │   └── requirements.yml
│   └── Containerfile
├── custom_ee.yml
├── requirements.txt
└── requirements.yml

2 directories, 10 files

Containerfileの中身は色々なコンテキストファイルを元として、希望したイメージを作成するための設定が書かれたファイルが生成されます。これを使ってイメージが作成されます。

今回はEE_BASE_IMAGEで指定したイメージをカスタマイズする例です。 ちなみにここで指定されているイメージquay.io/ansible/ansible-runner:stable-2.12-develの中身は、CentOS Stream 8が使われていました。

$ cat context/Containerfile 
ARG EE_BASE_IMAGE=quay.io/ansible/ansible-runner:stable-2.12-devel
ARG EE_BUILDER_IMAGE=quay.io/ansible/ansible-builder:latest

FROM $EE_BASE_IMAGE as galaxy
ARG ANSIBLE_GALAXY_CLI_COLLECTION_OPTS=-v
USER root

ADD _build/ansible.cfg ~/.ansible.cfg

ADD _build /build
WORKDIR /build

RUN ansible-galaxy role install -r requirements.yml --roles-path "/usr/share/ansible/roles"
RUN ANSIBLE_GALAXY_DISABLE_GPG_VERIFY=1 ansible-galaxy collection install $ANSIBLE_GALAXY_CLI_COLLECTION_OPTS -r requirements.yml --collections-path "/usr/share/ansible/collections"

FROM $EE_BUILDER_IMAGE as builder

COPY --from=galaxy /usr/share/ansible /usr/share/ansible

ADD _build/requirements.txt requirements.txt
ADD _build/bindep.txt bindep.txt
RUN ansible-builder introspect --sanitize --user-pip=requirements.txt --user-bindep=bindep.txt --write-bindep=/tmp/src/bindep.txt --write-pip=/tmp/src/requirements.txt
RUN assemble

FROM $EE_BASE_IMAGE
USER root
RUN whoami
RUN cat /etc/os-release

COPY --from=galaxy /usr/share/ansible /usr/share/ansible

COPY --from=builder /output/ /output/
RUN /output/install-from-bindep && rm -rf /output/wheels
RUN echo This is a post-install command!
RUN ls -la /etc

作成したイメージを使ってPlaybookを実行

作成したイメージを使って、Playbookを実行してみます。 当然ながら問題なく動きました。

$ cd ansiblenavi
$ ansible-navigator run --eei custom_ee:2.12 playbook/test.yml -i inventory/hosts -vv
ansible-playbook [core 2.12.5.post0]
  config file = None
  configured module search path = ['/home/runner/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.8/site-packages/ansible
  ansible collection location = /home/runner/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/local/bin/ansible-playbook
  python version = 3.8.13 (default, Jun 24 2022, 15:27:57) [GCC 8.5.0 20210514 (Red Hat 8.5.0-13)]
  jinja version = 2.11.3
  libyaml = True
No config file found; using defaults
Skipping callback 'awx_display', as we already have a stdout callback.
Skipping callback 'default', as we already have a stdout callback.
Skipping callback 'minimal', as we already have a stdout callback.
Skipping callback 'oneline', as we already have a stdout callback.

PLAYBOOK: test.yml *************************************************************
1 plays in /home/fedora/ansiblenavi/playbook/test.yml

PLAY [all] *********************************************************************
META: ran handlers

TASK [ping] ********************************************************************
task path: /home/fedora/ansiblenavi/playbook/test.yml:6
ok: [172.16.214.188] => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"}, "changed": false, "ping": "pong"}
META: ran handlers
META: ran handlers

PLAY RECAP *********************************************************************
172.16.214.188             : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

イメージのデバッグ

作成したイメージを確認してみましょう。Podmanでカスタムイメージを使ってコンテナーを作成し、シェルに入ってみます。 コマンドを実行すると、それぞれセットアップ済みであることがわかります。

//カスタムイメージを使ってコンテナを実行
$ podman container run -it localhost/custom_ee:2.12 bash

//rpmパッケージの確認
bash-4.4# rpm -q krb5-devel                                    
krb5-devel-1.18.2-21.el8.x86_64

//Pythonモジュールの確認
bash-4.4# pip list  | egrep "awxkit"
awxkit           21.5.0

//ansible-galaxy collectionの確認
bash-4.4# ansible-galaxy collection list
Collection        Version
----------------- -------
ansible.posix     1.4.0  
awx.awx           21.5.0 
community.general 5.5.0  

基本的にはベースイメージを使ってAnsibleのジョブをコンテナーを使って実行すればよいですが、繰り返し作業するようなジョブの場合は、事前に必要なコンポーネントを組み込んでイメージ化しておいたほうが、実行ごとにイメージをビルドするより効率的でしょう。

何度も繰り返し作業するような場合にAnsible Builderが必要になってくると思います。

参考情報