警告
本文最后更新于 2021-04-04,文中内容可能已过时。
环境
预备知识
如果你不知道NFS是做什么的,那么请参考下面链接(包括但不限于)进行学习:
- NFS
- nfs 是基于网络共享存储,所以在大数据量场景下不适用,在环境搭建测试学习 k8s 阶段反而很合适,当然,小业务量场景下也非常合适使用。
- NFS 允许系统将其目录和文件共享给网络上的其他系统。通过 NFS,用户和应用程序可以访问远程系统上的文件,就象它们是本地文件一样。
##使用前要注意 k8s 版本
在v1.20.0中禁用了selfLink,在 v1.21 中将会彻底的移除,In k8s 1.20 they have removed selfLink as per release notes.
报错:selfLink was empty
1
2
3
|
[root@node01 deploy]# kubectl logs -f nfs-client-provisioner-cf84d684-vtns2
.....
E0324 15:05:21.127112 1 controller.go:1004] provision "default/test-claim" class "managed-nfs-storage": unexpected error getting claim reference: selfLink was empty, can't make reference
|
参考:
解决办法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
如果是 kubeadm 基于 yaml 安装 kube-apiserver方式安装:
Current workaround is to edit /etc/kubernetes/manifests/kube-apiserver.yaml
Under here:
spec:
containers:
- command:
- kube-apiserver
Add this line:
- --feature-gates=RemoveSelfLink=false
The do this:
kubectl apply -f /etc/kubernetes/manifests/kube-apiserver.yaml
kubectl apply -f /etc/kubernetes/manifests/kube-apiserver.yaml
如果是 二进制安装的话,add --feature-gates=RemoveSelfLink=false to /opt/kubernetes/cfg/kube-apiserver.conf,然后 restart 一下,
(I had to do it twice to get it to work)
|
创建 NFS 服务器
安装nfs-utils
- 在集群每一个节点安装
nfs-utils
,master 和 node 节点等。
1
|
yum install -y nfs-utils
|
配置nfs-server
1
|
mkdir -p /ifs/kubernetes/
|
- 编辑
/etc/exports
文件添加需要共享目录,每个目录的设置独占一行,编写格式如下:
1
|
NFS共享目录路径客户机IP段(参数1,参数2,...,参数n)
|
1
|
/ifs/kubernetes 192.168.110.0/24(rw,no_root_squash)
|
参数说明:
ro只读访问
rw读写访问
sync所有数据在请求时写入共享
asyncnfs在写入数据前可以响应请求
securenfs通过1024以下的安全TCP/IP端口发送
insecurenfs通过1024以上的端口发送
wdelay如果多个用户要写入nfs目录,则归组写入(默认)
no_wdelay如果多个用户要写入nfs目录,则立即写入,当使用async时,无需此设置hide在nfs共享目录中不共享其子目录
no_hide共享nfs目录的子目录
subtree_check如果共享/usr/bin之类的子目录时,强制nfs检查父目录的权限(默认)
no_subtree_check不检查父目录权限
all_squash共享文件的UID和GID映射匿名用户anonymous,适合公用目录
no_all_squash保留共享文件的UID和GID(默认)
root_squashroot用户的所有请求映射成如anonymous用户一样的权限(默认)
no_root_squashroot用户具有根目录的完全管理访问权限
anonuid=xxx指定nfs服务器/etc/passwd文件中匿名用户的UID
anongid=xxx指定nfs服务器/etc/passwd文件中匿名用户的GID
- 注1:尽量指定IP段最小化授权可以访问NFS 挂载的资源的客户端
- 注2:经测试参数insecure必须要加,否则客户端挂载出错mount.nfs: access denied by server while mounting
启动NFS服务
- 配置完成后,您可以在终端提示符后运行以下命令来启动 NFS 服务器:
1
2
|
systemctl start nfs && systemctl start rpcbind
systemctl enable nfs && systemctl enable rpcbind
|
检查NFS服务提供是否正常
1
2
3
|
[root@node05 ~]# showmount -e
Export list for node05:
/ifs/kubernetes 192.168.110.0/24
|
在客户端验证
1
2
3
4
5
|
[root@k8s-node1 ~]# yum -y install nfs-utils
[root@k8s-node1 ~]# mount -t nfs 192.168.110.239:/ifs/kubernetes /mnt
[root@k8s-node1 ~]# df -h|grep mnt
192.168.110.239:/ifs/kubernetes 37G 4.2G 33G 12% /mnt
[root@k8s-node1 ~]# touch /mnt/a.txt
|
yml 方式:安装 nfs-client-provisioner
###在集群每一个节点安装nfs-utils
1
|
yum install -y nfs-utils
|
在任意一个master节点执行下面,安装nfs-client-provisioner
1
2
3
|
yum -y install git
git clone https://github.com/kubernetes-incubator/external-storage
cd external-storage/nfs-client/deploy/
|
- commit 版本:
201f40d78a9d3fd57d8a441cfc326988d88f35ec
###安装:
需要修改的地方:
-
rbac.yaml :默认使用 default 的 namespace,如果有需要要自行更改
-
class.yaml :场景 storageclass 存储卷
-
deployment.yaml :这个文件是创建 nfs client,供其他 pod 调用客户端,这里除了使用 default 的 namespace 之外,还要修改 nfs 的配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
# cat deployment.yaml
......省略
containers:
- name: nfs-client-provisioner
image: quay.io/external_storage/nfs-client-provisioner:latest #网络不好要换成国内的镜像地址
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: fuseim.pri/ifs
- name: NFS_SERVER
value: 192.168.110.239 ### 这里要换成 nfs 主机的 地址
- name: NFS_PATH
value: /ifs/kubernetes ### 这里要换成 nfs 的存储路径
volumes:
- name: nfs-client-root
nfs:
server: 192.168.110.239 ### 这里要换成 nfs 主机的 地址
path: /ifs/kubernetes ### 这里要换成 nfs 的存储路径
|
部署:
1
2
3
|
kubectl apply -f rbac.yaml
kubectl apply -f class.yaml
kubectl apply -f deployment.yaml
|
安装结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
[root@node01 deploy]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nfs-client-provisioner-cf84d684-cxpmd 1/1 Running 0 6m37s
[root@node01 deploy]# kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
managed-nfs-storage fuseim.pri/ifs Delete Immediate false 6m40s
[root@node01 deploy]# kubectl get serviceaccounts
NAME SECRETS AGE
default 1 3h48m
nfs-client-provisioner 1 7m25s
[root@node01 deploy]# kubectl logs nfs-client-provisioner-cf84d684-cxpmd
I0404 05:53:56.745867 1 leaderelection.go:185] attempting to acquire leader lease default/fuseim.pri-ifs...
E0404 05:53:56.759885 1 event.go:259] Could not construct reference to: '&v1.Endpoints{TypeMeta:v1.TypeMeta{Kind:"", APIVersion:""}, ObjectMeta:v1.ObjectMeta{Name:"fuseim.pri-ifs", GenerateName:"", Namespace:"default", SelfLink:"", UID:"522dc6e9-bb00-49bb-8d11-71a2f85be921", ResourceVersion:"19718", Generation:0, CreationTimestamp:v1.Time{Time:time.Time{wall:0x0, ext:63753112436, loc:(*time.Location)(0x1956800)}}, DeletionTimestamp:(*v1.Time)(nil), DeletionGracePeriodSeconds:(*int64)(nil), Labels:map[string]string(nil), Annotations:map[string]string{"control-plane.alpha.kubernetes.io/leader":"{\"holderIdentity\":\"nfs-client-provisioner-cf84d684-cxpmd_24f93740-950a-11eb-921c-c69636fbe444\",\"leaseDurationSeconds\":15,\"acquireTime\":\"2021-04-04T05:53:56Z\",\"renewTime\":\"2021-04-04T05:53:56Z\",\"leaderTransitions\":0}"}, OwnerReferences:[]v1.OwnerReference(nil), Initializers:(*v1.Initializers)(nil), Finalizers:[]string(nil), ClusterName:""}, Subsets:[]v1.EndpointSubset(nil)}' due to: 'selfLink was empty, can't make reference'. Will not report event: 'Normal' 'LeaderElection' 'nfs-client-provisioner-cf84d684-cxpmd_24f93740-950a-11eb-921c-c69636fbe444 became leader'
I0404 05:53:56.759957 1 leaderelection.go:194] successfully acquired lease default/fuseim.pri-ifs
I0404 05:53:56.759997 1 controller.go:631] Starting provisioner controller fuseim.pri/ifs_nfs-client-provisioner-cf84d684-cxpmd_24f93740-950a-11eb-921c-c69636fbe444!
I0404 05:53:56.860178 1 controller.go:680] Started provisioner controller fuseim.pri/ifs_nfs-client-provisioner-cf84d684-cxpmd_24f93740-950a-11eb-921c-c69636fbe444!
|
验证安装
- 该 git 提供了两个测试例子:test-pod.yaml 和 test-claim.yaml ,创建 pvc 和 pod 去验证 nfs
1
2
|
kubectl apply -f test-pod.yaml
kubectl apply -f test-claim.yaml
|
1
2
3
4
5
6
7
|
[root@node01 deploy]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
test-claim Bound pvc-35ef9c39-fa80-4b0e-9a3c-fdb755beddf9 1Mi RWX managed-nfs-storage 10s
[root@node01 deploy]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nfs-client-provisioner-cf84d684-brlfk 1/1 Running 0 71s
test-pod 0/1 Completed 0 23s
|
查看日志,正常创建test-claim
1
2
3
|
[root@node01 deploy]# kubectl logs -f nfs-client-provisioner-cf84d684-brlfk
......
I0404 06:15:53.548454 1 event.go:221] Event(v1.ObjectReference{Kind:"PersistentVolumeClaim", Namespace:"default", Name:"test-claim", UID:"35ef9c39-fa80-4b0e-9a3c-fdb755beddf9", APIVersion:"v1", ResourceVersion:"22423", FieldPath:""}): type: 'Normal' reason: 'ProvisioningSucceeded' Successfully provisioned volume pvc-35ef9c39-fa80-4b0e-9a3c-fdb755beddf9
|
查看 nfs 存储,也成功创建
1
2
3
4
5
|
[root@node05 kubernetes]# ll
total 0
drwxrwxrwx 2 root root 21 Apr 4 14:15 default-test-claim-pvc-35ef9c39-fa80-4b0e-9a3c-fdb755beddf9
[root@node05 kubernetes]# pwd
/ifs/kubernetes
|
pod状态为Completed
则为正常,若长时间为ContainerCreating
状态则为不正常,请确认安装操作步骤是否正确。
1
|
kubelete delete -f test-claim.yaml && kubelete delete -f test-pod.yaml
|
helm 方式:安装 nfs-client
注意事项:与上面 yml 注意一样
- nfs-client-provisioner部署到刚刚创建的nfs命名空间下
- storageClass.name #指定storageClassName名称,用于 PVC 自动绑定专属动态 PV 上
- 需要指定NFS服务器的IP 地址(192.168.110.239),以及共享名称路径(/ifs/kubernetes)
创建 nfs 动态 pv 命名空间
###配置 nfs-client 的启动参数
产看配置:helm show values helm-stable/nfs-client-provisioner
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
cat > /data/helm/nfs-client/nfs-client.yaml << EOF
# NFS 设置
nfs:
server: 192.168.110.239
path: /ifs/kubernetes
storageClass:
# 此配置用于绑定 PVC 和 PV
name: nfs-client-manager
# 资源回收策略
#主要用于绑定的PVC删除后,资源释放后如何处理该PVC在存储设备上写入的数据。
#Retain:保留,删除PVC后,PV保留数据;
#Recycle:回收空间,删除PVC后,简单的清除文件;(NFS和HostPath存储支持)
#Delete:删除,删除PVC后,与PV相连接的后端存储会删除数据;(AWS EBS、Azure Disk、Cinder volumes、GCE PD支持)
reclaimPolicy: Retain
# 使用镜像
image:
repository: azure/nfs-client-provisioner
# 副本数量
#replicaCount: 1
EOF
|
###部署 nfs-client-provisioner
helm 添加 charts 源
1
2
3
4
|
helm repo add helm-stable https://charts.helm.sh/stable
helm repo add azure http://mirror.azure.cn/kubernetes/charts/
helm repo add incubator https://charts.helm.sh/incubator
helm repo update
|
指定 chart 版本
1
|
helm install nfs-cleint-storage -n nfs --values nfs-client.yaml helm-stable/nfs-client-provisioner --version 1.2.8
|
不指定默认版本
1
|
helm install nfs-cleint-storage1 -n nfs --values nfs-client.yaml helm-stable/nfs-client-provisioner
|
查看版本
1
|
helm search repo nfs-client-provisioner
|
安装后校验
1
2
3
4
|
#查看 nfs namespace 下的 app
helm list -n nfs
#查看所有 namespace 的 app
helm list -A
|
###不走配置文件,直接命令启动方式为:
1
2
3
4
5
|
helm install nfs-storage helm-stable/nfs-client-provisioner \
--set nfs.server=192.168.110.239 \
--set nfs.path=/ifs/kubernetes \
--set storageClass.name=nfs-storage \
--set storageClass.defaultClass=true
|