chore: 清理调试脚本并收敛到 Ansible 流程

移除已废弃的调试/验证脚本与空目录,统一文档与脚本说明到 ansible-playbook 的部署方式,避免失效引用和误用路径。

Made-with: Cursor
This commit is contained in:
2026-03-23 19:18:55 +08:00
parent 8a54cac61f
commit be97836e0d
92 changed files with 3463 additions and 4855 deletions

View File

@@ -1,4 +1,4 @@
# 03-06-k3s local-path PVC 本地持久化
# 03-05-k3s local-path PVC 本地持久化
> K3s 自带的 **local-path-provisioner**:通过 PVC 自动创建本地 PersistentVolume适用于单副本应用、缓存、日志等无需 NFS 或 Longhorn。
@@ -7,42 +7,178 @@
| 方式 | 共享 | 适用场景 |
|------|------|----------|
| **local-path**(本页) | 否,单节点 | 单副本应用Traefik acme.json、单机数据库等Pod 固定调度到同一节点 |
| **NFS**`03-08` | 是,多节点读写 | 多副本共享目录、需跨节点访问 |
| **Longhorn**`03-09` | 块存储CSI | 重状态系统、快照/备份、生产推荐 |
| **NFS**`03-06-k3s-使用nfs存储.md` | 是,多节点读写 | 多副本共享目录、需跨节点访问 |
| **Longhorn**`03-07-k3s-longhorn-持久化存储.md` | 块存储CSI | 重状态系统、快照/备份、生产推荐 |
## 前置条件
- K3s 已安装local-path-provisioner 默认启用)
- 无额外组件,`kubectl get storageclass` 可见 `local-path`(通常为默认)
- 无额外组件,`kubectl get storageclass` 可见 `local-path`(通常为 default例如
```text
NAME PROVISIONER ...
local-path (default) rancher.io/local-path ...
```
## 操作步骤
### 1. 清单PVC + Deployment
**唯一真源**[`ansible/files/local-path-demo/local-path-pvc-demo.yaml`](../ansible/files/local-path-demo/local-path-pvc-demo.yaml)(含 PVC `local-pvc-demo``nginx-local-pvc-demo` Deployment`storageClassName` 可省略K3s 默认多为 `local-path`)。
**唯一真源**[`ansible/files/local-path-demo/local-path-pvc-demo.yaml`](../ansible/files/local-path-demo/local-path-pvc-demo.yaml)(含 PVC `local-pvc-demo``nginx-local-pvc-demo` Deployment清单内已写 **`storageClassName: local-path`**,与 `kubectl get storageclass` 中名称一致即可)。
### 2. 应用与验证
在**本仓库根目录**执行(或把 `-f` 换成清单的绝对路径):
```bash
kubectl apply -f ansible/files/local-path-demo/local-path-pvc-demo.yaml
# 等 Pod 调度、PVC 绑定后再操作local-path 多为 WaitForFirstConsumer前几秒 Pending 正常)
kubectl rollout status deploy/nginx-local-pvc-demo --timeout=180s
kubectl get pv,pvc
kubectl get pod -o wide
kubectl exec deploy/nginx-local-pvc-demo -- sh -c 'echo hello > /usr/share/nginx/html/test.txt'
kubectl delete pod -l app=nginx-local-pvc-demo
kubectl rollout status deploy/nginx-local-pvc-demo --timeout=180s
kubectl exec deploy/nginx-local-pvc-demo -- cat /usr/share/nginx/html/test.txt # 应仍为 hello
```
> **勿在 Pod 仍为 Pending 时 `exec`**,否则会报 `does not have a host assigned`。先 `kubectl get pod -o wide` 确认 **NODE** 有值且 **READY 1/1**。
### 3. Pending 排查PVC / Pod 长时间不 Ready
```bash
kubectl describe pvc local-pvc-demo -n default
kubectl describe pod -l app=nginx-local-pvc-demo -n default
kubectl get events -n default --sort-by=.lastTimestamp | tail -30
kubectl get pods -n kube-system | grep -i local-path
kubectl logs -n kube-system deploy/local-path-provisioner --tail=80 2>/dev/null || \
kubectl logs -n kube-system -l app=local-path-provisioner --tail=80
```
常见原因:**local-path-provisioner** 未就绪或报错、节点磁盘/权限、曾留下异常 PVC。可删除后重试
```bash
kubectl delete deploy/nginx-local-pvc-demo -n default --ignore-not-found
kubectl delete pvc local-pvc-demo -n default --ignore-not-found
# 等待 PV 回收后再 apply
kubectl apply -f ansible/files/local-path-demo/local-path-pvc-demo.yaml
kubectl rollout status deploy/nginx-local-pvc-demo --timeout=180s
```
## 注意事项
- **绑定到节点**PV 创建在 Pod 首次调度到的节点上Pod 重建后仍会调度到节点provisioner 会打 nodeAffinity
- **WaitForFirstConsumer**PVC 在 Pod 未调度前可长期 **Pending**PV 在 **Pod 首次成功调度到节点** 才创建,且会带 nodeAffinityPod 重建后仍倾向同一节点
- **单副本**`ReadWriteOnce`,同一 PVC 只能被同一节点上的一个 Pod 挂载;多副本需 NFS 或 Longhorn
- **数据路径**:默认在 K3s `--data-dir` 下的 `storage`,如 `/var/lib/rancher/k3s/storage``/storage`
- **回收策略**`Delete`,删除 PVC 时 PV 及本地目录会被清理
## Traefik acme.json 示例
## storageClass: local-path 与「本地路径」说明
若希望 Traefik 的 ACME 证书走 local-path PVC需在 HelmChartConfig 的 values 中为 Traefik 配置 volume 与 volumeMount`03-02-k3s-traefik-acme.md` 可选配置)。多数场景下,配合 `nodeSelector` 固定 Traefik 到同一节点,再用 hostPath 或 local-path 均可;无 hostPath 时 K3s 默认会为 Traefik 挂 emptyDir 或默认卷。
### PVC / StorageClass 里**不能**写宿主机目录
在清单里写 `storageClassName: local-path`(或 Traefik Helm `persistence.storageClass: local-path`)只表示:**交给 K3s 自带的 local-path-provisioner 在某一工作节点上自动创建本地目录并绑定 PV**。
- **不能**在 PVC 或 StorageClass 里指定「数据必须落在 `/mnt/mydata/xxx`」这类**宿主机绝对路径**。
- 实际在节点磁盘上的目录,由 **provisioner 的全局配置 + 内部命名规则** 生成;通常位于 K3s `--data-dir` 下的 `storage` 子树(与上文「注意事项」一致)。
### Traefik `persistence.path: /data` 是**容器内**挂载点
在 [`traefik-dashboard-acme.yaml`](../ansible/files/traefik-dashboard-acme/traefik-dashboard-acme.yaml) 中:
| 字段 | 含义 |
|------|------|
| `persistence.path: /data` | Traefik **容器内**的挂载目录Helm chart 把 PVC 挂到这里) |
| `acme.storage=/data/acme.json` | **容器内**证书文件路径,与上面挂载一致 |
| `storageClass: local-path` | 使用哪种**动态供给**方式,不等价于「宿主机路径」 |
因此:**容器里永远是 `/data/...`**;宿主机上对应哪一块目录,要看该 PVC 绑定的 **PV**
### 如何查看数据实际落在节点的哪个目录
PVC 绑定后,用 PV 反查Traefik 示例在 `kube-system`
```bash
# 1) 找到 Traefik 使用的 PVC 名称chart 创建的 claim 名因版本可能略有差异)
kubectl -n kube-system get pvc
# 2) 从 PVC 的 Volume / Bound 信息得到 PV 名,再查看 PV路径在 spec 或 describe 输出中)
kubectl -n kube-system describe pvc <你的-pvc-名>
kubectl describe pv <上一步看到的-pv-名>
kubectl get pv <pv-名> -o yaml # 在 spec 中查 path、hostPath、local、csi.volumeAttributes 等
```
不同 K3s / provisioner 版本字段名可能略有差异,以 `describe` / `yaml` 实际输出为准。
### 需要指定「整盘根目录」时:改 local-path-provisioner 配置
若希望**某一类节点**上通过 `local-path` 创建的数据统一落在指定根路径下(仍由 provisioner 在根下自动分子目录),可编辑 **`kube-system`** 中的 ConfigMap **`local-path-config`**(键名多为 `config.json`),使用 **`nodePathMap`** 等为节点配置路径。
> 修改前建议 `kubectl -n kube-system get configmap local-path-config -o yaml` 备份;改错会导致新 PVC 无法创建。
示意(**仅为结构说明,请与集群内现有 JSON 合并修改,勿直接整段覆盖**
```json
{
"nodePathMap": [
{
"node": "DEFAULT_PATH_FOR_NON_LISTED_NODES",
"paths": ["/var/lib/rancher/k3s/storage"]
},
{
"node": "你的节点主机名",
"paths": ["/data/k3s-local-path"]
}
]
}
```
保存 ConfigMap 后,通常需 **重启** `local-path-provisioner` 相关负载使配置生效(以你集群实际 Deployment/DaemonSet 名为准):
```bash
kubectl -n kube-system rollout restart deploy/local-path-provisioner 2>/dev/null || true
```
具体字段与默认值以当前 K3s 版本自带的 [rancher local-path-provisioner](https://github.com/rancher/local-path-provisioner) 文档为准。
### 与 hostPath 的区别
| 方式 | 说明 |
|------|------|
| **storageClass: local-path** | 动态 PV路径由 provisioner 管理;适合一般工作负载与 Traefik ACME。 |
| **hostPath / 手写 PV** | 在清单里直接绑定节点上某一目录需自行保证节点一致性与权限与「local-path StorageClass」不是同一条配置路径。 |
若 Traefik Helm chart 支持你也可使用其 **`persistence.hostPath`** 类选项(若版本提供),则属于 **显式 hostPath**,与仅写 `local-path` 的用法不同。
## Traefik ACME证书固定到 local-path推荐
ACME 存储路径在配置里已是 **`/data/acme.json`**(见 `03-02``03-03`。K3s 自带 **Traefik Helm chart** 支持 **`persistence`**:开启后由 chart **自动创建 PVC**`storageClass: local-path`),挂载到 **`/data`**,与 `acme.storage` 一致,**Pod 重建 / 滚动后证书仍在**。
**前提**`nodeSelector` 必须把 Traefik **固定在同一节点**(与 local-path **ReadWriteOnce** 一致);若换节点,需迁卷或重新签发。
| 场景 | 唯一真源 |
|------|----------|
| **Dashboard + ACME + local-path推荐** | **仅此一份**[`ansible/files/traefik-dashboard-acme/traefik-dashboard-acme.yaml`](../ansible/files/traefik-dashboard-acme/traefik-dashboard-acme.yaml)**HelmChart persistence + ACME + Dashboard + IngressRoute** |
清单内已含:`persistence.enabled: true``storageClass: local-path``size: 512Mi``path: /data`,与 `acme.storage=/data/acme.json` 一致。部署前替换 **`<YOUR_REAL_EMAIL>`**、`nodeSelector` 中的 **主机名**;并确保 **`cloudflare-api-token`** Secret 已存在(同 `03-02` / `03-03`)。**不需要 Dashboard** 时按该 YAML 文件头注释删减。
> **只能有一份** `HelmChartConfig``metadata.name: traefik`)。若曾用旧版无 persistence 的清单,请 **合并为** 上述 `traefik-dashboard-acme.yaml`(或 `traefik-acme.yaml` 并自行补全 persistence避免多文件重复定义。
**应用与核对**(路径按你的 manifests 目录调整):
```bash
kubectl apply -f ansible/files/traefik-dashboard-acme/traefik-dashboard-acme.yaml
kubectl -n kube-system rollout status deploy/traefik --timeout=300s
kubectl -n kube-system get pvc | grep -i traefik
kubectl -n kube-system exec deploy/traefik -- ls -la /data/acme.json
kubectl -n kube-system logs deploy/traefik --tail=80 | grep -i acme || true
```
**emptyDir / 无持久卷** 迁到 PVC 时,若旧 Pod 里已有有效 `acme.json`,可先 `kubectl cp` 备份再切换;否则切换后会按新账户重新向 Lets Encrypt 申请。
更多 ACME 排障见 `03-02-k3s-traefik-acme.md``03-03-k3s-traefik-dashboard-acme.md`
## 下一步