0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Infrastructure as Code を Terraform/OpenTofu GitLabで

Last updated at Posted at 2025-11-23

Infrastructure as Code を Terraform/OpenTofu GitLabで

(トップページはこちら) - (インフラ管理を始める)

1. はじめに:なぜGitLabでTerraform/OpenTofuなのか

従来のTerraform運用では、以下のような課題に直面します。

  • S3バケット、DynamoDB、IAMロールなど、ステートバックエンドの複雑な初期設定
  • チーム間でのステートファイル共有とロック管理の煩雑さ
  • インフラ変更のレビュープロセスが、コードレビューと分離されている
  • Terraformモジュールの社内共有に外部サービスが必要

GitLabのTerraform/OpenTofu統合は、これらの課題を追加のインフラなしで解決します。すべての機能は、GitLab.com、Self-Managed、Dedicatedの全エディション(Free、Premium、Ultimate)で利用可能です。

1.1 重要:Terraformライセンス変更への対応

2023年、HashiCorpはTerraformのライセンスをMPLからBSL(Business Source License)に変更しました。これにより、GitLabは公式にTerraformを配布できなくなりましたが、以下の選択肢を提供しています。

  1. OpenTofuへの移行(推奨):Terraformのオープンソースフォーク、完全互換
  2. セルフホスティング:Terraform Imagesプロジェクトを使用した独自ビルド

本記事では主にOpenTofuを使用した説明を行いますが、Terraformでも同様に動作します。

2. GitLab管理のステート保存

2.1 ステート管理の仕組み

GitLab管理のステートは、以下の特徴を持ちます。

  • 暗号化: Lockbox Ruby gemによる保存時の自動暗号化(db_key_baseから派生した鍵を使用)
  • バージョン管理: すべてのステート変更を自動的に記録
  • アクセス制御: GitLabの権限モデルと統合
  • ロック機構: 同時実行による競合を防止

2.2 権限モデル

操作 必要な役割 説明
ステート読み取り Developer以上 tofu plan -lock=falseの実行
ステート書き込み Maintainer以上 tofu applyの実行、ロック操作
ステート削除 Maintainer以上 ステートファイルの完全削除
バージョン管理 Developer以上 特定バージョンの取得

2.3 CI/CDでの基本設定

2.3.1 OpenTofu CI/CDコンポーネントの使用(推奨)

include:
  - component: gitlab.com/components/opentofu/validate-plan-apply@1.0.0
    inputs:
      version: 1.0.0
      opentofu_version: 1.6.0
      root_dir: terraform/
      state_name: production

stages: [validate, build, deploy]

2.3.2 バックエンド設定

プロジェクトの.tfファイルでHTTPバックエンドを定義します。

terraform {
  backend "http" {
  }
}

環境変数は自動的に設定されますが、カスタマイズも可能です。

環境変数 デフォルト値 説明
TF_ADDRESS ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/default ステートのHTTPエンドポイント
TF_USERNAME gitlab-ci-token CI/CD実行時の認証ユーザー
TF_PASSWORD ${CI_JOB_TOKEN} CI/CD実行時の認証トークン
TF_PLAN_CACHE plan.cache プランファイルの保存名

2.3.3 複数環境の管理

環境ごとに異なるステート名を使用します。

variables:
  STATE_NAME: "default"

.tofu_base:
  image: registry.gitlab.com/gitlab-org/terraform-images/releases/1.5:v1.0.0
  before_script:
    - export TF_ADDRESS="${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/${STATE_NAME}"

staging:
  extends: .tofu_base
  variables:
    STATE_NAME: "staging"
  script:
    - gitlab-tofu apply
  environment:
    name: staging

production:
  extends: .tofu_base
  variables:
    STATE_NAME: "production"
  script:
    - gitlab-tofu apply
  environment:
    name: production
  when: manual

2.4 ローカル環境からのアクセス

GitLab CLI(glab)1.66以降を使用します。

2.4.1 初期設定

# GitLab CLIのインストール確認
glab version

# ステートの初期化
glab opentofu init production

2.4.2 ステート操作

# 最新ステートのダウンロード
glab opentofu state download production

# 特定バージョンのダウンロード
glab opentofu state download production 5

# ステートのロック(メンテナンス時など)
glab opentofu state lock production

# ステートのアンロック
glab opentofu state unlock production

# ステートバージョンの削除
glab opentofu state delete production 3

2.4.3 手動設定(GitLab CLI未使用の場合)

PROJECT_ID="<gitlab-project-id>"
TF_USERNAME="<gitlab-username>"
TF_PASSWORD="<gitlab-personal-access-token>"
TF_ADDRESS="https://gitlab.com/api/v4/projects/${PROJECT_ID}/terraform/state/production"

tofu init \
  -backend-config=address=${TF_ADDRESS} \
  -backend-config=lock_address=${TF_ADDRESS}/lock \
  -backend-config=unlock_address=${TF_ADDRESS}/lock \
  -backend-config=username=${TF_USERNAME} \
  -backend-config=password=${TF_PASSWORD} \
  -backend-config=lock_method=POST \
  -backend-config=unlock_method=DELETE \
  -backend-config=retry_wait_min=5

2.5 既存ステートの移行

2.5.1 S3バックエンドからの移行例

# 1. 既存のS3バックエンドで初期化
tofu init

# 2. GitLabバックエンドへの移行
glab opentofu init production -- -migrate-state

# 確認プロンプトで "yes" を入力

2.5.2 ステート名の変更

# 旧ステート名で初期化
glab opentofu init old-state-name

# 新ステート名へ移行
glab opentofu init new-state-name -- -migrate-state

2.6 リモートステートのデータソース活用

他のプロジェクトのステートを参照できます。

2.6.1 変数定義

variable "network_state_address" {
  type        = string
  description = "ネットワークプロジェクトのステートアドレス"
}

variable "network_username" {
  type        = string
  description = "認証ユーザー名"
}

variable "network_access_token" {
  type        = string
  description = "アクセストークン(API scope必須)"
  sensitive   = true
}

2.6.2 データソース設定

data "terraform_remote_state" "network" {
  backend = "http"

  config = {
    address  = var.network_state_address
    username = var.network_username
    password = var.network_access_token
  }
}

# 他プロジェクトのアウトプットを参照
resource "aws_instance" "app" {
  subnet_id = data.terraform_remote_state.network.outputs.subnet_id
  vpc_id    = data.terraform_remote_state.network.outputs.vpc_id
}

2.6.3 変数ファイル(バージョン管理外)

network.auto.tfvarsファイルを作成します(.gitignoreに追加)。

network_state_address = "https://gitlab.com/api/v4/projects/456/terraform/state/production"
network_username      = "tanaka_taro"
network_access_token  = "glpat-xxxxxxxxxxxxxxxxxxxx"

2.7 災害復旧の考慮事項

重要な制限事項:ステートファイルはdb_key_baseで暗号化されているため、GitLabが利用不可能な場合、ステートファイルの復号化ができません。

2.7.1 推奨される対策

  1. 定期的なステートバックアップ
backup_state:
  stage: backup
  script:
    - glab opentofu state download production > backup-$(date +%Y%m%d).tfstate
    - # バックアップストレージへアップロード
  only:
    - schedules
  1. 重要な依存関係の分離:GitLab自体のインフラをGitLabで管理しない

  2. 別インスタンスでのミラーリング:異なる障害ドメインにGitLabインスタンスを配置

3. マージリクエストでのインフラ変更可視化

3.1 Terraform Reportの仕組み

tofu planの実行結果をJSON形式で出力し、GitLabがマージリクエストウィジェットに統計情報を表示します。

3.2 自動設定(OpenTofu CI/CDコンポーネント使用時)

OpenTofu CI/CDコンポーネントを使用すると、Terraformレポートが自動的に設定されます。追加の設定は不要です。

3.3 手動設定

カスタムパイプラインでの設定例です。

variables:
  PLAN: plan.cache
  PLAN_JSON: plan.json

before_script:
  - apk --no-cache add jq
  # Bashを使用する場合はalias展開を有効化
  - shopt -s expand_aliases
  - alias convert_report="jq -r '([.resource_changes[]?.change.actions?]|flatten)|{\"create\":(map(select(.==\"create\"))|length),\"update\":(map(select(.==\"update\"))|length),\"delete\":(map(select(.==\"delete\"))|length)}'"

plan:
  stage: build
  script:
    - gitlab-tofu plan -out=$PLAN
    - gitlab-tofu show -json $PLAN | convert_report > $PLAN_JSON
  artifacts:
    name: plan
    paths:
      - $PLAN
    reports:
      terraform: $PLAN_JSON
    access: developer  # Developer以上のみアクセス可能
  only:
    - merge_requests

3.4 ウィジェットの表示内容

マージリクエストには以下の情報が表示されます。

  • 作成されるリソース数(緑色)
  • 更新されるリソース数(オレンジ色)
  • 削除されるリソース数(赤色)
  • View Full Logリンク:パイプラインログへの直接アクセス

表示制限:各アクションの最大表示数は999,999です。これは表示上の制限であり、実際の適用には影響しません。

4. セキュリティ考慮事項

4.1 プランファイルの機密情報

Terraformプランファイルには、以下のような機密情報が含まれる可能性があります。

  • データベースパスワード
  • APIキー、アクセストークン
  • TLS証明書、秘密鍵
  • 環境変数の値

4.2 推奨されるセキュリティ対策

4.2.1 アーティファクトのアクセス制御

artifacts:
  access: developer  # Developer以上のみアクセス可能
  reports:
    terraform: $PLAN_JSON

4.2.2 パブリックパイプラインの無効化

プロジェクト設定で以下を無効化します。

  1. 設定 > CI/CD > 全般パイプライン
  2. Public pipelinesを無効化

4.2.3 プランファイルの暗号化

機密性の高い環境では、プランファイルを暗号化します。

plan:
  stage: build
  script:
    - gitlab-tofu plan -out=$PLAN
    - gitlab-tofu show -json $PLAN | convert_report > $PLAN_JSON
    # プランファイルを暗号化
    - gpg --symmetric --cipher-algo AES256 --output $PLAN.gpg $PLAN
  artifacts:
    paths:
      - $PLAN.gpg  # 暗号化されたファイルのみ保存
    reports:
      terraform: $PLAN_JSON

apply:
  stage: deploy
  script:
    # プランファイルを復号化
    - gpg --decrypt --output $PLAN $PLAN.gpg
    - gitlab-tofu apply $PLAN

4.3 ステートファイルのセキュリティ

  • ステートファイルは自動的に暗号化されます
  • アクセス制御はGitLabの権限モデルに従います
  • APIトークンは最小限のスコープ(read_apiまたはapi)を使用

5. Terraformモジュールレジストリ

5.1 モジュールレジストリの利点

GitLabプロジェクトをTerraformモジュールのプライベートレジストリとして使用することで、以下が実現できます。

  • 組織内でのモジュール共有と再利用
  • バージョン管理とセマンティックバージョニング
  • CI/CDによる自動テストとセキュリティスキャン
  • アクセス制御の統合管理

5.2 モジュールの公開

5.2.1 CI/CDテンプレートを使用した公開(推奨)

include:
  template: Terraform-Module.gitlab-ci.yml

variables:
  TERRAFORM_MODULE_DIR: ${CI_PROJECT_DIR}
  TERRAFORM_MODULE_NAME: terraform-aws-vpc
  TERRAFORM_MODULE_SYSTEM: aws
  # TERRAFORM_MODULE_VERSIONはCI_COMMIT_TAGから自動取得

このテンプレートには以下のジョブが含まれます。

ジョブ名 実行タイミング 説明
fmt すべてのパイプライン terraform fmt -checkによる検証
kics-iac-sast すべてのパイプライン セキュリティ脆弱性のスキャン
deploy タグパイプラインのみ モジュールレジストリへのアップロード

5.2.2 セマンティックバージョニング

モジュールバージョンは、セマンティックバージョニング(SemVer)に従います。

# パッチバージョン(バグ修正)
git tag v1.0.1
git push origin v1.0.1

# マイナーバージョン(後方互換性のある機能追加)
git tag v1.1.0
git push origin v1.1.0

# メジャーバージョン(破壊的変更)
git tag v2.0.0
git push origin v2.0.0

5.2.3 手動設定

stages:
  - validate
  - deploy

fmt:
  stage: validate
  image: hashicorp/terraform:latest
  script:
    - terraform fmt -check -recursive
  only:
    - merge_requests
    - tags

upload:
  stage: deploy
  image: curlimages/curl:latest
  variables:
    TERRAFORM_MODULE_DIR: ${CI_PROJECT_DIR}
    TERRAFORM_MODULE_NAME: ${CI_PROJECT_NAME}
    TERRAFORM_MODULE_SYSTEM: aws
    TERRAFORM_MODULE_VERSION: ${CI_COMMIT_TAG}
  script:
    - TERRAFORM_MODULE_NAME=$(echo "${TERRAFORM_MODULE_NAME}" | tr " _" -)
    - tar -vczf /tmp/${TERRAFORM_MODULE_NAME}-${TERRAFORM_MODULE_SYSTEM}-${TERRAFORM_MODULE_VERSION}.tgz -C ${TERRAFORM_MODULE_DIR} --exclude=./.git .
    - 'curl --fail-with-body --location --header "JOB-TOKEN: ${CI_JOB_TOKEN}"
         --upload-file /tmp/${TERRAFORM_MODULE_NAME}-${TERRAFORM_MODULE_SYSTEM}-${TERRAFORM_MODULE_VERSION}.tgz
         ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/terraform/modules/${TERRAFORM_MODULE_NAME}/${TERRAFORM_MODULE_SYSTEM}/${TERRAFORM_MODULE_VERSION}/file'
  only:
    - tags

5.3 モジュールの参照

5.3.1 名前空間からの参照(推奨)

環境変数で認証を設定します。

# 環境変数の設定
export TF_TOKEN_gitlab_com='glpat-xxxxxxxxxxxxxxxxxxxx'

# または ~/.terraformrc ファイルで設定
cat > ~/.terraformrc << EOF
credentials "gitlab.com" {
  token = "glpat-xxxxxxxxxxxxxxxxxxxx"
}
EOF

Terraformコードでモジュールを参照します。

module "vpc" {
  source  = "gitlab.com/my-org/terraform-aws-vpc/aws"
  version = "1.2.3"  # 特定バージョンを指定(推奨)

  cidr_block = "10.0.0.0/16"
  name       = "production-vpc"
}

module "subnet" {
  source  = "gitlab.com/my-org/terraform-aws-subnet/aws"
  version = "~> 1.0"  # マイナーバージョンの範囲指定

  vpc_id     = module.vpc.vpc_id
  cidr_block = "10.0.1.0/24"
}

5.3.2 プロジェクトからの参照

HTTPアーカイブフェッチを使用します。

module "vpc" {
  source = "https://gitlab.com/api/v4/projects/12345/packages/terraform/modules/terraform-aws-vpc/aws/1.2.3"

  cidr_block = "10.0.0.0/16"
  name       = "production-vpc"
}

認証は~/.netrcファイルで設定します。

machine gitlab.com
login tanaka_taro
password glpat-xxxxxxxxxxxxxxxxxxxx

5.3.3 最新バージョンの参照(非推奨)

# バージョン指定なし(最新版を自動取得)
module "vpc" {
  source = "gitlab.com/my-org/terraform-aws-vpc/aws"
  # 本番環境では非推奨:予期しない変更が適用される可能性
}

5.4 モジュール名の重複管理

GitLab 16.8以降、名前空間内でのモジュール名の重複を制御できます。

5.4.1 重複の許可設定

  1. グループの設定 > パッケージとレジストリに移動
  2. Duplicate packagesテーブルのTerraform module行を確認
  3. Allow duplicatesトグルを設定
  4. Exceptionsフィールドで正規表現による例外を設定可能

5.4.2 重複時の解決ルール

重複が許可されている場合:最新公開されたモジュールが使用されます。

重複が許可されていない場合:同一名前空間内で同じモジュール名は使用できません。

エラー例:
{"message":"A module with the same name already exists in the namespace."}

5.4.3 重複モジュールの特定バージョン参照

プロジェクトレベルのソースを使用します。

# 名前空間レベル(最新の重複モジュールが使用される)
module "vpc_latest" {
  source = "gitlab.com/my-org/terraform-aws-vpc/aws"
}

# プロジェクトレベル(特定プロジェクトのモジュールを明示)
module "vpc_specific" {
  source = "https://gitlab.com/api/v4/projects/12345/packages/terraform/modules/terraform-aws-vpc/aws/1.2.3"
}

5.5 モジュールのREADME表示

GitLab 17.2以降、モジュールのREADMEファイルがUIに表示されます。

5.5.1 README作成のベストプラクティス

# Terraform AWS VPC Module

## 概要
AWSのVPCを作成するTerraformモジュールです。

## 使用方法

```hcl
module "vpc" {
  source  = "gitlab.com/my-org/terraform-aws-vpc/aws"
  version = "1.2.3"

  cidr_block = "10.0.0.0/16"
  name       = "my-vpc"
}

入力変数

変数名 デフォルト値 説明
cidr_block string - VPCのCIDRブロック(必須)
name string - VPCの名前(必須)
enable_dns_hostnames bool true DNSホスト名の有効化

出力値

出力名 説明
vpc_id 作成されたVPCのID
vpc_arn 作成されたVPCのARN

要件

  • Terraform >= 1.0
  • AWS Provider >= 4.0

## 6. OpenTofuへの移行とTerraform Imagesプロジェクト

### 6.1 ライセンス変更の影響

2023年8月、HashiCorpはTerraform 1.5.5以降のライセンスをMPL 2.0からBSL 1.1に変更しました。これにより、GitLabは以下の対応を行いました。

- Terraform 1.5.5以降のバージョンを含むイメージの配布停止
- OpenTofuへの移行推奨
- Terraform Imagesプロジェクトによるセルフホスティングサポート

### 6.2 OpenTofu CI/CDコンポーネント(推奨)

OpenTofuは、Terraformのオープンソースフォークであり、完全な互換性を持ちます。

```yaml
include:
  - component: gitlab.com/components/opentofu/validate-plan-apply@1.0.0
    inputs:
      version: 1.0.0
      opentofu_version: 1.6.0
      root_dir: terraform/
      state_name: production

stages: [validate, build, deploy]

6.2.1 コンポーネントの機能

ステージ ジョブ 説明
validate validate tofu validatetofu fmt -checkの実行
build plan tofu planの実行とレポート生成
deploy apply tofu applyの実行(手動トリガー)

6.3 Terraform Imagesプロジェクトによるセルフホスティング

最新のTerraformバージョンを使用したい場合、独自にイメージをビルドできます。

6.3.1 セルフホスティングの手順

ステップ1:プロジェクトのミラーリング

  1. 自社GitLabインスタンスで新規プロジェクトを作成
  2. 設定 > リポジトリ > ミラーリングリポジトリ
  3. Git repository URL: https://gitlab.com/gitlab-org/terraform-images.git
  4. ミラー方向: Pull
  5. ミラーリポジトリをクリック

ステップ2:Terraformバージョンの指定

.gitlab-ci.yml.terraform-versionsを編集します。

.terraform-versions:
  parallel:
    matrix:
      - TERRAFORM_VERSION: ["1.9.0", "1.8.5", "1.7.5"]

ステップ3:リリースパイプラインの実行

git tag v1.0.0
git push origin v1.0.0

ステップ4:プロジェクトでの使用

include:
  - project: "my-org/terraform-images"
    file: "/templates/Terraform.gitlab-ci.yml"

default:
  image:
    name: ${CI_REGISTRY}/my-org/terraform-images/releases/1.9.0:v1.0.0

variables:
  TF_ROOT: ${CI_PROJECT_DIR}/terraform
  TF_STATE_NAME: production

6.4 gitlab-terraformスクリプトの機能

gitlab-terraformは、terraformバイナリのラッパーであり、以下を自動化します。

  • GitLab HTTPバックエンドの設定
  • CI/CD環境変数のTF_VARへの変換
  • プランファイルの標準化された管理

6.4.1 自動公開されるCI/CD変数

以下の変数がTF_VAR_プレフィックス付きで自動的に利用可能になります。

GitLab変数 Terraform変数 説明
CI_JOB_ID TF_VAR_CI_JOB_ID ジョブID
CI_COMMIT_SHA TF_VAR_CI_COMMIT_SHA コミットSHA
CI_JOB_STAGE TF_VAR_CI_JOB_STAGE ステージ名
CI_PROJECT_ID TF_VAR_CI_PROJECT_ID プロジェクトID
CI_PROJECT_NAME TF_VAR_CI_PROJECT_NAME プロジェクト名
CI_PROJECT_NAMESPACE TF_VAR_CI_PROJECT_NAMESPACE 名前空間
CI_PROJECT_PATH TF_VAR_CI_PROJECT_PATH プロジェクトパス
CI_PROJECT_URL TF_VAR_CI_PROJECT_URL プロジェクトURL

6.4.2 Terraformでの使用例

variable "CI_PROJECT_NAME" {
  type        = string
  description = "GitLabプロジェクト名(CI/CDから自動注入)"
}

variable "CI_COMMIT_SHA" {
  type        = string
  description = "コミットSHA(CI/CDから自動注入)"
}

resource "aws_s3_bucket" "terraform_state" {
  bucket = "${var.CI_PROJECT_NAME}-terraform-state"

  tags = {
    Project   = var.CI_PROJECT_NAME
    CommitSHA = var.CI_COMMIT_SHA
    ManagedBy = "Terraform"
  }
}

6.4.3 ロックファイルの取り扱い

.terraform.lock.hclをリポジトリにコミットする場合の推奨設定です。

variables:
  TF_INIT_FLAGS: "-lockfile=readonly"

plan:
  script:
    - gitlab-terraform init ${TF_INIT_FLAGS}
    - gitlab-terraform plan

理由-backend-configオプションを使用すると、設定がプランファイルにキャッシュされ、apply時に問題が発生する可能性があります。環境変数を使用することで、この問題を回避できます。

6.5 TerraformとOpenTofuの互換性

以下の機能は、TerraformとOpenTofuの両方で完全に互換性があります。

機能 Terraform OpenTofu 備考
GitLab管理ステート HTTPバックエンド使用
マージリクエスト統合 レポート形式は同一
モジュールレジストリ プロトコル互換
CI/CDコンポーネント - OpenTofu専用
gitlab-terraformスクリプト 両方で動作

7. 実践的なワークフロー

7.1 開発からデプロイまでの完全なフロー

7.2 環境別の管理戦略

7.2.1 ディレクトリ構造

terraform/
├── modules/
│   ├── vpc/
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   └── outputs.tf
│   └── rds/
│       ├── main.tf
│       ├── variables.tf
│       └── outputs.tf
├── environments/
│   ├── staging/
│   │   ├── main.tf
│   │   ├── backend.tf
│   │   ├── terraform.tfvars
│   │   └── .terraform.lock.hcl
│   └── production/
│       ├── main.tf
│       ├── backend.tf
│       ├── terraform.tfvars
│       └── .terraform.lock.hcl
└── .gitlab-ci.yml

7.2.2 環境別のCI/CD設定

include:
  - component: gitlab.com/components/opentofu/validate-plan-apply@1.0.0
    inputs:
      version: 1.0.0
      opentofu_version: 1.6.0
      root_dir: terraform/environments/staging
      state_name: staging
  - component: gitlab.com/components/opentofu/validate-plan-apply@1.0.0
    inputs:
      version: 1.0.0
      opentofu_version: 1.6.0
      root_dir: terraform/environments/production
      state_name: production

stages: [validate, build, deploy]

# Staging環境は自動デプロイ
staging_apply:
  extends: .apply
  variables:
    TF_ROOT: terraform/environments/staging
    TF_STATE_NAME: staging
  environment:
    name: staging
  only:
    - main

# Production環境は手動デプロイ
production_apply:
  extends: .apply
  variables:
    TF_ROOT: terraform/environments/production
    TF_STATE_NAME: production
  environment:
    name: production
  when: manual
  only:
    - main

7.3 ベストプラクティス

7.3.1 ステート管理

推奨事項

  1. 環境ごとに異なるステート名を使用
variables:
  TF_STATE_NAME: "${CI_ENVIRONMENT_NAME}"
  1. 定期的なステートバックアップ
backup_state:
  stage: backup
  script:
    - |
      for env in staging production; do
        glab opentofu state download ${env} > backup-${env}-$(date +%Y%m%d).tfstate
        # S3などにアップロード
      done
  only:
    - schedules
  1. ステートロックのタイムアウト設定
terraform {
  backend "http" {
    retry_wait_min = 5
    retry_wait_max = 30
  }
}

7.3.2 セキュリティ

推奨事項

  1. 機密情報の外部化
# 環境変数から取得
variable "db_password" {
  type      = string
  sensitive = true
}

# GitLab CI/CD変数で設定
# TF_VAR_db_password = "secret_password"
  1. プランファイルのアクセス制御
artifacts:
  access: developer
  expire_in: 1 week  # 保持期間を制限
  1. SAST(Static Application Security Testing)の有効化
include:
  - template: Security/SAST.gitlab-ci.yml

kics-iac-sast:
  variables:
    SAST_EXCLUDED_PATHS: "spec, test, tests, tmp"

7.3.3 モジュール管理

推奨事項

  1. セマンティックバージョニングの厳守
# バグ修正
git tag v1.0.1

# 新機能(後方互換)
git tag v1.1.0

# 破壊的変更
git tag v2.0.0
  1. モジュールのバージョン固定
module "vpc" {
  source  = "gitlab.com/my-org/terraform-aws-vpc/aws"
  version = "1.2.3"  # 完全一致
}

module "subnet" {
  source  = "gitlab.com/my-org/terraform-aws-subnet/aws"
  version = "~> 1.2"  # 1.2.x の最新
}
  1. CHANGELOG.mdの維持
# Changelog

## [1.2.3] - 2024-01-15
### Fixed
- サブネットのタグ設定バグを修正

## [1.2.0] - 2024-01-10
### Added
- IPv6サポートを追加

## [1.1.0] - 2024-01-05
### Added
- VPCフローログ機能を追加

7.3.4 CI/CD

推奨事項

  1. 環境変数の適切な管理
variables:
  TF_INIT_FLAGS: "-lockfile=readonly"
  TF_CLI_ARGS_plan: "-parallelism=10"
  TF_CLI_ARGS_apply: "-parallelism=10"
  1. 段階的なロールアウト
production_apply:
  stage: deploy
  script:
    - gitlab-tofu apply -auto-approve
  environment:
    name: production
    deployment_tier: production
  when: manual
  needs:
    - staging_apply  # Stagingの成功を前提
  1. 失敗時の通知
.notify_on_failure:
  after_script:
    - |
      if [ "$CI_JOB_STATUS" == "failed" ]; then
        curl -X POST $SLACK_WEBHOOK_URL \
          -H 'Content-Type: application/json' \
          -d "{\"text\":\"Terraform apply failed in ${CI_ENVIRONMENT_NAME}\"}"
      fi

7.4 トラブルシューティング

7.4.1 ステートロックの解除

問題:パイプラインが異常終了し、ステートがロックされたまま

解決方法

# UIから解除
# Operate > Terraform states > Actions > Unlock

# CLIから解除
glab opentofu state unlock production

# 強制解除(最終手段)
curl --request DELETE --header "PRIVATE-TOKEN: <token>" \
  "https://gitlab.com/api/v4/projects/<project-id>/terraform/state/production/lock"

7.4.2 プランとアプライの不一致

問題Can't lock Terraform state files in CI jobs

原因-backend-configオプションの使用によるキャッシュ問題

解決方法:環境変数を使用

# 悪い例
script:
  - terraform init -backend-config="address=$TF_ADDRESS"

# 良い例
variables:
  TF_ADDRESS: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/production"
script:
  - gitlab-terraform init

7.4.3 モジュールの認証エラー

問題Error: Failed to download module

解決方法

# 環境変数の確認
echo $TF_TOKEN_gitlab_com

# 再設定
export TF_TOKEN_gitlab_com='glpat-xxxxxxxxxxxxxxxxxxxx'

# または ~/.terraformrc の確認
cat ~/.terraformrc

8. まとめ

GitLabのTerraform/OpenTofu統合は、以下の価値を提供します。

8.1 主要な利点

  1. 統合されたワークフロー

    • コード、ステート、レビュープロセスが単一プラットフォームに集約
    • 追加のインフラ設定が不要
  2. セキュアな管理

    • ステートファイルの自動暗号化
    • GitLab権限モデルとの統合
    • バージョン管理による変更追跡
  3. チームコラボレーション

    • マージリクエストでのインフラ変更可視化
    • レビュープロセスの標準化
    • 変更履歴の一元管理
  4. モジュール再利用

    • プライベートレジストリによる組織内共有
    • セマンティックバージョニングのサポート
    • CI/CDによる自動テストとセキュリティスキャン
  5. 柔軟な選択肢

    • TerraformとOpenTofuの両方をサポート
    • セルフホスティングによる完全なコントロール
    • 段階的な移行パス

8.2 導入ロードマップ

フェーズ1:基本的なステート管理(1-2週間)

  • GitLab管理ステートへの移行
  • CI/CDパイプラインの基本設定
  • チームメンバーへのトレーニング

フェーズ2:マージリクエスト統合(1週間)

  • Terraformレポートの有効化
  • レビュープロセスの確立
  • セキュリティ対策の実装

フェーズ3:モジュール化(2-4週間)

  • 共通パターンのモジュール化
  • モジュールレジストリの構築
  • ドキュメント整備

フェーズ4:最適化(継続的)

  • パイプラインの最適化
  • セキュリティスキャンの強化
  • ベストプラクティスの確立

8.3 今後の展望

HashiCorpのライセンス変更により、Terraformの配布方法は変化しましたが、GitLabは以下を通じて継続的なサポートを提供します。

  • OpenTofuへの完全な移行サポート
  • Terraform Imagesプロジェクトによるセルフホスティング
  • コミュニティベースのサポート体制

GitLabのIaC機能を活用することで、インフラストラクチャ管理の効率化、品質向上、そしてチーム全体の生産性向上を実現できます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?