kubernets: Persistent Volume & Persistent Volume Claim
by 伊布
k8s 1.5版本支持了有状态应用StatefullSet,其中一个很重要的技术支撑点就是,持久化存储。
在前面介绍Statefull的时候,我把涉及到PV的地方改为使用HostPath+nodeSelector来代替了,虽然可以达到“有状态”的目的,但是应用如果要保证数据的HA,需要应用本身起多副本,并且副本之间需要能够自行完成数据的备份。
要求有点高。
更好的做法是什么呢?回过头来看,如果将应用app和数据做好解耦,那么只要做到数据本身的HA就可以了,所以,Persist Volume(持久化存储)是一剂良药。
kubernetes v1.2版本开始,引入了2个资源API:PersistentVolume(pv)和PersistentVolumeClaim(pvc)。
pv与container用的volume不同。container用的volume是与pod相同生命周期的,delete pod后,volume也会随之删除;但pv不同,其生命周期独立于pod。
有了pv,pod的需求按说就满足了,为什么还要pvc呢?原因是,生产环境上pod的提交者可能只是普通用户,而pv的创建需要admin,所以更好的做法是将pv看作一种像cpu/memory的资源,普通客户的pod需要多少存储,向k8s提交请求(pvc)就行了。k8s会根据请求和当前的pv情况,选择一个能够满足pvc要求的pv,将该pv与该pvc绑定,并挂载到pod中。pod生命周期结束后,pv还是继续存在的。
PV支持的类型:
- GCEPersistentDisk
- AWSElasticBlockStore
- AzureFile
- AzureDisk
- FC (Fibre Channel)
- Flocker
- NFS
- iSCSI
- RBD (Ceph Block Device)
- CephFS
- Cinder (OpenStack block storage)
- Glusterfs
- VsphereVolume
- Quobyte Volumes
- HostPath (single node testing only – local storage is not supported in any way and WILL NOT WORK in a multi-node cluster)
- VMware Photon
看着很多,但大部分都是云存储(公有云或私有云),我现在能用的其实就是NFS和HostPath,而HostPath只是单node测试用的,多节点上由于Pod重新调度后会漂移到其他node,是有问题的。
下面我会以NFS为例,简单介绍下PV/PVC的用法。当然了,NFS本身也不是可靠的,但是具备了PV/PVC的基础要求。
安装NFS
NFS server所在的机器是centos 7.2,具体的安装步骤参考这篇文章就好了,配置很简单。如果你在mount的时候,出现了“mount.nfs: access denied by server while mounting”,检查下/etc/exports的配置,这里填的IP地址是client的地址。我设置了网段,如下。
# cat /etc/exports
/home/nfs 192.168.128.*(rw,sync,no_root_squash,no_subtree_check)
创建一个5GB的PV
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv0003
# annotations:
# volume.beta.kubernetes.io/storage-class: "slow"
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
nfs:
path: /tmp
server: 192.168.182.1
保存成文件pv.yml,kubectl create -f pv.yml
即可。你将看到一个Available状态的PV:
kubectl get pv
NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM REASON AGE
pv0003 5Gi RWO Recycle Available 3s
创建一个带PVC的nginx RC
---
kind: ReplicationController
apiVersion: v1
metadata:
name: nginx-controller
spec:
replicas: 1
selector:
component: nginx
template:
metadata:
labels:
component: nginx
spec:
containers:
- name: nginx
image: nginx:1.11
ports:
- containerPort: 80
volumeMounts:
- name: volume-root
mountPath: /usr/share/nginx/html
volumes:
- name: volume-root
persistentVolumeClaim:
claimName: nfs-claim
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: nfs-claim
# annotations:
# volume.beta.kubernetes.io/storage-class: "slow"
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
还是一样保存成文件用来kubectl create。之后你将看到pv/pvc的状态都转为Bound,对应关系也是一目了然。如果状态一直是Pending,那么可以kubectl describe pvc nfs-claim和kubectl describe pod nginx-controller-xxxx来看具体是什么原因,一般是PVC的请求条件不满足。
# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESSMODES AGE
nfs-claim Bound pv0001 5Gi RWO 1h
[root@titan1 StatefulSets]#
# kubectl get pv
NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM REASON AGE
pv0001 5Gi RWO Recycle Bound default/nfs-claim 1h
验证
- 通过kubectl exec -it nginx-controller-xxxx bash进入到容器的文件系统,到/usr/share/nginx/html去创建一个文件,然后在nfs server的机器的/home/nfs目录里看有没有对应的文件,可以验证PV/PVC的功能好使。
- kubectl delete pod nginx-controller-xxxx,之后rc会重新拉起一个新的pod,再kubectl exec进到这个容器的文件系统里,查看/usr/share/nginx/html有没有刚刚打进去的文件。
Subscribe via RSS