Problemas para la Implementación de VPC con Subredes con CDK y Python

0

Pregunta

Estoy tratando de crear una VPC con subredes para un proyecto, sin embargo, estoy corriendo en un problema donde CDK parece hacer dos subredes con el mismo bloque CIDR cuando sintetizar el código en una plantilla de CloudFormation, aunque yo sólo uso de un bloque CIDR una vez por cada subred de la declaración. Esto hace que la implementación a fallar desde CIDR bloques en conflicto unos con otros a la hora de crear las subredes. Aquí está el código para la definición de la pila:

from aws_cdk import core as cdk
from aws_cdk import aws_ec2 as ec2

class CdkWorkshop3Stack(cdk.Stack):

    def __init__(self, scope: cdk.Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        # The code that defines your stack goes here

        # instantiate VPC with dns support and hostname enabled and cidr block at 10.0.0.0/24
        vpc = ec2.Vpc(self, "vpc-cf",
                      cidr="10.0.0.0/24",
                      enable_dns_support=True,
                      enable_dns_hostnames=True
                      )

        # instantiate internet gateway and attach VPC with internet gateway
        igw = ec2.CfnInternetGateway(self, "igw")
        igw_attach = ec2.CfnVPCGatewayAttachment(
            self, "igw_attach", vpc_id=vpc.vpc_id, internet_gateway_id=igw.attr_internet_gateway_id)

        # instantiate elastic IP with VPC domin
        eip = ec2.CfnEIP(self, "eip", domain="VPC")

        # instantiate public and private subnets and use first availability zone
        pub_subnetA = ec2.Subnet(
            self, "public-subnetA", availability_zone=super().availability_zones[0], cidr_block="10.0.0.0/26", vpc_id=vpc.vpc_id, map_public_ip_on_launch=True)
        pub_subnetB = ec2.Subnet(
            self, "public-subnetB", availability_zone=super().availability_zones[0], cidr_block="10.0.0.64/26", vpc_id=vpc.vpc_id, map_public_ip_on_launch=True)
        pri_subnetA = ec2.Subnet(
            self, "private-subnetA", availability_zone=super().availability_zones[0], cidr_block="10.0.0.128/26", vpc_id=vpc.vpc_id, map_public_ip_on_launch=False)
        pri_subnetB = ec2.Subnet(
            self, "private-subnetB", availability_zone=super().availability_zones[0], cidr_block="10.0.0.192/26", vpc_id=vpc.vpc_id, map_public_ip_on_launch=False)

        # instantiate NAT gateway
        nat_gateway = ec2.CfnNatGateway(
            self, "nat_gateway", allocation_id=eip.attr_allocation_id, subnet_id=pub_subnetA.subnet_vpc_id)

        # instantiate routing tables
        pub_route_table = ec2.CfnRouteTable(
            self, "pub_route_table", vpc_id=vpc.vpc_id)
        pri_route_table = ec2.CfnRouteTable(
            self, "pri_route_table", vpc_id=vpc.vpc_id)

        # instantiate public and private routes
        pub_route = ec2.CfnRoute(self, "pub_route", route_table_id=pub_route_table.attr_route_table_id,
                                 destination_cidr_block="0.0.0.0/0", gateway_id=igw.attr_internet_gateway_id)
        pri_route = ec2.CfnRoute(self, "pri_route", route_table_id=pri_route_table.attr_route_table_id,
                                 destination_cidr_block="0.0.0.0/0", nat_gateway_id=nat_gateway.ref)

        # instantiate subnet route table associations
        pub_subnetA_route_table_association = ec2.CfnSubnetRouteTableAssociation(
            self, "pub_subnetA_route_table_association", route_table_id=pub_route_table.attr_route_table_id, subnet_id=pub_subnetA.subnet_vpc_id)
        pub_subnetB_route_table_association = ec2.CfnSubnetRouteTableAssociation(
            self, "pub_subnetB_route_table_association", route_table_id=pub_route_table.attr_route_table_id, subnet_id=pub_subnetB.subnet_vpc_id)
        pri_subnetA_route_table_association = ec2.CfnSubnetRouteTableAssociation(
            self, "pri_subnetA_route_table_association", route_table_id=pri_route_table.attr_route_table_id, subnet_id=pri_subnetA.subnet_vpc_id)
        pri_subnetB_route_table_association = ec2.CfnSubnetRouteTableAssociation(
            self, "pri_subnetB_route_table_association", route_table_id=pri_route_table.attr_route_table_id, subnet_id=pri_subnetB.subnet_vpc_id)

        security_group = ec2.SecurityGroup(self, "security_group", vpc=vpc)
        security_group.add_ingress_rule(
            ec2.Peer.ipv4("0.0.0.0/0"), ec2.Port.tcp(22))

        ec2_instance = ec2.Instance(self, "EC2", instance_type=ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.MICRO), machine_image=ec2.MachineImage.latest_amazon_linux(),
                                    key_name="RandomKeyName", security_group=security_group, vpc=vpc, vpc_subnets=pri_subnetA)

No sé cómo resolver este problema, ya que es evidente que se deben utilizar solamente los bloques CIDR una vez. Pero no es así.

EDIT: ahora estoy incluyendo un enlace a la plantilla de CloudFormation de salida en respuesta a un comentario. He notado que este problema de conflicto sólo parece ocurrir con public_subnetA y private_subnetA. Yo todavía no entiendo por qué esto está ocurriendo.

EDIT 2: he intentado siguientes maafk la sugerencia y la reducción de mi código a la siguiente. Quiero mantener el 2 públicas y privadas configuración de subred, pero ahora no puedo conectar a mi instancia de EC2 no importa lo que yo trato. ¿Por qué es algo que se puede conseguir fácilmente en Terraformar tan innecesariamente difícil de hacer en AWS CDK, y mucho menos en Python?

from aws_cdk import core as cdk
from aws_cdk import aws_ec2 as ec2

class HelloCdkStack(cdk.Stack):

    def __init__(self, scope: cdk.Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)
        vpc = ec2.Vpc(self, "vpc-cf",
                      cidr="10.0.0.0/24",
                      enable_dns_support=True,
                      enable_dns_hostnames=True,
                      nat_gateways=1,
                      max_azs=1,
                      subnet_configuration=[ec2.SubnetConfiguration(
                          name="public-subnetA",
                          cidr_mask=26,
                          subnet_type=ec2.SubnetType.PUBLIC
                      ), ec2.SubnetConfiguration(
                          name="public-subnetB",
                          cidr_mask=26,
                          subnet_type=ec2.SubnetType.PUBLIC
                      ), ec2.SubnetConfiguration(
                          name="private-subnetA",
                          cidr_mask=26,
                          subnet_type=ec2.SubnetType.PRIVATE
                      ), ec2.SubnetConfiguration(
                          name="private-subnetB",
                          cidr_mask=26,
                          subnet_type=ec2.SubnetType.PRIVATE)]
                      )

        ec2_instance = ec2.Instance(self, "EC2", instance_type=ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.MICRO), machine_image=ec2.MachineImage.latest_amazon_linux(
        ), key_name="KeyPairRandom", vpc=vpc, vpc_subnets=vpc.select_subnets(subnet_type=ec2.SubnetType.PUBLIC).subnets[0])

        ec2_instance.connections.allow_from_any_ipv4(
            ec2.Port.tcp(22), 'Allow inbound SSH from anywhere')
1

Mejor respuesta

1

Vas a añadir mucho más código del necesario.

La creación de una VPC con CDK ya se ocupa de la mayor parte de esto para usted

Desde el docs

Una VPC predeterminada configuración creará público y privado subredes

Aquí está una más "CDK modo nativo" para escribir esto.

from aws_cdk import core as cdk
from aws_cdk import aws_ec2 as ec2

class CdkWorkshop3Stack(cdk.Stack):

    def __init__(self, scope: cdk.Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        vpc = ec2.Vpc(self, "vpc-cf",
            cidr="10.0.0.0/24",
            # dns hostnames and support enabled by default
        )

        ec2_instance = ec2.Instance(self, "EC2", 
            instance_type=ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.MICRO), machine_image=ec2.MachineImage.latest_amazon_linux(),
            key_name="RandomKeyName", 
            vpc=vpc,
            # PRIVATE subnets are chosen by default
        )
        # Not a great security practice to open ssh to the world, but can do it this way
        ec2_instance.connections.allow_from_any_ipv4(ec2.Port.tcp(22), 'Allow inbound SSH from anywhere')

Mucho menos código, y el uso de la información "sensible" valores predeterminados que vienen con CDK

2021-11-20 12:31:11

¿Cómo puedo hacer es elegir una subred pública. Creo que las subredes privadas por defecto se me va no se puede conectar a mi ejemplo a través de SSH.
Karma Cool

Retirar la documentación en la Vpc construir.
gshpychka

La mejor opción para SSH es el uso de la SSM administrador de Sesión (instalado por defecto en Amazon Linux), o utilizar un bastión host en una subred pública. Si usted absolutamente debe crear la instancia en una subred pública, puede agregar vpc_subnets=vpc.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC) a la ec2.Instance parámetros
maafk

En otros idiomas

Esta página está en otros idiomas

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Slovenský
..................................................................................................................