k8s 服务升级为啥 pod 会部署到我们不期望的节点上??看来你还不懂污点和容忍度

简介: k8s 服务升级为啥 pod 会部署到我们不期望的节点上??看来你还不懂污点和容忍度

做自动化的同事今天居然问我 k8s 中为什么我部署的 pod 会跑到你们开发的节点上来?我可以去控制它吗?🧐🧐

兄弟,自然是可以控制的,接下来我详细给你说一下关于 k8s 中节点污点,pod 对污点的容忍度,以及 亲缘性和非亲缘性✔✔

👀需求场景

首先我们要明确咱们的需求和场景

  1. 如果期望自己的 pod 需要部署到指定的 Node 上,那么可以在 pod 的 yaml 中加上 nodeSelector 节点标签选择器,或者在 pod 中加上节点亲缘性的配置
  2. 如果我们期望某一个节点不让别的 pod 的部署上来,只期望一些特定的 pod 部署到这个 Node 上,那么我们就可以使用节点的污点,和 pod 对污点的容忍度来进行实现

接下来我们就开始吧,看看什么是 nodeSelector,以及上述提到的各种名词,本次文章内容,需要有一点点 k8s 基础的同学看起来会更加友好,至少你得知道 Deployment 资源和 pod 资源的 yaml 清单

✔nodeSelector 节点标签选择器

nodeSelector 节点标签选择器, 用过K8S的我们都知道,如果想让 pod 指定部署到某一些节点上,那么我们可以通过这个字段来进行标识。

例如我们的 Pod 资源中 nodeSelector 字段标识的是 func=dev ,那么 pod 就会部署到 func=dev 的任意节点上,这是强制指定的😥

apiVersion: v1
kind: Pod
metadata:
  name: test-node-selector
sepc:
  nodeSelector:
    fun: "dev"
    ...

通过这里就可以看到节点标签选择器,它的使用局限性还是非常明显的,它只能用于你指定 pod 一定要部署到某一个指定标签节点上的时候,那如果这个时候没有这种标签的节点时,你这个 pod 就会部署不成功。

✔k8s 中节点污点和 pod 对污点的容忍度

我们一般会使用节点污点和 pod 对污点的容忍度来阻止 pod 被调度到特定的节点上

如果你期望某一个 pod 一定不能部署到某一个节点上的时候,你就可以使用节点污点和pod 对污点的容忍度

例如现在上了一个新的节点,但是还没有调试完整,你不期望你部署的 pod 会部署到这个新的节点上,那么这个时候,你就可以给这个节点加上污点。

那你测试这个新节点的时,你就可以在你将要部署的 pod 资源上面,加上 pod 对该污点的容忍度

先来看一下k8s master上默认的一个污点

可以看到我们环境里面的 minikube,它的污点是空

因为它只有一个节点,它既是 master 又是worker,所以它部署的 pod 仍然可以在这个节点上进行正常部署

如果我们是在 K8S 集群中查看 master 节点的详情时,我们可以看到这样的污点

Taints:             node-role.kubernetes.io/master:NoSchedule

其中污点的

key 是 node-role.kubernetes.io/master

value 是 空的

effect 是 NoSchedule

表达的意思是这个污点会阻止 pod 调度到这个节点上面

一个 pod 只有容忍了节点上的污点,那么他才可以被调度到这个节点上

一般情况下,用于系统的 pod 会容忍 master 上的这个污点也,就是说这样的 pod 就可以部署到master上

对于污点 Taints ,我们需要注意这三类

前两类(NoSchedule, PreferNoSchedule)污点都只作用于调度期间,后一类的污点(NoExecute),它会影响正在节点上运行的 pod

NoSchedule

表示如果 pod 无法容忍这个污点那么 pod 将不能调度到包含该污点的节点上

PreferNoSchedule

表示尽量阻止 pod 被调度到这个节点上,当然如果没有其他节点可以调度,那么 pod 仍然还是可以调度到当前有这种污点的节点上的

NoExecute

如果在一个节点上加入了这种类型的污点,那么在当前节点上已经运行的 pod,若不能容忍这个污点,则这些 pod 就会被干掉

如何操作

👀我们可以通过编辑的方式去修改节点的污点或者通过命令的方式给节点加上污点

  • 通过 edit node 的方式修改
kubectl edit node [nodeName]

找到 Taints 的位置,加上我们的 key,value,effect

修改完毕后,使用命令查看污点是否添加成功

kubectl describe node [nodeName]
  • 通过命令的方式修改
kubectl taint node [nodeName] key=value:effect
例如:
kubectl taint node vm-20-15-centos node-type=newNode:NoSchedule

表达的意思是,给节点 vm-20-15-centos 加上一个污点:

Key 为 node-type

Value 为 newNode

Effect 为 NoSchedule

此时,只有容忍这个新节点上污点(node-type=newNode:NoSchedule) 的 pod 才可以部署上来,其他没有容忍度的 pod 就无法部署上来

👀我们可以这样在 pod 里面添加对污点的容忍度

直接在 pod 资源中,或者在 deployment 资源中的 spec.template.spec 下添加 tolerations 的配置

tolerations:
      - effect: NoSchedule
        key: node-type
        operator: Equal
        value: newNode

现在,咱们的刚修改的这个 pod 有了对这个污点的容忍度(node-type=newNode:NoSchedule),因此可以在上述节点上进行部署

🧐简单理解

如果你能够容忍得了坏的生活,那么你也值得好的生活,好坏你都可以去感受去选择

如果你无法容忍坏的生活,那么你无法接近这片区域的

✔节点亲缘性

节点的亲缘性和节点标签选择器有点类似,但节点亲缘性能够表达的意思更多。

使用节点亲缘性,它可以让我们部署的 pod,更加倾向于调度到某一些节点上,在 K8S 中会尽量的将这个 pod 按照我们期望的节点进行部署,如果没办法实现的话,那也会把这些节点部署到其他节点上。

对于节点的亲源性,我们聊一聊如下三个重要的标签

failure-domain.beta.kubernetes.io/region

表示节点所在地域

failure-domain.beta.kubernetes.io/zone

表示节点所在的可用性区域

kubernetes.io/hostname

表示节点的主机名

🧐如何操作

第1步

自然是先将节点打上我们期望的标签,例如节点的标签是 func=dev,当然我们也可以不用自定义标签,可以使用系统的默认标签,例如 kubernetes.io/hostname 主机名

kubectl label nodes [nodeName] key=value
例如
kubectl label nodes vm-20-15-centos func=dev

第2步

我们需要去修改 pod 资源中关于节点亲和性的位置,例如可以这样。

nodeSelectorTerms 标签下满足任意一个 matchExpressions 即可

matchExpressions 标签下需要全部满足

spec:
  affinity: 
    nodeAffinity: 
      requiredDuringSchedulingIgnoredDuringExecution: 
        nodeSelectorTerms: 
          - matchExpressions: 
              - key: func 
                operator: Euqal
                values: 
                  - dev
          - matchExpressions: 
              - key: kubernetes.io/hostname
                operator: NotIn
                values: 
                  - dev

这个时候,咱们部署的 pod ,就会去找有 func=dev 标签的节点进行部署,如果没有的话,那么就无法部署

这里我们可以看到 nodeAffinity 下面有一长串单词 requiredDuringSchedulingIgnoredDuringExecution,此处详细解释一下。我们可以分开来看这一长串单词。

requiredDuringScheduling

此处的 required 表示的是必须包含,表示 pod 若要调度到该节点上,那么必须要指出该节点包含的标签。

IgnoredDuringExecution

根据单词名字我们可以看出。在调度过程中会忽略正在运行的 pod,也就是说对正在执行的 pod 不影响。

同样的道理,我们可以将上述的 required 换成 preferred ,对 K8S 来说就是尽可能的优先将 pod 调度到我们指定的节点上,如果没有这样的节点,那么它也是会将 pod 调度到其他节点上的。

可以这样写,尽量满足要求

spec:
  affinity: 
    nodeAffinity: 
      prefferredDuringSchedulingIgnoredDuringExecution: 
      - weight 100
        preference:
          matchExpressions: 
          - key: func 
            operator: Euqal
            values: 
            - dev

看到此处你已经学会了,如何让 pod 部署到指定的节点上,同时你也可以让某一些节点拒绝 pod 部署上来。

✔Pod 的亲缘性

这个时候我们会有另外的一些需求,我们希望将一些交互比较多的不同类型的 pod 部署到一个节点上,这样的话他们的网络通信性能会更好。

例如租户系统就会经常调用用户管理系统的接口。那么这两类 pod 就可以放到同一个节点进行部署。这个时候我们就可以使用 pod 的亲缘性来很好地处理。

对于 pod 亲缘性和节点的亲缘性来说,在写法上将 nodeAffinity 换成了 podAffinity

🧐如何操作

例如,此处的 租户系统 pod 标签为 app=tenant , 那么 用户管理写 pod 亲和性的时候,就只需要去找这个标签的 pod 所在的节点进行部署即可

修改 pod / deployment 资源

spec:
  affinity: 
    podAffinity: 
      requiredDuringSchedulingIgnoredDuringExecution: 
      - topologyKey: kubernetes.io/hostname
        labelSelector:
          masrchLabels:
            app: tenant
            ...

其中 topologyKey 指定 kubernetes.io/hostname ,含义是:要求 pod 将被调度到 包含 app=tenant 标签的 pod 所在的相同节点上面

✔Pod 的非亲缘性

我们的需求总是无穷无尽的,现在我们为了服务更加的健壮,期望同一个应用,能够在 K8S上每一个节点都部署一个,而不是这一个应用全都部署在一个节点上。

这样是为了防止某一个节点出现故障之后,其他节点上仍然有这个应用提供服务。

那咱们可以如法炮制,既然有 pod 的亲缘性,那自然也有 pod 的非亲缘性

Pod 的非亲缘性,咱们一般用来去分开调度 pod ,让同一类型 pod 分别部署到不同的 节点上

👀如何操作

修改 pod / deployment 资源

spec:
  affinity: 
    podAntiAffinity: 
      requiredDuringSchedulingIgnoredDuringExecution: 
      - topologyKey: kubernetes.io/hostname
        labelSelector:
          masrchLabels:
            app: tenant
            ...

此处我们可以看到,使用的 podAntiAffinity 表示 pod 的反亲缘性, 此处不要弄错了

此处写的标签是 app=tenant ,表示的意思是,如果有一个 pod 标签为 app=tenant 在 节点 1 上,那么如果再部署这种类型的 pod 的时候,就不会再部署到节点1 上的,就会去部署到其他节点上

🔥总结

至此,通过上面的知识,我们解决了这样几个场景问题

  • 利用节点的亲缘性将 pod 指定部署到某些节点上,如果这样的节点不存在,那么也可以将他们的部署到别的节点上。
  • 利用 pod 亲缘性将交互比较频繁的一些服务应用尽可能部署到同一个节点上。
  • 利用 pod 的非亲缘性将 pod 分开调度到不同的节点上,更好的保证高可用

本次就是这样,如果有帮助到你,欢迎点赞,评论,留言哦

感谢阅读,欢迎交流,点个赞,关注一波 再走吧

欢迎点赞,关注,收藏

朋友们,你的支持和鼓励,是我坚持分享,提高质量的动力

技术是开放的,我们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。

我是阿兵云原生,欢迎点赞关注收藏,下次见~

文中提到的技术点,感兴趣的可以查看这些文章:

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
7月前
|
存储 Kubernetes 开发工具
使用ArgoCD管理Kubernetes部署指南
ArgoCD 是一款基于 Kubernetes 的声明式 GitOps 持续交付工具,通过自动同步 Git 存储库中的配置与 Kubernetes 集群状态,确保一致性与可靠性。它支持实时同步、声明式设置、自动修复和丰富的用户界面,极大简化了复杂应用的部署管理。结合 Helm Charts,ArgoCD 提供模块化、可重用的部署流程,显著减少人工开销和配置错误。对于云原生企业,ArgoCD 能优化部署策略,提升效率与安全性,是实现自动化与一致性的理想选择。
344 0
|
6月前
|
存储 Kubernetes 异构计算
Qwen3 大模型在阿里云容器服务上的极简部署教程
通义千问 Qwen3 是 Qwen 系列最新推出的首个混合推理模型,其在代码、数学、通用能力等基准测试中,与 DeepSeek-R1、o1、o3-mini、Grok-3 和 Gemini-2.5-Pro 等顶级模型相比,表现出极具竞争力的结果。
|
7月前
|
存储 Kubernetes 监控
K8s集群实战:使用kubeadm和kuboard部署Kubernetes集群
总之,使用kubeadm和kuboard部署K8s集群就像回归童年一样,简单又有趣。不要忘记,技术是为人服务的,用K8s集群操控云端资源,我们不过是想在复杂的世界找寻简单。尽管部署过程可能遇到困难,但朝着简化复杂的目标,我们就能找到意义和乐趣。希望你也能利用这些工具,找到你的乐趣,满足你的需求。
647 33
|
7月前
|
Kubernetes Docker 容器
Kubernetes与Docker参数对照:理解Pod中的command、args与Dockerfile中的CMD、ENTRYPOINT。
需要明确的是,理解这些都需要对Docker和Kubernetes有一定深度的理解,才能把握二者的区别和联系。虽然它们都是容器技术的二个重要组成部分,但各有其特性和适用场景,理解它们的本质和工作方式,才能更好的使用这些工具,将各自的优点整合到生产环境中,实现软件的快速开发和部署。
223 25
|
7月前
|
Kubernetes 开发者 Docker
集群部署:使用Rancher部署Kubernetes集群。
以上就是使用 Rancher 部署 Kubernetes 集群的流程。使用 Rancher 和 Kubernetes,开发者可以受益于灵活性和可扩展性,允许他们在多种环境中运行多种应用,同时利用自动化工具使工作负载更加高效。
374 19
|
7月前
|
Kubernetes API 网络安全
当node节点kubectl 命令无法连接到 Kubernetes API 服务器
当Node节点上的 `kubectl`无法连接到Kubernetes API服务器时,可以通过以上步骤逐步排查和解决问题。首先确保网络连接正常,验证 `kubeconfig`文件配置正确,检查API服务器和Node节点的状态,最后排除防火墙或网络策略的干扰,并通过重启服务恢复正常连接。通过这些措施,可以有效解决与Kubernetes API服务器通信的常见问题,从而保障集群的正常运行。
441 17
|
5月前
|
资源调度 Kubernetes 调度
从单集群到多集群的快速无损转型:ACK One 多集群应用分发
ACK One 的多集群应用分发,可以最小成本地结合您已有的单集群 CD 系统,无需对原先应用资源 YAML 进行修改,即可快速构建成多集群的 CD 系统,并同时获得强大的多集群资源调度和分发的能力。
186 9
|
5月前
|
资源调度 Kubernetes 调度
从单集群到多集群的快速无损转型:ACK One 多集群应用分发
本文介绍如何利用阿里云的分布式云容器平台ACK One的多集群应用分发功能,结合云效CD能力,快速将单集群CD系统升级为多集群CD系统。通过增加分发策略(PropagationPolicy)和差异化策略(OverridePolicy),并修改单集群kubeconfig为舰队kubeconfig,可实现无损改造。该方案具备多地域多集群智能资源调度、重调度及故障迁移等能力,帮助用户提升业务效率与可靠性。
|
7月前
|
人工智能 分布式计算 调度
打破资源边界、告别资源浪费:ACK One 多集群Spark和AI作业调度
ACK One多集群Spark作业调度,可以帮助您在不影响集群中正在运行的在线业务的前提下,打破资源边界,根据各集群实际剩余资源来进行调度,最大化您多集群中闲置资源的利用率。
|
10月前
|
Prometheus Kubernetes 监控
OpenAI故障复盘 - 阿里云容器服务与可观测产品如何保障大规模K8s集群稳定性
聚焦近日OpenAI的大规模K8s集群故障,介绍阿里云容器服务与可观测团队在大规模K8s场景下我们的建设与沉淀。以及分享对类似故障问题的应对方案:包括在K8s和Prometheus的高可用架构设计方面、事前事后的稳定性保障体系方面。

热门文章

最新文章

推荐镜像

更多