25
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

DNSimpleをTerraform+GitHub+CircleCIで管理する

Last updated at Posted at 2015-05-20

処理の流れとしては次のような感じ。

  • GitHubにpushされるとCircleCI上でterraform planが走る
  • そのPRがmasterにマージされるとterraform applyが走る

Terraformのテンプレート

まずはdnsimpleプロバイダについて記述する。

dnsimple.tf
variable "dnsimple_email" {} # 環境変数TF_VAR_dnsimple_email
variable "dnsimple_token" {} # 環境変数TF_VAR_dnsimple_token

provider "dnsimple" {
  token = "${var.dnsimple_token}"
  email = "${var.dnsimple_email}"
}

DNSimpleに接続する際のtokenとemailをTerraformに渡す必要があるのだけれど、それらはリポジトリに載せたくないので環境変数として渡すようにしておく。その際環境変数には接頭辞TF_VAR_が必要で、例えば環境変数TF_VAR_foo$var.fooとして参照する。

続けてwww.example.comに対してexample.herokuapp.comへのALIASレコードを設定する場合は次のように記述する。

dnsimple.tf
resource "dnsimple_record" "example-com" {
  domain  = "example.com"           # 設定する対象のドメイン
  name    = "www"                   # サブドメイン部分。ルートドメインなら空文字を渡す
  value   = "example.herokuapp.com" # ALIAS先。AレコードならIPアドレス、CNAMEなら転送先を渡す
  type    = "ALIAS"                 # レコードのタイプ
}

dnsimple_recordリソースにはほかにもTTLのオプションなどがある。設定値についてはDNSimpleのレコード作成のAPIも参考になる。

DNSimpleへの反映

先のテンプレートファイルのあるディレクトリでterraform applyコマンドを実行する。

$ terraform apply

tfstateをAWS S3に保存する

terraform applyでリソースへ変更を行うと、最新の状態を記録したterraform.tfstateというファイルが作成・更新される。詳しくはドキュメントに任せるとして、このファイルがCircleCI上で毎回作成されては破棄されるようだといざ手元で作業したときに困りそう。ということでS3に記録するようにする。1

たとえばs3://example-terraform-state/terraform.tfstateとして保存する場合、まず下準備として次のことを行う。

  1. S3で example-terraform-state バケットを作る
  2. そのバケットにファイルを書き込める権限(S3FullAccessとか)を持ったIAMユーザを作成する
  3. 鍵情報とバケットのリージョン情報として、次の3つの環境変数を設定する
    • AWS_ACCESS_KEY_ID
    • AWS_SECRET_ACCESS_KEY
    • AWS_DEFAULT_REGION

それが終わったらterraform remote config2で保存先を設定する。

$ terraform remote config \
  -backend=S3 \
  -backend-config="bucket=example-terraform-state" \
  -backend-config="key=terraform.tfstate"

そして反映の前後で、S3から取得(pull)、更新(push)を行う。

$ terraform remote pull
$ terraform apply # もしくはplan
$ terraform remote push

ちなみにterraform remote configすると、それまでカレントディレクトリにできていたterraform.tfstateterraform.tfstate.backupが、.terraformというディレクトリに作られるようになる。このディレクトリの中身はS3に上がるものと同じなので.gitignoreに追加しても問題ないと思う。

circle.yml

内容としては次のことが行われるようにする。

  • Terraformをダウンロードしてきて~/.terraformに展開、パスを通す
  • ~/.terraformをキャッシュする
  • testで
    • terraform remote config
    • terraform remote pull
    • terraform plan
    • terraform remote push
  • masterブランチにマージされたら
    • terraform remote config
    • terraform remote pull
    • terraform apply
    • terraform remote push
circle.yml
machine:
  environment:
    PATH: $HOME/.terraform:$PATH
    TERRAFORM_VERSION: 0.5.1
dependencies:
  cache_directories:
    - ~/.terraform
  pre:
    - |
      mkdir -p $HOME/.terraform
      if [ -z "$(ls -A $HOME/.terraform)" ]; then
        cd $HOME/.terraform
        curl -LO https://dl.bintray.com/mitchellh/terraform/terraform_${TERRAFORM_VERSION}_linux_amd64.zip
        unzip terraform_${TERRAFORM_VERSION}_linux_amd64.zip
        rm terraform_${TERRAFORM_VERSION}_linux_amd64.zip
      fi
test:
  pre:
    - |
      terraform remote config -backend=S3 -backend-config="bucket=example-terraform-state" -backend-config="key=terraform.tfstate"
      terraform remote pull
  override:
    - |
      terraform plan
  post:
    - |
      terraform remote push
deployment:
  production:
    branch: master
    commands:
      - |
        terraform remote config -backend=S3 -backend-config="bucket=example-terraform-state" -backend-config="key=terraform.tfstate"
        terraform remote pull
        terraform apply
        terraform remote push

ちなみに、circle.ymlに処理を記述するだけだといざ手元で実行しようとしたときに不便なので、実際にはrakeタスクとして定義し、それを呼び出すようにしている。

CircleCIでの設定

GitHubとCircleCIを連携する。

またこれまでに出てきた次の5つの環境変数をCircleCIのプロジェクトごとの画面から設定する。

変数名 概要
TF_VAR_dnsimple_email DNSimpleに登録してるemail
TF_VAR_dnsimple_token DNSimpleのAPI Token
AWS_ACCESS_KEY_ID AWS IAMで発行したユーザのAccess Key ID
AWS_SECRET_ACCESS_KEY AWS IAMで発行したユーザのSecret Access Key
AWS_DEFAULT_REGION AWSで作ったS3のバケットのリージョン。Tokyoだとap-northeast-1

所感

  • Terraformで管理する前にすでに同じレコードが登録されている場合、applyで上書きできずに失敗する。遊びで使っているドメインなら削除してからapplyして作りなおせばいいけど、業務で使っているような場合には厳しい。
    • ちなみに今回の場合はtfファイルで一度でも記述したドメインのみが管理対象になるのに対し、Roadworkerの場合はドメイン(Hosted Zone)以下全てが管理対象になる。
  • テストとしてterraform planが走るだけだと、実際の記述が正しいかどうかはわからない。ただtfファイルの記述の時点で処理が入り乱れるようなものでもないし、あくまでも誰か人間がterraform applyしなきゃいけないっていう手間を省くものとしてはアリな気がしている。

参考

  1. Terraform v0.5.0以上が必要

  2. https://www.terraform.io/docs/commands/remote.html

25
23
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
25
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?