背景
我正试图使用AWS CDK在Python中创建一个带有Cluster对象的EKS Cluster。
我有一个Stack,它构造了诸如VPCs和Subnets之类的网络对象。该Stack定义了三个";"类型";子网数:
- 控制子网组-包含EKS ENI
- 工作子网组-包含工作节点组
- 公共子网组-使用公共路由表,并负责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
))
然后我创建了一个VPC,用于EKS,通过打开这些SubnetConfiguration列表:
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))
返回
DEBUG:root:<class 'aws_cdk.aws_ec2.PrivateSubnet'>
DEBUG:root:<class 'aws_cdk.aws_ec2.PrivateSubnet'>
这些是ISubnet对象,对吗?
方法1
我的第一次尝试是为特定列表提供一个解包器,该列表应该是一组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]])
]
但是发生了相同的错误。
方法2
使用实际的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
返回一个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")
AlbControllerOptions
的version
参数需要AlbControllerVersion
的实例,而不是字符串。
正确的代码是:
alb_controller=eks.AlbControllerOptions(version=eks.AlbControllerVersion.V2_3_1),