AWS CDK Python - 在堆栈之间传递多个变量

Pat*_*ick 7 python python-3.7 aws-cdk

背景

我的 CDK 应用程序中有两个 Stack。一种是定义网络构造(例如 VPC、安全组等)的堆栈,另一种是负责创建 EKS 集群的堆栈。作为集群配置过程的一部分,EKS 集群需要能够使用网络堆栈的变量和输出。示例如下:

网络堆栈:

class NetworkingStack(Stack):
   def __init__(self, scope: Construct, id: str, MyCidr,**kwargs) -> None:
       super().__init__(scope, id)

       subnet_count = range(1,3)
       public_subnets = []
       worker_subnets = []
       control_subnets = []

       for x in subnet_count:
           x = str(x)
           control_subnets.append(ec2.SubnetConfiguration(
               name = 'Control-0{}'.format(x),
               cidr_mask=28,
               subnet_type = ec2.SubnetType.PRIVATE_WITH_NAT,
               reserved = False
           ))
           worker_subnets.append(ec2.SubnetConfiguration(
               name = 'Worker-0{}'.format(x),
               cidr_mask=24,
               subnet_type = ec2.SubnetType.PRIVATE_WITH_NAT,
               reserved = False
           ))
           public_subnets.append(ec2.SubnetConfiguration(
               name = 'Public-0{}'.format(x),
               cidr_mask=27,
               map_public_ip_on_launch=True,
               subnet_type = ec2.SubnetType.PUBLIC,
               reserved = False
           ))

       kubernetes_vpc = ec2.Vpc(self, 
       "Kubernetes", 
       cidr=MyCidr,
       default_instance_tenancy=ec2.DefaultInstanceTenancy.DEFAULT,
       enable_dns_hostnames=True,
       enable_dns_support=True,
       flow_logs=None,
       gateway_endpoints=None,
       max_azs=2,
       nat_gateway_provider=ec2.NatProvider.gateway(),
       nat_gateways=1, # this is 1 PER AZ
       subnet_configuration=[*public_subnets,*control_subnets,*worker_subnets],
       vpc_name="Kubernetes",
       vpn_connections=None
       )
       

       controlplane_security_group = ec2.SecurityGroup(self, "ControlPlaneSecurityGroup", vpc=kubernetes_vpc)
       workerplane_security_group = ec2.SecurityGroup(self, "WorkerPlaneSecurityGroup", vpc=kubernetes_vpc) 
       public_security_group = ec2.SecurityGroup(self, "PublicPlaneSecurityGroup", vpc=kubernetes_vpc)
Run Code Online (Sandbox Code Playgroud)

现在,集群堆栈需要使用此处创建的几个变量。具体来说,它需要能够访问kubernetes_vpcpublic/control/worker subnetspublic/control/workerplane security groups

在同一区域、同一帐户、同一 CDK 中,environment我有另一个堆栈,即集群堆栈:

集群堆栈:

        cluster = eks.Cluster(
            self,
            "InfrastructureCluster",
            default_capacity_type=eks.DefaultCapacityType.NODEGROUP,
            alb_controller=eks.AlbControllerOptions(version="latest"),
            endpoint_access=eks.EndpointAccess.PUBLIC_AND_PRIVATE,
            version=eks.KubernetesVersion.V1_21,
            cluster_name="InfrastructureCluster",
            security_group=MyNetworkStack.controlplane_security_group,
            vpc=MyNetworkStack.kubernetes_vpc,
            vpc_subnets=ec2.SubnetSelection(
                subnets=[*MyNetworkStack.control_subnets, *MyNetworkStack.worker_subnets, *MyNetworkStack.public_subnets],
            )
        )
Run Code Online (Sandbox Code Playgroud)

官方文档使用了Stack之间共享bucket的示例,以便从StackB访问StackAbucket。他们通过在堆栈之间传递对象来实现这一点。这意味着我需要为每个变量创建一个参数,以便在堆栈之间传递它。有更容易的方法吗?

我尝试将实际的 NetworkingStack 传递到 ClusterStack,如下所示:

class ClusterStack(Stack):
    def __init__(self, scope: Construct, id: str, MyNetworkStack, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)
Run Code Online (Sandbox Code Playgroud)

然后在app.py中:

NetworkingStack(app, "NetworkingStack", MyCidr="10.40.0.0/16")
ClusterStack(app, "ClusterStack", MyNetworkStack=NetworkingStack)
Run Code Online (Sandbox Code Playgroud)

但是当我将 NetworkingStack 中的变量引用为属性时,这似乎不起作用,例如security_group=MyNetworkStack.controlplane_security_group。我得到的错误通常与这个变量特别相关AttributeError: type object 'NetworkingStack' has no attribute 'controlplane_security_group'

问题:

在堆栈之间传递多个变量而不必将每个变量定义为参数的最佳方法是什么?

Kau*_*kar 6

步骤1

将您想要引用的任何变量更改为 NetworkStack 类的属性。

所以,而不是:

controlplane_security_group = ec2.SecurityGroup(self, "ControlPlaneSecurityGroup", vpc=kubernetes_vpc)
Run Code Online (Sandbox Code Playgroud)

你应该做:

self.controlplane_security_group = ec2.SecurityGroup(self, "ControlPlaneSecurityGroup", vpc=kubernetes_vpc)
Run Code Online (Sandbox Code Playgroud)

第2步

您需要传递对象,而不是传递类。

所以,而不是:

NetworkingStack(app, "NetworkingStack", MyCidr="10.40.0.0/16")
ClusterStack(app, "ClusterStack", MyNetworkStack=NetworkingStack)
Run Code Online (Sandbox Code Playgroud)

你应该做:

networking_stack = NetworkingStack(app, "NetworkingStack", MyCidr="10.40.0.0/16")
ClusterStack(app, "ClusterStack", MyNetworkStack=networking_stack)
Run Code Online (Sandbox Code Playgroud)

现在MyNetworkStack.controlplane_security_group可以正常工作了。

我还建议再进行一项更改,即将名称更改MyNetworkStackmy_network_stack,因为这是根据PEP8 的方法参数名称的一般 Python 约定。