Mastodon のコンテナイメージを作成する Kubernetes の Job を作った
概要
これまでは Docker Compose 環境を使っていたので、手元でコンテナイメージを作りたい時は docker build .
すれば良かったのですが、今後、Kuberenets を使い倒していきたいことから、Kubernetes 環境の中でコンテナイメージを作れるようにしたいと考えて試行錯誤してみました。
コンテナイメージを作りたい Mastodon は公式リポジトリの中で Dockerfile を提供してくれていますので、これをそのまま使っていく方向で実装しています。
全体イメージ
出てくるコンポーネントの説明
- Job : コンテナイメージのビルド処理だけをワンショットで実行する Pod を作成する
- PVC / PV : 過去に作成したコンテナイメージなどをキャッシュして置くための永続ストレージ領域
- ConfigMap : 具体的なビルド処理を記載したシェルスクリプト(ファイル)を持たせておく
- Secret : Harbor(プライベートのコンテナレジストリ)に push するためのパスワードなどの機密情報
Namespace
今回作成する各種のリソースの入れ物となる Namespcae を定義しておきます。
kind: Namespace
apiVersion: v1
metadata:
name: mastodon-image-builder
labels:
name: mastodon-image-builder
Job
実行する Pod (Container) の枠組みを定義しています。
この Pod は 2つのコンテナーを同居させているのが工夫ポイントです。
- GitHub リポジトリから Mastodon を
git clone
してきて、docker build
コマンドを投げ込むための Ubuntu コンテナ - Ubuntu コンテナからの要求に応じて Docker サービスを実行する(Docker in Kubernetes)ための DIND コンテナ ※ DIND = Docker in Docker
apiVersion: batch/v1
kind: Job
metadata:
name: image-builder
namespace: mastodon-image-builder
spec:
template:
spec:
restartPolicy: Never
containers:
- image: docker:git
name: ubuntu
command: ['sh', '/data/build.sh'] # ConfigMap のシェルをキックする
env:
- name: DOCKER_HOST
value: tcp://localhost:2375
envFrom:
- secretRef:
name: secret
volumeMounts: # ConfigMap のシェルスクリプトをマウントしている
- name: build-sh
mountPath: /data
- name: dind-daemon
image: docker:dind
env:
- name: DOCKER_TLS_CERTDIR
value: ""
volumeMounts:
- name: dind-var-lib-docker
mountPath: /var/lib/docker
securityContext:
privileged: true
volumes:
- name: dind-var-lib-docker
persistentVolumeClaim:
claimName: docker-cache
- name: build-sh
configMap:
name: build.sh
ConfigMap
ビルド処理を行う Pod にマウントされるシェルスクリプトを保持しています。
Job 定義と分けて個別に持たせることで、シェルスクリプトのメンテナンスがちょっとだけ楽になります。
apiVersion: v1
kind: ConfigMap
metadata:
name: build.sh
namespace: mastodon-image-builder
data:
build.sh: |
set -e
# Mastodon 公式リポジトリをクローンしてくる
git clone https://github.com/mastodon/mastodon.git
cd mastodon
# DinDが起動してくるまでちょっと待つ
sleep 10
# BuildKit を有効化して docker build する
BUILD_DATE=$(date -u +"%Y%m%d-%H%M")
VCS_REF=$(git rev-parse --short HEAD)
export DOCKER_BUILDKIT=1
docker build --build-arg BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ") --build-arg VCS_REF=${VCS_REF} -t ${IMAGE_NAME} -t ${IMAGE_REGISTRY}/${PROJECT_NAME}/${IMAGE_NAME}:${BUILD_DATE} -t ${IMAGE_REGISTRY}/${PROJECT_NAME}/${IMAGE_NAME}:latest .
# Harbor にログインして、作成したコンテナイメージを push する
echo "${BOT_PASS}" | docker login https://${IMAGE_REGISTRY} --username ${BOT_NAME} --password-stdin
docker push -a ${IMAGE_REGISTRY}/${PROJECT_NAME}/${IMAGE_NAME}
PersistentVolumeClaim
Docker サービスが利用する /var/lib/docker ディレクトリ配下を永続化して、ビルド処理の時に実行済みの処理を省略するためのキャッシュ用となるボリュームの定義。
内容的には LocalHostPath でも十分な程度の要件ですが、TrueNAS の iSCSI 領域に保持ししたら予想外に速度が出たので外出ししています。
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: docker-cache
namespace: mastodon-image-builder
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 32Gi
Secret
コンテナイメージのビルド処理の中で使う環境変数や、Harbor へ push する時に利用するキー情報を保持させています。
apiVersion: v1
kind: Secret
metadata:
name: secret
namespace: mastodon-image-builder
stringData:
IMAGE_NAME: mastodon
PROJECT_NAME: mastodon
IMAGE_REGISTRY: registry.home.wirednet.jp
BOT_NAME: "robot$mastodon_build_bot"
BOT_PASS: "zxcvbhjkl....qwertyui1234567890"
実行する
Job リソースを作成すると、自動的に Pod を作成して指定されたシェルスクリプトを実行しはじめます。
$ kubectl apply -f job.yml
実行中の処理の様子は、kubectl logs
で見ることが出来ます。
$ kubectl -n mastodon-image-builder logs -f jobs/image-builder
シェルスクリプトの処理が終わったら、Harbor にビルドされたコンテナイメージが格納されていました。
(何度もテスト実行しているので同じハッシュ値にタグがたくさん付いていますが……)
Discussion