NFS(Network File System)是一种分布式文件系统协议,允许在网络上共享文件和目录。
在K8S中可以用于:
共享存储卷: NFS 可以用作共享存储卷的后端,允许多个 Pod 共享相同的存储。这在需要多个 Pod 之间共享数据或状态时非常有用,例如,一些应用可能需要多个副本协同工作并共享相同的数据。
持久化存储: NFS 可以用作 Kubernetes 集群中的持久化存储解决方案,确保 Pod 中的数据在 Pod 重启或迁移时得以保留。这对于需要数据持久性的应用程序(如数据库)是至关重要的。
1. NFS 服务端配置
1.1 安装 NFS 服务端
{.line-numbers}1
| sudo apt install rpcbind nfs-kernel-server -y
|
1.2 创建共享目录
{.line-numbers}1 2 3
| mkdir /srv/nfs chmod -R 777 /srv/nfs
|
1.3 配置 NFS 共享
1.3.1 编辑NFS服务主配置文件
末行加入
{.line-numbers}1 2
| /srv/nfs *(rw,sync,no_subtree_check,no_root_squash)
|
参数名称 | 参数用途 |
rw |
读写权限 |
ro |
只读权限 |
sync |
请求或写入数据时,数据同步写入到NFS Server的硬盘后才返回。优点:数据安全不会丢;缺点:性能比不启动该参数要差 |
async |
写入时数据会先写入到内存缓冲区,直到硬盘有空档才会再写入磁盘,这样可以提升写入效率!风险为若服务器宕机或不正常关机,不会缓冲未写入磁盘的数据(解决办法:服务器主板电池或UPS不间断电源) |
no_root_squash |
访问NFS Server共享目录的用户如果是root的话,它对该共享目录具有root权限。这个配置原本是为无盘客户端准备的。用户应避免使用。 |
root_squash |
如果访问NFS Server共享目录的用户时root,则它的权限将被压缩成匿名用户,同时它的UID和GID通常会变成nfsnobody账号身份。 |
all_squash |
不管访问NFS Server共享目录的用户身份如何,它的权限都将被压缩成匿名用户,同时它的UID和GID都会变成nfsnobody帐号身份。在早期多个NFS 客户端同时读写NFS Server数据时,这个参数很有用。 在生产中配置NFS 的重要技巧: l)确保所有客户端服务器对NFS共享目录具备相同的用户访问权限 a.all_squash 把所有客户端都压缩成固定的匿名用户(UID相同) b.就是anonuid,anongid 指定的UID和GID的用户。 2)所有的客户端和服务端都需要有一个相同的UID和GID的用户,即nfsnobody(UID必须相同)。 |
anonuid |
参数以anon*开头即指anonymous匿名用户,这个用户的UID设置值通常为nfsnobody的UID值,当然也可以自行设置这个UID值。但是,UID必须存在于/etc/passwd 中。在多NFS Clients时,如多台Web Server共享一个NFS目录,通过这个参数可以使得不同的NFS Clients写入的数据对所有NFS Clients保持同样的用户权限,即为配置的匿名UID对应用户权限,这个参数很有用,一般默认即可。 |
anongid |
同anonuid,区别就是把uid(用户id)换成gid(组id)。 |
1.3.2 重启服务sudo systemctl restart nfs-kernel-server
1.3.3 验证共享exportfs -v
或showmount -e localhost
2. NFS客户端挂载
2.1 安装 NFS 客户端
{.line-numbers}1
| sudo apt install nfs-common
|
2.2 创建本地挂载目录
2.3 将 NFS 服务器上的/data
目录,挂载到本地的/mnt/
目录下
{.line-numbers}1
| sudo mount -t nfs <NFS-SERVER-IP>:/srv/nfs /mnt/nfs
|
3. K8S挂载
想要 Kubernetes 支持 NFS 存储,可以选择安装 nfs-subdir-external-provisioner ,它是一个存储资源自动调配器,它可将现有的 NFS 服务器通过持久卷声明来支持 Kubernetes 持久卷的动态分配。该组件是对 Kubernetes NFS-Client Provisioner 的扩展, nfs-client-provisioner 已经不提供更新,已经迁移到 nfs-subdir-external-provisioner仓库。
3.1 helm 方式安装
{.line-numbers}1 2 3
| helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner kubectl create ns nfs-system helm install nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner -n nfs-system --set storageClass.name=nfs-sc --set nfs.server=<NFS-SERVER-IP> --set nfs.path=/srv/nfs --set storageClass.defaultClass=true
|
参数:
nfs.server
NFS 服务器的 IP 地址
nfs.path
NFS 服务器上的共享目录
storageClass.name
存储类的名称
storageClass.defaultClass
是否设置为默认存储类
image.repository:
自定义 nfs-subdir-external-provisioner 镜像拉取地址
3.2 验证
- 检查storageClass
kubectl get sc nfs-sc -o wide
3.2.1 创建PVC资源申请测试
- 编写yaml
{.line-numbers}1 2 3 4 5 6 7 8 9 10 11
| kind: PersistentVolumeClaim apiVersion: v1 metadata: name: test-nfs-pvc spec: storageClassName: nfs-sc accessModes: - ReadWriteMany resources: requests: storage: 1Gi
|
- 创建PVC
kubectl apply -f test-nfs-pvc.yaml
- 查看PVC
kubectl get pvc -n nfs-system -o wide
3.2.2 创建测试Pod
- 编写yaml
{.line-numbers}1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| kind: Pod apiVersion: v1 metadata: name: test-nfs-pod spec: containers: - name: test-nfs-pod image: busybox:latest command: - "/bin/sh" args: - "-c" - "touch /mnt/SUCCESS && sleep 3600" volumeMounts: - name: nfs-pvc mountPath: "/mnt" restartPolicy: "Never" volumes: - name: nfs-pvc persistentVolumeClaim: claimName: test-nfs-pvc
|
- 创建Pod
kubectl apply -f test-nfs-pod.yaml -n nfs-system
- 查看Pod
kubectl get pods -n nfs-system -o wide
3.2.3 清理测试资源
{.line-numbers}1 2
| kubectl delete -f test-nfs-pod.yaml -n nfs-system kubectl delete -f test-nfs-pvc.yaml -n nfs-system
|
参考文章
- ubuntu22.04安装NFS及配置
- K8S集群中部署NFS之一:配置NFS服务
- 30分钟玩转Kubernetes持久化存储之 NFS 实战入门