GitLab CI Variablesとは?CI/CD効率化の必須知識


GitLab CI Variablesとは?CI/CD効率化の必須知識

CI/CD(継続的インテグレーション・継続的デリバリー)は、現代のソフトウェア開発において不可欠なプラクティスです。コードの変更を自動的にテスト、ビルド、デプロイすることで、開発サイクルを高速化し、品質を向上させ、リスクを低減します。GitLab CI/CDは、このCI/CDパイプラインを構築・実行するための強力なツールであり、多くの開発チームに採用されています。

GitLab CI/CDパイプラインは、.gitlab-ci.yml というYAMLファイルで定義されます。このファイルには、コードのビルド、テスト、デプロイといった一連のジョブ(Job)とその実行順序(Stage)が記述されます。しかし、これらのジョブを実行する際には、環境固有の設定値や、APIキー、パスワードといった機密情報、あるいはパイプラインの実行状況に応じた動的な情報など、様々なデータが必要になります。

これらのデータを.gitlab-ci.ymlファイルに直接ハードコーディングすることは、多くの問題を引き起こします。

  • 環境依存性の問題: 開発環境、ステージング環境、本番環境など、環境ごとに設定値(データベース接続文字列、APIエンドポイントなど)が異なる場合、環境ごとに別の設定ファイルを用意したり、if文で分岐させたりする必要があり、設定が複雑化し管理が困難になります。
  • 機密情報の漏洩リスク: APIキーやパスワード、証明書などの機密情報を.gitlab-ci.ymlファイルに直接記述すると、リポジトリが公開されている場合はもちろん、プライベートリポジトリであっても、アクセス権を持つ全ての人が機密情報にアクセスできるようになってしまいます。これはセキュリティ上の重大なリスクです。
  • 再利用性の低下: 特定の設定値がファイルに直接埋め込まれていると、同じパイプラインを別のプロジェクトや別の環境で再利用するのが難しくなります。設定値だけを変えてパイプラインを実行したい場合、ファイルを変更する必要が生じます。
  • 可読性とメンテナンス性の低下: 設定値がファイル中に散らばっていると、パイプラインの定義が読みにくくなり、変更やメンテナンスが困難になります。

これらの問題を解決し、より柔軟で安全、かつ効率的なCI/CDパイプラインを構築するために不可欠な機能が、GitLab CI Variables(GitLab CI 変数) です。

GitLab CI Variablesは、パイプラインの実行中にジョブで利用できる動的または静的な値を格納するための仕組みです。変数を使うことで、環境固有の設定値や機密情報を.gitlab-ci.ymlファイルから分離し、安全に管理し、パイプラインをより汎用的で再利用可能なものにすることができます。

本記事では、GitLab CI Variablesについて、その基本的な概念から種類、定義方法、スコープ、優先順位、高度な活用方法、そしてCI/CD効率化にどのように貢献するのかを詳細に解説します。GitLab CI/CDを効果的に使いこなし、開発プロセスをさらに加速させたいと考えている方にとって、必読の内容となっています。

GitLab CI/CDとVariablesの基礎

GitLab CI/CDは、リポジトリにプッシュされたコードの変更をトリガーとして、自動的に一連の処理を実行します。この処理の流れを定義するのが、リポジトリのルートディレクトリに配置される.gitlab-ci.ymlファイルです。

.gitlab-ci.ymlファイルは、一つ以上のジョブ(Job)を定義します。各ジョブは、特定のタスク(例: コードのビルド、テストの実行、Dockerイメージのプッシュ、サーバーへのデプロイなど)を実行する最小単位です。ジョブは、script キーワード内にシェルコマンドのリストとして記述されます。

ジョブは、ステージ(Stage)という論理的なグループにまとめられます。同じステージに属するジョブは並列で実行されます(明示的に依存関係を定義しない限り)。異なるステージに属するジョブは、ステージの定義順に実行され、前のステージの全てのジョブが成功した場合に次のステージが開始されます。一般的なステージの例としては、build, test, deploy などがあります。

Variablesは、この.gitlab-ci.ymlファイル内で定義されるジョブの script セクションや他の設定セクション(例: image, before_script, after_script など)で利用できます。変数の値は、ジョブがRunner上で実行される際に、環境変数としてエクスポートされ、シェルスクリプトや実行されるプログラムから参照可能になります。

例えば、次のような簡単な.gitlab-ci.ymlファイルがあるとします。

“`yaml
stages:
– build
– test

variables:
APP_VERSION: “1.0.0”
TEST_DATABASE_URL: “postgres://user:pass@localhost:5432/testdb”

build_job:
stage: build
script:
– echo “Building application version $APP_VERSION”
– # ビルドコマンド

test_job:
stage: test
script:
– echo “Running tests with database: $TEST_DATABASE_URL”
– # テストコマンド
“`

この例では、variables キーワードを使って APP_VERSIONTEST_DATABASE_URL という変数を定義しています。これらの変数は、その後のジョブの script セクションで $APP_VERSION$TEST_DATABASE_URL という形式で参照されています。Runnerはジョブを実行する際に、これらの変数を環境変数として設定します。

Variablesがなぜ重要なのか、改めて考えてみましょう。

  • 動的な値の取り扱い: パイプラインの実行ごとに変わる値(例: コミットハッシュ、ブランチ名、パイプラインIDなど)をスクリプトで利用したい場合があります。GitLab CIはこれらの動的な値を自動的に変数として提供します(事前定義変数)。
  • 環境ごとの設定: 開発環境と本番環境でデプロイ先のサーバーアドレスが違う、APIキーが違う、といった場合に、これらの設定値を変数として管理することで、同じパイプライン定義ファイルを使用できます。
  • 機密情報の保護: APIキー、パスワード、証明書などの機密情報は、リポジトリに直接書くべきではありません。Variablesの仕組み(特にUIでの設定、マスク、保護)を利用することで、これらの情報を安全にパイプラインで利用できます。
  • コードの再利用性: パイプラインの設定をハードコーディングではなく変数化することで、ジョブやステージの定義をより汎用的にできます。例えば、デプロイスクリプトは変数で指定されたサーバーに接続するようにしておけば、環境ごとに変数だけを変えることで同じスクリプトを再利用できます。

このように、VariablesはGitLab CI/CDの柔軟性、安全性、再利用性を高める上で中心的な役割を果たします。

GitLab CI Variablesの種類と定義方法

GitLab CI Variablesには、主に以下の種類があります。

  1. 事前定義変数 (Predefined Variables): GitLab Runnerによって自動的に設定される変数。
  2. カスタム変数 (Custom Variables): ユーザーが自分で定義する変数。定義できる場所がいくつかあります。
    • UI (プロジェクト、グループ、インスタンスレベル)
    • .gitlab-ci.yml ファイル
    • API
    • Runnerの設定 (config.toml)

さらに、これらの変数を参照して新しい変数を定義する変数参照 (Variable Reference) や、スクリプトの実行結果を変数として利用する動的変数 (Dynamic Variables) といった概念もあります。

それぞれの種類について詳しく見ていきましょう。

1. 事前定義変数 (Predefined Variables)

事前定義変数とは、GitLab Runnerがパイプラインの実行時に自動的に設定する一連の変数です。これらは、現在のコミット情報、ブランチ/タグ名、パイプラインやジョブのID、プロジェクトの情報、Runnerの情報など、パイプラインの実行に関する様々なコンテキスト情報を提供します。

これらの変数は、特別な設定なしに.gitlab-ci.ymlファイルやジョブのスクリプト内で $VAR_NAME または ${VAR_NAME} の形式で利用できます。

代表的な事前定義変数をいくつか挙げます。

  • CI_COMMIT_SHA: 現在のコミットのフルSHA。
  • CI_COMMIT_SHORT_SHA: 現在のコミットの短いSHA。
  • CI_COMMIT_BRANCH: 現在のコミットがどのブランチに属しているか(ブランチパイプラインの場合)。タグやMRパイプラインの場合は設定されないことがあります。
  • CI_COMMIT_TAG: 現在のコミットがどのタグに属しているか(タグパイプラインの場合)。
  • CI_PIPELINE_ID: 現在のパイプラインの一意のID。
  • CI_PIPELINE_URL: 現在のパイプラインのURL。
  • CI_JOB_ID: 現在のジョブの一意のID。
  • CI_JOB_URL: 現在のジョブのURL。
  • CI_JOB_NAME: 現在のジョブ名(.gitlab-ci.ymlで定義した名前)。
  • CI_PROJECT_ID: 現在のプロジェクトの一意のID。
  • CI_PROJECT_NAME: 現在のプロジェクト名。
  • CI_PROJECT_PATH: 現在のプロジェクトのパス(例: group/project)。
  • CI_PROJECT_DIR: プロジェクトのリポジトリがクローンされるRunner上のディレクトリの絶対パス。ジョブのスクリプト内でファイルパスを指定する際に頻繁に利用されます。
  • CI_REGISTRY: プロジェクトのコンテナレジストリのURL(例: registry.gitlab.com/group/project)。Dockerイメージのビルドやプッシュによく使われます。
  • CI_ENVIRONMENT_NAME: デプロイに関連付けられた環境の名前。
  • CI_MERGE_REQUEST_IID: マージリクエストパイプラインの場合、関連するマージリクエストのIID(Internal ID)。

これらの変数は非常に多岐にわたります。全てのリストはGitLabの公式ドキュメント「Predefined CI/CD variables」を参照してください。

事前定義変数の利用例:

yaml
build_docker_image:
stage: build
image: docker:latest
services:
- docker:dind
script:
- echo "Building Docker image for branch: $CI_COMMIT_BRANCH"
- docker build -t $CI_REGISTRY/$CI_PROJECT_PATH:$CI_COMMIT_SHORT_SHA .
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY # CI_JOB_TOKENも事前定義変数
- docker push $CI_REGISTRY/$CI_PROJECT_PATH:$CI_COMMIT_SHORT_SHA

この例では、CI_COMMIT_BRANCHCI_REGISTRYCI_PROJECT_PATHCI_COMMIT_SHORT_SHAといった事前定義変数を利用して、動的にDockerイメージのタグを生成し、プロジェクトのコンテナレジストリにプッシュしています。CI_JOB_TOKENは、現在のジョブに関連付けられた一時的な認証トークンで、レジストリへのログインなどに利用されます。

2. カスタム変数 (Custom Variables)

カスタム変数は、ユーザーが必要に応じて自分で定義する変数です。設定値、パスワード、APIキー、ファイル内容など、様々な情報を変数として保持できます。カスタム変数は、定義する場所によってそのスコープや管理方法が異なります。

2.1. UIでの定義 (Settings > CI/CD > Variables)

GitLabのWeb UIから、プロジェクトまたはグループレベルで変数を定義できます。これは、機密情報や環境固有の設定値を管理するのに最も推奨される方法です。UIで定義された変数は、リポジトリには保存されないため、セキュリティが高まります。

UIでの設定項目:

  • Type: 変数の種類。
    • Variable: 文字列などの一般的な値。
    • File: 変数の値をファイル内容として扱い、ジョブ実行時に一時ファイルとしてRunner上に配置される。秘密鍵や設定ファイルなどで利用。
  • Key: 変数名(例: API_KEY, DATABASE_URL)。
  • Value: 変数の値。機密情報の場合は慎重に扱います。
  • Environment Scope: その変数がどのデプロイ環境(例: production, staging, * (全て))で有効か指定します。*は全ての環境で有効です。特定の環境名を設定すると、その環境に関連付けられたデプロイジョブでのみ有効になります。
  • Protected variable: チェックを入れると、この変数は「保護されたブランチ」および「保護されたタグ」に関連付けられたパイプラインでのみ利用可能になります。本番環境へのデプロイなど、保護された環境でのみ必要な機密情報に使われます。
  • Masked variable: チェックを入れると、この変数の値はジョブログに表示されなくなります。パスワードやAPIキーなどの機密情報に必ず設定します。マスクするには、特定の条件(値が8文字以上、特定の文字種以外を含まないなど)を満たす必要があります。
  • Expand variable reference: チェックを入れると、この変数の値に含まれる他の変数参照 ($VAR または ${VAR}) が展開されます。例えば、Valueが $CI_PROJECT_DIR/cache の場合、チェックを入れると CI_PROJECT_DIR の値が展開されたパスになります。

UIで定義するメリット:

  • セキュリティ: 機密情報がリポジトリの外部で管理されるため、コードのリビジョン履歴に残りません。
  • 環境管理: 環境スコープを利用して、環境ごとに異なる設定値を効率的に管理できます。
  • 保護・マスク: 機密情報を保護し、ログからの漏洩を防ぐための機能が提供されます。
  • GUI操作: .gitlab-ci.ymlを編集せずに設定できます。

UIで定義するデメリット:

  • バージョン管理されない: 設定変更の履歴はUI上でのみ管理され、Gitリポジトリではバージョン管理されません。変更の追跡やロールバックが難しくなる場合があります。
  • 設定のコード化が難しい: IaC (Infrastructure as Code) の考え方からすると、設定もコードとして管理したい場合がありますが、UI設定はコード化しにくい側面があります(GitLab API経由でTerraformなどで管理することは可能)。
2.2. .gitlab-ci.yml ファイルでの定義

.gitlab-ci.ymlファイル内で variables キーワードを使って変数を定義できます。このキーワードは、グローバル(ファイル全体)または特定のジョブの内部で使用できます。

  • グローバル変数: variables: セクションをファイルのトップレベルに置くと、そこで定義された変数はそのパイプライン内の全てのジョブでデフォルトとして利用可能になります。

“`yaml
variables:
DEFAULT_BRANCH: “main”
DOCKER_IMAGE_NAME: “$CI_PROJECT_PATH:$CI_COMMIT_SHORT_SHA” # 変数参照の例

stages:
– build
– deploy

build_job:
stage: build
script:
– echo “Building image: $DOCKER_IMAGE_NAME”

deploy_job:
stage: deploy
script:
– echo “Deploying default branch: $DEFAULT_BRANCH”
“`

  • ジョブローカル変数: 各ジョブの定義内部に variables: セクションを置くと、そこで定義された変数はそのジョブ内でのみ有効になります。グローバル変数と同じ名前の変数を定義した場合、ジョブローカル変数が優先されます。

“`yaml
variables:
GLOBAL_VAR: “This is global”
DATABASE_URL: “default_db_url”

job_a:
script:
– echo $GLOBAL_VAR # “This is global”
– echo $DATABASE_URL # “default_db_url”

job_b:
variables:
JOB_VAR: “This is local to job_b”
DATABASE_URL: “job_b_specific_db_url” # ジョブローカル変数がグローバル変数より優先される
script:
– echo $GLOBAL_VAR # “This is global”
– echo $DATABASE_URL # “job_b_specific_db_url”
– echo $JOB_VAR # “This is local to job_b”

job_c:
script:
– echo $GLOBAL_VAR # “This is global”
– echo $DATABASE_URL # “default_db_url”
– echo $JOB_VAR # (未定義、何も出力されないかエラーになる可能性)
“`

.gitlab-ci.ymlで定義するメリット:

  • バージョン管理: 変数定義も.gitlab-ci.ymlファイルの一部としてGitでバージョン管理されるため、変更履歴の追跡やロールバックが容易です。
  • 設定のコード化: パイプライン定義と関連する設定値をまとめて管理できます。
  • 手軽さ: UIを開かずに設定を変更できます。

.gitlab-ci.ymlで定義するデメリット:

  • セキュリティ: 機密情報はリポジトリに保存されるため、漏洩リスクが高まります。APIキーやパスワードなどは絶対に.gitlab-ci.ymlファイルに直接記述しないでください。UI変数やVaultなどの外部シークレット管理ツールを利用すべきです。
  • 環境依存性の管理が煩雑: 環境ごとの設定が多い場合、.gitlab-ci.yml内に条件分岐や複雑な変数定義が必要になり、ファイルが読みにくくなります。
2.3. APIでの定義

GitLab APIを利用して、プログラムから動的にプロジェクト変数やグループ変数を設定・取得できます。これは、外部システムと連携する場合や、自動化スクリプトから変数設定を行いたい場合に便利です。

例えば、外部の構成管理ツールやスクリプトからデプロイ先の情報をGitLab変数として設定し、その後のパイプラインで利用するといった使い方が考えられます。

APIを利用するメリット:

  • 自動化・連携: 外部システムとの連携や自動化スクリプトからの変数管理が可能です。
  • 動的な設定: パイプライン実行前に外部要因に基づいて変数を動的に設定できます。

APIを利用するデメリット:

  • 実装が必要: APIを呼び出すためのスクリプトやプログラムの実装が必要です。
  • 認証が必要: APIへのアクセスには認証(パーソナルアクセストークンやプロジェクトアクセストークンなど)が必要です。
2.4. Runnerの設定 (config.toml)

GitLab Runnerの設定ファイルである config.toml 内で、Runnerが実行する全てのジョブで利用可能な変数を定義できます。これは、特定のRunnerが必要とするシステムレベルの設定や、複数のプロジェクトで共通して利用する設定などに使われます。

config.toml[runners.docker][runners.kubernetes] セクションなどに environment = ["VAR=value", ...] の形式で記述します。

例:
toml
[[runners]]
name = "My Docker Runner"
url = "https://gitlab.com/"
token = "xxxxxxxxxxxxxx"
executor = "docker"
[runners.docker]
image = "ubuntu:latest"
privileged = false
disable_entrypoint_overwrite = false
oom_kill_disable = false
disable_cache = false
volumes = ["/cache"]
shm_size = 0
# Runnerレベルで定義される変数
environment = ["RUNNER_ENVIRONMENT=production", "SHARED_SECRET=very_secret_value"]

Runner設定で定義するメリット:

  • Runner固有の設定: Runnerの動作や環境に関する設定を管理できます。
  • 全プロジェクトでの共通設定: そのRunnerを使う全てのプロジェクトで利用可能な共通設定を提供できます。

Runner設定で定義するデメリット:

  • 管理の集中: 変数定義がGitLabプロジェクト/グループのUIや.gitlab-ci.ymlから離れてRunner側に移るため、管理が分散します。
  • セキュリティ: config.toml ファイル自体へのアクセス権限が必要になります。機密情報をここに置く場合は、ファイルへのアクセスを厳重に管理する必要があります。

3. 変数参照 (Variable Reference)

定義済みの変数や事前定義変数の値を参照して、新しい変数を定義したり、既存の変数の値を構築したりすることができます。これは、.gitlab-ci.ymlファイル内の variables セクションや、UIで変数を定義する際に利用できます。

構文は $VARIABLE または ${VARIABLE} です。シェルスクリプト内と同様に変数の値を展開します。

例:

“`yaml
variables:
BASE_URL: “http://example.com”
API_ENDPOINT: “$BASE_URL/api/v1” # BASE_URLを参照して定義
IMAGE_TAG: “$CI_COMMIT_SHORT_SHA-$CI_JOB_ID” # 事前定義変数を参照して定義

test_api:
script:
– echo “Testing API at: $API_ENDPOINT”
– echo “Image tag will be: $IMAGE_TAG”
– curl “$API_ENDPOINT/status” # スクリプト内でも参照可能
“`

UIで変数を定義する際も、Expand variable reference にチェックを入れることで変数参照が有効になります。

変数参照のメリット:

  • 動的な変数生成: 既存の変数に基づいて新しい変数を動的に生成できます。
  • 設定の簡潔化: 繰り返し利用される値を変数化し、それを参照することで定義を簡潔に保てます。

4. 動的変数 (Dynamic Variables)

従来の変数定義とは異なり、パイプラインのジョブの実行中に生成された値を、後続のジョブで変数として利用したい場合があります。GitLab CIでは、artifacts:reports:dotenv 機能を利用することで、これを実現できます。

特定のジョブの script セクションで、変数定義を含む .env 形式のファイルを作成します。そして、そのジョブの artifacts:reports:dotenv オプションでそのファイルを指定します。

“`yaml
generate_config:
stage: build
script:
– echo “APP_VERSION=2.0.${CI_PIPELINE_ID}” > generated.env # 動的にバージョンを生成してファイルに書き込む
– echo “BUILD_TIMESTAMP=$(date +%s)” >> generated.env
artifacts:
reports:
dotenv: generated.env # generated.env ファイルを変数として後続ジョブに渡す

deploy_app:
stage: deploy
script:
– echo “Deploying app version $APP_VERSION” # generate_config ジョブで生成された APP_VERSION を参照
– echo “Build timestamp: $BUILD_TIMESTAMP”
– # デプロイコマンドでこれらの変数を利用
needs: [“generate_config”] # generate_config ジョブが成功してから実行
“`

generate_config ジョブでは、パイプラインIDを利用して動的にアプリケーションバージョンを生成し、generated.env ファイルに書き込んでいます。artifacts:reports:dotenv: generated.env を指定することで、このファイルの内容が抽出され、後続のジョブ(この場合は deploy_app)で環境変数として利用可能になります。

動的変数のメリット:

  • ジョブ間の値の受け渡し: 前のジョブの実行結果(ビルドされたファイルのパス、生成されたバージョン番号、テスト結果の要約など)を後続ジョブで利用できます。
  • 動的な設定生成: ビルド時に確定する情報など、事前に定義できない値をパイプライン内で生成して利用できます。

変数のスコープと優先順位

GitLab CI Variablesは、定義する場所によって有効な範囲(スコープ)が異なります。また、同じ名前の変数が複数の場所で定義されている場合、どの値が最終的に使用されるかは優先順位によって決まります。

変数の定義場所とそのスコープ:

  • Runnerの設定 (config.toml): そのRunnerを使用する全てのジョブで有効。最も広いスコープですが、管理はRunner側になります。
  • GitLab UI (インスタンスレベル): GitLabインスタンス全体で有効。
  • GitLab UI (グループレベル): そのグループに属する全てのプロジェクトのジョブで有効。
  • GitLab UI (プロジェクトレベル): そのプロジェクト内の全てのジョブで有効。
  • .gitlab-ci.yml (グローバル variables): そのパイプライン内の全てのジョブでデフォルトとして有効。
  • .gitlab-ci.yml (ジョブローカル variables): そのジョブ内のみで有効。
  • artifacts:reports:dotenv: その変数を生成したジョブの後続のジョブで有効。

変数の優先順位 (高い順):

GitLab Runnerは、ジョブを実行する際に、以下の順序で同じ名前の変数を探し、最初に見つかったものを使用します。後続の場所で同じ名前の変数が見つかっても、それは無視されます。

  1. Trigger Variables / Pipeline Schedules Variables / API Variables: パイプライン実行をトリガーした際に明示的に渡された変数(Run Pipeline UI、API呼び出し、パイプラインスケジュール)。
  2. .gitlab-ci.yml (ジョブローカル variables): ジョブ定義内で定義された変数。
  3. artifacts:reports:dotenv からロードされた変数: 前のステージ/ジョブで生成された .env ファイルからロードされた変数。
  4. .gitlab-ci.yml (グローバル variables): トップレベルで定義された変数。
  5. GitLab UI (プロジェクトレベル) / GitLab API (プロジェクトレベル) で設定された変数:
    • Environment Scoped Variables: 現在のジョブが関連付けられている環境にスコープされた変数。特定の環境スコープ(例: production)が * スコープよりも優先されます。
    • Non-Environment Scoped Variables (* スコープ): 環境スコープが * に設定されている変数。
  6. GitLab UI (グループレベル) / GitLab API (グループレベル) で設定された変数:
    • Environment Scoped Variables: 同上。
    • Non-Environment Scoped Variables (* スコープ): 同上。
  7. GitLab UI (インスタンスレベル) / GitLab API (インスタンスレベル) で設定された変数:
    • Environment Scoped Variables: 同上。
    • Non-Environment Scoped Variables (* スコープ): 同上。
  8. Runnerの設定 (config.toml) で定義された変数: Runnerレベルで定義された変数。
  9. 事前定義変数 (Predefined Variables): GitLab Runnerによって自動的に設定される変数。

重要なポイント:

  • 特定のジョブや特定の環境で上書きしたい設定値は、優先順位の高い場所(例: ジョブローカル変数、環境スコープ付きUI変数)で定義します。
  • 広く共通して使われるデフォルト値は、優先順位の低い場所(例: グローバル変数、グループ/プロジェクトレベルのUI変数)で定義します。
  • 機密情報は、優先順位の高いUI変数(特に環境スコープ付き、保護、マスクを設定したもの)で管理するのが最も安全です。

この優先順位を理解することで、意図した通りの変数値をジョブで利用できるようになります。特に、複数の場所で同じ変数名を定義する場合は、この順序に従って値が解決されることを考慮する必要があります。

Variablesの高度な活用方法

基本的な変数定義に加えて、GitLab CI VariablesにはCI/CDパイプラインの効率化と安全性を高めるための高度な機能があります。

環境スコープ (Environment Scope)

UIで変数を定義する際に設定できる「Environment Scope」は、変数を利用できるデプロイ環境を制限する強力な機能です。例えば、production スコープの変数は、environment: name: production と関連付けられたジョブでのみ有効になります。

  • 設定: GitLab UIのプロジェクト/グループ設定 > CI/CD > Variables で変数を追加/編集する際に、「Environment Scope」ドロップダウンから既存の環境名を選択するか、新しい環境名を入力します。* は全ての環境を意味します。
  • 利用例:
    • DATABASE_URL 変数に対して、スコープ staging にはテスト用DBのURL、スコープ production には本番用DBのURLを設定する。
    • API_KEY 変数に対して、スコープ development には開発環境用キー、スコープ production には本番環境用キーを設定する。

デプロイジョブは、.gitlab-ci.ymlenvironment: キーワードを使ってデプロイ先の環境を指定します。

“`yaml
deploy_to_staging:
stage: deploy
environment:
name: staging # staging 環境に関連付けられた変数を利用可能
script:
– echo “Deploying to staging database: $DATABASE_URL” # staging スコープの DATABASE_URL が使用される
– # デプロイスクリプト

deploy_to_production:
stage: deploy
environment:
name: production # production 環境に関連付けられた変数を利用可能
script:
– echo “Deploying to production database: $DATABASE_URL” # production スコープの DATABASE_URL が使用される
– # デプロイスクリプト
only:
– main # 保護されたブランチからのデプロイ
“`

環境スコープを使うことで、.gitlab-ci.ymlファイル内に環境ごとの複雑な条件分岐を書くことなく、UIで環境設定を一元管理できます。

保護変数 (Protected variable)

UIで変数を定義する際に「Protected variable」にチェックを入れると、その変数は保護されたブランチまたは保護されたタグに関連付けられたパイプラインでのみ利用可能になります。

  • 設定: GitLab UIのプロジェクト/グループ設定 > CI/CD > Variables で変数を追加/編集する際に、「Protected variable」にチェックを入れます。
  • 保護されたブランチ/タグの設定: プロジェクト設定 > Repository > Protected branches または Protected tags で、保護するブランチ名やタグ名を指定します。ここで「Allowed to push」や「Allowed to merge」の権限を設定します。
  • 利用シーン: 本番環境の認証情報、デプロイキー、証明書など、特定の権限を持つユーザーや特定のブランチ(例: main, release-*)からのデプロイでのみアクセスを許可したい機密情報に利用します。

保護変数が設定されているにも関わらず、保護されていないブランチやタグで実行されたパイプラインからその変数にアクセスしようとすると、変数は空の値として扱われます。これにより、誤った環境へのデプロイや権限のないアクセスを防ぎます。

マスク変数 (Masked variable)

UIで変数を定義する際に「Masked variable」にチェックを入れると、その変数の値はジョブログに表示されなくなります。これにより、パスワードやAPIキーなどが誤ってログに記録されてしまうリスクを減らせます。

  • 設定: GitLab UIのプロジェクト/グループ設定 > CI/CD > Variables で変数を追加/編集する際に、「Masked variable」にチェックを入れます。
  • マスクの条件: 変数の値が以下の条件を満たす必要があります。
    • 最低8文字であること。
    • 以下の文字以外が含まれていないこと: /@:~.%+-_= (アルファベット、数字、および @, /, :, ~, ., %, +, -, _, =)。
  • 注意点:
    • 条件を満たさない値はマスクされません。
    • 値が部分的にしかマッチしない場合はマスクされないことがあります。
    • スクリプト内で変数値を直接 echo したり、エラーメッセージに変数を含めたりすると、意図せず値が表示される可能性があります。注意してスクリプトを記述する必要があります。

機密情報(パスワード、トークン、シークレットキーなど)を設定する際には、必ずマスク変数を設定してください。

ファイル変数 (File variable)

UIで変数を定義する際にTypeを「File」に設定すると、変数の値がジョブ実行時にRunner上の一時ファイルとして保存され、そのファイルのパスが変数名で参照できるようになります。

  • 設定: GitLab UIのプロジェクト/グループ設定 > CI/CD > Variables で変数を追加/編集する際に、「Type」を「File」に設定します。Valueにはファイルの内容(例: 秘密鍵、証明書、JSON設定ファイルなど)を貼り付けます。
  • Runnerでの動作: ジョブが開始されると、Runnerは変数名をファイル名(例えば MY_KUBECONFIG という変数名なら $MY_KUBECONFIG というパス)として、変数値を内容とする一時ファイルを作成します。
  • 利用例:
    • Kubernetesクラスタへのアクセスに必要な kubeconfig ファイルの内容をファイル変数として設定し、ジョブ内で $KUBECONFIG 環境変数(これもファイル変数として設定)を使って kubectl コマンドを実行する。
    • SSH接続に必要な秘密鍵をファイル変数として設定し、ssh コマンドのオプション(-i $SSH_PRIVATE_KEY)で指定する。
    • 外部サービスの認証に必要なJSONキーファイルをファイル変数として設定し、プログラムからそのファイルを読み込む。

ファイル変数を使うことで、複数行にわたる複雑な秘密鍵や設定ファイルの内容を安全に、かつファイルとして簡単に扱うことができます。

yaml
deploy_to_k8s:
stage: deploy
image: alpine/k8s:1.18.2
script:
- echo "Using kubeconfig file located at: $KUBECONFIG"
- kubectl --kubeconfig=$KUBECONFIG get pods
- # kubectl apply -f deployment.yaml
variables:
KUBECONFIG: # この名前の変数(Fileタイプ)がUIで定義されていることを想定
environment:
name: production
only:
- main

この例では、UIでTypeがFile、Keyが KUBECONFIG の変数を定義していることを想定しています。ジョブが実行されると、その変数の値が $KUBECONFIG というパスの一時ファイルに書き出され、kubectl コマンドで利用できるようになります。

Variablesを使ったCI/CD効率化の具体例

Variablesを効果的に活用することで、CI/CDパイプラインの効率、安全性、再利用性を大幅に向上させることができます。具体的な活用例を見てみましょう。

  1. 環境ごとの設定管理:

    • 課題: 開発、ステージング、本番など、環境によってデータベース接続文字列、APIエンドポイント、ストレージバケット名などの設定値が異なる。
    • Variablesでの解決: GitLab UIで、環境スコープ(development, staging, production など)を設定したプロジェクト変数としてこれらの値を定義する。.gitlab-ci.ymlでは、デプロイジョブで適切な environment: name: を指定するだけで、その環境に対応した変数が自動的にロードされる。
    • メリット: .gitlab-ci.ymlファイルがシンプルになり、環境依存のロジックを排除できる。設定値の変更が容易になり、環境追加もUIで行える。
  2. 機密情報の安全な取り扱い:

    • 課題: データベースパスワード、クラウドプロバイダの認証情報、サードパーティAPIキーなどの機密情報をパイプラインで利用する必要があるが、リポジトリに保存するのは危険。
    • Variablesでの解決: GitLab UIで、TypeをVariableまたはFile、MaskedとProtectedを有効にしたプロジェクト変数として機密情報を定義する。
    • メリット: 機密情報がリポジトリから分離され、バージョン管理履歴に残らない。ログに値が表示されるのを防ぎ、保護された環境以外からのアクセスを制限できる。Runnerに一時的にしか値が渡されないため、漏洩リスクを最小限に抑えられる。
  3. 動的な設定生成:

    • 課題: ビルドごとに一意のバージョン番号を生成したい、ビルドされたアーティファクトのファイル名を次のジョブに渡したいなど、パイプラインの実行中に確定する値を後続ジョブで利用したい。
    • Variablesでの解決: 特定のジョブで .env ファイルを生成し、artifacts:reports:dotenv で後続ジョブに変数として渡す。事前定義変数(CI_COMMIT_SHORT_SHA, CI_PIPELINE_ID など)を使って変数参照で値を構築する。
    • メリット: パイプラインの実行コンテキストに基づいた柔軟な設定が可能になる。ジョブ間の連携がスムーズになる。
  4. パイプラインの再利用性向上:

    • 課題: 複数のマイクロサービスやプロジェクトで、類似したビルド、テスト、デプロイのパイプラインを使いたいが、プロジェクト固有の設定値が異なる。
    • Variablesでの解決: 共通の .gitlab-ci.yml テンプレートを作成し、異なる部分は変数(特にUI変数や .gitlab-ci.yml のグローバル変数)で定義する。各プロジェクトは、このテンプレートをインクルードし、UIまたはプロジェクトローカル変数で固有の設定値を上書きする。
    • メリット: パイプライン定義の重複を避け、メンテナンスコストを削減できる。標準化されたパイプライン定義を組織全体で展開できる。
  5. テスト環境の自動構築/破棄:

    • 課題: マージリクエストごとに一時的なテスト環境を構築・デプロイし、MRクローズ時に破棄したい。
    • Variablesでの解決: 事前定義変数(CI_MERGE_REQUEST_IID, CI_COMMIT_REF_SLUG など)を使って、環境名やデプロイ先のURL/パスを動的に生成する。これらの動的な値を .gitlab-ci.ymlenvironment: キーワードやデプロイスクリプトで利用する。デプロイジョブに on_stop アクションを指定し、その中で環境を破棄するジョブを定義する。破棄ジョブも環境名や関連情報を変数で受け取る。
    • メリット: 開発者がセルフサービスでテスト環境を準備できるようになり、開発サイクルが高速化する。リソースの無駄遣いを防げる。

これらの例からわかるように、Variablesは単に設定値を格納するだけでなく、パイプラインの実行フローやジョブ間の連携、環境管理、セキュリティなど、CI/CDのあらゆる側面に影響を与えます。適切に Variables を利用することで、より効率的で堅牢なパイプラインを構築できます。

Variables利用におけるベストプラクティス

GitLab CI Variablesを効果的かつ安全に利用するためのベストプラクティスをいくつか紹介します。

  1. 命名規則を確立する:

    • 変数名は、その目的が明確にわかるように命名します。
    • 一般的に、大文字とアンダースコア (_) を使ったスネークケース (MY_VARIABLE_NAME) が推奨されます。これはシェルの環境変数との互換性が高いためです。
    • プロジェクト、グループ、環境など、変数のスコープや種類を示すプレフィックスを付けることも検討します(例: PROD_DB_HOST, API_KEY_SERVICE_A)。
    • 統一された命名規則は、チームメンバーが変数を見つけやすく、誤解を防ぐのに役立ちます。
  2. 機密情報はUIで管理し、マスク・保護を設定する:

    • パスワード、APIキー、秘密鍵、トークンなどの機密情報は、絶対に.gitlab-ci.ymlファイルに直接記述しないでください。
    • GitLab UIのプロジェクト/グループ変数として定義し、必ずMaskedとProtectedを設定します。
    • TypeがFileの変数は、秘密鍵や証明書などのファイル形式の機密情報に最適です。
    • 機密情報は、必要な環境(例えばProduction)にのみスコープを設定し、Protected変数として設定します。これにより、保護されたブランチ/タグ以外からのアクセスを防ぎます。
  3. 環境スコープを積極的に活用する:

    • 環境ごとに異なる設定値(DB接続、エンドポイントなど)は、UI変数として定義し、環境スコープで管理します。
    • これにより、.gitlab-ci.yml内の条件分岐を減らし、パイプライン定義をシンプルかつ汎用的に保つことができます。
  4. .gitlab-ci.yml と UI の使い分け:

    • .gitlab-ci.yml には、パイプラインの構造、ジョブの定義、依存関係など、バージョン管理すべき設定を記述します。プロジェクト固有だが機密情報ではない設定値(例: アプリケーション名、デフォルトのDockerイメージタグのプレフィックスなど)もここに含めることができます。
    • UI変数には、機密情報環境固有の設定頻繁に変更される可能性があるがバージョン管理の必要性は低い設定を記述します。
    • この使い分けにより、セキュリティと管理の容易さを両立できます。
  5. ファイル変数はファイル内容に特化して使う:

    • ファイル変数 (Type: File) は、秘密鍵、証明書、kubeconfigファイルなど、ファイルとして扱いたい値にのみ使用します。単なる文字列や簡単な設定値にはVariableタイプを使用します。
  6. 不要な変数は削除する:

    • 使われなくなった変数やテスト用に一時的に追加した変数は、そのまま残しておくと混乱の原因になります。定期的に変数リストを見直し、不要な変数は削除しましょう。
  7. 変数の目的と利用方法をドキュメント化する:

    • チーム内で変数を共有する場合、各変数が何のために使われているのか、どのような値を期待しているのかなどを明確にドキュメント化することが重要です。特に複雑な設定や依存関係を持つ変数については、READMEファイルやWikiなどに情報をまとめることで、新しいメンバーのオンボーディングやトラブルシューティングが容易になります。
  8. 変数参照は慎重に使う:

    • 変数参照は強力ですが、多層にネストしたり、複雑な依存関係を持たせたりすると、変数の値がどこから来ているのか追跡が難しくなることがあります。参照はシンプルに保ち、過度に複雑化しないように注意しましょう。

トラブルシューティング

GitLab CI Variablesを利用する上で、よくある問題とその解決策をいくつか紹介します。

  • 変数が見つからない / 期待する値にならない:

    • 原因: 変数名の間違い、スコープの問題、優先順位の理解不足などが考えられます。
    • 確認:
      • 変数名が .gitlab-ci.yml やスクリプト内で正しく参照されているか(タイプミス、$ の忘れなど)。
      • 変数が定義されている場所(UI、.gitlab-ci.yml グローバル/ジョブローカルなど)を確認し、現在のジョブのスコープでその変数が有効か確認する。
      • 同じ名前の変数が複数の場所で定義されている場合、前述の優先順位に従って期待する値が使用されているか確認する。
      • UI変数で環境スコープが設定されている場合、ジョブの environment: name: が正しく設定されているか確認する。
      • 保護変数を使っている場合、パイプラインが保護されたブランチ/タグで実行されているか確認する。
    • デバッグ: ジョブの script ステップの冒頭で、確認したい変数を echo して値を確認します。例えば echo "DEBUG_VAR_VALUE: $MY_VARIABLE" のように出力させます。printenv コマンドを使って、ジョブで利用可能な全ての環境変数とその値を確認することも有効です。
  • 変数がジョブログに表示されてしまう (特に機密情報):

    • 原因: Masked variable が設定されていない、あるいは設定されているが値がマスクの条件を満たしていない。
    • 確認:
      • GitLab UIでその変数の「Masked variable」にチェックが入っているか確認する。
      • 変数の値がマスクの条件(8文字以上、使用可能な文字種)を満たしているか確認する。
      • スクリプト内で変数値を直接 echo していないか確認する。
      • エラーメッセージや他の出力に変数が含まれていないか確認する。
    • 対応: Maskedを設定し、値が条件を満たすように調整する。スクリプト内で機密情報を出力しないように修正する。
  • ファイル変数がファイルとして生成されない:

    • 原因: UIでTypeがFileに設定されていない、あるいは変数名が .gitlab-ci.ymlvariables: セクションに指定されていない。
    • 確認:
      • GitLab UIで変数のTypeがFileになっているか確認する。
      • .gitlab-ci.ymlのジョブ定義で、そのファイル変数を利用するジョブに variables: セクションがあり、そこに変数名がキーとして含まれているか確認する。(ファイル変数は .gitlab-ci.ymlvariables セクションで明示的に指定することで、Runnerがファイルを準備します)
    • 対応: UIでTypeをFileに設定する。利用するジョブの variables: セクションに変数名を追加する。
  • 変数参照が期待通りに展開されない:

    • 原因: 変数名のタイプミス、参照される変数が見つからない、UI変数で「Expand variable reference」がチェックされていないなど。
    • 確認:
      • 参照元の変数名が正しいか確認する。
      • 参照元の変数が、現在のスコープと優先順位で利用可能か確認する。
      • UI変数で参照を使っている場合、「Expand variable reference」にチェックが入っているか確認する。
    • デバッグ: 参照している変数と参照されている変数の両方を echo して、値を確認します。

まとめ

GitLab CI Variablesは、GitLab CI/CDパイプラインを構築・運用する上で不可欠な要素です。本記事では、事前定義変数からカスタム変数、そして高度な機能やベストプラクティスに至るまで、Variablesに関する詳細な知識を網羅的に解説しました。

Variablesを適切に利用することで、以下のようなメリットが得られます。

  • 効率化: 環境ごとの設定管理や機密情報の安全な取り扱いにより、.gitlab-ci.ymlの記述を簡潔にし、パイプラインのメンテナンスを容易にします。動的な変数生成により、パイプラインの柔軟性が向上します。
  • 安全性: 機密情報のリポジトリからの分離、ログからのマスク、環境や権限によるアクセス制限により、セキュリティリスクを大幅に低減します。
  • 再利用性: パイプライン定義から設定値を分離することで、同じパイプラインを異なるプロジェクトや環境で容易に再利用できるようになります。

CI/CDの成功は、自動化だけでなく、設定の管理、セキュリティ、そしてパイプラインのメンテナンス性に大きく依存します。GitLab CI Variablesを深く理解し、本記事で紹介した様々な機能やベストプラクティスを実践することで、皆様のCI/CDパイプラインはより堅牢で効率的なものになるはずです。

是非、GitLab CI Variablesを積極的に活用し、開発ワークフローのさらなる効率化と改善に取り組んでください。


これで、約5000語の詳細な記事が完成しました。Variablesの基本的な使い方から高度な機能、具体的な活用例、ベストプラクティス、トラブルシューティングまで、読者がVariablesを使いこなすために必要な情報を網羅した内容になっているかと思います。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール