GitLabバージョンアップにおける問題対応 後編

カバー

[!] この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

前回は、GitLabバージョンアップの背景、システム構成変更、バージョンアップ手順、バージョンアップ時に起きた問題の対応方法を解説しました。
今回は、引き続きバージョンアップ時に起きた問題の対応方法を解説します。

バージョンアップ時に起きた問題対応

画像ファイルが表示されない問題

v13.11.7に上げた際、Wikiの一部の画像ファイルが表示されない問題が起きました。

failure
原因を調査したところ、バージョンアップにより画像ファイルの管理方法が変更になったことが分かりました。
以下の図のように、v12.0.3までは1つのプロジェクト内で作成した画像ファイルを別のプロジェクトにコピー&ペーストした場合、コピー先に画像ファイルは作成されず、コピー元のプロジェクトから参照する仕組みでした。これがv13.11.7ではコピー先のプロジェクトに画像ファイルを作成する方法に変更されました。

image-dir

この管理方法の変更の影響により、バージョンアップを行うと、別プロジェクトの画像ファイルを参照していたプロジェクトでは、画像ファイルが表示されない問題が起きるようになりました。

image-dir2

私たちはこの問題に対して、表示されない画像ファイルを元のプロジェクトのディレクトリから、画像ファイルを表示させたいプロジェクトのディレクトリにコピーする、という内容のシェルスクリプトを作成して対応しました。
シェルスクリプトの具体的な処理内容は以下の通りです。

  • 表示されない画像ファイルのURLをスクリプトの引数として受け取る
  • GitLabのAPIにcurlでGetリクエストを送り、プロジェクトのIDを取得
  • 画像ファイルのURLのhash値部分からコピー元のファイルの格納場所を取得
  • コピー先ディレクトリを作成
  • コピー元からコピー先へファイルをコピー

以下はシェルスクリプトの例です。

#!/bin/sh

if [ $# != 1 ]; then
  echo "Usage: $0 <Invisible Image URL>"
  exit 1
fi

BASEPATH=/path-to-data/data/gitlab-rails/uploads/@hashed/
BASEURL=api/v4/projects/

TOPURL=`echo -n $1 | grep -o ".*my-gitlab-domain.com/"`
PJPATH=`echo -n $1 | grep -oP "(?<=$TOPURL).+?(?=/uploads/)" | sed 's/\//%2f/g'`

echo プロジェクトIDを取得
PJID=`curl -ks $TOPURL$BASEURL$PJPATH | grep -oP '(?<=^{"id":).+?(?=,")'`
if [ "$PJID" = "" ]; then
  echo プロジェクトIDが取得できませんでした。
  echo $TOPURL$BASEURL$PJPATH
  echo 異常終了
  exit 1
fi
echo プロジェクトID:$PJID
PJID=`echo -n $PJID | sha256sum | awk '{print $1}'`

FNAME=`echo $1 | grep -oP '(?<=/)([^/]+$)'`

echo コピー元ファイルを検索
SRCDIR=`echo "$1" | egrep -o "[0-9a-z]{32}"`
PATH1=`echo $PJID | cut -b 1-2 -`
PATH2=`echo $PJID | cut -b 3-4 -`
SRCPATH=`find $BASEPATH -name $SRCDIR -type d`

if [ "$SRCPATH" = "" ]; then
  echo find $BASEPATH -name $SRCDIR -type d
  echo コピー元ファイルが検索できませんでした。
  echo 異常終了
  exit 1
fi

if [ `echo $SRCPATH | tr " " "\n" | wc -l` != 1 ]; then
  echo コピー元ファイルが複数検索されました。
  echo $SRCPATH | tr " " "\n" | grep $SRCDIR
  echo 異常終了
  exit 1
fi

if [ ! -e $SRCPATH/$FNAME ]; then
  echo コピー元ファイルが検索できませんでした。
  echo $SRCPATH/$FNAME
  echo 異常終了
  exit 1
fi

echo コピー元ファイル:`ls -ld $SRCPATH/$FNAME`

echo コピー先ディレクトリ作成
mkdir -p $BASEPATH$PATH1/$PATH2/$PJID/$SRCDIR/
if [ ! -e $BASEPATH$PATH1/$PATH2/$PJID/$SRCDIR/ ]; then
  echo コピー先ディレクトリが作成できませんでした。
  echo コピー先ディレクトリ:$BASEPATH$PATH1/$PATH2/$PJID/$SRCDIR/
  echo 異常終了
  exit 1
fi

echo コピー元ファイルをコピー
cp -p $SRCPATH/$FNAME $BASEPATH$PATH1/$PATH2/$PJID/$SRCDIR/

if [ ! -e $BASEPATH$PATH1/$PATH2/$PJID/$SRCDIR/$FNAME ]; then
  echo コピー元ファイルをコピーできませんでした。
  echo コピー先ファイル:$BASEPATH$PATH1/$PATH2/$PJID/$SRCDIR/$FNAME
  echo 異常終了
  exit 1
fi

echo コピー先ファイル:`ls -ld $BASEPATH$PATH1/$PATH2/$PJID/$SRCDIR/$FNAME`
echo 正常終了

リストアに失敗する問題

バージョンアップの検証中にGitLabのバックアップからリストアしようとすると、以下のメッセージが出力されリストアに失敗することがありました。

Errno::ENOENT: No such file or directory - /var/opt/gitlab/backups/registry.tar.gz

原因を調査したところ、registry機能が無効になっているGitLabからバックアップを取得し、registry機能が有効になっているGitLabにリストアしようとすると、このエラーメッセージが出力されることが分かりました。
具体的には、registry機能が有効になっているGitLabにリストアしようとすると、GitLabはregistry機能がリストア対象に含まれていると判断して、registry.tar.gzというファイルを探します。しかし、バックアップを取得したGitLabではregistry機能を使用していないため、registry.tar.gzはバックアップに含まれません。そのため、リストアに必要なファイルが存在しないことになり、上記のエラーメッセージが出力されます。
この問題の対策は2つあります。
1つ目は、バックアップを取得する際、以下のようにコマンドのオプションとしてSKIP=registryを指定する方法です。

gitlab-backup create SKIP=registry

このオプションを指定することにより、バックアップにregistry.tar.gzが除外されたことをリストア時にGitLabが認識するため、エラーメッセージが出力されません。
2つ目は、バックアップに含まれるファイル(backup_information.yml)の:skipped:の行に、registryという文言を追加する方法です。
backup_information.ymlにはバックアップのメタ情報が含まれており、:skipped:の行にはバックアップから除外した機能が記載されます。この修正を行うことで、リストア時にGitLabがbackup_information.ymlを参照し、バックアップにregistry.tar.gzが含まれていないことを認識するため、エラーメッセージが出力されません。

数式が正しく表示されない問題

v13.11.7でWikiのページを開くとき、以下の2つの問題が起きました。

  • 数式が含まれている部分が表示されない
  • ボタンを押下すると数式が表示されるが意図せず改行が入る

数式が表示されない問題ですが、本来は以下の図のように表示されます。

math3

しかし、v13.11.7では以下の図のように数式が表示されない場合があります。

math1

上記のDisplay anywayというボタンを押下すると、以下の図のように本来の数式が表示されますが、意図せず改行が入ってしまいます。

math2

この問題の原因は、Wikiのページを表示する際にタイマーが設定されており、画像ファイルが多く貼り付けてあるWikiのページを表示しようとしてタイムアウトしたことです。原因となっているソースファイル(main.3987bf13.chunk.js)を以下に記載します。

.removeAttribute("style"),this.totalMS>=m||i.length

mはタイマーの時間を指定する変数で、値は2e3(2秒)が入ります。私たちは、対策としてタイマーを9e3(9秒)に伸ばすことでタイムアウトを回避する方法を採用しました。v13.11.7のイメージをビルドする際に、ソースファイルを以下のように修正しました。

.removeAttribute("style"),this.totalMS>=9e3||i.length

v13.11.7のイメージをビルドする際に使用したDockerfileの例です。最後の3行にソースファイル修正の処理が入っています。

FROM docker.io/gitlab/gitlab-ce:13.11.7-ce.0

ENV http_proxy=http://proxy-example.com/
ENV https_proxy=http://proxy-example.com/

RUN apt-get update -q && \
    apt-get install -yq patch language-pack-ja-base language-pack-ja && \
    update-locale LANG=ja_JP.UTF-8 LANGUAGE=ja_JP:ja

ENV LANG ja_JP.UTF-8
ENV LC_ALL ja_JP.UTF-8
ENV LC_CTYPE ja_JP.UTF-8

RUN unlink /etc/localtime && \
    ln -s /usr/share/zoneinfo/Japan /etc/localtime

RUN apt-get clean

#patch main.3987bf13.chunk.js line 20
RUN /usr/bin/sed -i -e 's/totalMS>=m/totalMS>=9e3/' /opt/gitlab/embedded/service/gitlab-rails/public/assets/webpack/main.3987bf13.chunk.js && \
rm -f /opt/gitlab/embedded/service/gitlab-rails/public/assets/webpack/main.3987bf13.chunk.js.gz

スニペットが移行されない問題

バージョンアップ環境でv13.11.7に上げた後、バックアップを取得して本番環境でリストアしようとしたところ、以下のメッセージが出力されて、スニペットのリストアに失敗しました。

Snippet snippets/13 can't be restored: Error: Repository has more than one branch.

GitLabのv13.0からスニペットをGitで管理するようになり、従来のスニペットは自動でGitへの移行が行われる仕組みになりました。
上記のエラーの原因は、この移行作業が失敗したことです。
対策として、v13.0.14に上げた時点で、移行に失敗したスニペットを手動で移行させることにしました。移行方法は以下の通りです。

  • 移行されていないスニペットのIDを確認
gitlab-rake gitlab:snippets:list_non_migrated
  • 手動で移行
gitlab-rake gitlab:snippets:migrate SNIPPET_IDS="移行されていないスニペットのID"

この対策を行うことで、無事に全てのスニペットを移行することができました。
全てのスニペットが移行されていることは、上記の移行されていないスニペットのIDを確認するコマンドを実行した際に出力される、以下のメッセージにより確認できます。

All snippets were migrated successfully

ブランチのページ切り替えができない問題

リリース後に、ブランチのページ切り替えが正常に行えないという問い合わせがありました。
プロジェクト毎のページで画面左端のRepository→Branchesを選択すると、プロジェクト内のブランチ一覧が表示されます。
ブランチの数が20を超えると複数ページに分かれて表示されますが、ページ送りするためのNextボタン(下図赤枠)を押下すると、次のページではなく最初と同じページが表示されてしまいます。

branches

これはGitLabのバグが原因であり、NextボタンとリンクしているページのURLが以下のようになっています。

https://gitlab-domain/group-name/project-name/-/branches/active?offset=1&page_token=Branch004&sort=updated_desc

以下のように末尾にpage=を含めたものが正しいURLであり、ブラウザにこのURLを入力すると、期待したページが表示されることを確認しました。

https://gitlab-domain/group-name/project-name/-/branches/active?offset=1&page_token=Branch004&sort=updated_desc&page=2

この問題への対応として、私たちはFeature flag(GitLabが用意する、コマンドラインを使用して動的に設定変更を行う仕組み)を用いて2つのパラメータ(branches_pagination_without_countとbranch_list_keyset_pagination)をdisabledに設定しました。以下は設定する際に使用するコマンドです(Rails consoleを使用します)。

irb(main):XXX:0> Feature.disable(:branches_pagination_without_count)
irb(main):XXX:0> Feature.disable(:branch_list_keyset_pagination)

この設定を行うことにより、ページ送りするボタンが以下の図のように変更され、Nextボタンを押下した際にも期待したページが表示されることを確認しました。

count

注意点として、このパラメータを設定してから反映されるまで、数時間の待ち時間が発生します。

おわりに

本記事ではGitLabをバージョンアップする際の問題対応について解説しました。GitLabバージョンアップの流れを説明した前回も併せてご覧いただくと、さらにGitLabのバージョンアップへの理解が深まります。
本記事がGitLabを運用中の方やこれから導入を検討する方のお役に立てば幸いです。


TOP
アルファロゴ 株式会社アルファシステムズは、ITサービス事業を展開しています。このブログでは、技術的な取り組みを紹介しています。X(旧Twitter)で更新通知をしています。