Elastic BeanstalkでELB作成を抑止する

[Elastic Beanstalk](https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/Welcome.html)で管理しているプロダクトを任意のALBでパスルーティングする場合、コスト削減のためにELB作成を抑制することがあります。その時の設定のコツと注意点を書きたいと思います。

<!-- more -->

* 基本的に下記名前空間において環境アーキテクチャとサービスロールを設定する必要があります。

  <b><i>名前空間: aws:elasticbeanstalk:environment</i></b>

* ELB作成を抑止するためには<i>EnvironmentType</i>を<i>SingleInstance</i>と指定します。
そうすることでELBは作成されずに単一のEC2 Instanceのみが起動する環境を作成できます。

```tf
  // EnvironmentType LoadBalanced or SingleInstance
  setting {
    namespace = "aws:elasticbeanstalk:environment"
    name      = "EnvironmentType"
    value     = "SingleInstance"
  }
```

* 環境作成時にAuto Scaling Groupも自動で作成されますが、<b>Desired Capacity(必要な容量)</b>、<b>Min(インスタンスの最小数)</b>、<b>Max(インスタンスの最大数)</b>は強制的に<i><b>1</b></i>に設定されます。サーバリソースが高負荷になっても自動でスケールされないという点は注意が必要です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58788/5d840347-3815-7149-ed23-cbe6e2fc7835.png)


* これは<b><i>名前空間: aws:autoscaling:trigger</i></b>を明示的に記述しても無視されます。
ELB作成時に使用している下記設定は不要となります。

```elastic_beanstalk_environment_front.tf
  setting {
    namespace = "aws:autoscaling:trigger"
    name      = "MeasureName"
    value     = "TargetResponseTime"
  }

  setting {
    namespace = "aws:autoscaling:trigger"
    name      = "Statistic"
    value     = "Average"
  }

  setting {
    namespace = "aws:autoscaling:trigger"
    name      = "Unit"
    value     = "Seconds"
  }

  setting {
    namespace = "aws:autoscaling:trigger"
    name      = "Period"
    value     = "1"
  }

  setting {
    namespace = "aws:autoscaling:trigger"
    name      = "BreachDuration"
    value     = "1"
  }

  setting {
    namespace = "aws:autoscaling:trigger"
    name      = "UpperThreshold"
    value     = "10"
  }

  setting {
    namespace = "aws:autoscaling:trigger"
    name      = "UpperBreachScaleIncrement"
    value     = "1"
  }

  setting {
    namespace = "aws:autoscaling:trigger"
    name      = "LowerThreshold"
    value     = "1"
  }

  setting {
    namespace = "aws:autoscaling:trigger"
    name      = "LowerBreachScaleIncrement"
    value     = "-1"
  }

setting {
  namespace = "aws:ec2:vpc"
  name      = "ELBSubnets"
  value     = var.ELBSubnets
}
```

* Elastic Beanstalkが作成したTarget GroupはALBのリスナールールとして指定できないので別途作成してリスナールールに設定することが必要です。

```autoscaling_attachment.tf
resource "aws_autoscaling_attachment" "xxxxxxxxxx" {  
  autoscaling_group_name = aws_elastic_beanstalk_environment.xxxxxxxxxx.autoscaling_groups[0]  
  alb_target_group_arn   = aws_lb_target_group.xxxxxxxxxx.arn 
}
```

```lb_target_group.tf
resource "aws_lb_target_group" "xxxxxxxxxx" {
  name     = "xxxxxxxxxx"
  port     = 80
  protocol = "HTTP"
  vpc_id   = data.aws_vpc.xxxxxxxxxx.id

  health_check {
    enabled             = true
    interval            = 30
    path                = "/xxxxxxxxxx"
    port                = "traffic-port"
    protocol            = "HTTP"
    timeout             = 5
    healthy_threshold   = 3
    unhealthy_threshold = 3
    matcher             = 200
  }

  tags = {
    Name        = "xxxxxxxxxx"
    Service     = "xxxxxxxxxx"
    Environment = "xxxxxxxxxx"
    Description = "Managed by Terraform"
  }
}
```
* <b><i>SingleInstance</i></b>で作成するEC2 InstanceはPublicIPを付与させない設定のSubnetで起動させてもEIPが付与されてしまいますが、これは仕様です。
* 限定的なリクエストしか来ないようなプロダクトの商用環境であっても<i>SingleInstance</i>での運用が可能かは計測する必要があります。