AWS CDK Python - SubnetSelection 和 ISubnet 对象
AWS CDK Python - SubnetSelection and ISubnet objects
背景
我正在尝试使用 AWS CDK 在 Python 中使用 Cluster 对象创建 EKS 集群。
我有一个构建网络对象(例如 VPC 和子网)的堆栈。该堆栈定义了三种“类型”的子网:
- 控制子网组 - 包含 EKS ENI
- 一个工作子网组 - 包含工作节点组
- 一个 public 子网组 - 使用 public 路由表并将负责 ALB 等
定义该信息的代码如下。这来自我的网络堆栈:
# Define the number of subnets to create in a for loop later on. This will be a shared value between the worker, control, and public subnets.
subnet_count = range(1,3)
# Create empty lists for each of our subnet types. These will hold our SubnetConfigurations that are passed to VPC creation
self.public_subnets = []
self.worker_subnets = []
self.control_subnets = []
# Loop through our defined range above, creating the appropriate control, worker, and public subnets, aligning to CIDRs above
for x in subnet_count:
x = str(x)
self.control_subnets.append(ec2.SubnetConfiguration(
name = 'Control-0{}'.format(x),
cidr_mask=28,
subnet_type = ec2.SubnetType.PRIVATE_WITH_NAT,
reserved = False
))
self.worker_subnets.append(ec2.SubnetConfiguration(
name = 'Worker-0{}'.format(x),
cidr_mask=24,
subnet_type = ec2.SubnetType.PRIVATE_WITH_NAT,
reserved = False
))
self.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
))
然后我通过解压缩那些 SubnetConfiguration 列表来创建一个用于 EKS 的 VPC:
self.kubernetes_vpc = ec2.Vpc(self,
"Kubernetes",
cidr=my_cidr,
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=[*self.public_subnets,*self.control_subnets,*self.worker_subnets],
vpc_name="Kubernetes",
vpn_connections=None
)
我将此堆栈传递给 EKS 集群堆栈,引用为 my_network_stack
所以我现在要做的是使用 ec2.SubnetSelection
的 subnet_group_name
参数明确调用在另一个堆栈中创建的控制子网的名称,然后将其移交到 EKS 堆栈中 Cluster
的 vpc_subnets
参数。
self.control_subnets = []
for subnet_config in my_network_stack.control_subnets:
self.selected_subnets = my_network_stack.kubernetes_vpc.select_subnets(subnet_group_name=subnet_config.name).subnets
my_network_stack.control_subnets
是先前在网络堆栈中定义的 self.control_subnets
。
这应该给我一个根据控制子网组名称正确选择的 ISubnet 对象列表,我在这里设置了一个简单的测试:
for item in self.selected_subnets:
logging.debug(type(item))
哪个returns
DEBUG:root:<class 'aws_cdk.aws_ec2.PrivateSubnet'>
DEBUG:root:<class 'aws_cdk.aws_ec2.PrivateSubnet'>
那些是 ISubnet 对象,对吗?
方法一
我第一次尝试让它工作是为特定列表提供一个解包器,它应该是一组 ISubnet 对象(截断的集群参数):
self.Cluster = eks.Cluster(
vpc_subnets = [
ec2.SubnetSelection(subnets=[*self.selected_subnets])
]
这给了我错误:
jsii.errors.JSIIError: Expected object reference, got "latest"
不完全确定我做错了什么。我已经尝试了一些关于传递正确的 ISubnet 对象列表的变体,即使我专门调用了数组索引:
vpc_subnets = [
ec2.SubnetSelection(subnets=[self.selected_subnets[0], self.selected_subnets[1]])
]
但出现同样的错误。
方法二
使用实际的 SubnetSelection
函数获取 ISubnet 对象列表:
vpc_subnets = [
ec2.SubnetSelection(subnets=
[my_network_stack.kubernetes_vpc.select_subnets(subnet_group_name=self.control_subnet_names[0]).subnets, my_network_stack.kubernetes_vpc.select_subnets(subnet_group_name=self.control_subnet_names[1])])
]
这给了我错误:
jsii.errors.JSIIError: Expected object reference, got [{"$jsii.byref":"aws-cdk-lib.aws_ec2.PrivateSubnet@10011"},{"$jsii.byref":"aws-cdk-lib.aws_ec2.PrivateSubnet@10012"}]
这看起来可能是具有实际 ISubnet 对象的字典引用列表,在这种情况下,不确定它比引用实际对象的方法 1 有何优势。
pip freeze
的输出:
$ pip freeze
attrs==21.4.0
aws-cdk-lib==2.8.0
cattrs==1.10.0
constructs==10.0.37
jsii==1.52.1
publication==0.0.3
python-dateutil==2.8.2
six==1.16.0
typing-extensions==4.0.1
更新:解决方案
正如回答者所指出的,这个错误expected object, got 'latest'
与集群创建语句中的ALB版本有关,与传入的子网无关。一直以来都是这个问题。我在下面包含了那个(损坏的)代码:
self.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=my_network_stack.controlplane_security_group,
vpc=my_network_stack.kubernetes_vpc,
vpc_subnets=
[
ec2.SubnetSelection(subnets=self.selected_subnets)
],
)
此外,这并不能解决传入子网的问题,但我最终能够让这段代码工作。这里的关键是 select_subnets(subnet_group_name=subnet_config
returns 一个 ISubnet 对象列表,所以你把它分成对象,然后把它解压到集群的 vpc_subnets
:
for subnet_config in my_network_stack.control_subnets:
for item in my_network_stack.kubernetes_vpc.select_subnets(subnet_group_name=subnet_config.name).subnets:
self.selected_subnets.append(item)
# Later, during cluster creation:
vpc_subnets=
[
ec2.SubnetSelection(subnets=[*self.selected_subnets])
]
我只能让上面的方法起作用,传入列表对象的组合(SubnetSelection(subnets=[]) 需要一个列表)会导致语法错误。
以下情况正常,不是问题的原因:
self.Cluster = eks.Cluster(
vpc_subnets = [SubnetSelection(subnets=selected_subnets)]
问题的原因是您在聊天中提供的 Cluster
初始化中的以下行:
alb_controller=eks.AlbControllerOptions(version="latest")
version
parameter of the AlbControllerOptions
expects an instance of AlbControllerVersion
,不是字符串。
正确的代码是:
alb_controller=eks.AlbControllerOptions(version=eks.AlbControllerVersion.V2_3_1),
背景
我正在尝试使用 AWS CDK 在 Python 中使用 Cluster 对象创建 EKS 集群。
我有一个构建网络对象(例如 VPC 和子网)的堆栈。该堆栈定义了三种“类型”的子网:
- 控制子网组 - 包含 EKS ENI
- 一个工作子网组 - 包含工作节点组
- 一个 public 子网组 - 使用 public 路由表并将负责 ALB 等
定义该信息的代码如下。这来自我的网络堆栈:
# Define the number of subnets to create in a for loop later on. This will be a shared value between the worker, control, and public subnets.
subnet_count = range(1,3)
# Create empty lists for each of our subnet types. These will hold our SubnetConfigurations that are passed to VPC creation
self.public_subnets = []
self.worker_subnets = []
self.control_subnets = []
# Loop through our defined range above, creating the appropriate control, worker, and public subnets, aligning to CIDRs above
for x in subnet_count:
x = str(x)
self.control_subnets.append(ec2.SubnetConfiguration(
name = 'Control-0{}'.format(x),
cidr_mask=28,
subnet_type = ec2.SubnetType.PRIVATE_WITH_NAT,
reserved = False
))
self.worker_subnets.append(ec2.SubnetConfiguration(
name = 'Worker-0{}'.format(x),
cidr_mask=24,
subnet_type = ec2.SubnetType.PRIVATE_WITH_NAT,
reserved = False
))
self.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
))
然后我通过解压缩那些 SubnetConfiguration 列表来创建一个用于 EKS 的 VPC:
self.kubernetes_vpc = ec2.Vpc(self,
"Kubernetes",
cidr=my_cidr,
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=[*self.public_subnets,*self.control_subnets,*self.worker_subnets],
vpc_name="Kubernetes",
vpn_connections=None
)
我将此堆栈传递给 EKS 集群堆栈,引用为 my_network_stack
所以我现在要做的是使用 ec2.SubnetSelection
的 subnet_group_name
参数明确调用在另一个堆栈中创建的控制子网的名称,然后将其移交到 EKS 堆栈中 Cluster
的 vpc_subnets
参数。
self.control_subnets = []
for subnet_config in my_network_stack.control_subnets:
self.selected_subnets = my_network_stack.kubernetes_vpc.select_subnets(subnet_group_name=subnet_config.name).subnets
my_network_stack.control_subnets
是先前在网络堆栈中定义的 self.control_subnets
。
这应该给我一个根据控制子网组名称正确选择的 ISubnet 对象列表,我在这里设置了一个简单的测试:
for item in self.selected_subnets:
logging.debug(type(item))
哪个returns
DEBUG:root:<class 'aws_cdk.aws_ec2.PrivateSubnet'>
DEBUG:root:<class 'aws_cdk.aws_ec2.PrivateSubnet'>
那些是 ISubnet 对象,对吗?
方法一
我第一次尝试让它工作是为特定列表提供一个解包器,它应该是一组 ISubnet 对象(截断的集群参数):
self.Cluster = eks.Cluster(
vpc_subnets = [
ec2.SubnetSelection(subnets=[*self.selected_subnets])
]
这给了我错误:
jsii.errors.JSIIError: Expected object reference, got "latest"
不完全确定我做错了什么。我已经尝试了一些关于传递正确的 ISubnet 对象列表的变体,即使我专门调用了数组索引:
vpc_subnets = [
ec2.SubnetSelection(subnets=[self.selected_subnets[0], self.selected_subnets[1]])
]
但出现同样的错误。
方法二
使用实际的 SubnetSelection
函数获取 ISubnet 对象列表:
vpc_subnets = [
ec2.SubnetSelection(subnets=
[my_network_stack.kubernetes_vpc.select_subnets(subnet_group_name=self.control_subnet_names[0]).subnets, my_network_stack.kubernetes_vpc.select_subnets(subnet_group_name=self.control_subnet_names[1])])
]
这给了我错误:
jsii.errors.JSIIError: Expected object reference, got [{"$jsii.byref":"aws-cdk-lib.aws_ec2.PrivateSubnet@10011"},{"$jsii.byref":"aws-cdk-lib.aws_ec2.PrivateSubnet@10012"}]
这看起来可能是具有实际 ISubnet 对象的字典引用列表,在这种情况下,不确定它比引用实际对象的方法 1 有何优势。
pip freeze
的输出:
$ pip freeze
attrs==21.4.0
aws-cdk-lib==2.8.0
cattrs==1.10.0
constructs==10.0.37
jsii==1.52.1
publication==0.0.3
python-dateutil==2.8.2
six==1.16.0
typing-extensions==4.0.1
更新:解决方案
正如回答者所指出的,这个错误expected object, got 'latest'
与集群创建语句中的ALB版本有关,与传入的子网无关。一直以来都是这个问题。我在下面包含了那个(损坏的)代码:
self.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=my_network_stack.controlplane_security_group,
vpc=my_network_stack.kubernetes_vpc,
vpc_subnets=
[
ec2.SubnetSelection(subnets=self.selected_subnets)
],
)
此外,这并不能解决传入子网的问题,但我最终能够让这段代码工作。这里的关键是 select_subnets(subnet_group_name=subnet_config
returns 一个 ISubnet 对象列表,所以你把它分成对象,然后把它解压到集群的 vpc_subnets
:
for subnet_config in my_network_stack.control_subnets:
for item in my_network_stack.kubernetes_vpc.select_subnets(subnet_group_name=subnet_config.name).subnets:
self.selected_subnets.append(item)
# Later, during cluster creation:
vpc_subnets=
[
ec2.SubnetSelection(subnets=[*self.selected_subnets])
]
我只能让上面的方法起作用,传入列表对象的组合(SubnetSelection(subnets=[]) 需要一个列表)会导致语法错误。
以下情况正常,不是问题的原因:
self.Cluster = eks.Cluster(
vpc_subnets = [SubnetSelection(subnets=selected_subnets)]
问题的原因是您在聊天中提供的 Cluster
初始化中的以下行:
alb_controller=eks.AlbControllerOptions(version="latest")
version
parameter of the AlbControllerOptions
expects an instance of AlbControllerVersion
,不是字符串。
正确的代码是:
alb_controller=eks.AlbControllerOptions(version=eks.AlbControllerVersion.V2_3_1),