Files
Deploy-Laboratory/docs/03-04-k3s-cloudflare-tunnel-配置接入.md
2026-03-29 09:08:01 +08:00

13 KiB
Raw Permalink Blame History

03-04-k3s Cloudflare Tunnel 配置接入

本文覆盖 Tunnel 完整流程Zero Trust 云端创建、域名映射,以及将 cloudflared 安装到 K3s 并跑起 Pod使 Traefik 通过 Tunnel 对外提供服务

状态:已验证2026-03本仓库实验室 K3s 集群)。

TL;DR

  • 自动化验收./ansible/bin/verify.sh run 03-04
  • 关键前置Traefik 可用;域名托管 CloudflareZero Trust 中 Tunnel 与 Public Hostname 已配置
  • 自动化所需环境变量(见 ansible/env/.env.verify.exampleCF_TUNNEL_TEST_URLHTTPS 完整探针 URL CF_TUNNEL_TEST_HOST(仅主机名,脚本拼成 https://HOST/TUNNEL_TOKEN 与集群内 kube-system/cloudflared-credentials 二选一(已有 Secret 可不设 env。二者探针变量皆缺时验收为 gated。可选 CF_TUNNEL_CURL_INSECURE=1 为探针 curl 加 -k(仅排障)。
  • 成功判据:达到本文「预期」且 playbook 断言通过rollout + HTTPS 探针)
  • 排障:见本文「排障」

访问链路(如何通过 Tunnel 访问 K3s 资源)

整体流程:公网域名 → Cloudflare Edge → Tunnel → cloudflared Pod → Traefik → 根据 Host/Path 路由到具体 Service如 Dashboard、GitLab、Homer 等)。

Traefik 是唯一入口。所有流量经 Tunnel 进入后,由 Traefik 的 IngressRoute/Ingress 按 HostPath 分发到不同后端。先保证 Traefik 内有对应路由(如 Dashboard 的 IngressRoute再在 Zero Trust 中把域名指到 Traefik即可访问。


前置条件

  • 控制节点已就绪:01-01-k3s-控制节点含traefik.md
  • Traefik 已可用;若要通过 Tunnel 访问 Dashboard需先部署 03-01-k3s-traefik-dashboard.md03-03-k3s-traefik-dashboard-acme.md
  • 域名已托管在 Cloudflare且 Nameserver 已指向 Cloudflare
  • 已创建 Cloudflare Zero Trust 账号

云端创建 TunnelZero Trust 操作说明)

1. 创建 Tunnel

  1. 登录 Cloudflare Zero Trust Dashboard
  2. 左侧导航:NetworksTunnels(或 ConnectorsCloudflare Tunnels
  3. 点击 Create a tunnel
  4. 选择 Cloudflared 作为 Connector 类型
  5. 输入 Tunnel 名称(如 k3s-lab),点击 Save tunnel

2. 复制 Tunnel Token

  1. 在 Tunnel 创建成功后,会进入 Install connector 页面
  2. 选择操作系统(如 Linux
  3. 在安装命令中,找到形如 cloudflared tunnel run --token <长串 Token>Token
  4. 复制整个 Token(点击复制图标,或手动选中),妥善保存
  5. 该 Token 将用于下方 K3s 中 cloudflared 部署

若已关闭页面:在 Tunnels 列表中点击该 Tunnel → ConfigureInstall connector,可重新查看/生成 Token。

3. 部署 cloudflared 到 K3s

ansible/files/03-04/cloudflared.yaml 仅含 DeploymentSecret 必须单独创建(避免 kubectl apply 覆盖 token。推荐与 ansible/playbooks/verify/03-04.yml 一致:先 cloudflared-credentials,再 apply Deployment。

  1. 在集群中创建 SecretYOUR_TOKEN 换成 Zero Trust 里的 Tunnel token
kubectl -n kube-system create secret generic cloudflared-credentials \
  --from-literal=TUNNEL_TOKEN='YOUR_TOKEN' \
  --dry-run=client -o yaml | kubectl apply -f -
  1. 应用 Deployment 并等待就绪(按实际 manifests 路径选择其一):
# 默认路径
kubectl apply -f /var/lib/rancher/k3s/server/manifests/cloudflared.yaml
kubectl -n kube-system rollout status deploy/cloudflared
# 自定义 data-dir如 /storage
kubectl apply -f /storage/server/manifests/cloudflared.yaml
kubectl -n kube-system rollout status deploy/cloudflared
  1. Deployment 清单 放入上述 manifests 目录后K3s 重启时会自动加载Secret 仍需单独存在)。

建议要点:

  • 使用官方 cloudflared 镜像
  • Secret 不写死在明文 YAML
  • cloudflared 放在 kube-system 或专用 namespace
  • Tunnel 指向的 URL 在 Zero Trust 中配置为 Traefik Service无需在 cloudflared.yaml 内指定

集群内 Traefik 地址Public Hostname 的 URL 填什么)

Tunnel 后端应指向 集群内的 Traefik 入口,常用写法:

写法 说明
traefik.kube-system.svc.cluster.local:80 见下「与哪份 YAML / 哪些字段对应」。不要手写 http://Zero Trust 里选 HTTP 后只填主机与端口。
192.168.2.61 节点 IP与 Traefik Service EXTERNAL-IP 之一、端口 80 等价。Public Hostname 的 URL 只填到 IP/主机path 在浏览器访问时带上(见步骤 6

和仓库里哪份 YAML 的关系

  • 本仓库的 cloudflared.yaml 定义 cloudflared 的 DeploymentSecret cloudflared-credentials 单独创建不包含 Traefik Service。Tunnel 在 Zero Trust 里指向的仍是 集群内已存在的 Traefik Service
  • Traefik 的 Service 由 K3s 内置 TraefikHelmChart安装时创建资源名一般为 traefik,命名空间 kube-system。若你改过 chart 或 Service 名,以下 FQDN 与端口要以 实际 kubectl get svc 输出 为准。

kubectl get svc traefik -o yaml 里哪些字段对应

集群 DNS 完整名规则:<metadata.name>.<metadata.namespace>.svc.cluster.local:<spec.ports 中 web 的 port>

你填的片段 对应 YAML 路径(kubectl -n kube-system get svc traefik -o yaml
traefik metadata.name
kube-system metadata.namespace
:80 spec.portsname 常为 webport: 80HTTP 入口;若你环境 port 不是 80Tunnel URL 里端口改成一致)

示例(节选,以你集群为准):

metadata:
  name: traefik                 # → FQDN 第一段
  namespace: kube-system      # → FQDN 第二段
spec:
  ports:
    - name: web
      port: 80                  # → Tunnel URL 里冒号后的端口
      # ...
  type: LoadBalancer            # EXTERNAL-IP 为节点 IP 列表时,也可用 IP:80 代替集群 DNS

怎么用 kubectl 查(建议逐条执行)

# 1) 表格式:确认 NAME / PORT(S) / 集群 IP
kubectl -n kube-system get svc traefik -o wide

# 2) 打印集群 DNS 主机名(无端口)
kubectl -n kube-system get svc traefik -o jsonpath='{.metadata.name}.{.metadata.namespace}.svc.cluster.local'
echo

# 2b) 各端口名与端口(核对 HTTP 一般为 name=web、port=80
kubectl -n kube-system get svc traefik -o jsonpath='{range .spec.ports[*]}{.name}={.port}{"\n"}{end}'

# 3) 导出完整 YAML人工对照 metadata / spec.ports
kubectl -n kube-system get svc traefik -o yaml

HTTP 入口一般为 name=webport: 80;若你环境端口名不是 web,以第 1、2、3 条里 实际 port 数字 为准Tunnel URL 中冒号后改为该数字。

cloudflared 与 Traefik 同集群时,优先用 traefik.kube-system.svc.cluster.local:80,不依赖某台节点 IP 是否变更。

临时验证(集群内 curl

官方 cloudflared 镜像多为 distroless、无 sh,不要用 kubectl exec deploy/cloudflared -- sh

kube-system 起临时 Pod 探测 Traefik与 Tunnel 后端同源):

# 根路径(常见 404无默认路由时正常
kubectl run curl-test --rm -n kube-system --restart=Never \
  --image=curlimages/curl:latest -- \
  curl -sS -o /dev/null -w "HTTP %{http_code}\n" \
  http://traefik.kube-system.svc.cluster.local:80/

# Dashboard已按 03-01/03-03 部署时期望 200
kubectl run curl-test --rm -n kube-system --restart=Never \
  --image=curlimages/curl:latest -- \
  curl -sS -o /dev/null -w "HTTP %{http_code}\n" \
  http://traefik.kube-system.svc.cluster.local:80/dashboard/
  • / → 404:多数环境正常(未配置根路径路由)。
  • /dashboard/ → 200:说明集群 DNS 与 Traefik 可达Public Hostname 可填上述集群内地址。

4. 验证连接

kubectl -n kube-system get pods | grep cloudflared
kubectl -n kube-system logs deploy/cloudflared --tail=100

确认 Pod 为 Running,日志中可见 tunnel connected只有 Connector 已连接后,才能进行下一步域名配置。

5. 配置域名映射Public Hostnames / Route tunnel

Zero Trust 向导顺序为:选择类型 → 命名 → 安装并运行 Connector路由流量。需等 Pod 跑起并显示已连接后,再配置 Public Hostnames。

  1. 在 Tunnel 配置页,切换到 Public Hostnames(已发布应用程序)标签,点击 Add a public hostname
  2. 配置如下:
字段 填写说明
Subdomain 子域名(如 k3sgithome),或留空表示根域
Domain 下拉选择已托管在 Cloudflare 的域名(如 jackadam.top
Path 留空表示全路径;或填正则如 ^/blog 做路径匹配
Service type 选择 HTTP(集群内 Traefik 为 HTTP勿选 HTTPS
URL 仅填 traefik.kube-system.svc.cluster.local:80不要加 http://(含义与核对见上文「集群内 Traefik 地址」)

重要URL 输入框会根据 Service type 自动加协议前缀。选 HTTP 时只需填 traefik.kube-system.svc.cluster.local:80;若手写 http:// 会变成 http://http://...,导致「服务 URL 无效」。

  1. 点击 Save hostname,按需重复添加其他子域,均指向同一内部地址。

示例Subdomain k3s + Domain jackadam.top → 公网 k3s.jackadam.top 访问 Traefik不同子域由 Traefik 的 IngressRoute 按 Host 分发。

6. 快速验证:以 Dashboard 为例

若已按 03-01 或 03-03 部署 Traefik Dashboard按上述步骤 5 添加一条 Public Hostname。Traefik 无需修改

Public Hostname 的 URL 只能写到「主机 + 端口」,不能写成 192.168.2.61/dashboard 这类带 path 的地址;控制台也不支持在 URL 里做 path patch/转发。路径由浏览器访问时带上,由 Traefik 按路由匹配。

Dashboard 专用子域(示例)

字段 填写值
Subdomain dashboard
Domain jackadam.top(或你的域名)
Path 留空
Service type HTTP
URL traefik.kube-system.svc.cluster.local:80192.168.2.61(仅主机或集群 DNS在 URL 里写 /dashboard

192.168.2.61 换成你的 Traefik 入口节点 IPkubectl get svc traefik 中 EXTERNAL-IP 之一一致即可)。

访问时在域名后带上 path:浏览器打开 https://dashboard.jackadam.top/dashboard/(路径 /dashboard/ 由 Traefik 的 Dashboard IngressRoute 处理)。


其他用法:单域名 k3s.jackadam.topURL 同样只填到 traefik...:80 或节点 IP访问时带路径https://k3s.jackadam.top/dashboard/;或为每个应用单独配子域。


架构说明

  • 流量路径:公网 → Cloudflare Edge → Tunnel → cloudflared Pod → Traefik Service → 各 IngressRoute 后端
  • 配置要点Public Hostname 的 URL 为 traefik.kube-system.svc.cluster.local:80Service type 选 HTTPcloudflared 与 Traefik 同集群,可直接通过 Service 访问。

预期

  • Pod 为 Running,日志中可见 tunnel connected
  • 配置域名后,访问公网域名可到达 Traefik 路由

注意事项

  • 没有 token/凭据:回到 Zero Trust 页面重新生成
  • 顺序:先跑起 Pod 并确认连接,再配置 Public Hostnames否则「路由流量」步骤无法生效
  • URL 填写错误Service type 选 HTTPURL 只填 traefik.kube-system.svc.cluster.local:80,勿加 http://

失败排查

  • 域名解析正常但访问超时:先看 Tunnel 状态与 cloudflared 日志
  • 返回 404:通常是 Traefik 路由未命中
  • 返回 502:优先排查后端链路(06-01-k3s-networkpolicy-故障排查.md

下一步

  • 其他应用GitLab、Homer 等):在集群内创建 IngressRoute/Ingress 指定 Host 与后端,再在 Zero Trust 中添加对应子域的 Public Hostname 即可
  • 05-03-k3s-安装gitlab-含runner.md
  • 05-01-k3s-部署homer首页面板.md

排障

  • 先看 playbook 输出:失败时先定位是 deploy/wait/http_check 哪一步。
  • 集群侧总览kubectl get nodes -o widekubectl -n kube-system get pods -o wide
  • 事件与日志kubectl -n <ns> describe ...kubectl -n <ns> logs ... --tail=200