Atlantis とは
Atlantisをご存じでしょうか。
簡単に言うと
GitHubやGitLabなどでterraform を管理する際、自動で terraform plan 結果を表示してくれたり、 リポジトリ内で terraform apply まで行ってくれるツールで、terraform 作業をgit repositoryで完結させれるようになるツールです。
ただ、何も考えずに利用すると、 リポジトリのtopで terraform plan などと実行するため、ディレクトリに分割して管理していると辛い面があります。
そこで他の CIツールのように .atlantis.yaml
というファイルを置いておくと、動作をある程度指定できるようになります。
version: 3 automerge: true projects: - name: my-project-name dir: . workspace: default terraform_version: v0.11.0 autoplan: when_modified: ["*.tf", "../modules/**.tf"] enabled: true apply_requirements: [mergeable, approved] workflow: myworkflow workflows: myworkflow: plan: steps: - run: my-custom-command arg1 arg2 - init - plan: extra_args: ["-lock", "false"] - run: my-custom-command arg1 arg2 apply: steps: - run: echo hi - apply
こちらがそのyamlのサンプルです。 公式のドキュメントから持ってきました。
分割統治する
atlantisでは、terraform plan/apply する対象を projectという単位で管理します。
上記サンプルでは、ルートディレクトリを起点とする、1つのプロジェクトしか記載がありませんが、リポジトリのトップをルートとして、任意のディレクトリをプロジェクトの起点として設定できます。
たとえば
version: 3 projects: - dir: service-A/ - dir: service-B/
などです。
projectで必須なのはディレクトリ指定だけなので、最小の設定が上記のようなものになります。
プロジェクトが定義されていると、そのプロジェクトの起点ディレクトリより下にあるファイルが更新されると、更新されたプロジェクトのみが CI/CDの対象となります。
これにより、モノレポであっても、更新が必要な部分のみを対象として CI/CDが回せるようになります。とても便利です。
moduleを扱う
ただ、terraform には、共通部分を切り出すためにモジュールという機能があります。このモジュールは複数のprojectで共有されるものなので、モジュールが更新されたら、モジュールを利用しているプロジェクトはCI/CDの対象としたいところです。
そのための機能として、 autoplan
という設定があります
たとえば
version: 3 projects: - dir: service-A/ autoplan: when_modified: ["../modules/**/*.tf", "*.tf*"] - dir: service-B/
などです。
autoplan
の when_modified
に、moduleの場所をそのプロジェクトのトップからの相対パスで指定しておくと、モジュールファイルが変更された際に、CI/CDの対象とすることができるようになります
任意の処理をはさむ
また、プロジェクトには当然、そこで利用するvarファイルやprovider.tfなどの設定が必要になりますが、これをいちいちプロジェクトごとに管理したくない、共通のものを利用したい、など、terraform plan/apply を独自に設定したいという場合もあります。
そのための機能として、 custom workflow があります
workflows: myworkflow: plan: steps: - run: terraform init -input=false -no-color # If you're using workspaces you need to select the workspace using the # $WORKSPACE environment variable. - run: terraform workspace select -no-color $WORKSPACE # You MUST output the plan using -out $PLANFILE because Atlantis expects # plans to be in a specific location. - run: terraform plan -input=false -refresh -no-color -out $PLANFILE apply: steps: # Again, you must use the $PLANFILE environment variable. - run: terraform apply -no-color $PLANFILE
公式ドキュメントにあるサンプルはこのようなものです。
plan
apply
共に、steps に、行いたい処理をリストで書いていけます。 provider.tf をコピーしたりなど、行いたい作業を記載することができます。
私の会社では、 terraform apply の結果をslackに通知するなどのことも行っており、このcustom workflowを利用しています。
さらに便利にしたい
この atlantis.yaml
ですが、管理が面倒そうだなという印象を受けるかと思います。なぜなら、プロジェクトが増えるたびに、依存するモジュールが増えるたびに、書き換える必要があるからです。
とてもではありませんが、それらをきちんと、手動で管理するのは無理です。
そこで、atlantis.yaml
を自動生成するツールを作成して利用しています。
+-module-+-module1 | +-module2 | +-projects-+-projectA +-projectB
このように、モジュールを置くディレクトリをプロジェクトを置くディレクトリを分割し、ツールにはprojectsディレクトリを走査するようにして、 各projectのtfファイルを読んで、依存するモジュールリストを作成する。
ということを行っています。 モジュールがモジュールに依存するようなケースについてはいったんあきらめることでツール自体は簡素化しています。
リポジトリにあらたなプロジェクトを追加する際や、モジュールを新たに利用する際には、リポジトリにpushする前にツールを用いてatlantis.yaml
ファイルを更新する。
という方法で今のところは運用を行っています。 gitのhookでpush前に自動実行したりすると良いのでしょうが、今のところ、そこまで追加や削除が多くないので、pushした際に 再生成するのを忘れたことに気づいて再生成してpushするなどで運用は回っています。
おわりに
便利なAtlantisですが、実運用にのせてますという話があんまり多くなさそうだったのでこうして筆をとりました。
terraform plan/apply までがリポジトリのCI/CDで完結するのは、とても便利ですし、監査的にも良いのでかなりお勧めです。
plan結果がそのままpull requestに表示されるので、手動でplan結果を記載する手間もなくなり、ファイルの変更箇所と実際のインフラの変化がすぐにチェックできてとても良いです。
実運用に十分耐えられるのでぜひ使ってみてはいかがでしょうか。