k8s-持久化存储PV与PVC(1)
1、概述
为什么 kubernetes 要持久化存储?
在 kubernetes 中部署应用都是以 Pod 的容器运行的,而 Pod 是有生命周期,一旦 Pod 被删除或重启后,这些数据也会随着丢失,则需要对这些数据进行持久化存储。
PV:Persistent Volume (简称:PV) 描述的是持久化存储数据卷。API 对象定义的是一个持久化存储在宿主机上的目录如:NFS的挂载目录。这个PV,通常是由运维人员事先创建好的,在 kubernetes 集群里面等待使用。
PVC:PersistentVolumeClaim(简称:PVC) 主要是用来向 kubernetes 申请存储资源的,PVC 是给 Pod 使用的对象,代表 Pod 去系统申请资源 PV。如果申请成功,kubernetes 会把 PV 和 PVC 绑定。
StorageClass:当作 PV的模板,PVC 绑定不到合适的PV时,可以动态创建的一种机制。在大规模的 kubernetes 生产集群中,可能会有很多的 PVC,随着项目的增加,可能还需要不断添加新的 PV,否则可能为某个新的 Pod 因 PVC 绑定不到 PV 而创建失败。于是 kubernetes 提供可以自动创建 PV 的机制,核心是 StorageClass API对象。
2、示例
首先,运维人员事先创建好 PV,在 kubernetes 集群里待用,这里定义一个 nfs(network file system)网络文件系统,yaml 文件如下:
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-demo
namespace: default
spec:
storageClassName: nfs-storeage # 存储名称
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
nfs:
server: 192.168.120.11 # IP 是NFS服务器的地址
path: /nfs/data/haha/ # 该目录需要提前创建好,否则可能失败
开发人员要去使用,首先创建 PVC,比如想要使用 一个 1GiB 大小的 PVC,yaml 文件如下:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-demo
namespace: default
spec:
storageClassName: nfs-storeage # 存储类的名称(必须与PV的storageClassName相同)
accessModes:
- ReadWriteOnce # 单节点读写
resources:
requests:
storage: 1Gi
accessModes 访问模式:
- ReadWriteOnce:卷可以被一个节点以读写方式挂载;
- ReadOnlyMany:可以被多个节点以只读方式挂载;
- ReadWriteMany:卷可以被多个节点以读写方式挂载;
- ReadWriteOncePod:卷可以被单个Pod以读写方式挂载;
这样就可以使用的了,但是要真正让容器使用起来,需要注意的点:
- PV 和 PVC 的storageClassName 字段必须一样;
- 必须满足 PVC 的要求;
- 还有值得注意的是Kubernetes 里定义存储容量使用的是国际标准,日常习惯使用的 KB/MB/GB 的基数是 1024,要写成 Ki/Mi/Gi ,否则单位不一致实际容量就会对不上。
以上示例,Kubernetes 就会根据 PVC 里的描述,去找能够匹配 StorageClass 和容量的 PV,然后把 PV 和 PVC“绑定”在一起,实现存储的分配。当将 PVC 和 PV 进行绑定之后,Pod 就能够像使用 hostPath 等常规类型的 Volume 一样,有了持久卷存储,现在就可以为 Pod 挂载存储卷了,在 YAML 文件里声明使用这个 PVC 了,如下所示:
apiVersion: v1
kind: Pod
metadata:
name: "nginx-pvc"
namespace: default
labels:
app: "nginx-pvc"
spec:
containers:
- name: nginx-pvc
image: "nginx"
ports:
- containerPort: 80
name: http
volumeMounts:
- name: localtime
mountPath: /etc/localtime
- name: html
mountPath: /usr/share/nginx/html/
volumes:
- name: localtime
hostPath:
path: /usr/share/zoneinfo/Asia/Shanghai
- name: html
persistentVolumeClaim:
claimName: nginx-pvc # 申请书的名字
restartPolicy: Always
这样就把存储卷挂载到 Nginx 容器的 /etc/localtime
和 /usr/share/nginx/html/
目录了。
3、PV 与 PVC 小结
PV 和 PVC:
- 只要有PV,那么PVC先是Pending状态;
- PV被创建后,正好PVC要用,那么PVC自动绑定到这个PV卷上;
- PVC可以被提前创建并和PV绑定,以后Pod需要关联PVC即可;
Pod 删除,PVC 还在吗?
PVC 并不会影响,需要手动删除PVC。(yaml遵循Pod和PVC写在文件)
PVC 删除会不会影响 PV?
根据回事策略不同决定的。如NFS回收策略是Recycle,那么PV不会被删除,但内容被清空,PV重新变回可用状态。如果是Retain策略,PVC删除,PV是不受影响的要删除自己手动。
Retain策略场景:如Pod部署数据库的,如删除Pod时,希望k8s重新拉起(不能用Retain和Recycle一旦删除啥都没有了)所以Retain是默认的。
状态表示:
- Released :PV 释放,释放了和PVC关联关系,绑定不存在,新的不同PVC不能重新绑定上来
- Available: PV 可用,也可以和任意的PVC绑定
- Failed(失败,可能卷不支持)
- Bound(已绑定)
4、emptyDir 存储卷
使用 emptyDir 时,Pod 分配到某个 Node 上时,emptyDir 会被创建,当Pod在该节点运行期间卷一直存在的,卷最初时空的。
尽管Pod中的容器挂载 emptyDir 卷的路径可能相同也可能不同,这些容器都可以读写 emptyDir卷中相同的文件。
当Pod因为某些原因被从节点删除时,这时emptyDir卷中数据也会被永久删除的。
示例:
定义了 2 个容器,两个容器之间挂载的 emptyDir ,它们是可以实现共享。
apiVersion: v1
kind: Pod
metadata:
name: nginx-test
spec:
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: nginx-containers
ports:
- name: http
containerPort: 80
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
- name: busybox
image: busybox:latest
name: busybox-containers
imagePullPolicy: IfNotPresent
volumeMounts:
- name: html
mountPath: /data/
command: ['/bin/sh','-c','while true;do echo $(date) >> /data/index.html;sleep 2;done']
volumes:
- name: html
emptyDir: {}
说明:Pod里面容器无论重启或崩溃期间 emptyDir 卷是安全的,不会导致卷丢失。但 Pod被删除,重新拉起,或Pod超出资源限制被 Kubelet 杀死了,emptyDir 卷中的数据也会被永久删除,这种存储卷也称为“临时存储”。
5、hostPath 存储卷
指的是 Pod 挂载宿主机的某个目录或文件,hostPath 卷使得容器可以使用宿主机的文件系统进行存储。
示例:
apiVersion: v1
kind: Pod
metadata:
name: "pod-hostpath-test"
namespace: default
labels:
app: "pod-hostpath-test"
spec:
containers:
- name: pod-time
image: "busybox"
command: ["sleep","60000"]
volumeMounts:
- name: localtime
mountPath: /etc/localtime
volumes:
- name: localtime # 卷名称一定要一样
hostPath: # 宿主机路径,这个文件挂在到容器目录(/etc/localtime)
path: /usr/share/zoneinfo/Asia/Shanghai
type: Directory # 细节:可以声明类型是文件夹还是文件
说明:当 Pod 被删除,这个存储卷还在,只要保证同一个 Pod 被调度到同一个节点上, 在 pod 被删除重新被调度到这个节点之后,对应的数据依然是存在的。
6、emptyDir 与 hostPath 小结
- emptyDir与hostPath属于节点级别的卷类型;
- emptyDir的生命周期与Pod资源相同,一旦Pod被删除,数据也就丢失;
- hostPath卷的Pod一旦被重新调度至其他节点,那么它将无法再使用此前的数据;
原文地址:https://blog.csdn.net/realize_dream/article/details/144312094
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!