Carpe Diem

備忘録。https://github.com/jun06t

TerraformでNLBを使う

概要

先日新しいL4のロードバランサーであるNLBがAWSからリリースされました。
ALBはL7のロードバランサーであるため、これまでgRPCはCLBの方でしか利用できませんでしたが、これからはNLBを使うことで対応が可能です。
terraform-provider-aws1.3.1から利用できるようになったので(1.3.0バグが有りました)、その使い方を紹介します。

環境

  • terraform 0.11.0
  • terraform-provider-aws 1.3.1

前提知識

NLBはこれまでのCLBやALBと幾つか仕様が異なるため、それを理解していないと躓きます。
特にSecurityGroup周りが大きく違っていて、以下のことを知っていないと疎通がうまく行きません。

NLBにはSecurityGroupを設定できない

NLBはSubnetは持ちますが、SecurityGroupを持ちません。
なのでself referenceを利用して同じSecurityGroupを持つことで疎通させるというテクニックは使えません。

SecurityGroupはバックエンドインスタンスで設定する

前述の理由から、バックエンドインスタンスでSecurityGroupを設定します。
基本的に以下の方針になります。

type バックエンドインスタンスのSecurityGroup
internal アクセス元のprivate subnetを許可する
internet-facing 外部アクセスを許可するため、0.0.0.0/0を許可する

ソースコード

aws_lb

NLBを使う場合はaws_lbリソースでload_balancer_typenetworkにする必要があります。
これを設定しないとデフォルトのapplicationとなり、ALBとして作成されます。

今回はgRPCを使ったマイクロサービス間の内部通信を実現するために作るので、internal = trueにしています。

security_groupsに関しては、先の前提知識でも触れたようにNLBでは設定できません。

resource "aws_lb" "dev_api" {
  name                       = "dev-api"
  subnets                    = ["${var.subnets["dev_private_1a"]}", "${var.subnets["dev_private_1c"]}"]
  internal                   = true
  load_balancer_type         = "network"
  enable_deletion_protection = false
}

aws_lb_listener

リスナーの設定です。
L4ロードバランサーを用意したいので、protocolTCPにします。

resource "aws_lb_listener" "dev_api" {
  load_balancer_arn = "${aws_lb.dev_api.arn}"
  port              = "9090"
  protocol          = "TCP"

  default_action {
    target_group_arn = "${aws_lb_target_group.dev_api.arn}"
    type             = "forward"
  }
}

aws_lb_target_group

ターゲットの設定です。
L4として使いたいのでこちらもprotocolTCPにします。

またそれに合わせてhealth_checkTCPにします。
porttraffic-portにすると自動で使用するポートに対する設定になります。 NLBではtimeoutは設定できず、healthy_thresholdunhealthy_thresholdの値も同じにしないといけません。

resource "aws_lb_target_group" "dev_api" {
  name                 = "dev-api"
  port                 = 9090
  protocol             = "TCP"
  vpc_id               = "${var.aws["vpc"]}"
  deregistration_delay = 180

  health_check {
    interval            = 30
    port                = "traffic-port"
    protocol            = "TCP"
    healthy_threshold   = 3
    unhealthy_threshold = 3
  }
}

疎通確認

ncコマンドでチェックできます。

$ nc -vz <LBのFQDN> 9090
Connection to <LBのFQDN> 9090 port [tcp/*] succeeded!

バックエンドインスタンスでのSecurityGroupが適切でないと、ちゃんと疎通できないので注意してください。

ソース