How an HTTP request reaches a private application connected with Cloudflare Tunnel

Cloudflared 在您的资源和 Cloudflare 的全球网络之间建立出站连接(隧道)。隧道是将流量路由到 DNS 记录的持久对象。在同一个隧道中,您可以根据需要运行任意数量的“cloudflared”进程(连接器)。这些进程将建立与 Cloudflare 的连接并将流量发送到最近的 Cloudflare 数据中心。 – 官方介绍(翻译)

预先准备

  • Cloudflare账号,通过邮箱直接注册即可,点击注册链接
  • k8s集群,可以使用kindminikubek3s等工具进行快速创建;
  • 一个可用的域名,需要托管到Cloudflare平台,免费域名可以去cloudns或者us.kg注册,相关注册视频教程可以参考YouTube;

快速开始

Cloudflare中创建token

CleanShot 2025-01-07 at 16.41.28@2x

依次点击管理账户–> 账户API权限 –> 建立token,点开之后选择最下面的自定义token

CleanShot 2025-01-07 at 16.44.25@2x

添加以上权限:Zone:Zone:Read, Zone:DNS:Edit, 和 Account:Cloudflare Tunnel:Edit,保存后会给出一个token,复制该token,后面安装时会用到.

给出的API测试示例如下:

1
2
3
curl -X GET "https://api.cloudflare.com/client/v4/accounts/4005a043825c260305904a1c11eexxxx/tokens/verify" \
     -H "Authorization: Bearer oM9Dp-NCZFzFr5wrw4yUXgzBTCrqYWi99jWxxxxx" \
     -H "Content-Type:application/json"

注意上面account后面的一串字母数字为账户ID,后面也会用到.

部署cloudflare-tunnel ingress

添加helm仓库:

1
2
helm repo add strrl.dev https://helm.strrl.dev
helm repo update

使用helm安装ingress:

1
2
3
4
5
helm upgrade --install --wait \
  -n cloudflare-tunnel-ingress-controller --create-namespace \
  cloudflare-tunnel-ingress-controller \
  strrl.dev/cloudflare-tunnel-ingress-controller \
  --set=cloudflare.apiToken="<cloudflare-api-token>",cloudflare.accountId="<cloudflare-account-id>",cloudflare.tunnelName="<your-favorite-tunnel-name>" 

将之前cloudflare中生成的tokenacouunt id分别替换上面的<cloudflare-api-token><cloudflare-account-id><your-favorite-tunnel-name>为自定义tunnel名称,该tunnel会自动创建,示例名称ingress-tunnel

等待helm安装完之后,使用以下命令可以检查是否已经安装成功:

1
2
3
4
5
6
7
8
> kubectl get po -n cloudflare-tunnel-ingress-controller
NAME                                                    READY   STATUS    RESTARTS   AGE
cloudflare-tunnel-ingress-controller-5d4bc84957-jzl8h   1/1     Running   0          148m

> kubectl get ingressclass
NAME                CONTROLLER                                       PARAMETERS   AGE
cloudflare-tunnel   strrl.dev/cloudflare-tunnel-ingress-controller   <none>       147m
nginx               k8s.io/ingress-nginx                             <none>       15d

创建ingress对外暴露服务

1
2
3
4
> kubectl -n prometheus-stack \
  create ingress grafana-via-cf-tunnel \
  --rule="grafana.xxxx.us.kg/*=prometheus-stack-grafana:80"\
  --class cloudflare-tunnel

其中,grafana.xxxx.us.kg为你的二级域名,prometheus-stack-grafana:80分别是服务名称和端口。

创建完成之后,通过查看ingress,可以获取其状态:

1
2
3
❯ kubectl get ingress -n prometheus-stack
NAME                       CLASS               HOSTS                   ADDRESS                                                 PORTS   AGE
grafana-via-cf-tunnel      cloudflare-tunnel   grafana.xxxx.us.kg   b0d72de6-a176-41fc-bdaa-03e8d60e57f7.cfargotunnel.com   80      90m

此时通过浏览器打开https://grafana.xxxx.us.kg 即可直接访问你的服务。

观察cloudflare-tunnel-ingress-controller命名空间中的资源发现,自动创建了一个对应的deploy:

1
2
3
4
> kubectl get deploy -n cloudflare-tunnel-ingress-controller
NAME                                   READY   UP-TO-DATE   AVAILABLE   AGE
cloudflare-tunnel-ingress-controller   1/1     1            1           153m
controlled-cloudflared-connector       1/1     1            1           152m

cloudflare中的tunnel自动创建出来了,而且新增了一条CNAME的DNS记录.

参考链接