はじめに
Atlantis によるTerraform共同作業環境をサンプルで立ち上げるべくドキュメントを読みながら進めてみました。
Atlantis って?
Terraform Pull Request Automation
と書かれています。
実際に使った感覚としては、 Pull RequestベースでTerraformによる環境構築をする流れをGitHubに集約するための仕組みづくりをしてくれる子
という感じでしょうか。
詳しくは下に図示してみます。
Atlantisで何ができるの?
こんな感じのことができます。
- あるリポジトリをTerraformを操作するファイル群として構成しておく(つまりtfファイルとか)
- そのリポジトリに対してPull Requestが来た場合に、AtlantisがそれをWeb hook経由で検知して、
terraform plan
を投げる - その結果はPull Requstのコメントとして表示される
- 結果が問題なければ、自分なりレビュワーが、
terraform apply
決行のためのコメントをPull Requetに付与する - AtlantisがTerraform Applyをして、更に結果をPull Requstにコメントする
イメージを図にしたのが以下です。
すべてをPull Requestベースで可視化できる!というのがメリットのようです。
・・・と ここ に書いてます。
当然ですが、別に Enterprise Cloud
じゃなくて良いんですよもちろん。
Terraformが制御できるものなら何でも同じフローで制御できます。
前提
上記のような環境を作るまでの流れを実際にやってみたので記録として残します。
その上での前提となる内容をこちらに記載しておきます。
- GCPのインスタンス上にAtlantis環境を作る
- このインスタンス上にはTerraform自体も必要なので tfenv を使って構築した(解説の対象外)
- Atlantisドキュメント内のGit Hostとしては、
GitHub
を利用 - Terraform自体の制御をする
.tf
群等は、github.com/keiichi-hikita/terraform_work
リポジトリに格納(Private Repository) - このリポジトリへのPull Requestは自身の端末から実施
では、以下Atlantis環境を作っていくまでの流れです。
こちらの Installation Guide に従って進めていきます。
書かれていることを読みながら、自分がチェックしたことや、実際にした行動、コマンドの例みたいなことを書き連ねていきます。
(本記事の以降の見出しは、それぞれ上記ページの左側のメニューに対応しています)
Requirements
- Git Host的にはGitHub使うから問題なし
- local state以外は全部サポートしているということなので何かしらのremote stateにする
- 今回はTerraform Cloudなので問題なし
- リポジトリの構成については特にどんな形でも問題はないらしいのでOK
- workspaceもサポートしている。その場合
atlantis.yaml
に書く(のだがTerraform Cloudがworkspace固定になっちゃうので事実上あまり関係がない) -
.tfvars
ファイルは自動検出すると書いてあるが、-var-ile
引数経由もしくはatlantis.yaml
経由で明示できるように見える - Terraformのバージョンはすべてサポート(0.12含む)
だそうなので、特に問題になるような点はなさそうでした。
Git Host Access Credentials
- Create an Atlantis user(optional)・・・は無視
- Access Tokenを作る
- ここ にやり方が書いてあるが、
-
Settings / Developer Settings / Personal access tokenns からtokenを作る
- Noteに
atlantis token
とでも入れておき、repo
に対するフルアクセスを与えてGenerate token
をクリック - 生成後にtoken文字列をコピーしておく。じゃないと二度と表示されない
- Noteに
Webhook Secrets
- Atlantisからの接続を明確に判断するための識別子を自分で生成しておく
- こんなやり方でできるよ という例があるのでそれに従って作る
- 自分は
www.nrandom.org
使って作成
Deployment
Architecture Overview
Architectureについて書いてあった
- Runtime
- (自分の場合は)GitHubからのWebhookを受け取ってTerraformコマンドをローカルにて実行する役割
- OfficialなDockerイメージもある
- Routing
- AtlantisとGitHubの間で相互に通信が必要になる
- GitHub的ないわゆるパブリックサイトを使っている場合はAtlantis自体を外にさらさないとだめだと書いてある
- Data
- Atlantis自体は外部Database(おそらく外部データソース的な意味合いで書いてある)を持たない
- Atlantisは
Terraform plan files
をローカルに持つので、基本永続的なディスクを使えるようにしておくこと
Deployment
- Atlantis自体をどうやって自身の環境にデプロイするかという話
- この場所が外にさらされていないといけないことになる(GitHubからリーチ可能な場所)
- 自分はGCPの永久無料インスタンス内に、 tfenv を入れた上で、atlantis自体も普通に ここ からバイナリ(v0.8.2)を落としてパスの通るところにおいた
- 最終的に、GitHub相手の場合はAtlantisを以下のようにして立ち上げる
URL=http://[your host name or ip]:4141
USERNAME=keiichi-hikita
TOKEN=[取得したGitHub token]
SECRET=[作成したWebhook Secret]
REPO_WHITELIST="github.com/keiichi-hikita/terraform_work" # <-- tfとか入っているリポジトリ
atlantis server \
--atlantis-url="$URL" \
--gh-user="$USERNAME" \
--gh-token="$TOKEN" \
--gh-webhook-secret="$SECRET" \
--repo-whitelist="$REPO_WHITELIST"
ちなみに Terraform Cloud
を使うので、 Atlantis稼働サーバーの ~/.terraformrc
に以下のような記載が必要
credentials "app.terraform.io" {
token = "your token"
}
Configuring Webhooks
- webhookをorganizationもしくはリポジトリ単位でインストールできるということだが、自分のアカウントのみで完結させるのでリポジトリ単位になる
- つまり
If installing on a single repository, navigate to the repository home page and click Settings.
相当 - リポジトリの
Settins
に行く - 左メニューの
Webhooks
を選択し、Add webhook
をクリック -
Payload URL
に先程指定した$URL
+/events
を入力 -
Content type
をapplication/json
に変更 -
Secret
にWebhook用に作ったSecretをペースト -
Which events would you like to trigger this webhook?
の問いに対してLet me select individual events.
を選択 - 下図のように、4つを選択
- Pull request reviews
- Pushes
- Issue comments
- Pull requests
-
Active
チェックボックスのONはそのままにしておく -
Add webhook
ボタンをクリック
- つまり
ここまで終わるとAtlantisにリクエストが飛んできてます。以下のようなログが出てればOKです。
$ atlantis server \
> --atlantis-url="$URL" \
> --gh-user="$USERNAME" \
> --gh-token="$TOKEN" \
> --gh-webhook-secret="$SECRET" \
> --repo-whitelist="$REPO_WHITELIST"
2019/06/19 10:41:07+0900 [INFO] server: Atlantis started - listening on port 4141
2019/06/19 10:41:16+0900 [INFO] server: GET / – from 115.69.226.68:23101
2019/06/19 10:41:16+0900 [INFO] server: GET / – respond HTTP 200
2019/06/19 10:51:46+0900 [INFO] server: POST /events – from 140.82.115.69:28540
2019/06/19 10:51:46+0900 [INFO] server: POST /events – respond HTTP 200
Provider Credentials
- Atlantisはシンプルにサーバー上で
terraform plan
,terraform apply
を実行数r - そのためにはprovider用のクレデンシャルが必要になる
- 色々なやり方があるよと書かれているが、自分の場合は普通にAtlantisホスト上に定義しておいた
ではPull Requestを投げてみる
ここまで来ると環境設定は完了してますので、あとは前提にも書いた、github.com/keiichi-hikita/terraform_work
にPRを投げてみます。
リポジトリはこんな構成になっています。(超シンプル)
.
├── main.tf # <-- 現状空っぽ
├── provider.tf # <-- 認証情報
└── terraform.tf # <-- Remoteステートの設定 for Terraform Cloud
では、 main.tf
にキーペアでも足してみます。
resource "ecl_compute_keypair_v2" "keypair_1" {
name = "keypair_1"
}
空の状態から上記の状態にしたので、単純に 1つのリソースを追加した
というPRを投げることになります。
ブランチ名は add_keypair
にでもしておきます。
で、Pull RequestをOpenします。
ここまでは普通の流れです。
Pull RequestがOpenされると、自動的にAtlantis側で terraform plan
が実行され、その結果がコメントに反映されます。
今回はエラーになってしまいました。
Enterprise Cloud
のproviderバイナリを置き忘れていましたね。
こういうのも含めてDockerイメージ化しておけば良いんでしょうね多分。
さて、バイナリを ~/.terraform.d/plugins/linux_amd64/
配下に設置し、気を取り直して再チャレンジ。
今度はうまくいきました。
で、このplan結果をapplyしたいなら ”atlantis apply -d ." ってコメントしてね
と書かれているのでコメントしてみます。
おー、無事applyされました。
実際にリソースができたかどうかも見ておきます。
% ecl --os-cloud=jp4 compute keypair list
+-----------+-------------------------------------------------+
| Name | Fingerprint |
+-----------+-------------------------------------------------+
| keypair_1 | ab:ba:7f:a7:32:bf:8a:dc:53:e3:8f:02:45:a1:34:de |
+-----------+-------------------------------------------------+
問題なし!
この間、Atlantis側を見ていると、いろいろとログが流れています。
どうやらPull Requestの内容を取得する際に、 $HOME/.atlantis/repos/keiichi-hikita/terraform_work/2/default"
みたいな感じでリポジトリがCloneされているっぽいですねぇ。
Pull Requestとその際のTerraformの挙動を、一体的に管理できるのはわかりやすいですね。
Plan結果が表示されるのでレビューもしやすい。
stateをremote管理にして、tf
ファイル群をgit管理にして全員で最新版を共有していても、バラバラにApplyしちゃうとわからなくなってしまいますし(ま、そんなやり方しない気がしますが)、とはいえCI通してやるとなると情報がそこに集まっちゃいますしね。