云原生Kubernetes:pod亲和性与反亲和性

news/2024/7/4 7:37:42 标签: 云原生, kubernetes, 容器

目录

一、理论

1.调度策略

2.亲和性与反亲和性案例

二、实验

1.亲和性与反亲和性

三、问题

1.节点批次打标签错误

2.for循环批量创建pod报错

四、总结


一、理论

1.调度策略

(1)对比

2.Pod 拓扑分布约束

(1)概念

使用 拓扑分布约束(Topology Spread Constraints) 来控制 Pod在集群内故障域之间的分布, 例如区域(Region)、可用区(Zone)、节点和其他用户自定义拓扑域。 这样做有助于实现高可用并提升资源利用率。

(2)拓扑分布约束 (涉及K8S v1.25及以上版本)

Pod 拓扑分布约束使你能够以声明的方式进行配置。

topologySpreadConstraints 字段,Pod API 包括一个 spec.topologySpreadConstraints 字段。这个字段的用法如下所示:

---
apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  # 配置一个拓扑分布约束
  topologySpreadConstraints:
    - maxSkew: <integer>
      minDomains: <integer> # 可选;自从 v1.25 开始成为 Beta
      topologyKey: <string>
      whenUnsatisfiable: <string>
      labelSelector: <object>
      matchLabelKeys: <list> # 可选;自从 v1.27 开始成为 Beta
      nodeAffinityPolicy: [Honor|Ignore] # 可选;自从 v1.26 开始成为 Beta
      nodeTaintsPolicy: [Honor|Ignore] # 可选;自从 v1.26 开始成为 Beta
  ### 其他 Pod 字段置于此处

(3) 示例

① 节点标签

拓扑分布约束依赖于节点标签来标识每个节点所在的拓扑域。 例如,某节点可能具有标签:

说明:
为了简便,此示例未使用众所周知的标签键 topology.kubernetes.io/zone 和 topology.kubernetes.io/region。 但是,建议使用那些已注册的标签键,而不是此处使用的私有(不合格)标签键 region 和 zone。

无法对不同上下文之间的私有标签键的含义做出可靠的假设。

有一个 4 节点的集群且带有以下标签

从逻辑上看集群如下

一致性

应该为一个组中的所有 Pod 设置相同的 Pod 拓扑分布约束。

通常,如果正使用一个工作负载控制器,例如 Deployment,则 Pod 模板会帮你解决这个问题。 如果混合不同的分布约束,则 Kubernetes 会遵循该字段的 API 定义; 但是,该行为可能更令人困惑,并且故障排除也没那么简单。

运维人员需要一种机制来确保拓扑域(例如云提供商区域)中的所有节点具有一致的标签。 为了避免运维人员需要手动为节点打标签,大多数集群会自动填充知名的标签, 例如 kubernetes.io/hostname。检查运维人员的集群是否支持此功能。

一个拓扑分布约束

假设拥有一个 4 节点集群,其中标记为 foo: bar 的 3 个 Pod 分别位于 node1、node2 和 node3 中:

希望新来的 Pod 均匀分布在现有的可用区域,则可以按如下设置其清单:

kind: Pod
apiVersion: v1
metadata:
  name: mypod
  labels:
    foo: bar
spec:
  topologySpreadConstraints:
  - maxSkew: 1
    topologyKey: zone
    whenUnsatisfiable: DoNotSchedule
    labelSelector:
      matchLabels:
        foo: bar
  containers:
  - name: pause
    image: registry.k8s.io/pause:3.1

从此清单看,topologyKey: zone 意味着均匀分布将只应用于存在标签键值对为 zone: <any value> 的节点 (没有 zone 标签的节点将被跳过)。如果调度器找不到一种方式来满足此约束, 则 whenUnsatisfiable: DoNotSchedule 字段告诉该调度器将新来的 Pod 保持在 pending 状态。

如果该调度器将这个新来的 Pod 放到可用区 A,则 Pod 的分布将成为 [3, 1]。 这意味着实际偏差是 2(计算公式为 3 - 1),这违反了 maxSkew: 1 的约定。 为了满足这个示例的约束和上下文,新来的 Pod 只能放到可用区 B 中的一个节点上:

或者:

可以调整 Pod 规约以满足各种要求:

将 maxSkew 更改为更大的值,例如 2,这样新来的 Pod 也可以放在可用区 A 中。
将 topologyKey 更改为 node,以便将 Pod 均匀分布在节点上而不是可用区中。 在上面的例子中,如果 maxSkew 保持为 1,则新来的 Pod 只能放到 node4 节点上。
将 whenUnsatisfiable: DoNotSchedule 更改为 whenUnsatisfiable: ScheduleAnyway, 以确保新来的 Pod 始终可以被调度(假设满足其他的调度 API)。但是,最好将其放置在匹配 Pod 数量较少的拓扑域中。 请注意,这一优先判定会与其他内部调度优先级(如资源使用率等)排序准则一起进行标准化。

3.亲和性与反亲和性案例

(1)环境准备

node01、 node02 都有标签 test=a,有个pod1 运行在node01上, 标签为app=myapp01

#设置node01和node02节点,拥有标签 test=a
[root@master demo]# kubectl  label nodes node{01,02} test=a --overwrite
node/node01 labeled
node/node02 labeled

#查看拥有标签test=a的节点
[root@master demo]# kubectl  get nodes -l test=a
NAME     STATUS   ROLES    AGE    VERSION
node01   Ready    <none>   7d6h   v1.15.1
node02   Ready    <none>   7d6h   v1.15.1
[root@master demo]# vim test.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp01
  labels:
    app: myapp01
spec:
  containers:
  - name: with-node-affinity
    image: soscscs/myapp:v1
#声明式创建pod 
[root@master demo]# kubectl  apply  -f test.yaml 
pod/myapp01 created

#查看pod myapp01的详细信息的标签
[root@master demo]# kubectl  get pods  myapp01  -o wide --show-labels 
NAME      READY   STATUS    RESTARTS   AGE   IP             NODE     NOMINATED NODE   READINESS GATES   LABELS
myapp01   1/1     Running   0          26s   10.244.1.112   node01   <none>           <none>            app=myapp01

(2) 亲和性+ In 测试

[root@master demo]# vim a.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: myapp10
  labels:
    app: myapp03
spec:
  containers:
  - name: myapp03
    image: soscscs/myapp:v1
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - myapp01
        topologyKey: test

pod拥有app=myapp01 标签(设这个pod为x),则把新pod调度到和 pod x 拥有同一个拓扑域test=a 的 节点上。

[root@master demo]# for i in myapp{11..15}; do kubectl apply -f a.yaml; sed -ri "4s#myapp1[0-9]#$i#" a.yaml; done
pod/myapp10 created
pod/myapp11 created
pod/myapp12 created
pod/myapp13 created
pod/myapp14 created
[root@master demo]# kubectl  get pods -o wide --show-labels 
NAME      READY   STATUS    RESTARTS   AGE   IP             NODE     NOMINATED NODE   READINESS GATES   LABELS
myapp01   1/1     Running   0          88m   10.244.1.112   node01   <none>           <none>            app=myapp01
myapp10   1/1     Running   0          6s    10.244.2.104   node02   <none>           <none>            app=myapp03
myapp11   1/1     Running   0          6s    10.244.1.138   node01   <none>           <none>            app=myapp03
myapp12   1/1     Running   0          5s    10.244.2.105   node02   <none>           <none>            app=myapp03
myapp13   1/1     Running   0          5s    10.244.1.139   node01   <none>           <none>            app=myapp03
myapp14   1/1     Running   0          5s    10.244.2.106   node02   <none>           <none>            app=myapp03

因为拓扑域test=a内,已经有了pod存在于node01节点上,所以把新pod调度到和 pod x 拥有同一个拓扑域test=a 的 节点上。

(3)亲和性+NotIn 测试

[root@master demo]# vim a.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: myapp10
  labels:
    app: myapp03
spec:
  containers:
  - name: myapp03
    image: soscscs/myapp:v1
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: NotIn
            values:
            - myapp01
        topologyKey: test
[root@master demo]# kubectl delete pod myapp{10..14};for i in myapp{11..15}; do kubectl apply -f a.yaml; sed -ri "4s#myapp1[0-9]#$i#" a.yaml; done
pod "myapp10" deleted
pod "myapp11" deleted
pod "myapp12" deleted
pod "myapp13" deleted
pod "myapp14" deleted
pod/myapp10 created
pod/myapp11 created
pod/myapp12 created
pod/myapp13 created
pod/myapp14 created
[root@master demo]# kubectl  get pods -o wide --show-labels 
NAME      READY   STATUS    RESTARTS   AGE   IP             NODE     NOMINATED NODE   READINESS GATES   LABELS
myapp01   1/1     Running   0          91m   10.244.1.112   node01   <none>           <none>            app=myapp01
myapp10   1/1     Running   0          5s    10.244.1.140   node01   <none>           <none>            app=myapp03
myapp11   1/1     Running   0          5s    10.244.2.107   node02   <none>           <none>            app=myapp03
myapp12   1/1     Running   0          4s    10.244.1.141   node01   <none>           <none>            app=myapp03
myapp13   1/1     Running   0          4s    10.244.2.108   node02   <none>           <none>            app=myapp03
myapp14   1/1     Running   0          4s    10.244.1.142   node01   <none>           <none>            app=myapp03

(4)非亲和性+In 测试

[root@master demo]# vim a.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp10
  labels:
    app: myapp03
spec:
  containers:
  - name: myapp03
    image: soscscs/myapp:v1
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - myapp01
        topologyKey: test
[root@master demo]# kubectl delete pod myapp{10..14};for i in myapp{11..15}; do kubectl apply -f a.yaml; sed -ri "4s#myapp1[0-9]#$i#" a.yaml; done
pod "myapp10" deleted
pod "myapp11" deleted
pod "myapp12" deleted
pod "myapp13" deleted
pod "myapp14" deleted
pod/myapp10 created
pod/myapp11 created
pod/myapp12 created
pod/myapp13 created
pod/myapp14 created
[root@master demo]# kubectl  get pods -o wide --show-labels 
NAME      READY   STATUS    RESTARTS   AGE   IP             NODE     NOMINATED NODE   READINESS GATES   LABELS
myapp01   1/1     Running   0          96m   10.244.1.112   node01   <none>           <none>            app=myapp01
myapp10   0/1     Pending   0          4s    <none>         <none>   <none>           <none>            app=myapp03
myapp11   0/1     Pending   0          3s    <none>         <none>   <none>           <none>            app=myapp03
myapp12   0/1     Pending   0          3s    <none>         <none>   <none>           <none>            app=myapp03
myapp13   0/1     Pending   0          3s    <none>         <none>   <none>           <none>            app=myapp03
myapp14   0/1     Pending   0          3s    <none>         <none>   <none>           <none>            app=myapp03


[root@master demo]# kubectl  describe  pod myapp10

(5)非亲和性 + NotIn 测试

[root@master demo]# vim a.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: myapp10
  labels:
    app: myapp03
spec:
  containers:
  - name: myapp03
    image: soscscs/myapp:v1
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: NotIn
            values:
            - myapp01
        topologyKey: test
[root@master demo]# kubectl delete pod myapp{10..14};for i in myapp{11..15}; do kubectl apply -f a.yaml; sed -ri "4s#myapp1[0-9]#$i#" a.yaml; done
pod "myapp10" deleted
pod "myapp11" deleted
pod "myapp12" deleted
pod "myapp13" deleted
pod "myapp14" deleted
pod/myapp10 created
pod/myapp11 created
pod/myapp12 created
pod/myapp13 created
pod/myapp14 created
[root@master demo]# kubectl  get pods -o wide --show-labels 
NAME      READY   STATUS    RESTARTS   AGE    IP             NODE     NOMINATED NODE   READINESS GATES   LABELS
myapp01   1/1     Running   0          102m   10.244.1.112   node01   <none>           <none>            app=myapp01
myapp10   1/1     Running   0          8s     10.244.2.109   node02   <none>           <none>            app=myapp03
myapp11   0/1     Pending   0          8s     <none>         <none>   <none>           <none>            app=myapp03
myapp12   0/1     Pending   0          7s     <none>         <none>   <none>           <none>            app=myapp03
myapp13   0/1     Pending   0          7s     <none>         <none>   <none>           <none>            app=myapp03
myapp14   0/1     Pending   0          7s     <none>         <none>   <none>           <none>            app=myapp03


[root@master demo]# kubectl  describe  pod myapp11

二、实验

1.亲和性与反亲和性

(1)环境准备

node01、 node02 都有标签 test=a,有个pod1 运行在node01上, 标签为app=myapp01

编写资源清单

声明式创建pod

查看pod myapp01的详细信息的标签

pod myapp01 拥有标签app=myapp01,且被调度到了node01上

(2) 亲和性+ In 测试

pod拥有app=myapp01 标签(设这个pod为x),则把新pod调度到和 pod x 拥有同一个拓扑域test=a 的 节点上。

创建pod myapp10-myapp14

因为拓扑域test=a内,已经有了pod存在于node01节点上,所以把新pod调度到和 pod x 拥有同一个拓扑域test=a 的 节点上。

pod从node01节点开始在两个节点上依次循环创建pod

查看资源清单文件,最后一次更改为15后,执行了14,然后修改为15结束for循环,实际是创建pod myapp10-myapp14就结束了

(3)亲和性+NotIn 测试

先修改资源清单文件

批量删除之前的pod myapp10-myapp14,并创建pod myapp10-myapp14

pod从node01节点开始,在两个节点上依次循环创建pod

(4)非亲和性+In 测试

先修改资源清单文件

批量删除之前的pod myapp10-myapp14,并创建pod myapp10-myapp14

查看信息,新创建的pod都处于Pending状态

查看详细信息

两个节点都不匹配pod非亲和规则,又因为使用的是硬限制,因此当找不到合适的node节点调度pod时,就会处于Pending状态

(5)非亲和性 + NotIn 测试

先修改资源清单文件

批量删除之前的pod myapp10-myapp14,并创建pod myapp10-myapp14

查看信息,只有第一个myapp10成功在node02上创建,剩余的4个pod都处于Pending状态

查看详细信息

两个节点都不满足现有的pod反亲和性特征

三、问题

1.节点批次打标签错误

(1)报错

(2)原因分析

语法错误

(3)解决方法

将括号()修改为花括号 { }

修改前:

修改后:

成功:

2.for循环批量创建pod报错

(1)报错

(2)原因分析

“s”命令缺少终止符合#

(3)解决方法

添加终止符#

修改前:

修改后:

成功:

3.比较 podAffinity 和 podAntiAffinity

(1)比较

在 Kubernetes 中, Pod亲和性和反亲和性控制 Pod 彼此的调度方式(更密集或更分散)。

podAffinity
吸引 Pod;你可以尝试将任意数量的 Pod 集中到符合条件的拓扑域中。

podAntiAffinity
驱逐 Pod。如果将此设为 requiredDuringSchedulingIgnoredDuringExecution 模式, 则只有单个 Pod 可以调度到单个拓扑域;如果你选择 preferredDuringSchedulingIgnoredDuringExecution, 则你将丢失强制执行此约束的能力。

要实现更细粒度的控制,你可以设置拓扑分布约束来将 Pod 分布到不同的拓扑域下,从而实现高可用性或节省成本。 这也有助于工作负载的滚动更新和平稳地扩展副本规模。

四、总结

批量删除之前的pod myapp10-myapp14,并创建pod myapp10-myapp14

[root@master]# kubectl delete pod myapp{10..14};for i in myapp{11..15}; do kubectl apply -f a.yaml; sed -ri "4s#myapp1[0-9]#$i#" a.yaml; done


http://www.niftyadmin.cn/n/5036396.html

相关文章

基于SSM+Vue的舞蹈网站

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用Vue技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

融云受邀参加 Web3.0 顶级峰会「Meta Era Summit 2023」

本周四 19:00-20:00&#xff0c;融云直播课 社交泛娱乐出海最短变现路径如何快速实现一款 1V1 视频应用&#xff1f; 欢迎点击上方小程序报名~ 9 月 12 日&#xff0c;由中国香港 Web3.0 媒体 Meta Era 主办的“Meta Era Summit 2023”在新加坡收官&#xff0c;融云作为战略合作…

gpt扣款失败,openai扣款失败无法使用-如何解决gpt扣款失败的问题?

gpt扣款失败&#xff0c;openai扣款失败无法使用。毕竟你花了钱却无法使用你所期待的服务&#xff0c;这种情况确实令人不快。但是&#xff0c; 为什么gpt扣款失败&#xff1f; 可能是由于支付问题导致的扣款失败。这包括信用卡额度不足、支付信息错误等等。如果你的支付信息…

【jmeter】jmeter引用变量,变量值传递失败

最近在用jmeter做接口测试的时候&#xff0c;发现有个变量&#xff0c;参数值一直没有传递进来&#xff0c;导致request的时候&#xff0c;请求体里面一直是${}变量的形式。 后来经过排查发现&#xff0c;是因为我在定义用户变量的时候&#xff0c;在这个now后面多加了一个空格…

APP产品经理岗位的具体内容(合集)

APP产品经理岗位的具体内容1 1、负责项目产品团队的管理工作&#xff0c;对项目产品团队考核目标负责; 2、全面负责“工务园”所有产品&#xff0c;全方位负责其生命周期管理; 3、按照产品管理相关的计划和规范&#xff0c;对产品版本的更新及发布负责&#xff0c;完善产品的…

SDXL prompt 笔记

模型 模型有两个&#xff0c;分别是 stable-diffusion-xl-base-1.0、stable-diffusion-xl-refiner-1.0。 base 模型是用来做文生图&#xff0c;refiner 模型是用来做图生图的。 SDXL 模型之 base、refiner 和 VAE_云水木石的博客-CSDN博客 分辨率 默认是1024*1024&#xf…

(避开网上复制操作)最详细的树莓派刷机配置(含IP固定、更改国内源的避坑操作、SSH网络登录、VNC远程桌面登录)

一、准备工作 SD卡格式化 二、 树莓派系统环境搭建&#xff08;官方&#xff09; 官方镜像 1.1、 必备的配件 读卡器&#xff0c; 内存卡&#xff08;强烈推荐 32GB 内存卡&#xff0c; #lite 命令行界面版本至少需要 8G&#xff0c; 图形化带桌面版镜像需要 16GB&#xf…

yarn命令详细解读

yarn命令详细解读 Yarn 的简介Yarn的特点Yarn的安装Yarn的常用命令npm 与 yarn 命令比较npm 与 yarn 相关问题比较 Yarn 的简介 Yarn是facebook发布的一款取代npm的包管理工具&#xff1b; Yarn的特点 速度超快----Yarn缓存了每个下载过的包&#xff0c;所以再次使用时无需重…