前情提要
- Kubernetes的持久化存储体系里面,提到最多的是对接外部ceph服务或者NFS服务。
- 有时候,Kubernetes集群所在的环境不一定提供对应的外部存储服务,而且为了性能的需求(低延迟、高IOPS等),外部基于网络的存储无法很好的满足需求。
- 除此之外想把数据存放到宿主机本地硬盘的做法就只有hostPath或者emptyDir,这种做法还是不够科学。
- 在Kubernetes社区里面,对本地持久化存储的呼声非常高,因此在v1.10版本引入了
Local Persistent Volume
即本地PV,然后v1.14版本正式GA。 - 本地PV并不适用于所有的应用,因为本地PV是直接跟节点绑定在一起的,如果Pod需要使用本地PV,在Pod调度过程中,会考虑本地PV的分布情况,然后选中有本地PV的节点作为调度目标节点。因此如果本地PV所在节点宕机,则可能会出现数据丢失的情况,需要应用自己能处理节点掉线数据无法访问的情况。
说明
- 仅记录操作过程和部署过程
- 操作系统使用的
CentOS-7.6.1810 x86_64
- 虚拟机配置
4CPU 8G内存 30G系统盘 20G数据盘A 5G数据盘B
- Kubernetes集群版本
v1.14.4
- 这里演示两种方式管理本地PV
- 手动管理本地PV
- 使用社区提供的
local-volume-provisioner
来简化本地PV的管理
准备步骤
参考社区文档
查看硬盘
- 20G本地硬盘
/dev/sdb
- 5G本地硬盘
/dev/sdc
1 | NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT |
创建目录
作为provisioner发现本地PV的目录
1 | mkdir -p /mnt/disks |
格式化硬盘
注意,这里是一个本地PV对应一个硬盘
1 | mkfs.ext4 /dev/sdb |
获取硬盘UUID
1 | SDB_UUID=$(blkid -s UUID -o value /dev/sdb) |
创建挂载目录
这里使用硬盘UUID作为挂载目录
1 | mkdir -p /mnt/disks/$SDB_UUID |
挂载硬盘
1 | mount -t ext4 /dev/sdb /mnt/disks/$SDB_UUID |
输出示例
1 | NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT |
写入fstab
1 | echo "UUID=${SDB_UUID} /mnt/disks/${SDB_UUID} ext4 defaults 0 2" | tee -a /etc/fstab |
输出示例
1 |
|
给节点打标签
1 | kubectl label node k8s-node1 local-pv=present |
检查一下节点标签
1 | kubectl get node -l local-pv=present |
输出示例
1 | NAME STATUS ROLES AGE VERSION |
手动管理本地PV
创建PV
1 | apiVersion: v1 |
创建StorageClass
1 | apiVersion: storage.k8s.io/v1 |
使用Provisioner管理本地PV
安装Helm
二进制安装
1 | wget -O - https://get.helm.sh/helm-v2.14.1-linux-amd64.tar.gz | tar xz linux-amd64/helm |
创建RBAC
1 | cat << EOF | kubectl apply -f - |
安装Helm服务端
1 | helm init --tiller-image gcr.azk8s.cn/google_containers/tiller:v2.14.1 \ |
检查部署结果
查看Pod状态
1 | kubectl -n kube-system get pod -l app=helm,name=tiller |
输出示例
1 | NAME READY STATUS RESTARTS AGE |
查看Helm版本信息
1 | helm version |
输出示例
1 | Client: &version.Version{SemVer:"v2.14.1", GitCommit:"d325d2a9c179b33af1a024cdb5a4472b6288016a", GitTreeState:"clean"} |
部署local-volume-provisioner
下载项目代码
1 | git clone --depth=1 https://github.com/kubernetes-sigs/sig-storage-local-static-provisioner.git |
修改配置
1 | vim sig-storage-local-static-provisioner/helm/provisioner/value.yaml |
修改如下
1 | # |
生成YAML文件
1 | helm template sig-storage-local-static-provisioner/helm/provisioner \ |
部署YAML文件
1 | kubectl apply -f local-volume-provisioner.generated.yaml |
查看provisioner
1 | kubectl -n kube-system get pod -l app=local-volume-provisioner |
输出示例
1 | NAME READY STATUS RESTARTS AGE |
验证本地PV
查看PersistentVolume
1 | kubectl get pv |
输出示例
1 | NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE |
查看StorageClass
1 | kubectl get sc |
输出示例
1 | NAME PROVISIONER AGE |
部署StatefulSet
1 | vim localpv-sts.yaml |
内容如下
1 | apiVersion: apps/v1 |
查看PV
1 | kubectl get pv |
输出示例
1 | NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE |
查看PVC
1 | kubectl get pvc |
输出示例
1 | local-vol-local-test-0 Bound local-pv-6e9321fd 4911Mi RWO local-storage 2m27s |
清理现场
删除StatefulSet
1 | kubectl delete -f localpv-sts.yaml |
删除pvc
1 | kubectl delete pvc local-vol-local-test-0 |
删除pv
1 | kubectl delete pv local-pv-6e9321fd |
清理本地目录
1 | ssh root@k8s-node1 "rm -rf /mnt/disks/9e0ead5f-ca8e-4018-98ad-960979d9cb26/*" |