K8S中基于NFS-Subdir-External-Provisioner存储组件实现的StorageClass
一般 StorageClass 都有一个制备器(Provisioner),用来决定使用哪个卷插件制备 PV。NFS-Subdir-External-Provisioner是对 nfs-client-provisioner 的扩展,如今nfs-client-provisioner 已经不提供更新,且 nfs-client-provisioner 的 Github 仓库已经迁移到 NFS-Subdir
K8S持久化存储之基于NFS-Subdir-External-Provisioner存储组件创建的StorageClass
前言:一般 StorageClass 都有一个制备器(Provisioner),用来决定使用哪个卷插件制备 PV。NFS-Subdir-External-Provisioner是对 nfs-client-provisioner 的扩展,如今nfs-client-provisioner 已经不提供更新,且 nfs-client-provisioner 的 Github 仓库已经迁移到 NFS-Subdir-External-Provisioner 的仓库。本文将介绍国内环境如何合理的以NFS-Subdir-External-Provisioner组件为基础创建StorageClass。
本文会涉及几个平台使用,也会分享我安装该组件时遇到的各个坑(带星号*部分)。最后成功实现由 StorageClass 根据 PVC 的需求动态创建 PV。
一、解决国内镜像问题
NFS存储类k8s.gcr.io/sig-storage/nfs-subdir-external-provisioner在国内的网络环境下无法使用docker pull将镜像拉取下来,而且在主流的国内镜像站里也找不到这些镜像仓库,这时候我们就需要想其他的办法来解决了,下面介绍使用阿里云构建镜像的方法配合GitHub拉取组件镜像的方法解决该问题。
1.1.1、在自己的GitHub创建一个仓库:
1.1.2、创建一个路径为k8s.gcr.io/sig-storage/nfs-subdir-external-provisioner/v4.0.2/Dockerfile文件,文件内容:
FROM k8s.gcr.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2
拉取该Provisioner组件镜像的命令。
1.2.1、登录阿里云,进入容器镜像服务控制台,容器列表处创建个人实例,个人实例下创建命名空间:
1.2.2、创建好命名空间后,就可以用该命名空间创建镜像仓库,代码源则选择绑定的GitHub上刚创建的仓库,并且勾选海外机器构建。
1.2.3、进入该镜像仓库,点击构建。添加规则使我们拉取私人镜像时可以利用GitHub的代码拉取到nfs-subdir-external-provisioner组件的源镜像。此处为了标准,上下文目录和版本号需要和GitHub上的一致,可直接复制刚GitHub创建的代码分支路径。
创建规则完成后,需要对规则构建,如果步骤正确时构建日志处会出现构建成功。
1.2.4、尝试拉取镜像。在该镜像仓库的基本信息,可直接复制公网地址,到我们国内正常联网的机器上尝试拉取镜像
按照阿里云的操作指南使用docker login命令登录后登录使用docker pull命令尝试拉取私人镜像
docker login --username=xxx registry.cn-hangzhou.aliyuncs.com
docker pull registry.cn-hangzhou.aliyuncs.com/niuma_1/nfs-subdir-external-provisioner:v4.0.2
发现拉取成功,说明使用GitHub+阿里云镜像构建的方法可成功在国内环境拉取国外源的镜像。
二、部署NFS-Subdir-External-Provisioner组件
2.1.1、部署该组件依赖可用的NFS服务,*本文不赘述安装NFS服务的步骤,
下文根据自己的NFS服务信息修改NFS Provisioner deploy的yaml文件内容即可,本文示例的NFS信息如下:
NFS服务器IP:192.168.113.131
服务文件路径: /data/nfs/rw
*需要K8S的所有的节点可访问该服务。
showmount -e 192.168.113.131
2.2.1、创建并配置RBAC的控制权限使其可以与NFS provisioner组件绑定赋予权限。
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner
namespace: default
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-client-provisioner-runner
rules:
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: run-nfs-client-provisioner
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner #关联的命名最好检查
namespace: default
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
namespace: default
rules:
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
namespace: default
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner #关联的命名最好检查一遍
namespace: default
roleRef:
kind: Role
name: leader-locking-nfs-client-provisioner
apiGroup: rbac.authorization.k8s.io
kubectl apply -f nfs-rbac.yaml
可顺手检查创建的SA和ClusterRole等创建的情况。
2.2.2、创建一个secret存放拉取镜像时的认证信息,自己私人仓库账号密码,可参照上文使用docker login时用的账号密码,*该secret需要被下文步骤部署 NFS-Subdir-External-Provisioner组件时引用到imagePullSecret中,否则会出现ImagePullBackOff。
kubectl create secret docker-registry myregistrykey --docker-server=registry.cn-hangzhou.aliyuncs.com --docker-username=xxxxxxx --docker-password=xxxxxxx --docker-email=xxxx@xx.com
2.2.3、部署NFS-Subdir-External-Provisioner
*注意:yaml文件中1、NFS服务IP;2、NFS文件路径,3、imagePullSecret配置
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-client-provisioner
labels:
app: nfs-client-provisioner
spec:
replicas: 1
strategy:
type: Recreate ## 设置升级策略为删除再创建(默认为滚动更新)
selector:
matchLabels:
app: nfs-client-provisioner
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner
imagePullSecrets: #此处引用的是上文创建的secret,携带了拉取镜像时的认证信息
- name: myregistrykey
containers:
- name: nfs-client-provisioner
image: registry.cn-hangzhou.aliyuncs.com/niuma_1/nfs-subdir-external-provisioner:v4.0.2 #指定的镜像地址要跟刚才创建的aliyun上的镜像仓库地址要对的上
#imagePullPolicy: Never
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME ## Provisioner的名称,创建storageclass时引用的制备器要和该名称保持一致
value: nfs-client
- name: NFS_SERVER ## NFS服务器地址,需和valumes参数中配置的保持一致
value: 192.168.113.131
- name: NFS_PATH ## NFS服务器数据存储目录,需和valumes参数中配置的保持一致
value: /data/nfs/rw
volumes:
- name: nfs-client-root
nfs:
server: 192.168.113.131 ## NFS服务器地址
path: /data/nfs/rw ## NFS服务器数据存储目录
kubectl apply -f nfs-provisioner-deploy.yaml
创建完成后查看nfs-provisioner制备器组件的deploy和pod是否正常,保证状态正常后再去尝试创建SC。
2.2.4、使用nfs-provisioner创建 NFS SotageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-storage #SC的名称,下文的PVC可根据名称直接引用
annotations:
storageclass.kubernetes.io/is-default-class: "false" ## 是否设置为默认的storageclass
provisioner: nfs-client ## 动态卷分配者名称,必须和上面创建的"provisioner"变量中设置的Name一致
parameters:
archiveOnDelete: "true" ## 设置为"false"时删除PVC不会保留数据,"true"则保留数据
mountOptions:
- hard ## 指定为硬挂载方式
- nfsvers=4 ## 指定NFS版本,这个需要根据NFS Server版本号设置
kubectl apply -f nfs-storage.yaml
到该步骤成功安装SC
三、创建PVC和Pod用于验证SC是否正常
3.1.1、创建PVC,观察是否自动创建PV。
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: nfs-sc-test-pvc
spec:
storageClassName: nfs-storage #需要与上面创建的storageclass的名称一致
accessModes:
- ReadWriteOnce #指定者可读写
resources:
requests:
storage: 2Mi #容量规格
kubectl apply -f nfs-sc-test-pvc.yaml
查看创建出来的pvc信息,观察其绑定的SC,PV的信息是否正确。
观察nfs服务器的共享文件夹发现,基于SC创建的PV都会在NFS服务器创建对应的文件夹,文件夹名可以跟PV名称对上。
3.1.2、创建一个POD绑定刚创建的PVC
apiVersion: v1
kind: Pod
metadata:
name: test-nginx-pod
spec:
containers:
- image: nginx
name: nginx-volume
volumeMounts:
- mountPath: /usr/share/nginx/html # 挂载到容器的目录
name: test-pvc-volume # 挂载哪个 volume
volumes:
- name: test-pvc-volume
persistentVolumeClaim: # 关联PVC
claimName: nfs-sc-test-pvc # 要关联到的pvc
查看Pod的描述发现已经绑定了指定的PVC
3.2.1、查看pod的服务是否正常
尝试能否请求到刚创建的pod内的nginx服务:
*发现了403报错,这个是正常现象,因为挂载的目录正好覆盖了nginx服务的主页文件。
3.2.2、查看pod内的服务和nfs交互文件内容是否正常进入pod的nginx容器内部,进入 /usr/share/nginx/html,发现果然没有文件,手工尝试创建一个index.html文件:
kubectl exec -it test-nginx-pod -- sh
cd /usr/share/nginx/html
ls -l
touch index.html
创建完之后在nfs服务器上看共享目录内对应的pv文件夹,发现该文件被创建了:
最后,我们尝试在nfs服务器配置,创建写入一些内容到上文的index.html文件中,
然后再尝试请求看能否请求到相关内容:
cd /data/nfs/rw/default-nfs-sc-test-pvc-pvc-2a2999c0-2718-4549-a287-20f863081e71
echo '------------I am The King of niuma--------------' > index.html
尝试去请求pod的nginx服务,发现可以请求到刚写入的内容了:
文章到此结束。
参考文章:
[1]陌上荼靡(2022).无法下载外网Docker镜像的解决方案.cnblogs.检索于2024-5-2,https://www.cnblogs.com/mstmdev/p/16047954.html
[2]zuozewei(2022).Kubernetes 集群部署 NFS-Subdir-External-Provisioner 存储插件.aliyun.检索于2024-5-2,https://developer.aliyun.com/article/856853
更多推荐
所有评论(0)