🥳

AtlantisでTerraformの実行を自動化しよう!

2021/12/12に公開

はじめに

こんにちは!Hamee株式会社の tatsuo48 です。
Terraformの自動化ツールであるAtlantisについて書きます。

主に以下の事項について書きます。

  • Atlantisとは何か?
  • 基本的な使い方、運用TIPS

逆に以下については触れません

  • Atlantisの内部仕様
  • Atlantisの構築方法

Atlantisとは何か?

AtlantisとはTerraformの操作(planapply)をPRのコメントベースで実行可能にしてくれるツールです。

公式のTOP画像がわかりやすいのでそれを見ながら説明します。
https://www.runatlantis.io/

PRを作成


Terrformのリソースを変更するようなPRを作成!

terraform planを自動実行


webhookなどを使ってPRが作成されたことを検知したAtlantisは、リポジトリをgit cloneしてterraform planを実行!
実行結果をPRにコメントとして返してくれます。

terraform applyを実行

実行結果を確認して問題がなければ、atlantis applyとコメントします。
またまた、このコメントをwebhookなどで検知したAtlantisは、今度はterraform applyを実行します。
そして、実行結果をこれまたPRにコメントとして返してくれます。
問題なければPRをマージして変更完了です🙌

GitHubActionやCircleCIでもできそうだけど?

はい!GitHubActionsでもterraform planterrform applyの自動化はできます。
以下のようなGitHubActionsや
https://github.com/marketplace/actions/hashicorp-setup-terraform

terraform plan結果通知のためのツールもあります
https://github.com/mercari/tfnotify

こういったツールを組みあわせて自動化した場合と比較してAtlantisには以下のようなメリットがあります。[2]

PR単位でのロック機構

AtlantisにはPR単位でロックする機能があります。
https://www.runatlantis.io/docs/locking.html

これにより複数人が同時並行でPRを作成した場合でも1つずつ順番に適用することが可能です。
Terraform自体にもロック機構はありますが、これはTerraformが並列実行されるのを避けるためにtfstateのロックを取るものです。よって、複数人が同時並行でPRを作成している場合、terraform planterraform applyのタイミングが異なれば、他のPRによる変更に気付かず、意図せずその変更を打ち消してしまう可能性があります。
Atlantisを使うと「他のPRがロックを持っているのでterraform planの自動実行ができなかったよ〜」とコメントで教えてくれるので気づくことができます。

コメントによるterraform apply

AtlantisではPRのコメントベースでterraformのCLI操作します。
実際にTerraformを触ったことがある方ならわかると思いますが、AWSのリソース作成などでterraform applyが一発で決まることってどのくらいあるでしょうか?
リソース名に使える文字種の制限文字数制限などに引っかかり、terraform applyに失敗することも多いのではないでしょうか?
GitHubActionsなどで自動化するとPRのマージトリガーでterraform applyしていることも多いと思います。その場合、terraform applyに失敗したら修正PRを出す必要がありました。
Atlantisを使うことで単一のPR上で試行錯誤しながら、上述のロック機構もあることで安全に何度もterraform applyすることが可能になります。

インフラリソースの操作権限をCIサービスに渡さずに済む

GitHubActionsなどを使って、AWSなどのインフラリソースをTerraformで作成する場合、比較的強めの権限を持ったIAMクレデンシャルをCIサービスに渡すことになるかと思います。
最小権限にするにしても、事前にどのAWSサービスを作成するかすべてを網羅することは難しいです。また、たとえそれができたとしても、新しいサービスを利用することになるたびに権限の調整をしていくことも手間です。
ということで比較的ガバっと強めの権限(IAM作れたり)を渡しがちです。
AtlantisのインフラをAWS内に作れば、IAMロールを使って権限を渡すことができます。こうすると、IAMクレデンシャルがAWS内でしか使われないのでCIサービスに渡した場合と比較しても安心です。[3]

使い方

基本的には構築したらもうそのまま使えますが、リポジトリにatlantis.yamlという設定ファイルを置くことで挙動を変更することも可能です。
https://www.runatlantis.io/docs/repo-level-atlantis-yaml.html

以下で、いくつか便利な使い方を紹介します。

1つのレポジトリに何個もtfstateがあるとき

以下のようにプロジェクトを分けることで、それぞれ別個にAtlantisを利用することができます。

version: 3
projects:
  - name: ProjectA
    dir: terraform/ProjectA
  - name: ProjectB
    dir: platform/ProjectB

moduleに変更があったときも自動でterraform planしてほしい

1つのレポジトリの中にmoduleディレクトリを用意するケースもあると思います。

├── module
│   └── alb
│       └── main.tf
├── projectA
│   └── main.tf
└── projectB
    └── main.tf

そういった場合はwhen_modifiedに相対パスで以下のように指定することでmoduleディレクトリ配下に変更があったときにも自動プランが実行されるようになります。

version: 3
projects:
  - name: ProjectA
    dir: terraform/ProjectA
    autoplan:
      when_modified:
        [
          "*.tf",
          "*.tfvars",
          "../modules/*/*.tf",
        ]
      enabled: true
  - name: ProjectB
    dir: platform/ProjectB
    autoplan:
      when_modified:
        [
          "*.tf",
          "*.tfvars",
          "../modules/*/*.tf",
        ]
      enabled: true

terraform apply完了したらマージもよろしく

https://www.runatlantis.io/docs/automerging.html#how-to-enable
先程のに足すとこんな感じですね〜

version: 3
automerge: true
projects:
  - name: ProjectA
    dir: terraform/ProjectA
    autoplan:
      when_modified:
        [
          "*.tf",
          "*.tfvars",
          "../modules/*/*.tf",
        ]
      enabled: true
  - name: ProjectB
    dir: platform/ProjectB
    autoplan:
      when_modified:
        [
          "*.tf",
          "*.tfvars",
          "../modules/*/*.tf",
        ]
      enabled: true

まとめ

日本語記事はあんまりなくて日本だとあんまり流行って無さそうで悲しいです。
この記事が普及の一助になれば幸いです🙌

Hamee Advent Calendar 2021、13日目の明日はyamakonaさんの「「ふりかえりガイドブック」から得たいつかやりたいふりかえり手法」です!

脚注
  1. https://www.runatlantis.io/docs/access-credentials.html#github-app ↩︎

  2. Atlantisのメリットとなる部分は、頑張れば自前で作ることもできるとは思いますが、多分大変です。 ↩︎

  3. 最近はOIDCを使ったセキュアに権限を渡す仕組みもあるので、GitHubActionsに関しては以前よりも安全に権限を渡せるようにはなってきています。
    https://github.blog/changelog/2021-10-27-github-actions-secure-cloud-deployments-with-openid-connect/ ↩︎

Discussion