跳转至

FRP 访问家庭内网 K8s 集群部署教程

目标

这篇教程解决的是下面这个问题:

  • 家里笔记本通过 VMware 跑了一套 Kubernetes 集群
  • 家里没有公网 IP
  • 你有一台腾讯云轻量服务器,有公网 IP
  • 你希望在任何地方都能通过域名访问家里 K8s 集群里的服务

这篇教程采用的方案是:

公网用户
  -> 域名
  -> 腾讯云轻量服务器
  -> frps
  -> frpc
  -> 家里 K8s Ingress / NodePort
  -> Service
  -> Pod

这套方案适合什么

适合下面这些场景:

  • 发布家里 K8s 中的博客、测试站点、管理页面
  • 让公网通过域名访问你家里的实验服务
  • 后续继续练 Ingress、证书、灰度、反向代理链路

这套方案不适合直接做这些事情:

  • kube-apiserver:6443 直接暴露到公网
  • etcdkubelet、Dashboard 管理端口直接暴露到公网
  • 把整个内网大面积映射出去

先说整体推荐

如果你要做公网访问,我建议你最终采用下面这个结构:

家里环境

  • VMware 里跑 K8s 集群
  • 安装 ingress-nginx
  • ingress-nginx controller 暴露为 NodePort
  • 在一台家里机器上运行 frpc

腾讯云轻量

  • 开放 80 / 443 / 7000
  • 运行 frps
  • 域名解析到腾讯云轻量公网 IP

访问链路

  • 公网访问 app.example.com
  • 流量先到腾讯云轻量
  • frps 通过隧道把请求转回家里
  • 家里 Ingress 再按域名和路径分发到具体服务

关键原则

原则 1:只暴露 Ingress,不暴露控制面

这是整篇里最重要的原则。

公网暴露的应该是:

  • 站点访问入口
  • 业务服务入口
  • 最多是反向代理入口

不要暴露:

  • 6443
  • 2379/2380
  • 10250
  • 10257
  • 10259

这些属于控制面、etcd 或 kubelet 相关端口,不应该通过 frp 直接给公网访问。

原则 2:把“发布服务”和“远程管理”分开

这篇文档只解决“发布服务到公网”。

如果你后面还要远程运维,建议单独走:

  • WireGuard
  • 跳板机
  • SSH 隧道

不要把 frp 同时拿来做所有管理入口。

你的目标拓扑

假设你家里 VMware 中的 K8s 环境如下:

角色 主机名 IP
control plane cp1 192.168.56.10
worker worker1 192.168.56.11
worker worker2 192.168.56.12

假设你的腾讯云轻量公网信息如下:

资源
公网 IP 1.2.3.4
域名 lab.example.com

假设你后续要发布的服务域名如下:

域名 目标服务
blog.lab.example.com 博客
demo.lab.example.com 测试应用

第一步:在 K8s 中安装 Ingress Controller

如果你家里 K8s 还没有 Ingress Controller,建议安装 ingress-nginx

安装

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml

安装后先看:

kubectl get pods -n ingress-nginx
kubectl get svc -n ingress-nginx

关键说明

默认情况下,在裸机或实验环境里,ingress-nginx-controller 往往不是云 LB,而是:

  • NodePort
  • 或者 LoadBalancer 但没有真实外部 IP

对于你这个场景,我们就是要用 NodePort

第二步:确认 ingress-nginx 暴露方式

先看 controller service:

kubectl get svc -n ingress-nginx ingress-nginx-controller -o wide

如果已经是 NodePort,记下端口。

如果不是,可以改成 NodePort

kubectl -n ingress-nginx edit svc ingress-nginx-controller

将:

type: LoadBalancer

改成:

type: NodePort

推荐端口

通常会生成类似:

  • HTTP: 30080
  • HTTPS: 30443

你也可以手动指定,但要确保不冲突。

验证

找一台 K8s 节点,例如 cp1,验证:

curl http://192.168.56.10:30080

如果看到 404 Not Found,这通常是正常的,说明 ingress-nginx 已经在监听,只是还没有匹配到 Ingress 规则。

第三步:准备一个测试服务

先在家里 K8s 中部署一个测试 nginx,确认链路可用。

kubectl create deployment nginx-demo --image=nginx
kubectl expose deployment nginx-demo --port=80 --target-port=80 --name=nginx-demo

然后创建 Ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-demo
spec:
  ingressClassName: nginx
  rules:
    - host: blog.lab.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: nginx-demo
                port:
                  number: 80

应用:

kubectl apply -f nginx-demo-ingress.yaml
kubectl get ingress

关键说明

这里一定要先在内网侧把 Ingress 路由跑通,再去配 frp。
否则你后面很容易分不清是:

  • frp 配错了
  • 还是 Ingress 配错了
  • 还是 Service 没挂上

第四步:在腾讯云轻量部署 frps

1. 下载 frp

在腾讯云轻量服务器上执行:

wget https://github.com/fatedier/frp/releases/download/v0.68.1/frp_0.68.1_linux_amd64.tar.gz
tar -xzf frp_0.68.1_linux_amd64.tar.gz
cd frp_0.68.1_linux_amd64

这里使用的是当前最新稳定版本 v0.68.1

2. 编写 frps.toml

bindPort = 7000
vhostHTTPPort = 80
vhostHTTPSPort = 443

auth.method = "token"
auth.token = "replace-with-a-strong-token"

webServer.addr = "127.0.0.1"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "replace-with-a-strong-password"

transport.tls.force = true

3. 启动 frps

./frps -c ./frps.toml

关键说明

注意 1:auth.token 一定要改

不要直接抄教程里的明文 token。

注意 2:Dashboard 不要直接开公网

这里我把:

webServer.addr = "127.0.0.1"

写成了本地监听,就是避免你把管理面板直接暴露给公网。

注意 3:强制 TLS

transport.tls.force = true

建议打开,避免客户端和服务端之间走裸明文控制链路。

第五步:配置腾讯云轻量安全组

你至少需要开放这些端口:

端口 作用
22 SSH
80 HTTP
443 HTTPS
7000 frp 控制通道

关键说明

注意 1:不要开放不必要的端口

尤其不要因为调试方便,就顺手把:

  • 6443
  • 2379
  • 10250

也开放出去。

注意 2:如非必要,不要开放 7500

Dashboard 最好只做本地访问,或者只对白名单 IP 开放。

第六步:在家里部署 frpc

你可以把 frpc 放在:

  • 家里物理笔记本宿主机
  • 家里某台 K8s 节点 VM
  • 家里专门的跳板机

最简单的做法是:

  • 如果宿主机能访问 VMware 内部 K8s 节点 IP,就直接部署在宿主机

下载 frp

在家里机器上执行:

wget https://github.com/fatedier/frp/releases/download/v0.68.1/frp_0.68.1_linux_amd64.tar.gz
tar -xzf frp_0.68.1_linux_amd64.tar.gz
cd frp_0.68.1_linux_amd64

如果你家里笔记本不是 Linux,就下载对应平台版本。

编写 frpc.toml

serverAddr = "1.2.3.4"
serverPort = 7000

auth.method = "token"
auth.token = "replace-with-a-strong-token"

[[proxies]]
name = "home-k8s-http"
type = "http"
localIP = "192.168.56.10"
localPort = 30080
customDomains = ["blog.lab.example.com", "demo.lab.example.com"]

[[proxies]]
name = "home-k8s-https"
type = "https"
localIP = "192.168.56.10"
localPort = 30443
customDomains = ["blog.lab.example.com", "demo.lab.example.com"]

启动 frpc

./frpc -c ./frpc.toml

第七步:配置 DNS

你的域名解析应该指向腾讯云轻量公网 IP,而不是指向家里。

例如:

记录
blog.lab.example.com 1.2.3.4
demo.lab.example.com 1.2.3.4

第八步:验证访问链路

先从家里内网验证

先确认 Ingress 本身没问题:

curl -H 'Host: blog.lab.example.com' http://192.168.56.10:30080

如果你看到 nginx 默认页面,说明:

  • Deployment 正常
  • Service 正常
  • Ingress 正常
  • NodePort 正常

再看 frpc 日志

如果 frpc 成功连接,你会看到类似已注册代理的日志。

再从外网验证

在任意外部网络执行:

curl http://blog.lab.example.com

或者直接浏览器访问:

http://blog.lab.example.com

HTTPS 怎么处理

这是整个方案里最容易绕晕的地方。

你有 2 种做法。

做法 1:TLS 终止在家里 Ingress

链路:

公网用户 -> 腾讯云 frps 443 -> frpc -> 家里 ingress-nginx 30443 -> Ingress TLS -> 服务

优点:

  • 证书和域名配置都在 K8s 里管理
  • 更接近真实 K8s 生产入口

缺点:

  • 你需要在家里 K8s 里自己处理证书

做法 2:TLS 终止在腾讯云

链路:

公网用户 -> 腾讯云 Nginx/Caddy HTTPS -> frps HTTP -> frpc -> 家里 Ingress HTTP

优点:

  • 证书统一放在腾讯云机器上
  • 公网侧证书运维更简单

缺点:

  • 链路多一层
  • 结构上不如“K8s 自己接 TLS”直观

我的建议

如果你现在目标是:

  • 快速打通链路
  • 先把服务发出去

建议先上:

  • 公网 HTTP
  • 或者 腾讯云 TLS 终止

等后面再升级到:

  • 家里 Ingress 直接做 HTTPS

最重要的几个注意点

注意 1:frpc 不要直接指向 Pod IP

你应该转发到:

  • Ingress NodePort
  • 或者稳定的内网代理入口

不要直接转发到某个 Pod IP,因为 Pod 会漂移。

注意 2:先把 Ingress 跑通,再配 frp

排障顺序建议固定:

  1. 先验证 Pod
  2. 再验证 Service
  3. 再验证 Ingress
  4. 最后验证 frp

注意 3:不要直接把 K8s 控制面穿到公网

特别是:

  • 6443
  • Dashboard
  • kubelet API

这不是“方便”,这是安全事故预备动作。

注意 4:宿主机和 VMware 内网要先互通

在部署 frpc 之前,先确认家里运行 frpc 的这台机器能访问:

curl http://192.168.56.10:30080

如果这一步不通,后面所有 frp 配置都不会成功。

注意 5:Ingress 规则要用真实域名

你的 Ingress host 必须和 frpc 里的 customDomains 对上。

不然会出现:

  • frp 通了
  • 域名也通了
  • 但是 ingress-nginx 一直返回默认 404

常见故障排查

1. 域名打不开

先查:

  • DNS 是否解析到腾讯云公网 IP
  • 腾讯云安全组是否放通 80/443
  • frps 是否正常启动

2. frpc 连不上 frps

先查:

  • serverAddr 是否正确
  • 7000 是否放通
  • token 是否一致
  • frps 是否已启动

3. frp 已连通,但访问仍然 404

这通常不是 frp 问题,而是 Ingress 问题。

先查:

  • Ingress host 是否和域名一致
  • ingressClass 是否正确
  • Service 后端是否正常

4. Service 有对象但页面打不开

先查:

  • Endpoints 是否生成
  • Pod 是否 Ready
  • Service targetPort 是否正确

5. 内网可访问,公网不可访问

先查:

  • 腾讯云安全组
  • frps 日志
  • 域名解析
  • frpc 是否成功注册对应域名代理

最终推荐结构

如果你要长期使用,我建议最终做成这样:

腾讯云轻量

  • frps
  • NginxCaddy
  • 域名解析入口

家里 K8s

  • ingress-nginx
  • NodePort
  • 所有站点都走 Ingress 统一管理

管理平面

公网只暴露业务入口,不暴露 K8s 控制面。

这篇教程适合接着读什么

建议和这些内容一起用:

后续建议

如果你愿意继续往下做,下一步最适合补的就是:

  1. frp + ingress-nginx + cert-manager 的 HTTPS 实战教程
  2. 一台腾讯云轻量同时承载 frps + Nginx + 证书自动续期 的完整架构

这样你这套家庭 K8s 发布链路就会更接近真实生产入口。