周りでGitLab Runnerを使ったExecution Environmentの自動ビルドが急に流行りだしたので、GitHub Actionsを使った自動ビルドを試してみた。
Ansibleの実行環境がコンテナ化し、その定義ファイルとしてexecution-environment.ymlに内容を記述できるようになった時点で試してみたかったけど、業務でさわる機会が全然なく後回しにしてたので、いい機会でした。
実物は以下
EEについては以下も参照
execution-environment.yml
サンプルなので特記事項無し。
ファイルは以下。
--- version: 1 build_arg_defaults: EE_BASE_IMAGE: 'registry.redhat.io/ansible-automation-platform-21/ee-minimal-rhel8:latest' ## require authentication ansible_config: 'ansible.cfg' dependencies: galaxy: requirements.yml python: requirements.txt system: bindep.txt additional_build_steps:
特記事項無しといいつつ、ファイルの内容については以前書いた[Ansible / Podman] もうこのぉ、venvを使った実行環境は終わりだ (Ansible RunnerとAnsible Builderお試し) - zaki work logも参照。
補足 蛇足
追記:「ver1.2だとVersion 3 Formatが使える」は誤り。ドキュメントの記述は
Version 3: Supported by
ansible-builder
versions after1.2
.
なので1.2 より新しい バージョンで対応する、ということっぽい。
追記ここまで。
Ansible Builderのドキュメントによると ansible-builder ver1.2だとVersion 3 Formatが使える (↑前述) ようだけど、ドキュメントの通りにimages
とadditional_build_files
を記述するとunknown yaml keyのエラーが出るので古い書式(Version 1 Format)を使ってる。(2023.04.16時点)
(builder) (main %=) [zaki@cloud-dev2 builder-example]$ ansible-builder --version 1.2.0 (builder) (main %=) [zaki@cloud-dev2 builder-example]$ ansible-builder build ansible_builder.exceptions.DefinitionError: Error: Unknown yaml key(s), {'images', 'additional_build_files'}, found in the definition file. Allowed options are: {'dependencies', 'build_arg_defaults', 'additional_build_steps', 'ansible_config', 'version'}
ansible-builder.readthedocs.io
GitHub Actions
Actionsを起動するための定義ファイルは.github/workflows/main.yml
に記述。
Gitのtagを作成したらそのタイミングで処理を起動し、tag名でイメージビルド、GitHub Container Registryにpushするようにしている。
name: build ee on: push: branches-ignore: - '**' tags: - 'v*' # https://docs.docker.com/build/ci/github-actions/manage-tags-labels/ jobs: build: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 - name: setup ansible builder run: python3 -m pip install ansible-builder - name: create Containerfile run: ansible-builder create - id: meta # https://docs.docker.com/build/ci/github-actions/manage-tags-labels/ uses: docker/metadata-action@v4 with: images: ghcr.io/zaki-lknr/ee-example tags: | type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=semver,pattern={{major}} - name: login github container registry uses: docker/login-action@v2 with: username: zaki-lknr password: ${{ secrets.PERSONAL_TOKEN }} registry: ghcr.io - name: login redhat registry uses: docker/login-action@v2 with: username: ${{ secrets.RH_USERNAME }} password: ${{ secrets.RH_PASSWORD }} registry: registry.redhat.io - name: build & push uses: docker/build-push-action@v4 with: context: context file: context/Containerfile push: true tags: ${{ steps.meta.outputs.tags }}
処理の流れとしては以下の通りで、tagが作成されたらジョブを起動する。
- ビルド環境はUbuntu 22.04
- リポジトリのチェックアウト
- PythonインタプリタとAnsible Builderをセットアップ
ansible-builder build
で直接ビルドせず、create
でContainerfile
を作成- リポジトリのtagをイメージのtagに使用するためのdocker/metadataアクション実行
- docker/loginのアクションでリポジトリへの認証情報作成
- docker/build-pushのアクションでイメージのbuild & pushを実行
細かい内容はGitHub Actionsのドキュメント参照
tagが作成されたら起動
以下で実現
on: push: branches-ignore: - '**' tags: - 'v*'
on: push
だけだと、push
に反応してジョブが走るため、今回はpush
でなくtag
に反応するように記述。そのためにbranches-ignore
でブランチへのpush
を無視するようにしている。
GitHub Actions のワークフロー構文 | on.push.<branches|tags|branches-ignore|tags-ignore>
リポジトリのチェックアウトとビルド環境構築
- uses: actions/checkout@v3 - uses: actions/setup-python@v4 - name: setup ansible builder run: python3 -m pip install ansible-builder
actions/checkout@v3
でリポジトリのチェックアウト、actions/setup-python@v4
でPythonの環境へのインストールを実施。バージョンは特に指定してないのでその時点の最新安定版(のはず。。)
Ansible Builderのインストールはrun
でコマンドを実行する。
Containerfileの作成
- name: create Containerfile run: ansible-builder create
これもrun
を使ってコマンドを実行。
ansible-builder build
でビルドをせずにContainerfile
を生成しているのは、後続の処理で、用意されているGitHub Actions用のDockerアクションでlogin/build/pushを行うため。
もちろん残りの処理もrun
で実装は可能。
ちなみにansible-builder build
の実行で、内部的にはpodman build
でのビルドもできる。
tag名の取り出し
- id: meta # https://docs.docker.com/build/ci/github-actions/manage-tags-labels/ uses: docker/metadata-action@v4 with: images: ghcr.io/zaki-lknr/ee-example tags: | type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=semver,pattern={{major}}
docker/metadata-action@v4
アクションを使用。
このアクションはv1.2.3
形式のtag作成時にlatest
、1.2.3
、1.2
、1
のイメージタグを自動でセットできるようにするための準備。build & push時tagを参照するのは最後の「build & push」の以下の箇所。
tags: ${{ steps.meta.outputs.tags }}
詳細はドキュメントを参照。
- docker/metadata-action: GitHub Action to extract metadata (tags, labels) from Git reference and GitHub events for Docker
- Manage tags and labels with GitHub Actions | Docker Documentation
バージョン表記についてはセマンティック バージョニング 2.0.0 | Semantic Versioningを参照
コンテナレジストリへのログイン
ビルドしたイメージのpush先のコンテナレジストリと、ビルド時のベースイメージであるregistry.redhat.io/ansible-automation-platform-21/ee-minimal-rhel8:latest
をpullするためのRed Hatコンテナレジストリの2箇所へログインしている(Red Hatのコンテナレジストリの認証情報は無料のDeveloper Subscriptionのものを使用)。
ベースイメージをquay.io/ansible/ansible-runner:stable-2.12-devel
等のように認証不要のリポジトリからpullする場合はpush用のみでOK
今回はGitHub Container Registry(ghcr.io)を使用。もちろんDocker HubでもOK
- name: login github container registry uses: docker/login-action@v2 with: username: zaki-lknr password: ${{ secrets.PERSONAL_TOKEN }} registry: ghcr.io - name: login redhat registry uses: docker/login-action@v2 with: username: ${{ secrets.RH_USERNAME }} password: ${{ secrets.RH_PASSWORD }} registry: registry.redhat.io
パスワードなどのSecretデータは、リポジトリの[Settings]->[Secrets and variables]->[Actions]のRepository secretsに登録しておけば、${{ secrets.<シークレット名> }}
で参照できる。
Ansible的にはAAP/AWXの「Credentials (認証情報)」と同様の機能。
複数レジストリへのログインをまとめられたらキレイな気がするけど、公式サイトの記載もこの通りなので必要な回数分実行する必要があると思われ。
GitHub Container Registryの認証情報
GitHub Container Registryの認証情報は、Personal Access Tokensを作成し、それをパスワードとして使用する。
アカウントの[Settings]->[Developer settings]にあるPersonal Access Tokens (Classic)で[Generate new token (classic)]を押下。
Expirationを無期限、scopeはwrite:packages
にチェックを入れて[Generate token]押下で生成する。
(write:packages
を有効にすると、repo
は連動して全て有効になる)
GitHub Container Registryは、サーバーがghcr.io
、ユーザー名にGitHubアカウント名、パスワードに前述のパーソナルトークンを使えばログインできる。
build and push
いよいよbuildとpush・・・といってもdocker/build-push-action
があるので、ビルドのコンテキスト(パス)とContainerfile
をパラメタとして指定すればOK
tag
には前処理で行ったリポジトリのtagから生成した値を参照するように記述する。
- name: build & push uses: docker/build-push-action@v4 with: context: context file: context/Containerfile push: true tags: ${{ steps.meta.outputs.tags }}
これを使用するために前段ではansible-builder build
でなくansible-builder create
でContainerfile
を生成するだけにしている。
参考
- GitHub Actions を理解する - GitHub Docs
- GitHub Actions のワークフロー構文 - GitHub Docs
- GitHub Marketplace · Actions to improve your workflow
- Manage tags and labels with GitHub Actions | Docker Documentation
- Build and push Docker images · Actions · GitHub Marketplace
- タグが打たれたらGitHub Container Registryにイメージをpushする | おそらくはそれさえも平凡な日々
あとブログ記事化してないけれど、GitHub PagesへのMkDocsを使ったサイト生成をGitHub Actionsで自動化したのが以下。
生成しているサイト zaki-lknr.github.io
MkDocsの紹介 zaki-hmkc.hatenablog.com
マルチプラットフォームのビルドもできるみたい。arm64ビルドも欲しいな。。
Multi-platform image with GitHub Actions | Docker Documentation