由于容器和Pod是短暂的,会被频繁销毁和创建,容器销毁时,内部的文件系统也会被清理。为了持久化保存容器的数据,可以使用Kubernates
Volume
emptyDir Volume
emptyDir是Host上的一个空目录,对于容器是持久化的,对于Pod不是。emptyDir
Volume的生命周期与Pod一致
适用场景:
Pod中的容器需要通过文件传递数据
Pod中的容器临时共享存储空间
hostPath Volume
hostPath
Volume将Host文件系统中已有的目录mount给Pod的容器,这样会将Pod与节点耦合,限制了Pod的创建
适用场景:需要访问kubernetes或docker内部数据(配置文件或二进制文件)的应用
云存储
如Elastic Block Store
PV&PVC
Persistent
Volume(PV)是外部存储系统中的一块空间,由管理员创建和维护。具有持久性,生命周期独立于Pod
Persistent Volume
Claim(PVC)是对PV的申请,由普通账号创建和维护,需要为Pod分配存储资源时,用户创建一个PVC,指明存储资源的小大和访问权限等信息
k8s支持的PV类型有:EBS,Ceph,NFS等
Think:为什么不直接为Pod创建云存储空间,而是通过PV-PVC
NFS
NFS(network file
system)通过网络,使不同的机器不同的系统实现文件共享。NFS客户端可以将NFS服务器共享的目录挂载到本地的文件系统中,访问目录如同访问本地目录一样
创建NFS服务器
在node1节点安装nfs服务
1 2 3 4 5 6 7 8 9 10 11
| # 安装nfs服务组件 yum install nfs-utils -y mkdir /home/work/nfs cat > /etc/exports <<EOF /home/work/nfs 192.168.174.0/24(rw,sync,no_root_squash) EOF systemctl start rpcbind systemctl start nfs cd /etc exportfs -r netstat -ntlp
|
客户端配置
搜索网络中可用的共享目录 showmount -e node1
创建本地目录并挂载共享目录
1 2 3
| mkdir /home/work/mnt mount -t nfs node1:/home/work/nfs /home/work/mnt cd /home/work/mnt && ll
|
创建PV
编写配置文件 nfs-pv1.yml,手动创建PV的方式叫静态供给
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| apiVersion: v1 kind: PersistentVolume metadata: name: pv-nginx-html spec: capacity: storage: 2Gi accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Retain storageClassName: nginx-html nfs: path: /home/work/nfs/nginx/html server: node1 --- apiVersion: v1 kind: PersistentVolume metadata: name: pv-nginx-log spec: capacity: storage: 2Gi accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Retain storageClassName: nginx-log nfs: path: /home/work/nfs/nginx/log server: node1 --- apiVersion: v1 kind: PersistentVolume metadata: name: pv-nginx-conf spec: capacity: storage: 2Gi accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Retain storageClassName: nginx-conf nfs: path: /home/work/nfs/nginx/conf server: node1
|
说明:
- capacity指定PV容量
- accessModes 指定访问模式:
- ReadWriteOnce:可读可写,只支持被单个节点挂载
- ReadOnlyMany:只读,可被多个节点挂载
- ReadWriteMany:可读可写,被多个节点挂载
- persistentVolumeReclaimPolicy 指定PV的回收策略:
- Retain:管理员手动清理
- Recycle:删除数据(NFS和HostPath支持)
- Delete:删除存储资源(EBS等云存储支持)
- storageClassName 指定PV的类型为nfs
- nfs的path需要是nfs服务器是存在的路径
创建pv1:Kubectl apply -f nfs-pv1.yml
查看pv:kubectl get pv
创建pvc
编写配置文件 nfs-pvc1.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| kind: PersistentVolumeClaim apiVersion: v1 metadata: name: nginx-html-pvc spec: accessModes: - ReadWriteMany resources: requests: storage: 1Gi storageClassName: nginx-html --- kind: PersistentVolumeClaim apiVersion: v1 metadata: name: nginx-conf-pvc spec: accessModes: - ReadWriteMany resources: requests: storage: 1Gi storageClassName: nginx-conf --- kind: PersistentVolumeClaim apiVersion: v1 metadata: name: nginx-log-pvc spec: accessModes: - ReadWriteMany resources: requests: storage: 1Gi storageClassName: nginx-log
|
创建pvc:kubectl apply -f nfs-pvc1.yml
查看pvc:kubectl get pvc
在Pod中使用存储
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| apiVersion: apps/v1 kind: Deployment metadata: labels: app: nginx name: nginx-deployment spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80 volumeMounts: - name: nginx-log mountPath: /var/log/nginx - name: nginx-html mountPath: /etc/nginx/html - name: nginx-conf-d mountPath: /etc/nginx/conf.d tolerations: - key: "key" operator: "Equal" value: "nginx" effect: "NoSchedule" volumes: - name: nginx-log persistentVolumeClaim: claimName: nginx-log-pvc - name: nginx-html persistentVolumeClaim: claimName: nginx-html-pvc - name: nginx-conf-d persistentVolumeClaim: claimName: nginx-conf-pvc
|
这样,将容器内nginx的html、conf、log挂载到nfs服务器上,方便编写页面、修改配置、查看日志
Think:多个应用要挂载路径可能很多,需要创建很多的PV和PVC,管理很不方便,而且PV一般由管理员创建,PVC由开发人员创建,如果每个挂载路径都要要求管理员创建PV,效率低下,不便于管理,该如何解决
Think:在nfs中修改nginx配置文件后,需要重启Pod才可以让配置生效,如果让Pod按照顺序先后重启,而不是全部同时重启
回收PV
kubectl delete pvc {pvc_name}
PV 动态供给
静态供给的缺点有:
- 需要提前创建PV,还需要在nfs等共享存储上提前创建目录,管理员的工作增加,效率低;
- 维护成本高
为了解决上面的问题,使用动态共给
https://kubernetes.io/docs/concepts/storage/storage-classes/#nfs
安装动态pv
使用helm安装nfs-client-provisioner:helm install nfs-client-provisioner stable/nfs-client-provisioner --set nfs.server=node1 --set nfs.path=/home/work/nfs --set storageClass.defaultClass=true --set image.repository=rkevin/nfs-subdir-external-provisioner --set image.tag=fix-k8s-1.20
验证
1 2 3 4 5 6 7 8 9 10 11 12 13
| cat > test-pvc.yaml << EOF apiVersion: v1 kind: PersistentVolumeClaim metadata: name: test-nfs-pvc spec: accessModes: - ReadWriteMany storageClassName: nfs-client resources: requests: storage: 1Gi EOF
|
无需手动创建pv
存在问题
- 为什么不直接为Pod创建云存储空间,而是通过PV-PVC(创建的云存储空间是一次性创建很大一块空间,应用是很多的,每个应用都挂载到一个独立的云存储空间不利于管理和维护,容易造成空间的浪费)
- 挂载路径太多,PV&PVC不便于管理,如何解决(答案:PV的动态供给)
- 重启nginx服务,如何不全部同时重启,防止服务不可用