パイプラインアーキテクチャ

パイプラインは、GitLabにおけるCI/CDの基本的な構成要素です。 このページでは、パイプラインに関連する重要な概念を説明します。

パイプラインは様々な方法で構成することができ、それぞれに利点があります。必要に応じて、これらの方法を混ぜて使うこともできます:

  • 基本: すべての設定が一か所に集まっている単純なプロジェクトに適しています。
  • Directed Acyclic Graph:効率的な実行を必要とする大規模で複雑なプロジェクトに適しています。
  • 親子パイプライン:モノレポや、独立に定義されたコンポーネントの多いプロジェクトに適しています。

    概要については、親子パイプライン機能のデモを参照してください。

  • マルチプロジェクトパイプラインマイクロサービスアーキテクチャのように、プロジェクト間の相互依存が必要な大規模なプロジェクトに適しています。

    例えば、3つの異なる GitLab プロジェクトからウェブアプリケーションをデプロイするような場合です。マルチプロジェクトパイプラインを使えば、それぞれのプロジェクトでパイプラインをトリガーし、それぞれにビルド、テスト、デプロイのプロセスを持たせることができます。プロジェクト間の相互依存関係を含め、接続されたパイプラインを一箇所で可視化できます。

    概要については、マルチプロジェクトパイプラインのデモを参照してください。

基本的なパイプライン

基本パイプラインはGitLabで最もシンプルなパイプラインです。ビルドステージですべてを並行して実行し、ビルドステージがすべて終了したらテストステージ以降も同じように実行します。最も効率的とは言えませんし、ステップがたくさんあるとかなり複雑になってしまいますが、メンテナーは簡単です:

graph LR subgraph deploy stage deploy --> deploy_a deploy --> deploy_b end subgraph test stage test --> test_a test --> test_b end subgraph build stage build --> build_a build --> build_b end build_a -.-> test build_b -.-> test test_a -.-> deploy test_b -.-> deploy

/.gitlab-ci.yml パイプラインの基本的な設定例です:

stages:
  - build
  - test
  - deploy

default:
  image: alpine

build_a:
  stage: build
  script:
    - echo "This job builds something."

build_b:
  stage: build
  script:
    - echo "This job builds something else."

test_a:
  stage: test
  script:
    - echo "This job tests something. It will only run when all jobs in the"
    - echo "build stage are complete."

test_b:
  stage: test
  script:
    - echo "This job tests something else. It will only run when all jobs in the"
    - echo "build stage are complete too. It will start at about the same time as test_a."

deploy_a:
  stage: deploy
  script:
    - echo "This job deploys something. It will only run when all jobs in the"
    - echo "test stage complete."
  environment: production

deploy_b:
  stage: deploy
  script:
    - echo "This job deploys something else. It will only run when all jobs in the"
    - echo "test stage complete. It will start at about the same time as deploy_a."
  environment: production

有向非環状グラフのパイプライン

効率を重視し、すべてをできるだけ早く実行したい場合は、有効非巡回グラフ(DAG) を使用できます。needs キーワードを使ってジョブ間の依存関係を定義します。GitLabがジョブ間の関係を把握していれば、可能な限りすべてを高速に実行することができ、可能な限り後続のステージにスキップすることもできます。

下の例では、build_atest_abuild_btest_b よりもずっと速い場合、GitLab はbuild_b がまだ実行中であってもdeploy_a を開始します。

graph LR subgraph Pipeline using DAG build_a --> test_a --> deploy_a build_b --> test_b --> deploy_b end

図と一致するDAG/.gitlab-ci.yml の設定例:

stages:
  - build
  - test
  - deploy

default:
  image: alpine

build_a:
  stage: build
  script:
    - echo "This job builds something quickly."

build_b:
  stage: build
  script:
    - echo "This job builds something else slowly."

test_a:
  stage: test
  needs: [build_a]
  script:
    - echo "This test job will start as soon as build_a finishes."
    - echo "It will not wait for build_b, or other jobs in the build stage, to finish."

test_b:
  stage: test
  needs: [build_b]
  script:
    - echo "This test job will start as soon as build_b finishes."
    - echo "It will not wait for other jobs in the build stage to finish."

deploy_a:
  stage: deploy
  needs: [test_a]
  script:
    - echo "Since build_a and test_a run quickly, this deploy job can run much earlier."
    - echo "It does not need to wait for build_b or test_b."
  environment: production

deploy_b:
  stage: deploy
  needs: [test_b]
  script:
    - echo "Since build_b and test_b run slowly, this deploy job will run much later."
  environment: production

親子パイプライン

パイプラインが複雑になるにつれ、いくつかの関連する問題が浮上し始めます:

  • ステージ構造では、次のステージの最初のジョブを開始する前に、ステージ内のすべてのステップを完了する必要があるため、待ち時間が発生し、処理が遅くなります。
  • 単一のグローバルパイプラインの設定が管理しにくくなります。
  • include を持つインポートは設定の複雑さを増し、意図せずにジョブが重複する名前空間の衝突を引き起こす可能性があります。
  • パイプラインUXは扱うジョブやステージが多すぎます。

加えて、パイプラインのふるまいをよりダイナミックにする必要があることもあります。特にYAMLが動的に生成される場合、サブパイプラインを開始する(もしくは開始しない)ことを選択できる機能は強力です。

Parent pipeline graph expanded

上記の基本パイプラインと 有効非巡回グラフの例では、独立してビルドできる2つのパッケージがあります。これらのケースは親子パイプラインを使うのに理想的です。設定を複数のファイルに分け、よりシンプルに保つことができます。親子パイプラインを組み合わせることができます:

  • rules キーワード :例えば、その領域に変更があったときだけ、子パイプラインがトリガーされるようにします。
  • include キーワード: 共通のビヘイビアを取り込み、同じことを繰り返さないようにします。
  • DAGパイプラインを子パイプラインの内側に配置することで、両者のメリットを実現しています。
graph LR subgraph Parent pipeline trigger_a -.-> build_a trigger_b -.-> build_b subgraph child pipeline B build_b --> test_b --> deploy_b end subgraph child pipeline A build_a --> test_a --> deploy_a end end

/.gitlab-ci.yml ダイアグラムに一致する親パイプラインの設定例:

stages:
  - triggers

trigger_a:
  stage: triggers
  trigger:
    include: a/.gitlab-ci.yml
  rules:
    - changes:
        - a/*

trigger_b:
  stage: triggers
  trigger:
    include: b/.gitlab-ci.yml
  rules:
    - changes:
        - b/*

/a/.gitlab-ci.yml にある、DAGneeds キーワードを使用した子a パイプライン設定例:

stages:
  - build
  - test
  - deploy

default:
  image: alpine

build_a:
  stage: build
  script:
    - echo "This job builds something."

test_a:
  stage: test
  needs: [build_a]
  script:
    - echo "This job tests something."

deploy_a:
  stage: deploy
  needs: [test_a]
  script:
    - echo "This job deploys something."
  environment: production

/b/.gitlab-ci.yml にある、DAGneeds キーワードを使用した子b パイプライン設定例:

stages:
  - build
  - test
  - deploy

default:
  image: alpine

build_b:
  stage: build
  script:
    - echo "This job builds something else."

test_b:
  stage: test
  needs: [build_b]
  script:
    - echo "This job tests something else."

deploy_b:
  stage: deploy
  needs: [test_b]
  script:
    - echo "This job deploys something else."
  environment: production

ジョブはGitLabの子パイプラインをトリガーする前や後に実行するように設定することができ、共通のセットアップステップや統一されたデプロイを可能にします。