はじめに
【2024/8/7】17.2.1に続き、17.2.2 についてもセキュリティ上の問題が報告されています。
【2024/10/12】17.2.2以降、毎月クリティカルなセキュリティ上の問題が報告されていて、17.4.2まで最新版にすることが勧告されています。sammersbn/docker-gitlabも数日遅れでコンテナイメージを更新してくれています。
Kubernetesにsameersbn/gitlab:15.2.2を導入してから15.11.13にするまでの顛末については別の記事にまとめています。
脆弱性への対応のため16系列にバージョンアップしようと検討を開始しようとしています。(最終的に作業を実施したタイミングでは16.7.3に更新することになりました)
現時点では15.11.13から16系列の最新版にするpathは、16.1.5→16.3.6→16.7.3となっています。多数のユーザーを抱える場合は16.0.8が必要とされていますが、おそらくCE版ではなくEE版の利用を検討するべきでしょう。
いままでのバージョンアップと比較するといくつかの点で懸念がありますので、その点をまとめつつ、実際にアップグレードした際の手順などを残していこうと思います。
【2024/1/19追記】実際にアップグレードすると再起動のタイミングで動作しなかったりしています。またバックアップからのリストアにも失敗しています。これらは解決しましたので経緯について追記しました。
この文書はGitLab v16.7.2へのアップグレードについて書いていましたが、Podの再起動後から500エラーが発生するようになりました。
確認できた現象は、GitLabコンテナの log/gitlab-workhorse.log に badgatewayエラー("badgateway: failed to receive response: dial unix /home/git/gitlab/tmp/sockets/gitlab.socket: connect: no such file or directory"
)が記録されている点です。
また /home/git/gitlab/node_modules/ ディレクトリの中が空になったまま自動的にパッケージのダウンロードが行われていない状態になっています。
そのままv16.7.3等へアップグレードすると一時的に解決しますが、再度Podを再起動すると同様の現象が発生します。
【2024/01/19追記】これらの現象については概ね解決しましたので経緯について追記しました。
v16.7.3に変更してから日毎のバックアップが取得されていません。本家のIssue#2790と原因は同じでバックアップファイルの取得には成功していますが、リストアに失敗していましたが、ENOENT: No such file or directory #2866 にリンクされているパッチを適用することで解決しました。
将来的にはv16.7.4 or v16.8.x以降にアップグレードすることで解決するはずです。
Podを再起動すると500エラーが発生する現象は、sameersbn版GitLab 15.6.0から発生するとのことです。
修正は16.7.4以降のコンテナに取り込まれるだろうと思われるので、それまで変更は止めた方が良いかもしれません。
16.7.3に更新後、Podを再起動したらサービスが復旧しなくなった障害対応の顛末
一連の問題の根本原因は/home/git/gitlab/public/assetsがシンボリックリンクからディレクトリに上書きされてしまうことでした。
テスト系に検証環境を構築するため、本番のバックアップファイルを転送してリストアします。
GitLabのリストア手順 (本番のv15.11.13をテスト環境にコピーする)
バックアップファイルとリストア先のサーバーはGitLabのバージョンが一致しなければいけません。
本番系で取得できていたファイルはGitLab v15.11.13のものなので、まずこのバージョンを稼動させてリストアしていきます。
まず素の何も設定しないGitLab v15.11.13を起動します。これをしないとコンテナ内部で/home/git/gitlab/node_modules/ディレクトリが空のままとなってしまいます。
$ ls
gitlab-data-pvc.yaml gitlab-rc.yml postgresql-rc.yml redis-rc.yml
gitlab-log-pvc.yaml gitlab-svc.yml postgresql-svc.yml redis-svc.yml
gitlab-node-pvc.yaml postgresql-pvc.yaml redis-pvc.yaml
$ sudo kubectl -n gitlab apply -f .
## 処理完了まで30分ほど待つ
初期状態のGitLab v15.11.13が起動するまで、手元のテスト環境では30分程度待ちました。
起動直後はしばらくエラーかと思われるログが出ていますが、しばらく待つと追加の初期化処理が進みます。
...
2024-01-19 09:35:22,277 INFO exited: sidekiq (exit status 1; not expected)
2024-01-19 09:35:23,279 INFO spawned: 'sidekiq' with pid 1868
2024-01-19 09:35:24,024 INFO exited: puma (exit status 1; not expected)
2024-01-19 09:35:25,025 INFO spawned: 'puma' with pid 1869
...
2024-01-19 09:40:43,750 INFO exited: sidekiq (exit status 1; not expected)
2024-01-19 09:40:44,752 INFO spawned: 'sidekiq' with pid 2188
2024-01-19 09:40:45,550 INFO exited: puma (exit status 1; not expected)
2024-01-19 09:40:46,552 INFO spawned: 'puma' with pid 2189
...
## この状態でも、まだ待つ
kubectl logsでは意味のない情報が流れている間にも、コンテナ内部のlog/production.logファイルに作業の内容が出力されています。
## コンテナに保存されているlog/production.logファイルを確認する
$ sudo kubectl -n gitlab exec -it $(sudo kubectl -n gitlab get pod -l name=gitlab -o jsonpath='{.items[*].metadata.name}') -- tail -f log/production.log
正常に15.11.13が起動したら、アプリケーションを起動しないように細工したargs: パラメータを加えます。
## ENTRYPOINTに指定されている"/sbin/entrypoint.sh"に与える引数をargs:に指定する
containers:
- name: gitlab
image: sameersbn/gitlab:15.11.13
args: ["sh","-c","--","while true; do sleep 30; done"]
Deploymentオブジェクトと違い、ReplicationControllerオブジェクトではPodの自動再起動は行われないため、変更したYAMLファイルを適用したら必ずPodを再起動します。
$ sudo kubectl -n gitlab apply -f gitlab-rc.yml
$ sudo kubectl -n gitlab delete pod $(sudo kubectl -n gitlab get pod -l name=gitlab -o jsonpath='{.items[*].metadata.name}')
このコンテナが稼動したらkubectl exec
で中に入って復旧作業を実施していきますが、その前に本番環境のバックアップファイルをテスト環境にコピーした上で、さらにgitlabのPod内部に配置します。
gitlab-q7j25
はPod名で、書式はscpやrsyncなどと類似のものです。
## バックアップファイルを/home/git/data/backupsに転送
$ sudo kubectl -n gitlab cp 1705075223_2024_01_13_15.11.13_gitlab_backup.tar gitlab-q7j25:/home/git/data/backups/1705075223_2024_01_13_15.11.13_gitlab_backup.tar
最初からargs:を指定してしまうとタスク実行に必要なライブラリなどが配置されないので、必ず一度デフォルトの状態でPodを稼動させます。(最初からargs:を追加した/sbin/entrypoint.sh app:init
の実行から始める方法もあると思いますが、試していません)
args:を追加してサーバープロセスが稼動していない状態になったら、Pod(以下の例はgitlab-q7j25)に入ってリストア作業を行います。
$ sudo kubectl -n gitlab exec -it gitlab-q7j25 -- bash
root@gitlab-q7j25#
プロンプトが変化したことを確認してからリストア作業を実施しますが、sameersbn版GitHubリポジトリのRestore手順ではdockerやdocker-composeコマンドを利用した場合しか掲載されていません。
これら手順にあるapp:rake
はコマンド名というよりも、/sbin/entrypoint.sh
スクリプトに対する命令です。DockerfileではこれがENTRYPOINTに指定されていて、デフォルトのapp:start
タスク名がCMDに指定されています。
コンテナの内部に入ってから直接rake
コマンドやbundle exec rake
などを呼び出しす行為は権限などの問題で正常に動作しません。
必ず/sbin/entrypoint.sh
の引数にコマンドを渡すことで作業を進めていきます。
/sbin/entrypoint.sh
を経由する点にだけ気をつければ、時間はかかるものの作業自体は難しくありません。
## リストアタスクを実行する
root@gitlab-q7j25# /sbin/entrypoint.sh app:rake gitlab:backup:restore BACKUP=1705075223_2024_01_13_15.11.13
途中でDBテーブルの削除に同意するためにyesを入力して処理を進めます。また最後にauthorized_keysの再生成について質問があるのでyesを入力します。全体のリストアタスクは、テストした環境では15分程度で終了しました。
終了時点での画面の出力は次のようになっています。
Do you want to continue (yes/no)? yes
Removing all tables. Press `Ctrl-C` within 5 seconds to abort
2024-01-19 10:01:30 +0900 -- Cleaning the database ...
2024-01-19 10:01:50 +0900 -- done
Restoring PostgreSQL database gitlab_production ... ERROR: must be owner of extension pg_trgm
ERROR: must be owner of extension btree_gist
ERROR: must be owner of extension btree_gist
ERROR: must be owner of extension pg_trgm
## ここから15分程度の待ち時間が発生する
...
This task will now rebuild the authorized_keys file.
You will lose any data stored in the authorized_keys file.
Do you want to continue (yes/no)? yes
2024-01-19 10:15:51 +0900 -- Deleting tar staging files ...
2024-01-19 10:15:51 +0900 -- Cleaning up /home/git/data/backups/backup_information.yml
2024-01-19 10:15:51 +0900 -- Cleaning up /home/git/data/backups/db
2024-01-19 10:15:51 +0900 -- Cleaning up /home/git/data/backups/repositories
2024-01-19 10:15:52 +0900 -- Cleaning up /home/git/data/backups/uploads.tar.gz
2024-01-19 10:15:52 +0900 -- Cleaning up /home/git/data/backups/builds.tar.gz
2024-01-19 10:15:52 +0900 -- Cleaning up /home/git/data/backups/artifacts.tar.gz
2024-01-19 10:15:52 +0900 -- Cleaning up /home/git/data/backups/pages.tar.gz
2024-01-19 10:15:52 +0900 -- Cleaning up /home/git/data/backups/lfs.tar.gz
2024-01-19 10:15:52 +0900 -- Cleaning up /home/git/data/backups/terraform_state.tar.gz
2024-01-19 10:15:52 +0900 -- Cleaning up /home/git/data/backups/packages.tar.gz
2024-01-19 10:15:52 +0900 -- Deleting tar staging files ... done
2024-01-19 10:15:52 +0900 -- Deleting backups/tmp ...
2024-01-19 10:15:52 +0900 -- Deleting backups/tmp ... done
2024-01-19 10:15:52 +0900 -- Warning: Your gitlab.rb and gitlab-secrets.json files contain sensitive data
and are not included in this backup. You will need to restore these files manually.
2024-01-19 10:15:52 +0900 -- Restore task is done.
2024-01-19 10:15:52 +0900 -- Deleting backup and restore lock file
画面上は500エラーが表示されているかもしれませんが、気にせずgitlab-rc.ymlファイルを編集し、先ほど追加したargs:パラメータをコメントアウトします。
containers:
- name: gitlab
image: sameersbn/gitlab:15.11.13
# args: ["sh","-c","--","while true; do sleep 30; done"]
この内容をapplyしてからPodを削除して再起動します。
$ sudo kubectl -n gitlab apply -f gitlab-rc.yml
$ sudo kubectl -n gitlab delete pod $(sudo kubectl -n gitlab get pod -l name=gitlab -o jsonpath='{.items[*].metadata.name}')
これで/sbin/entrypoint.sh
の引数にapp:start
が指定され、Recompiling assetsなどが自動的に実行されて無事に動作するはずです。
アプリケーションの起動には10分程度は放置する必要がありました。
...
2024-01-19 12:16:51,608 INFO supervisord started with pid 1
2024-01-19 12:16:52,612 INFO spawned: 'gitaly' with pid 1735
2024-01-19 12:16:52,617 INFO spawned: 'puma' with pid 1736
2024-01-19 12:16:52,622 INFO spawned: 'gitlab-workhorse' with pid 1737
2024-01-19 12:16:52,626 INFO spawned: 'sidekiq' with pid 1738
2024-01-19 12:16:52,631 INFO spawned: 'sshd' with pid 1742
2024-01-19 12:16:52,636 INFO spawned: 'nginx' with pid 1745
2024-01-19 12:16:52,641 INFO spawned: 'cron' with pid 1746
2024-01-19 12:16:54,052 INFO success: gitaly entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2024-01-19 12:16:54,052 INFO success: puma entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2024-01-19 12:16:54,052 INFO success: gitlab-workhorse entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2024-01-19 12:16:54,052 INFO success: sidekiq entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2024-01-19 12:16:54,052 INFO success: sshd entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2024-01-19 12:16:54,052 INFO success: nginx entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2024-01-19 12:16:54,053 INFO success: cron entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
## ここで一旦ログが停止するので10分程度放置する
とりあえず、この方法でv15.11.13までは復元することができました。
このバージョンで次のセクションにある手順のように手動でバックアップを取得すると、バックアップ取得前にサーバーが停止するため、バックアップ取得後の再起動後から正常に稼動しなくなります。その状態でもアップグレードは実行できるので続けても問題ありません。一度このバージョンで稼動させたい場合には後述するように public/assetsとdata/tmp/assetsの両方のディレクトリの内容を適切な状態にします。
検証のためpublic/assetsなどの内容はそのまま放置してv16.7.3まで下記にある当初の記事の手順に従ってアップグレードしていきます。
バックアップファイルが作成できない原因の調査 (GitLab v16.7.3)
次にv16.7.3でバックアップファイルが作成できていない状況を確認します。バックアップファイルさえあれば、先ほどのように復元できるためまずはこの状況を解決します。
冒頭でも紹介した本家のIssue#2790のように何かしら不足するディレクトリなどがあるのだと思います。
まずはバックアップファイルを作成させてエラーメッセージなどを確認します。
$ sudo kubectl -n gitlab exec -it $(sudo kubectl -n gitlab get pod -l name=gitlab -o jsonpath='{.items[*].metadata.name}') -- bash
root@gitlab-q7j25# /sbin/entrypoint.sh app:rake gitlab:backup:create
rake aborted!
...
Errno::ENOENT: No such file or directory @ rb_check_realpath_internal - /home/git/data/shared/ci_secure_files
/home/git/gitlab/lib/backup/files.rb:156:in `realpath'
/home/git/gitlab/lib/backup/files.rb:156:in `app_files_realpath'
...
メッセージはIssues#2790と同じでしたので、このディレクトリを作成してから、再度バックアップを取得して他に問題がないか確認します。
root@gitlab-q7j25# sudo -u git mkdir /home/git/data/shared/ci_secure_files
root@gitlab-q7j25# /sbin/entrypoint.sh app:rake gitlab:backup:create
2024-01-18 11:51:57 +0900 -- Deleting backups/tmp ...
2024-01-18 11:51:57 +0900 -- Deleting backups/tmp ... done
2024-01-18 11:51:57 +0900 -- Warning: Your gitlab.rb and gitlab-secrets.json files contain sensitive data
and are not included in this backup. You will need these files to restore a backup.
Please back them up manually.
2024-01-18 11:51:57 +0900 -- Backup 1705546301_2024_01_18_16.7.3 is done.
2024-01-18 11:51:57 +0900 -- Deleting backup and restore PID file ... done
バックアップの取得には成功しますが、内部的にはpumaやnginxなどのサーバープロセスが再起動されるためサービスはエラーになり復旧しませんが、下記にあるようにassets.rakeファイルを修正すると問題なくバックアップファイルが取得できます。
日毎のバックアップファイルが取得できない問題に対応するために、gitlab-rc.ymlファイルのinitContainersでbusyboxを立ち上げて、ci_secure_filesディレクトリを作成するようにしています。
Podの再起動後に正常起動しない問題の調査
バックアップから戻せることが分かったので、その情報でIssuesを検索しているとバックアップ取得後にシステムがエラーとなることが報告されています。
このIssuesの結論はバックアップから戻せるよ、というものなので参考にはなりませんでした。
このままでは毎日のバックアップ取得後にシステムが停止するかと思いましたが、15.11.13から16.7.3にアップグレードした本番サーバーはディレクトリを作成したまま様子をみていたところ毎日午前1時のバックアップが無事に取得できていました。
この問題は複数の状況が関係しているようで、一つは単純にリストアに失敗しているものです。起動処理が完了しない間に次の手続きに移ってしまうと問題が発生するので、前述のリストア手順に手掛りとなるようなログファイルやコンソールの様子を追記して処理が完結してから次に進むようにメモを追加しました。
もう一つは今日になって解決した以下の問題です。
GitLab v16.7.3で取得したバックアップファイルがリストアできない問題について
v16.7.3でバックアップファイルが取得できるようになってもリストアにどこまでも失敗していました。
コンテナのlog/production.log
ファイルを確認すると、次のようなメッセージが表示されていましたが、指示どおりにrakeタスクを実行しても解決しません。
...
Raven 3.1.2 configured not to capture errors: DSN not set
Raven 3.1.2 configured not to capture errors: DSN not set
ActionView::Template::Error (Could not load compiled manifest from /home/git/gitlab/public/assets/webpack/mani
fest.json.
Have you run `rake gitlab:assets:compile`?
(original error Errno::ENOENT: No such file or directory @ rb_sysopen - /home/git/gitlab/public/assets/webpack
/manifest.json)):
62:
63: = yield :page_specific_javascripts
64:
65: = webpack_bundle_tag 'super_sidebar'
66:
67: = webpack_controller_bundle_tags
68:
lib/gitlab/webpack/manifest.rb:82:in `rescue in load_manifest'
lib/gitlab/webpack/manifest.rb:77:in `load_manifest'
...
これはIssuesが上がっているようです。
アップグレードは元記事のように実行して、v16.7.3のコンテナが無事に起動してからもWebブラウザで500エラーが発生している状態で、次のような対応を実施します。
また、エディタは導入されていないので、GNU nanoを導入してから編集しています。
## public/assetsディレクトリを確認
root@gitlab-q7j25# ls -ld /home/git/gitlab/public/assets
## シンボリックリンクの場合は問題のない
lrwxrwxrwx 1 root root 25 Jan 19 15:03 /home/git/gitlab/public/assets -> /home/git/data/tmp/assets
## シンボリックリンクでない場合にはディレクトリを削除し、data/tmp/assetsへのリンクに変更
root@gitlab-q7j25# rm -r /home/git/gitlab/public/assets
root@gitlab-q7j25# ln -s /home/git/data/tmp/assets /home/git/gitlab/public/assets
## gitlab:assets:compileを実行する前にassets.rakeを修正
root@gitlab-q7j25# apt update && apt install nano
root@gitlab-q7j25# nano /home/git/gitlab/lib/tasks/gitlab/assets.rake
root@gitlab-q7j25# /sbin/entrypoint.sh app:rake gitlab:assets:compile
data/tmp/assetsディレクトリに最新のファイルが配置された状態でgitlabコンテナを再起動したところ問題なく稼動し、無事に本番環境のv16.7.3がテスト系で稼動しました。
public/assetsがシンボリックリンクではなくディレクトリの場合は、data/tmp/assetsの内容が空であったり古かったりすると、再起動したタイミングでpublic/assetsがdata/tmp/assetsを参照することで障害が発生します。
アップグレードした直後で問題なく稼動している、v16.7.3にアップグレードした直後でWebページが500エラーとなっている場合は、rsyncなどでpublic/assets/.の内容をdata/tmp/assets/.にコピーしておくことをお勧めします。
root@gitlab-q7j25# apt update && apt install rsync
root@gitlab-q7j25# rsync -av public/assets/. ../data/tmp/assets/.
root@gitlab-q7j25# rm -r public/assets
root@gitlab-q7j25# ln -s /home/git/data/tmp/assets public/assets
修正したgitlab-rc.ymlファイル
initContainersを利用してv15.11.13からv16.7.3までのPodを動作させるための一時対応を実施するgitlab-rc.ymlファイルです。
---
apiVersion: v1
kind: ReplicationController
metadata:
name: gitlab
namespace: gitlab
spec:
replicas: 1
selector:
name: gitlab
template:
metadata:
name: gitlab
labels:
name: gitlab
spec:
initContainers:
- name: chown-nodedir
image: busybox:1.36
command: ['sh', '-c', 'mkdir -p /home/git/data/shared/ci_secure_files ; chown 1000:1000 /home/git/git\
lab/node_modules/. /var/log/gitlab/. /home/git/data/shared/ci_secure_files/.']
volumeMounts:
- mountPath: /home/git/data
name: data
- mountPath: /home/git/gitlab/node_modules
name: node-data
- mountPath: /var/log/gitlab
name: log-data
containers:
- name: gitlab
image: sameersbn/gitlab:16.7.3
# args: ["sh","-c","--","while true; do sleep 30; done"]
env:
name: DEBUG
value: "false"
...envの詳細は省略..
ports:
- name: http
containerPort: 80
- name: ssh
containerPort: 22
volumeMounts:
- mountPath: /home/git/data
name: data
- mountPath: /home/git/gitlab/node_modules
name: node-data
- mountPath: /var/log/gitlab
name: log-data
volumes:
- name: data
persistentVolumeClaim:
claimName: gitlab-data-pvc
- name: node-data
persistentVolumeClaim:
claimName: gitlab-node-pvc
- name: log-data
persistentVolumeClaim:
claimName: gitlab-log-pvc
PVCは次のようなファイルをコピーしてname:行を変更して3つのgitlabコンテナ用のPVCを準備しています。
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: gitlab-data-pvc
namespace: gitlab
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 100Gi
storageClassName: rook-ceph-block
v15.11.13を16.7.3にアップグレードした時の元記事
ここから先の記事は当初に投稿した内容です。
環境
- Kubernetes: v1.25.6 (installed by kubespray)
- Rook/Ceph: v1.9.13
- Velero: v1.12.2
- Minio (Velero用ストレージ): quay.io/minio/minio:RELEASE.2023-07-07T07-13-57Z
参考情報
- https://docs.gitlab.com/ee/update/
- https://docs.gitlab.com/ee/update/versions/gitlab_16_changes.html (#issues-to-be-aware-of-when-upgrading-from-1511)
- https://github.com/sameersbn/docker-gitlab
- https://github.com/sameersbn/docker-postgresql
関連する作業について既存のドキュメントを参照してください。
懸念点
まず本家のドキュメント GitLab 16 changesと、sameersbnのGitHub/README.mdの2つを確認する必要があります。
- PostgreSQLのバージョンが最低でも13以上であることが必要 (公式ガイド)
- 15系列にバージョンアップする際、"15.11.0, 15.11.1, or 15.11.2"を経由しているとテーブルに自動修復されない変更が加えられているため個別に対応が必要 (公式ガイド)
- sameersbn/postgresqlには13系列のバージョンが存在しないため、12-20200524から14以降にアップグレードが必要 (sameersbn/docker-postgres)
sameersbn/docker-postgresのREADME.mdではアップグレードはコンテナイメージの更新だけで良いとの記述がありますが、issuesをみるとトラブルが発生する可能性はそれなりにありそうです。
なおRedisについては6.2.7を利用していますが、これはGitLab v16以降でもサポートされる(6.x or 7.x)ため、今回は変更の対象とはしていません。
準備作業
本番環境のGitLabは100GBほど確保しているPVCの内、22GBを消費しています。
少し時間がかかりそうですが、次のバックアップを取得します。
- Voleroによるnamespace全体のバックアップ取得
- GitLabレベルのバックアップファイルの確保
Voleroによるnamespace全体のバックアップの取得
テスト環境に登録しているMinioと連携させてVoleroのセットアップは完了しています。
まずバックアップの対象となるPVCにannotationを追加します。
$ sudo kubectl -n gitlab annotate "pod/$(sudo kubectl -n gitlab get pod -l name=redis -o jsonpath='{.items[0].metadata.name}')" backup.velero.io/backup-volumes=redis-data
$ sudo kubectl -n gitlab annotate "pod/$(sudo kubectl -n gitlab get pod -l name=postgresql -o jsonpath='{.items[0].metadata.name}')" backup.velero.io/backup-volumes=data
$ sudo kubectl -n gitlab annotate "pod/$(sudo kubectl -n gitlab get pod -l name=gitlab -o jsonpath='{.items[0].metadata.name}')" backup.velero.io/backup-volumes=data
全体のannotationの状況を確認します。
$ sudo kubectl -n gitlab get pod -o jsonpath='{range .items[*].metadata}{.labels.name}{": \t"}{.annotations.backup\.velero\.io\/backup-volumes}{"\n"}{end}'
gitlab: data
postgresql: data
redis: redis-data
問題がなければVeleroを起動し、バックアップを取得します。
$ sudo velero backup create "gitlab-$(date +%Y%m%d.%H%M)" --include-namespaces gitlab --wait
バックアップの取得が始まると次のようなメッセージが表示され、C-cで抜けてもバックグラウンドで実行が続きます。
Backup request "gitlab-20231212.0351" submitted successfully.
Waiting for backup to complete. You may safely press ctrl-c to stop waiting - your backup will continue in the
background.
...................................
GitLabのWeb-UIから確認できるディスク使用量(以下はテスト環境の6.82GBの場合)に応じて適切なバックアップ時間か確認します。
$ sudo velero backup get
NAME STATUS ERRORS WARNINGS CREATED EXPIRES STORAGE LOCATION SELECTOR
gitlab-20240113.0135 Completed 0 0 2024-01-13 01:35:36 +0000 UTC 29d default <none>
$ sudo velero backup describe --details gitlab-20240113.0135
...
Started: 2024-01-13 01:35:36 +0000 UTC
Completed: 2024-01-13 01:42:09 +0000 UTC
Expiration: 2024-02-12 01:35:35 +0000 UTC
...
restic Backups:
Completed:
gitlab/gitlab-rlz8h: data
gitlab/postgresql-rbq4c: data
gitlab/redis-t7cz6: redis-data
全てのPVCのバックアップが取得できていますが、念のためGitLab自身のバックアップファイルも保存しておきます。
テスト環境でVeleroで取得したGitLabのバックアップデータからリストアできることを確認しています。
GitLabレベルのバックアップファイルの確保
GitLabがシステムとして準備している/home/git/data/backups/からバックアップを取得します。
以下の操作ログはテスト系で実施した際のものです。
$ sudo kubectl -n gitlab exec -it "$(sudo kubectl -n gitlab get pod -l name=gitlab -o jsonpath='{.items[0].metadata.name}')" -- ls -al /home/git/data/backups/
total 4440
drwxr-xr-x 2 git git 4096 Dec 12 01:00 .
drwxr-xr-x 11 git git 4096 Sep 8 16:53 ..
-rw------- 1 git git 645120 Dec 6 01:00 1701792021_2023_12_06_15.11.13_gitlab_backup.tar
-rw------- 1 git git 645120 Dec 7 01:00 1701878421_2023_12_07_15.11.13_gitlab_backup.tar
-rw------- 1 git git 645120 Dec 8 01:00 1701964821_2023_12_08_15.11.13_gitlab_backup.tar
-rw------- 1 git git 645120 Dec 9 01:00 1702051221_2023_12_09_15.11.13_gitlab_backup.tar
-rw------- 1 git git 645120 Dec 10 01:00 1702137621_2023_12_10_15.11.13_gitlab_backup.tar
-rw------- 1 git git 645120 Dec 11 01:00 1702224021_2023_12_11_15.11.13_gitlab_backup.tar
-rw------- 1 git git 655360 Dec 12 01:00 1702310421_2023_12_12_15.11.13_gitlab_backup.tar
確認したファイル名(この例では"1702224021_2023_12_11_15.11.13_gitlab_backup.tar")を指定してK8sクラスター外にコピーします。
$ sudo kubectl -n gitlab cp "$(sudo kubectl -n gitlab get pod -l name=gitlab -o jsonpath='{.items[0].metadata.name}'):/home/git/data/backups/1702224021_2023_12_11_15.11.13_gitlab_backup.tar" 1702224021_2023_12_11_15.11.13_gitlab_backup.tar
SHA256チェックサムの値でも確認しておきます。
sudo kubectl -n gitlab exec -it "$(sudo kubectl -n gitlab get pod -l name=gitlab -o jsonpath='{.items[0].metadata.name}')" -- sha256sum /home/git/data/backups/1702224021_2023_12_11_15.11.13_gitlab_backup.tar
64e75d83d03b2574a5e58726f50ca870e7ad73ea6c82f1599624389477eabe63 1702224021_2023_12_11_15.11.13_gitlab_backup.tar
$ sha256sum 1702224021_2023_12_11_15.11.13_gitlab_backup.tar
64e75d83d03b2574a5e58726f50ca870e7ad73ea6c82f1599624389477eabe63 1702224021_2023_12_11_15.11.13_gitlab_backup.tar
アップグレードパスの適用条件の検討
基本的なアップグレードパスは 16.0.8 (条件付き) > 16.1.5 (条件付き) > 16.2.8 (条件付き) > 16.3.6 > 16.7.z > latest 16.Y.Z. となっています。
Large pipelinesに該当するかのチェック
おそらく最低限のパスで十分だと思いますが、念のため条件のlarge pipelinesに該当するか確認します。
$ sudo kubectl -n gitlab exec -it gitlab-k9p6b -- bash
root@gitlab-k9p6b:/home/git/gitlab# psql -h postgresql -p 5432 -U gitlab -d gitlab_production
Password for user gitlab:
psql (14.8 (Ubuntu 14.8-1.pgdg20.04+1))
Type "help" for help.
gitlab_production=> select count(*) from ci_pipeline_variables;
count
-------
0
(1 row)
v15.11.13に直接アップグレードしなかった場合のv15.11系列のバグのチェック
以前にv15.11.13にアップグレードした際に、v15.10等から直接v15.11.13に更新していれば良いのですが、その手前のv15.11.12などを経由していると、v16.2.x以降でDBスキーマに起因する障害が発生するようです。
これに該当しないか確認するため、large pipelinesのチェックと同様にpsqlコマンドを起動します。
gitlab_production=> select pg_typeof (id_convert_to_bigint) from public.ci_build_needs limit 1;
pg_typeof
-----------
(0 rows)
この問題にも該当しないようです。
今回のアップグレードパス
NPM Package Listの条件に該当しそうかよく分からなかったので、次のような順番でv15.11.13からアップグレードしていくことにしました。
- 16.1.5 (条件付き)
- 16.3.6
- 16.7.3
作業手順
作業前にGitLabのAdmin画面から"Background/Migrations"や"同Jobs"に実行中のタスクが残っていないか確認してから進めます。
PostgreSQLのバージョンアップ
主な作業手順は以下のとおりです。
- PostgreSQLのイメージをv14(sameersbn/docker-postgresql:14-20230628)に更新します
- GitLabのReplicationControllerオブジェクト定義を削除し、Podを停止させる
- PostgreSQLのYAMLファイルで新バージョンに変更して適用後に手動でPodを削除することで再起動させる
- 起動したPostgreSQLのログを確認する
$ sudo kubectl -n gitlab logs -f postgresql-fkxmn
...
Initializing database...
‣ Migrating PostgreSQL 12 data to 14...
‣ Installing PostgreSQL 12...
W: http://apt.postgresql.org/pub/repos/apt/dists/jammy-pgdg/InRelease: Key is stored in legacy trusted.gpg key
ring (/etc/apt/trusted.gpg), see the DEPRECATION section in apt-key(8) for details.
debconf: delaying package configuration, since apt-utils is not installed
‣ Migration in progress. Please be patient...Performing Consistency Checks
...
Starting PostgreSQL 14...
2024-01-13 02:09:26.251 UTC [1] LOG: starting PostgreSQL 14.8 (Ubuntu 14.8-1.pgdg22.04+1) on x86_64-pc-linux-
gnu, compiled by gcc (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0, 64-bit
2024-01-13 02:09:26.251 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
2024-01-13 02:09:26.251 UTC [1] LOG: listening on IPv6 address "::", port 5432
2024-01-13 02:09:26.391 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2024-01-13 02:09:26.658 UTC [2604] LOG: database system was shut down at 2024-01-13 02:09:25 UTC
2024-01-13 02:09:27.080 UTC [1] LOG: database system is ready to accept connections
ここでログが途絶えてしばらくすると、Podのステータスが正常になります。
$ sudo kubectl -n gitlab get pods
NAME READY STATUS RESTARTS AGE
postgresql-fkxmn 1/1 Running 1 (2m23s ago) 4m3s
redis-t7cz6 1/1 Running 1 (92d ago) 119d
この状態から再度GitLabのReplicationControllerオブジェクトを定義するYAMLファイルを適用し、gitlabのPodを起動する。
テスト環境では無事にPostgreSQLのバージョンアップが完了しました。
GitLabのバージョンアップ
基本的にはgitlab-rc.ymlファイルのバージョンをアップグレードパスで決めた順番に更新しながら、反映 → Pod削除による再起動 を繰り返すことで反映させていきます。
gitlabは起動してからアップグレード処理を行うため、ログファイルを確認しながら辛抱強く完了まで待ちます。
$ sudo kubectl -n gitlab logs -f $(sudo kubectl -n gitlab get pod -l name=gitlab -o jsonpath='{.items[0].metadata.name}')
アップグレード中はWebブラウザに500エラーの画面が表示されていますが、途中でPodを再起動するようなことがなければ無事に完了するはずです。
またブラウザでアクセスできるようになったら管理者権限でログインし、/gitlab/admin
ページからMonitoringタブのBackground Migrationsを確認し、実行中のジョブがないことを確認してから次のバージョンのコンテナを起動するために再起動を行うようにします。
さいごに
GitLabはオフィシャルのリリース(CE版)を元にコンテナ化されたsameersbn版を利用しています。
今回の方法でテスト系を含めて3つのGitLabのインスタンスを無事に最新版に更新することができました。
アップグレード・パスの調査などに時間をかけましたが、アップグレード作業自体はコンテナのバージョンを変更して再起動して待つだけの簡単な作業です。
Recompiling assets (relative_url in use), this could take a while...
のメッセージが表示された後、いつ終わるのか分からなくて不安になりましたが、結果として経験が蓄積できたのは良かったと思っています。
GitLabのセキュリティレポートが発行されてからしばらく経過していることもあり、問題に遭遇することもなく無事に16.7.3に更新できたと思ったものの未解決の障害に遭遇して数日間は調査に追われましたが無事に解決して良かったです。
GitHubは個人アカウントでもPrivateリポジトリが作成し放題ですが、外部に配置するのが不適切なコンテンツがあるため引き続き両方を使い分けながらできるだけ情報は公開しつつ、守るべきものは内部に置いていくつもりです。
【後日談】16.7.3から17.1.1へのアップグレード
GitLabのUpgrade Pathページを確認すると最新版(v17.1.1)へは次の順序でアップグレードすることとなっています。
- 16.7.8
- 16.11.5
- 17.1.1 (実際には17.0.3を経由してアップグレード)
関連のドキュメントを読む限り、PostgreSQLをv14にアップグレードしてGitLabが16.7.x系列になっていれば、v16系列の最新版へのアップグレードについては問題はなさそうです。
ただ一回毎のアップグレードには時間がかかるためkubectl -n gitlab logs -l name=gitlab
のようにログを確認して全ての処理が完了したことを確認して、さらにWebブラウザからAdmin Consoleを確認し、Background Migrationsが全て完了していることを確認しながら次のアップグレードに進む慎重さが必要です。
v16からv17にアップグレードする時にはドキュメントにいくつか指示があります。
- Migrating to the new runner registration workflowに従ってRunnerの古いregistration tokens機能を利用している場合はv17でtokenの発行停止、v18以降で機能自体が削除されるので対応が必要
- Gitalyのstorage設定で重複したパスを設定しないこと
- v17.1のバグで直接v16.xからアップグレードするとBackground Migration Jobsが永遠に完了しない
Gitalyの設定についてはgitlabのPodに入って$ /home/git/gitaly/config.toml
を確認します。Sameersbn版では設定可能な場所ではないのでデフォルト設定で使っている分には該当しません。
Background Migrationsが終わらないのは嫌なので、ワークアラウンドに記載されているv17.0.x系列のv17.0.3を経由してアップグレードする方法を採用しました。