こちらのブログは個人ブログと同じ内容です
こんにちは、 kotamat です。
Terraform 0.12がでてしばらく立ちますが、先日構築したCloudfrontの環境において、Terraform0.12のdynamicを使わないと実現できない事案が発生したため、この際にと思い、一気に0.12にバージョンアップしました。
マイグレーション方法とかは、terraform側が提供しているものを使えば80%くらいはやってくれるので(一部手動で修正が必要ですが、WARNING出してくれるのでポチポチやっていくだけです。)今回は主題のdynamicについて紹介します。
Dynamicとは
terraform 0.12で追加されたシンタックスのうちの一つです。
通常、トップレベルのリソースに関しては、一つ一つのリソースに名前をつけて記述したり、 count
とかを使って繰り返しを記述していきますが、security group
や cloudfront
のようなネストされたリソースを記述する際には一つ一つ重複して書く必要がありました。
特にcloudfrontは機能が多く、befaviorに各パスごとのoriginを書くことによってL7スイッチになることができるため、設定が繰り返し記述になりがちであり、かつネストが多い非常に複雑な構造になっているため、dynamicの恩恵を受けることができます。
記述方法
今回は
で紹介した形を例に考えてみます。
各種スイッチの向き先の対照表は下記になっています。
ディレクトリ | オリジンの向き先 |
---|---|
/api/* | API |
/nova/* | nova |
/nova-assets/* | nova |
/nova-api/* | nova |
/vendor/nova/* | nova |
default | S3(Nuxt.js) |
今までであれば、/apiのブロックを一つ、novaのブロックを4つ、deafultのブロックを一つ書く必要がありましたが、dynamicを用いることによって、defaultとordered一つのブロックですべての表現をすることができます。
resource "aws_cloudfront_distribution" "main" { // api ordered_cache_behavior { allowed_methods = [ "GET", "HEAD", "OPTIONS", "POST", "PUT", "PATCH", "DELETE", ] cached_methods = [ "GET", "HEAD", ] default_ttl = 0 forwarded_values { cookies { forward = "all" } headers = ["*"] query_string = true } max_ttl = 0 min_ttl = 0 target_origin_id = local.api_origin_id viewer_protocol_policy = "redirect-to-https" path_pattern = "/api/*" } // nova ordered_cache_behavior { allowed_methods = [ "GET", "HEAD", ] cached_methods = [ "GET", "HEAD", ] default_ttl = 0 forwarded_values { cookies { forward = "all" } headers = ["*"] query_string = true } max_ttl = 0 min_ttl = 0 target_origin_id = local.nova_origin_id viewer_protocol_policy = "redirect-to-https" path_pattern = "/nova/*" } // 以下 nova-assets/*とかも記述していく
↓
locals { path_patterns = [ "/api/*", "/nova/*", "/nova-assets/*", ] } resource "aws_cloudfront_distribution" "main" { dynamic "ordered_cache_behavior" { // 何を繰り返すのかをfor_eachで指定する for_each = locals.path_patterns content { allowed_methods = [ "GET", "HEAD", "OPTIONS", "POST", "PUT", "PATCH", "DELETE", ] cached_methods = [ "GET", "HEAD", ] default_ttl = 0 forwarded_values { cookies { forward = "all" } headers = ["*"] query_string = true } max_ttl = 0 min_ttl = 0 target_origin_id = local.api_origin_id viewer_protocol_policy = "redirect-to-https" path_pattern = ordered_cache_behavior.value // dynamicで指定したリソース名 + .valueでpathの中身を取得 } } }
他の使いみち
上記はbehaviorの設定をまとめるために使ってみましたが、例えばステージング環境は特定のパスだけBasic認証いれたいという要件が来たときには、今までだとlambda_function_association
だけ違う別リソースを記述する必要がありましたが、map
と組み合わせる事によって、下記のように同一ソースで記述することができます。
locals { lambda_associations = { "stg": { // stg特有のもの(Basic認証とか) { event_type = "viewer-request" lambda_arn = module.viewer_request.qualified_arn }, // prodと共通のもの { event_type = "origin-request" lambda_arn = module.origin_request.qualified_arn }, }, "prod": { { event_type = "origin-request" lambda_arn = module.origin_request.qualified_arn } } } } resource "aws_cloudfront_distribution" "main" { default_cache_behavior { dynamic "lambda_function_association" { for_each = local.lambda_associations[terraform.workspace] // workspaceの値を取得し、動的にassociationを切り替える content { event_type = lambda_function_association.value.event_type lambda_arn = lambda_function_association.value.lambda_arn } } } }
まとめ
terraform 0.12 dyanmicの使い方を、Cluodfrontを用いて紹介させてもらいました。 特に後者の、lambda edgeとの組み合わせは非常に使い勝手がいいので、よかったら試してもらえればと思います。