Pod亲和性;Pod反亲和性;API资源对象PV和PVC;本地存储;NFS存储
Pod亲和性
针对对象为Pod,目的是实现,新建Pod和目标Pod调度到一起,在同一个Node上。
示例:
apiVersion: v1
kind: Pod
metadata:
name: testpod01
labels:
app: myapp01
env: test1
spec:
containers:
- name: testpod01
image: nginx:1.23.2
apiVersion: v1
kind: Pod
metadata:
name: testpod02
labels:
app: myapp02
env: test2
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution: ##必须满足下面匹配规则
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- myapp01 ## app=myapp01, 上面的Pod是符合要求的
topologyKey: "kubernetes.io/hostname"
containers:
- name: testpod02
image: redis:6.2
Pod反亲和性
针对对象为Pod,目的是实现,新建Pod和目标Pod不要调度到一起,不在同一个Node上。
示例:
apiVersion: v1
kind: Pod
metadata:
name: testpod01
labels:
app: myapp01
env: test1
spec:
containers:
- name: testpod01
image: nginx:1.23.2
apiVersion: v1
kind: Pod
metadata:
name: testpod02
labels:
app: myapp02
env: test2
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution: ##必须满足下面匹配规则
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- myapp01 ## app=myapp01, 上面的Pod是符合要求的
topologyKey: "kubernetes.io/hostname"
containers:
- name: testpod02
image: redis:6.2
污点与容忍度
污点(Taint)针对节点来说,和节点亲和性正好相对,节点亲和性使Pod被吸引到一类特定的节点,而污点则使节点能够排斥一类特定的Pod。
容忍度(Toleration)应用于Pod上,它用来允许调度器调度带有对应污点的节点。 容忍度允许调度但并不保证调度:作为其功能的一部分, 调度器也会评估其他参数。
污点和容忍度(Toleration)相互配合,可以避免Pod被分配到不合适的节点上。 每个节点上都可以应用一个或多个污点,这表示对于那些不能容忍这些污点的Pod, 是不会被该节点接受的。
设置污点命令格式:
kubectl taint node [node] key=value:[effect]
说明:
其中[effect] 可取值:[ NoSchedule | PreferNoSchedule | NoExecute ]:
NoSchedule :一定不能被调度,已经在运行中的Pod不受影响。
PreferNoSchedule:尽量不要调度,实在没有节点可调度再调度到此节点。
NoExecute:不仅不会调度,还会驱逐Node上已有的Pod。
清除污点命令格式:
kubectl taint node [node] key:[effect]-
示例:
kubectl taint node tanglinux02 name=tang:NoSchedule
查看污点:
kubectl describe node tanglinux02 | grep Taints -A 10
设置容忍度的几种规则:
1)完全匹配
tolerations:
- key: "taintKey" #和污点的key名字保持一致
operator: "Equal" #匹配类型,Equal表示匹配污点的所有值
value: "taintValue" #和污点key的值保持一致
effect: "NoSchedule" #污点类型
说明:
Pod 的 Toleration 声明中的key和effect需要与Taint的设置保持一致。
Operator如果设置为Equal,则key和value,要和Taint的设置保持一致。
2)不完全匹配
tolerations:
- key: "taintKey" #和污点的key名字保持一致
operator: "Exists" #匹配类型,只要符合污点设置的key即可
effect: "NoSchedule" #污点的类型
说明:
Operator如果设置为Exists,则不需要指定value,只看key名字
3)大范围匹配
tolerations:
- key: "taintKey" #和污点的key名字保持一致
operator: "Exists"
说明:
如果不设置effect,则只需要看key名字即可,不管Taint里的effect设置为什么都会匹配到
4)匹配所有
tolerations:
- operator: "Exists"
说明:
如果省略key和effect,则匹配所有Taint, 在k8s中的daemonsets资源默认情况下是容忍所有污点的。
驱逐延缓时间设置
tolerations:
- key: "key1"
operator: "Equal"
value: "value1"
effect: "NoExecute"
tolerationSeconds: 3600
说明:
如果这个Pod 正在运行,那么Pod还将继续在节点上运行3600秒,然后被驱逐。 如果在此之前上述污点被删除了,则Pod不会被驱逐。
完整Pod YAML示例:
apiVersion: v1
kind: Pod
metadata:
name: ng
labels:
env: dev
spec:
containers:
- name: ng
image: nginx:1.21.0
tolerations:
- key: name
operator: Exists
effect: NoSchedule
存储持久化相关三个概念:
1) PersistentVolume(PV)
是对具体存储资源的描述,比如NFS、Ceph、GlusterFS等,通过PV可以访问到具体的存储资源;
2) PersistentVolumeClaim(PVC)
Pod想要使用具体的存储资源需要对接到PVC,PVC里会定义好Pod希望使用存储的属性,通过PVC再去申请合适的存储资源(PV),匹配到合适的资源后PVC和PV会进行绑定,它们两者是一一对应的;
3) StorageClass(SC)
PV可以手动创建,也可以自动创建,当PV需求量非常大时,如果靠手动创建PV就非常麻烦了,SC可以实现自动创建PV,并且会将PVC和PV绑定。
SC会定义两部分内容:
① pv的属性,比如存储类型、大小;
② 创建该PV需要用到的存储插件(provisioner),这个provisioner是实现自动创建PV的关键。
API资源对象PV和PVC
1)PV YAML示例:
vi testpv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: testpv
spec:
storageClassName: test-storage
accessModes:
- ReadWriteOnce
capacity:
storage: 500Mi ##提供500Mi空间
hostPath:
path: /tmp/testpv/
说明:
storageClassName: 定义存储类名称,PV和PVC中都会有该字段,目的是为了方便两者匹配绑定在一起
accessModes定义该pv的访问权限模式,有三种:
- ReadWriteOnce:存储卷可读可写,但只能被一个节点上的 Pod 挂载;
- ReadOnlyMany:存储卷只读不可写,可以被任意节点上的 Pod 多次挂载;
- ReadWriteMany:存储卷可读可写,也可以被任意节点上的 Pod 多次挂载;
capacity 定义该存储大小。
hostPath 定义该存储访问路径,这里指的是本地的磁盘。
2)PVC YAML示例:
vi testpvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: testpvc
spec:
storageClassName: test-storage
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Mi ##期望申请100Mi空间
应用pv和pvc的YAML
kubectl apply -f testpv.yaml -f testpvc.yaml
查看状态
kubectl get pv,pvc
实验:
将testpvc的期望100Mi改为1000Mi,查看PV的STATUS
3)PV和PVC匹配规则
PV创建好后,会等待PVC与其进行绑定,PVC一旦找到合适的PV就会绑定。如果有多个PV时,PVC又是如何匹配PV的呢?它有如下一些规则:
① 访问模式和存储类匹配:Kubernetes会筛选出访问模式(accessModes)和存储类(storageClassName)与PVC相匹配的PV。如果没有匹配的PV,PVC将保持未绑定状态。
② 资源大小:在满足访问模式和存储类匹配的PV中,Kubernetes会选择资源大小大于或等于PVC请求大小的PV。
③ 最佳匹配:在满足访问模式、存储类和资源大小的PV中,Kubernetes会选择资源大小最接近PVC请求大小的PV。如果有多个PV具有相同的资源大小,Kubernetes会选择其中一个进行绑定。
④ 避免重复绑定:一个PV在任何时候只能被一个PVC绑定。一旦PV被绑定到一个PVC,它将不再可用于其他PVC。
本地存储
在上一章节中的PV YAML示例,就是本地存储。本地存储类型的PV是Kubernetes中一种比较特殊的持久化存储,它允许将节点上的本地磁盘或目录用作PV。与其他PV类型(例如NFS、Ceph或云存储)不同,本地存储类型的PV直接使用节点上的存储资源,因此具有更低的延迟和更高的性能。
使用本地存储类型的PV时,需注意以下几个关键点:
- 节点特性:本地存储类型的PV与特定的节点绑定,因为它直接使用节点上的存储资源。这意味着当创建PV时,需要指定与之关联的节点。可以在PV的spec部分设置nodeAffinity来实现的。
nodeAffinity: ##定义节点亲和性
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- node-name
- 数据持久性:由于本地存储类型的PV与特定节点关联,当该节点发生故障时,存储在PV中的数据可能无法访问。因此,在使用本地存储类型的PV时,请确保采取适当的数据备份策略,以防止节点故障导致的数据丢失。
- 调度限制:Pod使用本地存储类型的Persistent Volume Claim(PVC)时,Kubernetes会尝试将Pod调度到关联PV的节点上。如果节点上的资源不足以运行Pod,Pod将无法启动。因此,在使用本地存储类型的PV时,请确保关联的节点有足够的资源来运行Pod。
- 回收策略:当PVC被删除时,PV的回收策略将决定如何处理关联的本地存储。对于本地存储类型的PV,建议使用Retain或Delete回收策略。Retain策略表示保留存储和数据,以便手动清理和管理;Delete策略表示删除存储和数据。需要注意的是,Recycle策略并不适用于本地存储类型的PV。
persistentVolumeReclaimPolicy: Retain
完整示例:
首先,确保在每个要使用本地存储的节点上创建一个本地目录。例如,在节点上创建/mnt/local-storage目录:
mkdir -p /mnt/local-storage
然后,创建一个PV资源配置文件,例如local-pv.yaml:
apiVersion: v1
kind: PersistentVolume
metadata:
name: local-pv
labels:
type: local
spec:
storageClassName: local-storage
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
local:
path: /mnt/local-storage
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname #这是内置的节点标签,表示节点的主机名
operator: In
values:
- tanglinux02 #只有tanglinux02这个主机节点才满足要求
应用PV资源配置文件:
kubectl apply -f local-pv.yaml
再创建一个PVC资源配置文件,例如local-pvc.yaml:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: local-pvc
spec:
storageClassName: local-storage
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
应用PVC资源配置文件:
kubectl apply -f local-pvc.yaml
Kubernetes会自动将PVC与PV绑定。创建好的PVC可以在Pod中使用,将本地存储挂载到容器中。
最后,创建一个Pod资源配置文件,例如local-pod.yaml:
apiVersion: v1
kind: Pod
metadata:
name: local-pod
spec:
containers:
- name: local-container
image: nginx:1.21.0
volumeMounts:
- name: local-storage
mountPath: /data
volumes:
- name: local-storage
persistentVolumeClaim:
claimName: local-pvc
应用Pod资源配置文件:
kubectl apply -f local-pod.yaml
现在,local-pod中的local-container已经挂载了本地存储。所有写入/data目录的数据都将持久化在本地存储中。
NFS存储
注意:在做本章节示例时,需要拿单独一台机器来部署NFS,具体步骤略。
NFS作为常用的网络文件系统,在多机之间共享文件的场景下用途广泛,毕竟NFS配置方便,而且稳定可靠。
NFS同样也有一些缺点:① 存在单点故障的风险;② 不方便扩容;③ 性能一般。
NFS比较适合一些简单的、对存储要求不高的场景,比如测试环境、开发环境。
完整示例:
首先部署好NFS服务,并且保证所有Kubernetes节点可以顺利挂载(showmount -e 192.168.222.128 )
安装相关依赖,节点也需要安装:
yum install nfs-utils
定义基于NFS的PV
vi nfs-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
storageClassName: nfs-storage
nfs:
path: /data/nfs2
server: 192.168.222.128
应用
kubectl apply -f nfs-pv.yaml
定义PVC
vi nfs-pvc.yaml
apiVersion: v1
kind: Pod
metadata:
name: nfs-pod
spec:
containers:
- name: nfs-container
image: nginx:1.21.0
volumeMounts:
- name: nfs-storage
mountPath: /data
volumes:
- name: nfs-storage
persistentVolumeClaim:
claimName: nfs-pvc
应用
kubectl apply -f nfs-pod.yaml