Jenkinsからのマイグレーション

多くのGitLabユーザーがJenkinsからGitLab CI/CDへのマイグレーションに成功しています。ここでは、これから始めようとしている人にとって参考になるようなリソースを集めました。このページは “GitLab CI/CD for Jenkins Users” ガイドだと思ってください。

次のリストは推奨される移行手順です。迅速にJenkinsから移行完了した例を参考として作成されました。

  1. まずはGitLab CI/CDクイックスタートガイド重要な製品の違いを読むことから始めましょう。
  2. 組織移行管理の重要性を学びます。
  3. GitLab インスタンスにRunnerを追加します。
  4. 開発者が、プロ​​ジェクトで次のステップを自身で実行できるように教育します。
    1. クイックスタートガイドパイプライン構成リファレンスを確認します。
    2. Jenkinsラッパーを使用することで、Jenkinsジョブを変更なく一時的に維持できます。
    3. ビルドジョブとCIジョブを移行し、マージリクエストに直接結果を表示するように設定します。Auto DevOpsを出発点として使用し、必要に応じて設定をカスタマイズまたは分割できます。
    4. レビューアプリを追加します。
    5. クラウドデプロイメントテンプレートを使用したデプロイメントジョブの移行、環境の追加、デプロイボードの追加の3つを実行します。
    6. まだJenkinsラッパーを使用して動作しているジョブを、ラッパー無しで動作するよう修正します。
  5. 一般的なCI/CDジョブの定義を把握し、それらのテンプレートを作成して共有します。
  6. GitLab CI/CDパイプラインをより速く、より効率的にする方法を学ぶには、パイプライン効率化ドキュメントをチェックしてください。

JenkinsからGitLabへのマイグレーションビデオをご覧ください:

  • JenkinsパイプラインをGitLab CI/CDパイプラインに変換します。
  • Auto DevOpsを使ってコードを自動的にテストします。

そうでない場合は、ボールを回すのに役立つ重要な情報をお読みください。GitLabへようこそ!

ここで質問の答えが見つからない場合は、GitLab コミュニティフォーラムを利用すると良いでしょう。

組織の移行を管理

JenkinsからGitLabへの移行で重要なのは、移行に伴う文化的・組織的な変化と、それをうまく管理することです。私たちが見つけた、これを助けるいくつかのものは以下の通りです:

  • マイグレーションのゴールについて明確なビジョンを設定し、それを伝えることで、なぜその作業に価値があるのかをユーザーに理解してもらうことができます。移行が完了すればその価値は明らかですが、移行が進行している間にも、ユーザーはその価値を認識する必要があります。
  • 関連する経営陣からの支援と調整は、上記の点でに役立ちます。
  • 何が違うのかユーザーへの教育に時間を費やし、この文書をユーザーと共有することが、成功への近道です。
  • マイグレーションの一部を順番にしたり遅らせたりする方法を見つけることは大いに役立ちますが、あまり長い間マイグレーションされていない(あるいは部分的にマイグレーションされた)状態のままにしておくことは避けたいものです。GitLabのメリットをすべて得るためには、既存のJenkinsのセットアップをそのまま移行するだけでは不十分です。GitLabが提供する改善点を活用する必要があり、そのためには(最終的には)移行の一環として実装を更新する必要があります。

JenkinsFile Wrapper

プラグインを含むGitLabジョブの中で完全なJenkinsインスタンスを実行するために使用できるJenkinsFile Wrapperを構築しています。これは、緊急性の低いパイプラインのマイグレーションを一定期間遅らせることで、移行プロセスを容易にするのに役立ちます。

GitLabのラッパーのテストに興味がある方は、公開テストに参加して説明を聞いたり、フィードバックを提供したりしてください。

note
GitLabの有料サブスクリプションをお持ちの場合、JenkinsFile WrapperはGitLabに同梱されておらず、サポートの対象外となります。詳しくは、サポートステートメントをご覧ください。

重要な製品の違い

特筆すべき製品間のハイレベルな違いは以下の通りです:

  • GitLabでは、すべてをラップするルートpipeline キーワードは必要ありません。
  • パイプラインをトリガーしたり、他のパイプラインをトリガーする方法はJenkinsとは異なります。GitLabのパイプラインは、以下の方法でトリガーできます。

  • どのジョブをどのケースで実行するかは、rules 構文 で制御できます。
  • GitLabパイプラインのスケジューリングのコンセプトもJenkins とは異なります。
  • include キーワードテンプレートを使ってパイプライン設定を再利用できます。テンプレートは中央のリポジトリに置いておくことができ(異なる権限で)、どのプロジェクトでもそれを使うことができます。この中央プロジェクトには、スクリプトやその他の再利用可能なコードを含めることもできます。
  • また、extends キーワード を使って、1つのパイプライン設定で設定を再利用することもできます。
  • 1つのステージ内のすべてのジョブは常に並列に実行され、すべてのステージは順番に実行されます。有向非巡回グラフ機能により、特定のジョブは必要に応じてこの順序を破ることがあります。
  • parallel キーワードは、並列化をサポートするテストのようなタスクを自動的に並列化することができます。
  • 通常、1 つのステージ内のすべてのジョブは並列に実行され、すべてのステージは順番に実行されます。異なるパイプラインアーキテクチャでは、この動作を変更することができます。
  • 新しいrules 構文 は、異なるジョブの実行タイミングを制御するための推奨方法です。これはonly/except 構文よりも強力です。
  • 1つの重要な違いは、ジョブが互いに独立して実行され、各ジョブで新しい環境を持つことです。ジョブ間のアーティファクトの受け渡しは、artifacts およびdependencies キーワードを使用して制御されます。終了したら、計画されたワークスペース機能を使用して、連続したジョブ間で共通のワークスペースを永続化します。
  • .gitlab-ci.yml ファイルはリポジトリのルートにチェックインされ、Jenkinsfile に似ていますが、Groovy DSL ではなく YAML フォーマット (完全なリファレンスを参照) です。宣言的な Jenkinsfile フォーマットに最も似ています。
  • 手動承認者もしくはゲートはwhen:manual ジョブとして設定できます。これらは、protected environments を活用して、承認者を制御することもできます。
  • GitLab にはコンテナレジストリが用意されているので、コンテナイメージを使ってビルド環境を構築することができます。たとえば、ビルド環境そのものを構築するパイプラインをひとつ用意して、それをコンテナレジストリに公開します。パイプラインがそれぞれ独自の環境を構築する代わりにこれを使用します。コンテナレジストリの使い方については、広範なドキュメントがあります。
  • 中央のユーティリティリポジトリは、スケジュールされたジョブやユーティリティのような機能を持つ手動ジョブを配置するのに最適な場所となります。Jenkinsのインストールでは、このようなジョブを持つ傾向があります。

エージェント vs. ランナー

JenkinsエージェントとGitLab Runnerはどちらもジョブを実行するホストです。Jenkinsエージェントを変換するには、エージェントをアンインストールしてからランナーをインストールして登録します。ランナーはそれほどオーバーヘッドを必要としないので、今まで使っていたJenkinsエージェントと同じようなサイズにすることができます。

エージェントと比較して、ランナーの動作方法におけるいくつかの重要な違いがあります:

  • ランナーはインスタンス全体で共有、グループレベルで追加、またはプロジェクトレベルで設定できます。ランナーは、定義したスコープから自動的にジョブを選択します。
  • タグを使用してより細かい制御を可能にし、Runnerを特定のジョブに関連付けできます。例えば、専用である必要があるジョブ・より強力なハードウェアを必要とするジョブ・特定のハードウェアを必要とするジョブに、タグを使用できます。
  • GitLab にはRunner のオートスケーリング機能があります。Jenkinsのエフェメラルエージェントと同じように、必要なときだけランナーをプロビジョニングし、不要なときはスケールダウンするためにオートスケーリングを使います。

gitlab.com を使っている場合は、共有ランナー・フリートを使って、自分でランナーをプロビジョニングすることなくジョブを実行することができます。セルフマネージドインスタンスでも利用できるように調査中です。

GroovyとYAMLの比較

JenkinsパイプラインはGroovyをベースにしているので、パイプラインの仕様はコードとして記述されます。GitLab は少し違っていて、より高度に構造化されたYAMLフォーマットを使います。スクリプトの要素は、パイプラインの仕様自体とは別にscript ブロックにあります。

YAMLを使うことはGitLabの長所です。また、Jenkinsファイルを理解・管理するのが難しくなるような、制約のない複雑さの問題も回避できます。

もちろん、DRY(繰り返さない)の原則は大切にしています。ジョブの動作は一度コード化すれば必要に応じて適用できるようにしたいと考えています。ジョブの設定を再利用するためにextends 構文を使うことができます。また、異なるプロジェクトのパイプラインの設定を再利用するためにinclude を使うことができます:

.in-docker:
  tags:
    - docker
  image: alpine

rspec:
  extends:
    - .in-docker
  script:
    - rake rspec

アーティファクトでの成果物

アーティファクトは、これまでJenkinsで使ってきたものとは少し違うかもしれません。GitLab では、artifacts キーワードを使って保存するアーティファクトのセットを定義することができます。このキーワードは、ジョブ間で永続化できるファイルやファイル群を指すように設定できます。詳しくはアーティファクトのドキュメントをご覧ください:

pdf:
  script: xelatex mycv.tex
  artifacts:
    paths:
      - ./mycv.pdf
      - ./output/
    expire_in: 1 week

さらに、ビルトインコンテナやパッケージレジストリなどのパッケージ管理機能もあります。パッケージング機能の完全なリストはPackages and registriesドキュメントで見ることができます。

統合された機能

コード品質、ユニットテスト、セキュリティスキャンなどをJenkinsで動作させるためにプラグインを使用したことがあるかもしれません。GitLab はエコシステムと連携して、これらの結果をマージリクエストやパイプラインの詳細ページなどに自動的に取り込むことができます。実際に、これらを表示させるために何も設定する必要がないことに気づくかもしれません。

テンプレート

高度なCI/CDチームにとって、プロジェクトテンプレートはパイプライン構成の再利用を可能にするだけでなく、内製化を促進します。

セルフマネージド GitLab インスタンスでは、インスタンステンプレートリポジトリを構築できます。組織全体の開発チームは、ドロップダウンリストからテンプレートを選択できます。グループメンテナーやグループオーナーは、カスタムプロジェクトテンプレートのソースとして使用するグループを設定することができます。これは、グループ内のすべてのプロジェクトで使用できます。インスタンス管理者は、インスタンスプロジェクトテンプレートのソースとしてグループを設定できます。

宣言型 Jenkinsfile の変換

宣言型Jenkinsfileには、パイプラインの動作を制御するための “セクション “と “ディレクティブ “が含まれています。GitLabにはこれらと同等のものが存在します。

このセクションでは、Jenkinsfileの構文ドキュメントに基づいて、GitLabの概念を紐付けすることを意図しています。

セクション

agent

エージェントセクションでは、パイプラインの実行方法を定義します。GitLabでは、この機能を提供するためにRunnerを使用します。Kubernetesや任意のホストで独自のRunnerを設定することができます。共有ランナーフリートも利用できます(共有ランナーフリートはGitLab.comユーザーだけが利用できます)。異なるジョブを異なるRunner(実行エージェント)に向けるためのタグの使用もサポートしています。

agent セクションでは、どのDockerイメージを実行に使用するかを定義することもできます。image キーワードを使用します。image 、単一のジョブで設定することも、トップレベルで設定することもできます。この場合、パイプライン内のすべてのジョブに適用されます:

my_job:
  image: alpine

post

post セクションは、パイプラインの最後に実行するアクションを定義します。GitLab はステージを使うことでもこれをサポートします。ステージを次のように定義すると、before_pipeline またはafter_pipeline ステージに割り当てられたジョブは期待通りに実行されます。ステージの名前は何でもかまいません:

stages:
  - before_pipeline
  - build
  - test
  - deploy
  - after_pipeline

ジョブの前後に実行するステップを設定するには、before_scriptafter_script キーワードを使います:

default:
  before_script:
    - echo "I run before any jobs starts in the entire pipeline, and can be responsible for setting up the environment."

stages

GitLab CI/CDでもステージを定義できますが、設定はもう少し自由形式です。GitLabstages キーワード はステージのリストを列挙するトップレベルの設定です。stages セクションの下に個々のジョブをネストする必要はありません。.gitlab-ci.yml で定義されたジョブは、stage キーワード を使うことで、どのステージの一部にもすることができます。

特に指定がない限り、すべてのパイプラインは、buildtestdeploy の順に実行されるステージでインスタンス化されます。stage が定義されていないジョブは、デフォルトでtest ステージに配置されます。もちろん、ステージを参照する各ジョブは、パイプライン設定に存在するステージを参照しなければなりません。

stages:
  - build
  - test
  - deploy

my_job:
  stage: build

steps

steps セクションは個々のジョブのscript セクション に相当します。steps セクションは YAML 配列で、各行は実行される個別のコマンドを表します:

my_job:
  script:
    - echo "hello! the current time is:"
    - time

ディレクティブ

environment

GitLabでは、variables キーワード を使って実行時に様々な変数を定義します。これらはGitLab UIのCI/CD設定からも設定できます。protected変数のセクションを含む、変数に関する一般的なドキュメントも参照してください。これは、特定の変数へのアクセスを特定の環境やRunnerに制限するために使うことができます:

variables:
  POSTGRES_USER: user
  POSTGRES_PASSWORD: testing_password

options

ここでいうオプションは、オブジェクト自体に関連づけられた様々なオプションを指します。例えば、ジョブに関連したオプションは、ジョブ自体に関連して定義されています。特定のオプションを探している場合は、完全な設定リファレンスページを検索することで、そのオプションがどこにあるのかを見つけることができるはずです。

parameters

GitLabでは手動でのジョブ起動時に、使用する変数を定義する必要はありません。ユーザーは好きな変数を起動時に設定できます。

triggers /cron

GitLabはGitと密接にインテグレーションされているため、トリガーのためのSCMポーリングオプションは必要ありません。パイプラインをスケジューリングするための構文をサポートしています。

tools

GitLabは個別のtools ディレクティブをサポートしていません。私たちが推奨するベストプラクティスは、ビルド済みのコンテナイメージを使うことです。これらのイメージはキャッシュすることができ、パイプラインに必要なツールをすでに含むようにビルドすることができます。パイプラインは、必要に応じてこれらのイメージを自動的にビルドし、コンテナレジストリにデプロイするように設定できます。

DockerやKubernetesでコンテナイメージを使用せず、独自のシステムでshell Executorを使用する場合は、環境をセットアップする必要があります。事前に環境をセットアップすることもできますし、before_script のアクションでジョブの一部としてセットアップすることもできます。

input

parameters キーワードと同様に、手動ジョブは常に実行時の変数入力を提供できるので、これは必要ありません。

when

GitLabはwhen キーワード をサポートしています。これは、失敗した場合に(あるいは失敗したにもかかわらず)ジョブを実行するタイミングを示すために使われます。パイプラインを制御するためのロジックのほとんどは、非常に強力なrules システム にあります:

my_job:
  script:
    - echo
  rules:
    - if: $CI_COMMIT_BRANCH

追加リソース

パイプラインの高速化と効率化については、パイプラインの効率化に関するドキュメントを参照してください。