Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
321 views
in Technique[技术] by (71.8m points)

amazon web services - Terraform: Why AWS NAT Gateway conflicts with Egress Only Internet Gateway

I have both IPv4 and IPv6, I'm trying to manage a Routing for private subnet.

Once NAT Gateway is attached to Route Table, it does not allow me to attach Egress Gateway to the same route table, and giving me an error:

An interface that is part of a NAT gateway cannot be the next hop for an IPv6 destination CIDR block or IPv6 prefix list

However if I'm attaching manually thought AWS Console, there is no problem

Manual Attachment worked as expected

Maybe I'm missing some info? I know that NAT only for IPv4 and Egress only for IPv6, can someone guide me on this? Why if NAT not compatible with Egress Only Gateway, it allows me to attach via aws console, but not with terraform?

Here is my simple terraform

resource "aws_eip" "neip"  {
   count = length(var.private_subnet) 
   vpc   = true
}

resource "aws_nat_gateway" "nat" {
   count = length(var.private_subnet) 
   subnet_id     = element(var.public_subnet, count.index)
   allocation_id = element(aws_eip.neip.*.id, count.index)
}
resource "aws_egress_only_internet_gateway"  "egw"  {
   count  = length(var.zones) > 0 ? 1 : 0
   vpc_id = var.vpc_id
}
resource "aws_route_table" "route" {
   count = length(var.private_subnet) 
   vpc_id = var.vpc_id
}

resource "aws_route" "ipv4" {
   count           = length(aws_route_table.route) 
   depends_on      = [ aws_route_table.route ]
   route_table_id  = aws_route_table.route[count.index].id
   nat_gateway_id  = element(aws_nat_gateway.nat.*.id, count.index)
   destination_cidr_block = "0.0.0.0/0"
}

resource "aws_route" "ipv6"  {
   count                   = length(aws_route_table.route) 
   depends_on              = [ aws_route_table.route ]
   route_table_id          = aws_route_table.route[count.index].id
   egress_only_gateway_id  = element(aws_egress_only_internet_gateway.egw.*.id, count.index)
   destination_ipv6_cidr_block = "::/0"
}

resource "aws_route_table_association" "route" {
   count          = length(aws_route_table.route) 
   subnet_id      = var.private_subnet[count.index]
   route_table_id = aws_route_table.route[count.index].id
}

No issue with terraform script

enter image description here


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I tried to reproduce your issue, but for me it works as expected. Maybe you still have some "typos" in your code presented here, thus its difficult to see why it woudn't work for you.

Anyway, here is the code I used in order to mimic your setup, though large chunks I had to create myself, as they are not shown in your code (e.g. VPC setup all missing, internet gateway, public subnets).

The code below works and I couldn't replicate your issue. Route tables work as expected:


data "aws_availability_zones" "available" {}

resource "aws_vpc" "vpc" {
    cidr_block = "10.0.0.0/16"
    enable_dns_hostnames = true
    assign_generated_ipv6_cidr_block = true
    tags = {
        Name = "testvpc"
    }
}

variable "private_cidrs" {
    default = ["10.0.2.0/24", "10.0.3.0/24"]
}

variable "public_cidrs" {
    default = ["10.0.0.0/24", "10.0.1.0/24"]
}

resource "aws_subnet" "public_subnet" {

    count = length(var.public_cidrs)

    cidr_block = var.public_cidrs[count.index]
    vpc_id = aws_vpc.vpc.id
    availability_zone = data.aws_availability_zones.available.names[count.index]
    tags = {
        Name = "public${count.index}"
    }
}

resource "aws_subnet" "private_subnet" {

    count = length(var.private_cidrs)

    cidr_block = var.private_cidrs[count.index]
    vpc_id = aws_vpc.vpc.id
    availability_zone = data.aws_availability_zones.available.names[count.index]
    tags = {
        Name = "private${count.index}"
    }
}

resource "aws_eip" "neip"  {
   count = length(var.private_cidrs) 
   vpc   = true
}

resource "aws_internet_gateway" "igw" {
  vpc_id = aws_vpc.vpc.id

  tags = {
    Name = "main"
  }
}

resource "aws_nat_gateway" "nat" {
   count         = length(var.private_cidrs) 
   subnet_id     = element(aws_subnet.public_subnet.*.id, count.index)
   allocation_id = element(aws_eip.neip.*.id, count.index)
   
   depends_on    = [aws_internet_gateway.igw]
}

resource "aws_egress_only_internet_gateway"  "egw"  {
   #count  = length(var.private_cidrs) 
   vpc_id = aws_vpc.vpc.id
}

# routes for public subnets

resource "aws_route_table" "public_route" {
   count = length(var.public_cidrs) 
   vpc_id = aws_vpc.vpc.id
}

resource "aws_route" "public_ipv4" {
   count           = length(aws_route_table.public_route) 
   route_table_id  = aws_route_table.public_route[count.index].id
   gateway_id  = aws_internet_gateway.igw.id
   destination_cidr_block = "0.0.0.0/0"
}

resource "aws_route" "ipv6_public"  {
   count                   = length(aws_route_table.public_route) 
   route_table_id          = aws_route_table.public_route[count.index].id
   egress_only_gateway_id  = aws_egress_only_internet_gateway.egw.id
   destination_ipv6_cidr_block = "::/0"
}

resource "aws_route_table_association" "public_route" {
   count          = length(aws_route_table.public_route) 
   subnet_id      = aws_subnet.public_subnet[count.index].id
   route_table_id = aws_route_table.public_route[count.index].id
}

# routes for private subnets

resource "aws_route_table" "route" {
   count = length(var.private_cidrs) 
   vpc_id = aws_vpc.vpc.id
}

resource "aws_route" "ipv4" {
   count           = length(aws_route_table.route) 
   route_table_id  = aws_route_table.route[count.index].id
   nat_gateway_id  = aws_nat_gateway.nat[count.index].id
   #nat_gateway_id  = aws_nat_gateway.nat.id
   destination_cidr_block = "0.0.0.0/0"
}

resource "aws_route" "ipv6"  {
   count                   = length(aws_route_table.route) 
   route_table_id          = aws_route_table.route[count.index].id
   egress_only_gateway_id  = aws_egress_only_internet_gateway.egw.id
   destination_ipv6_cidr_block = "::/0"
}

resource "aws_route_table_association" "route" {
   count          = length(aws_route_table.route) 
   subnet_id      = aws_subnet.private_subnet[count.index].id
   route_table_id = aws_route_table.route[count.index].id
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...