Kubernetes環境のsameersbn版GitLab 15.11.13を最新版(16.7.3→18.0.1)にしてみた

# はじめに

:::note warn
【2025/02/19】17.5.2から17.8.2に更新しました。[Upgrade Path](https://gitlab-com.gitlab.io/support/toolbox/upgrade-path/)を確認して17.5.5を経由しています。[Upgrade Guide](https://docs.gitlab.com/update/)によれば更新のタイミングで"ci_deleted_objects"に関するエラーが発生する可能性があるようです。私の環境では遭遇せずに17.8.2までバージョンアップが完了しました。
:::

:::note
17.8.2にアップグレードする際にログファイルにワーニングやエラーが記録される場合がありますが、最終的にはアップグレードに成功します。
```
warning Error running install script for optional dependency: "/home/git/gitlab/node_modules/tree-sitter: Command failed.
Exit code: 1
...
gyp ERR! build error
```
アップグレードの際には辛抱強く時間が経過するのを待つ必要があります。
:::

Kubernetesにsameersbn/gitlab:15.2.2を導入してから15.11.13にするまでの顛末については別の記事にまとめています。

* [GitlabをKubernetes環境にデプロイしてみた](https://qiita.com/YasuhiroABE/items/161510c61b94bc27190a)

脆弱性への対応のため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追記】実際にアップグレードすると再起動のタイミングで動作しなかったりしています。またバックアップからのリストアにも失敗しています。これらは解決しましたので経緯について追記しました。

:::note
この文書は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追記】これらの現象については概ね解決しましたので経緯について追記しました。
:::

:::note
v16.7.3に変更してから日毎のバックアップが取得されていません。[本家のIssue#2790](https://github.com/sameersbn/docker-gitlab/issues/2790)と原因は同じでバックアップファイルの取得には成功していますが、リストアに失敗していましたが、[ENOENT: No such file or directory #2866](https://github.com/sameersbn/docker-gitlab/issues/2866) にリンクされているパッチを適用することで解決しました。

将来的にはv16.7.4 or v16.8.x以降にアップグレードすることで解決するはずです。
:::

:::note
Podを再起動すると500エラーが発生する現象は、sameersbn版GitLab 15.6.0から発生するとのことです。

修正は16.7.4以降のコンテナに取り込まれるだろうと思われるので、それまで変更は止めた方が良いかもしれません。
:::

# 17.11.1に更新後、PostgreSQL v14からv17にバージョンを上げた時の手順

Gitlab v18以降はPostgreSQLのバージョンにv16以降を要求します。

準備のためにPostgreSQLのバージョンをv14(14.8)からv17(17.5)に更新することにしました。

``sameersbn/docker-gitlab``のIssuesでは議論が続いていますが、有志がPostgreSQL v16,v17のコンテナイメージをポストしています。

このイメージは``sameersbn/docker-gitlab``のREADME.mdにも記載されています。

今回は``kkimurak/sameersbn-postgresql:17-20250522``に更新した時の流れについてまとめておきます。

あらかじめバックアップイメージが取得されていることを確認しておきます。

```bash:あらかじめ設定してあるbash関数を利用してバックアップイメージの取得状況を確認する
function gitlab_backup_list {
  name=$(get_gitlab_podname)
  sudo kubectl -n gitlab exec -it "${name}" -- ls /home/git/data/backups/
}

$ gitlab_backup_list

Defaulted container "gitlab" out of: gitlab, chown-nodedir (init)
1747411227_2025_05_17_17.11.1_gitlab_backup.tar
1747497628_2025_05_18_17.11.1_gitlab_backup.tar
```

1. ``kubectl -n gitlab delete -f gitlab-rc.yml``の実行
2. ``kubectl -n gitlab delete -f postgresql-rc.yml``の実行
3. ``kubectl -n gitlab delete -f postgresql-pvc.yml``の実行
4. ``postgresql-rc.yml``のimage:行を修正し、``kkimurak/sameersbn-postgresql:17-20250522``に変更
5. (3)〜(1)の逆順に``delete``を``apply``に変更したコマンドを順次実行
6. Gitlabインスタンスが起動後、[GitLabのリストア手順](#gitLabのリストア手順)に従ってリストアを行う

:::note
PostgreSQLテーブルのリストア後に、リポジトリの復旧でエラーが出る場合がありました。
``gitlab:backup:restore``タスクのコマンドラインに``SKIP=db``を指定して再度リストア作業を行うことで復旧しています。

詳細は下記の記事を参照してください。

* [Gitlabのリストアに失敗したので調べてみた](https://qiita.com/YasuhiroABE/items/82110434907ce2050e71)
:::

``postgresql-rc.yml``ファイルは次のような内容にしています。

```diff:
diff --git a/gitlab/yaml/postgresql-rc.yml b/gitlab/yaml/postgresql-rc.yml
index 759f5b5..0d81fd7 100644
--- a/gitlab/yaml/postgresql-rc.yml
+++ b/gitlab/yaml/postgresql-rc.yml
@@ -17,7 +17,7 @@ spec:
     spec:
       containers:
       - name: postgresql
-        image: sameersbn/postgresql:14-20230628
+        image: kkimurak/sameersbn-postgresql:17-20250522
         env:
         - name: DB_USER
           value: gitlab
```

PostgreSQL v14からv17へのアップグレードはリストアで問題なく完了しています。

この後、Gitlabをv17.11.3→v18.0.1と更新して問題なく動作しています。

# 16.7.3に更新後、Podを再起動したらサービスが復旧しなくなった障害対応の顛末

:::note
一連の問題の根本原因は/home/git/gitlab/public/assetsがシンボリックリンクからディレクトリに上書きされてしまうことでした。
:::

テスト系に検証環境を構築するため、本番のバックアップファイルを転送してリストアします。

## GitLabのリストア手順

本番のv15.11.13のバックアップイメージからテスト環境にコピーサイトを構築します。

バックアップファイルとリストア先のサーバーはGitLabのバージョンが一致しなければいけません。

本番系で取得できていたファイルはGitLab v15.11.13のものなので、まずこのバージョンを稼動させてリストアしていきます。

まず素の何も設定しないGitLab v15.11.13を起動します。これをしないとコンテナ内部で/home/git/gitlab/node_modules/ディレクトリが空のままとなってしまいます。

```bash:docker-gitlab/kubernetes/以下のYAMLファイルをベースにしています
$ 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分程度待ちました。

起動直後はしばらくエラーかと思われるログが出ていますが、しばらく待つと追加の初期化処理が進みます。

```text:正常系でも次のようなメッセージが延々と記録されている
...
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ファイルに作業の内容が出力されています。

```bash:
## コンテナに保存されている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:** パラメータを加えます。

```bash:gitlab-rc.ymlファイルの変更箇所から抜粋
## 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を再起動します。

```bash: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}')
```

このコンテナが稼動したら``kubectl exec``で中に入って復旧作業を実施していきますが、その前に本番環境のバックアップファイルをテスト環境にコピーした上で、さらにgitlabのPod内部に配置します。

``gitlab-q7j25``はPod名で、書式はscpやrsyncなどと類似のものです。

```bash:kubectlコマンドによるバックアップファイルの転送
## バックアップファイルを/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**)に入ってリストア作業を行います。

```bash:
$ sudo kubectl -n gitlab exec -it gitlab-q7j25 -- bash
root@gitlab-q7j25# 
```

プロンプトが変化したことを確認してからリストア作業を実施しますが、[sameersbn版GitHubリポジトリのRestore手順](https://github.com/sameersbn/docker-gitlab#restoring-backups)ではdockerやdocker-composeコマンドを利用した場合しか掲載されていません。

:::note
これら手順にある``app:rake``はコマンド名というよりも、``/sbin/entrypoint.sh``スクリプトに対する命令です。DockerfileではこれがENTRYPOINTに指定されていて、デフォルトの``app:start``タスク名がCMDに指定されています。

コンテナの内部に入ってから直接``rake``コマンドや``bundle exec rake``などを呼び出しす行為は権限などの問題で正常に動作しません。

必ず``/sbin/entrypoint.sh``の引数にコマンドを渡すことで作業を進めていきます。
:::

``/sbin/entrypoint.sh``を経由する点にだけ気をつければ、時間はかかるものの作業自体は難しくありません。

```bash:K8s版のリストア手順
## リストアタスクを実行する
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分程度で終了しました。

終了時点での画面の出力は次のようになっています。

```text:gitlab:backup:restoreタスクが完了した端末画面
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:パラメータをコメントアウトします。

```yaml:gitlab-rc.ymlファイルの変更箇所
      containers:                            
      - name: gitlab         
        image: sameersbn/gitlab:15.11.13    
        # args: ["sh","-c","--","while true; do sleep 30; done"]
```

この内容をapplyしてからPodを削除して再起動します。

```bash:再び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}')
```

これで``/sbin/entrypoint.sh``の引数に``app:start``が指定され、Recompiling assetsなどが自動的に実行されて無事に動作するはずです。

アプリケーションの起動には10分程度は放置する必要がありました。

```text:gitlabコンテナのログメッセージ
...
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](https://github.com/sameersbn/docker-gitlab/issues/2790)のように何かしら不足するディレクトリなどがあるのだと思います。

まずはバックアップファイルを作成させてエラーメッセージなどを確認します。

```bash:
$ 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と同じでしたので、このディレクトリを作成してから、再度バックアップを取得して他に問題がないか確認します。

```bash:
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を検索しているとバックアップ取得後にシステムがエラーとなることが報告されています。

* [github.com/sameersbn/docker-gitlab Issues #1655](https://github.com/sameersbn/docker-gitlab/issues/1655)

このIssuesの結論はバックアップから戻せるよ、というものなので参考にはなりませんでした。

このままでは毎日のバックアップ取得後にシステムが停止するかと思いましたが、15.11.13から16.7.3にアップグレードした本番サーバーはディレクトリを作成したまま様子をみていたところ毎日午前1時のバックアップが無事に取得できていました。

この問題は複数の状況が関係しているようで、一つは単純にリストアに失敗しているものです。起動処理が完了しない間に次の手続きに移ってしまうと問題が発生するので、前述のリストア手順に手掛りとなるようなログファイルやコンソールの様子を追記して処理が完結してから次に進むようにメモを追加しました。

もう一つは今日になって解決した以下の問題です。

## GitLab v16.7.3で取得したバックアップファイルがリストアできない問題について

v16.7.3でバックアップファイルが取得できるようになってもリストアにどこまでも失敗していました。

コンテナの``log/production.log``ファイルを確認すると、次のようなメッセージが表示されていましたが、指示どおりにrakeタスクを実行しても解決しません。

```text:再起動して500エラーを返しているgitlabコンテナのlog/production.log
...
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が上がっているようです。

* [ENOENT: No such file or directory #2866](https://github.com/sameersbn/docker-gitlab/issues/2866)
* [この問題に対応するPR#2884](https://github.com/sameersbn/docker-gitlab/pull/2884)


アップグレードは元記事のように実行して、v16.7.3のコンテナが無事に起動してからもWebブラウザで500エラーが発生している状態で、次のような対応を実施します。

また、エディタは導入されていないので、GNU nanoを導入してから編集しています。

```bash:
## 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がテスト系で稼動しました。

:::note
public/assetsがシンボリックリンクではなくディレクトリの場合は、data/tmp/assetsの内容が空であったり古かったりすると、再起動したタイミングでpublic/assetsがdata/tmp/assetsを参照することで障害が発生します。

アップグレードした直後で問題なく稼動している、v16.7.3にアップグレードした直後でWebページが500エラーとなっている場合は、rsyncなどでpublic/assets/.の内容をdata/tmp/assets/.にコピーしておくことをお勧めします。

```bash:
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ファイルです。

```yaml:最終的に利用している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を準備しています。

```yaml:gitlab-data-pvc.yaml
---
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にアップグレードした時の元記事

:::note
ここから先の記事は当初に投稿した内容です。
:::

# 環境

* 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/)
* [https://docs.gitlab.com/ee/update/versions/gitlab_16_changes.html](https://docs.gitlab.com/ee/update/versions/gitlab_16_changes.html) ([#issues-to-be-aware-of-when-upgrading-from-1511](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-gitlab)
* [https://github.com/sameersbn/docker-postgresql](https://github.com/sameersbn/docker-postgresql)

関連する作業について既存のドキュメントを参照してください。

* [Veleroによるバックアップの取得について](https://qiita.com/YasuhiroABE/items/d625bb13b41fd1456d00)
* [GitLabのバックアップの取得について](https://qiita.com/YasuhiroABE/items/161510c61b94bc27190a#%E3%82%A2%E3%83%83%E3%83%97%E3%82%B0%E3%83%AC%E3%83%BC%E3%83%89%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)

# 懸念点

まず[本家のドキュメント GitLab 16 changes](https://docs.gitlab.com/ee/update/versions/gitlab_16_changes.html)と、[sameersbnのGitHub/README.md](https://github.com/sameersbn/docker-gitlab)の2つを確認する必要があります。

1. PostgreSQLのバージョンが最低でも13以上であることが必要 (公式ガイド)
1. 15系列にバージョンアップする際、"15.11.0, 15.11.1, or 15.11.2"を経由しているとテーブルに自動修復されない変更が加えられているため個別に対応が必要 (公式ガイド)
1. 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を追加します。

```bash:対象となる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の状況を確認します。


```bash:backup.velero.io/backup-volumesアノテーションの確認
$ 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を起動し、バックアップを取得します。

```bash:次にveleroによるバックアップの取得
$ sudo velero backup create "gitlab-$(date +%Y%m%d.%H%M)" --include-namespaces gitlab --wait
```

バックアップの取得が始まると次のようなメッセージが表示され、C-cで抜けてもバックグラウンドで実行が続きます。

```text:veleroの出力例
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の場合)に応じて適切なバックアップ時間か確認します。

```bash:取得したバックアップの詳細を確認する
$ 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/からバックアップを取得します。

以下の操作ログはテスト系で実施した際のものです。

```bash:バックアップ対象のファイル名を確認
$ 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クラスター外にコピーします。

```bash:kubectlのcpコマンドによりファイルをコピーする
$ 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チェックサムの値でも確認しておきます。

```bash:
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に該当するか確認します。

```bash:
$ 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コマンドを起動します。

```bash:
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のバージョンアップ

主な作業手順は以下のとおりです。

1. PostgreSQLのイメージをv14(sameersbn/docker-postgresql:14-20230628)に更新します
2. GitLabのReplicationControllerオブジェクト定義を削除し、Podを停止させる
3. PostgreSQLのYAMLファイルで新バージョンに変更して適用後に手動でPodを削除することで再起動させる
4. 起動したPostgreSQLのログを確認する

```bash:起動したPostgreSQL Podのログを確認する
$ 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のステータスが正常になります。

```bash: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は起動してからアップグレード処理を行うため、ログファイルを確認しながら辛抱強く完了まで待ちます。

```bash:
$ 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ページ](https://gitlab-com.gitlab.io/support/toolbox/upgrade-path/?current=16.7.3&edition=ce)を確認すると最新版(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](https://docs.gitlab.com/ee/ci/runners/new_creation_workflow.html)に従って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を経由してアップグレードする方法を採用しました。