TerraformでALBの高度なリスナールールがより簡潔に書けるようになる前の話

この記事は[ニフティグループ Advent Calendar 2019](https://qiita.com/advent-calendar/2019/nifty)の21日目の記事です。

昨日は@shin27さんの「[MySQLの外部レプリケーションを使って最小限のダウンタイムでAWS RDSに移行する](https://qiita.com/shin27/items/62315297afc4153c42ce)」でした。実は現在、@shin27さんと同じ部署でして、日々悩みながらも楽しく頑張っている姿を見ていました。

# はじめに
この記事では、2019年12月14日に私が書いた「[TerraformでALBの高度なリスナールールがより簡潔に書けるようになった話](https://qiita.com/shotaws/items/eab5887d0ce922271f4f)」に関連して、AWSプロバイダーのv2.41.0以前の世界では、管理の仕方をどうしていたのかを書きます。

# 自己紹介
はじめまして、ななです。

普段は既存のシステムを運用したり、GoプログラムやTerraformコードを書いたり、またエンジニアをより元気にするためにそのシステムを題材にモダン化を図ったりしています。

あと、2019年を振り返ると、一番の思い出は「[AWS Summit Tokyo 2019](https://aws.amazon.com/jp/summits/tokyo-2019/)」の2日目で登壇したことですね。詳細は[こちらの記事](https://blog.web.nifty.com/engineer/2124)に書いてありますので、興味がある方は覗いてみてください。

# ここで本題に入る前に2019年12月14日に投稿した記事がどういうものだったのかを復習してみる
「[TerraformでALBの高度なリスナールールがより簡潔に書けるようになった話](https://qiita.com/shotaws/items/eab5887d0ce922271f4f)」では、2019年12月14日 (日本時間) にリリースされた[AWSプロバイダーのv2.42.0](https://github.com/terraform-providers/terraform-provider-aws/blob/master/CHANGELOG.md)の中にあるALBの高度なリスナールールに関するアップデートについて書いています。

ALBの高度なリスナールールには色々なパターンがありますが、その記事ではHTTPヘッダーを題材にしました。Terraformでの詳細な書き方や他のパターンについては[公式のドキュメント](https://www.terraform.io/docs/providers/aws/r/lb_listener_rule.html)にも書いてありますので、そちらもあわせてご確認ください。
<img width="864" alt="スクリーンショット 2019-12-15 11.03.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144887/2f41d4ad-0459-125e-07cb-973c78c7fa3d.png">

# Terraformで実際にALBの高度なリスナールールを書いてみる
## 前提となる環境
* Terraform v0.12
* AWSプロバイダー v2.41.0以前（なおv2.42.0以降でも動きます）

## 設定内容
今回もChromeやSafariブラウザを判定するリスナールールを実現してみます。
elb.tfから一部抜粋した設定を以下に示しています。

```terraform:elb.tf
resource "aws_cloudformation_stack" "http_header_based_routing" {
  name = "http-header-based-routing-stack"

  template_body = <<STACK
  {
      "Resources": {
        "ListenerRuleBasedOnHTTPHeader": {
          "Type": "AWS::ElasticLoadBalancingV2::ListenerRule",
          "Properties": {
            "Actions": [{
              "Type": "forward",
              "TargetGroupArn": "${aws_lb_target_group.tg.arn}"
            }],
            "Conditions": [{
              "Field": "http-header",
              "HttpHeaderConfig": {
                  "HttpHeaderName": "User-Agent",
                  "Values": [
                    "*Chrome*",
                    "*Safari*"
                  ]
              }
            }],
            "ListenerArn": "${aws_lb_listener.front_end.arn}",
            "Priority": 10
          }
        }
      }
  }
  STACK
}
```

以下のコマンドを用いてデプロイした後で、AWSマネジメントコンソールで確認します。

```
$ terraform init
$ terraform plan
$ terraform apply
```
以下の図を見るとちゃんと設定されていますね。
<img width="1250" alt="スクリーンショット 2019-12-15 12.00.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144887/f40a569d-e36d-b424-3c5e-31582bf110a5.png">

ここでTerraformから作成したCloudFormationのスタックの様子を見てみましょう。まずはスタックの情報を見てみると、「CREATE_COMPLETE」になっていますね。
<img width="1368" alt="スクリーンショット 2019-12-15 12.01.44のコピー.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144887/8c363222-f187-af3e-c239-bb65649379da.png">
次にイベントを見てみると、これも「CREATE_COMPLETE」になっていますね。
<img width="1362" alt="スクリーンショット 2019-12-15 12.03.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144887/635d813e-1c3c-ec35-92f9-4f212c13fbe5.png">
最後にテンプレートの情報を見てみると、上記で記述された内容が入っていますね。しかも変数が展開されています。
<img width="1378" alt="スクリーンショット 2019-12-15 12.04.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144887/c6d561c9-22f8-1865-04a7-da25680c49f9.png">

ちなみに、ALBの高度なリスナールールは、Terraformでより簡潔に書けるようになった後と比べると、コードの記述量が2倍近くになっています。一見するとメンテナンスが大変に見えますね。
しかしながら、CloudFormationの既存コードを活かせるため、CloudFormationの記述方法で詰まった際にはAWS公式サポートを享受できたり、公式ドキュメントを活用できたりするので良いですね。またTerraformでしか基本的に書きたくないという方にもマッチする方法ですね。

# まとめ
今回は、2019年12月14日に書いた記事の比較対象として、TerraformでALBの高度なリスナールールがより簡潔に書けるようになる前の話を書きました。皆さんも既存のコードを活かしつつインフラ運用に関してどんどん最適化を図っていきましょう。

ありがとうございました。明日は@hamakou108さんです！よろしくお願いします。

# 余談 その1
この記事を書いている時に、TerraformとAWS Cloud Development Kit (AWS CDK) を連携しようと試みている[こちらの記事](https://blog.youyo.io/posts/terraform-with-aws-cdk/)を偶然見つけました。CDKの界隈でも同じように考える人が居るんだなと感じました。

# 余談 その2
[AWSプロバイダーのv2.43.0](https://github.com/terraform-providers/terraform-provider-aws/blob/master/CHANGELOG.md)がリリースされましたね。高度なリスナールール周りでも修正があったようです。
<img width="900" alt="スクリーンショット 2019-12-20 19.57.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144887/cad643da-1d08-88cc-f52f-a49c3ae3272e.png">

# 参考サイト
* [【まいうー】TerraformからCloudFormationをおいしくいただく ｜ Developers.IO](https://dev.classmethod.jp/devops/using-cloudformation-from-terraform/)
* [AWS::ElasticLoadBalancingV2::ListenerRule - AWS CloudFormation](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-listenerrule.html)
* [AWS: aws_cloudformation_stack - Terraform by HashiCorp](https://www.terraform.io/docs/providers/aws/r/cloudformation_stack.html)