Docker上で動いているMastodonをkubernetesクラスタに移動した作業メモ
本稿のスコープ外
- Kubernetes(以下 k8s)クラスタの構築方法
- Mastodon の初期設定
- kustomize のインストール
※ 多少読み替えて頂ければ、docker ではない Mastodon も移行できるはず
前提条件
- kubectl が実行可能なこと
- kustomize が使用可能なこと
- 以降元 docker コンテナのファイルを持ってこれること
作業手順
実は移行自体はそれほど難しくありません。
移行が必要なのは、PostgreSQL の DB だけです。redis のデータも移行した方がよいですが、
移行しなくてもその時点の Sidekiq のジョブが失われる程度で、恐らく誰も気づきません。
※ 管理者的には、Sidekiq 画面のジョブ数がリセットされるのが残念かな?程度
kubernetes クラスタ上に Pod を生成
Deployment 定義を github に公開しています。
私のインスタンスは、Glitch Edition なので Docker イメージ名が違いますが、基本的に
公開している Deployment をそのまま使用しています。
複数インスタンス持ちなので、myinstance をコピーして foundation としました。
myinstance/kustomize.yaml
は以下のように書き換えました。
namePrefix: myinstance- # Pod名の先頭にmyinstance- をつける
commonLabels:
app: myinstance
resources:
- ../base
configMapGenerator:
- name: config
env: env.production
files:
literals:
env.production
ファイルは稼働中のインスタンスからそのまま持ってきます。
その上で、DB_HOST
REDIS_HOST
を変更します。
base/kustomization.yaml 変更
DB を戻し終わるまでは、Web, Streaming, Sidekiq には起動して欲しくありません。
そのため、一時的に ./base/kustomization.yaml
を変更します。
resources:
- db-service.yaml
- db-pvc.yaml
- db-statefulset.yaml
- web-sidekiq-pvc.yaml
- redis-service.yaml
- redis-pvc.yaml
- redis-deployment.yaml
#- web-service.yaml ここから下をコメントアウト
#- web-deployment.yaml
#- streaming-service.yaml
#- streaming-deployment.yaml
#- sidekiq-deployment.yaml
ここまでできたら、
myinstance ディレクトリで
$ kustomize build | kubectl apply -f -
configmap/myinstance-config-4dm8g6h6gm created
(略)
移行元インスタンス停止
(リハーサルなら止めなくてよい)
DB と Redis コンテナ以外 を停止します。
DB, redis バックアップ取得
# 移行元インスタンスのdockerが動いてるところで
$ docker exec mastodon_db_1 pg_dumpall > pg_dumpall.sql
# このコマンドはredisへのアクセスが停止します。(短時間ですが)
$ docker exec mastodon_redis_1 redis-cli save
OK
$ docker cp mastodon_redis_1:/data/dump.rdb .
pg_dumpall.sql
dump.rdb
ファイルは、kubectl を使用可能な PC にコピーしておいて下さい。
DB バックアップを k8s 上の DB に戻す
$ kubectl cp pg_dumpall.sql myinstance-db-0:pg_dumpall.sql
$ kubectl exec -it myinstance-db-0 sh
$$ psql
root=# \i pg_dumpall.sql
(どばっと、DUMP取込のログが出る)
root=# quit
# SQLファイルを消しておかないとサーバーの容量を食うため(コンテナ再起動で消えますが)
$$ rm pg_dumpall.sql
Redis バックアップを k8s 上の DB に戻す
redis のバックアップは、 /data/dump.rdb を上書きするだけです。
しかし、一つ落とし穴があります。 それは、redis 稼働中に dump.rdb を上書きしても、
redis をシャットダウンする際に上書きされるという罠です。
なので、一旦 redis-server を起動しないようにします。
./base/redis-deployment.yaml
を編集。
<code class="language-yaml:./base/redis-deployment.yaml">(略)
containers:
- name: redis
image: redis:5.0-alpine
command: ["tail", "-f", "/dev/null"] # この行追加(またはコメントアウト解除)
resources:
requests:
memory: "16M"
livenessProbe:
# exec: # ここをコメントアウト
# command:
# - redis-cli
# - ping
(略)
$ kubectl get pod して、 myinstance-redis-* のpod を探す。
$ kubectl cp dump.rdb myinstance-redis-xxxx:dump.rdb_new
$ kubectl exec -it myinstance-redis-xxxx sh
$$ ps aux
PID USER TIME COMMAND
1 root 0:00 tail -f /dev/null # redis-server が動いていないことを確認
52 root 0:00 sh
72 root 0:00 ps aux
$$ ls -lh
-rw-r--r-- 1 redis redis 92 Aug 16 05:06 dump.rdb
-rw-r--r-- 1 501 dialout 5.3M Aug 16 05:28 dump.rdb_new # 所有者が違う!
$$ cp dump.rdb_new dump.rdb
$$ chown redis.redis dump.rdb
一時的に変更した設定ファイルの復元
- 編集した
./base/redis-deployment.yaml
を元に戻します。 - 編集した
./base/kustmization.yaml
を元に戻します。
元に戻したら、いよいよ起動を行います。
kustomize build | kubectl apply -f -
動作確認
とりあえず、 curl [外向きのIP等]:3000
して何かが帰ってくれば OK とします。
リバースプロクシの設定変更
動作確認ができたら、リバースプロクシの設定を変更しましょう。
積み残し
favicon
マウントしないといけないのですが、本稿では色々と事情があり割愛しています。
蛇足
.env.production じゃなくて env.production にリネームしたのなんで?
.env.production
だと ls
したときに表示されないからです。 ls -a
すれば見えますが。
個人的に見えないファイルが重要っていうのはあんまり好きではないので。。単純に好みですね
Discussion