K8S数据存储持久化Volume和高级存储之PV、PVC
1.Volume卷介绍
-
Volume介绍
- Volume是K8S抽象出来的对象,它被定义在Pod上,然后被一个Pod里的多个容器挂载到具体的文件目录上
- K8S通过Volume实现同一个Pod中不同容器之间的数据共享以及数据的持久化存储
- Volume的生命周期不与Pod中单个容器的生命周期相关,当容器终止或者重启时,Volume中的数据也不会丢失
- K8S可以支持许多类型的卷,Pod也能同时使用任意数量的卷
-
Volume常见的类型
- 常规存储:EmptyDir、HostPath
- 高级存储:PV、PVC
- 配置存储:ConfigMap、Secret
- 其他:网络存储系统NFS、CIFS,包括云服务商提供的、本地式、分布式
2.EmptyDir临时存储
- 概念
-
当Pod指定到某个节点上时,首先创建的是一个EmptyDir卷,只要Pod在该节点上运行卷就一直存在
-
当Pod因为某些原因被从节点删除时,EmptyDir卷中的数据也会永久删除
-
容器崩溃并不会导致Pod被从节点上移除,所以容器崩溃时EmptyDir卷中的数据是安全的
-
用途:临时缓存空间
-
案例:Pod里面定义两个容器,一个产生日志,一个读取日志输出到控制台
apiVersion: v1 kind: Pod metadata: name: gen-volume spec: containers: - image: nginx:1.23.0 name: nginx ports: - containerPort: 80 volumeMounts: # 将nginx-log-volue挂载到nginx容器中,对应的目录为/var/log/ngin - name: nginx-log-volume mountPath: /var/log/nginx - image: busybox:1.35.0 name: busybox command: ["/bin/sh","-c","tail -f /usr/local/test/access.log"] # 容器启动后初始命令,读取指定文件中内容 volumeMounts: - name: nginx-log-volume mountPath: /usr/local/test volumes: # 声明volume存储卷 - name: nginx-log-volume emptyDir: {}
-
3.HostPath持久化到node
-
概念
- EmptyDir中数据没做持久化,随着Pod的结束而销毁,需要持久化到磁盘则选其他方式
- HostPath类型的磁盘就是挂载了主机的一个文件或者目录
-
HostPath有多种类型,列举常见几个
- Directory:给定的目录路径必须存在
- DirectoryOrCreate:如果给定路径不存在则根据需要新建空目录
- File:给定路径上必须存在对应文件
- FIleOrCreate:如果给定路径文件不存在则根据需要新建空文件
-
案例
- 注意:需要去节点对应的目录查看文件是否存在,即Pod运行的节点,主节点没有
apiVersion: v1 kind: Pod metadata: name: gen-volume spec: containers: - image: nginx:1.23.0 name: nginx ports: - containerPort: 80 volumeMounts: # 将nginx-log-volue挂载到nginx容器中,对应的目录为/var/log/ngin - name: nginx-log-volume mountPath: /var/log/nginx - image: busybox:1.35.0 name: busybox command: ["/bin/sh","-c","tail -f /usr/local/test/access.log"] # 容器启动后初始命令,读取指定文件中内容 volumeMounts: - name: nginx-log-volume mountPath: /usr/local/test volumes: # 声明volume存储卷 - name: nginx-log-volume hostPath: path: /usr/local/test type: DirectoryOrCreate
-
EmptyDir和HostPath比较
-
都是本地存储卷方式
-
EmptyDir是临时存储空间,完全不提供持久化支持,在Pod内
-
HostPath的卷数据是持久化在node节点的文件系统中的,即便Pod已经被删除了,volume卷中的数据还留存在node节点上
-
3.ConfigMap存储配置信息
-
ConfigMap介绍(缩写cm)
- 是K8S的一种api对象,用来把非加密数据(明文)保存到键值对中,比如etcd
- 可以用作环境变量、命令行参数等,将环境变量、配置信息和容器镜像解耦,便于应用配置的修改
-
使用
-
方式一:使用命令创建
# kubectl create cm 名字 --from-literal=key1=value1 kubectl create cm gen-config --from-literal=key1=value1 --from-literal=username=Gen
-
方式二:使用yaml文件创建
apiVersion: v1 kind: ConfigMap metadata: name: gen-config data: username: "Gen" password: "123"
-
创建Pod的yaml,将ConfigMap挂载进去
apiVersion: v1 kind: Pod metadata: name: gen-volume spec: containers: - image: nginx:1.23.0 name: nginx ports: - containerPort: 80 volumeMounts: - name: config mountPath: /config volumes: # 声明volume存储卷 - name: config configMap: name: gen-config
-
-
4.Secret存储加密信息
-
介绍
- 用来保存敏感信息,例如密码、密钥、证书、OAuth令牌和ssh key等
- 就不需要把这些敏感数据暴露到镜像或者Pod中
- Pod可以用三种方式之一来使用Secret
- 作为挂载到一个或多个容器上的卷中的文件
- 作为容器的环境变量
- 有kubelet在为Pod拉取镜像时使用
-
Secret有多个类型
-
dockerconfigjson
- 用来存储私有docker registry的认证信息
-
Service Account
- 只要与K8S API有交互的Pod,都会自动拥有此种类型的Secret
- K8S自动创建,并且会自动挂载到Pod的/run/secrets/kubernetes.io/serviceaccount目录中
-
Opaque(工作常用)
-
加密类型为base64,其特点就是将明文改为了密文
-
操作实战:在Pod中的Secret信息实际已经被解密
# 获取base64加密后的字符 echo -n 'Gen' | base64 echo -n '123' | base64 # 创建gen-secret.yaml apiVersion: v1 kind: Secret metadata: name: gen-secret type: Opaque data: username: R2Vu password: MTIz # 创建Pod的yaml,将Secret挂载进去 apiVersion: v1 kind: Pod metadata: name: gen-volume spec: containers: - image: nginx:1.23.0 name: nginx ports: - containerPort: 80 volumeMounts: - name: config mountPath: /etc/secret volumes: # 声明volume存储卷 - name: config secret: secretName: gen-secret
-
-
5.NFS持久卷挂载
-
前置条件,NFS搭建:https://blog.csdn.net/2302_76363587/article/details/143812230
-
创建Pod挂载NFS
apiVersion: v1 kind: Pod metadata: name: gen-volume spec: containers: - image: nginx:1.23.0 name: nginx ports: - containerPort: 80 volumeMounts: - name: logs-volume mountPath: /var/log/nginx volumes: # 声明volume存储卷 - name: logs-volume nfs: server: 192.168.91.132 # NFS服务器地址 path: /data/NFSdata # 共享文件夹
6.高级存储之PV、PVC
-
什么是PV持久卷(Persistent Volume)
- 是集群中由管理员配置的一段网络存储,它是集群的一部分资源和底层存储密切相关,对象包含存储实现的细节,即对接NFS、CIFS等存储系统
- 不同的PV会对应到不同的存储资源,这样在Pod的时候直接调用集群内部的PV即可
- PV没有命名空间隔离概念
-
什么是PVC持久卷声明(Persistent Volume Claim)
- 假如存在很多PV,K8S需要使用PV的时候,如果需要存储能力比较大的存储资源,就需要一个一个去对比PV,这样很耗费资源(因为要满足需求)
- PVC是用户存储的一种声明,PVC可以请求特定的存储空间和访问模式,PVC消耗的是PV资源
- PVC必须与对应的PV建立关系,PVC会根据定义的PV去申请
- 创建Pod的时候会附带一个PVC的请求,PVC的请求相当于就是去寻找一个合适的PV
- 使用逻辑
- 在Pod中定义一个存储卷(该存储卷类型为PVC),定义的时候按指定大小,PVC必须与对应的PV建立关系,PVC会根据定义的需求去PV申请,而PV是由存储空间创建出来的
-
PV和PVC逻辑
-
PV是集群中的资源,PVC是对这些资源的请求
-
PV和PVC之间的相互作用遵循这个生命周期
- Provisioning(配置)–>Binding(绑定)–>Using(使用)–>Releasing(释放)–>Recycling(回收)
-
-
PV的yaml模板
apiVersion: v1 kind: PersistentVolume metadata: name: gen-pv spec: capacity: storage: 5Gi # 存储大小 accessModes: # 访问模式 - ReadWriteOnce persistentVolumeReclaimPolicy: Recycle # 回收策略 storageClassName: slow # 存储类别 nfs: # 卷插件 server: 192.168.91.132 # NFS服务器地址 path: /data/NFSdata # 共享文件夹
-
storage存储大小:存储大小是可请求的唯一资源。未来可能会包含IOPS、吞吐量等属性
-
accessModes访问模式:用户对资源的访问权限
- ReadWriteOnce(RWO):读写权限,只能被单个节点挂载
- ReadOnlyMany(ROX):只读权限,可以被多个节点挂载
- ReadWriteMany(RWX):读写权限,可以被多个节点挂载
-
storageClassName存储类别
- 每个PV可以属于某个类,通过将其storageClassName属性设置为某个StorageClass的名称来指定
- 特定类的PV卷只能绑定到请求该类存储卷的PVC申领
- 未设置storageClassName的PV卷没有类设定,只能给到那些没有指定特定存储类的PVC申领
-
persistentVolumeReclaimPolicy回收策略(当PV不再被使用了之后的处理策略)
- Retain(保留):当PV对象被删除之后,与之相关的位于外部的基础设施中的数据仍然存在(如NFS),需要根据实际情况手动回收
- Recycle(回收):相当于在卷上执行rm -rf /volume/* 操作,之后该卷可以用于新的PVC申领
- Delete(删除):当PV对象被删除之后,与之相关的位于外部的基础设施中的数据也被一并删除(如NFS),更多的是云厂商设备
-
-
状态(PV的生命周期有4种不同状态)
- Available(可用):一块空闲资源,还没被任何声明绑定
- Bound(已绑定):卷已经被声明绑定
- Released(已释放):声明被删除,但是资源还未被集群重新声明
- Failed(失败):该卷的自动回收失败
7.NFS+PV+PVC+Pod实战
-
NFS服务器操作
# 创建目录 mkdir -p /opt/nfsdata/pv1 /opt/nfsdata/pv2 chmod 777 /opt/nfsdata/pv1 /opt/nfsdata/pv2 # 修改配置文件,暴露nfs服务 vim /etc/exports /opt/nfsdata/pv1 192.168.91.0/24(rw,insecure,sync) /opt/nfsdata/pv2 192.168.91.0/24(rw,insecure,sync) # 重启nfs服务 systemctl restart nfs
-
创建两个PV
apiVersion: v1 kind: PersistentVolume metadata: name: gen-pv1 spec: capacity: storage: 1Gi accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Retain nfs: server: 192.168.91.132 path: /opt/nfsdata/pv1 --- apiVersion: v1 kind: PersistentVolume metadata: name: gen-pv2 spec: capacity: storage: 2Gi accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Retain nfs: server: 192.168.91.132 path: /opt/nfsdata/pv2
-
创建两个PVC(与PV不同,PVC不属于集群资源,拥有自己的命名空间)
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: gen-pvc1 spec: accessModes: - ReadWriteMany resources: requests: storage: 1Gi --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: gen-pvc2 spec: accessModes: - ReadWriteMany resources: requests: storage: 2Gi
-
创建Pod挂载PVC
apiVersion: v1 kind: Pod metadata: name: gen-pod1 spec: containers: - image: busybox name: busybox command: ["/bin/sh","-c","while true;do echo hello pod1 >> /opt/print.txt;sleep 3;done;"] volumeMounts: - name: volume mountPath: /opt volumes: - name: volume persistentVolumeClaim: claimName: gen-pvc1 readOnly: false --- apiVersion: v1 kind: Pod metadata: name: gen-pod2 spec: containers: - image: busybox name: busybox command: ["/bin/sh","-c","while true;do echo hello pod2 >> /opt/print.txt;sleep 3;done;"] volumeMounts: - name: volume mountPath: /opt volumes: - name: volume persistentVolumeClaim: claimName: gen-pvc2 readOnly: false