とよぶ

歌いながらコード書いてます

だれでも簡単terraform入門

リリース日は決まっているのに仕様は決まりません!
どうも、とよです。

以前所属していたプロジェクトでは自社DCで運用していたため、今まで全く触れてこなかったAWSですが、今のプロジェクトではAWSを使うので、terraformを使ってインフラを管理していこうと思っています。

このエントリでできること

  • terraformを使ってMacからAWSのインスタンスを立ち上げる
  • Macからterraformで作ったインスタンスにSSHする

環境

  • Mac OSX 10.9.5 Mavericks
  • Terraform v0.5.3

Terraformとは

Terraformは安全にかつ効率的にインフラを構築、変更、バージョニングできるツール。
かの有名なVagrantやPackerなどを擁するHashiCorp者のプロダクトで、Goで書かれてます。
インフラ管理がプログラマブルになるので、アプリエンジニアでもちょっと知識がつけば専属インフラエンジニアが不要になったり不要にならなかったりするでしょう。

なんかやたらとサイトがカッコイイ。
Terraform by HashiCorp

AWSインスタンスを立ち上げてみる

成果物は以下のリポジトリにおいてあります。

github.com

Terraformのインストール

Goなのでバイナリをダウンロードしてきて、PATHを通します。

www.terraform.io

今回は /usr/local/terraform 解凍したディレクトリをぶちこみます。

$ terraform --version
Terraform v0.5.3

勘所

次に、要となる設定ファイルを記述します。

設定ファイル名

terraformは*.tfのファイルをすべて読み込みますので、hoge.tfのように命名したファイルを作成します。

terraformを利用するIAMユーザーを作成

terraformでAWSにアクセスするためのユーザーが必要なので、AWSコンソールで作ります。
作成したユーザーにはAdministratorAccessのポリシーでもアタッチしておきましょう。

terraformで作成したユーザーにAmazonEC2FullAccessをつけておけばインスタンスの作成ができると思っていましたが、どうやらterraform利用ユーザーに強い権限つけないといけないみたいです(そのうち調べます)。

provider

Terraformは様々なインフラサービスのプロバイダをサポートしています。

www.terraform.io

ここではAWSを使うので、awsのproviderの設定を行います。

variable "access_key" {}
variable "secret_key" {}

provider "aws" {
  access_key = "${var.access_key}"
  secret_key = "${var.secret_key}"
  region = "ap-northeast-1"
}

このように記述することで、awsのリソースを扱うのに必要な情報を設定することができます。

また、見ていただくと分かる通り、アクセスキーとシークレットキーの情報が書かれていません。
このようなバージョン管理したくない情報は.gitignoreしたいので、別のファイルに外出しします。
Terraformでは*.tfvarsという拡張子でファイルを作ると変数を格納する設定ファイルを利用できるので、そのファイルだけignoreすればいいということになります。

$ cat terraform_iam.tfvars
access_key = "ACCESS_KEY"
secret_key = "SECRET_KEY"

このファイルを利用するには-var-fileオプションを使いますが、デフォルトではterraform.tfvarsファイルを使用するのでその場合は指定する必要がありません。

resource

AWSの場合、仕様できるリソースは以下のページで一覧できます。

www.terraform.io

今回はインスタンスを立ち上げてSSHできるところまでできればいいので、

  • aws_iam_instance_profile
  • aws_iam_role
  • aws_iam_role_policy
  • aws_security_group
  • aws_instance

この辺りを利用しています。
設定内容はリポジトリを御覧ください。
terraforming/simple_instance.tf at master · takasing/terraforming · GitHub

今回は後々Dockerを利用したいので、CoreOSのAMIを利用します。

実行

実行に際してはplan, applyを使用します。

plan

planはdryrunのようなもので、実行したら差分をチェックして反映される内容を出力してくれます。

$ terraform plan -var-file=terraform_iam.tfvars
Refreshing Terraform state prior to plan...


The Terraform execution plan has been generated and is shown below.
Resources are shown in alphabetical order for quick scanning. Green resources
will be created (or destroyed and then created if an existing resource
exists), yellow resources are being changed in-place, and red resources
will be destroyed.

Note: You didn't specify an "-out" parameter to save this plan, so when
"apply" is called, Terraform can't guarantee this is what will execute.

+ aws_iam_instance_profile.takasing_tf
    arn:              "" => "<computed>"
    create_date:      "" => "<computed>"
    name:             "" => "takasing-tf"
  ()

+ aws_iam_role.takasing_tf
    arn:                "" => "<computed>"
    assume_role_policy: "" => "{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Action\":   
  ()

+ aws_iam_role_policy.takasing_tf_policy
    name:   "" => "takasing-tf-policy"
    policy: "" => "{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Action\": \"ec2:*\",\n
  ()

+ aws_instance.tf_instance
    ami:                        "" => "ami-9cc1119c"
    availability_zone:          "" => "ap-northeast-1a"
  ()

+ aws_security_group.allow_all
    description:                          "" => "TODO: limit cidr_blocks"
  ()

ただ、このplanなんですけど、chef-client-Wオプションのように、ここで成功してもapplyの実行が必ず成功するとは限らないので##注意が必要みたいです。
たとえばplan実行して大丈夫そうだけど、実際に実行したらユーザーの権限足りなかった、みたいな。

apply

planで問題なさそうなことが確認できたら次はapplyを実行します。

$ terraform apply -var-file=terraform_iam.tfvars
aws_iam_role.takasing_tf: Refreshing state... (ID: takasing-tf)
aws_security_group.allow_all: Refreshing state... (ID: sg-XXXXXXXX)
aws_iam_role_policy.takasing_tf_policy: Refreshing state... (ID: takasing-tf:takasing-tf-policy)
aws_iam_instance_profile.takasing_tf: Refreshing state... (ID: takasing-tf)
aws_instance.tf_instance: Creating...
  ami:                        "" => "ami-9cc1119c"
  availability_zone:          "" => "ap-northeast-1a"
  ()

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

The state of your infrastructure has been saved to the path
below. This state is required to modify and destroy your
infrastructure, so keep it safe. To inspect the complete state
use the `terraform show` command.

State path: terraform.tfstate

この実行結果はインスタンスだけ存在しない場合の結果なんですけど、
terraformが差分をチェックして実行しているので、すでにセキュリティグループやIAMが準備済みでインスタンスのみが存在しないような場合は、インスタンスの作成のみをしてくれるみたいです。

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

と書いてありますね。

terraform.tfstate

terraformはapply実行後、次回以降の差分検出のためにterraform.tfstateというファイルを生成しています。
これはRDSのパスワードなどが平文で入るらしいので、バージョン管理しないほうが良いようです。

qiita.com

SSHしてみる

今回は22番ポートを開放してあるので、key pairの登録をちゃんとしていれば、手元にある鍵でSSHできるはずなのでSSHしてみます。 https://github.com/takasing/terraforming/blob/master/simple_instance.tf#L65-L74

ssh -i ~/.ssh/key.pem core@ec2-XX-XX-XX-XX.ap-northeast-1.compute.amazonaws.com
Last login: Thu Jun  4 04:13:04 2015 from XXX.XXX.XXX.XXX
CoreOS stable (647.2.0)
core@ip-XXX-XXX-XXX-XXX ~ $

CoreOS使っているのにec2-userでログインしようとしてしまって少しハマりましたw

TODO

  • 立ち上げるインスタンスをよりカスタマイズする
  • ECSのオペレーションをする

まとめ

Terraformを使うことで、Github上でインフラエンジニアとのコミュニケーションが取れるし、自動化も進みますし、管理も楽になるのでいいですね。

もっと自動化して働く時間減らしたいでござる