2020/05/25

GitlabをGKEで導入して、バージョンをupgradeする

gitlabgkek8s

概要

Titleの通りですが、OSSのソースコード管理ツールであるGitLabをkubernetes上にデプロイをしました。
以前もGitLabを使っていたのですが、バージョンが少し古かったので、新しいものにアップグレードしました。
バージョンのアップグレードは、使っていたデータも引き継ぐ必要があり、dbのmigrationが必要になったので、
そちらも実施しました。

実施事項

  • こちらの記事で作ったGKEクラスター上にGitLabをdeployしました。
  • また、gitlabのバージョンアップを行いました。

参考になったドキュメントやコード

k8sのデプロイ内容詳細

事前準備

データバックアップ

以前使っていたgitlabサーバー関連のデータのバックアップをしました。
gitlab関連のデータはcompute diskを使って、保存していたので、compute diskのスナップショットを作成しました。

その他

  • gitlabのDocker imageを作成
  • gitlab用のpostgresqlのDocker imageを作成
  • gitlab用のredisのDocker imageを作成
  • gitlab server用にstatic ipアドレスを作成
  • gitlab postgreqlデータ用のcompute diskを作成(空のdisk / 後ほど、手動でデータをrestore)

gitlab redisデータ用のcompute diskを作成

以下のような感じで、snapshotから新しいcompute diskを作成しました。

gcloud beta compute disks create gitlab-redis \
  --project project-new \
  --type=pd-ssd \
  --size=10GB \
  --source-snapshot projects/project-old/global/snapshots/snapshot-gitlab-redis-20200525 \
  --resource-policies=projects/project-new/regions/my-resion/resourcePolicies/my-snapshot-rule-name

gitlab serverデータ用のcompute diskを作成

以下のような感じで、snapshotから新しいcompute diskを作成しました。

gcloud beta compute disks create gitlab-server \
  --project project-new \
  --type=pd-ssd \
  --size=10GB \
  --source-snapshot projects/project-old/global/snapshots/snapshot-gitlab-server-20200525 \
  --resource-policies=projects/project-new/regions/my-resion/resourcePolicies/my-snapshot-rule-name

note

各種Docker imageはgithub.com/sameersbnさんのものを参考にしながら作成しました。

k8sへのデプロイ

namespace

apiVersion: v1
kind: Namespace
metadata:
  name: gitlab

secrets

apiVersion: v1
kind: Secret
metadata:
  name: gitlab-server
  namespace: gitlab
type: Opaque
data:
  db-key-base: <random-base64-encoded-string-here>
  secret-key-base: <random-base64-encoded-string-here>
  opt-key-base: <random-base64-encoded-string-here>
---
apiVersion: v1
kind: Secret
metadata:
  name: postgresql
  namespace: gitlab
type: Opaque
data:
  password: <base64-encoded-string-here>
---
apiVersion: v1
kind: Secret
metadata:
  name: sendgrid
  namespace: gitlab
type: Opaque
data:
  apiKey: <sendgrid-api-key-base64-encoded-string-here>
---
apiVersion: v1
kind: Secret
type: Opaque
metadata:
  name: internal-tls
  namespace: gitlab
data:
  # nginxで使うsslのcrtファイルの中身をbase64エンコードします
  tls_certificate_chain: <base64-encoded-string-here>
  # nginxで使うsslのkeyファイルの中身をbase64エンコードします
  tls_certificate_key: <base64-encoded-string-here>
  # you can generate tls_dhparam by `openssl dhparam 2048 -out tls_dhparam`
  tls_dhparam: <base64-encoded-string-here>

config map

apiVersion: v1
kind: ConfigMap
metadata:
  name: gitlab-server
  namespace: gitlab
data:
  gitlab-host: "gitlab.your-domain.com"
  gitlab-email: "[email protected]"
  gitlab-email-reply-to: "[email protected]"
  gitlab-email-incoming-email-address: "[email protected]"
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: postgresql
  namespace: gitlab
data:
  user: gitlab
  db-name: gitlabhq_production

redis

apiVersion: v1
kind: PersistentVolume
metadata:
  name: gitlab-redis
spec:
  storageClassName: gitlab-redis
  capacity:
    storage: 10Gi # <- 事前準備で作成した compute disk のサイズ
  accessModes:
    - ReadWriteOnce
  gcePersistentDisk:
    pdName: gitlab-redis # <- 事前準備で作成した compute disk の名前
    fsType: ext4
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: redis
  namespace: gitlab
spec:
  storageClassName: gitlab-redis
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
  namespace: gitlab
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      name: redis
      labels:
        app: redis
        node: management-suite
    spec:
      containers:
        - name: redis
          image: your-gitlab-redis-image-name
          ports:
            - name: redis
              containerPort: 6379
          volumeMounts:
            - mountPath: /var/lib/redis
              name: redis
          livenessProbe:
            exec:
              command:
                - redis-cli
                - ping
            initialDelaySeconds: 30
            timeoutSeconds: 5
          readinessProbe:
            exec:
              command:
                - redis-cli
                - ping
            initialDelaySeconds: 5
            timeoutSeconds: 1
      volumes:
        - name: redis
          persistentVolumeClaim:
            claimName: redis

postgresql

apiVersion: v1
kind: PersistentVolume
metadata:
  name: gitlab-postgresql
spec:
  storageClassName: gitlab-postgresql
  capacity:
    storage: 10Gi # <- 事前準備で作成した compute disk のサイズ
  accessModes:
    - ReadWriteOnce
  gcePersistentDisk:
    pdName: gitlab-postgresql # <- 事前準備で作成した compute disk の名前
    fsType: ext4
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgresql
  namespace: gitlab
spec:
  storageClassName: gitlab-postgresql
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgresql
  namespace: gitlab
spec:
  replicas: 1
  selector:
    matchLabels:
      app: postgresql
  template:
    metadata:
      name: postgresql
      labels:
        app: postgresql
        node: management-suite
    spec:
      containers:
        - name: postgresql
          image: your-gitlab-postgresql-image-name
          env:
            - name: DB_USER
              valueFrom:
                configMapKeyRef:
                  name: postgresql
                  key: user
            - name: DB_PASS
              valueFrom:
                secretKeyRef:
                  name: postgresql
                  key: password
            - name: DB_NAME
              valueFrom:
                configMapKeyRef:
                  name: postgresql
                  key: db-name
            - name: DB_EXTENSION
              value: pg_trgm
          ports:
            - name: postgres
              containerPort: 5432
          volumeMounts:
            - mountPath: /var/lib/postgresql
              name: postgresql
          livenessProbe:
            exec:
              command:
                - pg_isready
                - -h
                - localhost
                - -U
                - postgres
            initialDelaySeconds: 30
            timeoutSeconds: 5
          readinessProbe:
            exec:
              command:
                - pg_isready
                - -h
                - localhost
                - -U
                - postgres
            initialDelaySeconds: 5
            timeoutSeconds: 1
      volumes:
        - name: postgresql
          persistentVolumeClaim:
            claimName: postgresql
---
apiVersion: v1
kind: Service
metadata:
  name: postgresql
  namespace: gitlab
spec:
  ports:
    - name: postgres
      port: 5432
      targetPort: postgres
  selector:
    app: postgresql

デプロイ後に前のデータのdumpをとってからrestoreする。
今回はdbの名前やuser名、disk spaceのsizeを変更しているので、このような対応を取りました。

data restore
  1. kubectl exec コマンドで、旧postgresqlのpodにsshする
  2. pg_dump コマンドで、sql文を出力
  3. kubectl cp コマンドでローカルに持ってくる
kubectl cp postgresql-pod-name:/path/to/pg_dump/output ~/Desktop/gitlab_backup.sql
  1. kubectl cpで新postgresqlのpodにdumpファイルをアップロードする
kubectl cp ~/Desktop/gitlab_backup.sql postgresql-pod-name:/path/to/pg_dump/gitlab_backup.sql -n gitlab
  1. kubectl exec コマンドで、新postgresqlのpodにsshする
  2. restoreする
psql -U gitlab gitlabhq_production < gitlab_backup.sql
  1. データを確認
psql -U gitlab gitlabhq_production

gitlab server

apiVersion: v1
kind: PersistentVolume
metadata:
  name: gitlab-server
spec:
  storageClassName: gitlab-server
  capacity:
    storage: 10Gi # <- 事前準備で作成した compute disk のサイズ
  accessModes:
    - ReadWriteOnce
  gcePersistentDisk:
    pdName: gitlab-server  # <- 事前準備で作成した compute disk の名前
    fsType: ext4
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: gitlab-server
  namespace: gitlab
spec:
  storageClassName: gitlab-server
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: gitlab-server
  namespace: gitlab
spec:
  replicas: 1
  selector:
    matchLabels:
      app: gitlab-server
  template:
    metadata:
      name: gitlab-server
      labels:
        app: gitlab-server
        node: management-suite
    spec:
      containers:
      - name: gitlab-server
        image: your-gitlab-server-image-name
        env:
          - name: DEBUG
            value: "false"
          - name: TZ
            value: UTC
          - name: GITLAB_TIMEZONE
            value: UTC
          - name: GITLAB_SECRETS_DB_KEY_BASE
            valueFrom:
              secretKeyRef:
                name: gitlab-server
                key: db-key-base
          - name: GITLAB_SECRETS_SECRET_KEY_BASE
            valueFrom:
              secretKeyRef:
                name: gitlab-server
                key: secret-key-base
          - name: GITLAB_SECRETS_OTP_KEY_BASE
            valueFrom:
              secretKeyRef:
                name: gitlab-server
                key: opt-key-base
          - name: GITLAB_ROOT_PASSWORD
            value: ""
          - name: GITLAB_ROOT_EMAIL
            value: ""
          - name: GITLAB_HOST
            valueFrom:
              configMapKeyRef:
                name: gitlab-server
                key: gitlab-host
          - name: GITLAB_PORT
            value: "443"
          - name: GITLAB_SSH_PORT
            value: "22"
          - name: GITLAB_NOTIFY_ON_BROKEN_BUILDS
            value: "true"
          - name: GITLAB_NOTIFY_PUSHER
            value: "false"
          - name: GITLAB_EMAIL
            valueFrom:
              configMapKeyRef:
                name: gitlab-server
                key: gitlab-email
          - name: GITLAB_EMAIL_REPLY_TO
            valueFrom:
              configMapKeyRef:
                name: gitlab-server
                key: gitlab-email-reply-to
          - name: GITLAB_INCOMING_EMAIL_ADDRESS
            valueFrom:
              configMapKeyRef:
                name: gitlab-server
                key: gitlab-email-incoming-email-address
          - name: GITLAB_BACKUP_SCHEDULE
            value: weekly
          - name: GITLAB_BACKUP_TIME
            value: 01:00
          - name: DB_TYPE
            value: postgres
          - name: DB_HOST
            value: postgresql
          - name: DB_PORT
            value: "5432"
          - name: DB_USER
            valueFrom:
              configMapKeyRef:
                name: postgresql
                key: user
          - name: DB_PASS
            valueFrom:
              secretKeyRef:
                name: postgresql
                key: password
          - name: DB_NAME
            valueFrom:
              configMapKeyRef:
                name: postgresql
                key: db-name
          - name: REDIS_HOST
            value: redis
          - name: REDIS_PORT
            value: "6379"
          - name: SMTP_ENABLED
            value: "true"
          - name: SMTP_DOMAIN
            value: smtp.sendgrid.net
          - name: SMTP_HOST
            value: smtp.sendgrid.net
          - name: SMTP_PORT
            value: "2525"
          - name: SMTP_USER
            value: apikey
          - name: SMTP_PASS
            valueFrom:
              secretKeyRef:
                name: sendgrid
                key: apiKey
          - name: SMTP_STARTTLS
            value: "true"
          - name: SMTP_AUTHENTICATION
            value: login
          - name: IMAP_ENABLED
            value: "false"
          - name: IMAP_HOST
            value: ""
          - name: IMAP_PORT
            value: ""
          - name: IMAP_USER
            value: ""
          - name: IMAP_PASS
            value: ""
          - name: IMAP_SSL
            value: "false"
          - name: IMAP_STARTTLS
            value: "false"
          - name: GITLAB_HTTPS
            value: "true"
          - name: SSL_CERTIFICATE_PATH
            value: /etc/gitlab/tls/tls_certificate_chain
          - name: SSL_KEY_PATH
            value: /etc/gitlab/tls/tls_certificate_key
          - name: SSL_DHPARAM_PATH
            value: /etc/gitlab/tls/tls_dhparam
        ports:
          - name: http
            containerPort: 80
          - name: https
            containerPort: 443
          - name: ssh
            containerPort: 22
        volumeMounts:
          - mountPath: /home/git/data
            name: gitlab-server
          - name: internal-tls
            mountPath: /etc/gitlab/tls
            readOnly: true
        livenessProbe:
          exec:
            command:
              - "true"
          initialDelaySeconds: 10
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /healthz
            port: 80
            scheme: HTTP
          initialDelaySeconds: 10
          periodSeconds: 15
      volumes:
        - name: gitlab-server
          persistentVolumeClaim:
            claimName: gitlab-server
        - name: internal-tls
          secret:
            secretName: internal-tls
---
apiVersion: v1
kind: Service
metadata:
  name: gitlab-server
  namespace: gitlab
spec:
  type: LoadBalancer
  loadBalancerIP: <XXX.XXX.XXX.XXX> # <- 事前準備で作成した外部IPアドレスの値
  ports:
    - name: http
      port: 80
      targetPort: http
    - name: https
      port: 443
      targetPort: https
    - name: ssh
      port: 22
      targetPort: ssh
  selector:
    app: gitlab-server

version 12.7.5をデプロイしてdb migrationを行ったところ・・

Your current database version is too old to be migrated. You should upgrade to GitLab 11.11.0 before moving to this version. Please see https://docs.gitlab.com/ee/policy/maintenance.html#upgrade-recommendations

こんなエラーメッセージが出たので調査

https://docs.gitlab.com/ee/policy/maintenance.html#example-upgrade-paths

どうやら何回かに分けてupgradeしなくては行けないみたいです。。。めんどくさいですね。。。 まあ致し方なし。。。

以下のversion毎にdocker imageを作り直して、順次imageをdeployしてmigrationを実行していきます。

  • 11.4.3 (old ver)
  • 11.11.8
  • 12.0.12
  • 12.7.5 (new ver)

これらのdeploy後に、内部DNSにAレコードを追加して対応完了です。

最後に https://gitlab.your-domain.com/help にアクセスして、

GitLab Community Edition 12.7.5

と表示されていることを確認して、無事にアップグレードされていることを確認しました。