Kubernetes上のGitaly
- プラン: Free、Premium、Ultimate
- 提供形態: GitLab.com、GitLab Self-Managed、GitLab Dedicated
- ステータス: 制限付きで利用可能
KubernetesでGitalyを実行すると、可用性にトレードオフが生じるため、本番環境を計画する際にはこれらのトレードオフを考慮し、それに応じて期待値を設定してください。このドキュメントでは、既存の制限を最小限に抑え、計画する方法について説明し、ガイダンスを提供します。
タイムライン
Kubernetes上のGitalyは、Gitalyチームによって評価され、Gitalyをデプロイする安全な方法であると判断されました。このドキュメントの残りの部分では、そのためのベストプラクティスについて詳しく説明します。
社内では、この機能がGenerally Available (GA)になる前に、本番レベルのワークロードを処理できることを確認するために、Kubernetes上でGitalyのドッグフーディングのプロセスを実施しています。
FY26Q4にドッグフーディングを終了し、FY27Q1にKubernetes上のGitalyをGAに移行する予定です。
コンテキスト
設計上、Gitaly(非クラスター)は単一障害点のサービス(SPoF)です。データは、単一のインスタンスから供給され、提供されます。Kubernetesの場合、StatefulSetポッドが(たとえば、アップグレード、ノードのメンテナンス、または削除中に)ローテーションすると、そのローテーションにより、ポッドまたはインスタンスによって提供されるデータに対するサービス停止が発生します。
Cloud Native Hybrid構成(Gitaly仮想マシン)では、Linuxパッケージ(Omnibus)は、次の方法で問題をマスクします:
- Gitalyバイナリをインプレースでアップグレードします。
- 正常なリロードを実行します。
同じアプローチは、コンテナまたはポッドが完全にシャットダウンし、新しいコンテナまたはポッドとして起動する必要があるコンテナベースのライフサイクルには適合しません。
Gitalyクラスタ(Praefect)は、インスタンス間でデータをレプリケートすることにより、データとサービスの高可用性という側面を解決します。ただし、Gitalyクラスタ(Praefect)は、コンテナベースのプラットフォームによって拡張される既存のイシューと設計上の制約のため、Kubernetesでの実行には適していません。
クラウドネイティブデプロイをサポートするために、Gitaly(非クラスタ)が唯一のオプションです。適切なKubernetesおよびGitalyの機能と設定を活用することで、サービス停止を最小限に抑え、優れたユーザーエクスペリエンスを提供できます。
要件
このページの情報は、以下を前提としています:
- Kubernetesのバージョンが
1.29以上。 - Kubernetesノードの
runcのバージョンが1.1.9以上。 - Kubernetesノードcgroup v2。ネイティブ、ハイブリッドv1モードはサポートされていません。(Kubernetesのデフォルト)
systemdスタイルのcgroup構造のみがサポートされています。 - ノードマウントポイント
/sys/fs/cgroupへのポッドアクセス。 - Containerdバージョン2.1.0以降。
init-cgroupsのポッド初期化コンテナ()からrootユーザーのファイルシステム権限へのアクセス/sys/fs/cgroup。Gitalyコンテナ(ユーザーgit、固有識別子1000)にポッドcgroupを委任するために使用されます。- cgroupsファイルシステムは、
nsdelegateフラグを付けてマウントされていません。詳細については、Gitalyイシュー6480を参照してください。
ガイダンス
KubernetesでGitalyを実行する場合は、以下を実行する必要があります:
Containerdでcgroup_writableフィールドを有効にする
GitalyのCgroupサポートでは、特権のないコンテナのcgroupへの書き込みアクセスが必要です。Containerd v2.1.0では、cgroup_writable設定オプションが導入されました。このオプションを有効にすると、cgroupsファイルシステムが読み取り/書き込み権限でマウントされるようになります。
このフィールドを有効にするには、Gitalyがデプロイされるノードで次の手順を実行します。Gitalyが既にデプロイされている場合は、設定の変更後にポッドを再作成する必要があります。
/etc/containerd/config.tomlにあるContainerd設定ファイルを修正して、cgroup_writableフィールドを含めます:[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc] runtime_type = "io.containerd.runc.v2" cgroup_writable = trueKubeletサービスとContainerdサービスを再起動します:
sudo systemctl restart kubelet sudo systemctl restart containerdこれらのコマンドを実行すると、サービスの再起動に時間がかかる場合、ノードがNotReadyとしてマークされる可能性があります。
ポッドの中断に対処する
ポッドは多くの理由でローテーションする可能性があります。サービスのライフサイクルを理解し、計画することで、中断を最小限に抑えることができます。
たとえば、Gitalyの場合、Kubernetes StatefulSetはspec.templateオブジェクトの変更時にローテーションします。これは、Helm Chartのアップグレード(ラベル、またはイメージタグ付け)またはポッドリソースのリクエストまたは制限の更新中に発生する可能性があります。
このセクションでは、一般的なポッドの中断のケースと、それらに対処する方法について重点的に説明します。
メンテナンスウィンドウをスケジュールする
サービスは高可用性ではないため、特定の操作によって短時間のサービス停止が発生する可能性があります。メンテナンスウィンドウをスケジュールすると、潜在的なサービス中断が通知され、期待値を設定するのに役立ちます。メンテナンスウィンドウは、次の目的で使用する必要があります:
- GitLab Helmチャートのアップグレードと再設定。
- Gitalyの設定の変更。
- Kubernetesノードメンテナンスウィンドウ。たとえば、アップグレードとパッチです。Gitalyを独自の専用ノードプールに分離すると役立つ場合があります。
PriorityClassを使用する
PriorityClassを使用して、Gitalyポッドに他のポッドよりも高い優先度を割り当てて、ノードの飽和状態の圧力、削除の優先度、およびスケジューリングレイテンシーを軽減します:
優先度クラスを作成します:
apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: gitlab-gitaly value: 1000000 globalDefault: false description: "GitLab Gitaly priority class"優先度クラスをGitalyポッドに割り当てます:
gitlab: gitaly: priorityClassName: gitlab-gitaly
削除を防ぐためにノードオートスケールに信号を送る
ノードオートスケールツールは、ポッドをスケジュールし、コストを最適化するために、必要に応じてKubernetesノードを追加および削除します。
縮小イベント中、リソースの使用率を最適化するためにGitalyポッドが削除されることがあります。注釈は通常、この動作を制御し、ワークロードを除外するために使用できます。たとえば、Clusterオートスケーラーを使用する場合:
gitlab:
gitaly:
annotations:
cluster-autoscaler.kubernetes.io/safe-to-evict: "false"リソースの競合と飽和状態に対処する
Gitalyサービスのリソース使用量は、Git操作の性質が不確定であるため、予測できない場合があります。すべてのリポジトリが同じではなく、サイズはパフォーマンスとリソースの使用量に大きく影響します(特にモノレポの場合)。
Kubernetesでは、制御されていないリソースの使用により、Out Of Memory(OOM)イベントが発生する可能性があり、プラットフォームはポッドを強制終了し、すべてのプロセスを強制終了します。ポッドの終了により、2つの重要な懸念事項が発生します:
- データ/リポジトリの破損
- サービス中断
このセクションでは、影響のスコープを縮小し、サービス全体を保護することに重点を置いています。
Gitプロセスリソースの使用量を制限する
Gitプロセスを分離すると、単一のGit呼び出しがすべてのサービスとポッドのリソースを消費できないことが保証され、安全性が向上します。
Gitalyは、Linux Control Groups (cgroups)を使用して、リソースの使用量に対する、より小さなリポジトリごとのクォータを課すことができます。
cgroupのクォータは、ポッドリソースの全体的な割り当てよりも低く維持する必要があります。CPUはサービスの速度を低下させるだけなので、重要ではありません。ただし、メモリの飽和状態はポッドの終了につながる可能性があります。ポッドリクエストとGit cgroupの割り当ての間に1 GiBのメモリバッファがあると、安全な開始点になります。このバッファのサイズ設定は、トラフィックパターンとリポジトリデータによって異なります。
たとえば、ポッドメモリリクエストが15 GiBの場合、14 GiBがGit呼び出しに割り当てられます:
gitlab:
gitaly:
cgroups:
enabled: true
# Total limit across all repository cgroups, excludes Gitaly process
memoryBytes: 15032385536 # 14GiB
cpuShares: 1024
cpuQuotaUs: 400000 # 4 cores
# Per repository limits, 50 repository cgroups
repositories:
count: 50
memoryBytes: 7516192768 # 7GiB
cpuShares: 512
cpuQuotaUs: 200000 # 2 cores詳細については、Gitaly設定ドキュメントを参照してください。
ポッドリソースの適切なサイズ
Gitalyポッドのサイズ設定は重要であり、参照アーキテクチャは開始点としていくつかのガイダンスを提供します。ただし、さまざまなリポジトリと使用パターンでは、さまざまな程度のリソースが消費されます。リソースの使用状況を監視し、時間の経過とともにそれに応じて調整する必要があります。
メモリはKubernetesで最も機密性の高いリソースです。メモリ不足になると、ポッドの終了がトリガーされる可能性があるためです。cgroupを使用したGit呼び出しの分離は、リポジトリ操作のリソース使用量を制限するのに役立ちますが、Gitalyサービス自体は含まれません。cgroupのクォータに関する以前の推奨事項に沿って、全体的なGit cgroupメモリ割り当てとポッドメモリリクエストの間にバッファを追加して、安全性を向上させます。
GuaranteedポッドQuality of Serviceクラスが推奨されます(リソースリクエストが制限と一致します)。この設定では、ポッドはリソースの競合の影響を受けにくく、他のポッドからの消費に基づいて削除されないことが保証されます。
リソース設定の例:
gitlab:
gitaly:
resources:
requests:
cpu: 4000m
memory: 15Gi
limits:
cpu: 4000m
memory: 15Gi
init:
resources:
requests:
cpu: 50m
memory: 32Mi
limits:
cpu: 50m
memory: 32Mi並行処理制限を構成する
並行処理制限を使用すると、異常なトラフィックパターンからサービスを保護できます。詳細については、並行処理設定ドキュメントおよび制限を監視する方法を参照してください。
Gitalyポッドを分離する
複数のGitalyポッドを実行する場合は、障害ドメインを分散するために、異なるノードでスケジュールする必要があります。これは、ポッドのアンチアフィニティを使用して強制できます。例:
gitlab:
gitaly:
antiAffinity: hardポッドのローテーション時間を最適化する
このセクションでは、ポッドがトラフィックの提供を開始するまでにかかる時間を短縮することで、メンテナンスイベント中または計画外のインフラストラクチャイベント中のダウンタイムを短縮するための最適化の領域について説明します。
永続ボリュームの権限
データのサイズが大きくなるにつれて(Git履歴とより多くのリポジトリ)、ポッドが起動して準備が完了するまでにますます時間がかかるようになります。
ポッドの初期化中、永続ボリュームマウントの一部として、ファイルシステムの権限と所有権がコンテナuidとgidに明示的に設定されます。この操作はデフォルトで実行され、保存されているGitデータには多数の小さなファイルが含まれているため、ポッドの起動時間が大幅に遅くなる可能性があります。
この動作は、fsGroupChangePolicy属性で構成できます。この属性を使用して、ボリュームルートuidまたはgidがコンテナ仕様と一致しない場合にのみ、操作を実行します:
gitlab:
gitaly:
securityContext:
fsGroupChangePolicy: OnRootMismatchヘルスプローブ
Gitalyポッドは、準備プローブが成功した後、トラフィックの提供を開始します。デフォルトのプローブ時間は、ほとんどのユースケースをカバーするために控えめになっています。readinessProbe initialDelaySeconds属性を小さくすると、プローブがより早くトリガーされ、ポッドの準備が加速されます。例:
gitlab:
gitaly:
statefulset:
readinessProbe:
initialDelaySeconds: 2
periodSeconds: 10
timeoutSeconds: 3
successThreshold: 1
failureThreshold: 3Gitalyの正常なシャットダウンタイムアウト
デフォルトでは、終了時に、Gitalyは処理中のリクエストが完了するまで1分のタイムアウトを許可します。一見すると有益ですが、このタイムアウト:
- ポッドのローテーションが遅くなります。
- シャットダウンプロセス中にリクエストを拒否することにより、可用性を低下させます。
コンテナベースのデプロイでは、クライアント側の再試行ロジックに依存することをお勧めします。gracefulRestartTimeoutフィールドを使用して、タイムアウトを再構成できます。たとえば、1秒の正常なタイムアウトを許可するには:
gitlab:
gitaly:
gracefulRestartTimeout: 1ディスク使用量を監視する
ログローテーションが無効になっている場合、ログファイルの増加によってストレージのイシューが発生する可能性があるため、長時間実行されているGitalyコンテナのディスク使用量を定期的に監視してください。