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 分开调度到不同的节点上,更好的保证高可用

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

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

欢迎点赞,关注,收藏

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

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

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

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

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
2天前
|
存储 Kubernetes 容器
K8S部署nexus
该配置文件定义了Nexus 3的Kubernetes部署,包括PersistentVolumeClaim、Deployment和服务。PVC请求20Gi存储,使用NFS存储类。Deployment配置了一个Nexus 3容器,内存限制为6G,CPU为1000m,并挂载数据卷。Service类型为NodePort,通过30520端口对外提供服务。所有资源位于`nexus`命名空间中。
|
2月前
|
Prometheus Kubernetes 监控
k8s部署针对外部服务器的prometheus服务
通过上述步骤,您不仅成功地在Kubernetes集群内部署了Prometheus,还实现了对集群外服务器的有效监控。理解并实施网络配置是关键,确保监控数据的准确无误传输。随着监控需求的增长,您还可以进一步探索Prometheus生态中的其他组件,如Alertmanager、Grafana等,以构建完整的监控与报警体系。
135 60
|
25天前
|
Kubernetes Cloud Native 微服务
云原生入门与实践:Kubernetes的简易部署
云原生技术正改变着现代应用的开发和部署方式。本文将引导你了解云原生的基础概念,并重点介绍如何使用Kubernetes进行容器编排。我们将通过一个简易的示例来展示如何快速启动一个Kubernetes集群,并在其上运行一个简单的应用。无论你是云原生新手还是希望扩展现有知识,本文都将为你提供实用的信息和启发性的见解。
|
1月前
|
存储 Kubernetes Devops
Kubernetes集群管理和服务部署实战
Kubernetes集群管理和服务部署实战
49 0
|
2月前
|
NoSQL 关系型数据库 Redis
高可用和性能:基于ACK部署Dify的最佳实践
本文介绍了基于阿里云容器服务ACK,部署高可用、可伸缩且具备高SLA的生产可用的Dify服务的详细解决方案。
|
11天前
|
存储 Kubernetes 关系型数据库
阿里云ACK备份中心,K8s集群业务应用数据的一站式灾备方案
本文源自2024云栖大会苏雅诗的演讲,探讨了K8s集群业务为何需要灾备及其重要性。文中强调了集群与业务高可用配置对稳定性的重要性,并指出人为误操作等风险,建议实施周期性和特定情况下的灾备措施。针对容器化业务,提出了灾备的新特性与需求,包括工作负载为核心、云资源信息的备份,以及有状态应用的数据保护。介绍了ACK推出的备份中心解决方案,支持命名空间、标签、资源类型等维度的备份,并具备存储卷数据保护功能,能够满足GitOps流程企业的特定需求。此外,还详细描述了备份中心的使用流程、控制台展示、灾备难点及解决方案等内容,展示了备份中心如何有效应对K8s集群资源和存储卷数据的灾备挑战。
|
1月前
|
Kubernetes 监控 Cloud Native
Kubernetes集群的高可用性与伸缩性实践
Kubernetes集群的高可用性与伸缩性实践
71 1
|
2月前
|
JSON Kubernetes 容灾
ACK One应用分发上线:高效管理多集群应用
ACK One应用分发上线,主要介绍了新能力的使用场景
|
2月前
|
Kubernetes 持续交付 开发工具
ACK One GitOps:ApplicationSet UI简化多集群GitOps应用管理
ACK One GitOps新发布了多集群应用控制台,支持管理Argo CD ApplicationSet,提升大规模应用和集群的多集群GitOps应用分发管理体验。
|
2月前
|
Kubernetes Ubuntu Linux
Centos7 搭建 kubernetes集群
本文介绍了如何搭建一个三节点的Kubernetes集群,包括一个主节点和两个工作节点。各节点运行CentOS 7系统,最低配置为2核CPU、2GB内存和15GB硬盘。详细步骤包括环境配置、安装Docker、关闭防火墙和SELinux、禁用交换分区、安装kubeadm、kubelet、kubectl,以及初始化Kubernetes集群和安装网络插件Calico或Flannel。
203 4
下一篇
DataWorks