【30分で動かすシリーズ】まだCloudFormationで消耗してるの?TerraformでAWS環境を構築してみる(その1:TerraformでAWS環境を構築する準備)

記事タイトルとURLをコピーする

前置き

AWS CloudFormationはAWS環境を効率よく自動化して構築するに良いツールです。
ただ、できることが多い分、とっつきにくいです。
この記事を書いている間にCloudFormationでYAMLがサポートされたようですが、みんな大好きHashiCorp Terraformを使ってAWS環境の構築をしてみます。
Terraformは下記のようなことをお考えの方にいかがでしょうか。(個人差があります。個人の感想です)

  • AWSマネジメントコンソールでポチポチしていくのは面倒
  • AWS環境の構築過程を記録したい。が、AWSマネジメントコンソールのスクショを撮っていくのは不毛過ぎる
  • AWS CLIで構築スクリプトを書いても良いがバグっていたらバグった環境ができてしまい目も当てられない状況に
  • AWSマネジメントコンソールでポチポチやったり、スクリプト使うと構築履歴が録りづらく、構成管理しづらい
  • となれば、AWS CloudFormationなんでしょうけれど、よく分からん
  • AWS CloudFormationってなんであんなにタグを使いまくるの?
  • AWS CloudFormationで構築を始めたら、変更の度にClodFormationを使い続けないと構築履歴が保てなくなる。セキュリティグループのルール1つ直すみたいな変更だと大変

今回はTerraformのインストールとAWS環境を構築できるまでの準備を行ない、次回以降、EC2インスタンス等が設置できるようVPC等ネットワーク周りの構築、EC2やRDSインスタンスを立てるまで行ないます。

 

Terraformの導入

Terraformの導入については、公式サイトに案内があります。
ここに各OSでバイナリのパッケージがあります。
案内に倣って、/usr/local/terraform/bin にTerraformをインストールすると決めます。
ダウンロードして、展開して、現れたバイナリを決めた場所にコピーします。
TerraformをインストールしたところにPathを通しておけとあるので、通します。あと、Terraformの設定ファイルの置き場所(作業ディレクトリ)を作って、ここにもPathを通しておくみたいなので通しておきます。

PATH=/usr/local/terraform/bin:/home/your-user-name/terraform:$PATH

とりあえずTerraformを動かしてみます。

$ terraform
usage: terraform [--version] [--help]  [args]

The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you're just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.

Common commands:
    apply              Builds or changes infrastructure
    destroy            Destroy Terraform-managed infrastructure
    fmt                Rewrites config files to canonical format
    get                Download and install modules for the configuration
    graph              Create a visual graph of Terraform resources
    import             Import existing infrastructure into Terraform
    init               Initializes Terraform configuration from a module
    output             Read an output from a state file
    plan               Generate and show an execution plan
    push               Upload this Terraform module to Atlas to run
    refresh            Update local state file against real resources
    remote             Configure remote state storage
    show               Inspect Terraform state or plan
    taint              Manually mark a resource for recreation
    untaint            Manually unmark a resource as tainted
    validate           Validates the Terraform files
    version            Prints the Terraform version

All other commands:
    state              Advanced state management

あっさり動きました。
次にAWS環境を作るための設定ファイルについてです。

 

設定ファイル

Terraformは実行するディレクトリにある設定ファイルをすべて読み込んでうまいこと整合をとって書かれている内容を実行します。
読み込みの対象とする設定ファイルは拡張子が「.tf」もしくは「.tf.json」のファイルです。
設定ファイルの書式はここにあります。
拡張子「.tf」は、HashiCorp Configuration Language(HCL)と呼ばれるTerraformの開発元のHashiCorpが定めた書式で、拡張子「.tf.json」は名の通りJSONです。HCLですとコメント文が書けるので今回はこちらにしてみます。
設定ファイルは、たとえば設定する内容ごとにファイルを分けて書くことができます。AWS環境を作るときに使用するIAM情報、VPCやネットワーク周り、立てるEC2やRDS毎に、など設定ファイルを分けることができます。

設定ファイルの内容が被ったらどうなるか

たとえば、同じディレクトリに「10.0.0.0/16のVPCを作る」内容が複数のファイルに書かれていたらどうなるか、ですが、設定する内容毎に名前をつけられます。この場合は作るVPCの名前です。この名前で「このVPCにこのサブネットを作る」や「この名前のVPCの内容を出力して」などのことを行ないます。この名前が被っている場合は、Terraform実行時にエラーになります。
たとえば次のように「demo」と名付けたVPCが複数のファイルに現れるとTerraformはエラーとします。

$ cat vpc.tf
# VPC
resource "aws_vpc" "demo" {
    cidr_block = "10.0.0.0/16"
    tags {
        Name = "demo"
    }
}

$ cat vpc2.tf
# VPC
resource "aws_vpc" "demo" {
    cidr_block = "10.0.0.0/16"
    tags {
        Name = "demo2"
    }
}

$ terraform plan
module root: 1 error(s) occurred:

* aws_vpc.demo: resource repeated multiple times

明確に上書き設定したい場合は、「override.tf」と名付けた設定ファイルに内容を書くか、「_override」で終わるファイル名の設定ファイルに書きます。ここに解説があります。
上記の例だと「vpc2.tf」の内容を上書きしたいのであれば、「vpc2.tf」を「vpc_override.tf」にリネームします。

$ mv vpc2.tf vpc_override.tf

$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but
will not be persisted to local or remote state storage.


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. Cyan entries are data sources to be read.

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_vpc.demo
    cidr_block:                "10.0.0.0/16"
    default_network_acl_id:    ""
    default_route_table_id:    ""
    default_security_group_id: ""
    dhcp_options_id:           ""
    enable_classiclink:        ""
    enable_dns_hostnames:      ""
    enable_dns_support:        ""
    instance_tenancy:          ""
    main_route_table_id:       ""
    tags.%:                    "1"
    tags.Name:                 "demo2"


Plan: 1 to add, 0 to change, 0 to destroy.

通りました。旧vpc2.tfに書いた内容でVPCが作られます。

 

AWS環境構築の準備

各AWSリソースを作成できる権限のあるIAMを作成し、アクセスキーとシークレットアクセスキーを払出しておきます。
IAMに付加するポリシーは、AWS管理ポリシー「Power User」あたりを付加しておきます。

AWSリソースを作成するには、作成を行なうIAMのキーを設定ファイルに記述します。
Terraformの設定ファイルは、分割しての管理がラクなので、設定要素毎にファイルを分けておくことをオススメします。

provider "aws" {
    access_key = "foo"
    secret_key = "bar"
    region = "ap-northeast-1"
}

見て分かるかと思いますが、アクセスキー、シークレットアクセスキー、リージョンを指定します。
このあたりの文法や上記に書いたリージョンとは別のリージョンに構築したい場合はどうする?などはここに説明があります。

アクセスキーやシークレットアクセスキーをファイルに書いておきたくない場合は、コマンドラインオプションや環境変数で値を定義できます。
コマンドラインオプションは、 「-var 値の名前=値」です。
環境変数は

$ export AWS_ACCESS_KEY_ID="anaccesskey" 
$ export AWS_SECRET_ACCESS_KEY="asecretkey"
$ export AWS_DEFAULT_REGION="us-west-2"

こんな感じです。

「アクセスキーが許されるのは小学生までだよねー」という方にはAssume roleを利用する方法も用意されています。
このあたり詳しくはここに説明があります。
このようにドキュメントが充実しているのもTerraformの良いところです。

 

ここまでのまとめ

Terraformの導入、TerraformでAWS環境を構築する方法と準備を書いてみました。
少々長くなってしまいましたが、実際やってみるとすぐできるかと思います。
次回はいよいよVPC等ネットワーク周りの構築をTerraformで行なってみます。