akkomaを自分でビルドしてarm64/amd64が混在したkubernetesクラスタにデプロイする

## 経緯

自宅でkubernetesクラスタを構築し、長年の課題だった自宅サーバの可用性が大幅に向上した。これでやっとサービスの公開に移れる。ということで、今回は前々から立てたかったmastodon互換[^mastodon]のおひとり様インスタンスとしてakkoma[^akkoma]インスタンスを構築することにした。

で、構築の過程で以下のような問題が発生したのでそれについてまとめておく。

- 公式のdocker イメージがない
  => 自前でのイメージのビルド、およびクラスタからアクセスできる場所への公開が必要
- 初期設定が自動化できない
  => ボリュームをマウントした状態でコンテナ内での作業が必要

## 本記事で扱うこと
- マルチアーキテクチャなイメージのビルド
- giteaをコンテナレジストリとしたイメージのプッシュ・プル
- kubectl runでボリュームをマウントして作業する

## 本記事で扱わないこと
- Dockerfileの書き方
  公式のがあるので不要
- akkoma用のpostgresqlの構築
- kubernetes crusterの構築
- kubernetes 永続ボリュームの準備
- akkomaの初期設定の詳細
  こちらを参照
  [Installing in Docker - Akkoma Documentation](https://docs.akkoma.dev/stable/installation/docker_en/)

## バージョン情報
- kubernetes: 1.28.2
- podman: 4.6.2
- akkoma: 3.10.4

## マルチアーキテクチャなイメージのビルト

### gitリポジトリのpull、チェックアウト

公式のリポジトリに`Dockerfile`も入っているので、クローンする

```
$ git clone https://akkoma.dev/AkkomaGang/akkoma.git -b stable
$ cd akkoma
```

今後のことを考え、イメージはちゃんとバージョン管理しておきたかったので、確認する。

```
$ git log --oneline --graph
* ebfb617b2 (HEAD -> stable, origin/stable) Update .woodpecker/build-amd64.yml
* 0af8e9313 (tag: v3.10.4) bump version
* 98a64ab14 Mix format
* 94d1af2c4 Disallow nil hosts in should_federate
* 43c5fd5db bullseye build (you owe me for this one)
```
厳密には１コミット進んでいるが、v3.10.4が最新のステーブルのバージョンと考えてよさそう。

### イメージ/マニフェストのビルド

我が家のクラスタはamdとarmが混在している[^raspberrypi]ため、マルチアーキテクチャなイメージを作る。

```
$ podman buildx build --platform linux/arm64,linux/amd64  --manifest akkoma:v3.10.4  --format docker .
```

## gitea リポジトリへのプッシュ・デプロイ


### イメージのdocker互換レジストリへのアップロード

作ったマニフェストをkubernetesクラスタからアクセスできるレジストリにアップロードする。
今回はすでに稼働中のプライベートなgiteaに掲載することにした。

```
$ podman manifest push --format v2s2 akkoma:v3.10.4 gitea.example.com/fluo10/akkoma:v3.10.4
```

### kubernetesへのデプロイ

```
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: akkoma
  name: akkoma-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: akkoma
  template:
    metadata:
      labels:
        app: akkoma
    spec:
      containers:
      - name: akkoma
        image: gitea.example.com/fluo10/akkoma:v3.10.4
        ports:
        - containerPort: 4000
          name: akkoma-port
        volumeMounts:
        - mountPath: /opt/akkoma
          name: akkoma-volume
          subPath: akkoma
        env:
          - name: MIX_ENV
            value: prod
          - name: DB_USER
            value: akkoma
          - name: DB_NAME
            value: akkoma
          - name: DB_HOST
            value: postgresql.example.com
      volumes:
      - name: akkoma-volume
        persistentVolumeClaim:
          claimName: akkoma-pvc
```



これでイメージがプルできることは確認できた。
まだ初期設定ができていないので、このままでは、当然ちゃんとは動かない。

## volumeをマウントしながらコンテナで作業

akkomaの初期設定はコマンドで行う必要がある。kubenetesの場合は当然永続ボリュームをマウントしたうえでコンテナ内で実行するという形になるのだが、`docker run` や`podman run`とちがい、kubectl runはボリュームをマウントするためのオプションがない。代わりに`--overrides`というオプションでコンテナの設定を渡せるのだが、このオプションはファイルではなく平文で指定する必要がありどうしても長くなる。
ということで、以下のようなシェルスクリプトにした。

### 
```
#!/bin/bash
kubectl run akkoma-manage -i --namespace public --rm -ti --overrides='
{
  "metadata": {
    "namespace": "public"
  },
  "spec": {
    "containers": [
      {
        "name": "akkoma",
        "image": "gitea.example.com/fluo10/akkoma:v3.10.4",
        "stdin": true,
        "stdinOnce": true,
        "args": [
          "sh"
        ],
        "tty": true,
        "volumeMounts": [{
          "mountPath": "/opt/akkoma",
          "name": "akkoma-volume",
          "subPath": "akkoma"
        }]
      }
    ],
    "volumes": [{
      "name":"akkoma-volume",
      "persistentVolumeClaim": {
        "claimName": "akkoma-pvc"
      }
    }]
  }
}
'  --image=gitea.example.com/fluo10/akkoma:v3.10.4 --restart=Never 
```

これを実行すると、`sh`でコンテナ内に入ることができる。
あとは公式のマニュアルに沿って初期設定し、`pod`を再起動（削除）すれば動く。

## 参考
- [podman でマルチアーキテクチャ/マルチプラットフォーム対応コンテナイメージを作成する - Qiita](https://qiita.com/2fbCvmiYKX/items/ad56d630d5004a21e318)
- [PodmanでMulti-archビルドを試す - とことんDevOps | 日本仮想化技術のDevOps技術情報メディア](https://devops-blog.virtualtech.jp/entry/20220922/1663814898)
- [Create kubernetes pod with volume using kubectl run - Stack Overflow](https://stackoverflow.com/questions/37555281/create-kubernetes-pod-with-volume-using-kubectl-run)
- [https://gist.github.com/ctaggart/c372783291162d9c0b8e40441ab14845](https://gist.github.com/ctaggart/c372783291162d9c0b8e40441ab14845)

[^mastodon]: mastodon互換というとmastodonが標準という誤解を招きそうで良くないとは思うが、一番メジャーなので。
[^akkoma]: akkomaはpleromaの派生。選んだ理由はmastodonがおひとり様サーバーとしてはメモリを使いすぎるのと、[linuxカーネルの開発チームが採用した](https://www.reddit.com/r/fediverse/comments/11s7gkh/the_linux_kernel_team_joined_the_fediverse_with/)とのことで、十分にステーブルだろうという推測。

[^raspberrypi]: といってもワーカーノードは現時点ではすべてラズパイではあるが。