fbpx

GitLabのコミュニティSlackでトラブルシューティングをした話

こんにちわ。クリエーションラインのDevOps Solution Team所属の佐藤です。

GitLabを自社サーバーにインストールして運用していて、トラブルが発生して困った経験はないでしょうか?
この記事では、GitLabのコニュニティSlackで実施した、GitLabのトラブルシューティングについて解説します。

GitLabのコミュニティSlackについて

GitLabについて日本語で情報交換ができる場所としてGitLabのコミュニティSlackがあります。
私も参加していて気が向いたときに質問に回答をしていますが、あまり活発ではないのでこのブログで興味を持っていただけたらぜひ参加をしてみてください。

記事の形式

この記事では、GitLabのコミュニティSlackの#questionチャンネルに投稿された質問について、私が実施したトラブルシューティングについて解説します。

GitLabのコミュニティSlackは無料版のため、3ヶ月以上前のログは表示できなくなります。そのため、冗長ですがSlackのスレッドをすべて転載した上で、私が実施したトラブルシューティングについて解説します。

登場人物

Slackのスレッドの登場人物について簡単に説明します。

sue445

質問者のsue445さんは「Software Design 2020年1月号」の「自前でGitLabを管理するために知っておかなければならないこと」の著者で、GitLabの運用にはかなり詳しい方です。
そのため、GitLabの運用にかなり詳しい方という前提で、Slackのスレッドのログをお読みください。

jeffi7

回答者のjeffi7さんはGitLabコミュニティのオーガナイザーの一人です。また、クリエーションラインでは、GitLabのコンサルティングやテクニカルサポートなどを担当しています。

hiroponz

もう一人の回答者のhiroponzはこの記事の執筆者の私です。GitLabのコントリビューターであり、月間MVPを3回受賞したことがあります。

Slackのスレッドのログ

GitLabのコミュニティSlackでトラブルシューティングを実施したスレッドのログを以下に転載します。

sue445 2023年5月20日 23:17:34

【質問】社内のGitLabを15.6.1から15.11.3に上げたところ、リポジトリに権限があるにも関わらずIssueで「This issue is locked. Only project members can comment. Learn more」と表示されコメントの表示や書き込みができなくなってしまいました。
おそらくこのバージョン間でGitLabのデフォルトの設定が変わったことが予想されるのですが設定箇所が見つかりません。
この権限の設定を以前と同じようにする(リポジトリにDeveloper以上の権限を持っていればissueのコメントの閲覧や書き込みができるようにする)にはどうすれば良いでしょうか?
お手数おかけしますがよろしくお願いします。

sue445 2023年5月20日 23:32:19

【補足】 https://hub.docker.com/r/gitlab/gitlab-ce にあるDockerイメージを使っています。

sue445 2023年5月20日 23:54:03

該当のissueがunlockedの状態でもlock扱いになっている…?

jeffi7 2023年5月21日 00:22:39

しかも、ほんとうはlockしていても、プロジェクトメンバーはコメントできるはずですよね。
本来あり得ないことが起きているので、DBになにか不整合が起きてる感じがします。
Admin Area > Monitoring > Background Migrations で Fail しているものがないでしょうか?
それから、sudo gitlab-rake db:migrate:status の結果が全行 up でしょうか?

sue445 2023年5月21日 00:45:11

@jeffi7 回答ありがとうございます。

Admin Area > Monitoring > Background Migrations で Fail しているものがないでしょうか?

Background Migrationsは全部終了してるようでした

それから、sudo gitlab-rake db:migrate:status の結果が全行 up でしょうか?

gitlab-rake db:migrate:status の結果を見ましたがmigrationは全部あたっているようです

root@69a78640f33b:/# gitlab-rake db:migrate:status | wc -l
5928

root@69a78640f33b:/# gitlab-rake db:migrate:status | grep " up " | wc -l
5922

root@69a78640f33b:/# gitlab-rake db:migrate:status | grep -v " up "

database: gitlabhq_production

 Status   Migration ID    Migration Name
--------------------------------------------------


root@69a78640f33b:/# gitlab-rake db:migrate:status | grep " down " | wc -l
0

sue445 2023年5月21日 00:51:32

データ不整合で思い出したのですが、 db:migrate 中に https://gitlab.com/gitlab-org/gitlab/-/blob/master/db/post_migrate/20221118104752_validate_not_null_contraint_to_issues_namespace_id.rb でエラーになっていました。(issuesのnamespace_idがNULLになっているレコードが存在していてチェック制約に引っかかった)

ci: == 20221118104752 ValidateNotNullContraintToIssuesNamespaceId: migrating ======
ci: -- execute("ALTER TABLE issues VALIDATE CONSTRAINT check_c33362cd43;")
/home/runner/work/gcp-gitlab-playbook/gcp-gitlab-playbook/.github/workflows/util.rb:7:in `system': Command failed with exit 1: gcloud (RuntimeError)
    from /home/runner/work/gcp-gitlab-playbook/gcp-gitlab-playbook/.github/workflows/util.rb:7:in `sh'
    from ./.github/workflows/run_ansible.rb:121:in `<main>'

そのため、下記のようなSQLでnamespace_idを一括で設定していました。

update issues SET namespace_id = projects.namespace_id FROM projects where issues.namespace_id IS NULL AND projects.id = project_id

sue445 2023年5月21日 09:33:17

新しく作ったissueに対してもThis issue is lockedって表示が出るのでupdateは関係ないように見えるな…

sue445 2023年5月21日 10:01:41

念のためissueも投げてます
https://gitlab.com/gitlab-org/gitlab/-/issues/412375

jeffi7 2023年5月21日 10:16:41

「関係あるかないかわからないけど」と ValidateNotNullContraintToIssuesNamespaceId がエラーになったこと、SQLで namespace?id を update したことも、書き添えておくといいかもですね。
ValidateNotNullContraintToIssuesNamespaceId がエラーになったということは、これに該当していて、
https://docs.gitlab.com/ee/update/#1570:~:text=A%20database%20constraint,database%20migration%20error.
つまり、15.4 で namespace_id を backfill するマイグ レーションが、今回のアップデート前に完了していなかったということなんですが、
ここからは、調べきっていなくて確証がないんですが、
その対処がシンプルに namespace_id を update するだけでよかったのかどうかが、気になっています。
15.4 の namespace_id backfill に関係しそうなマイグレーションが、名前から見る限りこれだけあるんで (中身を見ずに言ってますが) もうちょっとややこしいことをしてたのではないかと。

20220914005141 ChangeNamespaceIdNotNullInMembers
20221004092038 TmpIndexMembersOnIdWhereNamespaceIdNull
20221018081416 MembersRemoveMemberNamespaceIdNotNullConstraint
20221103073328 ChangeMemberNamespaceIdNotNull
20221103084213 RemoveTmpIndexMembersOnIdWhereNamespaceIdNull
20221107220420 ValidateNotNullConstraintOnMemberNamespaceId ←これは今回ひっかかったやつ

sue445 2023年5月21日 10:26:09

db:migrateでエラーになったのでupdateした旨も追記しました

hiroponz 2023年5月21日 10:38:36

とりあえず、GitLab 15.11のアップデートで発生するmigrationのエラーのイシューを見つけたのでリンクを貼ります。
https://gitlab.com/gitlab-org/gitlab/-/issues/408835
コメントにwork aroundが書いてあるので、試してみてはいかがでしょうか?
https://gitlab.com/gitlab-org/gitlab/-/issues/408835#note_1373467326

hiroponz 2023年5月21日 10:50:56

408835 の中身を読みましたが、イシューがロックされる問題とは関係なさそうですね。発生バージョンとmigrationエラーということで、関係があると推測しましたが、見当違いっぽいです。

hiroponz 2023年5月21日 11:12:06

関係があるか分かりませんが、以下のようなイシューを見つけたので、sidekiqでエラーが発生していないか確認をしていただけませんか?

hiroponz 2023年5月21日 11:12:09

https://gitlab.com/gitlab-org/gitlab/-/issues/241672

sue445 2023年5月21日 11:18:55

sidekiqのログを見ましたがsidekiqのdeprecation warning以外は出てなさそうです。

root@69a78640f33b:/# cat /var/log/gitlab/sidekiq/current | grep '"severity":"WARN"'
{"severity":"WARN","time":"2023-05-21T02:08:27.809Z","message":"Job arguments to FlushCounterIncrementsWorker do not serialize to JSON safely. This will raise an error in\nSidekiq 7.0. See https://github.com/mperham/sidekiq/wiki/Best-Practices or raise an error today\nby calling `Sidekiq.strict_args!` during Sidekiq initialization.\n"}
{"severity":"WARN","time":"2023-05-21T02:15:43.963Z","message":"Job arguments to PipelineNotificationWorker do not serialize to JSON safely. This will raise an error in\nSidekiq 7.0. See https://github.com/mperham/sidekiq/wiki/Best-Practices or raise an error today\nby calling `Sidekiq.strict_args!` during Sidekiq initialization.\n"}

root@69a78640f33b:/# cat /var/log/gitlab/sidekiq/current | grep '"severity":"ERROR"'
root@69a78640f33b:/#

sue445 2023年5月21日 11:21:54

db:migrate 後もRailsやsidekiqが古いスキーマのキャッシュを持ち続けてエラーになる事象は以前ハマったことがあって、 db:migrate 後に明示的にコンテナを再起動するような対応を入れているのでそこの再発はもうしないはず…

hiroponz 2023年5月21日 11:31:56

類似のイシューを探しましたが見つからないので、環境依存の問題な気がします。
ちなみに、該当イシューのissuesテーブルのdisscoussion_lockedの値はtrueになっている感じでしょうか?多分この値がイシューのロック状態を保持していると思います。
https://gitlab.com/gitlab-org/gitlab/-/blob/v15.11.5-ee/db/structure.sql?ref_type=tags#L17492

sue445 2023年5月21日 11:35:36

discussion_locked?false になっていました

irb(main):014:0> Project.find(2).issues.find_by(iid: 3).discussion_locked?
=> false

hiroponz 2023年5月21日 11:45:41

ちなみに、GitLabサーバー側のログ、およびブラウザのコンソールには、関連しそうなエラーは出力されていないでしょうか?

sue445 2023年5月21日 11:54:22

サーバサイドとフロントエンド、ともに特にエラーは出ていなかったです。
issueのコメントはフロントエンドから /:namespace/:repo_name/noteable/issue/:issue_iid/notes でとってきてますが、chromeの開発者ツールで見ると空っぽのようでした。(ステータスコードは304)

{"last_fetched_at":1684637203230917,"notes":[]}

gitlab.com だと200を返しているのでちょっと気になってます。

hiroponz 2023年5月21日 11:58:03

304だとブラウザ側のキャッシュの影響が考えらえるので、ブラウザのキャッシュをクリアして変化がないか試していただけますか?

sue445 2023年5月21日 12:00:20

シークレットウィンドウでも同じでした

sue445 2023年5月21日 12:37:38

/:namespace/:repo_name/noteable/issue/:issue_iid/notes の実装は https://gitlab.com/gitlab-org/gitlab/-/blob/v15.11.3-ee/app/controllers/concerns/notes_actions.rb?ref_type=tags#L24-27 なんですが、 Note#readable_by? がnotesを全部rejectしてそうな気配を感じます

irb(main):003:0> issue = Project.find(2).issues.find_by(iid: 1)
irb(main):004:0> issue.notes.count
=> 3
irb(main):008:0> current_user = User.find_by(username: "sue445")
irb(main):010:0> notes = issue.notes
irb(main):011:0> notes = notes.select { |n| n.readable_by?(current_user) }
=> []

hiroponz 2023年5月21日 13:01:41

関係がありそうな変更を調べていたら、下記のようなコミットが見つかりました。
https://gitlab.com/gitlab-org/gitlab/-/commit/c0092bcb3de24d05149c79a506df11d9bb4e5a1c

issue.work_item_type.widgets.include?(::WorkItems::Widgets::Notes)

上記が true を返さないと、イシューのコメントがロックされる気がします。

hiroponz 2023年5月21日 13:05:00

revertのrevertが発生していて、ツラミを感じる。
https://gitlab.com/gitlab-org/quality/engineering-productivity/master-broken-incidents/-/issues/491

sue445 2023年5月21日 13:25:45

ここまでの調査結果( NoteController#indexNote#readable_by? が怪しそう)をissueに追記しました
https://gitlab.com/gitlab-org/gitlab/-/issues/412375#note_1398636341

sue445 2023年5月21日 13:31:32

上記がtrueを返さないと、イシューのコメントがロックされる気がします。

見事にfalseが返ってきてました…

irb(main):029:0> issue.work_item_type.widgets.include?(::WorkItems::Widgets::Notes)
=> false
irb(main):030:0> issue.work_item_type.widgets
=> []
irb(main):031:0> issue.work_item_type
=> 
#<WorkItems::Type:0x00007f5afbdc5c28
 id: 1,
 base_type: "issue",
 cached_markdown_version: 1900544,
 name: "Issue",
 description: nil,
 description_html: "",
 icon_name: "issue-type-issue",
 namespace_id: nil,
 created_at: Thu, 20 Oct 2022 12:18:59.633513000 JST +09:00,
 updated_at: Thu, 20 Oct 2022 12:18:59.633513000 JST +09:00>

hiroponz 2023年5月21日 15:01:07

WorkItem関連のDB migrationに失敗しているような気がします。下記のモデルのテーブルにseedデータは存在するでしょうか?
https://gitlab.com/gitlab-org/gitlab/-/blob/v15.11.5-ee/app/models/work_items/type.rb
https://gitlab.com/gitlab-org/gitlab/-/blob/v15.11.5-ee/app/models/work_items/widget_definition.rb

hiroponz 2023年5月21日 15:02:29

WorkItem関連のseedの投入箇所は以下になります。
https://gitlab.com/gitlab-org/gitlab/-/blob/v15.11.5-ee/db/fixtures/production/003_create_base_work_item_types.rb

hiroponz 2023年5月21日 15:03:12

https://gitlab.com/gitlab-org/gitlab/-/blob/v15.11.5-ee/lib/gitlab/database_importers/work_items/base_type_importer.rb#L110-145

sue445 2023年5月21日 15:11:14

WorkItems::Type はデータが入ってたのですが WorkItems::WidgetDefinition は空でした。

irb(main):001:0> WorkItems::Type.count
=> 7
irb(main):004:0> WorkItems::Type.pluck(:name)
=> ["Issue", "Incident", "Test Case", "Requirement", "Task", "Objective", "Key Result"]
irb(main):005:0> WorkItems::WidgetDefinition.count
=> 0

sue445 2023年5月21日 15:26:48

oh…

irb(main):001:0>  Gitlab::DatabaseImporters::WorkItems::BaseTypeImporter.upsert_types
/opt/gitlab/embedded/lib/ruby/gems/3.0.0/gems/activerecord-6.1.7.2/lib/active_record/connection_adapters/postgresql_adapter.rb:672:in `exec_params': PG::SREModifyingSqlDataNotPermitted: ERROR:  Table: "work_item_widget_definitions" is write protected within this Gitlab database. (ActiveRecord::StatementInvalid)
HINT:  Make sure you are using the right database connection
CONTEXT:  PL/pgSQL function gitlab_schema_prevent_write() line 4 at RAISE
/opt/gitlab/embedded/lib/ruby/gems/3.0.0/gems/activerecord-6.1.7.2/lib/active_record/connection_adapters/postgresql_adapter.rb:672:in `exec_params': ERROR:  Table: "work_item_widget_definitions" is write protected within this Gitlab database. (PG::SREModifyingSqlDataNotPermitted)
HINT:  Make sure you are using the right database connection
CONTEXT:  PL/pgSQL function gitlab_schema_prevent_write() line 4 at RAISE

sue445 2023年5月21日 16:02:16

gitlab-rake gitlab:db:unlock_writes して Gitlab::DatabaseImporters::WorkItems::BaseTypeImporter.upsert_types を実行したらいけました。ありがとうございます!


以上がSlackのスレッドのログとなります。

トラブルシューティングの進め方

私(hiroponz)は5月21日の午前中にSlackの質問に気がついて、スレッドの内容をざっくり確認しました。
スレッドの内容をざっくり確認して感じた印象は次のようなものでした。

  • バージョンアップ時のマイグレーションで何らかの不具合を踏んでいる可能性がある。
  • 影響が大きい不具合のため、既知の不具合としてイシューに報告されている可能性が高い。

イシューでの調査

そのため、まずは関係のありそうなイシューを検索して、問題を解決出来ないか試しています。

GitLabの不具合は公式イシューに報告するルールとなっています。しかし、ここには不具合だけではなく、機能リクエストや自動テストの失敗など様々なものが登録されています。2023年8月現在は、オープン状態のものだけで5万件近くが登録されていて、目的のイシューを探すのは簡単なことではありません。

参考までに、私がGitLabのイシューを検索する際に使用しているテクニックを紹介します。

はじめに、Google検索でイシューを検索します。これは、Google検索だと目的のイシューが上位に表示されることが多いという、個人的な経験によります。この時に検索条件として「site:gitlab.com inurl:gitlab-org inurl:issues」を付けることで、GitLabのイシューに絞って検索することが出来ます。

Google検索で目的のイシューが見つからない場合は、公式イシュートラッカーで検索します。この時に不具合に関するイシューには、 ~type::bug というラベルを付けるルールとなっているので、 ~type::bug というラベルを付けて検索することで、目的のイシューを効率的に検索することが出来ます。

なお、GitLabのイシューは、デフォルトでオープン状態のイシューのみが表示されます。最新版のGitLabでは既に解決済みの不具合の可能性があるので、クローズ状態のイシューも確認するようにしましょう。

ソースコードでの調査

今回のケースでは、イシューでの調査が暗礁に乗り上げたため、ソースコードでの調査を実施しました。

GitLabはソースコードが公開されているので、誰でもソースコードを調査することが出来ます。なお、GitLab EEとCEは一つのリポジトリに統合されているため、どちらのディストリビューションを利用している場合でも、調査するのは同じリポジトリとなります。

メッセージが画面に表示される条件を調べる

調査の取っ掛かりとして、「This issue is locked. Only project members can comment. Learn more」と画面に表示される条件の調査から開始しました。

GitLabではソースコードの検索が可能なため、今回はGitLab上でソースコードの調査を実施しました。GitLab上でGitLabのソースコードを検索する手順は次の通りです。

  • GitLabにサインインします。(ソースコードを検索するにはサインインする必要があります。)
  • GitLabのリポジトリを表示します。
  • バージョンを指定するためv15.11.3-eeタグを選択します。(GitLab CEの調査であっても、-eeのタグを選択することに注意してください。)
  • 画面上部の虫眼鏡アイコンをクリックして検索窓を表示します。
  • 検索したい文字列を入力してEnterを押下します。

フロントエンド(Vue.js)のコードを調査する

今回のケースでは「Only project members can comment」で検索すると、それらしいコードがいくつかヒットします。

discussion_locked_widget.vueの中身を読むと、このコンポーネントで「This issue is locked. Only project members can comment. Learn more」というメッセージを表示していることが分かります。
そのため、「DiscussionLockedWidget」で検索して、このコンポーネントを表示する条件を調査します。
その結果、comment_form.vueの下記のコードが、「This issue is locked.」というメッセージを表示する条件であることが分かります。

    <discussion-locked-widget v-else-if="!canCreateNote" :issuable-type="noteableDisplayName" />

すなわち、 canCreateNotefalse の場合にイシューのロックのメッセージが表示されることが分かります。
canCreateNoteの定義を調べると、次のようになっています。

    canCreateNote() {
      return this.getNoteableData.current_user.can_create_note;
    },

バックエンド(Rails)のコードを調査する

続いて、「can_create_note」で検索して、この定義を調べます。その結果、issue_entity.rbに下記のコードが見つかります。

    expose :can_create_note do |issue|
      can?(request.current_user, :create_note, issue)
    end

ここで、 can? というDSLが登場します。これはGitLabの DeclarativePolicy framework の記法であり、その定義はapp/policiesディレクトリに格納されています。ここで知りたいのは、issueのpolicyなのでissue_policy.rbを確認します。すると下記のコードが見つかります。

  # accessing notes requires the notes widget to be available for work items(or issue)
  condition(:notes_widget_enabled, scope: :subject) do
    @subject.work_item_type.widgets.include?(::WorkItems::Widgets::Notes)
  end

  rule { ~notes_widget_enabled }.policy do
    prevent :create_note
    prevent :read_note
    prevent :read_internal_note
    prevent :set_note_created_at
    prevent :mark_note_as_internal
    # these actions on notes are not available on issues/work items yet,
    # but preventing any action on work item notes as long as there is no notes widget seems reasonable
    prevent :resolve_note
    prevent :reposition_note
  end

上記のコードから以下のことが分かります。

  • notes_widget_enabledfalse の場合に、 create_noteprevent される。すなわち、notes_widget_enabledfalse の場合に、 create_notefalse となる。
  • notes_widget_enabled@subject.work_item_type.widgets.include?(::WorkItems::Widgets::Notes) の評価結果と同義である。

以上から、下記の評価結果が false の場合にイシューがロックされると推測されます。

issue.work_item_type.widgets.include?(::WorkItems::Widgets::Notes)

issue_policy.rb の変更がどうやら怪しいと当たりを付けたので、 blame でどのコミットで変更されたのか確認します。その結果、下記のコミット、及びマージリクエストで変更されていることが分かります。

上記のマージリクエストは、マイルストーンが 15.8 に設定されています。これは、GitLabを15.6.1から15.11.3にバージョンアップしたタイミングで問題が発生したことと合致します。

以上から、この変更が今回のトラブルの原因と考えて、Slackで確認を進めて無事にトラブルを解決することが出来ました。

なお、Slackでのやり取りを理解するにはGitLabの運用知識やRailsアプリの開発知識が必要となりますが、この記事で説明するには分量が多くなりすぎるため、この記事では深入りはしないことにします。

おわりに

GitLabのコミュニティSlackで、私が実施したトラブルシューティングについて説明をしました。イシューでの調査方法やソースコードでの調査方法など、GitLabのトラブルシューティングを行う際の参考になれば幸いです。

また、クリエーションラインではGitLabのテクニカルサポートを提供しています。GitLabの運用に課題を感じている場合は、ぜひお気軽にご相談ください。

新規CTA