emptyDir-用于存储临时数据的简单空目录html
hostPath-用于将目录从工做节点的文件系统挂载到podnode
nfs-挂载到pod中的NFS共享卷。mysql
还有其余的如gitRepo、gcepersistenDisknginx
卷的生命周期与pod的生命周期项关联,因此当删除pod时,卷的内容就会丢失。git
使用empty示例代码以下:web
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: {}
hostPath是持久性存储,emptyDir卷的内容随着pod的删除而删除。sql
使用hostPath会发现当删除一个pod,而且下一个pod使用了指向主机上相同路径的hostPath卷,则新pod将会发现上一个pod留下的数据,但前提是必须将其调度到与第一个pod相同的节点上。数据库
因此当你使用hostPath时请务必考虑清楚,当从新起一个pod时候,必需要保证pod的节点与以前相同。api
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
所以必需要将数据存储在某种类型的网络存储(NAS)中。安全
各类支持的方式不尽相同,例如 GlusterFS 须要建立 Endpoint,Ceph/NFS 之流就没这么麻烦了。
以NFS为例,yml代码以下:
secret和configmap能够理解为特殊的存储卷,可是它们不是给Pod提供存储功能的,而是提供了从集群外部向集群内部的应用注入配置信息的功能。ConfigMap扮演了K8S集群中配置中心的角色。ConfigMap定义了Pod的配置信息,能够以存储卷的形式挂载至Pod中的应用程序配置文件目录,从configmap中读取配置信息;也能够基于环境变量的形式,从ConfigMap中获取变量注入到Pod容器中使用。可是ConfigMap是明文保存的,若是用来保存数据库帐号密码这样敏感信息,就很是不安全。通常这样的敏感信息配置是经过secret
来保存。secret
的功能和ConfigMap同样,不过secret是经过Base64的编码机制保存配置信息。
从ConfigMap中获取配置信息的方法有两种:
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对数据进行了加密
当集群用户须要在其pod中使用持久化存储时,他们首先建立持久化声明(PVC)清单,指定所须要的最低容量要求,和访问模式,而后用户将持久卷声明清单提交给kubernetes API服务器,kubernetes将找到能够匹配的持久卷并将其绑定到持久卷声明。
持久卷声明能够当作pod中的一个卷来使用,其余用户不能使用相同的持久卷,除非先经过删除持久卷声明绑定来释放。
下面建立一个 PV mypv1
,配置文件pv1.yml
以下:
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.yml 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 申请。
接下来建立 PVC mypvc1
,配置文件 pvc1.yml
以下:
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.yml 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
上面已经建立好了pv和pvc,pod中直接使用这个pvc便可
与使用普通 Volume 的格式相似,在 volumes
中经过 persistentVolumeClaim
指定使用 mypvc1
申请的 Volume。
经过命令建立mypod1
:
可见,在 Pod 中建立的文件 /mydata/hello
确实已经保存到了 NFS 服务器目录 /nfsdata
中。
若是再也不须要使用 PV,可用删除 PVC 回收 PV。
当 PV 再也不须要时,可经过删除 PVC 回收。
未删除pvc以前 pv的状态是Bound
删除pvc以后pv的状态变为Available,,此时解除绑定后则能够被新的 PVC 申请。
/nfsdata文件中的文件被删除了
由于 PV 的回收策略设置为 Recycle
,因此数据会被清除,但这可能不是咱们想要的结果。若是咱们但愿保留数据,能够将策略设置为 Retain
。
经过 kubectl apply
更新 PV:
回收策略已经变为 Retain
,经过下面步骤验证其效果:
① 从新建立 mypvc1
。
② 在 mypv1
中建立文件 hello
。
③ mypv1
状态变为 Released
。
④ 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 等。
前面的例子中,咱们提早建立了 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,完整列表请参考 https://kubernetes.io/docs/concepts/storage/storage-classes/#provisioner
下面演示如何为 MySQL 数据库提供持久化存储,步骤为:
建立 PV 和 PVC。
部署 MySQL。
向 MySQL 添加数据。
模拟节点宕机故障,Kubernetes 将 MySQL 自动迁移到其余节点。
验证数据一致性。
首先建立 PV 和 PVC,配置以下:
mysql-pv.yml
mysql-pvc.yml
建立 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
更新数据库:
① 切换到数据库 mysql。
② 建立数据库表 my_id。
③ 插入一条数据。
④ 确认数据已经写入。
关闭 k8s-node2
,模拟节点宕机故障。
验证数据的一致性:
因为node2节点已经宕机,node1节点接管了这个任务。
经过kubectl run 命令 进入node1的这个pod里,查看数据是否依旧存在
MySQL 服务恢复,数据也无缺无损。