見出し画像

Ansbile Navigatorを使ってカスタムEEを作ってみる


はじめに


株式会社SHIFT ITソリューション部の水谷です。

前回は、Ansible EE(Execution Engine=AnsibleやPlaybookの実行に必要なコレクションなどがインストールされたコンテナ)でAnsible Playbookを実行するコマンドラインツールであるAnsible Navigatorについて書いてみました。その記事の最後で少しふれましたように、Ansible NavigatorにはEEをビルドする機能も備わっていますので、今回はこれを試してみます。

EEのビルドツールとしては、Ansible Builderがあります。Ansible NavigatorでのEEビルドはAnsible Builderのそれと何が違うのでしょうか?

ファイルの準備


EEのビルドには、いくつかの設定ファイルが必要がありますので、まずはそれらを作成します。

1つ目のファイルは execution-environment.yml です。これがEEをビルドする際の主ファイルで、多くの情報をここに記述します。

以下はRed Hat Developerサイトにあったサンプルです。

version: 1
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

dependenciesのところには、galaxy: requirements.ymlと書かれていて、requirements.ymlに記述したCollectionをAnsible Galaxyからダウンロードして、EEに含めてくれます。

例えば、requirements.ymlを以下のように記述すると、community.windowsとamazon.awsを含めてくれるのです。

collections:
  - community.windows
  - amazon.aws

続くrequirements.txtには、コレクション(実際にはその中に含まれるモジュールの実行に)必要となるPythonライブラリを列挙しておきます。

今回は、amazon.awsコレクションを使用するのに必要なboto3とbotocoreを書いておきました。

boto3>=1.26.0
botocore>=1.29.0

そして、bindep.txtには、rpmでインストールしたいパッケージを指定します。下はその例です(インストールしたいパッケージがなければ、system: bindep.txtの行や、bindep.txtは不要です。

findutils [compile platform:centos-8 platform:rhel-8]
gcc [compile platform:centos-8 platform:rhel-8]
make [compile platform:centos-8 platform:rhel-8]

一番最後の additional_build_steps には、コンテナのビルド前後に実行したいコマンドを、Dockerfileの書式で記述します。今回は特に実行したいコマンドがないので、このままにしておきます。

ビルドしてみると…


ファイルの準備ができたので、さっそくビルドしてみましょう。

ビルドのコマンドは、ansible-navigator builder build -m stdoutです。

$ ansible-navigator builder build -m stdout
Running command:
  docker build -f context/Dockerfile -t ansible-execution-env:latest context
...showing last 20 lines of output...
#13 ERROR: process "/bin/sh -c ANSIBLE_GALAXY_DISABLE_GPG_VERIFY=1 ansible-galaxy collection install $ANSIBLE_GALAXY_CLI_COLLECTION_OPTS -r requirements.yml --collections-path \"/usr/share/ansible/collections\"" did not complete successfully: exit code: 250
------
 > [galaxy 5/5] RUN ANSIBLE_GALAXY_DISABLE_GPG_VERIFY=1 ansible-galaxy collection install  -r requirements.yml --collections-path "/usr/share/ansible/collections":
0.720 Starting galaxy collection install process
0.720 Process install dependency map
9.012 to see the full traceback, use -vvv
9.012 [WARNING]: Skipping Galaxy server https://galaxy.ansible.com/api/. Got an
9.012 unexpected error when getting available versions of collection amazon.aws: '/ap
9.012 i/v3/plugin/ansible/content/published/collections/index/amazon/aws/versions/'
9.012 ERROR! Unexpected Exception, this is probably a bug: '/api/v3/plugin/ansible/content/published/collections/index/amazon/aws/versions/'
------
Dockerfile:36
--------------------
  34 |
  35 |     RUN ansible-galaxy role install $ANSIBLE_GALAXY_CLI_ROLE_OPTS -r requirements.yml --roles-path "/usr/share/ansible/roles"
  36 | >>> 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"
  37 |
  38 |     # Builder build stage
--------------------
ERROR: failed to solve: process "/bin/sh -c ANSIBLE_GALAXY_DISABLE_GPG_VERIFY=1 ansible-galaxy collection install $ANSIBLE_GALAXY_CLI_COLLECTION_OPTS -r requirements.yml --collections-path \"/usr/share/ansible/collections\"" did not complete successfully: exit code: 250

An error occurred (rc=1), see output line(s) above for details.

結果は御覧の通りエラーが出て止まってしまいました。

ログを読んでみると、amazon.awsコレクションをインストールするときに、インストール可能なバージョンのリストを取得することに失敗したようです。

調べてみると、ここ に似たようなエラーについてのIssueが上がっており、どうやらこのエラーはAnsibleのバージョンが2.11や2.12の時に発生するようです。

いや、そんな古いバージョンのAnsibleを使っているつもりはないんだけど…、と思いつつ、もう少し詳しく調べてみることにします。

Ansible NavigatorでEEをビルドする際に、contextというディレクトリが作成されます。実行結果の2行目にあるように、このディレクトリにDockerfileが自動生成され、これをビルドすることでEEが生成されることがわかります。

では、そのDockerfileの中身を覗いてみましょう。

$ cat context/Dockerfile
ARG EE_BASE_IMAGE="quay.io/ansible/ansible-runner:latest"
ARG EE_BUILDER_IMAGE="quay.io/ansible/ansible-builder:latest"
ARG PYCMD="/usr/bin/python3"
ARG PKGMGR_PRESERVE_CACHE=""
ARG ANSIBLE_GALAXY_CLI_COLLECTION_OPTS=""
ARG ANSIBLE_GALAXY_CLI_ROLE_OPTS=""

# Base build stage
FROM $EE_BASE_IMAGE as base
USER root
ARG EE_BASE_IMAGE
ARG EE_BUILDER_IMAGE
ARG PYCMD
ARG PKGMGR_PRESERVE_CACHE
ARG ANSIBLE_GALAXY_CLI_COLLECTION_OPTS
ARG ANSIBLE_GALAXY_CLI_ROLE_OPTS
...

先頭行でEE_BASE_IMAGEという変数が定義されていて、その後 FROM $EE_BASE_IMAGE as base となっているので、このEE_BASE_IMAGEがベースのイメージのだということがわかります。

Webブラウザで quay.io/ansible/ansible-runner を開いてみると……、このイメージのlatestタグはイメージ名が stable_2.12-latest のもののようですね。。。最終更新は2年前、つまり、ansible-runnerのイメージは2年更新されておらず、latestでもAnsible 2.12ベースのものでした。

ベースイメージを指定して解決


なぜこのような古いイメージがデフォルトで使用されるのかは不明ですが、この問題を解決することは難しくはないですね。ベースイメージとして、新しいバージョンのAnsibleが使われているものを指定すれば良いのですから。

ドキュメントを読むと、ベースイメージを指定するには execution-environment.yml に以下のように追加すればよいことがわかりました。

build_arg_defaults:
  EE_BASE_IMAGE: <イメージ>:<タグ>

で、ベースイメージを何にするかですが、awx-eeとかでも良いかなと思いましたが、今回はAnsible Lintも入っている creator-ee:latest にしてみます。

build_arg_defaults:
  EE_BASE_IMAGE: ghcr.io/ansible/creator-ee:latest

再度ビルドしてみます。

$ ansible-navigator builder build -m stdout
Running command:
  docker build -f context/Dockerfile -t ansible-execution-env:latest context
Complete! The build context can be found at: /home/mizutani/test_ee/context

ということで、ansible-execution-env:latest というイメージ名(とタグ)でEEがビルドされました。

Ansible Builderを使ったことのある方なら、この出力からもお分かりかと思いますが、Ansible NavigatorでEEをビルドするといっても、実際にはAnsible Navigatorが作ったコンテナ内でAnsible Builderが実行されているだけのようですね。

なお、イメージ名とタグをビルド時に指定したい場合は、(Ansible Builderと同じで)ビルド時に -t <イメージ名>:<タグ> を指定すればOKです(以下は例)。

$ ansible-navigator builder build -m stdout -t my_ee:v1

もちろん、デフォルトのイメージ名でビルドした後に docker tag コマンドで変更しても問題ないです。

作ったEEでPlaybookを実行してみる


EEができたので、さっそく使ってみましょう。

実行するPlaybookは以下のようなものです。

- name: Test Playbook
  hosts: localhost
  tasks:
    - name: Show ansible version
      ansible.builtin.debug: 
        msg: "{{ ansible_version }}"

    - name: Get all installed collections
      ansible.builtin.command: 'ansible-galaxy collection list'
      register: galaxy_result

    - name: Show installed collection list
      ansible.builtin.debug:
        var: galaxy_result.stdout

内容は、EE内のAnsibleのバージョンと、EEにインストールされているコレクションを表示するだけです。

結果は以下のようになりました。

$ ansible-navigator run /mnt/c/Projects/note/temp/site.yml --ee true --eei my_ee:v1 -m stdout
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that
the implicit localhost does not match 'all'

PLAY [Test Playbook] ***********************************************************

TASK [Gathering Facts] *********************************************************
ok: [localhost]

TASK [Show ansible version] ****************************************************
ok: [localhost] => {
    "msg": {
        "full": "2.16.3",
        "major": 2,
        "minor": 16,
        "revision": 3,
        "string": "2.16.3"
    }
}

TASK [Get all installed collections] *******************************************
changed: [localhost]

TASK [Show installed collection list] ******************************************
ok: [localhost] => {
    "galaxy_result.stdout": "\n# /usr/share/ansible/collections/ansible_collections\nCollection              Version\n----------------------- -------\namazon.aws              7.5.0  \nansible.posix           1.5.4  \nansible.windows         2.2.0  \nawx.awx                 23.7.0 \ncommunity.windows       2.2.0  \ncontainers.podman       1.12.0 \nkubernetes.core         3.0.0  \nredhatinsights.insights 1.2.2  \ntheforeman.foreman      4.0.0  "
}

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

ちょっと見づらいですが、requirement.ymlで追加したamazon.awsコレクションとcommunity.windowsコレクションがインストール済みであることが確認できました。期待通りですね。

おわりに


少しトラブルもありましたが、Ansible Navigatorだけを使ってEEの構築ができました。

これまで別々にインストールしていた Ansible Lint やEEをビルドするためのツールであるAnsible Builderなしに、Ansible Navigatorだけでこれらが実行できるのはちょっと嬉しいですね。Ansible Navigatorが今後どのように進化していくのかはわかりませんが、さらに統合が進んでより便利なツールになっていくのかもしれません。面白い機能の追加等がありましたら、紹介記事を書きたいと思います。


執筆者プロフィール:水谷 裕一
大手外資系IT企業で15年間テストエンジニアとして、多数のプロジェクトでテストの自動化作業を経験。その後画像処理系ベンチャーを経てSHIFTに入社。

SHIFTグループ会社「RGA」および「システムアイ」に出向し、インフラ構築の自動化やCI/CD、コンテナ関連の業務に従事した後、2024年3月よりSHIFTのインフラサービスGに配属。

LinuxよりWindowsの方が好き。


IaC支援サービスのご紹介

SHIFTではTerraformやCDKを使ったクラウドインフラ構築の自動化や、Ansibleを使ったサーバOSの設定自動化や構成管理のご支援も行っております。ご依頼・ご相談は下記リンクからお願いします。

お問合せはお気軽に

SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/

SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/

SHIFTの導入事例
https://service.shiftinc.jp/case/

お役立ち資料はこちら
https://service.shiftinc.jp/resources/

SHIFTの採用情報はこちら
https://recruit.shiftinc.jp/career/

PHOTO:UnsplashMax Chen