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本体も書き換えます。その他ローカルでテスト予定です。
お疲れさまでした!