当你的自托管服务多到一定程度,开始认真评估 K3s/Kubernetes 时,常常会发现"挂个 Pod"这种基础不难,难的是两件事:一是"流量怎么进"——多个服务以许多 Pod/IP 暴露在外,总不能每个都裸端口或改路由,需要一个统一的入口把外部流量按规则分发到对应服务;二是"数据怎么留"——Pod 天生是临时的、删掉就没了,而应用往往要持久化数据,得让数据不随 Pod 消失。这两件事正是 Ingress(入口/路由层)与持久化存储(Volume/PVC)解决的。这篇以 K3s/K8s 为背景讲清 Ingress 和存储各自解决什么、最小怎么用,以及它们在自托管脚本里"既是地面又是入口"的位置。
一、先弄清两件事为什么难:Pod 是"临时的",流量和是要"稳定落地"的
Kubernetes 的核心抽象是 Pod——运行应用的最小单元。但 Pod 有两个与实际使用冲突的特点:它的 IP 是按需变化的(Pod 删了重建 IP 就换),它也是临时的(卷、Pod 内数据会随生命周期消失)。于是生产使用 K8s 时,两个配套能力就被逼出来了:一是"入口稳定"——外部用户要访问一批会变化的 Pod,需要一个稳定的入口和按域名/路径分发的路由,这就是 Service + Ingress;二是"数据持久"——应用要有即使 Pod 没了也还在的数据,这就是 PersistentVolume(PV)/ PersistentVolumeClaim(PVC)与存储类(StorageClass)。
对自托管者,理解这两件事的意义在于:K3s/K8s 的便利(声明式、自愈、调度)建立在"Pod 可随时重建"之上,而"可重建"意味着你必须想清楚"重建后什么会丢"。Ingress 处理"流量怎么找到新 Pod",存储处理"Pod 没了数据不出事",两者一起,才让"摇曳的 Pod 体系"真正可被生产使用。之前用 Compose 是在单机上手动编排;K3s 上这两件正是从"能跑起 Pod"走向"能用好集群"的过渡点。
二、Ingress:把"一堆变化的 Pod"收敛成一个稳定入口
Ingress 解决的是"外部流量如何进入集群并分发到对应服务":它是一个标准资源,定义"当我访问主机名/路径 X,该路由到哪个 service/服务"。具体实现靠 Ingress Controller(如 Nginx Ingress、Traefik),它在集群里充当入口网关,按你的 Ingress 规则把请求转发到内部 service。这样你就有一"个统一入口 + 按域名/路径路由",内部 Pod 如何变、IP 如何变,对用户都无所谓,和之前在单机 Nginx/Caddy 上做反代的那套心智是一脉相承的,只是搬到集群内部用声明式表达了。
# 一个 Ingress 资源示意(访问 app.example.com 路由到 service:app-svc:80)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
spec:
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service: { name: app-svc, port: { number: 80 } }
# 证书:通常 Ingress Controller 可配 TLS/自动证书;前面再套负载/K3s 的 traefik 入口
落地要领和单机反代几乎一脉相承:一个入口收敛外部、按域名/路径分发、接好 HTTPS(常由 Ingress Controller 或外层负载终结)。对 K3s 用户,K3s 默认常带 Traefik 当 Ingress Controller;理解"你声明 Ingress,Controller 负责真正转发"这层分工,就能在"加个服务到底要不要改 Ingress""Host/路径怎么配"这类问题上不慌。先把"域名 → Ingress 规则 → service → Pod"这条链路打通,入口层就顺了。
三、持久化存储:让"Pod 没了、数据还在"
持久化存储解决"数据不随 Pod 消失"。机制上是让存储与 Pod 的生命周期解耦:你先声明想要的存储(PVC,PersistentVolumeClaim 描述"我要多少、什么类型"),集群用存储类(StorageClass)提供真正的存储(PV,可能是本地盘、网络存储、NFS 等),再把 PVC 挂给 Pod。这样 Pod 删除重建后,同样的 PVC 还能挂回,数据还在。对自托管,这是"数据库、相册、上传、配置这类要留的数据"在 K8s 里安全落地的关键。
# PVC 示意 + 在 Deployment 里挂载(Pod 重建后数据仍在 PVC)
apiVersion: v1
kind: PersistentVolumeClaim
metadata: { name: app-data }
spec: { accessModes: ["ReadWriteOnce"], resources: { requests: { storage: 10Gi } } }
# Deployment 里:把 PVC 挂成容器里的目录
# volumeMounts: [{ name: data, mountPath: /data }]
# volumes: [{ name: data, persistentVolumeClaim: { claimName: app-data } }]
落地关键是把"存储也当有生命周期、要备份"来规划:PVC 里可能躺着你宝贵的数据库/数据,别因为"它能在集群里持久"就以为万事大吉——集群级快照与异地备份仍要做(很多自托管者在 K8s 上最大的坑,就是把 PVC 当暂存、忘了它也承载唯一的数据)。同时理解"存取模式"(ReadWriteOnce/ReadWriteMany 等)影响你能不能多副本同时挂同一个卷;对数据库这类通常 RWO 挂单份即可,对要共享的(如前面聊的 NFS)则要用对应的模式/存储类。
四、结合自托管:Ingress + 存储如何让"从 Compose 到 K3s"值得
把 Ingress 与存储想清后,能更冷静地判断"要不要上 K3s"。价值在于:它让一批服务获得"声明式入口 + 声明式存储 + 自愈/调度"的统一管理——当你的服务已经多到在若干台机器上难以手工编排时,这套统一抽象很值。但代价是更高的复杂度与运维成本:要管 Ingress/Controller、存储类、还有升级与排障。所以合适的判断不是"K8s 很酷就上",而是"我现在服务的数量与多机需求,是否已经到手工编排吃力的程度"。
# 判断"要不要从 Compose 走到 K3s"的简单问题:
# 服务是否已多到/跨机器到难以手工编排? 需要统一的入口+存储+自愈抽象吗?
# 需要 → K3s(轻量发行版)很合适;单机少数服务 → Compose 仍最省心
真决定上后,专为自托管做好两件事:一是"存储先行"——先规划好本地存储类或接上 NFS/网络存储,搞清楚每个要持久化的数据的确该去哪(PVC),不要等数据丢了才补;二是"入口分层"——Ingress 收敛集群内部,前面可再接外层负载/CDN,层层清晰。把这两件作为"从 Compose 迈向 K3s"时最先想清楚的地基,集群才不至于"Pod 能跑、却不知道流量怎么进、数据会不会丢"的空中楼阁。
五、边界与提醒:存储是数据、不是免死金牌;复杂度要心里有数
最后把边界与提醒摆清楚。其一,"PVC 持久 ≠ 数据安全":它是"不随 Pod 消失",但不等于"灾难时不丢",仍需结合集群快照与异地备份,尤其对数据库这类唯一副本重要的数据。其二,"多副本与存储要匹配":不是所有存储都能被多个副本同时读写,别想当然让所有持久数据都多副本共享,要按数据性质选存取模式与存储类。其三,"复杂度是真实的":Ingress/Controller、存储类、PVC、升级与排障,都是要持续投入的运维面——决定上 K3s 就接受这份复杂度,别把它当"换个高级玩法"。
# 存储相关的自托管提醒:
# - PVC 里的核心数据仍要:集群快照 + 异地备份 + 恢复演练
# - 存取模式按需选:数据库类 RWO 单挂;共享类才考虑 RWX/NFS
# - 对既想 K3s 又要省心的,存储类与入口先规划好,别边跑边补地基建
把"入口抽象 + 存储抽象能得到什么、要付出什么复杂度"一并想全,K3s/K8s 才是你自托管体系的升级而非负担。它解决的核心——"一批会变化的 Pod,也有稳定入口、也有能留的数据"——正是多服务自托管从单机走向集群时的两根支柱。把 Ingress 与持久化存储从一开始就规划清楚、并配好备份与恢复,你的集群就能既灵活、又稳当地长期承载自托管服务。
结语
在 K3s/Kubernetes 里,Ingress 与持久化存储是让"一批随时可重建的 Pod"真正可用的两根支柱:Ingress 用 Controller 把外部流量按域名/路径收敛分发到内部 service(提供稳定入口),PVC/PV 与 StorageClass 让数据不随 Pod 消失(提供持久数据)。落地要点:先打通"域名 → Ingress → service → Pod"入口链路并接好 HTTPS;为要留的数据规划 PVC/存储类并挂载,数据库类用 RWO、共享类才考虑 RWX/NFS;对"要不要从 Compose 上 K3s"先评估`服务是否多到需要统一入口+存储+调度抽象`。边界是"PVC 持久≠数据安全的免死金牌",集群快照+异地备份+恢复仍要做,且要接受 Ingress/存储类的运维复杂度。当这两根支柱搭稳,K3s 才会从"能跑 Pod"成为你自托管可长期依靠的集群底座。


