1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GitHub ActionsからTerraform Planするお話

Posted at

この記事はIaC Meetup【Finatext × YUMEMI.grow】の登壇で発表した内容になります。

目次

  1. CIでPlanするメリット
  2. CIでPlanするための設定
  3. Plan実行の流れ

Planするメリット

  • 実行環境の再現性を向上させられる
  • インフラの一貫性維持とドリフト検知が
    できる
  • 依存関係のアップデートがしやすくなる

実行環境の再現性を向上させられる

たまにある問題: Aさんの環境ではPlanできるのに、Bさんの環境ではPlanできない

  • 認証の問題
  • 権限の問題
  • 環境の問題
  • variablesの設定値の問題
  • etc…

tf-auth-fail.png

上の図ではGitHubの認証エラーで弾かれている

Planするために必要な環境が明示されるようになる

  • CI上でPlanするために必要な準備を全て行う必要がある
  • そのためにはPlanするための認証、権限、環境をすべて用意し設定しているはず

実際に動く環境として、実行環境の明示がなされる。CIで設定している内容はPlanするために必須であり、個人の環境から実施する際にも必要になる。

インフラの一貫性維持とドリフト検知ができる

Terraformの内容と実際のリソースの状態が一致していることを確認する機会が増やせる

  • 一致していないとApplyで設定が巻き戻ってしまう可能性
    • 手動で変更していたのであれば必要な変更では?
  • この状態では新規に開発することが難しい

tf-plan-changes.png

スケジューラーが無効になっているがこれは有効にしてもOK? それとも無効のままがよい?
これを判断できないと迂闊にApplyできない
Terraform側を修正して現状維持するようにしてもいいが、間違ったインフラ変更だったという場合もある

依存関係のアップデートがしやすくなる

主な依存関係のProviderを更新させ続けられる

  • Providerの更新があった際に、対応が必要かそのまま適用できるか判断できる
    • PlanでNo changesであれば適用して問題ない場合が多い
    • Changeがあれば仕様が変わっている可能性がある
  • RenovateやDependabotで自動マージまで持っていくことも可能

tf-renovate-merge.png

renovate-approveを使用して依存関係の更新を完全自動化している。Providerの更新に対しplanで差分が検出されなければ自動でマージする設定になっている。

CIでPlanするための設定

  • 実行環境の設定
  • 認証の設定
  • 権限の設定

実行環境の設定

Terraform

  • hashicorp/setup-terraform のActionsでインストール可能
  • バージョンの指定はお好みで…
  • detailed-exitcodeのオプションとの相性が悪いようなのでterraform_wrapperは false
- uses: hashicorp/setup-terraform@v3
  with:
    terraform_wrapper: 'false'

AWS

  • aws-actions/configure-aws-credentials のActionを使用しOIDCによる認証を使用
  • Workflowにおけるpermissionsに、id-token: write を設定すること
  • mask-aws-account-id をtrueにするとアカウント番号を隠してくれる
- uses: aws-actions/configure-aws-credentials@v4
  with:
    aws-region: 'us-east-1'
    role-to-assume: ${{ secrets.AWS_TERRAFORM_PLANNER_ROLE }}
    role-session-name: 'TerraformCheck'
    mask-aws-account-id: true
    retry-max-attempts: 3

Google Cloud

  • google-github-actions/auth のActionを使用しOIDCによる認証を使用
  • Workflowにおけるpermissionsに、id-token: writeを設定すること
  • projectIdを隠したい場合はGitHub ActionsのSecretsに登録の上、 Workflowの中でSecretを参照する必要がある
  • Checkoutした直下に認証用のファイルを作成するので注意 ( gha-creds-40c829577b183395.json のようなファイル)
    • このファイルが漏れても直ちに影響があるわけではない
    • コミット指定なファイルが増えるのでgit diffなどで引っかかることがある
- uses: google-github-actions/auth@v2
  with:
    workload_identity_provider: ${{secrets.GOOGLE_CLOUD_IDENTITY_PROVIDER}}
    service_account: ${{secrets.GOOGLE_CLOUD_TERRAFORM_PLANNER_SERVICE_ACCOUNT}}

GitHub

  • actions/create-github-app-token のActionを使用しAppIdと秘密鍵でTokenを作成
  • RepositoryやOrganizationの設定をしたい際に使用する
    • ActionsのSecretやEnvironmentなど
  • Terraform側のProviderの設定でAppを使う設定にもできるが、instalation idが必要なので注意
- id: generate-token
  uses: actions/create-github-app-token@v2
  with:
    app-id: ${{ steps.get-secrets.outputs.app_id }} # from Secret Manager
    private-key: ${{ steps.get-secrets.outputs.pem }} # from Secret Manager
    owner: ${{ github.repository_owner }}

その他

  • サービスによって異なるが、API Keyなどを設定
    • APIKeyはActionsのSecretや、クラウドのSecret Managerなどから持ってくることになりそう
  • AWSに保存していれば、ephemeralblockで引っ張ってきて、Providerの設定に使用することもできる
    • GoogleCloudのSecret Managerはephemeralresourceの実装が現状ない
ephemeral "aws_ssm_parameter" "cloudflare_token" {
  arn = local.cloudflare_token_arn
}
provider "cloudflare" {
  api_token = ephemeral.aws_ssm_parameter.cloudflare_token.value
}

権限の設定

必要な権限

  • Stateファイルの読み込み/書き込みの権限
    • Applyするなら書き込みが必須。Planだけなら読み込みでOK
    • KMSで暗号化しているならその関連も必要
  • Lockに関する権限
    • Plan時にLockしない(-lock=false)なら不要
    • 書き込みの権限であることが多い
      • AWSならS3かDynamoDB
      • GoogleCloudならCloud Storage
  • Planするリソースに関する権限

Planするリソースに関する権限

(最小権限の原則を守れるのであればそれが一番)

  • マネージドな権限を設定するのが簡単+ アクセスさせたくないものはDenyするなど
    • AWSならReadOnlyAccessのポリシー
      • SSM Parameterの内容が読めるので注意
    • Google Cloudなら閲覧者のロール
    • どちらもSecret Managerの内容は読めない
  • 実際に使う際にはよく調査してから

aws_readonly_policy.png
google_cloud_viewer_role.png

Plan実行の流れ

  1. 認証の準備
  2. terraform init
  3. terraform plan

認証の準備

これまでで設定した認証を使用していく

auth.png

terraform init

init.png

これだけで1GB弱のProviderが設置されるので注意。AWS Providerが600MB以上を占める。Google CLoudやCloudflareは130MB未満くらい。

  • Providerをダウンロードしていく
    • 数百MBあるので、通信量には気を付ける
      • 特にSelf Hosted Runnerを使用している場合など
    • Providerをキャッシュするとダウンロード回数が減る
      • TF_PLUGIN_CACHE_DIR の指定で使用可能

init-cache.png

from shared cache directory

とあるのでキャッシュが使われている。

terraform plan

terraform plan -detailed-exitcode -lock=false
  • -detailed-exitcode で、差分がある場合に終了コードを2にしてくれる
  • ファイルに書き出す場合は-no-color もつけるのがおすすめ
    • privateやinternalのリポジトリでは不要だが、publicなリポジトリでやっている場合にはファイルに出力するなど簡単にはterraformの実行結果を見られないようにした方が安全
  • lockする設定だと、Renovateなどで一斉にProviderが更新された際に並列でplanされ、lockの取得に失敗する

plan.png

まとめ

CI組まないとRenovateやDependabotでオートマージさせられないのでPlanしよう。

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?