GitLab Runner 技術的課題

課題

コードベース

GitLab Runner のコードベースは時代とともにあまり良い状態を保てておらず、 新機能追加の際にさまざまな妥協がなされながら複数の方向に拡張されてきました。

例えば、ほぼすべてのものが依存する非常に大きな commonhelper パッケージが あります。

課題:

  • 関心事の分離が不十分なため、抽象化の漏れが生じやすく、 問題の修正がさらに困難になります。
  • 開発・メンテナンスの観点から理想的でないだけでなく、 現在いくつかの制限があります。例えば、gitlab-runner-helper バイナリは 軽量であるべきですが、common をインポートすると依存関係の全世界を 引き込んでしまいます。
  • GitLab Runner は互換性のない依存関係のために現在 AIX をターゲットにできませんが、 関心事の分離が改善されればヘルパーバイナリはサポートできるようになります。

抽象シェル

GitLab Runner はジョブをジョブ環境内で実行する複数のターゲットスクリプトに 変換します。これらのスクリプトは Git ソースのフェッチやキャッシュの展開などの 定義済みタスク、および CI/CD 設定からのユーザー提供スクリプト (before_scriptscriptafter_script)を実行します。

GitLab Runner は powershellpwshbash/POSIX シェルの組み込みサポートを 持ち、それに応じてターゲットスクリプトを変換するための抽象シェル実装を 採用しています。

課題:

  • GitLab Runner マネージャーはターゲットスクリプトを生成しますが、 ジョブはしばしばリモート環境で実行されます。これにより、ターゲット環境に 不適切なスクリプトが生成される可能性があります。よくある問題はパス名です。
  • シェルの動作はバージョン、OS の設定、スクリプトの実行方法(ファイル経由か stdin 経由か) によって異なる場合があります。1つのエッジケースに対処すると別のエッジケースが 生じることが多く、常にもぐらたたきの状態になります。
  • サポートが限定的なため課題があり、現在サポートされているシェルのフル機能セットを 維持・実装することはすでにメンテナンスの負担です。cmd シェルはまだ 広く使用されているにもかかわらず、メンテナンスと機能実装の困難さから削除されました。
  • 機能セットの乖離: 抽象シェルに依存する新機能を追加すると、サポートされている すべてのシェルで一度に一貫して実現することが困難な場合が多いです。

エグゼキューター

GitLab Runner のエグゼキューターはターゲットプラットフォームでジョブを実行するために 必要なロジックを処理します。

課題:

  • 異なるエグゼキューターは同じ問題(スクリプト実行やロギングなど)に 対処するために異なるアプローチを必要とし、重大な妥協と抽象化の漏れが しばしば生じます。
  • エグゼキューターは個々のジョブのみに焦点を当てています。例えば、Docker や Kubernetes エグゼキューターでは、各ジョブに対して新しい接続が確立されます。 このアプローチは、ガベージコレクションなどの機能に必要な長期実行のルーティンには 適していません。
  • 組み込みエグゼキューターは、カスタムエグゼキューターの抽象化の制限と 既存アーキテクチャ内のエグゼキューターとコードベースの残りの部分との 密結合のために、「カスタムエグゼキューター」に移植できません。
  • Docker と Kubernetes では、「ヘルパー」コンテナが定義済みスクリプトを 容易にします。しかし、ユーザースクリプトが実行される環境の外にヘルパーがある ことから、所有権とファイル権限に関するいくつかの問題が生じます。
  • 機能セットの乖離: 一部のエグゼキューターには他のエグゼキューターにない機能が あります。例えば、Web ターミナルサポートは各エグゼキューターで再実装する 必要があるため、すべてのエグゼキューターがサポートしているわけではありません。

ジョブのマイクロ管理

ジョブは複数のステージに分割されます: get_sourcesrestore_cachedownload_artifactsuser_scriptafter_scriptupload_artifacts_on_success など。

GitLab Runner はジョブの環境と通信し、アドホックな方法で各ステージの スクリプトを実行するよう指示します。スクリプトが完了するまで待機し、 ステータスコードを読み取り(成功か失敗かを判断するため)、その後次のステージを 開始します。

課題:

  • ジョブの環境がリモートでスクリプト実行中に接続が切れた場合、 Runner は実行を再開できません。この Issue は Kubernetes エグゼキューターで 頻繁に発生し、シェルスクリプトをバックグラウンドで実行してログ出力を 別の再開可能なプロセスが読み取るファイルにリダイレクトするよう促しました。 これはエグゼキューターに複雑さを加え、Kubernetes のみで利用可能です。 この複雑な変更は多数のお客様発見のエッジケースをもたらし、 対処するのに数マイルストーンかかりました。
  • Runner が実行フローを制御するため、クラッシュ/終了して再起動後に ジョブを再開することができません。

設定

Runner の設定は複雑です:

  • 複数のランナー設定を定義できます。
  • 複数のレイヤー:
    • グローバル設定
    • ランナー設定
    • エグゼキューター設定
    • オートスケーリング設定

課題:

  • 多数の設定オプション

    Runner は設定ファイル、環境変数、コマンドライン入力での変数設定をサポートします。 しかし、設定ファイルのみがすべての設定をサポートする唯一の方法です。 Twelve-Factor メソドロジーによる設定は、Runner の複雑なオプションには おそらく適していません。

  • 設定されているエグゼキューターに関係なく、すべてのエグゼキューターオプションが 表示されるため、--help コマンドが圧倒的になります。

  • 検証がありません。

  • ジョブ提供の設定に対するユーザー提供の検証が存在しません。 Kubernetes エグゼキューターの cpu_limit_overwrite_max_allowed などの アドホックな設定はジョブが CPU 制限を指定できますが、これらのフィールドの 維持はメンテナンスの負担です。

  • 設定ファイルはコメントを許可しますが、新しいランナーの登録 (または設定の再書き込みをトリガーするもの)はコメントを破棄します。

ジョブログ

ジョブログはランナーマネージャー、エグゼキューター、サービス、 ユーザースクリプトなど、さまざまなソースからのデータを組み合わせます。

課題:

  • セマンティックマークアップなし: 折りたたみ可能なセクションと ANSI カラーコードのみサポートしています。