6.1. 介绍卷
6.1.1. 卷的类型
emptyDir - 用于存储临时数据的简单空目录
hostPath - 用于将目录从工作节点的文件系统挂载到 pod
nfs - 挂载到 pod 中的 NFS 共享卷.
还有其他的如 gitRepo,gcepersistenDisk
6.2. 通过卷在容器间共享数据
6.2.1. 使用 emptyDir 卷
卷的生命周期与 pod 的生命周期项关联, 所以当删除 pod 时, 卷的内容就会丢失.
使用 empty 示例代码如下:
- apiVersion: v1
- kind: Pod
- metadata:
- name: fortune
- spec:
- containers:
- - image: luksa/fortune
- name: html-gener
- volumeMounts:
- - name: HTML
- mountPath: /usr/share/nginx
- readOnly: true
- - image: nginx/aplin
- name: web-service
- volumeMounts:
- - name: HTML
- mountPath: /usr/share
- readOnly: true
- volumes:
- - name: HTML // 一个名为 HTML 的单独 emptyDir 卷, 挂载在上面的两个容器中
- emptyDir: {}
6.3. 访问工作节点文件系统上的文件
6.3.1.hostPath 卷
hostPath 是持久性存储, emptyDir 卷的内容随着 pod 的删除而删除.
使用 hostPath 会发现当删除一个 pod, 并且下一个 pod 使用了指向主机上相同路径的 hostPath 卷, 则新 pod 将会发现上一个 pod 留下的数据, 但前提是必须将其调度到与第一个 pod 相同的节点上.
所以当你使用 hostPath 时请务必考虑清楚, 当重新起一个 pod 时候, 必须要保证 pod 的节点与之前相同.
- apiVersion: v1
- kind: Pod
- metadata:
- name: test-pd
- spec:
- containers:
- - image: k8s.gcr.io/test-webserver
- name: test-container
- volumeMounts:
- - mountPath: /test-pd
- name: test-volume
- volumes:
- - name: test-volume
- hostPath:
- # directory location on host
- path: /data
- # this field is optional
- type: Directory
6.4. 使用持久化存储
怎样保证 pod 重新启动后调度到任意一个节点都有相同的数据可用, 这就需要做到持久化存储.
因此必须要将数据存储在某种类型的网络存储 (NAS) 中.
各种支持的方式不尽相同, 例如 GlusterFS 需要创建 Endpoint,Ceph/NFS 之流就没这么麻烦了.
6.4.1. 使用 NFS 存储
以 NFS 为例, YAML 代码如下:
6.4.2.configmap 和 secert
secret 和 configmap 可以理解为特殊的存储卷, 但是它们不是给 Pod 提供存储功能的, 而是提供了从集群外部向集群内部的应用注入配置信息的功能. ConfigMap 扮演了 K8S 集群中配置中心的角色. ConfigMap 定义了 Pod 的配置信息, 可以以存储卷的形式挂载至 Pod 中的应用程序配置文件目录, 从 configmap 中读取配置信息; 也可以基于环境变量的形式, 从 ConfigMap 中获取变量注入到 Pod 容器中使用. 但是 ConfigMap 是明文保存的, 如果用来保存数据库账号密码这样敏感信息, 就非常不安全. 一般这样的敏感信息配置是通过 secret 来保存. secret 的功能和 ConfigMap 一样, 不过 secret 是通过 Base64 的编码机制保存配置信息.
从 ConfigMap 中获取配置信息的方法有两种:
一种是利用环境变量将配置信息注入 Pod 容器中的方式, 这种方式只在 Pod 创建的时候生效, 这就意味着在 ConfigMap 中的修改配置信息后, 更新的配置不能被已经创建 Pod 容器所应用.
另一种是将 ConfigMap 做为存储卷挂载至 Pod 容器内, 这样在修改 ConfigMap 配置信息后, Pod 容器中的配置也会随之更新, 不过这个过程会有稍微的延迟.
ConfigMap 当作存储卷挂载至 Pod 中的用法:
- apiVersion: v1
- kind: Pod
- metadata:
- name: pod-configmap-vol-2
- labels:
- name: pod-configmap-vol-2
- spec:
- containers:
- - name: myapp
- image: ikubernetes/myapp:v1
- volumeMounts:
- - name: my-cm-www
- mountPath: /etc/nginx/conf.d/ # 将名为 my-www 的 configmap 挂载至 Pod 容器的这个目录下.
- volumes:
- - name: my-cm-www
- configMap: # 存储卷类型选 configMap
secert 的方法类似, 只是 secert 对数据进行了加密
6.5. 从底层存储技术解耦 pod
6.5.1. 介绍持久卷和持久卷声明
当集群用户需要在其 pod 中使用持久化存储时, 他们首先创建持久化声明 (PVC) 清单, 指定所需要的最低容量要求, 和访问模式, 然后用户将持久卷声明清单提交给 kubernetes API 服务器, kubernetes 将找到可以匹配的持久卷并将其绑定到持久卷声明.
持久卷声明可以当做 pod 中的一个卷来使用, 其他用户不能使用相同的持久卷, 除非先通过删除持久卷声明绑定来释放.
6.5.2. 创建持久卷
下面创建一个 PV mypv1, 配置文件 pv1.YAML 如下:
- apiVersion: v1
- kind: PersistentVolume
- metadata:
- name: yh_pv1
- spec:
- capacity:
- storage: 1Gi //capacity 指定 PV 的容量为 1G
- accessModes: //accessModes 指定访问模式为 ReadWriteOnce
- - ReadWriteOnce
- persistentVolumeReclaimpolicy: Recycle //persistentVolumeReclaimPolicy 指定当 PV 的回收策略为 Recycle
- storageClassName: nfs //storageClassName 指定 PV 的 class 为 nfs. 相当于为 PV 设置了一个分类, PVC 可以指定 class 申请相应 class 的 PV.
- nfs:
- path: /nfs/data // 指定 PV 在 NFS 服务器上对应的目录
- server: 10.10.0.11
1.accessModes 指定访问模式为 ReadWriteOnce, 支持的访问模式有:
ReadWriteOnce - PV 能以 read-write 模式 mount 到单个节点.
ReadOnlyMany - PV 能以 read-only 模式 mount 到多个节点.
ReadWriteMany - PV 能以 read-write 模式 mount 到多个节点.
2.persistentVolumeReclaimPolicy 指定当 PV 的回收策略为 Recycle, 支持的策略有:
Retain - 需要管理员手工回收.
Recycle - 清除 PV 中的数据, 效果相当于执行 rm -rf /thevolume/*.
Delete - 删除 Storage Provider 上的对应存储资源, 例如 AWS EBS,GCE PD,Azure Disk,OpenStack Cinder Volume 等.
创建 pv:
- # kubectl apply -f pv1.YAML
- persistentvolume/yh-pv1 created
查看 pv:
- # kubectl get pv
- NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
- yh-pv1 1Gi RWO Recycle Available nfs 17m
STATUS 为 Available, 表示 yh-pv1 就绪, 可以被 PVC 申请.
6.5.3. 通过持久卷声明来获取持久卷
接下来创建 PVC mypvc1, 配置文件 pvc1.YAML 如下:
- apiVersion: v1
- kind: PersistentVolumeClaim
- metadata:
- name: yh-pvc
- spec:
- accessModes:
- - ReadWriteOnce
- resources:
- requests:
- storage: 1Gi
- storageClassName: nfs
PVC 就很简单了, 只需要指定 PV 的容量, 访问模式和 class.
执行命令创建 mypvc1:
- # kubectl apply -f pvc1.YAML
- persistentvolumeclaim/yh-pvc created
查看 pvc
- # kubectl get pvc
- NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
- yh-pvc Bound yh-pv1 1Gi RWO nfs 64s
从 kubectl get pvc 和 kubectl get pv 的输出可以看到 yh-pvc1 已经 Bound 到 yh- pv1, 申请成功.
- # kubectl get pv
- NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
- yh-pv1 1Gi RWO Recycle Bound default/yh-pvc nfs 47m
6.5.4. 在 pod 中使用持久卷声明
上面已经创建好了 pv 和 pvc,pod 中直接使用这个 pvc 即可
与使用普通 Volume 的格式类似, 在 volumes 中通过 persistentVolumeClaim 指定使用 mypvc1 申请的 Volume.
通过命令创建 mypod1:
可见, 在 Pod 中创建的文件 /mydata/hello 确实已经保存到了 NFS 服务器目录 /nfsdata 中.
如果不再需要使用 PV, 可用删除 PVC 回收 PV.
6.5.5. 回收持久卷
当 PV 不再需要时, 可通过删除 PVC 回收.
未删除 pvc 之前 pv 的状态是 Bound
删除 pvc 之后 pv 的状态变为 Available,, 此时解除绑定后则可以被新的 PVC 申请.
/nfsdata 文件中的文件被删除了
因为 PV 的回收策略设置为 Recycle, 所以数据会被清除, 但这可能不是我们想要的结果. 如果我们希望保留数据, 可以将策略设置为 Retain.
通过 kubectl apply 更新 PV:
回收策略已经变为 Retain, 通过下面步骤验证其效果:
1 重新创建 mypvc1.
2 在 mypv1 中创建文件 hello.
3 mypv1 状态变为 Released.
4 PV 中的数据被完整保留.
虽然 mypv1 中的数据得到了保留, 但其 PV 状态会一直处于 Released, 不能被其他 PVC 申请. 为了重新使用存储资源, 可以删除并重新创建 mypv1. 删除操作只是删除了 PV 对象, 存储空间中的数据并不会被删除.
新建的 mypv1 状态为 Available, 已经可以被 PVC 申请.
PV 还支持 Delete 的回收策略, 会删除 PV 在 Storage Provider 上对应存储空间. NFS 的 PV 不支持 Delete, 支持 Delete 的 Provider 有 AWS EBS,GCE PD,Azure Disk,OpenStack Cinder Volume 等.
6.6. 持久卷的动态配置
6.6.1. 通过 StorageClass 资源定义可用存储类型
前面的例子中, 我们提前创建了 PV, 然后通过 PVC 申请 PV 并在 Pod 中使用, 这种方式叫做静态供给(Static Provision).
与之对应的是动态供给(Dynamical Provision), 即如果没有满足 PVC 条件的 PV, 会动态创建 PV. 相比静态供给, 动态供给有明显的优势: 不需要提前创建 PV, 减少了管理员的工作量, 效率高.
动态供给是通过 StorageClass 实现的, StorageClass 定义了如何创建 PV, 下面是两个例子.
StorageClass standard:
StorageClass slow:
这两个 StorageClass 都会动态创建 AWS EBS, 不同在于 standard 创建的是 gp2 类型的 EBS, 而 slow 创建的是 io1 类型的 EBS. 不同类型的 EBS 支持的参数可参考 AWS 官方文档.
StorageClass 支持 Delete 和 Retain 两种 reclaimPolicy, 默认是 Delete.
与之前一样, PVC 在申请 PV 时, 只需要指定 StorageClass 和容量以及访问模式, 比如:
除了 AWS EBS,Kubernetes 支持其他多种动态供给 PV 的 Provisioner, 完整列表请参考
6.6.2.PV&&PVC 在应用在 MySQL 的持久化存储
下面演示如何为 MySQL 数据库提供持久化存储, 步骤为:
创建 PV 和 PVC.
部署 MySQL.
向 MySQL 添加数据.
模拟节点宕机故障, Kubernetes 将 MySQL 自动迁移到其他节点.
验证数据一致性.
首先创建 PV 和 PVC, 配置如下:
MySQL-pv.YAML
MySQL-pvc.YAML
创建 MySQL-pv 和 MySQL-pvc:
接下来部署 MySQL, 配置文件如下:
PVC MySQL-pvc Bound 的 PV MySQL-pv 将被 mount 到 MySQL 的数据目录 var/lib/MySQL.
MySQL 被部署到 k8s-node2, 下面通过客户端访问 Service MySQL:
kubectl run -it --rm --image=MySQL:5.6 --restart=Never MySQL-client -- MySQL -h MySQL -ppassword
更新数据库:
1 切换到数据库 MySQL.
2 创建数据库表 my_id.
3 插入一条数据.
4 确认数据已经写入.
关闭 k8s-node2, 模拟节点宕机故障.
验证数据的一致性:
由于 node2 节点已经宕机, node1 节点接管了这个任务.
通过 kubectl run 命令 进入 node1 的这个 pod 里, 查看数据是否依旧存在
MySQL 服务恢复, 数据也完好无损.
来源: https://www.cnblogs.com/yaohong/p/11489164.html