【云原生 | 从零开始学Kubernetes】十、k8sPod节点亲和性和反亲和性

简介: pod 和 pod 更倾向腻在一起,把相近的 pod 结合到相近的位置,比如同一区域,同一机架,这样的话 pod 和 pod 之间更好通信,比方说有两个机房,这两个机房部署的集群有 1000 台主机,那么我们希望把 nginx 和 tomcat 都部署同一个地方的 node 节点上,可以提高通信效率。

Pod 节点亲和性


pod 自身的亲和性调度有两种表示形式


podaffinity:pod 和 pod 更倾向腻在一起,把相近的 pod 结合到相近的位置,比如同一区域,同一机架,这样的话 pod 和 pod 之间更好通信,比方说有两个机房,这两个机房部署的集群有 1000 台主机,那么我们希望把 nginx 和 tomcat 都部署同一个地方的 node 节点上,可以提高通信效率。


podunaffinity:pod 和 pod 更倾向不腻在一起,如果部署两套程序,那么这两套程序更倾向于反亲和性,这样相互之间不会有影响。


第一个 pod 随机选则一个节点,做为评判后续的 pod 能否到达这个 pod 所在的节点上的运行方式,这就称为 pod 亲和性;我们怎么判定哪些节点是相同位置的,哪些节点是不同位置的。我们在定义 pod 亲和性时需要有一个前提,哪些 pod 在同一个位置,哪些 pod 不在同一个位置,这个位置是怎么定义的,标准是什么?以节点名称为标准,这个节点名称相同的表示是同一个位置,节点名称不相同的表示不是一个位置,或者其他方式。


[root@k8smaster ~]# kubectl explain pods.spec.affinity.podAffinity
KIND:     Pod
VERSION:  v1
RESOURCE: podAffinity <Object>
DESCRIPTION:
     Describes pod affinity scheduling rules (e.g. co-locate this pod in the
     same node, zone, etc. as some other pod(s)).
     Pod affinity is a group of inter pod affinity scheduling rules.
FIELDS:
   preferredDuringSchedulingIgnoredDuringExecution  <[]Object>      #软亲和性
   requiredDuringSchedulingIgnoredDuringExecution <[]Object>      #硬亲和性
[root@k8smaster ~]# kubectl explain pods.spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution 
KIND:     Pod
VERSION:  v1
RESOURCE: requiredDuringSchedulingIgnoredDuringExecution <[]Object>
DESCRIPTION:
     If the affinity requirements specified by this field are not met at
     scheduling time, the pod will not be scheduled onto the node. If the
     affinity requirements specified by this field cease to be met at some point
     during pod execution (e.g. due to a pod label update), the system may or
     may not try to eventually evict the pod from its node. When there are
     multiple elements, the lists of nodes corresponding to each podAffinityTerm
     are intersected, i.e. all terms must be satisfied.
     Defines a set of pods (namely those matching the labelSelector relative to
     the given namespace(s)) that this pod should be co-located (affinity) or
     not co-located (anti-affinity) with, where co-located is defined as running
     on a node whose value of the label with key <topologyKey> matches that of
     any node on which a pod of the set of pods is running
FIELDS:
   labelSelector  <Object>  #我们要判断 pod 跟别的 pod 亲和,跟哪个 pod 亲和,需要靠 labelSelector,通过 labelSelector选则一组能作为亲和对象的 pod 资源
   namespaces <[]string>  #labelSelector 需要选则一组资源,那么这组资源是在哪个名称空间中呢,通过 namespace 指定,如果不指定 namespaces,那么就是当前创建 pod 的名称空间
   topologyKey  <string> -required-       #位置拓扑的键,这个是必须字段 
怎么判断是不是同一个位置
rack=rack1
row=row1
使用 rack 的键是同一个位置 
使用 row 的键是同一个位置
[root@k8smaster ~]# kubectl explain pods.spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution.labelSelector
KIND:     Pod
VERSION:  v1
RESOURCE: labelSelector <Object>
DESCRIPTION:
     A label query over a set of resources, in this case pods.
     A label selector is a label query over a set of resources. The result of
     matchLabels and matchExpressions are ANDed. An empty label selector matches
     all objects. A null label selector matches no objects.
FIELDS:
   matchExpressions <[]Object>
   matchLabels  <map[string]string>
例:pod 节点亲和性 
#定义两个 pod,第一个 pod 做为基准,第二个 pod 跟着它走 
[root@k8smaster ~]# kubectl delete pods pod-first
pod "pod-first" deleted
[root@k8smaster ~]# vim pod-required-affinity-demo.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-first
  labels:
    app2: myapp2
    tier: frontend
spec:
    containers:
    - name: myapp
      image: nginx
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-second
  labels:
    app: backend
    tier: db
spec:
    containers:
    - name: busybox
      image: busybox:latest
      imagePullPolicy: IfNotPresent
      command: ["sh","-c","sleep 3600"]       
    affinity:
      podAffinity:
         requiredDuringSchedulingIgnoredDuringExecution:
         - labelSelector:
              matchExpressions:
              - {key: app2, operator: In, values: ["myapp2"]}
           topologyKey: kubernetes.io/hostname


busybox如果不写sleep会自动关闭,sleep是等待多长时间。然后下面就是pod亲和性,硬亲和性,然后通过label(标签选择器选择),之前我们也通过帮助文档看过了选择器里面的字段(也可以深入看match里面有啥)


下面的key意思是选择app2=myapp2的标签做亲和性,如果不写第二个pod会找不到和哪个做亲和性。


最后一行可以直接用nodes里的已有标签来位置拓扑的键。kubectl get nodes --show-labels查看标签。


kubernetes.io/hostname标签对应的是具体的k8snode节点名,如果frist调度到node2或者node1,第二个pod也跟着调度到哪个节点(根据主机名做位置)


#上面表示创建的 pod 必须与拥有 app2=myapp2 标签的 pod 在一个节点上 
[root@k8smaster ~]# kubectl apply -f pod-required-affinity-demo.yaml 
pod/pod-first created
pod/pod-second created
[root@k8smaster ~]# kubectl get pods -o wide
NAME                          READY   STATUS    RESTARTS   AGE     IP            NODE       NOMINATED NODE  
pod-first                     1/1     Running   0          26s     10.244.1.21   k8snode2   <none>           
pod-second                    1/1     Running   0          26s     10.244.1.22   k8snode2   <none>           
#上面说明第一个 pod 调度到哪,第二个 pod 也调度到哪,这就是 pod 节点亲和性 
[root@k8smaster ~]# kubectl delete -f pod-required-affinity-demo.yaml
pod "pod-first" deleted
pod "pod-second" deleted


pod 节点反亲和性



定义两个 pod,第一个 pod 做为基准,第二个 pod 跟它调度节点相反 同样基于node名字作为基准
[root@k8smaster ~]# vim pod-required-anti-affinity-demo.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-first
  labels:
    app1: myapp1
    tier: frontend
spec:
    containers:
    - name: myapp
      image: nginx
---
apiVersion: v1
kind: Pod
metadata:
  name: pod-second
  labels:
    app: backend
    tier: db
spec:
    containers:
    - name: busybox
      image: busybox
      imagePullPolicy: IfNotPresent
      command: ["sh","-c","sleep 3600"]
    affinity:
      podAntiAffinity:
         requiredDuringSchedulingIgnoredDuringExecution:
         - labelSelector:
              matchExpressions:
              - {key: app1, operator: In, values: ["myapp1"]}
           topologyKey: kubernetes.io/hostname
[root@k8smaster ~]# kubectl apply -f pod-required-anti-affinity-demo.yaml
pod/pod-first created
pod/pod-second created
[root@k8smaster ~]# kubectl get pods -o wide
NAME                          READY   STATUS    RESTARTS   AGE     IP            NODE       NOMINATED NODE  
pod-first                     1/1     Running   0          21s     10.244.1.23   k8snode2   <none>           
pod-second                    1/1     Running   0          21s     10.244.2.20   k8snode    <none>          
#两个 pod 不在一个 node 节点上,这就是 pod 节点反亲和性 
[root@k8smaster ~]# kubectl delete -f pod-required-anti-affinity-demo.yaml
pod "pod-first" deleted
pod "pod-second" deleted
#例3:换一个 topologykey 
[root@k8smaster ~]# kubectl label nodes k8snode zone=foo --overwrite
node/k8snode not labeled
[root@k8smaster ~]# kubectl label nodes k8snode2 zone=foo --overwrite
node/k8snode2 labeled
#然后去pp node 和当前目录下都删除掉k8s的pod。
[root@k8smaster pp]# kubectl delete -f .
resourcequota "mem-cpu-quota" deleted
pod "pod-test" deleted
[root@k8smaster node]# kubectl delete -f .
pod "demo-pod-1" deleted
pod "demo-pod" deleted
pod "pod-node-affinity-demo-2" deleted
pod "pod-node-affinity-demo" deleted
[root@k8smaster node]# kubectl get pods
NAME                          READY   STATUS    RESTARTS   AGE
[root@k8smaster node]# vim pod-first-required-anti-affinity-demo-1.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-first
  labels:
    app3: myapp3
    tier: frontend
spec:
    containers:
    - name: myapp
      image: nginx
[root@k8smaster node]# vim pod-second-required-anti-affinity-demo-1.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-second
  labels:
    app: backend
    tier: db
spec:
    containers:
    - name: busybox
      image: busybox
      imagePullPolicy: IfNotPresent
      command: ["sh","-c","sleep 3600"]
    affinity:
      podAffinity:
         requiredDuringSchedulingIgnoredDuringExecution:
         - labelSelector:
              matchExpressions:
              - {key: app3, operator: In, values: ["myapp3"]}
           topologyKey: zone
#如果写在一起,可能启动顺序会有错误,比如第二个pod先启动。不管pod调度到哪个节点,都都是以zone标签作为位置。
[root@k8smaster node]# kubectl apply -f pod-first-required-anti-affinity-demo-1.yaml 
pod/pod-first created
[root@k8smaster node]# kubectl apply -f pod-second-required-anti-affinity-demo-1.yaml 
pod/pod-second created
[root@k8smaster node]# kubectl get pods -o wide
NAME                          READY   STATUS    RESTARTS   AGE     IP            NODE       NOMINATED NODE  
pod-first                     1/1     Running   0          21s     10.244.1.23   k8snode2   <none>           
pod-second                    0/1     pending   0          21s     <none>        <none>     <none>   


第二个节点现是 pending,因为两个节点是同一个位置(因为配置了一样的zone标签,如果pod1调度到有zone标签的node上,那么第二个pod就永远不会调度到有zone标签的node上,因为我们要求的是反亲和性)现在没有不是同一个位置的了,所以就会处于 pending 状态,如果在反亲和性这个位置把 required 改成 preferred,那么也会运行。


podaffinity:pod 节点亲和性,pod 倾向于哪个 pod


nodeaffinity:node 节点亲和性,pod 倾向于哪个 node

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
1月前
|
存储 Kubernetes 开发者
容器化时代的领航者:Docker 和 Kubernetes 云原生时代的黄金搭档
Docker 是一种开源的应用容器引擎,允许开发者将应用程序及其依赖打包成可移植的镜像,并在任何支持 Docker 的平台上运行。其核心概念包括镜像、容器和仓库。镜像是只读的文件系统,容器是镜像的运行实例,仓库用于存储和分发镜像。Kubernetes(k8s)则是容器集群管理系统,提供自动化部署、扩展和维护等功能,支持服务发现、负载均衡、自动伸缩等特性。两者结合使用,可以实现高效的容器化应用管理和运维。Docker 主要用于单主机上的容器管理,而 Kubernetes 则专注于跨多主机的容器编排与调度。尽管 k8s 逐渐减少了对 Docker 作为容器运行时的支持,但 Doc
152 5
容器化时代的领航者:Docker 和 Kubernetes 云原生时代的黄金搭档
|
2月前
|
Kubernetes Cloud Native 微服务
云原生入门与实践:Kubernetes的简易部署
云原生技术正改变着现代应用的开发和部署方式。本文将引导你了解云原生的基础概念,并重点介绍如何使用Kubernetes进行容器编排。我们将通过一个简易的示例来展示如何快速启动一个Kubernetes集群,并在其上运行一个简单的应用。无论你是云原生新手还是希望扩展现有知识,本文都将为你提供实用的信息和启发性的见解。
|
2月前
|
Kubernetes Cloud Native 开发者
云原生入门:Kubernetes的简易指南
【10月更文挑战第41天】本文将带你进入云原生的世界,特别是Kubernetes——一个强大的容器编排平台。我们将一起探索它的基本概念和操作,让你能够轻松管理和部署应用。无论你是新手还是有经验的开发者,这篇文章都能让你对Kubernetes有更深入的理解。
|
2月前
|
运维 Kubernetes Cloud Native
云原生技术入门:Kubernetes和Docker的协同工作
【10月更文挑战第43天】在云计算时代,云原生技术成为推动现代软件部署和运行的关键力量。本篇文章将带你了解云原生的基本概念,重点探讨Kubernetes和Docker如何协同工作以支持容器化应用的生命周期管理。通过实际代码示例,我们将展示如何在Kubernetes集群中部署和管理Docker容器,从而为初学者提供一条清晰的学习路径。
|
2月前
|
Kubernetes Cloud Native 云计算
云原生入门:Kubernetes 和容器化基础
在这篇文章中,我们将一起揭开云原生技术的神秘面纱。通过简单易懂的语言,我们将探索如何利用Kubernetes和容器化技术简化应用的部署和管理。无论你是初学者还是有一定经验的开发者,本文都将为你提供一条清晰的道路,帮助你理解和运用这些强大的工具。让我们从基础开始,逐步深入了解,最终能够自信地使用这些技术来优化我们的工作流程。
|
1月前
|
运维 Cloud Native 持续交付
深入理解云原生架构及其在现代企业中的应用
随着数字化转型的浪潮席卷全球,企业正面临着前所未有的挑战与机遇。云计算技术的迅猛发展,特别是云原生架构的兴起,正在重塑企业的IT基础设施和软件开发模式。本文将深入探讨云原生的核心概念、关键技术以及如何在企业中实施云原生策略,以实现更高效的资源利用和更快的市场响应速度。通过分析云原生架构的优势和面临的挑战,我们将揭示它如何助力企业在激烈的市场竞争中保持领先地位。
|
1月前
|
Kubernetes Cloud Native 微服务
探索云原生技术:容器化与微服务架构的融合之旅
本文将带领读者深入了解云原生技术的核心概念,特别是容器化和微服务架构如何相辅相成,共同构建现代软件系统。我们将通过实际代码示例,探讨如何在云平台上部署和管理微服务,以及如何使用容器编排工具来自动化这一过程。文章旨在为开发者和技术决策者提供实用的指导,帮助他们在云原生时代中更好地设计、部署和维护应用。
|
2月前
|
Cloud Native Devops 云计算
云计算的未来:云原生架构与微服务的革命####
【10月更文挑战第21天】 随着企业数字化转型的加速,云原生技术正迅速成为IT行业的新宠。本文深入探讨了云原生架构的核心理念、关键技术如容器化和微服务的优势,以及如何通过这些技术实现高效、灵活且可扩展的现代应用开发。我们将揭示云原生如何重塑软件开发流程,提升业务敏捷性,并探索其对企业IT架构的深远影响。 ####
68 3
|
2月前
|
Cloud Native 持续交付 云计算
云原生架构的演进与挑战
随着云计算技术的不断发展,云原生架构已成为企业数字化转型的重要支撑。本文深入探讨了云原生架构的概念、发展历程、核心技术以及面临的挑战,旨在为读者提供一个全面了解云原生架构的视角。通过分析Kubernetes、Docker等关键技术的应用,以及微服务、持续集成/持续部署(CI/CD)等实践案例,本文揭示了云原生架构在提高应用开发效率、降低运维成本、增强系统可扩展性等方面的显著优势。同时,也指出了云原生架构在安全性、复杂性管理等方面所面临的挑战,并提出了相应的解决策略。
|
1月前
|
运维 Cloud Native 持续交付
云原生技术深度探索:重塑现代IT架构的无形之力####
本文深入剖析了云原生技术的核心概念、关键技术组件及其对现代IT架构变革的深远影响。通过实例解析,揭示云原生如何促进企业实现敏捷开发、弹性伸缩与成本优化,为数字化转型提供强有力的技术支撑。不同于传统综述,本摘要直接聚焦于云原生技术的价值本质,旨在为读者构建一个宏观且具体的技术蓝图。 ####