8.k8s持久化存储
1.Volumes Container(容器)中的磁盘文件是短暂的,当容器崩溃时,kubelet 会重新启动容器,但最初 的文件将丢失,Container 会以最干净的状态启动。另外,当一个 Pod 运行多个 Container 时,各 个容器可能需要共享一些文件。Kubernetes Volume
1.Volumes Container(容器)中的磁盘文件是短暂的,当容器崩溃时,kubelet 会重新启动容器,但最初 的文件将丢失,Container 会以最干净的状态启动。另外,当一个 Pod 运行多个 Container 时,各 个容器可能需要共享一些文件。Kubernetes Volume
Container(容器)中的磁盘文件是短暂的,当容器崩溃时,kubelet 会重新启动容器,但最初 的文件将丢失,Container 会以最干净的状态启动。另外,当一个 Pod 运行多个 Container 时,各 个容器可能需要共享一些文件。Kubernetes Volume 可以解决这两个问题。
一些需要持久化数据的程序才会用到 Volumes,或者一些需要共享数据的容器需要 volumes。 Redis-Cluster:nodes.conf
日志收集的需求:需要在应用程序的容器里面加一个 sidecar,这个容器是一个收集日志的 容器,比如 filebeat,它通过 volumes 共享应用程序的日志文件目录。
Volumes:官方文档 https://kubernetes.io/docs/concepts/storage/volumes/
背景
Docker 也有卷的概念,但是在 Docker 中卷只是磁盘上或另一个 Container 中的目录,其生 命周期不受管理。虽然目前 Docker 已经提供了卷驱动程序,但是功能非常有限,例如从 Docker 1.7 版本开始,每个 Container 只允许一个卷驱动程序,并且无法将参数传递给卷。 另一方面,Kubernetes 卷具有明确的生命周期,与使用它的 Pod 相同。因此,在 Kubernetes 中的卷可以比 Pod 中运行的任何 Container 都长,并且可以在 Container 重启或者销毁之后保留 数据。Kubernetes 支持多种类型的卷,Pod 可以同时使用任意数量的卷。 从本质上讲,卷只是一个目录,可能包含一些数据,Pod 中的容器可以访问它。要使用卷 Pod 需要通过.spec.volumes 字段指定为 Pod 提供的卷,以及使用.spec.containers.volumeMounts 字段 指定卷挂载的目录。从容器中的进程可以看到由 Docker 镜像和卷组成的文件系统视图,卷无法 挂载其他卷或具有到其他卷的硬链接,Pod 中的每个 Container 必须独立指定每个卷的挂载位置.和上述 volume 不同的是,如果删除 Pod,emptyDir 卷中的数据也将被删除,一般 emptyDir 卷用于 Pod 中的不同 Container 共享数据。它可以被挂载到相同或不同的路径上。
默认情况下,emptyDir 卷支持节点上的任何介质,可能是 SSD、磁盘或网络存储,具体取 决于自身的环境。可以将 emptyDir.medium 字段设置为 Memory,让 Kubernetes 使用 tmpfs(内 存支持的文件系统),虽然 tmpfs 非常快,但是 tmpfs 在节点重启时,数据同样会被清除,并且 设置的大小会被计入到 Container 的内存限制当中。
使用 emptyDir 卷的示例,直接指定 emptyDir 为{}即可:
创建
# kubectl apply -f nginx-deploy.yaml验证
hostPath 卷可将节点上的文件或目录挂载到 Pod 上,用于 Pod 自定义日志输出或访问 Docker 内部的容器等。
使用 hostPath 卷的示例。将主机的/data 目录挂载到 Pod 的/test-pd 目录
hostPath 卷常用的 type(类型)如下:
type 为空字符串:默认选项,意味着挂载 hostPath 卷之前不会执行任何检查。
DirectoryOrCreate:如果给定的 path 不存在任何东西,那么将根据需要创建一个权限为 0755 的空目录,和 Kubelet 具有相同的组和权限。
Directory:目录必须存在于给定的路径下。
FileOrCreate:如果给定的路径不存储任何内容,则会根据需要创建一个空文件,权限设 置为 0644,和 Kubelet 具有相同的组和所有权。
File:文件,必须存在于给定路径中。
Socket:UNIX 套接字,必须存在于给定路径中。
CharDevice:字符设备,必须存在于给定路径中。
BlockDevice:块设备,必须存在于给定路径中。
Exporter 配置 /data/nfs/ 192.168.0.0/24(rw,sync,no_subtree_check,no_root_squash)
只有Volume无法满足生产需求

当某个数据卷不再被挂载使用时,里面的数据如何处理?
如果想要实现只读挂载如何处理?
如果想要只能一个Pod挂载如何处理?
如何只允许某个Pod使用10G的空间?
PersistentVolume:简称PV,是由Kubernetes管理员设置的存储,可以配置Ceph、 NFS、GlusterFS等常用存储配置,相对于Volume配置,提供了更多的功能,比 如生命周期的管理、大小的限制。PV分为静态和动态。 PersistentVolumeClaim:简称PVC,是对存储PV的请求,表示需要什么类型的PV, 需要存储的技术人员只需要配置PVC即可使用存储,或者Volume配置PVC的名称 即可。 官方文档:https://kubernetes.io/docs/concepts/storage/persistent-volumes/
更简单的持久化存储方式

Retain:保留,该策略允许手动回收资源,当删除PVC时,PV仍然存 在,PV被视为已释放,管理员可以手动回收卷。
Recycle:回收,如果Volume插件支持,Recycle策略会对卷执行rm - rf清理该PV,并使其可用于下一个新的PVC,但是本策略将来会被弃 用,目前只有NFS和HostPath支持该策略。
Delete:删除,如果Volume插件支持,删除PVC时会同时删除PV, 动态卷默认为Delete,目前支持Delete的存储后端包括AWS EBS, GCE PD, Azure Disk, or OpenStack Cinder等。
可以通过persistentVolumeReclaimPolicy: Recycle字段配置
官方文档:https://kubernetes.io/docs/concepts/storage/persistent-volumes/#reclaim-policy
ReadWriteOnce:可以被单节点以读写模式挂载,命令行中可以被缩写为RWO。
ReadOnlyMany:可以被多个节点以只读模式挂载,命令行中可以被缩写为ROX。
ReadWriteMany:可以被多个节点以读写模式挂载,命令行中可以被缩写为RWX。
ReadWriteOncePod :只允许被单个Pod访问,需要K8s 1.22+以上版本,并且是CSI 创建的PV才可使用
官方文档:https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes
存储分类
PV的状态
hostPath:hostPath服务配置 path:宿主机路径
创建

创建pv
创建pvc
挂载PVC
验证
验证
root@k8s-master01:~/hhh# cat nginx-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
creationTimestamp: "2020-09-19T02:41:11Z"
generation: 1
labels:
app: nginx
name: nginx
namespace: default
spec:
progressDeadlineSeconds: 600
replicas: 2
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- image: nginx:1.15.2
imagePullPolicy: IfNotPresent
name: nginx
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /opt
name: share-volume
- image: nginx:1.15.2
imagePullPolicy: IfNotPresent
name: nginx2
command:
- sh
- -c
- sleep 3600
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /mnt
name: share-volume
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
volumes:
- name: share-volume
emptyDir: {}root@k8s-master01:~/hhh# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-749bf78769-hxdnc 2/2 Running 1 (12m ago) 73m
nginx-749bf78769-kxtlj 2/2 Running 1 73m
root@k8s-master01:~/hhh# kubectl exec -it nginx-749bf78769-hxdnc -c nginx bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@nginx-749bf78769-hxdnc:/# df -h
Filesystem Size Used Avail Use% Mounted on
overlay 19G 13G 5.0G 72% /
tmpfs 64M 0 64M 0% /dev
/dev/mapper/ubuntu--vg-ubuntu--lv 19G 13G 5.0G 72% /opt
shm 64M 0 64M 0% /dev/shm
tmpfs 3.6G 12K 3.6G 1% /run/secrets/kubernetes.io/serviceaccount
tmpfs 1.9G 0 1.9G 0% /proc/acpi
tmpfs 1.9G 0 1.9G 0% /proc/scsi
tmpfs 1.9G 0 1.9G 0% /sys/firmware
root@nginx-749bf78769-hxdnc:/# cd /opt/
root@nginx-749bf78769-hxdnc:/# mkdir test
root@nginx-749bf78769-hxdnc:/opt# ls
test
root@k8s-master01:~/hhh# kubectl exec nginx-749bf78769-hxdnc -c nginx2 -- ls /mnt
test容器nginx下
volumeMounts:
- mountPath: /opt
name: share-volume
- mountPath: /etc/timezone
name: timezone
volumes:
- name: share-volume
emptyDir: {}
- name: timezone
hostPath:
path: /etc/timezone
type: File
root@k8s-master01:~/hhh# kubectl replace -f nginx-deploy.yaml
root@k8s-master01:~/hhh# kubectl exec -it nginx-86f6b6c8b9-8nvd8 -c nginx bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@nginx-86f6b6c8b9-8nvd8:/# cat /etc/timezone
Asia/Shanghai容器nginx2下
- mountPath: /opt
name: nfs-volume
- name: nfs-volume
nfs:
server: 192.168.0.204
path: /data/nfs/test-dp
root@k8s-master01:~/hhh# kubectl replace -f nginx-deploy.yaml
nginx-5c9477c7f-8cghl 2/2 Running 0 35s
root@k8s-master01:~/hhh# kubectl exec -it nginx-5c9477c7f-5htsq -c nginx2 bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@nginx-5c9477c7f-5htsq:/# df -h
Filesystem Size Used Avail Use% Mounted on
overlay 19G 12G 6.0G 67% /
tmpfs 64M 0 64M 0% /dev
/dev/mapper/ubuntu--vg-ubuntu--lv 19G 12G 6.0G 67% /mnt
192.168.20.246:/data/nfs/test-dp 19G 17G 608M 97% /opt
shm 64M 0 64M 0% /dev/shm
tmpfs 3.6G 12K 3.6G 1% /run/secrets/kubernetes.io/serviceaccount
tmpfs 1.9G 0 1.9G 0% /proc/acpi
tmpfs 1.9G 0 1.9G 0% /proc/scsi
tmpfs 1.9G 0 1.9G 0% /sys/firmwareapiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nfs
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: nfs-slow
mountOptions:
- hard
- nfsvers=4.1
nfs:
path: /data/k8s
server: 192.168.20.246capacity:容量配置
volumeMode:卷的模式,目前支持Filesystem(文件系统) 和 Block(块),其中Block类型需要后端存储支持,默认为文件系统
accessModes:该PV的访问模式
storageClassName:PV的类,一个特定类型的PV只能绑定到特定类别的PVC;
persistentVolumeReclaimPolicy:回收策略
mountOptions:非必须,新版本中已弃用
nfs:NFS服务配置,包括以下两个选项
path:NFS上的共享目录
server:NFS的IP地址NFS服务器安装服务端: yum install nfs* rpcbind -y
所有K8s节点安装NFS客户端:yum install nfs-utils -y
NFS服务端:mkdir /data/k8s -p
NFS服务器创建共享目录:vim /etc/exports
/data/k8s/ *(rw,sync,no_subtree_check,no_root_squash)
exportfs -r
systemctl restart nfs rpcbind
挂载测试:mount -t nfs nfs-serverIP:/data/k8s /mnt/root@k8s-master01:~/hhh# kubectl create -f nfs-pv.yaml
persistentvolume/pv-nfs created
root@k8s-master01:~/hhh# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS C LAIM STORAGECLASS REASON AGE
pv-nfs 5Gi RWO Recycle Available kind: PersistentVolume
apiVersion: v1
metadata:
name: task-pv-volume
labels:
type: local
spec:
storageClassName: hostpath
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/data"root@k8s-master01:~/hhh# kubectl create -f task-pv-volume.yaml
root@k8s-master01:~/hhh# kubectl get pv task-pv-volume
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
task-pv-volume 10Gi RWO Retain Available hostpath 18sapiVersion: v1
kind: PersistentVolume
metadata:
name: ceph-rbd-pv
spec:
capacity:
storage: 1Gi
storageClassName: ceph-fast
accessModes:
- ReadWriteOnce
rbd:
monitors:
- 192.168.1.123:6789
- 192.168.1.124:6789
- 192.168.1.125:6789
pool: rbd
image: ceph-rbd-pv-test
user: admin
secretRef:
name: ceph-secret
fsType: ext4
readOnly: falseroot@k8s-master01:~/hhh# cat nfs-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nfs
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: nfs-slow
mountOptions:
- hard
- nfsvers=4.1
nfs:
path: /data/k8s
server: 192.168.20.246
root@k8s-master01:~/hhh#
root@k8s-master01:~/hhh# kubectl get pv pv-nfs
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-nfs 5Gi RWO Recycle Bound default/task-pvc-nfs nfs-slow 127m
root@k8s-master01:~/hhh# cat nfs-pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: task-pvc-nfs
spec:
storageClassName: nfs-slow
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3G
root@k8s-master01:~/hhh# kubectl get pvc task-pvc-nfs
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
task-pvc-nfs Bound pv-nfs 5Gi RWO nfs-slow 9m37s
root@k8s-master01:~/hhh# cat pvc-nfs.yaml
kind: Pod
apiVersion: v1
metadata:
name: task-pv-pod
spec:
volumes:
- name: task-pv-storage
persistentVolumeClaim:
claimName: task-pvc-nfs
containers:
- name: task-pv-container
image: nginx
ports:
- containerPort: 80
name: "http-server"
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: task-pv-storageroot@k8s-master01:~/hhh# kubectl get pod
NAME READY STATUS RESTARTS AGE
task-pv-pod 1/1 Running 0 18s
root@k8s-master01:~/hhh# kubectl exec -it task-pv-pod bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@task-pv-pod:/# df -h
Filesystem Size Used Avail Use% Mounted on
overlay 19G 12G 6.0G 67% /
tmpfs 64M 0 64M 0% /dev
/dev/mapper/ubuntu--vg-ubuntu--lv 19G 12G 6.0G 67% /etc/hosts
shm 64M 0 64M 0% /dev/shm
192.168.20.246:/data/k8s 19G 17G 600M 97% /usr/share/nginx/html
tmpfs 3.6G 12K 3.6G 1% /run/secrets/kubernetes.io/serviceaccount
tmpfs 1.9G 0 1.9G 0% /proc/acpi
tmpfs 1.9G 0 1.9G 0% /proc/scsi
tmpfs 1.9G 0 1.9G 0% /sys/firmware
root@harbor:/data/k8s# echo 666 > index.html
root@task-pv-pod:/usr/share/nginx/html# ls
index.htmlapiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
namespace: default
spec:
replicas: 2
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
volumes:
- name: task-pv-storage
persistentVolumeClaim:
claimName: task-pvc-nfs
containers:
- env:
- name: TZ
value: Asia/Shanghai
- name: LANG
value: C.UTF-8
image: nginx
imagePullPolicy: IfNotPresent
name: nginx
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: task-pv-storageroot@k8s-master01:~/hhh# kubectl replace -f pvc.yaml
deployment.apps/nginx replaced
root@k8s-master01:~/hhh# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-7b979c74f8-sbc2w 0/1 Terminating 0 20m
nginx-85f4ccf987-7k6f4 1/1 Running 0 4s
nginx-85f4ccf987-rmz4t 1/1 Running 0 6s
task-pv-pod 1/1 Running 0 8m16s
root@k8s-master01:~/hhh# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-85f4ccf987-7k6f4 1/1 Running 0 6s
nginx-85f4ccf987-rmz4t 1/1 Running 0 8s
task-pv-pod 1/1 Running 0 8m18s
root@k8s-master01:~/hhh# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-85f4ccf987-7k6f4 1/1 Running 0 8s
nginx-85f4ccf987-rmz4t 1/1 Running 0 10s
task-pv-pod 1/1 Running 0 8m20s
root@k8s-master01:~/hhh# kubectl exec -it pods/nginx-85f4ccf987-7k6f4 bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@nginx-85f4ccf987-7k6f4:/# cd /usr/share/nginx/html/
root@nginx-85f4ccf987-7k6f4:/usr/share/nginx/html# ls
index.html
root@nginx-85f4ccf987-7k6f4:/usr/share/nginx/html# cat index.html
666
root@nginx-85f4ccf987-7k6f4:/usr/share/nginx/html# exit
exit
root@k8s-master01:~/hhh# kubectl exec -it pods/nginx-85f4ccf987-rmz4t bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@nginx-85f4ccf987-rmz4t:/# cd /usr/share/nginx/html/
root@nginx-85f4ccf987-rmz4t:/usr/share/nginx/html# ls
index.html
root@nginx-85f4ccf987-rmz4t:/usr/share/nginx/html# cat index.html
666