我把我的 $70 Kubernetes 集群暴露到互联网(未打开任何端口)
Source: Dev.to
问题
在本地我通过 http://192.168.0.173:30300 访问 Grafana。
向互联网开放端口就像把前门敞开不锁。我不想让我的 GTX 1070 Ti 被加密货币挖矿程序利用。
我需要的解决方案必须满足:
- 安全 – 没有开放端口。
- 免费 – 预算有限。
- 公开 – 能通过
subdomain.domain.com访问。
于是选择 Cloudflare Tunnel。
零信任切换
DNS 迁移
| 旧方式 | 新方式 |
|---|---|
| Squarespace 注册商 → Netlify DNS | Squarespace 注册商 → Cloudflare DNS → Netlify(主站) + Tunnel(子域) |
我把域名服务器迁移到 Cloudflare,系统自动导入了已有记录,且零停机时间。
在 Kubernetes 中部署 cloudflared
我没有在每台机器(Pop!_OS 桌面、Ubuntu 笔记本)上单独运行二进制文件,而是把隧道连接器作为原生的 Kubernetes Deployment 部署。
apiVersion: apps/v1
kind: Deployment
metadata:
name: cloudflared
spec:
replicas: 2
template:
spec:
containers:
- name: cloudflared
image: cloudflare/cloudflared:latest
args:
- tunnel
- --no-autoupdate
- run
- --token
- $(TUNNEL_TOKEN)
现在集群会自动向 Cloudflare 拨号。如果节点重启,Kubernetes 会重新调度 Pod,隧道会即时重新连接。
告别 NodePort,迎接子域名
在 Cloudflare 仪表盘(Network > Tunnels)中,我把公共主机名映射到内部的 ClusterIP(或 NodePort):
grafana.bhargavmantha.dev → http://192.168.0.173:30300ollama.bhargavmantha.dev → http://192.168.0.173:31434uptime.bhargavmantha.dev → http://192.168.0.173:30001
SSL 证书由 Cloudflare 在边缘自动处理,所以我可以直接看到锁形图标,无需在集群内部配置 cert‑manager 或 Let’s Encrypt。
经验教训
教训 1 – Ingress 控制器对家庭实验室来说是大材小用
我花了好几天时间在裸金属集群上让 Traefik 或 Nginx Ingress 与 MetalLB 配合工作。Cloudflare Tunnel 直接绕过了整套层级。我不需要 Ingress 控制器,只需要一个连接器。
教训 2 – 安全也可以很便利
把所有服务都放在 Cloudflare 后面后,我以后可以再添加 Access Application 层,例如使用 Google/GitHub 登录页面来保护 grafana.bhargavmantha.dev,为本身不支持 2FA 的应用添加双因素认证。
当前状态
- 公开可访问: Grafana、Uptime Kuma、Open WebUI。
- 成本: $0(Cloudflare 免费套餐)。
- 安全性: 0 个开放端口。