Gitaly サービスのデバッグ

このドキュメントについて

このドキュメントは Gitaly エンジニア向けに作成されており、GitLab の本番環境のレイアウトを把握し、本番環境の問題を効果的にデバッグする能力を身につけることを目的としています。SaaS に重点を置いていますが、多くのスキルはセルフマネージドインスタンスのデバッグにも応用できます。

GitLab の一般的な背景

以下を読み/ざっと目を通し、まず概要を把握してから Gitaly に集中してください:

その他の有用なリンク:

Gitaly 固有の背景

本番環境における Gitaly

gitlab.com と Dedicated はいずれも「シャード」モード、すなわち Praefect(Gitaly Cluster)を使用しない形で Gitaly を使用しています。

モニタリングダッシュボード

GitLab の内部 Grafana インスタンスには、便利なプリビルトのモニタリングダッシュボードが用意されています。すべてのダッシュボードはこのフォルダに一覧されています。一部は古くなっている場合があることに注意してください。

よく使用されるダッシュボードは次のとおりです:

Gitaly のダッシュボードは自動生成されたものと手動で作成されたものがあります。ダッシュボードをコードとして管理するために Jsonnet(JSON のスーパーセット)を使用しています。このようなダッシュボードの定義はこのフォルダにあります。近年、これが可観測性ダッシュボードを管理する推奨方法です。GitLab の組み込みライブラリを使用でき、高度に標準化されたダッシュボードが実現します。

標準化されたダッシュボードには、環境フィルター、ノードフィルター、フィーチャーフラグアクティビティやデプロイなどの有用なアノテーションを含むトップレベルセクションが必要です。一部のダッシュボードには、Grafana と Kibana をワンクリックで接続する相互リンクシステムがあります。

このようなダッシュボードは通常 2 つの部分で構成されています。後半には Gitaly から収集したカスタムメトリクスのパネルが含まれています。前半はより複雑で、Gitaly が「正常」かどうかを示す GitLab 全体の指標と、ノードレベルのリソースメトリクスが含まれています。集計と計算は高度です。要約すると、これらのダッシュボードは事前定義されたしきい値に従って Gitaly が正常に機能しているかどうかを示します。質問があればObservability チームにお問い合わせください。

Gitaly デバッグインジケーター

エンジニアの視点から、組み込みダッシュボードを使用して本番問題を調査した例:

Gitaly の Prometheus メトリクス

ダッシュボードのパネルは、基となるメトリクスの集計バージョンを可視化したものです。メトリクスの収集には Prometheus を使用しています。簡単に説明すると、Gitaly サーバーは HTTP サーバー(コード)を公開しており、Prometheus インスタンスが定期的にメトリクスを取得できるようにしています。

ダッシュボードでは、右上のハンバーガーボタンをクリックして「Explore」を選択することで、基となるメトリクスにアクセスできます。またはExplore ページでメトリクスを操作することもできます。

Gitaly デバッグ Explore

残念ながら、すべての Gitaly メトリクスとその定義のキュレーションされたリストはありません。そのため、複数の場所で定義を調べる必要があるかもしれません。こちらは Gitaly 関連メトリクスの全リストです。いくつかのソースがあります:

  • ノードレベルまたは環境メトリクス。これらのメトリクスは Gitaly プロセスをホストする他のシステムによって提供されます。Gitaly では公開されませんが、たとえば CPU メトリクス、メモリメトリクス、cgroup メトリクスなど非常に有用です。
  • Gitaly 固有のメトリクス。これらのメトリクスはコードで直接計上されます。通常、gitaly_ のプレフィックスが付いています。
  • 集計メトリクス(異なるメトリクスを組み合わせたり、高カーディナリティの問題によりメトリクスを縮小したものなど)。Gitaly の集計メトリクスのリストはこのファイルに一覧されています。

Gitaly デバッグメトリクスリスト

コードでは次のようなものが見られます。登録されたメトリクスは Prometheus がエンドポイントからスクレイピングするときに利用可能になります。これらのインスタンスをトレースすることで、Gitaly 固有のメトリクスの使用方法を確認できます。

repoCounter := counter.NewRepositoryCounter(cfg.Storages)
prometheus.MustRegister(repoCounter)

packObjectsServedBytes = promauto.NewCounter(prometheus.CounterOpts{
  Name: "gitaly_pack_objects_served_bytes_total",
  Help: "Number of bytes of git-pack-objects data served to clients",
})

メトリクスにはラベルのセットがあります。GitLab はすべてのメトリクスに次のラベルセットを追加します:

  • env または environment: 環境。gprdgstgops などが含まれますが、これらに限られません。
  • fqdn: 完全修飾ドメイン名。Gitaly は現在 VM で動作しているため、このラベルはホスティングノードの識別子に相当します。
  • regionzone: ノードのリージョンとゾーン。
  • stage: プロセスの現在のステージ。main または cny のいずれか。
  • service/type: Gitaly の場合は常に gitaly

将来 Gitaly が K8s で動作するようになったとき、K8s 固有のラベルが追加される予定です。

クエリは PromQL 言語を使用します。いくつかの例:

デバッグおよびパフォーマンステストツール

  • gprcurl: gRPC 向けの curl のようなツール
  • grpcui: gRPC 向けの軽量な postman のようなツール
  • hyperfine: 時間経過とともにベンチマークを計測できるパフォーマンスツール
    • hyperfine は grpcurl と組み合わせて、gRPC 呼び出しのレスポンスタイムを確認することができます

Git トレースを有効にする

gitaly_log_git_traces フィーチャーフラグを使用すると、特定のユーザー、グループ、またはプロジェクトの Git trace2 スパンのロギングを有効にできます。有効にすると、Git はその特定のアクターが発行した gRPC ログにすべての trace2 スパンを出力します。

/chatops run feature set --project=gitlab-org/gitlab gitaly_log_git_traces true
/chatops run feature set --user=myusername gitaly_log_git_traces true

ログが大量に流れ込む頻度とノイズの多さを考慮して、カスタマーはサーバー側のログにフィルターを使用して次のいずれかのキーと値に一致させることをお勧めします:

  • "msg":"Git Trace2 API"
  • "component":"trace2hooks.log_exporter"

詳細については以下を参照してください:

クライアント側では、Git trace v1 の場合、カスタマーは次を含む GIT_TRACE* 変数を有効にすることができます:

GIT_TRACE=true
GIT_TRACE_PACK_ACCESS=true
GIT_TRACE_PACKET=true
GIT_TRACE_PERFORMANCE=true

Git trace v2 の場合:

# git 操作のデバッグ
# GIT_TRACE2_PERF_BRIEF または trace2.perfBrief が true の場合、time、file、line フィールドは省略されます。
GIT_TRACE2_PERF_BRIEF=1 GIT_TRACE2_PERF=true git clone https://gitlab.com/gitlab-org/gitaly
GIT_TRACE2_PERF_BRIEF=1 GIT_TRACE2_PERF=$(pwd)/git-perf.log git clone https://gitlab.com/gitlab-org/gitaly

# git イベントを json 形式で出力する
GIT_TRACE2_BRIEF=true GIT_TRACE2_EVENT=$(pwd)/trace2.json git clone https://gitlab.com/gitlab-org/gitaly

出力はさまざまな形式で設定できます:

# 通常形式
export GIT_TRACE2=~/log.normal
# またはパフォーマンス形式
export GIT_TRACE2_PERF=~/log.perf
# またはイベント形式
export GIT_TRACE2_EVENT=~/log.event
# または JSON 形式
export GIT_TRACE2_EVENT=~/log.json

詳細については以下を参照してください:

strace

gitaly プロセスの strace(1):

strace -fttTyyy -s 1024 -o /paht/filename -p $(pgrep -fd, gitaly)

またはプロセスをラップして strace を簡単に行えるようにする(特に後でさらにプロセスを生成する場合):

#!/bin/bash/sh
echo $(date)" $PPID $@" >> /tmp/gitlab-shell.txt
exec /opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell-orig "$@"
# strace -fttTyyy -s 1024 -o /tmp/sshd_trace-$PPID /opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell-orig

strace パーサー は結果をより読みやすくするのに役立ちます。

fast-stats

fast-stats は Support が GitLab のログから統計情報を素早く取り出すために開発した便利なツールです。

gitaly ログから 60 分間隔で最も多く呼ばれたメソッドを見つけるには:

fast-stats --interval 60m --limit 1 var/log/gitlab/gitaly/current

そのメソッドを呼び出している時間順に上位 10 件の User、Project、Client を見つけるには:

grep PostUploadPackWithSidechannel var/log/gitlab/gitaly/current | ~/bin/fast-stats --interval 60m top

git

Gitaly の Git コマンドを観察する。

  1. Gitaly を停止する
  2. gitaly-git プロセスを名前変更する: find /opt/gitlab/embedded/bin/gitaly-git-v* -exec mv {} {}_orig \;
  3. 各 git バージョンのラッパースクリプトを作成する。スクリプト内の opt/gitlab/embedded/bin/gitaly-git-vX.XX_orig を正しいバージョンに置き換えてください。
#!/bin/bash
GIT="/opt/gitlab/embedded/bin/gitaly-git-vX.XX_orig"
FILE="/tmp/gitaly-$(date +%Y-%m-%d@%H:%M)"
echo -e "\n$(date) $PPID $@\n" >> $FILE
exec $GIT "$@" | tee -a $FILE
echo -e "\n--------------\n" >> $FILE
  1. スクリプトを実行可能にする: find /opt/gitlab/embedded/bin/gitaly-git-v* -exec chmod 777 {} \;
  2. Gitaly を起動する

ログ分析

Kibana(Elastic)ダッシュボード

CPU とメモリのプロファイリング

pprof メトリクスは GCP Cloud Profiler にエクスポートされます。

Gitaly ノードは複数の GCP プロジェクトに分散しています。トップナビゲーションバーのプロジェクトドロップダウンを使用して、各種 gitlab-gitaly-gstg-* および gitlab-gitaly-gprd-* プロジェクト間を切り替えることができます。

キャパシティ管理

Gitaly チームは gitlab.com の適切なサービングキャパシティを維持する責任を負っています。

キャパシティが低下した場合は Tamland からアラートを受け取ります。詳細はこのイシューコメントを参照してください。

キャパシティプランニング ドキュメントでは、一般的な仕組みについて説明しています。