无法使用 Terraform 在自定义 VPC 中创建 Elastic Beanstalk 应用程序

Posted

技术标签:

【中文标题】无法使用 Terraform 在自定义 VPC 中创建 Elastic Beanstalk 应用程序【英文标题】:Cannot create an Elastic Beanstalk application in a custom VPC using Terraform 【发布时间】:2021-04-27 03:55:21 【问题描述】:

我正在尝试使用 Terraform 在自定义 VPC 的私有子网中创建 Elastic Beanstalk 应用程序。我遇到的问题是创建超时。

错误:

等待 Elastic Beanstalk 环境 (e-xxxxxxxxx) 准备就绪时出错:发生 2 个错误:

2021-01-22 16:37:56.664 +0000 UTC (e-xxxxxxxxx):名为“awseb-e-xxxxxxxxx-stack”的堆栈已中止操作。当前状态:“CREATE_FAILED”原因:未能创建以下资源:[AWSEBInstanceLaunchWaitCondition]。 2021-01-22 16:37:56.791 +0000 UTC (e-xxxxxxxxx) :EC2 实例无法与 AWS Elastic Beanstalk 通信,原因可能是 VPC 的配置问题或 EC2 实例失败。检查您的 VPC 配置并再次尝试启动环境。

我认为我缺少从 VPC 到外部的连接,但我不确定是什么。

我已尝试添加一些aws_vpc_endpoint 资源:

resource "aws_vpc" "main" 
  cidr_block = "10.16.0.0/16"

  enable_dns_support   = true
  enable_dns_hostnames = true


resource "aws_security_group" "elasticbeanstalk_vpc_endpoint" 
  name   = "elasticbeanstalk-vpc-endpoint"
  vpc_id = aws_vpc.main.id

  ingress 
    from_port   = 0
    to_port     = 65535
    protocol    = "tcp"
    cidr_blocks = [ "0.0.0.0/0" ]
  

  egress 
    from_port   = 0
    to_port     = 65535
    protocol    = "tcp"
    cidr_blocks = [ "0.0.0.0/0" ]
  


resource "aws_vpc_endpoint" "elasticbeanstalk" 
  vpc_id       = aws_vpc.main.id
  service_name = "com.amazonaws.$var.aws_region.elasticbeanstalk"

  security_group_ids = [
    aws_security_group.elasticbeanstalk_vpc_endpoint.id,
  ]

  vpc_endpoint_type = "Interface"


resource "aws_security_group" "ec2_vpc_endpoint" 
  name   = "ec2-vpc-endpoint"
  vpc_id = aws_vpc.main.id

  ingress 
    from_port   = 0
    to_port     = 65535
    protocol    = "tcp"
    cidr_blocks = [ "0.0.0.0/0" ]
  

  egress 
    from_port   = 0
    to_port     = 65535
    protocol    = "tcp"
    cidr_blocks = [ "0.0.0.0/0" ]
  


resource "aws_vpc_endpoint" "ec2" 
  vpc_id       = aws_vpc.main.id
  service_name = "com.amazonaws.$var.aws_region.ec2"

  security_group_ids = [
    aws_security_group.ec2_vpc_endpoint.id,
  ]

  vpc_endpoint_type = "Interface"

EB 实例:

resource "aws_elastic_beanstalk_environment" "endpoint" 
  name                = "foo-env"

  setting 
    namespace = "aws:ec2:vpc"
    name      = "VPCId"
    value     = aws_vpc.main.vpc_id
    resource  = ""
  

  setting 
    namespace = "aws:ec2:vpc"
    name      = "Subnets"
    value     = join(",", [ aws_subnet.private_a.id, aws_subnet.private_b.id ])
    resource  = ""
  

  setting 
    namespace = "aws:ec2:vpc"
    name      = "ELBScheme"
    value     = "internal"
    resource  = ""
  

  setting 
    namespace = "aws:elasticbeanstalk:environment"
    name      = "EnvironmentType"
    value     = "LoadBalanced"
    resource  = ""
  

  setting 
    namespace = "aws:elasticbeanstalk:environment"
    name      = "LoadBalancerType"
    value     = "application"
    resource  = ""
  

  setting 
    namespace = "aws:elasticbeanstalk:application:environment"
    name      = "AWS_REGION"
    value     = var.aws_region
    resource  = ""
  

  # ...

  depends_on = [
    aws_vpc_endpoint.ec2,
    aws_vpc_endpoint.elasticbeanstalk,
  ]


这样创建的子网:

resource "aws_subnet" "public" 
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.16.0.0/24"

  availability_zone       = "$var.aws_regionc"
  map_public_ip_on_launch = true


resource "aws_subnet" "private_a" 
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.16.192.0/24"

  availability_zone = "$var.aws_regiona"


resource "aws_subnet" "private_b" 
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.16.224.0/24"

  availability_zone = "$var.aws_regionb"

路由表:

resource "aws_route_table" "private" 
  vpc_id = aws_vpc.main.id


resource "aws_route_table_association" "private_a" 
  route_table_id = aws_route_table.private.id
  subnet_id      = aws_subnet.private_a.id


resource "aws_route_table_association" "private_b" 
  route_table_id = aws_route_table.private.id
  subnet_id      = aws_subnet.private_b.id


resource "aws_route_table" "public" 
  vpc_id = aws_vpc.main.id


resource "aws_route_table_association" "public" 
  route_table_id = aws_route_table.public.id
  subnet_id      = aws_subnet.public.id


resource "aws_internet_gateway" "public" 
  vpc_id = aws_vpc.main.id


resource "aws_route" "public_internet" 
  route_table_id = aws_route_table.public.id
  gateway_id     = aws_internet_gateway.public.id

  destination_cidr_block = "0.0.0.0/0"

【问题讨论】:

你能提供完整的aws_elastic_beanstalk_environment吗? 另外,您正在创建自定义 aws_vpc,但不会显示子网、路由表和您的 vpc 的任何配置详细信息。 @Marcin 我添加了更多细节 【参考方案1】:

下面列出了一些可能导致您的问题的观察结果。在私有 VPC 中设置 EB 的一般指南位于 aws docs。

观察结果:

aws_vpc.main.vpc_id 应该是 aws_vpc.main.id

在所有端点中,private_dns_enabled 默认为 false。端点应该是true 才能无缝工作。您可以将以下内容添加到您的端点:

private_dns_enabled = true
您的端点未与任何子网关联。要关联它们,您可以使用:
subnet_ids        = [aws_subnet.private_a.id, aws_subnet.private_b.id]
cloudformation 没有接口端点:
resource "aws_vpc_endpoint" "cloudformation" 
  vpc_id       = aws_vpc.main.id
  service_name = "com.amazonaws.$var.aws_region.cloudformation"

  security_group_ids = [
    aws_security_group.elasticbeanstalk_vpc_endpoint.id,
  ]
  
  subnet_ids        = [aws_subnet.private_a.id, aws_subnet.private_b.id]
  
  private_dns_enabled = true

  vpc_endpoint_type = "Interface"

EB 从 S3 获取应用程序 zip,但没有 S3 端点。对于 S3,您可以使用:
resource "aws_vpc_endpoint" "s3" 
  vpc_id       = aws_vpc.main.id
  service_name = "com.amazonaws.$var.aws_region.s3"
  
  vpc_endpoint_type = "Gateway"
  
  route_table_ids = [ aws_route_table.private.id ]

elasticbeanstalk-healthd 没有 vpc 端点。可以使用:
resource "aws_vpc_endpoint" "elasticbeanstalk-hc" 
  vpc_id       = aws_vpc.main.id
  service_name = "com.amazonaws.$var.aws_region.elasticbeanstalk-health"

  security_group_ids = [
    aws_security_group.elasticbeanstalk_vpc_endpoint.id,
  ]
  
  private_dns_enabled = true

  vpc_endpoint_type = "Interface"

如果您添加新的端点,您需要在aws_elastic_beanstalk_environment 中更新您的depends_on

【讨论】:

谢谢,我会试试这些然后回来。

以上是关于无法使用 Terraform 在自定义 VPC 中创建 Elastic Beanstalk 应用程序的主要内容,如果未能解决你的问题,请参考以下文章

AWS VPC 模块公有和私有子网 - Terraform

通过 terraform 在 aws 中创建 VPC 问题

Terraform 0.11:aws_lambda_function 中的条件 vpc_config

Terraform 基础 定义阿里云资源 VPC安全组

Terraform 管理阿里云 VPC

使用配置文件 (.ebextensions) 在自定义 VPC 中为 TCP 直通配置 Elastic Beanstalk 环境的负载均衡器