- ansible/files 改为与文档 XX-YY 对齐的目录结构,更新相关 playbook 路径 - 新增 scripts/verify.sh 与 ansible/playbooks/verify/*.yml,移除单体 verify-matrix.yml - 补充 docs/00-02 矩阵状态、00-05 验证框架与流程、00-04 环境与 ylc65 工作机说明 - 增加 k3s 存储准备、Longhorn、local-path 等 playbook 与辅助脚本 Made-with: Cursor
211 lines
7.2 KiB
Markdown
211 lines
7.2 KiB
Markdown
# 03-06-k3s 使用 NFS 存储
|
||
|
||
> 本文只讲 K3s 集群侧如何使用已安装好的 NFS。
|
||
|
||
## 前置条件
|
||
|
||
- 已完成 `01-05-armv7-nfs服务安装.md`
|
||
- 可从 K3s 节点访问 NFS 服务器与导出目录
|
||
|
||
## 方式对比(从简单到复杂)
|
||
|
||
| 项 | 方式 1:Pod 直接挂 NFS | 方式 2:静态 NFS(PV + PVC) | 方式 3:动态 NFS(选装 provisioner) |
|
||
|---|---|---|---|
|
||
| 复杂度 | 低 | 中 | 高 |
|
||
| 最少 YAML 段数 | 1 段(Deployment/Pod) | 2 段(PV+PVC) | 通常 1 段 PVC(PV/目录动态生成) |
|
||
| 目录创建 | 需手工提前创建 | 需手工提前创建 | 通常由 provisioner 自动创建子目录 |
|
||
| 与应用耦合 | 高(写死 server/path) | 低(应用只引用 PVC) | 低(应用只引用 PVC) |
|
||
| 适用场景 | 临时验证、概念验证(先跑通) | 稳定运行、团队协作 | 大规模/多团队、追求自动化 |
|
||
|
||
## 操作步骤
|
||
|
||
1. 按复杂度选择一种方式
|
||
2. 应用清单
|
||
3. 验证读写
|
||
|
||
> 结论:K3s 使用 NFS **不需要**先把 NFS 手工挂到每台节点主机;Pod/PVC 可直接挂远端 NFS。
|
||
|
||
### 方式 1:Pod 直接挂 NFS(最简单,快速验证)
|
||
|
||
> 说明:`nfs.path` 指向的目录(或子目录)需要在 NFS 服务端**提前创建并设置好权限**;K3s 不会自动在 NFS 服务端创建该目录。
|
||
>
|
||
> 例如在 onecloud 上预创建子目录:
|
||
>
|
||
> ```bash
|
||
> sudo mkdir -p /sdcard/app-a
|
||
> sudo chown 1000:1000 /sdcard/app-a
|
||
> sudo chmod 0770 /sdcard/app-a
|
||
> ```
|
||
|
||
```yaml
|
||
apiVersion: apps/v1 # Deployment 使用的 API 版本
|
||
kind: Deployment # 资源类型:Deployment
|
||
metadata: # 资源元信息
|
||
name: nfs-direct-demo # Deployment 名称
|
||
namespace: default # 命名空间
|
||
spec: # Deployment 规格
|
||
replicas: 1 # 副本数
|
||
selector: # Pod 选择器
|
||
matchLabels: # 标签匹配条件
|
||
app: nfs-direct-demo # 选择带 app=nfs-direct-demo 的 Pod
|
||
template: # Pod 模板
|
||
metadata: # Pod 元信息
|
||
labels: # Pod 标签
|
||
app: nfs-direct-demo # Pod 标签值
|
||
spec: # Pod 规格
|
||
containers: # 容器列表
|
||
- name: app # 容器名称
|
||
image: nginx:alpine # 容器镜像
|
||
volumeMounts: # 容器内挂载点
|
||
- name: nfs-data # 引用下方 volumes 的卷名
|
||
mountPath: /usr/share/nginx/html # 挂载到容器内目录
|
||
volumes: # Pod 卷定义
|
||
- name: nfs-data # 卷名
|
||
nfs: # 直接使用 NFS 卷
|
||
server: <NFS_SERVER_IP> # NFS 服务器地址(应用前替换)
|
||
path: <NFS_EXPORT_PATH_OR_SUBDIR> # NFS 导出目录或子目录(应用前替换)
|
||
```
|
||
|
||
### 方式 2:静态 NFS(PV + PVC,推荐)
|
||
|
||
**唯一真源**:[`ansible/files/03-06-nfs-demo/nfs-pv-pvc-demo.yaml`](../ansible/files/03-06-nfs-demo/nfs-pv-pvc-demo.yaml)。
|
||
|
||
> 为减少硬编码,示例清单已改为占位符:`<NFS_SERVER_IP>`、`<NFS_EXPORT_PATH>`。
|
||
> 应用前必须先替换(例如 `192.168.2.22`、`/sdcard`)。
|
||
|
||
> 静态 NFS 同样需要在服务端提前创建目录并设置权限;不会自动创建目录。
|
||
|
||
### 方式 3:动态 NFS(选装 provisioner)
|
||
|
||
这是选装增强,不是 K3s 内置默认能力。常见组件是 `nfs-subdir-external-provisioner`。
|
||
|
||
### 3.1 安装 provisioner(Helm)
|
||
|
||
> 前提:NFS 服务端已可用(例如 `192.168.2.22:/sdcard`),且 K3s 节点网络可达。
|
||
|
||
```bash
|
||
# 1) 添加 chart 仓库
|
||
helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
|
||
helm repo update
|
||
|
||
# 2) 安装(建议放到 kube-system)
|
||
helm upgrade --install nfs-subdir-external-provisioner \
|
||
nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
|
||
-n kube-system --create-namespace \
|
||
--set nfs.server=192.168.2.22 \
|
||
--set nfs.path=/sdcard \
|
||
--set storageClass.name=nfs-client \
|
||
--set storageClass.defaultClass=false \
|
||
--set storageClass.reclaimPolicy=Delete \
|
||
--set storageClass.archiveOnDelete=true
|
||
```
|
||
|
||
参数说明(最常改):
|
||
|
||
- `nfs.server`:NFS 服务器地址
|
||
- `nfs.path`:NFS 导出根目录(provisioner 会在其下创建子目录)
|
||
- `storageClass.name`:动态供给使用的 StorageClass 名称
|
||
- `archiveOnDelete`:删除 PVC 时是否归档目录(`true` 更稳妥,`false` 更干净)
|
||
|
||
### 3.2 验证 provisioner 与 StorageClass
|
||
|
||
```bash
|
||
kubectl -n kube-system get pod -l app.kubernetes.io/name=nfs-subdir-external-provisioner -o wide
|
||
kubectl get storageclass
|
||
```
|
||
|
||
### 3.3 用动态 PVC 验证自动建卷
|
||
|
||
创建一个最小 PVC(示例):
|
||
|
||
```yaml
|
||
apiVersion: v1
|
||
kind: PersistentVolumeClaim
|
||
metadata:
|
||
name: nfs-dynamic-pvc-demo
|
||
namespace: default
|
||
spec:
|
||
accessModes:
|
||
- ReadWriteMany
|
||
storageClassName: nfs-client
|
||
resources:
|
||
requests:
|
||
storage: 5Gi
|
||
```
|
||
|
||
应用并验证:
|
||
|
||
```bash
|
||
kubectl apply -f /tmp/nfs-dynamic-pvc-demo.yaml
|
||
kubectl get pvc nfs-dynamic-pvc-demo -n default
|
||
kubectl get pv | grep nfs-dynamic-pvc-demo
|
||
```
|
||
|
||
当 PVC `Bound` 后,通常可在 NFS 服务器的 `/sdcard` 下看到自动创建的子目录(命名规则由 provisioner 管理)。
|
||
|
||
### 3.5 本次实机验证记录(ylc61 + onecloud)
|
||
|
||
- `nfs-subdir-external-provisioner` 安装成功并 `Running`
|
||
- `StorageClass nfs-client` 创建成功
|
||
- 动态 PVC `nfs-dynamic-pvc-demo` 成功 `Bound`
|
||
- 自动创建 PV 成功,并在 NFS 服务端目录下生成子目录:
|
||
- `/sdcard/default-nfs-dynamic-pvc-demo-pvc-<uid>`
|
||
- 删除临时 PVC 后,PV 按 `Delete` 回收完成
|
||
|
||
> 备注:验证中曾出现过镜像拉取 `EOF`(偶发网络抖动),重试后官方镜像 `registry.k8s.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2` 已可正常拉取并启动。
|
||
|
||
### 3.4 何时选动态 NFS
|
||
|
||
- 目录数量多、变更频繁
|
||
- 希望减少手工维护 PV/PVC 对应关系
|
||
- 团队里希望应用只声明 PVC,平台统一管理 StorageClass
|
||
|
||
## 验证命令(若 YAML 在 manifests 目录,按实际路径选择其一复制执行)
|
||
|
||
```bash
|
||
# 仓库根直接应用
|
||
# 先替换 ansible/files/03-06-nfs-demo/nfs-pv-pvc-demo.yaml 里的占位符
|
||
# <NFS_SERVER_IP> -> 例如 192.168.2.22
|
||
# <NFS_EXPORT_PATH> -> 例如 /sdcard
|
||
kubectl apply -f ansible/files/03-06-nfs-demo/nfs-pv-pvc-demo.yaml
|
||
```
|
||
|
||
```bash
|
||
# 或默认路径(已拷贝到 manifests 时)
|
||
kubectl apply -f /var/lib/rancher/k3s/server/manifests/nfs-pv-pvc.yaml
|
||
kubectl get pv,pvc -A
|
||
kubectl describe pv nfs-pv-demo
|
||
```
|
||
|
||
```bash
|
||
# 自定义 data-dir(如 /storage)
|
||
kubectl apply -f /storage/server/manifests/nfs-pv-pvc.yaml
|
||
kubectl get pv,pvc -A
|
||
kubectl describe pv nfs-pv-demo
|
||
```
|
||
|
||
```bash
|
||
# 对方式 1(Pod 直挂)可这样验证
|
||
kubectl apply -f /tmp/nfs-direct-demo.yaml
|
||
kubectl rollout status deploy/nfs-direct-demo --timeout=180s
|
||
kubectl exec deploy/nfs-direct-demo -- sh -c 'echo nfs-direct-ok > /usr/share/nginx/html/nfs.txt && cat /usr/share/nginx/html/nfs.txt'
|
||
```
|
||
|
||
## 预期
|
||
|
||
- PV/PVC 状态为 `Bound`
|
||
- 业务 Pod 可读写挂载目录
|
||
|
||
## 失败排查
|
||
|
||
- 检查 NFS 服务与导出目录权限
|
||
- 检查节点到 NFS 服务器网络
|
||
- 检查 `path` 与 `server` 配置是否正确
|
||
- 若报 `Permission denied`,回到 `01-05` 的 `root_squash` 权限章节,确认导出目录与业务 UID/GID 对齐
|
||
|
||
## 下一步
|
||
|
||
- `03-05-k3s-local-path-pvc.md`:单副本应用用 K3s 自带 local-path 即可,无需 NFS
|
||
- `05-06-openlist挂载网盘与自动备份.md`
|
||
|