k8s记录-基础配置2

1、Secret

Secret作用:
用来保存敏感信息,比如密码、令牌、或者redis、Mysql的密码。
和configmap的区别是,secret是加密的。

1.1、使用命令创建secret

kubectl create secret generic db-user-pass \
    --from-literal=username=admin \
    --from-literal=password='S!B\*d$zDsb='

查看

kubectl describe secret db-user-pass 
Name:         db-user-pass
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

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

1.2、用文件创建secret

echo -n "user001" > username.txt
echo -n "666666" > password.txt

kubectl create secret generic db-user-pass \
	--from-file=./username.txt \
  --from-file=./password.txt

默认键名为文件名。你也可以通过 --from-file=[key]=source 设置键名,例如:

kubectl create secret generic db-user-pass \
    --from-file=username=./username.txt \
    --from-file=password=./password.txt

image.png

> kubectl get secrets db-user-pass -o yaml

apiVersion: v1
data:
  password: NjY2NjY2
  username: dXNlcjAwMQ==
kind: Secret
metadata:
  creationTimestamp: "2023-11-08T07:35:21Z"
  name: db-user-pass
  namespace: default
  resourceVersion: "235744"
  uid: bf4ec398-12c6-478e-999a-d0ead83b5a20
type: Opaque

1.3、解码secret,将加密的用户名和密码可以通过base64的方式解密出来

> echo NjY2NjY2 |base64 --decode && echo
666666

> echo dXNlcjAwMQ== |base64 --decode && echo
user001

查看创建的Secret内容

kubectl get secret db-user-pass -o jsonpath='{.data}'
{"password":"UyFCXCpkJHpEc2I9","username":"YWRtaW4="}

解码password数据

echo 'UyFCXCpkJHpEc2I9' |base64 --decode && echo
S!B\*d$zDsb=

kubectl get secret db-user-pass -o jsonpath='{.data.password}' | base64 --decode && echo
S!B\*d$zDsb=

先提前将用户名和密码加密、然后放到 yaml 文件中在创建 secret
加密

> echo -n 'admin' |base64
YWRtaW4=

> echo -n 'admin@123' |base64
YWRtaW5AMTIz

创建yaml

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque		# 待查询
data:
  uaername: YWRtaW4=			# 与上边加密后的帐密对应
  password: YWRtaW5AMTIz

kubectl apply -f secret.yaml

> kubectl get secrets mysecret -o yaml

apiVersion: v1
data:
  password: YWRtaW5AMTIz
  uaername: YWRtaW4=
kind: Secret
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","data":{"password":"YWRtaW5AMTIz","uaername":"YWRtaW4="},"kind":"Secret","metadata":{"annotations":{},"name":"mysecret","namespace":"default"},"type":"Opaque"}
  creationTimestamp: "2023-11-08T07:58:16Z"
  name: mysecret
  namespace: default
  resourceVersion: "237676"
  uid: d17f4c8d-6488-4a99-88ea-d9a53560c177
type: Opaque

通过base64的方式解密

> echo YWRtaW5AMTIz |base64 --decode && echo
admin@123

> echo YWRtaW4= |base64 --decode && echo
admin

1.4、使用 stringData 字段

这字段可以将一个非 base64 编码的字符串直接放入 Secret 中进行加密

apiVersion: v1
kind: Secret
metadata:
  name: stringdata
type: Opaque
stringData:			# 此处选择stringdata
  username: admin
  password: admin@123

kubectl apply -f stringData.yaml

> kubectl get secrets stringdata -oyaml
apiVersion: v1
data:
  password: YWRtaW5AMTIz
  username: YWRtaW4=
kind: Secret
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"Secret","metadata":{"annotations":{},"name":"stringdata","namespace":"default"},"stringData":{"password":"admin@123","username":"admin"},"type":"Opaque"}
  creationTimestamp: "2023-11-08T08:07:19Z"
  name: stringdata
  namespace: default
  resourceVersion: "238439"
  uid: 06980796-5b93-4ccf-9efb-0bc1631ddb33
type: Opaque

同样使用base64解密

> echo YWRtaW5AMTIz |base64 --decode && echo
admin@123

> echo YWRtaW4= |base64 --decode && echo
admin

1.5、imagePullSecrets对私有仓库的用户名和密码信息进行加密

Pull an Image from a Private Registry
作用:pod 拉取私有镜像仓库时使用的账号和密码、里面的信息会传递给 kubelet,然后 kubelet 就可以拉取有账号密码的镜像 【生产中用的最多】
首先通过命令创建加密的secret,格式如下,此处填写镜像仓库(例如harbor)的连接地址和帐密

kubectl create secret docker-registry registryinfo \
	--docker-server=192.168.10.128:5000 \
  --docker-username=admin \
  --docker-password=admin@123 \
  --docker-email=879844258@qq.com

查看

> kubectl get secrets registryinfo -oyaml
apiVersion: v1
data:
  .dockerconfigjson: eyJhdXRocyI6eyIxOTIuMTY4LjEwLjEyODo1MDAwIjp7InVzZXJuYW1lIjoiYWRtaW4iLCJwYXNzd29yZCI6ImFkbWluQDEyMyIsImVtYWlsIjoiODc5ODQ0MjU4QHFxLmNvbSIsImF1dGgiOiJZV1J0YVc0NllXUnRhVzVBTVRJeiJ9fX0=
kind: Secret
metadata:
  creationTimestamp: "2023-11-08T08:26:04Z"
  name: registryinfo
  namespace: default
  resourceVersion: "240019"
  uid: e3972d8c-66a7-4631-812a-8faf6e2391e4
type: kubernetes.io/dockerconfigjson

解密

> echo eyJhdXRocyI6eyIxOTIuMTY4LjEwLjEyODo1MDAwIjp7InVzZXJuYW1lIjoiYWRtaW4iLCJwYXNzd29yZCI6ImFkbWluQDEyMyIsImVtYWlsIjoiODc5ODQ0MjU4QHFxLmNvbSIsImF1dGgiOiJZV1J0YVc0NllXUnRhVzVBTVRJeiJ9fX0= |base64 --decode 
{"auths":{"192.168.10.128:5000":{"username":"admin","password":"admin@123","email":"879844258@qq.com","auth":"YWRtaW46YWRtaW5AMTIz"}}}

image.png
使用刚刚创建的secret,创建一个nginx

apiVersion: v1
kind: Pod
metadata:
  name: test-nginx
  namespace: default
  labels:
    name: test-nginx
spec:
  imagePullSecrets:
    - name: registryinfo  # 选择上边新建的secret
  containers:
    - name: nginx
      image: nginx:latest
      imagePullPolicy: IfNotPresent
      ports:
      - name: http
        containerPort: 80
        hostPort: 80

应用之后,kubectl 会拿着私有仓库的用户名和密码自动去匹配私有仓库拉去镜像

2、subpath解决目录覆盖的问题

在Pod中的Volume挂载时指定一个子路径(subpath),这个特性可以用来避免目录覆盖问题,同时让单个Volume可以被多个容器共享而互不干扰,或者在同一个容器内的不同路径下使用不同的目录。
subPath可以用来解决以下一些常见的问题:

  1. 共享存储: 当你希望多个Pod共享同一个Volume,但彼此使用不同的子目录时。
  2. 单个Pod多个挂载点: 当你希望建立一个单个Pod的多个容器之间的文件隔离,但又想要利用同一个Volume的情况。
  3. 避免目录覆盖: 当你的容器预期在挂载点需要某些文件或目录时,使用subPath挂载可以避免Volume挂载覆盖掉这些预期文件。
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mycontainer
    image: myimage
    volumeMounts:
    - name: myvolume
      mountPath: /usr/share/nginx/html
      subPath: html
  volumes:
  - name: myvolume
    persistentVolumeClaim:
      claimName: mypvc
  • 容器mycontainer将这个卷挂载在/usr/share/nginx/html路径下。
  • 通过指定subPath: html,Kubernetes会将PV中的html子目录挂载到容器的/usr/share/nginx/html路径下。
  • 如果没有指定subPath,整个Volume将会被挂载到/usr/share/nginx/html,可能会覆盖掉容器内该位置的预先存在的文件。

使用subPath可以确保只有Volume中的特定子路径被挂载到容器的mountPath下,这样原来路径下的文件就不会被覆盖。
但在某些情况下subPath的使用可能受到限制,例如在使用ConfigMap或Secret作为Volume时,或者在某些特定的Volume类型上。

讲 pv 的时候深入学习
ConfigMap 和 Secret 如果以 subPath 的形式挂载的,那么 pod 是不会感知到 ConfigMap 和 Secret 更新的。
如果 pod 的变量来自于 ConfigMap 和 Secret 中定义的内容,那么 ConfigMap 和 Secret 更新后、 也不会更新 pod 中的变量。

热更新 ConfigMap 和 Secret:(因为更改了配置文件、用 replace 或者 redit 命令重新应用配置 文件不起作用,所以用下面这个命令)

kubectl create cm nginx-conf-cm --from-file=nginx.conf --dry-run -oyaml |kubectl replace -f . 

把前面执行的结果打印出来 yaml 不交给 apiserver 去执行创建、然后交给管道符后面的命令来执行

kubectl exec -it podID – cat /etc/nginx.conf
把 pod 容器中的 nginx.conf 拷贝到宿主机创建cm
kubectl create cm nginx-conf-cm --from-file=nginx.conf
immutable: true #让 ConfigMap 和 Secret 的内容保持不变、写在 yaml 文件中

K8S | Config应用配置

3、卷 Volume

参考链接:https://kubernetes.io/zh/docs/concepts/storage/volumes/

3.1、hostPath 挂载宿主机路径

理论
hostPath卷能将主机节点文件系统上的文件或目录挂载到你的Pod中。虽然这不是大多数Pod需要的,但是它为一些应用程序提供了强大的逃生舱。
例如,hostPath的一些用法有:

  • 运行一个需要访问Docker内部机制的容器;可使用hostPath挂载/var/lib/docker路径。
  • 在容器中运行cAdvisor时,以hostPath方式挂载/sys。
  • 允许Pod指定给定的hostPath在运行Pod之前是否应该存在,是否应该创建以及应该以什么方式存在。

除了必须的path属性之外,用户可以选择性地为hostPath卷指定type。
支持的type值如下:

取值行为
空字符串(默认)用于向后兼容,这意味着在安装hostPath卷之前不会执行任何检查。
DirectoryOrCreate如果在给定路径上什么都不存在,那么将根据需要创建空目录,权限设置为0755,具有与kubelet相同的组和属主信息。
Directory在给定路径上必须存在的目录
FileOrCreate如果在给定路径上什么都不存在,那么将在那里根据需要创建空文件,权限设置为0644,具有与kubelet相同组和所有权。
File在给定路径上必须存在的文件
Socket在给定路径上必须存在的UNIX套接字
CharDevice在给定路径上必须存在的字符设备
BlockDevice在跟单路径上必须存在的块设备

hostPath配置示例

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: nginx:latest
    name: test-container
    volumeMounts:
    - mountPath: /test-pd # 挂载到容器的路径
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      path: /demo/volumes/data  # 宿主机上目录
      type: Directory # 可选

3.2、emptyDir 实现pod容器数据共享

参考链接
https://kubernetes.io/zh/docs/concepts/storage/volumes/
https://blog.csdn.net/weixin_40228200/article/details/124428556

1、emptyDir简介

emtpyDir总是在Pod被指定到Node节点上时创建,emptyDir在被创建之初是一个空目录,并且会一直存在于Pod的生命周期中,当Pod被移除时,emptyDir中的数据也会被随之删除。(但是,Pod中一个容器的崩溃并不会使得emptyDir被删除。)emptyDir可以被挂载到Pod的任意容器下的任意路径下,并且被Pod中的容器所共享。
emptyDir磁盘的作用如下所示:
1、Pod中容器的普通空间,用于临时的数据存储。
2、作为从崩溃中恢复的备份点。
在默认情况下,emptyDir会存储在主机所使用的媒介上,具体是何种存储媒介取决于环境。我们也可以将emptyDir.medium的值设置为Memory,使得Kubernetes来挂载基于内存的tmpfs,这样存储速度会增大,但是当主机重启后,数据会消失。
原文链接:https://blog.csdn.net/weixin_40228200/article/details/124428556
emptyDir常用于共享日志数据文件、比如用filebeat收集日志的时候、用emptyDir共享业务容器的日志文件、然后推送到日志平台上面。

kubectl explain deployment.spec.template.spec.volumes.emptyDir
kubectl explain pods.spec.volumes.emptyDir

emptyDir配置示例

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: registry.k8s.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir:
      sizeLimit: 500Mi
2、演示

执行如下yam文件

apiVersion: v1
kind: Namespace
metadata:
	name: volumes

---
apiVersion: v1
kind: Pod
metadata:
  name: pod-with-emptydir
  namespace: volumes
  labels:
    pod: myapp
    dir: empty
spec:
  containers:
  - name: myapp
    image: ikubernetes/myapp:v1
    ports:
    - name: http
      containerPort: 80
    volumeMounts:
    - name: html
      mountPath: /usr/share/nginx/html/
  - name: busybox
    image: busybox
    volumeMounts:
    - name: html
      mountPath: /exp/
    command: ['/bin/sh','-c','while true; do echo $(date) > /exp/index.html; sleep 3; done']
  volumes:
  - name: html
    emptyDir: {}

上述yaml文件中启动了2个容器恭喜html,busybox负责一直写数据到html中,myapp负责读html中的数据
验证共享目录

# 查看pod IP
kubectl -n volumes get all -o wide
NAME                    READY   STATUS    RESTARTS   AGE    IP            NODE     NOMINATED NODE   READINESS GATES
pod/pod-with-emptydir   2/2     Running   0          6m5s   10.244.2.15   node02   <none>           <none>


# 验证
while true;do curl 10.244.2.15;sleep 1;done
Tue Dec 5 09:44:30 UTC 2023
Tue Dec 5 09:44:33 UTC 2023
Tue Dec 5 09:44:33 UTC 2023
Tue Dec 5 09:44:33 UTC 2023
Tue Dec 5 09:44:36 UTC 2023
Tue Dec 5 09:44:36 UTC 2023
Tue Dec 5 09:44:36 UTC 2023

3.3、Volume 挂载 nfs至容器

首先所有节点都安装nfs软件包,为了让其他节点都识别nfs服务。
只启动共享目录的那台服务器的nfs服务,其他节点不启动nfs服务。
在master节点上创建nfs共享目录,其余节点测试识别nfs服务。

1、yum -y install nfs-utils rpcbind
2、创建要共享出去的目录,/demo/nfs 读写
mkdir -p /demo/nfs

修改nfs的配置文件
chmod 755 /demo/nfs/
vim /etc/exports
/demo/nfs/ *(rw,sync,no_root_squash,sync)

启动rpcbind程序,再启动nfs程序
systemctl restart rpcbind ##nfs 共享是依赖这个程序实现的数据的共享
systemctl restart nfs ##nfs 共享是靠这个程序来控制的

客户端测试:其他客户端安装nfs软件,不用启动nfs
yum -y install nfs-utils
showmount -e 192.168.10.16	# master节点IP
Export list for 192.168.10.16:
/demo/nfs *
apiVersion: v1
kind: Pod
metadata:
  name: test-nfs
spec:
  restartPolicy: Always
  containers:
  - name: nginx
    image: nginx:latest
    imagePullPolicy: IfNotPresent
    volumeMounts:
    - name: data-nfs
      mountPath: /opt
  volumes:
  - name: data-nfs
    nfs:
      path: /demo/nfs
      server: 192.168.10.16
  
  # nfs可以实现容器和本地共享读写一个目录

注意:由于nfs是单节点,性能不太好,生产环境中不建议使用。

4、持久化存储pv和pvc概念

pv后边可以连接nfs,gfs,ceph等存储,
pvc是namespace隔离的,pv不是。

5、计划任务

https://www.jianshu.com/p/70b572f019ae

  • Job
  • CronJob

我们在日常的工作中经常都会遇到一些需要进行批量数据处理和分析的需求,当然也会有按时间来进行调度的工作,在Kubernetes集群中为我们提供了Job和CronJob两种资源对象来应对这种需求。
CronJob其实就是在Job的基础上加上了时间调度,和linux的crontab很类似
一个CronJob对象其实就对应crontab文件中的一行,它根据配置的时间格式周期性地运行一个Job,CronJob格式和crontab也是一样的。
Job负责处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个Pod成功结束。
CronJob则就是在Job上加上了时间调度。

5.1、Job

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执行任务,第二次只会创建1个Pod执行任务
  template:
    spec:
      containers:
      - command:
        - echo
        - Hello, Job
        image: registry.cn-beijing.aliyuncs.com/dotbalo/busybox
        imagePullPolicy: Always
        name: echo
        resources: {}
      restartPolicy: Never

5.2、CronJob

CronJob其实就是在Job的基础上加上了时间调度,我们可以:在给定的时间点运行一个任务,也可以周期性地在给定时间点运行。这个实际上和Linux中的crontab就非常类似了。
一个CronJob对象其实就对应crontab文件中的一行,它根据配置的时间格式周期性地运行一个Job,格式和crontab也是一样的。
crontab的格式如下:
分 小时 日 月 周 要运行的命令 第1列分钟(0~59) 第2列小时(0~23) 第3列日(1~31) 第4列月(1~12) 第5列星期(0~7)(0和7表示星期天) 第6列要运行的命令

apiVersion: batch/v1beta1                  # 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。

6、污点和容忍度(taint、toleration)

6.1、介绍

参考连接:
https://kubernetes.io/zh-cn/docs/concepts/scheduling-eviction/taint-and-toleration/
https://blog.csdn.net/H_B_K/article/details/110293125
污点和容忍度两个关键参数

  • taint:使用tainet给node节点打污点
  • Toleration:使用它配置容忍
1、污点介绍

通过给节点添加污点,可以阻止 **Pod **创建在带有污点的节点上。管理员可以通过合理 的设置污点。来控制业务 Pod 的运行。如:管理员不希望业务 Pod 运行在 master 节点上。 这种需要就可以通过在 master 节点上添加污点来实现。事实上 kubernetes 默认也为 master 添加上了 node-role.kubernetes.io/master:NoSchedule 的污点。避免业务 Pod 直接运行在 master 节点上。

2、容忍度介绍

通过污点我们可以阻止 Pod 运行到带污点的节点上,如果希望 Pod 能运行到这些带污点的节 点上则需要给 Pod 添加容忍配置。通过设置容忍能够让 Pod 支持调度到带有污点的节点上。

3、污点的应用场景

通过污点规划专用节点,避免 Pod 被直接调度到该类节点上。比方说带有 GPU 设备的 节点。可以打上一个特定污点。只要未设置该类污点容忍配置的 Pod 都无法被调度到这类 GPU 节点上。只有需要使用 GPU 资源的 Pod 配置了容忍才能被调度到。通过这种方法可以 实现 Pod 调度控制。
基于污点来实现驱逐 Pod,可以通过给节点打上污点,让不支持该污点的 Pod 被驱逐到其他 节点上

4、污点效果effect支持下面三种类型
  • NoSchedule: 禁止调度

表示如果 pod 没有容忍这些污点,pod 则法被调度到包含该污点的节点上。

  • NoExecute: pod 驱逐策略配置

用于影响正在节点上运行的 pod。如果当前节点上运行的 pod 没有容忍该节点上的 NoExecute 污点,则会 Pod 将会从该节点上去除。

  • PreferNoSchedule: 尽量避免pod调度到该节点

如果其他节点资源不够了,再调度到该节点

上述的三种污点类型中
NoSchedule 和 PreferNoSchedule 是用于控制 Pod 调度过程时 的动作。
NoExecute 则是影响正在运行 Pod 的节点调度。

tolerations:
- key: "key"
  value: "value"
  operator: "Equal" # 或者 "Exists"
  effect: "NoSchedule" # 或者 "PreferNoSchedule" 或 "NoExecute"
  tolerationSeconds: 3600 # 只适用于 effect 为 "NoExecute" 的情况

容忍度支持简单的匹配(只是键值对)和更复杂的高级匹配。高级匹配包括以下几个方面:

  • operator:可以设置为Equal比较键和值,或者Exists只要键存在。
  • effect:指定污点的效果,Pod只会容忍具有匹配效果的污点。
  • tolerationSeconds:当使用NoExecute效果时,如果Pod有容忍度,但不是完全匹配,Pod将在指定的时间后被驱逐。如果是完全匹配,则Pod不会被驱逐。
  • key、value:用于匹配污点的键值对。

6.2、配置案例

用taint给master01打上一个污点

kubectl taint node master nginx=test:NoSchedule
kubectl taint node master nginx=test:NoExecute
kubectl describe node master

image.png
创建pod,配置容忍度为不调度NoSchedule

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-taint-test
  labels:
    app: nginx-taint
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-taint
  template:
    metadata:
      labels:
        app: nginx-taint
    spec:
      containers:
      - name: nginx-taint
        image: nginx:latest
        ports:
        - containerPort: 80
          name: nginx-taint
      tolerations: # 容忍度配置
      - key: "nginx" # 匹配node节点的key值为nginx
        operator: "Equal" # 操作符是等于
        value: "test"
        effect: "NoSchedule"  # 影响是 不调度
        # tolerationSeconds: 3600

kubectl apply -f taint/taint-test.sh
可以看到pod被分配到了node01和node02上
image.png
下面给node01打一个NoExecute污点后,可以看到node01上的pod被驱逐销毁,并在node02上新建pod
image.png
给node02打一个NoExecute污点后,可以看到pod处于pending状态
image.png
去掉节点上的污点

kubectl taint node node02 nginx=test:NoExecute- # 后边加-减号

6.3、yaml文件配置模板

tolerations:
- effect: NoSchedule	#影响是不调度 #key 值
	key: master-test 	#key值
	value: test #value 值
	operator: Equal #类似于正则表达式,等于这上述的就被容忍调度,key和value不对应也会受到影响
	tolerationsSeconds: 60 #只能容忍停留 60 秒、60 秒之后还会被驱逐

tolerations:
- effect: NoSchedule	#影响是不调度
	key: master-test		#key值
	operator: Exists		#只需匹配 node 节点 key 值就会容忍
	
tolerations:
- operator: Exists		#更粗暴的一种方式、匹配所有污点、一般很少这样用

tolerations:
- operator: Exists
	key: test						#只需匹配 key 这个值

7、Affinity亲和力:分为节点亲和力和pod亲和力

Affinity: 亲和力
虽然有nodeSelector、taint、但是都不够强大

7.1、Affinity 分为以下3种

  • NodeAffinity:节点亲和力
  • PodAffinity:pod亲和力
  • PodAntiAffinity:Pod反亲和力

备注:pod反亲和力用的比较多,比如我们部署zk、redis、kafka不让pod部署在同一个node节点上。

生产环境提示:
k8s官方建议当节点有上千个的话,不建议用Affinity,因为节点多的话,计算时间就会加长。
优化的一种方式:加入node节点有1000台,可以挑出其中的200台节点配置Affinity

7.2、三种亲和度都支持如下操作符号

Inlabel 的值在某个列表中
NotInlabel 的值不在某个列表中
Exists某个label存在
DoesNotExist某个label不存在
Gtlabel的值大于某个值
Ltlabel的值小于某个值

7.3、节点亲和力(Node Affinity)

节点亲和力允许你设置规则来限制Pod只能在满足特定条件的节点上运行,这些条件通常是基于节点的标签。

1、配置模板
affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
        - matchExpressions:
            - key: <label-key>
              operator: In
              values:
                - <label-value>
    preferredDuringSchedulingIgnoredDuringExecution:
      - weight: <weight>
        preference:
          matchExpressions:
            - key: <label-key>
              operator: In
              values:
                - <label-value>
  • requiredDuringSchedulingIgnoredDuringExecution:这表示Pod将仅在符合指定条件的节点上调度,是强制性的。
  • preferredDuringSchedulingIgnoredDuringExecution:这表示调度器将尝试调度Pod到符合指定条件的节点,但如果无法满足这些条件,Pod也可能被调度到其他节点。权重范围从1到100,优先级越来越高

注意:
如果nodeSelectorTerms下面有多个选项的话,满足任何一个条件就可以;
如果matchExpressions有多个选项的话,则必须同时满足这些条件才能正常调度pod

2、示例1:操作符号In,NotIn
  • 给node01上打标签

kubectl label nodes node01 app=test
kubectl label nodes node01 hard=ssd
查看
kubectl describe nodes node01 |head -15

image.png

  • 节点亲和性配置1(操作符号In,NotIn)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: node-affinity
  labels:
    app: node-affinity
spec:
  replicas: 3
  selector:
    matchLabels:
      app: node-affinity
  template:
    metadata:
      labels:
        app: node-affinity
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
          name: nginxweb
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:  # 硬策略,标签有app=test的节点,不生成pod
            nodeSelectorTerms:
            - matchExpressions:		# 在label值不包含app=test的node节点上生成pod
              - key: app
                operator: NotIn
                values:
                - test
          preferredDuringSchedulingIgnoredDuringExecution:  # 软策略,标签有hard=ssd的节点,尽量生成pod
          - weight: 1
            preference:
              matchExpressions:
              - key: hard
                operator: In
                values:
                - ssd

如下图所示,节点node01上有标签app=test,触发硬策略,不创建pod在node01上
image.png

2、示例2:操作符号Exists,DoesNotExist
  • 节点亲和性配置2(操作符Exists,DoesNotExist)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: node-exist-affinity
  labels:
    app: node-exist-affinity
spec:
  replicas: 3
  selector:
    matchLabels:
      app: node-exist-affinity
  template:
    metadata:
      labels:
        app: node-exist-affinity
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
          name: nginxweb
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:  # 硬策略,标签有app的节点,不生成pod
            nodeSelectorTerms:
            - matchExpressions:		# 节点标签key值不存在app的,生成pod
              - key: app
                operator: DoesNotExist
               # values:
               # - test
          preferredDuringSchedulingIgnoredDuringExecution:  # 软策略,标签有hard=ssd的节点,尽量生成pod
          - weight: 1
            preference:
              matchExpressions:
              - key: hard
                operator: In
                values:
                - ssd

如下图,node02上没有app=test标签,所以在node02上创建pod
image.png

7.4、Pod亲和力(Pod Affinity)

Pod亲和力允许你将Pod调度到与其他具有指定标签的Pod位于同一节点的位置。

1、配置模板
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mycontainer
    image: myimage
  affinity:
    # Pod亲和力设置
    podAffinity:
      # 必需的Pod亲和力规则,调度时强制执行
      requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            # 标签选择器,用于匹配其他Pod的标签
            matchLabels:
              key: value
            # 更复杂的表达式匹配
            matchExpressions:
              - key: another-key
                operator: In
                values:
                - value1
                - value2
          # 拓扑键,指示Pod应该与具有匹配标签的Pod位于同一拓扑域中
          topologyKey: kubernetes.io/hostname
      # 首选的Pod亲和力规则,调度时非强制执行
      preferredDuringSchedulingIgnoredDuringExecution:
        - weight: 100  # 权重设置,范围是1-100
          podAffinityTerm:
            labelSelector:
              matchLabels:
                key: value
            topologyKey: kubernetes.io/hostname

在这份模板中:

  • podAffinity 和 podAntiAffinity 允许你定义亲和力和反亲和力规则。
  • requiredDuringSchedulingIgnoredDuringExecution: 强制规则,必须满足。但在Pod运行时可能不再保证。
  • preferredDuringSchedulingIgnoredDuringExecution: 不是强制性的,调度器将尽量满足这些条件,权重范围从1到100,优先级越来越高
  • labelSelector 用于定义如何选择其他Pod的标签,如下两个选择器可以2选1,也可以同时使用
    • matchLabels: 是一个简单的键值对匹配。
    • matchExpressions: 提供了更复杂的选择功能,如以下操作符:In, NotIn, Exists, 和 DoesNotExist。
  • topologyKey: 定义了Pod之间应该如何分布。常见的值是 kubernetes.io/hostname,这表示Pod应该与具有匹配标签的Pod位于同一节点上。其他值可以是任何有效的标签键,比如 failure-domain.beta.kubernetes.io/zone 来指示在同一区域内。
2、示例
  • 配置步骤

1、创建一个参照pod,附带标签app2=web
2、再创建一个pod,添加pod亲和性标签app2=web,观察状态

  • 创建参照pod
apiVersion: v1
kind: Pod
metadata:
  name: nginx-flag
  namespace: default
  labels:
    app2: web  # 创建标签 app2=web,为下面pod的创建做参照
spec:
  containers:
    - name: nginx-flag
      image: nginx:latest

查看pod部署在那个节点
image.png
查看标签
image.png
查看node节点标签,没有app2=web
image.png

  • 创建有pod亲和性的pod
apiVersion: v1
kind: Pod
metadata:
  name: nginx-podaffinity
  namespace: default
spec:
  affinity:
    podAffinity:  # pod亲和性,匹配符合标签的pod,和其生成在同一个节点上
      requiredDuringSchedulingIgnoredDuringExecution:   # 硬策略
      - labelSelector:
          matchExpressions: # 匹配标签为 app2=web的pod,该pod就和其在同一个节点上生成
          - key: app2
            operator: In  # 操作符号
            values:
            - "web"
        topologyKey: kubernetes.io/hostname # 拓扑域、匹配k8s集群中node的名字
  containers:
  - name: nginx-podaffinity
    image: nginx:latest

如下图:
第1个pod生成在node01节点上,标签为app2=web
第2个pod匹配上标签为 app2=web的pod nginx-flag,就和其生成在同一个node节点上
这就是pod亲和性
image.png

7.5、pod反亲和力(pod AntiAffinity)

Pod反亲和力规则确保Pod被散布到不同的节点或拓扑域中,以提高应用的稳定性和高可用性。你可以使用这些规则来避免单点故障,或者将相似的服务分布到不同的节点上,以避免它们互相干扰。

1、配置模板
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mycontainer
    image: myimage
  affinity: 
    podAntiAffinity:
      # 必需的Pod反亲和力规则,在调度时强制执行
      requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
            # 标签选择器,用于匹配其他Pod的标签
            matchLabels:
              key1: value1
            # 可以使用更复杂的表达式匹配
            matchExpressions:
              - key: key2
                operator: In
                values:
                - value2
          # 拓扑键指示Pod不应与具有匹配标签的Pod位于同一拓扑域中
          topologyKey: kubernetes.io/hostname
      
      # 首选的Pod反亲和力规则,调度时非强制执行
      preferredDuringSchedulingIgnoredDuringExecution:
        - weight: 100  # 权重设置,范围1-100
          podAffinityTerm:
            labelSelector:
              matchLabels:
                key1: value1
            topologyKey: kubernetes.io/hostname

配置参数和pod亲和力一样

2、示例
apiVersion: v1
kind: Pod
metadata:
  name: nginx-podanti
  namespace: default
spec:
  affinity:
    podAntiAffinity:  # pod亲和性,匹配符合标签的pod,和其不在同一个节点上生成
      requiredDuringSchedulingIgnoredDuringExecution:   # 硬策略
      - labelSelector:
          matchExpressions: # 匹配标签为 app2=web的pod,该pod就和其不在同一个节点上生成
          - key: app2
            operator: In  # 操作符
            values:
            - "web"
        topologyKey: kubernetes.io/hostname # 拓扑域、匹配k8s集群中node的名字
  containers:
  - name: nginx-podanti
    image: nginx:latest

如下图所示,标签为app2=web的pod在node01上,故在node02上生成pod
image.png

如下文件有问题,反亲和力失效,新建pod和标签对应的pod在同一个节点上。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-pod-antiaffinity
  namespace: default
spec:
  affinity:
    podAntiAffinity:  # pod反亲和力,匹配符号标签的pod,和其不能部署在同一个节点上
      requiredDuringSchedulingIgnoredDuringExecution:   # 硬策略
      - labelSelector:
          matchExpressions: # 匹配标签为 app2=web的pod
          - key: app2
            operator: In  # 操作符
            values:
            - "web"
        topologyKey: kubernetes.io/hostname # 拓扑域定义一个范围
spec:
	replicas: 2
	selector:
  	matchLabels:
    	app2: web
  template:
    metadata:
      labels:
        app2: web
    spec:
      containers:
      - name: nginx-pod-antiaffinity
        image: nginx:latest
        ports:
          - containerPort: 80
            name: nginxweb

配置文件正常,可匹配,在除node01的其他节点上创建,但node02上只能创建一个pod。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: app
                    operator: In
                    values:
                      - web
              topologyKey: kubernetes.io/hostname
      containers:
        - name: web
          image: nginx:latest

7.6、affinity topology key 详解

参考:https://www.jianshu.com/p/d906e819245c

1. 我启动一个pod,希望(亲和性)或不希望(反亲和性)调度一台node上,并且这台node上有service=nginx标签的pod
2. 我启动一个2个副本控制器,pod标签为service=tomcat,可以调度到任意node上,不希望两个pod调度到同一个node上

需求:当前有两个机房( beijing,shanghai),需要部署一个nginx产品,副本为两个,为了保证机房容灾高可用场景,需要在两个机房分别部署一个副本
先给每个节点打标签

kubectl label nodes node01 zone=beijing
kubectl label nodes node02 zone=shanghai

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx-affinity-test
spec:
  serviceName: nginx-service
  replicas: 2
  selector:
    matchLabels:
      service: nginx
  template:
    metadata:
      name: nginx
      labels:
        service: nginx
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: service
                operator: In
                values:
                - nginx
            topologyKey: zone
      containers:
      - name: nginx
        image: nginx:latest
        command:
        - sleep
        - "360000000"

image.png
解释:两个node上分别有zone标签,来标注自己属于哪个机房,topologyKey定义为zone,pod所以在调度的时候,会根据node上zone标签来区分拓扑域,当前用的上 反亲和性调度 根据拓扑纬度调度,beijing机房调度完一个pod后,然后控制器判断beijing 拓扑域已经有server=nginx标签的pod,就在下一个拓扑域的node上调度了

8、临时容器EphemeralContainer

临时容器作用

当由于容器崩溃或容器镜像不包含调试工具而导致 kubectl exec 无用时, 临时容器对于交互式故障排查很有用。

https://www.jianshu.com/p/ff24560f9be1
https://blog.csdn.net/shenhonglei1234/article/details/106248054

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值