この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
先に結論から
.gitlab-ci.yml
内の以下のような重複処理は
validate-dev:
stage: terraform-static-test
script:
- cd env/dev
- terraform init -backend=false
- terraform validate
validate-stg:
stage: terraform-static-test
script:
- cd env/stg
- terraform init -backend=false
- terraform validate
validate-prod:
stage: terraform-static-test
script:
- cd env/prod
- terraform init -backend=false
- terraform validate
以下のようにスッキリさせることができます。
.validate:
stage: terraform-static-test
script:
- cd env/${ENV}
- terraform init -backend=false
- terraform validate
validate-dev:
extends: .validate
variables:
ENV: dev
validate-stg:
extends: .validate
variables:
ENV: stg
validate-prod:
extends: .validate
variables:
ENV: prod
このエントリで言いたいことはこれだけです。もう少し詳しく知りたい方は続けてお読みください。
課題: 重複処理がたくさん
GitLabを使ってTerraformのコードを管理しているプロジェクトがありました。このTerraformのコードは複数環境に対応するため以下のようなディレクトリ構成になっています。よくあるディレクトリ構成かと思います。
.
├── env
│ ├── dev
│ │ ├── main.tf
│ │ .
│ │ .
│ ├── prod
│ │ ├── main.tf
│ │ .
│ │ .
│ └── stg
│ ├── main.tf
│ .
│ .
└── modules
├── hoge
├── fuga
└── foo
terraform plan
などのterraformの各種コマンドは env/dev
や env/stg
といった各環境に対応したディレクトリにて実行します。具体的なコードはmodules
以下にあり、各環境からmoduleを呼び出す際の引数値を変えることで環境ごとの差分に対応します。(devだけIP制限をかける、リソースのスペックを下げるなど)
このプロジェクトにおいて、GitLab Runnerを用いて、Terraformのコードの継続的なチェックを行なっています。具体的には以下です。
- terraform fmt
- terraform validate
- tfsec
- TFLint
terraform fmt
以外はTerraformのルートディレクトリ(=root moduleがある、つまりterraformの各種コマンドを実行するディレクトリ)にて実行する必要があります。そのため環境分だけジョブを作成する必要がありました。例えばterraform validate
の部分はこんな感じでした。
.gitlab-ci.ymlの一部
validate-dev:
stage: terraform-static-test
script:
- cd env/dev
- terraform init -backend=false
- terraform validate
validate-stg:
stage: terraform-static-test
script:
- cd env/stg
- terraform init -backend=false
- terraform validate
validate-prod:
stage: terraform-static-test
script:
- cd env/prod
- terraform init -backend=false
- terraform validate
どう見てもイマイチです。こんな感じのがtfsecとTFLintの分もあります。
解決: extendsを使う
.gitlab-ci.yml
のextends
というパラメーターを使うとこの重複処理をまとめることがわかったので採用しました。以下のように書きます。
.validate:
stage: terraform-static-test
script:
- cd env/${ENV}
- terraform init -backend=false
- terraform validate
validate-dev:
extends: .validate
variables:
ENV: dev
validate-stg:
extends: .validate
variables:
ENV: stg
validate-prod:
extends: .validate
variables:
ENV: prod
- まずベースとなる
.validate
ジョブを定義します。
先頭がドット(.
)から始まるジョブは hide jobと呼ばれるジョブになり、無効化されそのジョブ自体は処理されなくなります。が、今回のように他のジョブのベースとすることができます。 (ベースとなるジョブは必ずしもhide jobである必要はなく、通常のジョブでもOKです。) .validate
ジョブでは、環境ごとに異なる部分を環境変数化しておきます。- 次に環境ごとのジョブをそれぞれ定義します。
extends
パラメーターを使い先程の.validate
ジョブを指定します。あとは環境ごとに異なるところ=環境変数の値を定義するだけです。