GitLab CIジョブの環境構築にaquaを使っている
この記事は GitLab Advent Calendar 2023 の 7日目の記事です。
GitLab CIジョブの環境構築
CI上でTerraformやAWS CLI、kubectlなどさまざまなツールを使って仕事をさせるのですが、環境構築において以下のような課題がありました。
- ツールのインストール方法がまちまち
- 同じツールでもリポジトリによって違ったりさえする
- バージョンを固定していたりしていなかったりする
- バージョンアップが忘れられている
- 手動で更新すること自体が面倒
- 加えて、インストール方法がまちまちなので変更箇所もまちまち
GitLab CIではGitHub Actionsのようにサードパーティーアクションをuseする仕組みもないため、ツールのバージョン管理はよりカオスになりやすい気がします。
aquaって?
公式サイトの紹介そのままですが「宣言的CLIバージョンマネージャー」です。
YAMLファイルにツールのバージョンを「宣言」して管理します。
registries:
- type: standard
ref: v4.93.0 # renovate: depName=aquaproj/aqua-registry
packages:
- name: aws/aws-cli@2.14.1
- name: helm/helm@v3.13.2
- name: helmfile/helmfile@v0.159.0
- name: kubernetes/kubectl@v1.25.9
- name: mikefarah/yq@v4.40.3
aquaで管理することによって以下の恩恵を受けることができます。
- インストール方法が統一できる
- バージョンを固定できる、一箇所で確認できる
- Renovateで簡単に更新ができる(config presetが提供されているため)
aquaの導入方法(詳細割愛)
aquaは公式ドキュメントが充実しています(英語)。
また、作者のShunsuke Suzukiさんが執筆された日本語の入門書もありますので、導入の詳細は割愛します。
簡単にまとめると以下の通りです。
- ローカルにaquaのバイナリを入手
-
aqua initでaqua.yamlを生成 -
aqua g -iで欲しいツールをaqua.yamlに登録 -
aqua.yamlをリポジトリに追加 - CI上でもaquaのバイナリを入手して
aqua i実行 - ツールのダウンロード完了(実行可能になる)
aquaの制約
いろんなパッケージマネージャーに共通することですが、registryに登録されていないツールは管理できません。
aqua gコマンドで表示されないものはstandard registryにはありません。
ほしいものがなかった場合、standard registryであるaqua-registryにコントリビュートして追加するか、local/private registryを作成することになります。
standard registryへの登録例
GitLab CIでaquaを使う
GitLab CIでaquaを使うには、各リポジトリにaqua.yamlを設置するだけでなく、ジョブ本来の仕事にかかる前にaquaそのものをインストールする過程が共通して必要になります。
なので、テンプレートを用意して各リポジトリでそれをincludeすることにします。
aqua自身のインストールに使う共通テンプレート
aqua自身をインストールするためのaqua-installerというツールが用意されています。
シェルスクリプト版とGitHub Actions版があり、シェルスクリプト版を使います。
foo-groups/gitlab-ci-templatesリポジトリに
templates/aqua-installer.gitlab-ci.ymlというファイル名で設置します。
.aqua_installer_before_script:
image:
name: ubuntu:22.04
before_script:
- apt update
- apt install -y curl wget
- curl -sSfL https://raw.githubusercontent.com/aquaproj/aqua-installer/v2.2.0/aqua-installer | bash -s -- -v v2.16.4
- export PATH="${AQUA_ROOT_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/aquaproj-aqua}/bin:$PATH"
- aqua install --only-link
やっていること
- aqua-installer実行の前提となるcurlとwgetを入手
- aqua-installerのv2.2.0を実行し、aquaのv2.16.4をインストール
- aquaのインストール先にPATHを通す
-
aqua.yamlに定義されたツールのLazy Installをする(--only-linkオプション)
Lazy Installをしないとaqua.yamlに書かれたすべてのツールを一気にダウンロードします。
Lazy Installをするとツール本体のダウンロードがツールを最初に呼び出す時点まで後回しにされます。
すべてのジョブでaqua.yamlに書かれたすべてのツールを使うわけではないためLazy Installを利用します。
aqua-installer呼び出し行のRenovateによる自動更新
config presetを利用すると、templates/aqua-installer.gitlab-ci.yml内部のaqua-installerおよびaquaのバージョンも自動更新ができます。
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"github>aquaproj/aqua-renovate-config:installer-script#1.13.0(templates/aqua-installer.gitlab-ci.yml)"
]
}
aqua-installerの引数に指定したaquaバージョンの自動更新
元々config presetはaqua-installerの自動更新に対応していましたが、引数に指定したaquaのバージョン更新には未対応でした。
aqua-renovate-config v1.3.0からaqua自身の自動更新にも対応しました。
テンプレート利用側の.gitlab-ci.yml
作成したテンプレートをincludeしてextendsします。
テンプレートのbefore_scriptでaqua install --only-linkを済ませているので、ジョブで使うコマンドをいきなり実行することができます。
include:
- project: foo-group/gitlab-ci-templates
file: /templates/aqua-installer.gitlab-ci.yml
some-kubectl-job:
extends: .aqua_installer_before_script
script:
- kubectl hogehoge
aquaを利用している感想
抱えていた課題が解消され、見通しのいい環境構築と快適なバージョンアップができるようになりました。
簡単に使い始めることができ、またドキュメントが充実している、アップデートが活発であるためおすすめできるツールだと思います。
フィードバックが早くて厚いため、コントリビューションも非常にしやすいプロジェクトだと思います。
少しだけ乗りこなしのいるところ
aquaの悪いところというわけではなく、実運用してみるまで気づかなかった豆知識みたいなものです。
ブランチがコンフリクトする→グルーピングを活用する
とくに設定しなければ、Renovateはaqua.yamlに書かれた各ツールそれぞれに1つのブランチとマージリクエストを作成します。
1つのMRをマージすると別のMRでコンフリクトが発生することがあり、手動でrebaseするかRenovateを再実行してRenovateにrebaseしてもらうことになります。
CIの待ち時間が長いリポジトリだと少し不便です。
registries:
- type: standard
ref: v4.93.0 # renovate: depName=aquaproj/aqua-registry
packages:
- name: aws/aws-cli@2.14.1
- name: helm/helm@v3.13.2
- name: helmfile/helmfile@v0.159.0
- name: kubernetes/kubectl@v1.25.9
- name: mikefarah/yq@v4.40.3
これに対してはrenovate.json5側でグルーピングを設定し、ブランチとMRをまとめることで回避しています。
"packageRules": [
{
"automerge": true,
"groupName": "automergeable-tools",
"matchPackagePatterns": [
"aws-cli",
"helm",
"helmfile",
"kubectl",
"yq",
]
}
グルーピングの留意事項
一般にたくさんまとめるほどCIが壊れやすくなり、原因特定も大変になることには注意します。
Lazy Installと同時実行→実行前にインストールを済ませる
共通テンプレートでLazy Installを有効にしている影響で、複数のディレクトリで同時にterraformを実行するようなジョブが失敗しました。
「最初の呼び出し」が同時多発的に行われるためダウンロードも同時に複数回試みられ、ファイルが破損したのが原因でした。
そのようなジョブでは同時実行を始める前にterraform versionコマンドなどで先にダウンロードを済ませておくことで問題を回避しました。
Discussion