VPC-ENI指定子网分配IP
概览
VPC-ENI容器网络模式支持指定子网为Pod分配IP,用户可以使用这个能力为不同的业务应用Pod规划分配不同子网的IP地址。
需求场景
需求场景1:指定子网动态分配IP
从与Pod匹配的子网拓扑约束策略关联的子网中动态为Pod分配IP。匹配了子网拓扑约束策略(psts
)的所有Pod只从策略包含的子网分配IP地址。
需求场景2:指定多个子网动态分配IP
指定多个子网动态分配IP是对需求场景1指定子网动态分配IP的功能补充,弥补了一个应用所有Pod都调度到同一个子网(可用区)对应用可用性可能导致的负面效果。
需求场景3:手动分配固定Pod IP
手动分配固定Pod IP策略的含义是给定一个IP列表,CCE从这个IP列表中给有状态负载的Pod分配IP。Pod删除后IP地址保留,Pod重建或者迁移后,IP地址仍然不变。
需求场景4: 指定子网手动分配IP
指定子网手动分配IP地址策略的含义是给定一个IP列表,CCE仅从这个IP列表中分配IP地址给Pod。Pod 删除后IP地址即回收,回收后可以给下一个符合策略的Pod使用。
需求场景5:namespace级多子网动态IP分配策略
作为namespace的默认Pod IP 地址分配策略,对namespace下所有Pod都生效。
方案概述
如下CRD数据结构所示,CCE提供了自定义CRD来指定Pod子网拓扑分布策略,用于在CCE集群中实施制定子网分配IP功能。
关键数据结构介绍
Pod 子网拓扑分布表 PodSubnetTopologySpreadTable
Pod子网拓扑分布表,用于在一个命名空间有多个Pod子网拓扑分布对象时,通过表格的形式更加清晰的组织多个子对象的优先级排序。每个namespace下只能有一个名为default
的 PodSubnetTopologySpreadTable
对象,这个对象会创建多个PodSubnetTopologySpread
子对象。Pod子网拓扑分布表核心数据结构如下:
apiVersion: cce.io/v1alpha1
kind: PodSubnetTopologySpreadTable
metadata:
name: pstt-test
spec:
# 拓扑分布表可以包含多个Pod子网拓扑分布对象
- name: fixed-ip-psts-test
subnets:
sbn-6mrkdcsyzpaw:
type: Fixed
releaseStrategy: Never
ipv4:
- 10.88.11.4
- 10.88.11.5
- 10.88.11.6
priority: 10
selector:
matchLabels:
workloadType: sts
fixedIP: "true"
app: fixedIPApp
- name: fixed-ip-psts-ttl
subnets:
sbn-6mrkdcsyzpaw:
type: Fixed
releaseStrategy: TTL
ipv4:
- 10.88.11.10
- 10.88.11.11
- 10.88.11.12
- 10.88.11.13
priority: 10
selector:
matchLabels:
workloadType: sts
fixedIP: "true"
app: fixedIPAppTTL
把多个PodSubnetTopologySpread
对象存放到一个PodSubnetTopologySpreadTable
表中的收益是更容易理解多个拓扑分布对象的优先级顺序。PodSubnetTopologySpread.spec.priority
字段可以指定多个子网拓扑分布约束之间的优先级,数据越大优先级越高,默认值是0.
Pod子网拓扑分布 PodSubnetTopologySpread
子网拓扑分布对象是指定子网分配IP的核心工作对象,它的核心数据结构定义如下:
apiVersion: cce.io/v1alpha1
kind: PodSubnetTopologySpread
metadata:
name: example-subnet-topology
namespace: default
spec:
# 拓扑分布对象名
name: example-subnet-topology
# 多个子网拓扑约束之间的优先级,数字越大,优先级越高。默认值0
priority: 0
subnets:
# 必须是与当前集群同VPC的子网ID,格式为sbn-*例如sbn-ccfud13pwcqf
# 使用专属子网,用户要确认该子网只有当前CCE集群使用
sbn-ccfud13pwcqf:
# 固定IP分配模式。
type: Fixed
# 该字段仅当固定IP模式下生效,固定IP模式下可在删除Pod后继续保留IP
releaseStrategy: Never
# 固定指定某几个ip地址
ipv4:
- 10.0.0.1
# 指定用于分配IP地址的区间,与ipv4两者只能选择其一
ipv4Range:
- 10.0.0.1/24
# 选择要使用该子网拓扑分布的Pod
selector:
matchLabels:
app: foo
# 启用pod拓扑分布控制
enablePodTopologySpread: true
# 多子网拓扑逻辑分布策略下在不同可用区的最大差异
maxSkew: 1
# 不满足拓扑分布时的策略
# DoNotSchedule: 默认选项,调度器不对该Pod调度
# ScheduleAnyway: 调度器继续对该Pod调度
whenUnsatisfiable: DoNotSchedule
该对象的核心字段如下:
域 | 数据类型 | 必须 | 默认值 | 描述 |
---|---|---|---|---|
name |
string |
拓扑分布对象名,在通过 PodSubnetTopologySpreadTable 创建子网拓扑分布时必填。 |
||
priority |
int32 |
否 | 0 | 多个子网拓扑约束之间的优先级,数字越大,优先级越高。 |
selector |
object |
否 | 使用该条件对Pod做标签匹配,符合条件的Pod将在分配IP地址时使用该规则。如果selector 为空,则同namespace下的所有Pod都匹配该规则。 |
|
subnets |
object |
是 | 策略要使用的子网。CCE会从这些子网中为Pod分配IP地址。 | |
subnets.type |
string |
否 | Elastic |
IP分配模式,可有以下三个取值:Elastic :在通用子网下动态分配IP;Fixed :在专属子网下为Pod绑定固定IP;Manual :在专属子网下,为Pod手动分配IP; |
subnets.releaseStrategy |
string |
否 | TTL |
Pod 删除后,IP地址的回收策略:TTL : Pod 删除后,IP地址在第一个gc周期被回收;Never :Pod删除后,IP地址会被保留,直到下次重建Pod重用; |
subnets.ipv4 |
[]string |
否 | 手动分配IP的地址列表,固定IP模式和手动管理IP模式需要该字段。 | |
subnets.ipv4Range |
[]string |
否 | 自动分配IP的地址列表,使用CIDR格式表示,如10.0.0.1/24 。该字段和ipv4 字段互斥。 |
|
subnets.enablePodTopologySpread |
bool |
否 | false |
是否开启Pod拓扑逻辑分布约束, Pod拓扑分布约束控制 Pod 在集群内故障域之间的分布,请参考Pod 拓扑分布约束。 |
subnets.maxSkew |
int32 |
否 | 1 |
描述 Pod 在多个子网关联的可用区可能被均匀分布的程度。你必须指定此字段且该数值必须大于零。 其语义将随着 whenUnsatisfiable 的值发生变化:如果你选择 whenUnsatisfiable: DoNotSchedule ,则 maxSkew 定义目标拓扑中匹配 Pod 的数量与 全局最小值(与拓扑域中标签选择算符匹配的最小 Pod 数量)之间的最大允许差值。 例如,如果你有 3 个可用区,分别有 2、4 和 5 个匹配的 Pod,则全局最小值为 2, 而 maxSkew 相对于该数字进行比较。如果你选择 whenUnsatisfiable: ScheduleAnyway ,则该调度器会更为偏向能够降低偏差值的拓扑域。 |
subnets.whenUnsatisfiable |
string |
否 | DoNotSchedule |
不满足maxSkew 拓扑分布时的策略:DoNotSchedule : 默认选项,调度器不对该Pod调度。ScheduleAnyway : 告诉调度器仍然继续调度,只是根据如何能将偏差最小化来对节点进行排序。 |
使用限制
- 该功能需使用VPC的ENI跨子网分配IP功能,请提交工单申请使用ENI跨子网分配IP功能。
kube-system
命名空间的Pod无法使用指定子网分配IP功能。- 使用
ipRange
能力时,注意IP范围内不要包含等特殊IP地址(如IPv4网络地址、网关地址、广播地址、多播地址),否则可能产生无法正常分配IP。 - 指定子网的Pod只能调度到子网所在可用区的节点,请确认可用区有Ready状态的节点。
- 固定IP和手动分配IP场景下只能使用专属子网(指定的子网只能供单个CCE集群使用),专属子网不支持变更为普通子网、不支持从集群内删除,详情见专属子网说明。
专属子网: 当用户需要为Pod分配指定子网下的某几个IP时,IP所属的子网将自动被标记为手动分配IP模式。手动分配IP模式下的子网有以下特征:
- 专属子网应为当前CCE集群专属,CCE会自动为子网增加专属标签,其它的CCE集群拒绝使用该子网。(用户可以操作百度云其它产品使用该子网)
- 对专属子网仅支持手动分配IP,不会自动分配IP。这需要用户自己管理IP地址规划
- 专属子网下IP和Pod的关系可以有优先分配和固定绑定两种。固定绑定策略使用Pod名作为绑定标识,同一个Pod名的IP地址相同
- 集群Pod的默认子网不能是专属子网,否则可能导致集群中的其它Pod无法正常分配IP
- 专属子网不支持变更为普通子网、不支持从集群内删除
配置步骤
环境准备
创建私有子网
在百度智能云VPC控制台->子网选项卡,为自己的VPC新建一个子网,并保存子网ID (以sbn-xxx
格式命名的是子网ID)。注意创建子网时应选择与CCE集群节点相关的可用区,否则可能导致调度失败。
说明: 如需使用ENI跨子网分配IP功能,请提交工单申请。
在CCE上操作指定子网分配IP
场景1: 指定子网动态分配IP
从与Pod匹配的子网拓扑约束策略关联的子网中动态为Pod分配IP。匹配了子网拓扑约束策略(psts
)的所有Pod只从策略包含的子网分配IP地址。
适用场景:
- 以子网维度对流量做统计
- 以子网维度做安全策略,如ACL规则控制
- 通过NAT网关为特定子网开启互联网访问
1. 创建psts
apiVersion: cce.io/v1alpha1
# pod 拓扑分布表
kind: PodSubnetTopologySpread
metadata:
name: default
namespace: default
spec:
# 多个子网拓扑约束之间的优先级,排序越靠前,优先级越大
priority: 0
name: default-psts
subnets:
# 必须是与当前集群同VPC的子网ID,格式为sbn-*例如sbn-ccfud13pwcqf
sbn-ccfud13pwcqf: {}
# 选择要使用该子网拓扑分布的pod
selector:
matchLabels:
app: foo
2. 创建工作负载
apiVersion: apps/v1
kind: Deployment
metadata:
name: elastic-deploy
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: foo
template:
metadata:
labels:
app: foo
spec:
containers:
- image: nginx
name: nginx
3. 验证IP分配结果
# kubectl get pod {podName} -oyaml
apiVersion: v1
kind: Pod
metadata:
annotations:
cce.baidubce.com/PodSubnetTopologySpread: example-subnet-topology
generateName: elastic-deploy-56dc49b486-
labels:
app: foo
name: elastic-deploy-56dc49b486-d6z7b
namespace: default
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- zoneF
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: nginx
resources:
limits:
cce.baidubce.com/ip: "1"
requests:
cce.baidubce.com/ip: "1"
场景2: 高级功能:指定多个子网动态分配IP
指定多个子网动态分配IP是对场景1(指定子网动态分配IP)的功能补充,弥补了一个应用所有Pod都调度到同一个子网(可用区)对应用可用性可能导致的负面效果。
使用场景:
- 应用要求分布在多个可用区,保证高可用
1. 创建 psts
apiVersion: cce.io/v1alpha1
kind: PodSubnetTopologySpread
metadata:
name: example-subnet-topology
namespace: default
spec:
# 多个子网拓扑约束之间的优先级,数字越大,优先级越高
priority: 0
subnets:
# # 必须是与当前集群同VPC的子网ID,格式为sbn-*例如sbn-ccfud13pwcqf
sbn-xcee24pjj0p1: {}
sbn-e8rk4zxn2ys6: {}
# 选择要使用该子网拓扑分布的pod
# 如果没有指定selector,同namespace下的所有Pod都会被匹配
selector:
matchLabels:
app: foo
# 启用pod拓扑分布控制
enablePodTopologySpread: true
# 多子网拓扑逻辑分布策略下在不同可用区的最大差异
maxSkew: 10
# 不满足拓扑分布时的策略度,在namespace场景下,推荐设置为 ScheduleAnyway
whenUnsatisfiable: ScheduleAnyway
2. 创建工作负载
apiVersion: apps/v1
kind: Deployment
metadata:
name: elastic-deploy
namespace: default
spec:
selector:
matchLabels:
app: foo
template:
spec:
containers:
- image: nginx
name: nginx
3. 验证IP分配结果
# kubectl get pod {podName} -oyaml
apiVersion: v1
kind: Pod
metadata:
annotations:
cce.baidubce.com/PodSubnetTopologySpread: example-subnet-topology
generateName: elastic-deploy-56dc49b486-
labels:
app: foo
name: elastic-deploy-56dc49b486-d6z7b
namespace: default
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
# pod 会自动对子网所属的可用区增加亲和性调度需求
- zoneF
- zoneC
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: nginx
resources:
limits:
cce.baidubce.com/ip: "1"
requests:
cce.baidubce.com/ip: "1"
场景3:手动分配固定Pod IP
手动分配固定Pod IP策略的含义是给定一个IP列表,CCE从这个IP列表中给有状态负载的Pod分配IP。Pod删除后IP地址保留,Pod重建或者迁移后,IP地址仍然不变。
适用场景:
- 固定Pod IP,要求Pod迁移后IP支持不变
- 使用专属子网,并完全手动管理该子网的IP
- 使用有状态工作负载(
apps/v1 StatefulSet
)
1. 创建 psts
apiVersion: cce.io/v1alpha1
kind: PodSubnetTopologySpread
metadata:
name: example-subnet-topology
namespace: default
spec:
priority: 0
subnets:
- sbn-6mrkdcsyzpaw:
type: Fixed
releaseStrategy: Never
ipv4:
- 10.88.11.4
- 10.88.11.5
- 10.88.11.6
priority: 10
selector:
matchLabels:
workloadType: sts
fixedIP: "true"
app: fixedIPApp
2. 创建工作负载
apiVersion: apps/v1
# 必须使用有状态工作负载
kind: StatefulSet
metadata:
name: foo
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: fixedIPApp
serviceName: foo
template:
metadata:
labels:
workloadType: sts
fixedIP: "true"
app: fixedIPApp
spec:
containers:
- image: nginx
name: nginx
3. 验证IP分配结果
# kubectl get pod {podName} -oyaml
apiVersion: v1
kind: Pod
metadata:
annotations:
cce.baidubce.com/PodSubnetTopologySpread: example-subnet-topology
labels:
app: foo
name: foo-0
namespace: default
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- zoneF
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: nginx
resources:
limits:
cce.baidubce.com/ip: "1"
requests:
cce.baidubce.com/ip: "1"
场景4:指定子网手动分配IP
指定子网手动分配IP地址策略的含义是给定一个IP列表,CCE仅从这个IP列表中分配IP地址给Pod。Pod 删除后IP地址即回收,回收后可以给下一个符合策略的Pod使用。
适用场景:
- 指定的子网必须是单个CCE集群使用,且该子网不再用于动态分配IP地址(子网会被CCE标记为专属子网)。
- 以IP地址为维度做安全策略,如以子网维度制定ACL。
1. 创建 psts
apiVersion: cce.io/v1alpha1
kind: PodSubnetTopologySpread
metadata:
name: example-subnet-topology
namespace: default
spec:
subnets:
sbn-mxxvp4gfdjyv:
# 多个subnet的类型必须一样
type: Manual
# 手动分配IP,只允许使用TTL的IP地址回收策略
# Pod 被释放后,IP地址即被回收
releaseStrategy: TTL
ipv4Range:
# 手动管理IP地址必须使用专属子网,专属子网所有的IP地址必须手动管理。
# 固定指定某几个IP地址,Pod的IP只从这几个地址中分配
- 192.168.78.228/32
- 192.168.78.229/32
sbn-s985prieeicc:
type: Manual
releaseStrategy: TTL
ipv4Range:
- 192.168.79.228/31
# 选择要使用该子网拓扑分布的Pod
selector:
matchLabels:
app: foo
2. 创建工作负载
apiVersion: apps/v1
kind: Deployment
metadata:
name: elastic-deploy
namespace: default
spec:
selector:
matchLabels:
app: foo
template:
spec:
containers:
- image: nginx
name: nginx
3. 验证IP分配结果
# # kubectl get pod {podName} -oyaml
apiVersion: v1
kind: Pod
metadata:
annotations:
cce.baidubce.com/PodSubnetTopologySpread: example-subnet-topology
generateName: elastic-deploy-56dc49b486-
labels:
app: foo
name: elastic-deploy-56dc49b486-d6z7b
namespace: default
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
# Pod 会自动对子网所属的可用区增加亲和性调度需求
- zoneF
- zoneC
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: nginx
resources:
limits:
cce.baidubce.com/ip: "1"
requests:
cce.baidubce.com/ip: "1"
场景5 namespace级多子网动态IP分配策略
场景2(指定多个子网动态分配IP)限制匹配psts.spec.selector
标签的Pod,才会使用多子网策略分配IP地址,限制了用户创建Pod时需要有相同的标签模板。下面介绍一种新的Pod子网拓扑分布的使用方式,它可以作为namespace的默认Pod IP 地址分配策略。
适用场景:
- 以namespace为维度划分治理Pod所使用的子网
1. 创建 psts
apiVersion: cce.io/v1alpha1
kind: PodSubnetTopologySpread
metadata:
name: example-subnet-topology
namespace: default
spec:
subnets:
# 必须是与当前集群同VPC的子网id,格式为sbn-*例如sbn-ccfud13pwcqf
sbn-ccfud13pwcqf: {}
sbn-asdascdsdfff: {}
# 如果没有指定selector,同namespace下的所有Pod都会被匹配
2. 创建工作负载
apiVersion: apps/v1
kind: Deployment
metadata:
name: elastic-deploy
namespace: default
spec:
selector:
matchLabels:
app: foo
template:
spec:
containers:
- image: nginx
name: nginx
3. 验证IP分配结果
# kubectl get pod {podName} -oyaml
apiVersion: v1
kind: Pod
metadata:
annotations:
cce.baidubce.com/PodSubnetTopologySpread: example-subnet-topology
generateName: elastic-deploy-56dc49b486-
labels:
app: foo
name: elastic-deploy-56dc49b486-d6z7b
namespace: default
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
# Pod 会自动对子网所属的可用区增加亲和性调度需求
- zoneF
- zoneC
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: nginx
resources:
limits:
cce.baidubce.com/ip: "1"
requests:
cce.baidubce.com/ip: "1"