NFS
NFS 是 Network File System 的缩写,即网络文件系统。功能是让客户端通过网络访问不同主机上磁盘里的数据,主要用在类Unix系统上实现文件共享的一种方法。 本例演示 CentOS 7 下安装和配置 NFS 的基本步骤。
记得保证所有pod可部署机器都要安装NFS服务端或者NFS客户端,否则出现类似错误:
wrong fs type, bad option, bad superblock on 192.168.1.5:/home/shared, missing codepage or helper program, or other error
NFS服务的优缺点
优点
节省本地存储空间将常用的数据存放在一台服务器可以通过网络访问
简单容易上手
方便部署非常快速,维护十分简单
缺点
局限性容易发生单点故障,及server机宕机了所有客户端都不能访问
在高并发下NFS效率/性能有限
客户端没用用户认证机制,且数据是通过明文传送,安全性一般(一般建议在局域网内使用)
NFS的数据是明文的,对数据完整性不做验证
多台机器挂载NFS服务器时,连接管理维护麻烦
环境说明
CentOS 7(Minimal Install)
1 | $ cat /etc/redhat-release |
本例演示环境如下
| Name | IP Addr | Descprition |
|---|---|---|
| Server | 192.169.0.110 | 服务端 IP |
| Client | 192.168.0.101 | 客户端 IP |
根据官网说明 Chapter 8. Network File System (NFS) - Red Hat Customer Portal,CentOS 7.4 以后,支持 NFS v4.2 不需要 rpcbind 了,但是如果客户端只支持 NFC v3 则需要 rpcbind 这个服务。
服务端
服务端安装
使用 yum 安装 NFS 安装包。
1 | $ sudo yum install nfs-utils -y |
注意
只安装 nfs-utils 即可,rpcbind 属于它的依赖,也会安装上。
服务端配置
设置 NFS 服务开机启动
1 | $ sudo systemctl enable rpcbind |
启动 NFS 服务
1 | $ sudo systemctl start rpcbind |
防火墙需要打开 rpc-bind 和 nfs 的服务
1 | $ sudo firewall-cmd --zone=public --permanent --add-service={rpc-bind,mountd,nfs} |
配置共享目录
服务启动之后,我们在服务端配置一个共享目录
1 | $ sudo mkdir /data |
根据这个目录,相应配置导出目录
1 | $ sudo vi /etc/exports |
添加如下配置
1 | /data/ 192.168.0.0/24(rw,sync,no_root_squash,no_all_squash) |
/data: 共享目录位置。192.168.0.0/24: 客户端 IP 范围,*代表所有,即没有限制。rw: 权限设置,可读可写。sync: 同步共享目录。no_root_squash: 可以使用 root 授权。no_all_squash: 可以使用普通用户授权。
:wq 保存设置之后,重启 NFS 服务。
1 | $ sudo systemctl restart nfs |
可以检查一下本地的共享目录
1 | $ showmount -e localhost |
这样,服务端就配置好了,接下来配置客户端,连接服务端,使用共享目录。
Linux 客户端
客户端安装
与服务端类似
1 | $ sudo yum install nfs-utils -y |
客户端配置
设置 rpcbind 服务的开机启动
1 | $ sudo systemctl enable rpcbind |
启动 NFS 服务
1 | $ sudo systemctl start rpcbind |
注意
客户端不需要打开防火墙,因为客户端时发出请求方,网络能连接到服务端即可。
客户端也不需要开启 NFS 服务,因为不共享目录。
客户端连接 NFS
先查服务端的共享目录
1 | $ showmount -e 192.168.0.110 |
在客户端创建目录
1 | $ sudo mkdir /data |
挂载
1 | $ sudo mount -t nfs 192.168.0.101:/data /data |
挂载之后,可以使用 mount 命令查看一下
1 | $ mount |
这说明已经挂载成功了。
测试 NFS
测试一下,在客户端向共享目录创建一个文件
1 | $ cd /data |
之后取 NFS 服务端 192.168.0.101 查看一下
1 | $ cd /data |
可以看到,共享目录已经写入了。
客户端自动挂载
自动挂载很常用,客户端设置一下即可。
1 | $ sudo vi /etc/fstab |
在结尾添加类似如下配置
1 | # |
由于修改了 /etc/fstab,需要重新加载 systemctl。
1 | $ sudo systemctl daemon-reload |
之后查看一下
1 | $ mount |
此时已经启动好了。如果实在不放心,可以重启一下客户端的操作系统,之后再查看一下。
卸载共享目录
共享目录使用结束之后,卸载共享目录,运行以下命令:
1 | 如果卸载失败,使用 -f 选项强制卸载。 |
PV和PVC使用NFS静态存储
使用volumes显式的配置持久卷方式, 至少存在两个问题:
Pod声明与底层存储耦合在一起,每次声明volume都需要配置存储类型以及该存储插件的一堆配置,如果是第三方存储,配置会非常复杂。
开发人员的需求可能只是需要一个20GB的卷,这种方式却不得不强制要求开发人员了解底层存储类型和配置。使用第三方的pv, 声明Pod都需要配置地址以及secret,特别麻烦。
于是引入了PV(Persistent Volume),PV其实就是把Volume的配置声明部分从Pod中分离出来:
- PV(Persistent Volume):持久化存储卷,和node类似,是一种集群资源,由管理员定义,对接不同的存储
- PVC(Persistent Volume Claims): 持久化存储声明,和pod类似,作为PV的使用者
利用静态的PV和PVC来测试一下NFS系统能否正常工作
pv_pvc.yaml
1 | apiVersion: v1 |
关于hostpath类型type的值 :
DirectoryOrCreate 目录存在就使用,不存在就先创建后使用
Directory 目录必须存在
FileOrCreate 文件存在就使用,不存在就先创建后使用
File 文件必须存在
Socket unix套接字必须存在
CharDevice 字符设备必须存在
BlockDevice 块设备必须存在关于访问模式(accessModes)的值 :
- ReadWriteOnce(RWO):如果您需要写入该卷,但您不要求多个 Pod 应该能够写入该卷,请使用
ReadWriteOnce.- ReadOnlyMany(ROX):如果您只需要从卷中读取,并且您可能有多个 Pod 需要从卷中读取,您更喜欢将这些 Pod 灵活地调度到不同节点,并且
ReadOnlyMany是给定 K8s 集群的卷插件的一个选项,使用ReadOnlyMany。- ReadWriteMany(RWX):如果您需要写入卷,并且您可能有多个 Pod 需要写入卷,您更喜欢将这些 Pod 灵活地调度到不同节点,并且
ReadWriteMany是给定 K8s 集群的卷插件的一个选项,使用ReadWriteMany.关于回收策略(persistentVolumeReclaimPolicy)的值
Retain (保留) 保留数据,需要管理员手工清理数据
Recycle(回收) 清除 PV 中的数据,效果相当于执行 rm -rf /thevolume/*
Delete (删除) 与 PV 相连的后端存储完成 volume 的删除操作,当然这常见于云服务商的存储服务
需要注意的是,底层不同的存储类型可能支持的回收策略不同
创建后,查看是否能够自动绑定(Bound状态)(kubectl get pv, kubect get pvc)
利用NFS动态提供Kubernetes后端存储卷
本文翻译自nfs-client-provisioner的说明文档,本文将介绍使用nfs-client-provisioner这个应用,利用NFS Server给Kubernetes作为持久存储的后端,并且动态提供PV。前提条件是有已经安装好的NFS服务器,并且NFS服务器与Kubernetes的Slave节点都能网络连通。 所有下文用到的文件来自于git clone https://github.com/kubernetes-incubator/external-storage.git的nfs-client目录。
nfs-client-provisioner
nfs-client-provisioner 是一个Kubernetes的简易NFS的外部provisioner,本身不提供NFS,需要现有的NFS服务器提供存储
- PV以
${namespace}-${pvcName}-${pvName}的命名格式提供(在NFS服务器上) - PV回收的时候以
archieved-${namespace}-${pvcName}-${pvName}的命名格式(在NFS服务器上)
安装部署
- 修改deployment文件并部署
deploy/deployment.yaml
需要修改的地方只有NFS服务器所在的IP地址(10.10.10.60),以及NFS服务器共享的路径(/ifs/kubernetes),两处都需要修改为你实际的NFS服务器和共享目录
1 | kind: Deployment |
- 修改StorageClass文件并部署
deploy/class.yaml
此处可以不修改,或者修改provisioner的名字,需要与上面的deployment的PROVISIONER_NAME名字一致。
1 | apiVersion: storage.k8s.io/v1 |
授权
如果您的集群启用了RBAC,或者您正在运行OpenShift,则必须授权provisioner。 如果你在非默认的“default”名称空间/项目之外部署,可以编辑deploy/auth/clusterrolebinding.yaml或编辑`oadm policy“指令。
如果启用了RBAC
需要执行如下的命令来授权。
1 | $ kubectl create -f deploy/auth/serviceaccount.yaml |
测试
测试创建PVC
kubectl create -f deploy/test-claim.yaml
测试创建POD
kubectl create -f deploy/test-pod.yaml
在NFS服务器上的共享目录下的卷子目录中检查创建的NFS PV卷下是否有"SUCCESS" 文件。
删除测试POD
kubectl delete -f deploy/test-pod.yaml
删除测试PVC
kubectl delete -f deploy/test-claim.yaml
在NFS服务器上的共享目录下查看NFS的PV卷回收以后是否名字以archived开头。
我的示例
NFS服务器配置
1
# cat /etc/exports
1
/media/docker *(no_root_squash,rw,sync,no_subtree_check)
nfs-deployment.yaml示例
NFS服务器的地址是ubuntu-master,共享出来的路径是/media/docker,其他不需要修改。
1 | # cat nfs-deployment.yaml |
- StorageClass示例
可以修改Class的名字,我的改成了default。
1 | # cat class.yaml |
- 查看StorageClass
1 | # kubectl get sc |
- 设置这个default名字的SC为Kubernetes的默认存储后端
1 | # kubectl patch storageclass default -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}' |
- 测试创建PVC
查看pvc文件
1 | # cat test-claim.yaml |
创建PVC
1 | # kubectl apply -f test-claim.yaml |
- 启动测试POD
POD文件如下,作用就是在test-claim的PV里touch一个SUCCESS文件。
1 | # cat test-pod.yaml |
启动POD,一会儿POD就是completed状态,说明执行完毕。
1 | # kubectl apply -f test-pod.yaml |
我们去NFS共享目录查看有没有SUCCESS文件。
1 | # cd default-test-claim-pvc-fe3cb938-3f15-11e8-b61d-08002795cb26 |
说明部署正常,并且可以动态分配NFS的共享卷。
