Kubernetes のイメージを GitLab Agent で自動更新する方法

サーバー
スポンサーリンク

自宅サーバ環境で Kubernetes のイメージを自動更新するCIワークフローを構築する方法を紹介します.

スポンサーリンク

やりたいこと

git push した際,次の3点を自動で行いたい.

  • テスト
  • コンテナイメージのビルドおよびコンテナレジストリへの登録
  • Kubernets 上の Pod のイメージ更新

この際,テストやコンテナイメージの中においては,一般公開したくないデータを気軽に扱えるようにしたいので,自宅サーバでシステム構築することにします.

前提と道具立て

自宅サーバーでのシステム構築するにあたり,下記の前提をおきます.

2番目の項目はセキュリティを維持して運用するコストが無視しがたいためです.この前提の元だと,Let’s Encrypt とかが使えなくなるので,自動的に3番目の者の前提が発生します.

以上を踏まえ,使用するソフトと目的は下記とします.

GitLab
git を軸にした CI ワークフローを回すのに使用します.Docker で動かします.
Docker registry
Kubernetes クラスタ上で動かすコンテナイメージを格納するのに使います.Docker で動かします.
GitLab Runnner
GitLab CI ジョブを走らせるために使用します.Kubernetes クラスタ上で動かします.
GitLab Agent for Kubernetes
GitLab CI ジョブの中から Kubernetes クラスタに対して kubectl コマンドを実行するのに使用します.Kubernetes クラスタ上で動かします.

GitLab と Docker registry は Kubernetes 上で動かすこともでききます.ただ,自宅で Kubernetes を運用する場合はバージョンアップ時にクラスタを再構築する可能性があるので,今回はクラスタ外に設置しました.

自宅 Kubernetes クラスタのバージョンアップ (ずぼら編)
約一年前に構築した自宅 Kubernetes クラスタをバージョンアップした手順のメモです.

Docker registry は GitLab のコンテナの中にはいっているものを使っても良いのですが,GitLab 関連でトラブった際にもレジストリは正常稼働させたいので,今回は別に設定します.

ESXi 等を使って,専用の仮想サーバを立ててその中で Docker を動かすと良いと思います.

なお,Kubernetes のイメージを自動更新する方法としては,Argo CD Image Updater という手段もよく使われているようなのですが,GitLab CI のフローの中で完結させた方が分かりやすいので、今回は GitLab Agent for Kubernetes の方を採用しました.

準備

GitLab Agent for Kubernetes を使うには,GitLab を HTTPS でアクセスできるようにしないといけないので,準備としてプライベートCA(認証局) を作って,サーバー証明書を発行しておきます.

作業手順は以下の通りです.「gitlab.green-rabbit.net」の部分はお手元の環境に置き換えてください.

何をやっているかは参考文献のリンク先が詳しいです.

  1. プライベート CA の運用をサポートしてくれる Easy-RSA をインストール.
  2. 作業用のディレクトリを準備.
  3. 設定ファイルを準備.
  4. プライベートCA(認証局) を初期化.
  5. サーバー用の証明書を発行.

使用するのは生成された次の3つのファイルです.

pki/ca.crt
プライベートCA(認証局) のルート証明書.分かりやすいように,名前を local-ca.crt に変更しておきます.
GitLab コンテナ,GitLab Runner,GitLab Agent にて使用します.
今回は紹介しませんが,Windwos の「信頼されたルート証明機関」に追加することで,ブラウザで表示したときに警告が出なくなります.
pki/issued/gitlab.green-rabbit.net.crt
サーバ証明書.
GitLab コンテナで使用します.
gitlab.green-rabbit.net.key
サーバー秘密鍵.
GitLab コンテナで使用します.

インストールと設定

以降で必要なソフトのインストール手順を準備説明します.
先ほどと同様に「gitlab.green-rabbit.net」の部分は GitLab を設定するホスト名に置き換えてください.

GitLab

  1. カスタムイメージを作成します.

    GitLab Agent を動かすには GitLab が HTTPS でアクセスできる必要があるのですが,
    現状だと GitLab のコンテナの中で動く GitLab Agent Server にプライベートCAのルート証明書を渡す方法がありません.よって,証明書をシステムに仕込んだイメージを作成します.

    「rehash: warning: skipping ca-certificates.crt,it does not contain exactly one certificate or CRL」という警告がでますが,無視して OK です.

  2. ディレクトリと TSL 用のファイルを準備します.
  3. 下記の内容の docker-compose.yml を作成します.

    registry_external_url は,後ほど設置する Docker registry のアドレスを記載しておきます.

    メールの送信とかにも対応したい場合,下記を見ながら適宜追加を行います.

    Configuring a Linux package installation | GitLab
    GitLab product documentation.
  4. 下記のコマンドで起動します.サイトがアクセスできるようになるまで,5分前後かかります.

  5. GitLab にアクセスできるようになったら,下記のコマンドで初期パスワード確認し,ユーザ名 root ログインします.

Docker registry

設置は下記の内容の docker-compose.yml を作成し,docker-compose up すればOK.

上記のようにすると HTTPS ではなく,HTTP でアクセスする形になるので,コンテナイメージを扱うホスト全てで,次の設定をしておきます.「registry.green-rabbit.net」は Docker registry を設置したホスト名です.お手元の環境に合わせて読み替えてください.

/etc/docker/daemon.json
次の内容でファイルを作成します.

もし,既に設定されたホストがある場合は下記のように追加します.
/etc/containerd/config.toml
「[plugins.”io.containerd.grpc.v1.cri”.registry]」という行の少しあとに,4行追加します.

終わったら containerd を再起動しておきます.

GitLab Runnner

基本的には下記の「Install on Kubernetes」に従えば OK です.

Install GitLab Runner Operator | GitLab
GitLab product documentation.

具体的な手順を紹介します.

  1. Operator を使ってインストールします.(Helm でインストールする方法もあります)

    次のように,「Succeeded」となっていればインストール成功です.

  2. 下記のマニフェストを作成して kubectl apply します.

    runner-registration-token には,「Register an instance runner」で取得したトークンを指定します.管理者用メニューを [CI/CD] – [Runners] と辿っていくと右側にでてきます.

    「kind: Secret」には,プライベートCA のルート証明書 local-ca.crt の中身を貼り付けます.

    [runners.kubernetes] 以降の設定は,CI の中で docker コマンドを実行するのに必要になります.

GitLab Agent for Kubernetes

このステップは,GitLab で管理しているプロジェクト毎に実施するので,事前になにかプロジェクトを作っておきます.
作業としては,基本的に下記の「Register the agent with GitLab」に従えば OK です.

Installing the agent for Kubernetes | GitLab
GitLab product documentation.

具体的な手順を紹介します.

  1. チェックアプトしたプロジェクトに,「.gitlab/agents/[任意の名前]」というファイルを作成し,git commit && git push します.[任意の名前] の部分はアルファベット小文字と「-」で構成されていれば何でもOKです.アンダーバー「_」は使えないので注意.
  2. プロジェクトの右側のメニューを [Infrastructure] – [Kubernetes clusters] – [Connect a cluster] と辿っていくと,先ほど追加した[任意の名前] が出てくるので選択肢,Register をクリックします.(下図は,「pod-rollout」というファイル名にしていた場合)

  3. 下記のように表示されるので赤枠の部分をコピー.

  4. kubectl が実行できる環境で,先ほどコピーしたコマンドの末尾に「–set-file config.caCert=/path/to/local-ca.crt」を付けて実行します.「/path/to/local-ca.crt」の部分はプライベートCAのルート証明書のパスに読み替えてください.

  5. 先ほどの GitLab のページで下記のように Connected となっていれば成功です

テスト

先ほど Agent を登録したプロジェクトのトップに .gitlab-ci.yml という名前で次のよう内容のファイルを作成します.

「kimata/e-ink_weather_panel:pod-rollout」の部分は下記で読み替えてください.

  • コロンの前は GitLab のリポジトリのパス
  • コロンの後ろは Agent を登録するときに使った名前

これによって先ほど登録した Agent 経由で Kubernetes クラスタを操作できるようになります.

git commit && git push してからしばらく待って,プロジェクトの右側のメニューを [CI/CD] – [Jobs] と辿り,「passed」と表示されていれば成功です.

なお,kubectl を実行する際に --insecure-skip-tls-verify=true を付けたくない場合は,GitLab のイメージにプライベートCAのルート証明書を追加したのと同様の作業を bitnami/kubectl:latest のイメージに対して行い,そちらのイメージを使うようにすれば OK です.

ハマったポイント

GitLab Agent for Kubernetes のアーキは,GitLab が HTTPS でインターネットで公開されていることを前提としており,プライベートCAのルート証明書を扱う想定をしていないので動くようになるまで苦労しました.

上手くいかない場合「x509: certificate signed by unknown authority 」というエラーが出るのですが,このエラーを出すのが CI ジョブ上の kubectl だけでなく,GitLab イメージ内の GitLab agent server for Kubernetes (KAS) にもあることに気付けるかどうかが鍵でした.

GitLab Agent for Kubernetes のリポジトリにある下記のアーキ図を眺めていたら全てが繋がった感じです.

doc/architecture.md · master · GitLab.org / cluster-integration / GitLab Agent for Kubernetes · GitLab
GitLab Agent for Kubernetes allows to integrate your cluster with GitLab in a secure way.

上の図において kas から GitLab RoR に矢印が伸びているのがポイントです.既存の公式ドキュメントでは,agentk から伸びる矢印でプライベートCAのルート証明書を使う方法(--set-file config.caCert)は書かれていても,このアクセスにおいてが記載されていません.あとは,agentk と kas のソースコードをざっと比較して全てを悟りました.

一応,解決方法は本家のフォーラムにも投げてあります.もしかしたら,私の思い違いとかがあって,もっと良い方法がでてくるかも.

Gitlab agent for Kubernetes - x509: certificate signed by unknown authority
Hi all, I have a Omnibus Gitlab EE 15.10.7-ee.0 running with docker compose on premise It works fine with Kubernetes Run...

参考文献

easy-rsaでプライベートCA(認証局)を作ってオレオレ証明書ではないローカル用TLS証明書の管理をする
プライベートCAを使った証明書の発行についてわかりやすく解説されています.
GitLabにpushされたらGitHubのリポジトリにも反映させる!(ミラーリング)
ローカルの GitLab から GitHub にリポジトリを同期する方法が紹介されています.
ローカルの GitLab に移行すると,リポジトリの完全性をどう保守していくかが気になりますが,ここで紹介されている方法を使えば自動的に同期させるのでそうした心配も不要になります.

GitHub のリポジトリのアドレスを指定するときに HTTPS を使い,ユーザー名を入れるのがポイントです.(GitHub から git clone する際のアドレスだとユーザ名が入っていないので注意)

コメント