AWS CDK Python - 在堆栈之间传递多个变量
AWS CDK Python - Passing multiple variables between Stacks
背景
我的 CDK 应用程序中有两个堆栈。一种是定义 Network Constructs(如 VPC、Security Groups 等)的 Stack,一种是负责创建 EKS 集群的 Stack。作为集群配置过程的一部分,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)
现在,集群堆栈需要使用此处创建的几个变量。具体来说,它需要能够访问 kubernetes_vpc
、public/control/worker subnets
和 public/control/workerplane security groups
在同一个区域,同一个账户,同一个 CDK environment
我有另一个 Stack,Cluster Stack:
集群堆栈:
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],
)
)
官方documentation为了从StackB访问StackA的bucket,使用了在Stacks之间共享一个bucket的例子。他们通过在堆栈之间传递对象来做到这一点。这意味着我需要为我正在寻找的每个变量创建一个参数,以便在 Stacks 之间传递它。有没有更简单的方法?
我尝试将实际的 NetworkingStack 传递给 ClusterStack:
class ClusterStack(Stack):
def __init__(self, scope: Construct, id: str, MyNetworkStack, **kwargs) -> None:
super().__init__(scope, id, **kwargs)
然后在 app.py:
NetworkingStack(app, "NetworkingStack", MyCidr="10.40.0.0/16")
ClusterStack(app, "ClusterStack", MyNetworkStack=NetworkingStack)
但是当我将 NetworkingStack 中的变量作为属性引用时,这似乎不起作用,例如security_group=MyNetworkStack.controlplane_security_group
。我得到的错误通常与这个变量有关 AttributeError: type object 'NetworkingStack' has no attribute 'controlplane_security_group'
问题:
在堆栈之间传递多个变量而不必将每个变量都定义为参数的最佳方法是什么?
步骤 1
将您想要引用的任何变量更改为 NetworkStack 的属性 class。
所以,而不是:
controlplane_security_group = ec2.SecurityGroup(self, "ControlPlaneSecurityGroup", vpc=kubernetes_vpc)
你应该这样做:
self.controlplane_security_group = ec2.SecurityGroup(self, "ControlPlaneSecurityGroup", vpc=kubernetes_vpc)
第 2 步
您需要传递对象,而不是传递 class。
所以,而不是:
NetworkingStack(app, "NetworkingStack", MyCidr="10.40.0.0/16")
ClusterStack(app, "ClusterStack", MyNetworkStack=NetworkingStack)
你应该这样做:
networking_stack = NetworkingStack(app, "NetworkingStack", MyCidr="10.40.0.0/16")
ClusterStack(app, "ClusterStack", MyNetworkStack=networking_stack)
现在 MyNetworkStack.controlplane_security_group
可以正常工作了。
我还建议再进行一项更改,即将名称 MyNetworkStack
更改为 my_network_stack
,因为根据 PEP8 这是方法参数名称的一般 Python 约定.
背景
我的 CDK 应用程序中有两个堆栈。一种是定义 Network Constructs(如 VPC、Security Groups 等)的 Stack,一种是负责创建 EKS 集群的 Stack。作为集群配置过程的一部分,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)
现在,集群堆栈需要使用此处创建的几个变量。具体来说,它需要能够访问 kubernetes_vpc
、public/control/worker subnets
和 public/control/workerplane security groups
在同一个区域,同一个账户,同一个 CDK environment
我有另一个 Stack,Cluster Stack:
集群堆栈:
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],
)
)
官方documentation为了从StackB访问StackA的bucket,使用了在Stacks之间共享一个bucket的例子。他们通过在堆栈之间传递对象来做到这一点。这意味着我需要为我正在寻找的每个变量创建一个参数,以便在 Stacks 之间传递它。有没有更简单的方法?
我尝试将实际的 NetworkingStack 传递给 ClusterStack:
class ClusterStack(Stack):
def __init__(self, scope: Construct, id: str, MyNetworkStack, **kwargs) -> None:
super().__init__(scope, id, **kwargs)
然后在 app.py:
NetworkingStack(app, "NetworkingStack", MyCidr="10.40.0.0/16")
ClusterStack(app, "ClusterStack", MyNetworkStack=NetworkingStack)
但是当我将 NetworkingStack 中的变量作为属性引用时,这似乎不起作用,例如security_group=MyNetworkStack.controlplane_security_group
。我得到的错误通常与这个变量有关 AttributeError: type object 'NetworkingStack' has no attribute 'controlplane_security_group'
问题:
在堆栈之间传递多个变量而不必将每个变量都定义为参数的最佳方法是什么?
步骤 1
将您想要引用的任何变量更改为 NetworkStack 的属性 class。
所以,而不是:
controlplane_security_group = ec2.SecurityGroup(self, "ControlPlaneSecurityGroup", vpc=kubernetes_vpc)
你应该这样做:
self.controlplane_security_group = ec2.SecurityGroup(self, "ControlPlaneSecurityGroup", vpc=kubernetes_vpc)
第 2 步
您需要传递对象,而不是传递 class。
所以,而不是:
NetworkingStack(app, "NetworkingStack", MyCidr="10.40.0.0/16")
ClusterStack(app, "ClusterStack", MyNetworkStack=NetworkingStack)
你应该这样做:
networking_stack = NetworkingStack(app, "NetworkingStack", MyCidr="10.40.0.0/16")
ClusterStack(app, "ClusterStack", MyNetworkStack=networking_stack)
现在 MyNetworkStack.controlplane_security_group
可以正常工作了。
我还建议再进行一项更改,即将名称 MyNetworkStack
更改为 my_network_stack
,因为根据 PEP8 这是方法参数名称的一般 Python 约定.