正式なドキュメントは英語版であり、この日本語訳はAI支援翻訳により作成された参考用のものです。日本語訳の一部の内容は人間によるレビューがまだ行われていないため、翻訳のタイミングにより英語版との間に差異が生じることがあります。最新かつ正確な情報については、英語版をご参照ください。

GitLab Runnerマネージャーポッドのパフォーマンスを最適化

  • プラン: Free、Premium、Ultimate
  • 提供形態: GitLab.com、GitLab Self-Managed、GitLab Dedicated

Kubernetes環境でGitLab Runnerマネージャーポッドのパフォーマンスを監視および最適化するために、GitLabは次のベストプラクティスを推奨します。これらを適用して、パフォーマンスのボトルネックを特定し、最適なCI/CDパイプラインの実行のためのソリューションを実装します。

前提要件

これらの推奨事項を実装する前に:

  • Kubernetes executorを使用して、KubernetesにGitLab Runnerをデプロイします
  • Kubernetesクラスタへの管理者アクセス権を持っている
  • GitLab RunnerのPrometheusモニタリングを設定する
  • Kubernetesリソース管理の基本的な理解

GitLab Runnerマネージャーポッドの役割

GitLab Runnerマネージャーポッドは、Kubernetes内のすべてのCI/CDジョブの実行を調整します。そのパフォーマンスは、パイプラインの効率に直接影響します。

処理内容:

  • ログ処理: ワーカーポッドからのジョブログを収集してGitLabに転送します
  • キャッシュ管理: ローカルおよびクラウドベースのキャッシュ操作を調整します
  • Kubernetes APIリクエスト: ワーカーポッドを作成、監視、および削除します
  • GitLab API通信: ジョブをポーリングして、ステータスの更新をレポートします
  • ポッドライフサイクル管理: ワーカーポッドのプロビジョニングとクリーンアップを管理します
%%{init: { "fontFamily": "GitLab Sans" }}%%
flowchart LR
    accTitle: GitLab Runner manager pod architecture
    accDescr: The manager pod polls GitLab for jobs, creates job pods through the Kubernetes API, manages the S3 cache, and forwards logs from job pods to GitLab.

    subgraph "External Services"
        GL[GitLab Instance]
        S3[S3 Cache Storage]
    end

    subgraph "Manager Pod"
        MP[Manager Process]
        LB[Log Buffer]
        CM[Cache Manager]
    end

    subgraph "Kubernetes API"
        K8S[API Server]
    end

    subgraph "Job Pods"
        JP1[Job Pod 1]
        JP2[Job Pod 2]
        JP3[Job Pod N]
    end

    GL <-->|Poll Jobs<br/>Update Status| MP
    MP <-->|Create/Delete<br/>Monitor Pods| K8S
    MP <-->|Cache Operations| S3
    JP1 -->|Stream Logs| LB
    JP2 -->|Stream Logs| LB
    JP3 -->|Stream Logs| LB
    LB -->|Forward Logs| GL
    CM <-->|Manage Cache| S3

各役割はパフォーマンスに異なる影響を与えます:

  • CPU集中型: Kubernetes API操作、ログ処理
  • メモリ集中型: ログバッファリング、ジョブキュー管理
  • ネットワーク集中型: GitLab API通信、ログストリーミング

KubernetesにGitLab Runnerをデプロイする

GitLab Runner Operatorを使用してGitLab Runnerをインストールします。Operatorは、新しい機能と改善を積極的に受信します。GitLab Runnerチームは、Experimental GRIT frameworkを介してOperatorをインストールします。

KubernetesにGitLab Runnerをインストールする最も簡単な方法は、最新リリースのoperator.k8s.yamlマニフェストを適用し、Operatorインストールに関するドキュメントの手順に従うことです。

モニタリングの設定

ポッドは一時的であり、メトリクスが主要な運用表示レベルを提供するため、KubernetesでのGitLab Runner管理には可観測性が重要です。

モニタリングには、kube-prometheus-stackをインストールします。

Operatorのモニタリングを設定するには、GitLab Runner Operatorのモニタリングを参照してください。

パフォーマンスのモニタリング

効果的なモニタリングは、最適なマネージャーポッドのパフォーマンスを維持するために重要です。

%%{init: { "fontFamily": "GitLab Sans" }}%%
flowchart TD
    accTitle: Metrics collection and monitoring flow
    accDescr: The manager pod exposes metrics, Prometheus scrapes the metrics using PodMonitor configuration, Grafana visualizes the data, and Alertmanager notifies operators.

    subgraph "Metrics Collection Flow"
        MP[Manager Pod<br/>:9252/metrics]
        PM[PodMonitor]
        P[Prometheus]
        G[Grafana]
        A[Alertmanager]

        MP -->|Expose Metrics| PM
        PM -->|Scrape| P
        P -->|Query| G
        P -->|Alerts| A
        A -->|Notify| O[Operators]
    end

主要なパフォーマンスメトリクス

これらの重要なメトリクスを監視します:

メトリック説明パフォーマンス指標
gitlab_runner_jobs現在実行中のジョブジョブキューの飽和
gitlab_runner_limit設定されたジョブの並行処理制限容量使用率
gitlab_runner_request_concurrency_exceeded_total並行処理制限を超えるリクエストAPIスロットリング
gitlab_runner_errors_totalキャッチされたエラーの合計システムの安定性
container_cpu_usage_seconds_totalコンテナのCPU使用量リソース消費量
container_memory_working_set_bytesコンテナのメモリ使用量メモリプレッシャー

Prometheusクエリ

これらのクエリを使用して、マネージャーポッドのパフォーマンスを追跡します:

# Manager pod memory usage in MB
container_memory_working_set_bytes{pod=~"gitlab-runner.*"} / 1024 / 1024

# Manager pod CPU utilization in Millicores
rate(container_cpu_usage_seconds_total{pod=~"gitlab-runner.*"}[5m]) * 1000

# Job queue saturation
gitlab_runner_jobs / gitlab_runner_limit

# Jobs per runner
gitlab_runner_jobs

# API request rate
sum(rate(apiserver_request_total[5m]))

ダッシュボードの例

次のダッシュボードは、以前に説明したPrometheusクエリを使用して、すべてのポッドでのManagerポッドの使用率を示しています:

マネージャーポッドのメモリとCPU使用量を示すGitLab Runnerマネージャーポッドのメトリクスダッシュボード

このダッシュボードは、以下を視覚化するのに役立ちます:

  • マネージャーポッド全体のメモリ使用量の傾向
  • ジョブ実行中のCPU使用率パターン
  • ジョブキューの飽和レベル
  • 個々のポッドのリソース消費量

オーバーロードされたマネージャーポッドの特定

パフォーマンスの低下を認識して、パイプラインに影響を与える前に認識します。

リソース使用率指標

デフォルトでは、GitLab Runner OperatorはマネージャーポッドにCPUまたはメモリ制限を適用しません。

リソース制限を設定するには:

kubectl patch deployment gitlab-runner -p '{"spec":{"template":{"spec":{"containers":[{"name":"gitlab-runner","resources":{"requests":{"cpu":"500m","memory":"256Mi"},"limits":{"cpu":"1000m","memory":"512Mi"}}}]}}}}'

Operator設定からのデプロイパッチを許可する機能は開発中です。詳細については、マージリクエスト197を参照してください。

CPU使用率が高いパターン:

  • 標準操作中にCPUが常に70%を超えている
  • ジョブの作成中にCPUスパイクが90%を超える
  • 対応するジョブアクティビティーがない状態で高いCPUが持続する

メモリ消費量の傾向:

  • 割り当てられた制限の80%を超えるメモリ使用量
  • ワークロードが増加せずに継続的なメモリ増加
  • マネージャーポッドログでのメモリ不足(OOM)イベント

パフォーマンス低下の兆候

これらの運用上の症状に注意してください:

  • ジョブが通常よりも長く保留になっている
  • ポッドの作成時間が30秒を超える
  • GitLabジョブインターフェースでのログ出力の遅延
  • ログ内のetcdserver: request timed outエラー

診断コマンド

# Current resource usage
kubectl top pods --containers

> POD                                                 NAME              CPU(cores)   MEMORY(bytes)
> gitlab-runner-runner-86cd68d899-m6qqm               runner            7m           32Mi

# Check for performance errors
kubectl logs gitlab-runner-runner-86cd68d899-m6qqm --since=2h | grep -E "(error|timeout|failed)"

リソース設定

適切なリソース設定は、最適なパフォーマンスに不可欠です。

パフォーマンステスト開発手法

GitLab Runner Managerポッドのパフォーマンスは、ログ出力を最大化するジョブを使用してテストされます:

パフォーマンステストジョブ定義
performance_test:
  stage: build
  timeout: 30m
  tags:
    - kubernetes_runner
  image: alpine:latest
  parallel: 100
  variables:
    FILE_SIZE_MB: 4
    CHUNK_SIZE_BYTES: 1024
    FILE_NAME: "test_file_${CI_JOB_ID}_${FILE_SIZE_MB}MB.dat"
    KUBERNETES_CPU_REQUEST: "200m"
    KUBERNETES_CPU_LIMIT: "200m"
    KUBERNETES_MEMORY_REQUEST: "200Mi"
    KUBERNETES_MEMORY_LIMIT: "200Mi"
  script:
    - echo "Starting performance test job ${CI_PARALLEL_ID}/${CI_PARALLEL_TOTAL} with ${FILE_SIZE_MB}MB file size, ${CHUNK_SIZE_BYTES} bytes chunk size"
    - dd if=/dev/urandom of="${FILE_NAME}" bs=1M count=${FILE_SIZE_MB}
    - echo "File generated successfully. Size:"
    - ls -lh "${FILE_NAME}"
    - echo "Reading file in ${CHUNK_SIZE_BYTES} byte chunks"
    - |
      TOTAL_SIZE=$(stat -c%s "${FILE_NAME}")
      BLOCKS=$((TOTAL_SIZE / CHUNK_SIZE_BYTES))
      echo "Processing $BLOCKS blocks of $CHUNK_SIZE_BYTES bytes each"
      for i in $(seq 0 99 $BLOCKS); do
        echo "Processing blocks $i to $((i+99))"
        dd if="${FILE_NAME}" bs=${CHUNK_SIZE_BYTES} skip=$i count=100 2>/dev/null | xxd -l $((CHUNK_SIZE_BYTES * 100)) -c 16
        sleep 0.5
      done

このテストでは、ジョブあたり4MBのログ出力が生成され、マネージャーポッドのログ処理機能をストレステストするために、デフォルトのoutput_limitに到達します。

テスト結果:

並列ジョブ数ピークCPU使用率ピークメモリ使用量
50308m261 MB
100657m369 MB
%%{init: { "fontFamily": "GitLab Sans" }}%%
xychart-beta
    accTitle: Manager pod resource usage compared to concurrent jobs
    accDescr: Chart showing CPU usage (10-610 millicores) and memory usage (50-300 MB) that scale with concurrent jobs (0-100).

    x-axis [0, 25, 50, 75, 100]
    y-axis "Resource Usage" 0 --> 700
    line "CPU (millicores)" [10, 160, 310, 460, 610]
    line "Memory (MB)" [50, 112, 175, 237, 300]

主な調査結果:

  • CPU使用率は、並行処理ジョブ数とほぼ線形にスケールします
  • メモリ使用量はジョブ数とともに増加しますが、線形ではありません
  • すべてのジョブは、キューイングなしで同時に実行されます

CPU要件

GitLabのパフォーマンステストに基づいて、マネージャーポッドのCPU要件を計算します:

マネージャーポッドのCPU =基本CPU +(並行処理ジョブ×ジョブあたりのCPUファクター)

各設定項目の意味は次のとおりです。:

  • 基本CPU: 10m(ベースラインオーバーヘッド)
  • ジョブあたりのCPUファクター:並行処理ジョブあたり約6m(テストに基づく)

テスト結果に基づく例:

50個の並行処理ジョブの場合:

resources:
  requests:
    cpu: "310m" # 10m + (50 × 6m) = 310m
  limits:
    cpu: "465m" # 50% headroom for burst traffic

100個の並行処理ジョブの場合:

resources:
  requests:
    cpu: "610m" # 10m + (100 × 6m) = 610m
  limits:
    cpu: "915m" # 50% headroom

メモリ要件

GitLabのテストに基づいて、メモリ要件を計算します:

マネージャーポッドメモリ=基本メモリ+(並行処理ジョブ×ジョブあたりのメモリ)

各設定項目の意味は次のとおりです。:

  • 基本メモリ: 50 MB(ベースラインオーバーヘッド)
  • ジョブあたりのメモリ:並行処理ジョブあたり約2.5 MB(4MBのログ出力を使用)

テスト結果に基づく例:

50個の並行処理ジョブの場合:

resources:
  requests:
    memory: "175Mi" # 50 + (50 × 2.5) = 175 MB
  limits:
    memory: "350Mi" # 100% headroom

100個の並行処理ジョブの場合:

resources:
  requests:
    memory: "300Mi" # 50 + (100 × 2.5) = 300 MB
  limits:
    memory: "600Mi" # 100% headroom

メモリ使用量は、ログ量に基づいて大幅に異なります。4 MBを超えるログを生成するジョブには、比例してより多くのメモリが必要です。

設定例

小規模(1〜20個の並行処理ジョブ):

resources:
  limits:
    cpu: 300m
    memory: 256Mi
  requests:
    cpu: 150m
    memory: 128Mi

runners:
  config: |
    concurrent = 20

    [[runners]]
      limit = 20
      request_concurrency = 5

大規模(75個以上の並行処理ジョブ):

resources:
  limits:
    cpu: 1000m
    memory: 1Gi
  requests:
    cpu: 600m
    memory: 600Mi

runners:
  config: |
    concurrent = 150

    [[runners]]
      limit = 150
      request_concurrency = 20

水平ポッドオートスケーラー

自動スケーリングを設定する:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: gitlab-runner-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: gitlab-runner
  minReplicas: 2
  maxReplicas: 5
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 80

パフォーマンスの問題のトラブルシューティング

これらのソリューションを使用して、一般的なマネージャーポッドのパフォーマンスの問題に対処します。

APIレート制限

問題: マネージャーポッドがKubernetes APIレート制限を超えています。

解決策: APIポーリングを最適化します。

[[runners]]
  [runners.kubernetes]
    poll_interval = "5s"  # Increase from default 3s
    poll_timeout = "180s"

パフォーマンスの最適化

困難なシナリオについては、これらのパフォーマンス最適化戦略を適用します。

キャッシュの最適化

分散キャッシュを設定して、マネージャーポッドの負荷を軽減します。このアクションにより、キャッシュされたファイルを共有することで、ジョブポッドに必要な計算が削減されます:

[runners.cache]
  Type = "s3"
  Shared = true

  [runners.cache.s3]
    ServerAddress = "cache.example.com"
    BucketName = "gitlab-runner-cache"
    PreSignedURLDisabled = false

ノード分離

安定したパフォーマンスを確保し、リソースの競合を防ぐために、専用ノードを使用してマネージャーポッドをジョブポッドから分離します。この分離により、ジョブポッドが重要なマネージャーポッド操作を中断することがなくなります。

%%{init: { "fontFamily": "GitLab Sans" }}%%
graph TB
    accTitle: Kubernetes node segregation architecture
    accDescr: Node segregation with manager pods on dedicated manager nodes and job pods on worker nodes, separated by taints.

    subgraph "Kubernetes Cluster"
        subgraph "Manager Nodes"
            MN1[Manager Node 1<br/>Taint: runner.gitlab.com/manager]
            MN2[Manager Node 2<br/>Taint: runner.gitlab.com/manager]
            MP1[Manager Pod 1]
            MP2[Manager Pod 2]
            MN1 --> MP1
            MN2 --> MP2
        end

        subgraph "Worker Nodes"
            WN1[Worker Node 1<br/>Taint: runner.gitlab.com/job]
            WN2[Worker Node 2<br/>Taint: runner.gitlab.com/job]
            WN3[Worker Node 3<br/>Taint: runner.gitlab.com/job]
            JP1[Job Pod 1]
            JP2[Job Pod 2]
            JP3[Job Pod 3]
            JP4[Job Pod 4]
            WN1 --> JP1
            WN1 --> JP2
            WN2 --> JP3
            WN3 --> JP4
        end
    end

    MP1 -.->|Creates & Manages| JP1
    MP1 -.->|Creates & Manages| JP2
    MP2 -.->|Creates & Manages| JP3
    MP2 -.->|Creates & Manages| JP4

ノードテイイントの設定

マネージャーノードの場合:

# Taint nodes dedicated to Manager Pods
kubectl taint nodes <manager-node-name> runner.gitlab.com/manager=:NoExecute

# Label nodes for easier selection
kubectl label nodes <manager-node-name> runner.gitlab.com/workload-type=manager

ワーカーノードの場合:

# Taint nodes dedicated to job pods
kubectl taint nodes <worker-node-name> runner.gitlab.com/job=:NoExecute

# Label nodes for job scheduling
kubectl label nodes <worker-node-name> runner.gitlab.com/workload-type=job

マネージャーポッドのスケジューリングを設定する

専用ノードでのみマネージャーポッドをスケジュールするようにGitLab Runner Operator設定を更新します:

apiVersion: apps.gitlab.com/v1beta2
kind: Runner
metadata:
  name: gitlab-runner
spec:
  gitlabUrl: https://gitlab.example.com
  token: gitlab-runner-secret
  buildImage: alpine
  podSpec:
    name: "manager-node-affinity"
    patch: |
      {
        "spec": {
          "nodeSelector": {
            "runner.gitlab.com/workload-type": "manager"
          },
          "tolerations": [
            {
              "key": "runner.gitlab.com/manager",
              "operator": "Exists",
              "effect": "NoExecute"
            }
          ]
        }
      }
    patchType: "strategic"

ジョブポッドのスケジューリングを設定する

config.tomlを更新して、ジョブポッドがワーカーノードでのみ実行されるようにします。

[runners.kubernetes.node_selector]
"runner.gitlab.com/workload-type" = "job"

[runners.kubernetes.node_tolerations]
"runner.gitlab.com/job=" = "NoExecute"

ノード分離の利点:

  • ジョブの干渉なしにマネージャーポッド専用のリソース
  • リソースの競合なしに予測可能なパフォーマンス
  • 専用ノードを使用する場合、リソース制限なしで実行するオプション
  • ノードベースのスケーリングによる容量計画の簡素化

緊急手順

正常な再起動:

# Scale down to stop accepting new jobs
kubectl scale deployment gitlab-runner --replicas=0

# Wait for active jobs to complete (max 10 minutes)
timeout 600 bash -c 'while kubectl get pods -l job-type=user-job | grep Running; do sleep 10; done'

# Scale back up
kubectl scale deployment gitlab-runner --replicas=1

容量計画

これらの計算は、ジョブあたり4 MBのログ出力を使用したテストに基づいています。リソース要件は、以下に基づいて異なる場合があります:

  • ジョブごとのログ量
  • ジョブの実行パターン
  • キャッシュの使用状況
  • GitLabへのネットワークレイテンシー

このPython関数を使用して、最適なリソースを計算します:

def calculate_manager_resources(concurrent_jobs, avg_log_mb_per_job=4):
    """Calculate Manager Pod resources based on performance testing."""
    # CPU: ~6m per concurrent job + 10m base
    base_cpu = 0.01  # 10m
    cpu_per_job = 0.006  # 6m per job
    total_cpu = base_cpu + (concurrent_jobs * cpu_per_job)

    # Memory: ~2.5MB per job + 50MB base (for 4MB log output)
    base_memory = 50
    memory_per_job = 2.5 * (avg_log_mb_per_job / 4)  # Scale with log size
    total_memory = base_memory + (concurrent_jobs * memory_per_job)

    return {
        'cpu_request': f"{int(total_cpu * 1000)}m",
        'cpu_limit': f"{int(total_cpu * 1.5 * 1000)}m",  # 50% headroom
        'memory_request': f"{int(total_memory)}Mi",
        'memory_limit': f"{int(total_memory * 2.0)}Mi"  # 100% headroom
    }

パフォーマンスのしきい値

プロアクティブな介入のしきい値を確立します:

メトリック警告重大必要なアクション
CPU使用率70%持続85%持続スケールまたは最適化
メモリ使用状況制限の80%制限の90%制限を引き上げる
APIエラー率リクエストの2%リクエストの5%ボトルネックを調査する
ジョブキュー時間30秒2分容量を確認する

概要

GitLab Runnerマネージャーポッドのパフォーマンスを最適化するには、体系的なモニタリング、適切なリソース割り当て、およびプロアクティブなトラブルシューティングが必要です。

主要な戦略は次のとおりです:

  • PrometheusメトリクスとGrafanaダッシュボードを使用したプロアクティブなモニタリング
  • 並行処理ジョブ容量とログ量に基づくリソース計画
  • フォールトトレランスと負荷分散のためのマルチマネージャーアーキテクチャ
  • 迅速な問題解決のための緊急手順

これらの戦略を実装して、信頼性の高いCI/CDパイプラインの実行を保証しながら、最適なリソース使用率を維持します。