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