【云原生】Kubernetes资源配额+HPA+节点选择器+亲和性+污点

Kubernetes高级功能

文章目录

  • Kubernetes高级功能
    • 一、资源配额
      • 1.1、什么是资源配额
      • 1.2、资源配额应用
        • 1.2.1、针对Namespace设置资源配额
        • 1.2.2、针对Pod设置资源配额
    • 二、HorizontalPodAutoscaler(HPA)
      • 2.1、什么是HorizontalPodAutoscaler
      • 2.2、HorizontalPodAutoscaler支持的指标
      • 2.3、指标来源
      • 2.4、HorizontalPodAutoscaler应用
        • 2.4.1、部署Metrics
        • 2.4.2、准备测试服务
        • 2.4.3、命令行配置HPA
        • 2.4.4、编写yaml文件配置HPA
        • 2.4.5、HPA测试
    • 三、节点选择器
      • 3.1、通过nodeSelector
      • 3.2、通过nodeName
    • 四、亲和性
      • 4.1、Node亲和性
      • 4.2、Pod亲和性
        • 4.2.1、Pod亲和
        • 4.2.2、Pod反亲和
    • 五、五点容忍
      • 5.1、污点
        • 5.1.1、添加污点
        • 5.1.2、查看污点
        • 5.1.3、删除污点
      • 5.2、容忍
        • 5.2.1、设置污点
        • 5.2.2、运行没有容忍的Pod
        • 5.2.3、运行带有容忍的Pod

一、资源配额

1.1、什么是资源配额

  • 当多个用户或团队共享具有固定节点数目的集群时,人们会担心有人使用超过其基于公平原则所分配到的资源量
  • 资源配额是帮助管理员解决这一问题的工具。
  • 资源配额,通过ResourceQuota对象来定义,对每个命名空间的资源消耗总量提供限制。它可以限制命名空间中某种类型的对象的总数目上限,也可以限制命名空间中的Pod可以使用的计算资源的总上限。
  • 对于cpu和memory资源:ResourceQuota强制该命名空间中的每个(新)Pod为该资源设置限制。如果你在命名空间中为cpu和memory实施资源配额,你或其他客户端必须为你提交的每个新Pod指定资源的requests或limits。否则,控制平面可能会决绝接纳该Pod。
  • 对于其他资源:ResourceQuota可以工作,并且会忽略命名空间中的Pod。而无需为该资源设置限制或请求。这意味着,如果资源配额限制了此命名空间的临时存储,则可以创建没有限制/请求临时存储的新Pod。你可以使用限制范围自动设置对这些资源的默认请求。

1.2、资源配额应用

1.2.1、针对Namespace设置资源配额
  • 创建的ResourceQuota对象将在test命名空间添加限制,每个容器必须设置内存请求(memory request),内存限额(memory limit),cpu请求(cpu request)和cpu限额(cpu limit),所有容器的内存请求总额不得超过2GiB,所有容器的内存限额总额不得超过4GiB,所有容器的CPU请求总额不得超过2CPU,所有容器的CPU限额不得超过4CPU
[root@master ~]# cat namespace_ResourceQuota.yaml 
apiVersion: v1
kind: Namespace
metadata:
  name: test
---
apiVersion: v1
kind: ResourceQuota
metadata:
  name: mem-cpu-quota
  namespace: test
spec:
  hard:
    # 启动Pod时所有Pod请求的CPU个数不得超过2个
    requests.cpu: "2"
    # 启动Pod时所有Pod请求的内存总和不得超过2G
    requests.memory: "2Gi"
    # 限制所有Pod的CPU请求总和不得超过4个
    limits.cpu: "4"
    # 限制所有Pod的内存请求总和不得超过4G
    limits.memory: "4Gi"


# 部署资源
[root@master ~]# kubectl apply -f namespace_ResourceQuota.yaml 
namespace/test created
resourcequota/mem-cpu-quota created


# 可以通过describe查看test命名空间中我们设置的资源配额限制
[root@master ~]# kubectl describe ns test
Name:         test
Labels:       kubernetes.io/metadata.name=test
Annotations:  <none>
Status:       Active

Resource Quotas
  Name:            mem-cpu-quota
  Resource         Used  Hard
  --------         ---   ---
  limits.cpu       0     4
  limits.memory    0     4Gi
  requests.cpu     0     2
  requests.memory  0     2Gi

No LimitRange resource.
1.2.2、针对Pod设置资源配额
  • 对于有资源限制的命名空间,下面的Pod,创建Pod时候必须设置资源限额。否则创建失败
  • requests:代表容器启动请求的资源限制,分配的资源必须要达到此要求。
  • limits:代表最多可以请求多少资源
  • 单位m:CPU的计量单位叫毫核(m)。一个节点的CPU核心数量乘以1000,得到的就是节点的总的CPU总数量。如,一个节点有两个核,那么该节点的CPU总量为2000m。
# 该容器启动时请求500/2000的核心(%25)
[root@master ~]# cat pod_resources.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: test-nginx
  namespace: test
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    ports:
      - containerPort: 80
    image: nginx
    imagePullPolicy: IfNotPresent
    # 定义了容器请求和限制的资源量
    resources:
    # 定义容器请求资源量
      requests:
        # 容器启动时请求100MiB的内存
        memory: "100Mi"
        # 启动启动时请求500mCPU(即0.5个CPU核心)
        cpu: "500m"
      # 定义容器限制资源量
      limits:
        # 容器可使用的最大内存限制为2GiB 
        memory: "2Gi"
        # 启动可使用的最大CPU限制为2个CPU核心
        cpu: "2" 


# 部署资源
[root@master ~]# kubectl apply -f pod_resources.yaml 
pod/test-nginx created

二、HorizontalPodAutoscaler(HPA)

2.1、什么是HorizontalPodAutoscaler

  • HorizontalPodAutoscaler简称HAP,用来自动化的去扩缩容,防止以外的业务量增大导致管理员措手不及,Kubernetes为我们提供了这样一个资源对象:HorizontalPodAutoscaler(Pod水平自动伸缩),简称HPA。HPA通过监控分析RC或Deployment控制的所有Pod的负载变化情况来确定是否需要调整Pod的副本数量,这是HPA最基本的原理。

  • HorizontalPodAutoscaler(简称HAP)自动更新工作负载资源(例如Deployment或StatefulSet),目的是自动扩缩工作负载以满足需求。

  • 水平扩缩意味着对增加的负载的响应是部署更多的Pod。这与“垂直扩缩”不同,对于Kubernetes,垂直扩缩意味着将更多资源(例如:内存或CPU)分配给已经为工作负载运行的Pod。

  • 如果负载减少,并且Pod的数量高于配置的最小值,HorizontalPodAutoscaler会指示工作资源(Deployment、StatefulSet、或其他类资源)缩减

2.2、HorizontalPodAutoscaler支持的指标

  • HPA支持的指标可以使用kubectl api-versions | grep autoscal命令查询
[root@master ~]# kubectl api-versions | grep autoscal
autoscaling/v1
autoscaling/v2
autoscaling/v2beta1
autoscaling/v2beta2


# autoscaling/v1:只支持基于CPU的缩放
# autoscaling/v2:支持Resource Metrics(资源指标,如pod的CPU。内存)和Custom Metrics(自定义指标)的缩放
# autoscaling/v2beta1:支持Resource Metrics(资源指标,如Pod的CPU,内存)和Custom Metrics(自定义指标)和ExternalMetrics(额外指标)的缩放,但是目前也仅仅是出于beta阶段
# autoscaling/v2beta2(稳定版本):其中包括对基于内存和自定义指标扩缩的支持

2.3、指标来源

  • HPA会像资源监控系统获取Pod的资源使用情况,资源监控系统是容器编排系统必不可少的自建,它为用户提供了快速了解系统资源分配和利用状态的有效突进,同时也是系统编排赖以实现的基础要件。
  • 老的版本使用Heapster进行资源各项资源指标数据的采集,从Kubernetes1.11开始Heapster被废弃不在使用,metrics-server替代了Heapster
  • K8S从1.8版本卡死hi,CPU、内存的等资源的信息可以通过Metrics API来获取,用户可以直接获取这些metrics信息(例如通过执行kubectl top),HAP使用这些metaics信息来实现动态的伸缩

Metrics API:

  • 通过Metrics API我们可以获取到指定node或者pod的当前资源使用情况,API本身不存储任何信息,所以我们不可以通过API来获取资源的历史使用情况
  • Mterics API的获取路径位于:/apis/metrics.k8s.io/
  • 获取Metrics API的前提条件是metrics server要在K8S集群中成功部署
  • 更多有关metrics资源请参考:https://github.com/kubernetes/metrics

Metrics server:

  • Metrics server是K8S集群资源使用情况的集合器
  • 从1.8版本开始,Metrics server默认可以通过kubectl-up.sh脚本以deployment的方式进行部署,也可以通过yaml文件的方式进行部署
  • metrics server收集所有node节点的metrics信息

2.4、HorizontalPodAutoscaler应用

2.4.1、部署Metrics
# 加载配置文件以后需要等待1分钟左右,使其配置加载成功,再使用top查询node节点的资源使用情况
[root@master ~]# kubectl apply -f components.yaml 
serviceaccount/metrics-server created
clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created
clusterrole.rbac.authorization.k8s.io/system:metrics-server created
rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created
clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator created
clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created
service/metrics-server created
deployment.apps/metrics-server created
apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io created


# 使用kubectl top命令可以查询资源使用情况
[root@master ~]# kubectl top node
NAME     CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   
master   83m          4%     842Mi           22%       
node1    20m          1%     316Mi           8%        
node2    22m          1%     322Mi           8%        
2.4.2、准备测试服务
  • 注意在所有node节点上上传镜像文件cpu_stress_v3.tar.gz,使用docker load加载一下
[root@master ~]# cat stress.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: stress
spec:
  replicas: 1
  selector:
    matchLabels:
      app: stress
  template:
    metadata:
      labels:
        app: stress
    spec:
      containers:
      - name: stress
        image: cpu_stress:v3
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        # 定义一个资源请求和限制
        resources:
          requests:
            cpu: "100m"
          limits:
            cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
  name: stress
spec:
  ports:
  - port: 80
    targetPort: 80
  selector: 
    app: stress


# 部署资源
[root@master ~]# kubectl apply -f stress.yaml 
deployment.apps/stress created
service/stress created
2.4.3、命令行配置HPA
# --cpu-percent:指定pod的cpu使用率维持在50%左右,超过就扩容小于就缩容
# --min:指定Pod数量最少多少
# --max:指定Pod数量最多多少
# 以西为的deployment资源stress进行配置
[root@master ~]# kubectl autoscale deployment stress --cpu-percent=50 --min=1 --max=10
horizontalpodautoscaler.autoscaling/stress autoscaled


# 查看hpa
[root@master ~]# kubectl get hpa
NAME     REFERENCE           TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
stress   Deployment/stress   0%/50%    1         10        1          74s
2.4.4、编写yaml文件配置HPA
# scaleTargetRef:指定要缩放的目标,在这里是“stress”这个Dployment
# minReplicas:1缩放的最小的Pod的数量
# maxReplicas:10缩放的最大的Pod的数量
[root@master ~]# cat stress_hap.yaml 
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: stress
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment # 目标资源类型为Deployment
    name: stress    # 目标Deployment的名称为stress
  minReplicas: 1	# 表示Pod的缩放最小数量
  maxReplicas: 10   # 表示Pod的增加最大数量
  metrics:
  - type: Resource	# 指定要缩放所用的资源类型,这里是资源利用率指标
    resource:
      name: cpu		# 指定资源类型,这里是CPU
      target:
        type: Utilization	# 表示基于CPU利用率百分比来自动扩缩容
        averageUtilization: 50  # 平均利用率为50%。当利用率超过这个目标值时会缩放Pod的数量


# 部署资源(可能会出现一个警告的信息,没有关系不影响)
[root@master ~]# kubectl apply -f stress_hap.yaml 
horizontalpodautoscaler.autoscaling/stress created


[root@master ~]# kubectl get hpa
NAME     REFERENCE           TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
stress   Deployment/stress   0%/50%    1         10        1          3m56s
2.4.5、HPA测试
[root@master ~]# cat test.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: cpustress
spec:
  replicas: 1
  selector:
    matchLabels: 
      app: cpustress
  template:
    metadata:
      labels:
        app: cpustress
    spec:
      containers:
      - name: cpustress
        image: alpine
        imagePullPolicy: IfNotPresent
        command:
        - "sh"
        - "-c"
        - "sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories && apk update && apk add curl && while true; do curl stress/stress?duration=30&load=70 ;sleep 32;done"


# 部署资源
[root@master ~]# kubectl apply -f test.yaml 
deployment.apps/cpustress created


# 查看HPA情况
[root@master ~]# kubectl get hpa
NAME     REFERENCE           TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
stress   Deployment/stress   62%/50%   1         10        10         12m


# 查看Pod的是否增加
[root@master ~]# kubectl get pod
NAME                         READY   STATUS    RESTARTS   AGE
cpustress-649d7f6485-6dxrr   1/1     Running   0          3m
stress-548b54ff89-457cx      1/1     Running   0          2m1s
stress-548b54ff89-4hstr      1/1     Running   0          2m1s
stress-548b54ff89-877d9      1/1     Running   0          2m1s
stress-548b54ff89-9hg62      1/1     Running   0          2m16s
stress-548b54ff89-b9qnl      1/1     Running   0          23m
stress-548b54ff89-bblxr      1/1     Running   0          2m16s
stress-548b54ff89-fnwt5      1/1     Running   0          106s
stress-548b54ff89-k2dkw      1/1     Running   0          2m1s
stress-548b54ff89-mdklt      1/1     Running   0          106s
stress-548b54ff89-xn4tc      1/1     Running   0          2m16s


# 停止压力测试
[root@master ~]# kubectl delete -f test.yaml 
deployment.apps "cpustress" deleted


# 等待一段时间会发现Pod的数量降下来了,可能需要几分钟
[root@master ~]# kubectl get pod
NAME                      READY   STATUS    RESTARTS   AGE
stress-548b54ff89-b9qnl   1/1     Running   0          66m

三、节点选择器

3.1、通过nodeSelector

  • nodeSelector是节点选择约束的最简单的推荐形式。你可以将nodeSelector字段添加到Pod的规约中设置你希望目标节点所具有的节点标签。Kubernetes只会将Pod踢调度到拥有你所指定的每个标签的节点上。
# 该示例是运行Pod在具有disk=ceph标签的节点上
[root@master ~]# cat pod_nodeSelector.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: podnodeselector
  namespace: default
  labels:
    app: nginx
spec:
  nodeSelector:
    disk: ceph
  containers:
  - name: podnodeselector
    ports:
      - containerPort: 80
    image: nginx
    imagePullPolicy: IfNotPresent
    resources:
      requests:
        memory: "100Mi"
        cpu: "500m"
      limits:
        memory: "1Gi"
        cpu: "1"  


# 部署资源
[root@master ~]# kubectl apply -f pod_nodeSelector.yaml 
pod/podnodeselector created


# 可以看到没有节点带有disk=ceph标签,所以Pod是Pending状态
[root@master ~]# kubectl get pod
NAME                      READY   STATUS    RESTARTS   AGE
podnodeselector           0/1     Pending   0          56s
stress-548b54ff89-b9qnl   1/1     Running   0          73m
[root@master ~]# kubectl get node -l disk=ceph
No resources found


# 给node1节点打标签,然后Pod就自动运行在有指定标签的节点了
[root@master ~]# kubectl label node node1 disk=ceph
node/node1 labeled
[root@master ~]# kubectl get node -l disk=ceph
NAME    STATUS   ROLES    AGE     VERSION
node1   Ready    <none>   6d18h   v1.23.0
[root@master ~]# kubectl get pod -o wide
NAME                      READY   STATUS    RESTARTS   AGE    IP           NODE    NOMINATED NODE   READINESS GATES
podnodeselector           1/1     Running   0          2m4s   10.244.2.8   node1   <none>           <none>

3.2、通过nodeName

  • nodeName是比性和性或者nodeSelector更为直接的形式。nodeName是Pod规约中的一个字段。如果nodeName字段不为空,调度器会忽略该Pod,而指定节点上的kubelet会尝试将Pod放到该节点上。使用nodeName规则的优先级会高于使用nodeSelector或亲和性与非亲和性的规则。

使用nodeName来选择节点的方式有一些局限性

  • 如果所指定的节点不存在,则Pod无法运行,而且在某些情况下会被自动删除。
  • 如果所指定的节点无法提供用来运行Pod所需的资源,Pod会失败,而其失败原因中会给出是否因为内存或CPU不足而造成无法运行
  • 在云环境中的节点名称并不总是可预测的,也不总是稳定的
[root@master ~]# cat nodeName.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: podnodename
  namespace: default
  labels:
    app: nginx
spec:
  nodeName: node1
  containers:
  - name: podnodename
    image: nginx
    imagePullPolicy: IfNotPresent


# 部署资源
[root@master ~]# kubectl apply -f nodeName.yaml 
pod/podnodename created


# 查看是否调度到指定节点
[root@master ~]# kubectl get pod -o wide
NAME                      READY   STATUS    RESTARTS   AGE     IP           NODE    NOMINATED NODE   READINESS GATES
podnodename               1/1     Running   0          31s     10.244.2.9   node1   <none>           <none>

四、亲和性

  • Affinity翻译成中文是“亲和性”,它对应的是Anti-Affinity,我们翻译成“互斥”。这两个词比较形象,可以把pod选择node的过程比成磁铁的吸引和互斥,不同的是除了简单的正负极之外,pod和node的吸引和互斥是可以灵活配置的。

Affinity的优点

  • 匹配有更多的逻辑组合,不只是字符串的完成相等
  • 调度分为软策略和硬策略,在软策略下,如果没有满足调度条件的节点,node会忽略这条规则,继续完成调度

目前主要的node affinity:

  • requiredDuringSchedulingIgnoredDuringExecution:表示Pod必须部署到满足条件的节点上,如果没有满足条件的节点,就不停重试。其中IgnoreDuringExecution表示Pod部署之后运行的时候,如果节点标签发生了变化,不再满足Pod指定的条件,Pod也会继续运行

  • requiredDuringSchedulingRequiredDuringExecution:表示Pod必须部署到满足条件的节点上,如果没有满足条件的节点。就不听重试。其中RequitredDuringExecution表示Pod部署之后运行的时候,如果节点标签发生了变化,不再满足Pod的指定的条件,则重新选择符合要求的节点

  • preferredDuringSchedulingRequiredDuringExecution:表示优先部署到满足的节点上,如果没有满足条件的节点,就忽略这些条件,按照正常逻辑部署,其中RequitredDuringExecution表示如果后面节点标签发生了变化,满足了条件,则重新调度到满足条件的节点

4.1、Node亲和性

  • node节点亲和性调度:nodeAffinity
  • 使用requiredDuringSchedulingIgnoredDuringExecution硬亲和性节点有disktype=ssd标签或disktype=hhd标签即可被调度,若是都没有Pod则是Pending状态
[root@master ~]# cat podAffinity.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-node-affinity-demo
  namespace: default
  labels:
    app01: nginx
spec:
  containers:
  - name: nginx
    ports:
      - containerPort: 80
    image: nginx
    imagePullPolicy: IfNotPresent
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
           - key: disktype
             operator: In
             values:
             - ssh
             - hhd


# 部署资源
[root@master ~]# kubectl apply -f podAffinity.yaml 
pod/pod-node-affinity-demo created


# 查看pod状态时Pending,因为没有节点带有disktyp=ssd标签或者disktype=hhd标签
[root@master ~]# kubectl get pod 
NAME                      READY   STATUS    RESTARTS   AGE
pod-node-affinity-demo    0/1     Pending   0          61s
[root@master ~]# kubectl get node -l disktype=ssd
No resources found
[root@master ~]# kubectl get node -l disktype=hhd
No resources found


# 打标签以后发现Pod就正常运行了,并且是运行在打标签的节点上
[root@master ~]# kubectl label node node1 disktype=ssh
node/node1 labeled
[root@master ~]# kubectl get pod -o wide
NAME                      READY   STATUS    RESTARTS   AGE    IP            NODE    NOMINATED NODE   READINESS GATES
pod-node-affinity-demo    1/1     Running   0          5m6s   10.244.2.10   node1   <none>           <none>

4.2、Pod亲和性

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

  • podaffinity:Pod和Pod更倾向于腻在一起,把相近的pod结合到相近的位置,如同一区域,同一机架,这样的话‘pod和pod之间更好通信,比方说有两个机房,这两个机房部署的集群有1000台主机,那么我们希望把nginx和tomcat都部署同一个地方的node节点上,可以提高通信效率
  • poddunaffinity:pod和pod更倾向于不腻在一起,如果部署两台程序,那么这两套程序更倾向于反亲和性,这样相互之间不会有影响
  • 第一个pod随机选择一个节点,作为评判后续的Pod是否到达这个Pod所在的节点上运行方式,这就成为Pod亲和性;我们怎么判断哪些节点是相同位置,哪些节点不同位置;我们在定义pod亲和性时需要有一个提前,哪些pod在同一位置,哪些pod不在同一位置,这个位置是怎么定义的,标准是什么?以节点名称为标准,这个节点相同表示是同一个位置,节点名称不相同的表示不是一个位置

topplogyKey:

  • 位置拓扑的键,这个是必须字段
  • 怎么判断是不是同一个位置
  • rack=rack1
  • row=row1
  • 使用rack的键是同一个位置
  • 使用row的键是同一个位置

labelsSelector:

  • 我们要判断pod跟别的pod亲和,跟哪个pod亲和,需要靠labelSelector,通过labelSelector选择一组作为亲和对象的pod资源

namspace:

  • labelSelector:需要选择一组资源,那么这组资源是在哪个名称空间中呢,通过namespace指定,如果不指定namespace,那么就是当前创建的Pod 的名称空间
4.2.1、Pod亲和
  • Pod亲和就是后启动的Pod要和前面启动的Pod调度在一个节点上,使用podAffinity字段定义
[root@master ~]# cat podAffinity.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: nginx01
  namespace: default
  labels:
    app01: nginx01
spec:
  containers:
  - name: mynginx
    ports:
      - containerPort: 80
    image: nginx
    imagePullPolicy: IfNotPresent
---
apiVersion: v1
kind: Pod
metadata:
  name: nginx02
  namespace: default
  labels:
    app02: nginx02
spec:
  containers:
  - name: mynginx
    ports:
      - containerPort: 80
    image: nginx
    imagePullPolicy: IfNotPresent
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
            - key: app01
              operator: In
              values:
              - nginx01
        topologyKey: kubernetes.io/hostname # 每个节点都有kubernetes.io/hostname标签,这个标签通常是主机名,topologKey制定了这个标签意思是限定在一个节点上


# 部署资源
[root@master ~]# kubectl apply -f podAffinity.yaml 
pod/nginx01 created
pod/nginx02 created


[root@master ~]# kubectl get pod -o wide
NAME                      READY   STATUS    RESTARTS   AGE    IP            NODE    NOMINATED NODE   READINESS GATES
nginx01                   1/1     Running   0          33s    10.244.1.16   node2   <none>           <none>
nginx02                   1/1     Running   0          33s    10.244.1.15   node2   <none>           <none>
4.2.2、Pod反亲和
  • Pod反亲和就是后启动的Pod要和前面启动的Pod不调度在一个节点上,使用podAntiAffinity字段定义
[root@master ~]# cat podAntiAffinity.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: nginx01
  namespace: default
  labels:
    app01: nginx01
spec:
  containers:
  - name: mynginx
    ports:
      - containerPort: 80
    image: nginx
    imagePullPolicy: IfNotPresent
---
apiVersion: v1
kind: Pod
metadata:
  name: nginx02
  namespace: default
  labels:
    app02: nginx02
spec:
  containers:
  - name: mynginx
    ports:
      - containerPort: 80
    image: nginx
    imagePullPolicy: IfNotPresent
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
            - key: app01
              operator: In
              values:
              - nginx01
        topologyKey: kubernetes.io/hostname 


# 部署资源
[root@master ~]# kubectl apply -f podAntiAffinity.yaml 
pod/nginx01 created
pod/nginx02 created


[root@master ~]# kubectl get pod -o wide
NAME                      READY   STATUS    RESTARTS   AGE    IP            NODE    NOMINATED NODE   READINESS GATES
nginx01                   1/1     Running   0          36s    10.244.1.19   node2   <none>           <none>
nginx02                   1/1     Running   0          36s    10.244.2.11   node1   <none>           <none>

五、五点容忍

  • 节点亲和性是Pod的一种属性,它使Pod被吸引到一类特定的节点(这可能处于一种偏好,也可能是硬性要求)。污点(Taint)则相反——它使节点能够排斥一类特定的Pod。
  • 容忍度(Toeration)是应用于Pod上的。容忍度允许调度器调度带有对应污点的Pod容忍度允许调度并不保存调度:作为其功能的一部分,调度器也会评估其他参数
  • 污点和容忍度(Toleration)相互配合,可以用来避免Pod被分配到不合适的节点上。每个节点都可以应用一个或多个污点,这表示对于那些不能容器这些污点的Pod。是不会被节点接受的

5.1、污点

  • 我们给节点打一个污点,不容器的pod就运行不上来了,污点就是定义在节点上的键值属性数据,可以决定拒绝那些pod

  • 使用kubeadm安装的Kubernetes集群的master节点默认具有node-role.kubernetes.io/master:NoSchedule污点

    每个污点有一个key和value作为污点的标签,effect描述污点的作用。当前faint effect支持如下效果:

  • NoSchedule:表示K8S将不会把Pod调度到具有该污点的Node节点上

  • PreferNoSchedule:表示K8S将尽量避免把Pod调度到具有该污点的Node节点上

  • NoExecyute:表示K8S将不会把Pod调度到具有该污点的Node节点上,同时会将Node上已经存在的Pod驱逐出去

5.1.1、添加污点
# 给节点 node1 增加一个污点,它的键名是 key1,键值是 value1,效果是NoSchedule
[root@master ~]# kubectl taint nodes node1 key1=value1:NoSchedule
node/node1 tainted
5.1.2、查看污点
# 查询 node1 节点污点,找到Taints
[root@master ~]# kubectl describe node node1 | grep Taints
Taints:             key1=value1:NoSchedule
5.1.3、删除污点
# 去除节点 node1 的污点,它的键名是 key1,键值是value1,效果是NoSchedule
[root@master ~]# kubectl taint node node1 key1=value1:NoSchedule-
node/node1 untainted

5.2、容忍

  • 默认情况下,Pod是不会运行在具有污点的节点上,但是我们可以配置容忍,让Pod运行在这个节点
5.2.1、设置污点
[root@master ~]# kubectl get node
NAME     STATUS   ROLES                  AGE     VERSION
master   Ready    control-plane,master   6d19h   v1.23.0
node1    Ready    <none>                 6d19h   v1.23.0
node2    Ready    <none>                 6d19h   v1.23.0
[root@master ~]# kubectl taint node node1 node-type=test:NoSchedule
node/node1 tainted
[root@master ~]# kubectl taint node node2 node-type=production:NoSchedule
node/node2 tainted
5.2.2、运行没有容忍的Pod
[root@master ~]# cat nginx-taint.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: default
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
    - name: http
      containerPort: 80


# 部署资源
[root@master ~]# kubectl apply -f nginx-taint.yaml 
pod/nginx created


[root@master ~]# kubectl get pod
NAME                      READY   STATUS    RESTARTS   AGE
nginx                     0/1     Pending   0          29s


# 使用describe查询
[root@master ~]# kubectl describe pod nginx
Name:         nginx
Namespace:    default
Priority:     0
Node:         <none>
Labels:       app=nginx
Annotations:  <none>
Status:       Pending
IP:           
IPs:          <none>
Containers:
  nginx:
    Image:        nginx
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-48d2z (ro)
Conditions:
  Type           Status
  PodScheduled   False 
Volumes:
  kube-api-access-48d2z:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   BestEffort
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type     Reason            Age   From               Message
  ----     ------            ----  ----               -------
#################################################################### 
  Warning  FailedScheduling  51s   default-scheduler  0/3 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate, 1 node(s) had taint {node-type: production}, that the pod didn't tolerate, 1 node(s) had taint {node-type: test}, that the pod didn't tolerate.
####################################################################
5.2.3、运行带有容忍的Pod
[root@master ~]# cat nginx-taint.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: default
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
    - name: http
      containerPort: 80
    # 容忍key是node-type,value是production,污点级NoSchedule的污点
  tolerations:
  - key: "node-type"
    operator: "Equal"
    value: "production"
    effect: "NoSchedule"


# 部署资源
[root@master ~]# kubectl apply -f nginx-taint.yaml 
pod/nginx configured


# 因为该Pod定义了容忍node-type=production:NoSchedule污点所以可以在node2节点运行
[root@master ~]# kubectl get pod -o wide
NAME                      READY   STATUS    RESTARTS   AGE     IP            NODE    NOMINATED NODE   READINESS GATES
nginx                     1/1     Running   0          4m31s   10.244.1.20   node2   <none>           <none>
# 只要对应的键是存在的,exists,其值被自动定义成通配符
tolerations:
- key: "node-type"
  operator: "Exists"
  value: ""
  effect: "NoSchedule
# 有一个node-type的键,不管值是什么,不管是什么效果,都能容忍
tolerations:
- key: "node-type"
  operator: "Exists"
  value: ""
  effect: ""

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/774500.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

快递物流运输中的RFID智能锁控应用方案

一、物流货运管理的痛点分析 1.1 货物安全与监控难题 物流货运过程中&#xff0c;货物安全是首要关注的问题。传统的锁控方式存在诸多不足&#xff0c;例如易被撬锁、监控盲点以及难以实时追踪货物状态。据统计&#xff0c;每年因货物丢失或损坏导致的经济损失高达数十亿美元…

景区智能厕所系统,打造智能化,人性化公共空间

在智慧旅游的大潮中&#xff0c;景区智能厕所系统正逐渐成为提升公共空间智能化、人性化水平的关键载体。作为智慧城市建设的重要组成部分&#xff0c;智能厕所系统不仅解决了传统公厕存在的诸多问题&#xff0c;更通过科技的力量&#xff0c;为游客创造了更加舒适、便捷的如厕…

中电金信:加快企业 AI 平台升级,构建金融智能业务新引擎

在当今数字化时代的浪潮下&#xff0c;人工智能&#xff08;AI&#xff09;技术的蓬勃发展正为各行业带来前所未有的变革与创新契机。尤其是在金融领域&#xff0c;AI 模型的广泛应用已然成为提升竞争力、优化业务流程以及实现智能化转型的关键驱动力。然而&#xff0c;企业在积…

Zabbix 配置 VMware 监控

Zabbix监控VMware 官方文档&#xff1a;https://www.zabbix.com/documentation/current/en/manual/vm_monitoring Zabbix 可以使用低级发现规则自动发现 VMware 虚拟机管理程序和虚拟机&#xff0c;并根据预定义的主机原型创建主机来监控它们。Zabbix 还包括用于监控 VMware …

缓存与数据库数据一致性问题

在用了redis缓存的系统中&#xff0c;正常情况下&#xff0c;一个读操作会先查缓存&#xff0c;如果在缓存中查到了&#xff0c;则直接返回&#xff0c;如果缓存中没有&#xff0c;则会查数据库&#xff0c;再将查到的数据写到redis中&#xff0c;然后返回。如下图&#xff1a;…

PDI-kettle工具连接本地虚拟机Ubuntu上的数据库

PDI 配置ubuntu数据库配置Kettle工具 PDI版本&#xff1a;9.4 Ubuntu2204&#xff1a;10.11.8-MariaDB-0ubuntu0.24.04.1 Ubuntu 24.04 配置ubuntu数据库 安装 apt install -y mariadb-server配置监听地址 cat > /etc/mysql/mariadb.conf.d/99-kettle.cnf << EOF …

国衍科技——梅雨季节文物保护专家

尊敬的文物保护者们 随着梅雨季节的脚步渐近&#xff0c;湿润的空气和连绵的雨水不仅为我们的生活带来了不便&#xff0c;更为文物保护工作带来了严峻的挑战。在这个季节&#xff0c;文物发霉的风险急剧上升&#xff0c;每一件珍贵的文化遗产都面临着被时间侵蚀的威胁。然而&am…

玩转内网穿透详细教程,收藏这一篇就够了

小朋友&#xff0c;你是否有过以下这些烦恼&#xff1f; 当你在外地&#xff0c;苦于无法拿到存储在家里的资料&#xff1b; 当你在玩游戏的时候&#xff0c;苦于无法和朋友直接联机&#xff1b; 当你在家里&#xff0c;苦于无法通过自己的电脑连上公司电脑远程办公&#xf…

WPF在.NET9中的重大更新:Windows 11 主题

在2023年的2月20日&#xff0c;在WPF的讨论区&#xff0c;WPF团队对路线的优先级发起了一次讨论。 对三个事项发起了投票。 第一个是Windows 11 主题 第二个是更新的控件 第三个是可空性注释 最终Windows 11 主题得票最高&#xff0c;WPF团队2023-2024的工作优先级就是Windows…

VUE3使用antd引入百度地图 实现位置查询,获取地址经纬度

实现效果: 1.index.html 中先引入下 <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=自己申请的key"></script> 申请密钥key地址:登录百度账号 注册登录后创建应用,根据自己需求选择 2.新建bmp.js文件…

期权学习必看圣书:《3小时快学期权》要在哪里看?

今天带你了解期权学习必看圣书&#xff1a;《3小时快学期权》要在哪里看&#xff1f;《3小时快学期权》是一本关于股票期权基础知识的书籍。 它旨在通过简明、易懂的语言和实用的案例&#xff0c;让读者在短时间内掌握股票期权的基本概念、操作方法和投资策略。通过这本书&…

Hyper-V克隆虚拟机教程分享!

方法1. 使用导出导入功能克隆Hyper-V虚拟机 导出和导入是Hyper-V服务器备份和克隆的一种比较有效的方法。使用此功能&#xff0c;您可以创建Hyper-V虚拟机模板&#xff0c;其中包括软件、VM CPU、RAM和其他设备的配置&#xff0c;这有助于在Hyper-V中快速部署多个虚拟机。 在…

数字信号处理实验二(模拟信号采样与重构及频谱分析FFT)

模拟信号采样与重构及频谱分析FFT&#xff08;2学时&#xff09; 要求&#xff1a; 对一模拟信号进行采样&#xff1b;对该采样信号进行重构&#xff1b;分析它们的频谱特征。目的&#xff1a; 熟悉MATLAB命令和编辑、运行、调试环境&#xff1b;掌握采样定理及对信号的频谱分析…

无线领夹麦克风怎么挑选,无线领夹麦克风哪个品牌音质最好详解!

在数字化内容创作的浪潮中&#xff0c;无线领夹麦克风凭借其轻便的设计和卓越的录音性能&#xff0c;成为了许多创作者不可或缺的音频帮手。这种类型的麦克风能够轻松附着在衣物上&#xff0c;使得创作者在进行直播或录制视频时能够自由移动&#xff0c;而不受传统麦克风线缆的…

STM32智能家居安防系统教程

目录 引言环境准备智能家居安防系统基础代码实现&#xff1a;实现智能家居安防系统 4.1 数据采集模块 4.2 数据处理与分析 4.3 控制系统实现 4.4 用户界面与数据可视化应用场景&#xff1a;安防管理与优化问题解决方案与优化收尾与总结 1. 引言 智能家居安防系统利用STM32嵌…

前端从业者的历史难题Vue和React的抉择:难度不亚于丈母娘和媳妇

**前端从业者的历史难题&#xff1a;Vue和React的抉择——难度不亚于丈母娘和媳妇** Vue和React这两个框架无疑是当下最为流行的两个选择。它们各自拥有独特的优势和特点&#xff0c;吸引了大量的前端从业者。然而&#xff0c;对于许多从业者来说&#xff0c;如何在Vue和React…

D. Beauty of the mountains(cf955)

分析&#xff1a;有一个n*m的数组a&#xff0c;对应n*m的数组b&#xff0c;想让b0的下标的a的数组之和等于b1的下标的a的数组之和&#xff0c;你可以进行k*k的范围所有数字全部加任意数。 求出子矩阵里0和1的差值&#xff1b; #include<bits/stdc.h> using namespace st…

Android 四大组件

1. Activity 应用程序中&#xff0c;一个Activity通常是一个单独的屏幕&#xff0c;它上面可以显示一些控件&#xff0c;也可以监听并对用户的事件做出响应。 Activity之间通过Intent进行通信&#xff0c;在Intent 的描述结构中&#xff0c;有两个最重要的部分&#xff1a;动…

电子行业MES系统解决方案

工业4.0时代的工业自动化&#xff0c;将在原有自动化技术和架构下&#xff0c;实现集中式控制向分散式增强型控制的基本模式转变&#xff0c;让设备从传感器到因特网的通讯能够无缝对接&#xff0c;从而建立一个高度灵活的、个性化和数字化、融合了产品与服务的生产模式。在这种…

springboot城市菜园共享系统-计算机毕业设计源码00524

目 录 摘要 1 绪论 1.1 研究背景与意义 1.2 国内外研究现状和发展趋势 1.3论文结构与章节安排 2 城市菜园共享系统系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据增加流程 2.2.2 数据修改流程 2.2.3 数据删除流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.…