Kubernetesを動かす(4) Misskey本体+PostgresOperator+Pgpool+Redis Operator編
完成しました!!
こちらはちょっと複雑な感じですが、あとでシンプルな構成なk8s+misskey鯖の立て方を別記事で載せるかも?
MisskeyはMisskey本体(web)+PostgreSQL(データーベース)+Redisで動いているのでデーターベースやRedisを冗長化しつつ構成してみます。
データーベースの作成
まずk8s上でPostgreSQLを冗長化してくれるPostgres Operatorを導入します。こちらが自動フェイルオーバー(データーベースが落ちたとき自動で復旧する)やDBのバックアップなどを担当してくれます。
Zalando Postgres Operatorのデプロイ
Percona Operatorを使用する予定でしたがPostgreSQL本体にpgroonga拡張を導入したい関係でZalandoになりました。使用するPostgreSQLイメージがSpiloというPostgreSQL+patroniで自分でビルドできるので、Dockerfileを弄ればpgroongaがインストールできます。
Percona Operatorを弄ったときの備忘録はこちらへ
公式のリポジトリをcloneします。
git clone https://github.com/zalando/postgres-operator.git
cd postgres-operator
manifests/configmap.yamlにバックアップ先の設定などを記述するので編集します。
パラメータの説明はこちら
MiniOを使用する場合WAL-Gを使用する必要があるとのこと
# デフォルトのmanifests/configmap.yamlに下記を追加
WAL_S3_BUCKET: test
WAL_BUCKET_SCOPE_PREFIX: ""
WAL_BUCKET_SCOPE_SUFFIX: ""
USE_WALG_BACKUP: "true"
USE_WALG_RESTORE: "true"
BACKUP_SCHEDULE: '00 10 * * *'
AWS_ACCESS_KEY_ID: アクセスキー
AWS_SECRET_ACCESS_KEY: シークレットキー
AWS_S3_FORCE_PATH_STYLE: "true"
AWS_ENDPOINT: https://img.estampie.work
AWS_REGION: "us-east-1"
WALG_DISABLE_S3_SSE: "true"
BACKUP_NUM_TO_RETAIN: "5"
CLONE_USE_WALG_RESTORE: "true"
できたら下記でデプロイ
kubectl create -f manifests/configmap.yaml
kubectl create -f manifests/operator-service-account-rbac.yaml
kubectl create -f manifests/postgres-operator.yaml
kubectl create -f manifests/api-service.yaml
さらに下記でダッシュボードもインストールできます。NodePortサービスを作成するかkubectl port-forward --address 0.0.0.0 svc/postgres-operator-ui 8081:80
を実行中にhttp://マスターノードのIP:8081/でアクセスできます。
kubectl apply -f ui/manifests/
PostgreSQLデーターベースのデプロイ
データーベースを作成するためにpostgres.yamlを作成します。(名前は適当)
最低限必要な設定はminimal-postgres-manifest.yamlに、他に設定出来る項目はcomplete-postgres-manifest.yamlに書かれているので参考にします。
apiVersion: "acid.zalan.do/v1"
kind: postgresql
metadata:
name: mypg
spec:
teamId: "misskey"
volume:
size: 5Gi # DBサイズ
numberOfInstances: 2 # レプリカ数
users:
DBユーザー名:
- superuser # この辺はroleを付与
- createdb
databases:
misskeydb: DBユーザー名
postgresql:
version: "15"
parameters: # Expert section
shared_buffers: "32MB"
max_connections: "10"
log_statement: "all"
できたら下記でデプロイ
kubectl create -f postgres.yaml
DBパスワードはランダムに生成されるので
kubectl get secret DBユーザー名.mypg.credentials.postgresql.acid.zalan.do -o jsonpath="{.data.password}" | base64 -d
でデコードしたものを使用するか、自分で設定したい場合はkubectl exec -it pod名 -- /bin/bash
でmypg-0の中に入ってpostgresユーザーでDBにログインして設定します。
# postgresユーザーのパスワードを取得
kubectl get secret postgres.mypg.credentials.postgresql.acid.zalan.do -o jsonpath="{.data.password}" | base64 -d
# pod内部で行う
psql -h mypg -U postgres
ALTER USER DBユーザー名 WITH PASSWORD 'DBパスワード';
自分で設定した場合はSecretも更新します。
kubectl patch secret DBユーザー名.mypg.credentials.postgresql.acid.zalan.do -p '{"stringData":{"password":"DBパスワード"}}'
Pgpool-IIのデプロイ
負荷分散はPgpool-IIにやってもらいます。pgpoolを通すと自動で書き込みをプライマリに、リードレプリカとしてreplicaにアクセスを分散させられます。
pgpool.yaml
pgpool本体です。
apiVersion: apps/v1
kind: Deployment
metadata:
name: pgpool
spec:
replicas: 1
selector:
matchLabels:
app: pgpool
template:
metadata:
labels:
app: pgpool
spec:
containers:
- name: pgpool
image: pgpool/pgpool:4.4.3
env:
- name: PGPOOL_PARAMS_BACKEND_HOSTNAME0
value: "mypg"
- name: PGPOOL_PARAMS_BACKEND_PORT0
value: "5432"
- name: PGPOOL_PARAMS_BACKEND_WEIGHT0
value: "1"
- name: PGPOOL_PARAMS_BACKEND_FLAG0
value: "ALWAYS_PRIMARY|DISALLOW_TO_FAILOVER"
- name: PGPOOL_PARAMS_BACKEND_HOSTNAME1
value: "mypg-repl"
- name: PGPOOL_PARAMS_BACKEND_PORT1
value: "5432"
- name: PGPOOL_PARAMS_BACKEND_WEIGHT1
value: "1"
- name: PGPOOL_PARAMS_BACKEND_FLAG1
value: "DISALLOW_TO_FAILOVER"
- name: PGPOOL_PARAMS_FAILOVER_ON_BACKEND_ERROR
value: "off"
- name: PGPOOL_PARAMS_ENABLE_POOL_HBA
value: "off"
- name: PGPOOL_PARAMS_SSL
value: "on"
- name: POSTGRES_USERNAME
valueFrom:
secretKeyRef:
name: DBユーザー名.mypg.credentials.postgresql.acid.zalan.do
key: username
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: DBユーザー名.mypg.credentials.postgresql.acid.zalan.do
key: password
- name: PGPOOL_ENABLE_POOL_PASSWD
value: "true"
- name: PGPOOL_SKIP_PASSWORD_ENCRYPTION
value: "false"
---
apiVersion: v1
kind: Service
metadata:
name: pgpool
spec:
selector:
app: pgpool
ports:
- name: pgpool-port
protocol: TCP
port: 9999
targetPort: 9999
kubectl get service
コマンドでプライマリとレプリカのサービス名がわかるのでそれぞれPGPOOL_PARAMS_BACKEND_HOSTNAME0,PGPOOL_PARAMS_BACKEND_HOSTNAME1に設定します。
できたらデプロイ
kubectl apply -f pgpool.yaml
Redis
Redisをを作成します。Misskey Hubのスケールアウトを参考にPub/Subとジョブキューを別podにしています。
redis.yaml
# Main
apiVersion: v1
kind: Service
metadata:
name: redis
spec:
selector:
app: redis
ports:
- protocol: TCP
port: 6379
targetPort: 6379
---
# Pub/Sub
apiVersion: v1
kind: Service
metadata:
name: redis-pubsub
spec:
selector:
app: redis-pubsub
ports:
- protocol: TCP
port: 6379
targetPort: 6379
---
# ジョブキュー
apiVersion: v1
kind: Service
metadata:
name: redis-jobqueue
spec:
selector:
app: redis-jobqueue
ports:
- protocol: TCP
port: 6379
targetPort: 6379
---
# main
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
spec:
replicas: 2
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7-alpine
volumeMounts:
- name: redis-data
mountPath: /data
volumeClaimTemplates:
- metadata:
name: redis-data
spec:
storageClassName: rook-ceph-block
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
---
# Pub/Sub
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis-pubsub
spec:
replicas: 1
selector:
matchLabels:
app: redis-pubsub
template:
metadata:
labels:
app: redis-pubsub
spec:
containers:
- name: redis-pubsub
image: redis:7-alpine
volumeMounts:
- name: redis-pubsub-data
mountPath: /data
volumeClaimTemplates:
- metadata:
name: redis-pubsub-data
spec:
storageClassName: rook-ceph-block
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
---
# ジョブキュー
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis-jobqueue
spec:
replicas: 1
selector:
matchLabels:
app: redis-jobqueue
template:
metadata:
labels:
app: redis-jobqueue
spec:
containers:
- name: redis-jobqueue
image: redis:7-alpine
volumeMounts:
- name: redis-jobqueue-data
mountPath: /data
volumeClaimTemplates:
- metadata:
name: redis-jobqueue-data
spec:
storageClassName: rook-ceph-block
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
kubectl create -f redis.yaml
Misskey本体のデプロイ
とりあえず公式イメージで
misskey-config.yaml
設定ファイルです。元々の/misskey/.config/default.ymlの内容をここに書きます
apiVersion: v1
kind: ConfigMap
metadata:
name: misskey-config
data:
default.yml: |
# Misskey configuration
url: https://mymiss.local/
port: 3000
db:
host: pgpool
port: 9999
db: misskeydb
user: DBユーザー名
pass: DBパスワード
dbReplications: false # pgpoolを使用する場合pgpookが行うので不要
redis:
host: redis
port: 6379
redisForPubsub:
host: redis-pubsub
port: 6379
redisForJobQueue:
host: redis-jobqueue
port: 6379
id: 'aid'
proxyBypassHosts:
- api.deepl.com
- api-free.deepl.com
- www.recaptcha.net
- hcaptcha.com
- challenges.cloudflare.com
signToActivityPubGet: true
misskey.yaml
misskeyは最終的には自分でビルドしたものを使いますがとりあえず作成済みイメージで
apiVersion: v1
kind: Service
metadata:
name: web
spec:
type: NodePort
selector:
app: web
ports:
- name: http
protocol: TCP
port: 3000
targetPort: 3000
nodePort: 30100
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: misskey-web
spec:
replicas: 1
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: "50%"
maxSurge: "50%"
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
securityContext:
fsGroup: 1000
containers:
- name: web
image: misskey/misskey:latest
envFrom:
- configMapRef:
name: misskey-config
env:
volumeMounts:
- mountPath: /misskey/files
name: misskey-files
- mountPath: /misskey/.config
name: misskey-config
ports:
- containerPort: 3000
resources:
limits:
cpu: "2"
command: ["pnpm", "run", "migrateandstart"]
volumes:
- name: misskey-config
configMap:
name: misskey-config
- name: misskey-files
persistentVolumeClaim:
claimName: pvc-misskey-files
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-misskey-files
spec:
storageClassName: rook-ceph-block
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
できたらデプロイ
kubectl apply -f misskey-config.yaml
kubectl apply -f misskey.yaml
完成
kubectl logs pod名
でログを確認しつつ、データーベースのマイグレーションが終了したらマスターノードのマシンからcurl
コマンドでアクセスしてみます。

やった~👍
ホストOS側のブラウザでも確認してみます。

デプロイできました。やったね🎉
終わりに
DB接続周りで結構躓きましたがとりあえずデプロイできました。
次はPostgreSQLイメージのSpiloのDockerfileにPgroonga拡張インストールを追加してカスタムイメージにして読み込ませます。また、pgroonga拡張を導入した検索にMisskey本体も書き換えます。その他ローカルでテスト予定です。
お疲れさまでした!