TerraformとGitLabのインテグレーションに関するトラブルシューティング

TerraformとGitLabのインテグレーションを使っていると、トラブルシューティングが必要なイシューに遭遇することがあります。

gitlab_group_share_group サブグループの状態が更新されたときにリソースが検出されない

GitLab Terraformプロバイダは、“User with permissions cannot retrieveshare_with_groups from the API” というイシューのために、既存のgitlab_group_share_group リソースの検出に失敗することがあります。この結果、Terraformが既存のリソースを再作成しようとするため、terraform apply を実行するとエラーになります。

例えば、以下のようなグループ/サブグループの設定を考えてみましょう:

parent-group
├── subgroup-A
└── subgroup-B

どこに:

  • ユーザーuser-1parent-groupsubgroup-Asubgroup-B を作成します。
  • subgroup-Asubgroup-B と共有されます。
  • ユーザーterraform-userparent-group のメンバーで、両方のサブグループへのアクセス権はowner に継承されます。

Terraform の状態がリフレッシュされると、プロバイダが発行した API クエリGET /groups/:subgroup-A_idshared_with_groups 配列内のsubgroup-B の詳細を返しません。これはエラーにつながります。

このイシューを回避するには、以下のいずれかの条件を適用してください:

  1. terraform-user がすべてのサブグループリソースを作成します。
  2. subgroup-Bterraform-user ユーザーにメンテナーまたはオーナーのロールを付与します。
  3. terraform-user は、少なくとも1つのプロジェクトへのアクセスを継承subgroup-B し、 subgroup-Bプロジェクトを含んでいます。

ベーステンプレート使用時に無効なCI/CD構文エラー

Terraformテンプレートを使用する際にCI/CD構文エラーが発生することがあります:

  • GitLab 14.2 以降では、latest テンプレートを使用します。
  • GitLab 15.0以降では、どのバージョンのテンプレートでも使用できます。

使用例:

include:
  # On 14.2 and later, when using either of the following:
  - template: Terraform/Base.latest.gitlab-ci.yml
  - template: Terraform.latest.gitlab-ci.yml
  # On 15.0 and later, the following templates have also been updated:
  - template: Terraform/Base.gitlab-ci.yml
  - template: Terraform.gitlab-ci.yml

my-terraform-job:
  extends: .apply

エラーの原因は3つあります:

  • の場合、.initinitステージとジョブがテンプレートから削除さ .initれた.initためにエラーが発生 .initします。.init構文エラーを解決するには、.NET Frameworkを拡張するジョブを安全に削除して .initください。
  • 他のすべてのジョブの場合、失敗の原因は基本ジョブの名前が変更されたことです:すべてのジョブ名に.terraform: という接頭辞が追加されています。例えば、.apply.terraform:apply になりました。このエラーを修正するには、基本ジョブ名を更新してください。例えば

       my-terraform-job:
     -   extends: .apply
     +   extends: .terraform:apply
    
  • GitLab 15.0 では、テンプレートはonly/exceptの代わりにrules の構文を使用します。.gitlab-ci.yml ファイルの構文が両方を含んでいないことを確認してください。

古いバージョンのテンプレートを使う

メジャーリリースの際には、変更が加えられることがあります。変更に遭遇したり、古いバージョンのテンプレートを使用したい場合は、.gitlab-ci.yml を更新して古いテンプレートを参照することができます。例えば

include:
  remote: https://gitlab.com/gitlab-org/configure/template-archive/-/raw/main/14-10/Terraform.gitlab-ci.yml

template-archiveを見て、利用可能なテンプレートを確認してください。

Terraform状態のトラブルシューティング

terraform apply の CI ジョブで、以前のジョブで作成されたプランを使用して Terraform の状態ファイルをロックできません。

-backend-config=terraform init に渡すと、Terraform はこれらの値をプランキャッシュファイル内部に永続化します。これにはpassword の値も含まれます。

その結果、プランを作成し、後で別の CI ジョブで同じプランを使用する場合、-backend-config=password=$CI_JOB_TOKEN を使用すると、Error: Error acquiring the state lock エラーが発生する可能性があります。これは、$CI_JOB_TOKEN の値が現在のジョブの間だけ有効であるために起こります。

回避策として、CIジョブでhttpバックエンド設定変数を使います。これは、GitLab CIを使い始めるの説明に従っているときに裏で起こっていることです。

エラー:”address”: 必須フィールドが設定されていません。

デフォルトでは、TF_ADDRESS${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/${TF_STATE_NAME} を設定しています。ジョブでTF_STATE_NAME またはTF_ADDRESS を設定していない場合、エラーメッセージError: "address": required field is not set が表示されてジョブが失敗します。

これを解決するには、エラーを返したジョブでTF_ADDRESS またはTF_STATE_NAME のいずれかにアクセスできるようにしてください:

  1. ジョブのCI/CD環境スコープを設定してください。
  2. 前のステップで設定した環境スコープに合わせて、ジョブの環境を設定します。

状態の更新エラー:HTTPリモート状態のエンドポイントは認証が必要です

これを解決するには

  • 使用するアクセストークンのスコープがapi
  • TF_HTTP_PASSWORD CI/CD変数を設定した場合は、以下のいずれかを確認してください:
    • と同じ値を設定してください。TF_PASSWORD
    • CI/CD ジョブで明示的に使用しない場合はTF_HTTP_PASSWORD 変数を削除してください。

開発者ロールが破壊的コマンドにアクセスできるようにします。

Developerロールを持つユーザーに破壊的コマンドの実行を許可するには、回避策が必要です:

  1. apiプロジェクトアクセストークンを作成してください。
  2. CI/CD 変数にTF_USERNAMETF_PASSWORD を追加します:
    1. TF_USERNAME の値をプロジェクトのアクセストークンのユーザー名に設定します。
    2. TF_PASSWORD の値をプロジェクトのアクセストークンのパスワードに設定します。
    3. オプション。保護されたブランチまたは保護されたタグで実行されるパイプラインでのみ使用できるように、変数を保護します。

状態名にピリオドが含まれる場合、状態が見つかりません。

GitLab 15.6以前では、ステート名にピリオドが含まれている場合にTerraformがステートをロックしようとすると404エラーを返していました。

Terraformコマンドに-lock=false 。GitLabバックエンドはリクエストを受け入れましたが、内部でピリオドとそれに続く文字をステート名から取り除きました。例えば、foo.bar という名前のステートはfoo という名前で保存されます。しかし、この回避策は推奨されておらず、ステート名の衝突を引き起こす可能性もあります。

GitLab 15.7以降では、ピリオドを含むステート名がサポートされています。-lock=false の回避策を使い、GitLab 15.7 以降にアップグレードすると、ジョブが失敗する可能性があります。この失敗は、GitLabバックエンドが既存のステート名と異なる完全なステート名で新しいステートを保存することが原因です。

失敗するジョブを修正するには、ピリオドとそれに続く文字を除いたステート名に変更してください。例えば、Terraformテンプレートを使用する場合:

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

variables:
  TF_STATE_NAME: foo

TF_HTTP_ADDRESSTF_HTTP_LOCK_ADDRESSTF_HTTP_UNLOCK_ADDRESS が設定されている場合は、状態名を更新してください。

あるいは、Terraformの状態をマイグレーションすることもできます。