feat: 按 doc_id 重组 ansible/files 与验证框架

- 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
This commit is contained in:
2026-03-26 07:01:14 +08:00
parent a67788de56
commit 8c43761962
192 changed files with 4006 additions and 320 deletions

View File

@@ -1,4 +1,4 @@
# 03-07-k3s 使用 NFS 存储
# 03-06-k3s 使用 NFS 存储
> 本文只讲 K3s 集群侧如何使用已安装好的 NFS。
@@ -7,19 +7,167 @@
- 已完成 `01-05-armv7-nfs服务安装.md`
- 可从 K3s 节点访问 NFS 服务器与导出目录
## 方式对比(从简单到复杂)
| 项 | 方式 1Pod 直接挂 NFS | 方式 2静态 NFSPV + PVC | 方式 3动态 NFS选装 provisioner |
|---|---|---|---|
| 复杂度 | 低 | 中 | 高 |
| 最少 YAML 段数 | 1 段Deployment/Pod | 2 段PV+PVC | 通常 1 段 PVCPV/目录动态生成) |
| 目录创建 | 需手工提前创建 | 需手工提前创建 | 通常由 provisioner 自动创建子目录 |
| 与应用耦合 | 高(写死 server/path | 低(应用只引用 PVC | 低(应用只引用 PVC |
| 适用场景 | 临时验证、概念验证(先跑通) | 稳定运行、团队协作 | 大规模/多团队、追求自动化 |
## 操作步骤
1. 创建 NFS 类型 `PersistentVolume`
2. 创建 `PersistentVolumeClaim`
3. 在业务 Pod 中挂载 PVC
1. 按复杂度选择一种方式
2. 应用清单
3. 验证读写
**唯一真源**[`ansible/files/nfs-demo/nfs-pv-pvc-demo.yaml`](../ansible/files/nfs-demo/nfs-pv-pvc-demo.yaml)(按你的 NFS `server` / `path` 修改)
> 结论K3s 使用 NFS **不需要**先把 NFS 手工挂到每台节点主机Pod/PVC 可直接挂远端 NFS
### 方式 1Pod 直接挂 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静态 NFSPV + 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 安装 provisionerHelm
> 前提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
# 仓库根直接应用
kubectl apply -f ansible/files/nfs-demo/nfs-pv-pvc-demo.yaml
# 先替换 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
@@ -36,6 +184,13 @@ kubectl get pv,pvc -A
kubectl describe pv nfs-pv-demo
```
```bash
# 对方式 1Pod 直挂)可这样验证
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`
@@ -46,6 +201,7 @@ kubectl describe pv nfs-pv-demo
- 检查 NFS 服务与导出目录权限
- 检查节点到 NFS 服务器网络
- 检查 `path``server` 配置是否正确
- 若报 `Permission denied`,回到 `01-05``root_squash` 权限章节,确认导出目录与业务 UID/GID 对齐
## 下一步