Terraform全まとめ AWS

まとめ系記事は随時更新中です。

Terraform初心者向けに、Terraformの概要やポイントとコマンドを記載しておきます。

スポンサーリンク

IaCとは

Infrastructure as Codeの略です。インフラのコード化です。

メリットは多数あり、誰かが構築したインフラをコードで再現出来る。コードとして冪等性を持たせて管理出来る。コードとして内容を把握する事が出来る。コードとしてレビューが出来る。処理に組み込む事で自動化が出来る。スケーラブルに対応出来る。他にも色々ありそうですね。

Terraformとは

簡単に言えば、TerraformとはAWSやGCPなどのインフラ環境を構築してくれるツールです。

上で触れましたが、「インフラのコード化」という言葉を聞いた事があると思います。Terraformは、これを実現する為の現時点で一番人気があるツールです。

AWSのCLIだけだと、依存関係を意識しながら順番に構築していく必要があったり、ゴリゴリとスクリプトを組む事も必要です。

これがTerraformだと、依存関係は意識しながらですが、処理順はTerraform任せになります。構築に必要な情報を記載していくだけなので、CLIより簡単です。

TerraformはAWSの中にあるものではありません。PCやデプロイ司令環境にインストールして使用します。

Terraformで構築されたインフラをまた構成変更したい場合などに、差分確認が出来て更新する事も可能です。

その為に、Terraformで構築した時点で状態ファイル(.tfstate)を出力します。一般的にはs3に保管してチームでシェアします。(これをterraformではbackendにs3を使用するという風に呼びます。)

AWSアカウント切り分け

s3にtfstateファイルを管理(生成・更新)するAWSアカウントと、LambdaやEC2など実際の環境を構築するAWSアカウントは、後者の方が影響・権限が強いので、別にして管理したい事があると思います。

先ず、aws configure でs3用のアカウントアクセスキー、シークレットキーを設定します。これでTerraformの実行に伴うs3配置の状態管理が出来ます。

Lambdaなどを構築するアカウントは、Terraformのprovider句で指定します。いくつか方法があるので記載しておきます。

コマンド引数でアクセスキーを指定するやり方もりますが、.tfvars ファイルに記載したり、~/.aws/credentials にprofile として記載したキーを使うという指定も可能ですし、AWSのassume roleを使用して、権限をキーなしで期限付きで委譲するという事も可能です。

Assume Roleで実装出来れば、キーの管理や切り替えが不要ですし、期限付きなので、一番良いと思います。

AWSのアカウントを取り扱う上で、最悪のパターンはキーをコミットしてしまう事です。もしリポジトリが公開されていれば、悪い巡回BOTにより、すぐさまキーが公開された事が検知され、仮想通貨のマイニングにガッツリ使われて、AWSから使ってもいないハイスペックな多額の請求が届くという事件が実際に起きているようです。ですので、キーの管理にだけはご注意ください。

サンプルを記載しておきます。

コマンド引数でアクセスキーを渡す方法

以下コマンドでコマンドラインからアカウント情報を渡します。

[variables.tf] にvariableでアカウント項目を定義して入力を受け取ります。

[main.tf] などで以下の書き方で使用可能です。

.tfvarsに記載する方法

[任意名.tfvars] を作成して、中に変数と値を記載します。※これはコミット対象外にします。(.gitignoreに *.tfvars と記載)

コマンドラインから [-var-file ファイル名] を指定します。

varables.tfなどにvariableで入力値を受け取る箇所からは「コマンド引数でアクセスキーを渡す方法」と同様です。

~/.aws/credentials にprofile として記載する方法

  • deployuserというユーザの場合

aws コマンドの場合は —profile=deployuser オプションですが、terraformでは、、、あとで書きます

Assume Role で権限を委譲する方法

Terraformコマンド

Terraformでよく使うコマンドを記載しておきます。

terraform init

ローカルに .terraform ディレクトリが生成されます。

terraform plan

でAWS上の構築済インフラと、terraformファイル(*.tf)による更新予定との差分が確認出来ます。

terraform workspace new [dev]

バックエンドで指定したs3のdevディレクトリに.tfstateファイルを準備します。

余談ですが、CircleCIでTerraformによるデプロイをやろうとした時、CircleCIではエラーコードがはかれると、デフォルトだとそこで試合終了です。

newしようとしたworkspaceが既にある場合、エラーで終了してしまうので、selectと合わせて書きます。

とする事で、new出来ればそこで正常終了し、出来なければ既にあるものをselectする。という形にしてエラーコードが回避出来ます。

terraform apply

terraformで書いた構築を行います。

terraform destroy

Terraformで構築したインフラを削除します。

terraform fmt

一括でインデント等を修正してくれます。 -recursive オプションをつけるとサブディレクトリ配下も一括でやってくれるので、このオプションは重宝しています。

Terraformの具体的用途

インフラの構築

Route53, CloudFront, ACM, ALB, VPC などを構築します。

AWS Lambda関数の更新

初期構築だけでなく、Lambda関数のPGの修正をデプロイする事にも使用可能です。CircleCI上でTerraformによるBlueGreenデプロイも可能です。Lambdaにはエイリアスをつけられるので、これをALBターゲットの向き先として使います。

Terraform運用の注意点

管理に失敗すると触れば触るほど戻すのが困難になります。

状態管理ファイルであるtfstateファイルを削除しないこと。

Terraform管理対象の環境を不用意に手動で更新しないこと。

s3に状態ファイルを格納する場合、プロパティでバージョニングを有効にさせておく事で、状態をバージョニングできるのでやっておくこと。

terraform apply する前に terraform plan で計画を確認すること。

Terraformサンプルコード

TerraformによるACM構築コード
resource "aws_acm_certificate" "acm" { domain_name = "example...

Terraformエラー・対応記事

エラー時に調べた記録など残しております。

S3関連

TerraformでALBのログをS3に指定したら権限エラー
TerraformでALBのログをS3に指定したら権限エラーになったので対応等記録しておきます。 エラーメッセージ Error...
TerraformでCloudFrontのログをS3に出力しようとしたらエラー「MalformedPolicy: Invalid principal in policy」になった
CloudFrontとS3連携では、以下の記事のようにS3のバケットポリシーにCFのIdentityを設定してあげる必要があります。 ...

VPC関連

Terraform AWSエラーRulesPerSecurityGroupLimitExceeded セキュリティグループ数上限60個超過
Terraformでセキュリティグループに多めのIPを積んで apply しようとしたところ、エラー RulesPerSecurityGr...

LoadBalancer関連

[Terraform AWS]ALBにACMで複数ドメインを指定しようとしたら出たエラー Error creating LB Listener: DuplicateListener: A listener already exists on this port for this load balancer
要件 AドメインとBドメインのリクエストを、1つのALBでhttpとhttpsの両方をリスナーとして捌きたい。 httpsはA...
TerraformがALBのaws_lb_listener_ruleでhttp-headerに対応していなかった
いやもう結論タイトルなのですが、現時点(2019/9)ではALBのリスナーで、http-headerを判定してごにょごにょという事が、Te...

CloudFront関連

https://normalblog.net/system/terraform-error-invalidlambdafunctionassociation/

その他

Terrafom remote state(外部tfstateのリソース)を使用する方法
Terraformで外部tfstateのリソースを使用する場合は普通にあり得ます。特にマイクロサービス化などでtfstateを細かく分割し...