美文网首页云原生
十 Kubernetes高级调度计划任务、污点和容忍、Affi

十 Kubernetes高级调度计划任务、污点和容忍、Affi

作者: 負笈在线 | 来源:发表于2022-05-17 17:55 被阅读0次

(一) Job

Job负责批量处理短暂的一次性任务 (short lived one-off tasks),即仅执行一次的任务,它保证批处理任务的一个或多个Pod成功结束。
中文文档:https://www.kubernetes.org.cn/job
Kubernetes支持以下几种Job:
A:非并行Job:通常创建一个Pod直至其成功结束
B:固定结束次数的Job:设置.spec.completions,创建多个Pod,直到.spec.completions个Pod成功结束
C:带有工作队列的并行Job:设置.spec.Parallelism但不设置.spec.completions,当所有Pod结束并且至少一个成功时,Job就认为是成功


根据.spec.completions和.spec.Parallelism的设置,可以将Job划分为以下几种pattern:

1.job****的使用
[root@k8s-master01 job]# vim job.yaml
apiVersion: batch/v1
kind: Job
metadata:
 labels:
 job-name: echo
 name: echo
 namespace: default
spec:
 suspend: true # 1.21+
 ttlSecondsAfterFinished: 100 //Job在执行结束之后(状态为completed或Failed)自动清理。设置为0表示执行结束立即删除,不设置则不会清除,需要开启TTLAfterFinished特性
 backoffLimit: 4 //如果任务执行失败,失败多少次后不再执行
 completions: 1 //有多少个Pod执行成功,认为任务是成功的,为空默认和parallelism数值一样
 parallelism: 1 //并行执行任务的数量,如果parallelism数值大于未完成任务数,只会创建未完成的数量;比如completions是4,并发是3,第一次会创建3个Pod执行任务,第二次只会创建一个Pod执行任务
 template:
 spec:
 containers:
 - command:
 - echo
 - Hello, Job
 image: registry.cn-beijing.aliyuncs.com/dotbalo/busybox
 imagePullPolicy: Always
 name: echo
 resources: {}
 restartPolicy: Never

创建验证:

[root@k8s-master01 job]# kubectl create -f job.yaml
job.batch/echo created
[root@k8s-master01 job]# kubectl get pod
NAME READY STATUS RESTARTS AGE
echo-9wlwq 0/1 Completed 0 7s
nginx-66cfc7f7d5-jkmvh 1/1 Running 1 6d1h
nginx-66cfc7f7d5-zdk4r 1/1 Running 1 6d1h
[root@k8s-master01 job]# kubectl get job //执行完毕
NAME COMPLETIONS DURATION AGE
echo 1/1 4s 24s
[root@k8s-master01 job]# kubectl logs -f echo-9wlwq //查看日志
Hello, Job

(二) CronJob

中文文档:https://www.kubernetes.org.cn/cronjob
CronJob即定时任务,就类似于Linux系统的crontab,在指定的时间周期运行指定的任务。在Kubernetes 1.5,使用CronJob需要开启batch/v2alpha1 API,即–runtime-config=batch/v2alpha1。

.spec.schedule指定任务运行周期,格式同Cron
.spec.jobTemplate指定需要运行的任务,格式同Job
.spec.startingDeadlineSeconds指定任务开始的截止期限
.spec.concurrencyPolicy指定任务的并发策略,支持Allow、Forbid和Replace三个选项


1.crontab的使用
[root@k8s-master01 job]# vim cronjob.yaml
apiVersion: batch/v1beta1 //1.21+ batch/v1
kind: CronJob
metadata:
 labels:
 run: hello
 name: hello
 namespace: default
spec:
 concurrencyPolicy: Allow //并发调度策略。可选参数如下:Allow:允许同时运行多个任务。Forbid:不允许并发运行,如果之前的任务尚未完成,新的任务不会被创建。Replace:如果之前的任务尚未完成,新的任务会替换的之前的任务。
 failedJobsHistoryLimit: 1 //保留多少失败的任务。
 jobTemplate:
 metadata:
 spec:
 template:
 metadata:
 labels:
 run: hello
 spec:
 containers:
 - args:
 - /bin/sh
 - -c
 - date; echo Hello from the Kubernetes cluster
 image: registry.cn-beijing.aliyuncs.com/dotbalo/busybox
 imagePullPolicy: Always
 name: hello
 resources: {}
 restartPolicy: OnFailure //重启策略,和Pod一致。
 securityContext: {}
 schedule: '*/1 * * * *'             //调度周期,和Linux一致,分别是分时日月周。
 successfulJobsHistoryLimit: 3 //保留多少已完成的任务,按需配置。
 suspend: false //如果设置为true,则暂停任务,默认为false。

创建验证

[root@k8s-master01 job]# kubectl create -f cronjob.yaml
cronjob.batch/hello created
[root@k8s-master01 job]# kubectl get cj //查看cronjob,简称cj
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE  
hello */1 * * * * False 0 43s 56s
[root@k8s-master01 job]# kubectl get pod //查看pod
NAME     READY STATUS RESTARTS AGE
echo-9wlwq 0/1 Completed 0 19m
hello-1629201900-9q7wt 0/1 Completed 0 2m3s
hello-1629201960-jtxj6 0/1 Completed 0 63s
hello-1629202020-87n74 0/1 ContainerCreating 0 2s
nginx-66cfc7f7d5-jkmvh 1/1 Running 1 6d1h
nginx-66cfc7f7d5-zdk4r 1/1 Running 1 6d1h
[root@k8s-master01 job]# kubectl logs hello-1629201900-9q7wt //查看执行日志
Tue Aug 17 12:05:03 UTC 2021
Hello from the Kubernetes cluster

(三) InitContainer**

1.初始化容器的用途

Init容器可以包含一些安装过程中应用容器中不存在的实用工具或个性化代码;
Init容器可以安全地运行这些工具,避免这些工具导致应用镜像的安全性降低;
Init容器可以以root身份运行,执行一些高权限命令;
Init容器相关操作执行完成以后即退出,不会给业务容器带来安全隐患。

在主应用启动之前,做一些初始化的操作,比如创建文件、修改内核参数、等待依赖程序启动或其他需要在主程序启动之前需要做的工作。

2.初始化容器PostStart区别

PostStart:依赖主应用的环境,而且并不一定先于Command运行。
InitContainer:不依赖主应用的环境,可以有更高的权限和更多的工具,一定会在主应用启动之前完成。

3.初始化容器和普通容器的区别

Init容器与普通容器非常像,除了以下几点:
它们总是运行到完成;
上一个运行完成才会运行下一个;
如果Pod的Init容器失败,Kubernetes会不断地重启Pod,直到Init容器成功为止,但是Pod对应的restartPolicy值为Never,Kubernetes不会重新启动Pod;
Init容器不支持lifecycle、livenessProbe、readinessProbe和startupProbe。

4.初始化容器配置示例及解析

[root@k8s-master01 init]# vim init.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
 labels:
 app: test-init
 name: test-init
 namespace: kube-public
spec:
 replicas: 3 //副本数3
 selector:
 matchLabels:
 app: test-init
 template:
 metadata:
 labels:
 app: test-init
 spec:
 volumes:
 - name: data
 emptyDir: {}
 initContainers: //初始化容器,和volumes、containers平级。
 - command:
 - sh
 - -c
 - touch /mnt/test-init.txt //执行的操作
 image: nginx
 imagePullPolicy: IfNotPresent
 name: init-touch //容器名init-touch
 volumeMounts:
 - name: data
 mountPath: /mnt
 - command:
 - sh
 - -c
 - for i in `seq 1 100`; do echo $i; sleep 1; done //执行的操作
 image: nginx
 imagePullPolicy: IfNotPresent
 name: echo //容器名echo
 containers:
 - image: nginx
 imagePullPolicy: IfNotPresent
 name: test-init
 volumeMounts:
 - name: data
 mountPath: /mnt

创建验证:

[root@k8s-master01 init]# kubectl create -f init.yaml
deployment.apps/test-init created
[root@k8s-master01 init]# kubectl get pod -n kube-public //查看pod
NAME READY STATUS RESTARTS AGE
test-init-7c58ff4db4-4gjws 0/1 Init:1/2 0 116s
test-init-7c58ff4db4-m8t2l 0/1 Init:1/2 0 116s
test-init-7c58ff4db4-n68q4 0/1 Init:1/2 0 116s
[root@k8s-master01 init]# kubectl describe pod test-init-7c58ff4db4-4gjws -n kube-public
Name: test-init-7c58ff4db4-4gjws
Namespace: kube-public
Priority: 0
Node: k8s-master03/192.168.1.102
Start Time: Tue, 17 Aug 2021 20:52:57 +0800
Labels: app=test-init
 pod-template-hash=7c58ff4db4
....
 Normal Pulled 2m19s kubelet Successfully pulled image "nginx" in 29.496733351s
 Normal Created 2m18s kubelet Created container init-touch
 Normal Started 2m18s kubelet Started container init-touch
 Normal Pulled 2m18s kubelet Container image "nginx" already present on machine
 Normal Created 2m18s kubelet Created container echo
 Normal Started 2m18s kubelet Started container echo
 Normal Pulled 37s kubelet Container image "nginx" already present on machine
 Normal Created 37s kubelet Created container test-init
 Normal Started 37s kubelet      Started container test-init //显示初始化容器中
[root@k8s-master01 init]# kubectl logs -f test-init-7c58ff4db4-4gjws -c echo -n kube-public //查看其中一个副本echo容器的日志,发现在打印中。

(四) 临时容器EphemeralContainer**

临时容器:1.16版本以上支持
官方文档:https://kubernetes.io/zh/docs/concepts/workloads/pods/ephemeral-containers/
一种特殊的容器,容器在现有 Pod 中临时运行,以便完成用户发起的操作,例如故障排查。 你会使用临时容器来检查服务,而不是用它来构建应用程序.

1.了解临时容器

Pod 是 Kubernetes 应用程序的基本构建块。 由于 Pod 是一次性且可替换的,因此一旦 Pod 创建,就无法将容器加入到 Pod 中。 取而代之的是,通常使用 Deployment 以受控的方式来删除并替换 Pod。
有时有必要检查现有 Pod 的状态。例如,对于难以复现的故障进行排查。 在这些场景中,可以在现有 Pod 中运行临时容器来检查其状态并运行任意命令。

2.什么是临时容器?

临时容器与其他容器的不同之处在于,它们缺少对资源或执行的保证,并且永远不会自动重启, 因此不适用于构建应用程序。 临时容器使用与常规容器相同的 ContainerSpec 节来描述,但许多字段是不兼容和不允许的。

A:临时容器没有端口配置,因此像 ports,livenessProbe,readinessProbe 这样的字段是不允许的。
B:Pod 资源分配是不可变的,因此 resources 配置是不允许的。
C:有关允许字段的完整列表

临时容器是使用 API 中的一种特殊的 ephemeralcontainers 处理器进行创建的, 而不是直接添加到 pod.spec 段,因此无法使用 kubectl edit 来添加一个临时容器。
与常规容器一样,将临时容器添加到 Pod 后,将不能更改或删除临时容器

3.临时容器的用途

当由于容器崩溃或容器镜像不包含调试工具而导致 kubectl exec 无用时, 临时容器对于交互式故障排查很有用。
尤其是,Distroless 镜像 允许用户部署最小的容器镜像,从而减少攻击面并减少故障和漏洞的暴露。 由于 distroless 镜像不包含 Shell 或任何的调试工具,因此很难单独使用 kubectl exec 命令进行故障排查。
使用临时容器时,启用进程名字空间共享很有帮助,可以查看其他容器中的进程。

4.临时容器的使用

开启临时容器
二进制方式:
主节点

# vi /usr/lib/systemd/system/kube-apiserver.service //修改配置文件(二进制搭建)
--feature-gates=EphemeralContainers=true
# vi /usr/lib/systemd/system/kube-controller-manager.service
--feature-gates=EphemeralContainers=true
# vi /usr/lib/systemd/system/kube-scheduler.service
--feature-gates=EphemeralContainers=true

node节点

# vi /usr/lib/systemd/system/kube-proxy.service
--feature-gates=EphemeralContainers=true
# vi /etc/kubernetes/kubelet-conf.yml
featureGates:
 EphemeralContainers: true

重启all:

[root@k8s-master01 ~]# systemctl daemon-reload
[root@k8s-master01 ~]# systemctl restart kube-apiserver kube-scheduler kube-controller-manager kubelet kube-proxy

使用命令:
K8s 1.16+ https://kubernetes.io/docs/concepts/workloads/pods/ephemeral-containers
K8s 1.18+ kubectl alpha debug redis-new-5b577b46c7-2jv4j -ti –image=registry.cn-beijing.aliyuncs.com/dotbalo/debug-tools
K8s 1.20+ kubectl debug redis-new-5b577b46c7-2jv4j -ti –image=registry.cn-beijing.aliyuncs.com/dotbalo/debug-tools
kubectl debug node/k8s-node01 -it –image=registry.cn-beijing.aliyuncs.com/dotbalo/debug-tools

(****五) Tain和Toleration

官方文档:https://kubernetes.io/zh/docs/concepts/scheduling-eviction/taint-and-toleration/ 设计理念:Taint在一类服务器上打上污点,让不能容忍这个污点的Pod不能部署在打了污点的服务器上。Toleration是让Pod容忍节点上配置的污点,可以让一些需要特殊配置的Pod能够调用到具有污点和特殊配置的节点上。

  • Taint是作用在节点上。
  • Toleration是作用在pod上。


1.污点配置解析

创建一个污点(一个节点可以有多个污点):

# kubectl taint nodes NODE_NAME TAINT_KEY=TAINT_VALUE:EFFECT 比如: kubectl taint nodes k8s-node01 ssd=true:PreferNoSchedule

查看:

# kubectl describe node k8s-node01 | grep Taint (注意大写T)

NoSchedule:禁止调度到该节点,已经在该节点上的Pod不受影响 NoExecute:禁止调度到该节点,如果不符合这个污点,会立马被驱逐(或在一段时间后) PreferNoSchedule:尽量避免将Pod调度到指定的节点上,如果没有更合适的节点,可以部署到该节点


2.容忍配置解析

方式一完全匹配:满足全部条件 tolerations:

– key: “taintKey”
operator: “Equal”
value: “taintValue”
effect: “NoSchedule”

方式二不完全匹配:满足一个key,符合NoSchedule

tolerations:
– key: “taintKey”
operator: “Exists”
effect: “NoSchedule”

方式三大范围匹配(不推荐key为内置Taint):满足一个key即可 – key: “taintKey”

operator: “Exists

方式四匹配所有(不推荐): tolerations:

– operator: “Exists”

停留时间配置:(默认300秒迁移,tolerationSeconds设置迁移时间,下列3600秒驱逐走)

tolerations:
– key: “key1”
operator: “Equal”
value: “value1”
effect: “NoExecute”
tolerationSeconds: 3600

实例: 1. 有一个节点(假设node01)是纯SSD硬盘的节点,现需要只有一些需要高性能存储的Pod才能调度到该节点上 给节点打上污点和标签:

[root@k8s-master01 ~]# kubectl get po -A -owide | grep node01 #查看node01有哪些pod
[root@k8s-master01 ~]# kubectl taint nodes k8s-node01 ssd:PreferNoSchedule- #去除PreferNoSchedule属性污点 
[root@k8s-master01 ~]# kubectl taint nodes k8s-node01 ssd=true:NoExecute #此时会驱逐没有容忍该污点的Pod
[root@k8s-master01 ~]# kubectl taint nodes k8s-node01 ssd=true:NoSchedule #给node01打上污点 
[root@k8s-master01 ~]# kubectl label node k8s-node01 ssd=true #给node01打上ssd标签 [root@k8s-master01 ~]# kubectl get node -l ssd #查看集群有ssd的节点
[root@k8s-master01 ~]# kubectl describe node k8s-node01 | grep Taint #查看node01打上的污点

配置Pod:(表示能部署到node01节点,并不表示一定能部署在node01节点)

[root@k8s-master01 ~]# vim  tolerations.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  nodeSelector:
    ssd: "true"
  tolerations:
  - key: "ssd"
    operator: "Exists"

由于打了NoExecute,node01上只剩下了calico,然后创建pod,发现pod已经成功部署到node01节点。

[root@k8s-master01 ~]# kubectl get pod -A -owide | grep node01 
kube-system        calico-node-hrj82          1/1     Running   15         6d13h   192.168.0.103     k8s-node01   
kube-system        kube-proxy-mrl9j           1/1     Running   7          6d12h   192.168.0.103     k8s-node01    
[root@k8s-master01 ~]# kubectl create -f tolerations.yaml  #创建pod,查看效果
pod/nginx created
[root@k8s-master01 ~]# kubectl get pod -A -owide | grep node01   #发现pod已经成功部署到node01节点
default       nginx      1/1     Running     0        50s     172.161.125.33    k8s-node01    

删除pod,修改yaml,把容忍注释掉,再次部署发现pod没部署成功,describe寻找问题。

[root@k8s-master01 ~]# vim tolerations.yaml  #修改
....
  nodeSelector:
    ssd: "true"
  #tolerations:
  #- key: "ssd"
  #  operator: "Exists"
[root@k8s-master01 ~]# kubectl delete -f tolerations.yaml #删除
pod "nginx" deleted
[root@k8s-master01 ~]# kubectl get -f tolerations.yaml  #nginx处于pending状态
NAME    READY   STATUS    RESTARTS   AGE
nginx   0/1     Pending   0          89s
[root@k8s-master01 ~]# kubectl describe po nginx   #一个节点有污点,但是没容忍,四个节点没affinity。
...
  Warning  FailedScheduling  84s   default-scheduler  0/5 nodes are available: 
1 node(s) had taint {ssd: true}, that the pod didn't tolerate, 4 node(s) didn't match Pod's node affinity.

3.内置污点

node.kubernetes.io/not-ready:#节点未准备好,相当于节点状态Ready的值为False。
node.kubernetes.io/unreachable:#Node Controller访问不到节点,相当于节点状态Ready的值为Unknown。node.kubernetes.io/out-of-disk:#节点磁盘耗尽。
node.kubernetes.io/memory-pressure:#节点存在内存压力。
node.kubernetes.io/disk-pressure:#节点存在磁盘压力。
node.kubernetes.io/network-unavailable:#节点网络不可达。
node.kubernetes.io/unschedulable:#节点不可调度。
node.cloudprovider.kubernetes.io/uninitialized:#如果Kubelet启动时指定了一个外部的cloudprovider,它将给当前节点添加一个Taint将其标记为不可用。在cloud-controller-manager的一个controller初始化这个节点后,Kubelet将删除这个Taint。

节点不健康,6000秒后再驱逐(默认是300秒):

tolerations:
- key: "node.kubernetes.io/unreachable"
 operator: "Exists"
 effect: "NoExecute"
 tolerationSeconds: 6000

4.taint常用命令

创建一个污点(一个节点可以有多个污点): kubectl taint nodes NODE_NAME TAINT_KEY=TAINT_VALUE:EFFECT
比如:

# kubectl taint nodes k8s-node01 ssd=true:PreferNoSchedule

查看一个节点的污点:

# kubectl  get node k8s-node01 -o go-template --template {{.spec.taints}}
# kubectl describe node k8s-node01 | grep Taints -A 10

删除污点(和label类似):
基于Key删除: kubectl taint nodes k8s-node01 ssd-
基于Key+Effect删除: kubectl taint nodes k8s-node01 ssd:PreferNoSchedule-
修改污点(Key和Effect相同):kubectl taint nodes k8s-node01 ssd=true:PreferNoSchedule --overwrite

(六) Affinity亲和性**

1.Affinity分类

Affinity亲和力: ·NodeAffinity:节点亲和力/反亲和力 ·PodAffinity:Pod亲和力 ·PodAntiAffinity:Pod反亲和力 Affinity分类:


2.Affinity的几种场景

如下图,一个应用分别部署在4个node节点中,当其中一个出现问题时,其他3个可以确保高可用。



如下图,一个应用分别部署在两个区域,当其中一个区域出故障(光纤挖断等),另一个区域可以确保高可用。



尽量把同一项目不同应用部署在不同的节点上(确保宕机等影响范围降低)

3.节点node亲和力的配置

[root@k8s-master01 ~]# vim with-node-affinity.yaml
apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:    #和containers对齐
    nodeAffinity:   #节点亲和力(部署在一个节点)
      requiredDuringSchedulingIgnoredDuringExecution:  #硬亲和力配置(required,强制),与软亲和力只能存在一项。
        nodeSelectorTerms:   #节点选择器配置,可以配置多个matchExpressions(满足其一)
        - matchExpressions:   #可以配置多个key、value类型的选择器(都需要满足)
          - key: kubernetes.io/e2e-az-name
            operator: In   #标签匹配的方式(下文)
            values:   #可以配置多个(满足其一)
            - e2e-az1
            - az-2
      preferredDuringSchedulingIgnoredDuringExecution:  #软亲和力配置(preferred),与硬亲和力只能存在一项。
      - weight: 1    #软亲和力的权重,权重越高优先级越大,范围1-100
        preference:  #软亲和力配置项,和weight同级,可以配置多个,matchExpressions和硬亲和力一致
          matchExpressions:
          - key: another-node-label-key
            operator: In   #标签匹配的方式(下文)
            values:
            - another-node-label-value
  containers:
  - name: with-node-affinity
    image: nginx
operator:标签匹配的方式
In:相当于key = value的形式
NotIn:相当于key != value的形式
Exists:节点存在label的key为指定的值即可,不能配置values字段
DoesNotExist:节点不存在label的key为指定的值即可,不能配置values字段
Gt:大于value指定的值
Lt:小于value指定的值

4.pod亲和力的配置

[root@k8s-master01 ~]# vim with-pod-affinity.yaml
apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
spec:
  affinity: 
    podAffinity:  #pod亲和力 
      requiredDuringSchedulingIgnoredDuringExecution: #硬亲和力
      - labelSelector:  #Pod选择器配置,可以配置多个
          matchExpressions:   #可以配置多个key、value类型的选择器(都需要满足)
          - key: security   
            operator: In    #标签匹配的方式
            values:       #可以配置多个(满足其一)
            - S1
        topologyKey: failure-domain.beta.kubernetes.io/zone   #匹配的拓扑域的key,也就是节点上label的key,key和value相同的为同一个域,可以用于标注不同的机房和地区

    podAntiAffinity:  #pod反亲和力 
      preferredDuringSchedulingIgnoredDuringExecution:  #软亲和力
      - weight: 100     #权重,权重越高优先级越大,范围1-100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: security
              operator: In
              values:
              - S2
          namespaces:    #和哪个命名空间的Pod进行匹配,为空为当前命名空间 
          - default
          topologyKey: failure-domain.beta.kubernetes.io/zone
  containers:
  - name: with-pod-affinity
    image: nginx

5.同一个应用部署在不同的宿主机

如下例,有5个副本,配置的是强制反亲和力,假设K8S总共有3个节点,那么会分别在3个节点启动一个pod,剩下2个会一直处于pending状态,并且pod不能和app=must-be-diff-nodes的标签部署在一起。

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: must-be-diff-nodes
  name: must-be-diff-nodes
  namespace: kube-public
spec:
  replicas: 5   #副本数
  selector:
    matchLabels:
      app: must-be-diff-nodes
  template:
    metadata:
      labels:
        app: must-be-diff-nodes
    spec:
      affinity:
        podAntiAffinity:  #反亲和力
          requiredDuringSchedulingIgnoredDuringExecution:  #强制
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - must-be-diff-nodes   #标签
            topologyKey: kubernetes.io/hostname 
      containers:
      - image: nginx
        imagePullPolicy: IfNotPresent
        name: must-be-diff-nodes
5.1同一个应用不同副本固定节点
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-cache
spec:
  selector:
    matchLabels:
      app: store
  replicas: 3
  template:
    metadata:
      labels:
        app: store
    spec:
      nodeSelector:
          app: store
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - store
            topologyKey: "kubernetes.io/hostname"
      containers:
      - name: redis-server
        image: redis:3.2-alpine
5.2应用和缓存尽量部署在同一个域内
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-server
spec:
  selector:
    matchLabels:
      app: web-store
  replicas: 3
  template:
    metadata:
      labels:
        app: web-store
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - web-store
            topologyKey: "kubernetes.io/hostname"  
        podAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - store
              topologyKey: "kubernetes.io/hostname"
      containers:
      - name: web-app
        image: nginx:1.16-alpine

6.尽量调度到高配置服务器

如下图pod尽量配置到ssd=true的标签节点(软亲和,100权重),而且没有GPU=true标签的节点,也可以部署在type=physical标签的节点(权重10).

[root@k8s-master01 ~]# vim nodeAffinitySSD.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: prefer-ssd
  name: prefer-ssd
  namespace: kube-public
spec:
  replicas: 1
  selector:
    matchLabels:
      app: prefer-ssd
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: prefer-ssd
    spec:
      affinity:
        nodeAffinity:   #节点亲和力
          preferredDuringSchedulingIgnoredDuringExecution:   #软亲和力,如果需要强制部署在一个节点可以用requried
          - preference:
              matchExpressions:
              - key: ssd       #ssd标签
                operator: In   #满足
                values:
                - "true"
              - key: GPU     #GPU便标签
                operator: NotIn    #不满足
                values:
                - "true"
            weight: 100    #权重
          - preference:
              matchExpressions:
              - key: type  #type=physical标签
                operator: In
                values:
                - physical
            weight: 10    #权重
      containers:
      - env:
        - name: TZ
          value: Asia/Shanghai
        - name: LANG
          value: C.UTF-8
        image: nginx
        imagePullPolicy: IfNotPresent
        name: prefer-ssd

打标签

[root@k8s-master01 ~]# kubectl get node --show-labels  #查看节点标签
分别给master01,node01节点打上ssd=true的标签,master01节点单独打上GPU=true的标签
[root@k8s-master01 ~]# kubectl label node k8s-master01 ssd=true 
[root@k8s-master01 ~]# kubectl label node k8s-master01 GPU=true 
[root@k8s-master01 ~]# kubectl label node k8s-node01 GPU=true
给node02打上type=physical的标签
[root@k8s-master01 ~]# kubectl label node k8s-node02 type=physical 

创建应用

[root@k8s-master01 ~]# kubectl create -f nodeAffinitySSD.yaml   
[root@k8s-master01 ~]# kubectl get pod -n kube-public  -owide   #发现部署在node01上
NAME                         READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
prefer-ssd-dcb88b7d9-wdd54   1/1     Running   0          18s   172.161.125.41   k8s-node01  

假设去掉node1的ssd标签,再重新创建,就会创建到node02打了type标签的节点上。

[root@k8s-master01 ~]# kubectl label node k8s-node01 ssd-   #去掉node01的ssd标签
node/k8s-node01 labeled
[root@k8s-master01 ~]# kubectl delete -f nodeAffinitySSD.yaml #删除
deployment.apps "prefer-ssd" deleted
[root@k8s-master01 ~]# kubectl create -f nodeAffinitySSD.yaml #再创建
deployment.apps/prefer-ssd created
[root@k8s-master01 ~]# kubectl get pod -n kube-public  -owide #查看
NAME                         READY   STATUS    RESTARTS   AGE   IP               NODE         NOMINATED NODE   READINESS GATES
prefer-ssd-dcb88b7d9-58rfw   1/1     Running   0          87s   172.171.14.212   k8s-node02   

7.拓扑域TopologyKey

topologyKey:拓扑域,主要针对宿主机,相当于对宿主机进行区域的划分。用label进行判断,不同的key和不同的value是属于不同的拓扑域 如下图,相同区域可以打相同的一个标签,不同区域打不一样的标签,避免同一个区出现故障,所有pod都部署在同一个区域里面导致服务无法使用。


7.1同一个应用多区域部署

根据上图逻辑上设置3个域标签,把应用pod部署在不同的的区域内

master01,02: region=daxing
master03,node01: region=chaoyang
node02: region=xxx
[root@k8s-master01 ~]# kubectl label node k8s-master01 k8s-master02 region=daxing
[root@k8s-master01 ~]# kubectl label node k8s-node01 k8s-master03 region=chaoyang
[root@k8s-master01 ~]# kubectl label node k8s-node02  region=xxx

创建yaml,设置topologyKey为region,每个pod会部署在不同region上,由于设置是pod强制反亲和力,如果pod副本数超过区域上限数量,剩下的pod就会处于pending状态启动不了。

[root@k8s-master01 ~]# vim must-be-diff-zone.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: must-be-diff-zone
  name: must-be-diff-zone
  namespace: kube-public
spec:
  replicas: 3
  selector:
    matchLabels:
      app: must-be-diff-zone
  template:
    metadata:
      labels:
        app: must-be-diff-zone
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution: #强制反亲和力
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - must-be-diff-zone
            topologyKey: region   #根据上图设置区域标签
      containers:
      - image: nginx
        imagePullPolicy: IfNotPresent
        name: must-be-diff-zone

创建并查看,发现启动的3个pod都在不同的节点上。

[root@k8s-master01 ~]# kubectl create -f must-be-diff-zone.yaml
[root@k8s-master01 ~]# kubectl get pod -n kube-public  -owide
NAME                                 READY   STATUS    RESTARTS   AGE     IP               NODE           NOMINATED NODE   READINESS GATES
must-be-diff-zone-755966bd8b-42fft   1/1     Running   0          2m22s   172.171.14.213   k8s-node02                
must-be-diff-zone-755966bd8b-fx6cs   1/1     Running   0          2m22s   172.169.92.68    k8s-master02              
must-be-diff-zone-755966bd8b-k5d7q   1/1     Running   0          2m22s   172.161.125.42   k8s-node01      

相关文章

网友评论

    本文标题:十 Kubernetes高级调度计划任务、污点和容忍、Affi

    本文链接:https://www.haomeiwen.com/subject/rctuurtx.html