k8s核心详解系列-服务发现、存储配置以及高级调度

miloyang
0 评论
/ /
676 阅读
/
21617 字
30 2023-12

服务发现

之前在核心篇总有相关介绍,主要是分为东西流量和南北流量,也就是service和ingress,那为什么又了service和ingress就能实现服务发下呢?请往下看。

service

外部,比如我们的kubectl来访问,首先都是进入apis-services的,如下图:

serviceliuchengtu

  • master节点中,有一个service,api-service通过端口找到其中对应的service,然后找到对应的endpoint。
  • endpoint里面维护了对应的ip,也维护了对应的端口,然后通过iptables最终转发到目标的机器上面。
  • 找到目标的机器后,通过kube-proxy代理到具体的容器内部,然后实现跟容器内具体的交互。

也就是所有的容器都是通过service来实现互相的访问。

创建

apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
  labels:
    app: nginx-svc
spec:
  ports:
  - name: http # service 端口配置的名称
    protocol: TCP # 端口绑定的协议,支持 TCP、UDP、SCTP,默认为 TCP
    port: 80 # service 自己的端口
    targetPort: 9527 # 目标 pod 的端口
  - name: https
    port: 443
    protocol: TCP
    targetPort: 443
  selector: # 选中当前 service 匹配哪些 pod,对哪些 pod 的东西流量进行代理
    app: nginx

kubectl create -f nginx-svc.yaml

创建后:

NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP          3d13h
nginx-svc    ClusterIP   10.108.186.61    <none>        80/TCP,443/TCP   26m
[root@k8s-master ~]# kubectl get pod -o wide
NAME                     READY   STATUS    RESTARTS   AGE   IP               NODE        NOMINATED NODE   READINESS GATES
nginx-86c57db685-p7gpz   1/1     Running   0          52m   10.244.169.130   k8s-node2   <none>           <none>

使用一个临时的dns来访问

[root@k8s-master services]# kubectl run -it --image busybox:1.28.4 dns-test --restart=Never --rm /bin/sh
/ # wget  10.244.169.130
Connecting to 10.244.169.130 (10.244.169.130:80)
index.html           100% |*************************************************************|   615   0:00:00 ETA
/ # wget  10.244.169.130/index.html

反向代理外部域名

比如反向代理到博客首页:

apiVersion: v1
kind: Service
metadata:
  labels:
    app: boxiaoyang
  name: boxiaoyang-domain
spec:
  type: ExternalName
  externalName: www.boxiaoyang.club
[root@k8s-master services]# kubectl create -f nginx-svn-external-blog.yaml 
service/boxiaoyang-domain created
[root@k8s-master services]# kubectl get svc
NAME                       TYPE           CLUSTER-IP       EXTERNAL-IP           PORT(S)          AGE
boxiaoyang-domain          ExternalName   <none>           www.boxiaoyang.club   <none>           11s
kubernetes                 ClusterIP      10.96.0.1        <none>                443/TCP          3d14h
nginx                      NodePort       10.100.117.202   <none>                80:31000/TCP     73m
[root@k8s-master services]#  kubectl run -it --image busybox:1.28.4 dns-test1 --restart=Never --rm /bin/sh
If you don't see a command prompt, try pressing enter.
/ # wget boxiaoyang-domain
Connecting to boxiaoyang-domain (124.223.47.250:80)
index.html           100% |**********************| 35444   0:00:00 ETA
/ # 

Ingress

官方介绍: ingress

刚刚都是通过内部访问的,比如起一个内部的busybox来访问内部的pod,但是外部的访问,还是得根据ingress来。 架构图如下: ingressjiagoutuces

有点像ingress代替了传统的nginx了。

安装 ingress-nginx

先安装helm,这个是k8s的资源包仓库,理解为linux的yum。

wget https://get.helm.sh/helm-v3.2.3-linux-amd64.tar.gz
tar -zxvf helm-v3.2.3-linux-amd64.tar.gz 
[root@k8s-master heml]# cd linux-amd64/
[root@k8s-master linux-amd64]# pwd
/var/heml/linux-amd64
[root@k8s-master linux-amd64]# cp helm /usr/local/bin/

添加仓库

[root@k8s-master linux-amd64]# helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
"ingress-nginx" has been added to your repositories
[root@k8s-master linux-amd64]# helm repo list
NAME            URL                                       
ingress-nginx   https://kubernetes.github.io/ingress-nginx
[root@k8s-master linux-amd64]# helm search repo ingress-nginx
NAME                            CHART VERSION   APP VERSION     DESCRIPTION                                       
ingress-nginx/ingress-nginx     4.9.1           1.9.6           Ingress controller for K8s using NGINX a...
[root@k8s-master linux-amd64]# 

下载安装包

helm pull ingress-nginx/ingress-nginx

# 将下载好的安装包解压
tar xf ingress-nginx-xxx.tgz

# 解压后,进入解压完成的目录
cd ingress-nginx

# 修改 values.yaml
镜像地址:修改为国内镜像
registry: registry.cn-hangzhou.aliyuncs.com
image: google_containers/nginx-ingress-controller
image: google_containers/kube-webhook-certgen
tag: v1.3.0

hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet

修改部署配置的 kind: DaemonSet
nodeSelector:
  ingress: "true" # 增加选择器,如果 node 上有 ingress=true 就部署
将 admissionWebhooks.enabled 修改为 false
将 service 中的 type 由 LoadBalancer 修改为 ClusterIP,如果服务器是云平台才用 LoadBalancer

# 为 ingress 专门创建一个 namespace
kubectl create ns ingress-nginx

# 为需要部署 ingress 的节点上加标签
kubectl label node k8s-node1 ingress=true

# 安装 ingress-nginx
helm install ingress-nginx ./ingress-nginx -n ingress-nginx

创建一个 ingress

apiVersion: networking.k8s.io/v1
kind: Ingress # 资源类型为 Ingress
metadata:
  name: wolfcode-nginx-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules: # ingress 规则配置,可以配置多个
  - host: k8s.wolfcode.cn # 域名配置,可以使用通配符 *
    http:
      paths: # 相当于 nginx 的 location 配置,可以配置多个
      - pathType: Prefix # 路径类型,按照路径类型进行匹配 ImplementationSpecific 需要指定 IngressClass,具体匹配规则以 IngressClass 中的规则为准。Exact:精确匹配,URL需要与path完全匹配上,且区分大小写的。Prefix:以 / 作为分隔符来进行前缀匹配
        backend:
          service: 
            name: nginx-svc # 代理到哪个 service
            port: 
              number: 80 # service 的端口
        path: /api # 等价于 nginx 中的 location 的路径前缀匹配

多域名配置

apiVersion: networking.k8s.io/v1
kind: Ingress # 资源类型为 Ingress
metadata:
  name: wolfcode-nginx-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules: # ingress 规则配置,可以配置多个
  - host: k8s.wolfcode.cn # 域名配置,可以使用通配符 *
    http:
      paths: # 相当于 nginx 的 location 配置,可以配置多个
      - pathType: Prefix # 路径类型,按照路径类型进行匹配 ImplementationSpecific 需要指定 IngressClass,具体匹配规则以 IngressClass 中的规则为准。Exact:精确匹配,URL需要与path完全匹配上,且区分大小写的。Prefix:以 / 作为分隔符来进行前缀匹配
        backend:
          service: 
            name: nginx-svc # 代理到哪个 service
            port: 
              number: 80 # service 的端口
        path: /api # 等价于 nginx 中的 location 的路径前缀匹配
      - pathType: Exec # 路径类型,按照路径类型进行匹配 ImplementationSpecific 需要指定 IngressClass,具体匹配规则以 IngressClass 中的规则为准。Exact:精确匹配>,URL需要与path完全匹配上,且区分大小写的。Prefix:以 / 作为分隔符来进行前缀匹配
        backend:
          service:
            name: nginx-svc # 代理到哪个 service
            port:
              number: 80 # service 的端口
        path: /
  - host: api.wolfcode.cn # 域名配置,可以使用通配符 *
    http:
      paths: # 相当于 nginx 的 location 配置,可以配置多个
      - pathType: Prefix # 路径类型,按照路径类型进行匹配 ImplementationSpecific 需要指定 IngressClass,具体匹配规则以 IngressClass 中的规则为准。Exact:精确匹配>,URL需要与path完全匹配上,且区分大小写的。Prefix:以 / 作为分隔符来进行前缀匹配
        backend:
          service:
            name: nginx-svc # 代理到哪个 service
            port:
              number: 80 # service 的端口
        path: /

配置和存储

配置

后台开发是有很多配置,为了防止硬编码,所以会在k8s中配置很多的配置信息。但是很多信息是不能放在容器里面的,因为修改起来很不方便,所以呢,我们要抽取出来。

ConfigMap

一般用于去存储 Pod 中应用所需的一些配置信息,或者环境变量,将配置于 Pod 分开,避免应为修改配置导致还需要重新构建 镜像与容器。 一般来说,有两种方式,一种是基于文件夹的方式,比如我们在test目录下面创建两个文件夹,然后使用过key=value的方式把值填写过去,如:

drwxr-xr-x 2 root root 4096 Jan 30 12:08 test
[root@k8s-master config]# cd test
[root@k8s-master test]# ll
total 8
-rw-r--r-- 1 root root 28 Jan 30 12:08 db.properties
-rw-r--r-- 1 root root 25 Jan 30 12:08 redis.properties
[root@k8s-master test]# cat db.properties 
username=root
pawword=admin

然后通过指定文件夹的方式来创建configmap: kubectl create cm test-config --from-file=文件路径

[root@k8s-master config]# kubectl create cm test-config --from-file=test/
configmap/test-config created
[root@k8s-master config]# kubectl get cm
NAME          DATA   AGE
test-config   2      7s
[root@k8s-master config]# kubectl describe cm test-config
Data
====
db.properties:
----
username=root
pawword=admin

redis.properties:
----
host:127.0.0.1
prot:6379

但是大部分的时候,是通过另外一种方式,就是指定某个文件的方式进行创建,因为有时候并非想把整个文件夹的文件全部放进去,而是指定放入某几个文件。 kubectl create cm calico-yaml --from-file=app.yaml

比如下面:

[root@k8s-master test]# cat app.yaml 
kind: ConfigMap
apiVersion: v1
metadata:
  name: calico-config
  namespace: kube-system
[root@k8s-master test]# kubectl create cm calico-yaml --from-file=app.yaml 
configmap/calico-yaml created
[root@k8s-master test]# kubectl get cm
NAME          DATA   AGE
calico-yaml   1      4s
test-config   2      130m
[root@k8s-master test]# kubectl describe cm calico-yaml
Name:         calico-yaml
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
app.yaml:
----
kind: ConfigMap
apiVersion: v1
metadata:
  name: calico-config
  namespace: kube-system

还有一种方式,就是直接通过命令行的方式指定key和value

[root@k8s-master helm]# kubectl create configmap test-env-config --from-literal=JAVA_OPTS_TEST='-Xms512m -Xmx512m' --from-literal=APP_NAME=BLOG
configmap/test-env-config created
[root@k8s-master helm]# kubectl get cm
NAME              DATA   AGE
calico-yaml       1      14m
test-config       2      145m
test-env-config   2      5s
[root@k8s-master helm]# kubectl describe cm test-env-config
Name:         test-env-config
Namespace:    default
Labels:       <none>
Annotations:  <none>
Data
====
APP_NAME:
----
BLOG
JAVA_OPTS_TEST:
----
-Xms512m -Xmx512m
Events:  <none>

加载

那这些配置,如何加载到我们的容器里面呢?

举个例子,我们来创建一个pod,然后在pod里面引用相关配置:

[root@k8s-master test]# vim env-test-po.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: test-env-cm
spec:
  containers:
    - name: env-test
      image: alpine
      command: ["/bin/sh" ,"-c","env;sleep 3600"]
      imagePullPolicy: IfNotPresent
      env:
      - name: JAVA_VM_OPTS
        valueFrom:
          configMapKeyRef:
            name: test-env-config
            key: JAVA_OPTS_TEST
      - name: APP
        valueFrom:
          configMapKeyRef:
            name: test-env-config #用到了配置里文件
            key: APP_NAME # key为appname的
  restartPolicy: Never

基于yaml创建pod之后,然后等到启动起来后看日志可以发现:

[root@k8s-master test]# kubectl logs -f test-env-cm
...
HOSTNAME=test-env-cm
JAVA_VM_OPTS=-Xms512m -Xmx512m
APP=BLOG
...

secret加密数据配置

与 ConfigMap 类似,用于存储配置信息,但是主要用于存储敏感信息、需要加密的信息,Secret 可以提供数据加密、解密功能。

在创建 Secret 时,要注意如果要加密的字符中,包含了有特殊字符,需要使用转义符转移,例如 $ 转移后为 $,也可以对特殊字符使用单引号描述,这样就不需要转移例如 1$289*-! 转换为 '1$289*-!'

一般来说,用的较少。

[root@k8s-master test]# kubectl create secret generic orig-secret --from-literal=username=admin --from-literal=password=admin
secret/orig-secret created
[root@k8s-master test]# kubectl get secret
NAME                  TYPE                                  DATA   AGE
default-token-mnb9p   kubernetes.io/service-account-token   3      3d18h
orig-secret           Opaque                                2      9s
[root@k8s-master test]# kubectl describe secret orig-secret
Name:         orig-secret
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
password:  5 bytes
username:  5 bytes

配置热更新

我们通常会将项目的配置文件作为 configmap 然后挂载到 pod,那么如果更新 configmap 中的配置,会不会更新到 pod 中呢?

这得分成几种情况:

  • 默认方式

    会更新,更新周期是更新时间 + 缓存时间

  • subPath

    不会更新

  • 变量形式

    如果 pod 中的一个变量是从 configmap 或 secret 中得到,同样也是不会更新的

对于 subPath 的方式,我们可以取消 subPath 的使用,将配置文件挂载到一个不存在的目录,避免目录的覆盖,然后再利用软连接的形式,将该文件链接到目标位置

但是如果目标位置原本就有文件,可能无法创建软链接,此时可以基于前面讲过的 postStart 操作执行删除命令,将默认的吻技安删除即可

持久化存储

在k8s中,持久化存储有三种类型,Volumes、NFS挂载、PV和PVC这三种,都是比较常用的、

Volumes

类似于docker中的容器中,把node节点上挂载在pod容器里面去,即使pod消失,但是文件还在node上面。

我们先编写一个配置文件:

apiVersion: v1
kind: Pod
metadata:
  name: test-volume-pd
spec:
  containers:
  - image: nginx
    name: nginx-volume
    volumeMounts:
    - mountPath: /test-pd #挂载到容器的哪个目录
      name: test-volume # 挂载哪个volume
  volumes:
  - name: test-volume 
    hostPath: # 与主机共享目录,加载主机中的指定目录到容器中
      path: /data # 节点中的目录
      type: DirectoryOrCreate # 检查类型,如果没有就创建

测试

使用kubectl get pod -o wide 发现创建的po落在了node1上面,去node1上查看并创建文件:

[root@k8s-node1 /]# cd /data
[root@k8s-node1 data]# ll
total 0
[root@k8s-node1 data]# touch index.html

去pod上查看发现存在,也就是确实挂载了。

[root@k8s-master volumes]# kubectl exec -it test-volume-pd -- sh
# cd /data
# ls
bin  boot  dev  docker-entrypoint.d  docker-entrypoint.sh  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  test-pd  tmp  usr  var
# cd test-pd
# ls
index.html

当然,还有一种方式就是pod里面多个容器之间进行共享,就是EmptyDir

EmptyDir 主要用于一个 Pod 中不同的 Container 共享数据使用的,由于只是在 Pod 内部使用,因此与其他 volume 比较大的区别是,当 Pod 如果被删除了,那么 emptyDir 也会被删除。

存储介质可以是任意类型,如 SSD、磁盘或网络存储。可以将 emptyDir.medium 设置为 Memory 让 k8s 使用 tmpfs(内存支持文件系统),速度比较快,但是重启 tmpfs 节点时,数据会被清除,且设置的大小会计入到 Container 的内存限制中。

NFS挂载

nfs 卷能将 NFS (网络文件系统) 挂载到你的 Pod 中。 不像 emptyDir 那样会在删除 Pod 的同时也会被删除,nfs 卷的内容在删除 Pod 时会被保存,卷只是被卸载。 这意味着 nfs 卷可以被预先填充数据,并且这些数据可以在 Pod 之间共享。 也就是不在本地,在一个局域网上面。

相当于把HostPath和EmptyDir结合了,即可永久存储,又可以容器内访问,但是效率没那么高,磁盘的效率已经很低了,再加一层网络。你可以用,但是不能频繁的读取上,比如mysql这些。你懂得。

# 安装 nfs 每个节点都做一次吧
yum install nfs-utils -y

# 启动 nfs
systemctl start nfs-server

# 查看 nfs 版本
cat /proc/fs/nfsd/versions

# 在磁盘大的节点上创建共享目录
mkdir -p /data/nfs
cd /data/nfs
mkdir rw
mkdir ro

# 设置共享目录 export
vim /etc/exports
/data/nfs/rw 192.168.113.0/24(rw,sync,no_subtree_check,no_root_squash)
/data/nfs/ro 192.168.113.0/24(ro,sync,no_subtree_check,no_root_squash)

# 重新加载
exportfs -f
systemctl reload nfs-server

# 到其他测试节点安装 nfs-utils 并加载测试
mkdir -p /mnt/nfs/rw
mount -t nfs 192.168.113.121:/data/nfs/rw /mnt/nfs/rw

PV和PVC

以上都是小菜,这两个才是真正的实现方案,也是最重要的。

  • 持久卷(PersistentVolume,PV)

    是集群中的一块存储,可以由管理员事先制备, 或者使用存储类(Storage Class)来动态制备。 持久卷是集群资源,就像节点也是集群资源一样。PV 持久卷和普通的 Volume 一样, 也是使用卷插件来实现的,只是它们拥有独立于任何使用 PV 的 Pod 的生命周期。 此 API 对象中记述了存储的实现细节,无论其背后是 NFS、iSCSI 还是特定于云平台的存储系统。

  • 持久卷申领(PersistentVolumeClaim,PVC)

    表达的是用户对存储的请求。概念上与 Pod 类似。 Pod 会耗用节点资源,而 PVC 申领会耗用 PV 资源。Pod 可以请求特定数量的资源(CPU 和内存);同样 PVC 申领也可以请求特定的大小和访问模式 (例如,可以要求 PV 卷能够以 ReadWriteOnce、ReadOnlyMany 或 ReadWriteMany 模式之一来挂载)。

关联关系如下:

pvpvcdasdsadfasdf

构建

  • 创建PV

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv0001
    spec:
      capacity:
        storage: 5Gi # pv 的容量
      volumeMode: Filesystem # 存储类型为文件系统
      accessModes: # 访问模式:ReadWriteOnce、ReadWriteMany、ReadOnlyMany
        - ReadWriteOnce # 可被单节点独写
      persistentVolumeReclaimPolicy: Recycle # 回收策略
      storageClassName: slow # 创建 PV 的存储类名,需要与 pvc 的相同
      mountOptions: # 加载配置
        - hard
        - nfsvers=4.1
      nfs: # 连接到 nfs
        path: /data/nfs/rw/test-pv # 存储路径
        server: 192.168.113.121 # nfs 服务地址
    
    [root@k8s-master pv]# kubectl create -f pv-nfs.yaml 
    persistentvolume/pv0001 created
    [root@k8s-master pv]# kubectl get pv
    NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
    pv0001   1Gi        RWO            Recycle          Available           slow                    4s
    

    有以下几种状态:

    • Avaliable:空闲
    • Bound:已经被PVC绑定
    • Released:PVC被删除,资源已经回收,但是pv未被重新使用
    • Failed:自动回收失败
  • 创建PVC

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: nfs-pvc
    spec:
      accessModes:
        - ReadWriteOnce # 权限需要与对应的 pv 相同
      volumeMode: Filesystem
      resources:
        requests:
          storage: 8Gi # 资源可以小于 pv 的,但是不能大于,如果大于就会匹配不到 pv
      storageClassName: slow # 名字需要与对应的 pv 相同
    #  selector: # 使用选择器选择对应的 pv
    #    matchLabels:
    #      release: "stable"
    #    matchExpressions:
    #      - {key: environment, operator: In, values: [dev]}
    

    我们来看看是否绑定了

    [root@k8s-master pv]# kubectl get pvc
    NAME      STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    nfs-pvc   Bound    pv0001   1Gi        RWO            slow           6s
    [root@k8s-master pv]# kubectl get pv
    NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM             STORAGECLASS   REASON   AGE
    pv0001   1Gi        RWO            Recycle          Bound    default/nfs-pvc   slow                    9m57s
    
  • 把pod进行绑定

    apiVersion: v1
    kind: Pod
    metadata:
      name: test-pvc-pd
    spec:
      containers:
      - image: nginx
        name: nginx-volume
        volumeMounts:
        - mountPath: /usr/share/nginx/html #挂载到容器的哪个目录
          name: test-volume # 挂载哪个volume
      volumes:
      - name: test-volume 
        persistentVolumeClaim:  # 关联PVC
          claimName: nfs-pvc # 要关联哪个PVC
    

高级调度

CornJob计划任务

和linux中的corntab类似,只不过放入了k8s中执行。

apiVersion: batch/v1
kind: CronJob
metadata:
  name: hello
spec:
  concurrencyPolicy: Allow # 并发调度策略:Allow 允许并发调度,Forbid:不允许并发执行,Replace:如果之前的任务还没执行完,就直接执行新的,放弃上一个任务
  failedJobsHistoryLimit: 1 # 保留多少个失败的任务
  successfulJobHistoryLimit: 3 # 保留多少个成功的任务
  suspend: false # 是否挂起任务,若为 true 则该任务不会执行
#  startingDeadlineSeconds: 30 # 间隔多长时间检测失败的任务并重新执行,时间不能小于 10
  schedule: "* * * * *" # 调度策略
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox:1.28
            imagePullPolicy: IfNotPresent
            command:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure

初始化容器InitContainer

在真正的容器启动之前,先启动 InitContainer,在初始化容器中完成真实容器所需的初始化操作,完成后再启动真实的容器。

相对于 postStart 来说,首先 InitController 能够保证一定在 EntryPoint 之前执行,而 postStart 不能,其次 postStart 更适合去执行一些命令操作,而 InitController 实际就是一个容器,可以在其他基础容器环境下执行更复杂的初始化功能。

在 pod 创建的模板中配置 initContainers 参数: spec: initContainers:

  • image: nginx imagePullPolicy: IfNotPresent command: ["sh", "-c", "echo 'inited;' >> ~/.init"] name: init-test

污点和容忍

污点

我们知道,主节点是很重要的节点,负责调度从节点来实现对应的任务,是一个很重要的角色,所以它的资源应该是要更加充沛,而且不做很多事情来保障它的可用性,但是我们k8s分配任务的时候,是随机分配节点的,所以我们可以给master节点打上污点的标签,这样任务就不会部署过来。

污点:是标注在节点上的,当我们在一个节点上打上污点以后,k8s 会认为尽量不要将 pod 调度到该节点上,除非该 pod 上面表示可以容忍该污点,且一个节点可以打多个污点,此时则需要 pod 容忍所有污点才会被调度该节点。

分类

一般来说,我们有两种分类:

  • NoSchedule

    如果不能容忍该污点,那么 Pod 就无法调度到该节点上,但是已经存在的节点不会被驱逐

  • NoExecute

    如果 Pod 不能忍受这类污点,Pod 会马上被驱逐。
    如果 Pod 能够忍受这类污点,但是在容忍度定义中没有指定 tolerationSeconds, 则 Pod 还会一直在这个节点上运行。
    如果 Pod 能够忍受这类污点,而且指定了 tolerationSeconds, 则 Pod 还能在这个节点上继续运行这个指定的时间长度。

操作

一般来说,我们可以如下创建污点:

# 为节点打上污点
kubectl taint node k8s-master key=value:NoSchedule

# 移除污点
kubectl taint node k8s-master key=value:NoSchedule-

# 查看污点
kubectl describe no k8s-master

容忍

当然,有些事情是必须要在放在master上面的,但是master有污点了怎么办?此时就可以给master配一个这个任务的容忍。

容忍:是标注在 pod 上的,当 pod 被调度时,如果没有配置容忍,则该 pod 不会被调度到有污点的节点上,只有该 pod 上标注了满足某个节点的所有污点,则会被调度到这些节点

类型

  • Equal

    比较操作类型为 Equal,则意味着必须与污点值做匹配,key/value都必须相同,才表示能够容忍该污点

  • Exists

    容忍与污点的比较只比较 key,不比较 value,不关心 value 是什么东西,只要 key 存在,就表示可以容忍。

配置

tolerations:
- key: "污点的 key"
  value: "污点的 value"
  offect: "NoSchedule" # 污点产生的影响
  operator: "Equal" # 表是 value 与污点的 value 要相等,也可以设置为 Exists 表示存在 key 即可,此时可以不用配置 value

亲和力Affinity

这个和污点相反,污点的作用简单来说就是你不要来,而亲和力就是来吧亲爱的。如果说是反亲和力,那也有污点的作用,就是滚。

比如内存消耗比较大的任务,就可以分配到内存大一点的node上面,对于存储要求高的,就可以优先分配到ssd硬盘上面等等。

人未眠
工作数十年
脚步未曾歇,学习未曾停
乍回首
路程虽丰富,知识未记录
   借此博客,与之共进步