跳转到内容
本站为社区维护的非官方中文翻译,与 Cloudflare, Inc. 无关联。本站不提供账户登录,请勿在任何非官方站点输入您的 Cloudflare 账户信息。官方文档:developers.cloudflare.com

在 Docker / Kubernetes 中运行 Mesh

最后更新 查看 MarkdownAgent 设置

cloudflare/mesh ↗ Docker 镜像为 Linux 容器打包了 Cloudflare Mesh 节点。它在基于 Wolfi ↗ 的精简运行时中,以无界面模式运行 Cloudflare One Client 的 warp-svc 守护进程。

使用容器镜像,将 Mesh 节点添加到 Docker Compose 应用栈、Kubernetes 集群和 CI/CD 流水线,无需在主机上安装软件包。

受支持的架构

latest 标签是多平台清单。Docker 会自动选择适合主机架构的镜像。

架构 标签
多架构 latest
x86-64 latest-amd64
ARM64 latest-arm64

前提条件

启动容器前,创建 Mesh 节点并获取其 token。

  1. 在 Cloudflare 仪表板中,前往 Networking(网络) > Mesh。

    前往 Mesh ↗
  2. 选择 Add participant(添加参与者) > Add node(添加节点)。

  3. 输入节点名称(例如 k8s-gateway 或 docker-agent)。

  4. 选择 Create node(创建节点)。

  5. 选择 Kubernetes、Docker Compose 或 Docker CLI。

  6. 按照显示的说明操作。仪表板会隐藏节点 token,但复制的命令需要 token 时会将其包含在内。Docker Compose 配置和 Kubernetes 清单会引用秘密,而不会直接包含 token。

使用具有 Cloudflare One Connectors Write 或 Cloudflare One Connector: WARP Write 权限的 API token,创建节点并获取其连接器 token:

set -euo pipefail

NODE_RESPONSE=$(
	curl --fail-with-body --silent --show-error \
		"https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/warp_connector" \
		--request POST \
		--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
		--header "Content-Type: application/json" \
		--data '{"name":"k8s-gateway"}'
)

jq -e '.success == true and (.result.id | type == "string")' \
	<<< "$NODE_RESPONSE" > /dev/null
NODE_ID=$(jq -r '.result.id' <<< "$NODE_RESPONSE")

TOKEN_RESPONSE=$(
	curl --fail-with-body --silent --show-error \
		"https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/warp_connector/$NODE_ID/token" \
		--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
)

MESH_NODE_TOKEN=$(jq -er \
	'select(.success == true) | .result | select(type == "string" and length > 0)' \
	<<< "$TOKEN_RESPONSE")

安装 jq,然后在运行命令前设置 ACCOUNT_ID 和 CLOUDFLARE_API_TOKEN。命令会在发生 HTTP 或 API 错误时停止。请在命令返回零且设置 NODE_ID 和 MESH_NODE_TOKEN 后再继续。如果创建节点后 token 获取失败,仅使用现有 NODE_ID 重试 token 请求。不要重新执行节点创建请求。将 MESH_NODE_TOKEN 传入容器。

如果这是首个 Mesh 节点,请配置必需的账户设置。你可以使用仪表板向导、API 或 Terraform。

使用 Docker Compose 部署

Docker Compose 是将 Mesh 节点与应用服务一起运行的推荐方式。在 compose.yaml 中添加 cloudflare-mesh 服务:

services:
  cloudflare-mesh:
    image: cloudflare/mesh:latest
    container_name: cloudflare-mesh
    cap_add:
      - NET_ADMIN
      - NET_RAW
    devices:
      - /dev/net/tun:/dev/net/tun
    environment:
      MESH_NODE_TOKEN: ${MESH_NODE_TOKEN}
      SRCNAT_ENABLED: "true"
    sysctls:
      net.ipv4.ip_forward: "1"
      net.ipv6.conf.all.forwarding: "1"
      net.ipv6.conf.default.forwarding: "1"
    volumes:
      - mesh_data:/var/lib/cloudflare-warp
    restart: unless-stopped

volumes:
  mesh_data:

启动应用栈:

MESH_NODE_TOKEN="<YOUR-TOKEN>" docker compose up -d

确认节点已连接:

docker exec cloudflare-mesh warp-cli status

使用 Docker CLI 部署

对于不使用 Compose 的独立容器:

docker run -d \
  --name cloudflare-mesh \
  --cap-add NET_ADMIN \
  --cap-add NET_RAW \
  --device /dev/net/tun \
  --sysctl net.ipv4.ip_forward=1 \
  --sysctl net.ipv6.conf.all.forwarding=1 \
  --sysctl net.ipv6.conf.default.forwarding=1 \
  -e MESH_NODE_TOKEN="$MESH_NODE_TOKEN" \
  -e SRCNAT_ENABLED=true \
  -v mesh_data:/var/lib/cloudflare-warp \
  --restart unless-stopped \
  cloudflare/mesh:latest

在 Kubernetes 上部署

此示例创建具有持久化注册状态的单副本 StatefulSet。它需要允许 NET_ADMIN、NET_RAW 和 /dev/net/tun 主机访问的 Kubernetes 集群(例如 GKE Standard)。

1. 创建 token Secret

kubectl create secret generic cloudflare-mesh \
  --from-literal=MESH_NODE_TOKEN="$MESH_NODE_TOKEN"

2. 应用清单

将以下内容保存为 cloudflare-mesh.yaml:

apiVersion: v1
kind: Service
metadata:
  name: cloudflare-mesh
spec:
  clusterIP: None
  selector:
    app: cloudflare-mesh
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: cloudflare-mesh
spec:
  serviceName: cloudflare-mesh
  replicas: 1
  selector:
    matchLabels:
      app: cloudflare-mesh
  template:
    metadata:
      labels:
        app: cloudflare-mesh
    spec:
      containers:
        - name: mesh
          image: cloudflare/mesh:latest
          env:
            - name: MESH_NODE_TOKEN
              valueFrom:
                secretKeyRef:
                  name: cloudflare-mesh
                  key: MESH_NODE_TOKEN
            - name: SRCNAT_ENABLED
              value: "true"
          securityContext:
            capabilities:
              add:
                - NET_ADMIN
                - NET_RAW
          volumeMounts:
            - name: warp-data
              mountPath: /var/lib/cloudflare-warp
            - name: dev-net-tun
              mountPath: /dev/net/tun
      volumes:
        - name: dev-net-tun
          hostPath:
            path: /dev/net/tun
            type: CharDevice
  volumeClaimTemplates:
    - metadata:
        name: warp-data
      spec:
        accessModes:
          - ReadWriteOnce
        resources:
          requests:
            storage: 1Gi

3. 验证节点

kubectl apply -f cloudflare-mesh.yaml
kubectl rollout status statefulset/cloudflare-mesh
kubectl exec cloudflare-mesh-0 -- warp-cli status

PersistentVolumeClaim 会在 Pod 重启后保留 Mesh 注册。

Kubernetes sidecar

要将应用容器连接到 Mesh,请将 Mesh 镜像作为 sidecar 添加到同一 Pod 中。Pod 中的容器共享网络命名空间,因此 Mesh sidecar 可以将应用连接到 Cloudflare,无需更改应用。

1. 创建 token Secret

为 sidecar 创建单独的 Mesh 节点和 Kubernetes Secret:

kubectl create secret generic cloudflare-mesh-sidecar \
  --from-literal=MESH_NODE_TOKEN="$MESH_NODE_TOKEN"

2. 应用清单

将以下内容保存为 cloudflare-mesh-sidecar.yaml:

apiVersion: v1
kind: Service
metadata:
  name: cloudflare-mesh-sidecar-headless
spec:
  clusterIP: None
  selector:
    app: cloudflare-mesh-sidecar
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: cloudflare-mesh-sidecar
spec:
  serviceName: cloudflare-mesh-sidecar-headless
  replicas: 1
  selector:
    matchLabels:
      app: cloudflare-mesh-sidecar
  template:
    metadata:
      labels:
        app: cloudflare-mesh-sidecar
    spec:
      containers:
        - name: application
          image: busybox:1.37.0
          command:
            - sh
            - -c
            - |
              echo "Hello from the Kubernetes sidecar example" > /tmp/index.html
              httpd -f -p 8080 -h /tmp
          ports:
            - name: http
              containerPort: 8080
        - name: mesh
          image: cloudflare/mesh:latest
          env:
            - name: MESH_NODE_TOKEN
              valueFrom:
                secretKeyRef:
                  name: cloudflare-mesh-sidecar
                  key: MESH_NODE_TOKEN
            - name: SRCNAT_ENABLED
              value: "true"
          securityContext:
            capabilities:
              add:
                - NET_ADMIN
                - NET_RAW
          volumeMounts:
            - name: warp-data
              mountPath: /var/lib/cloudflare-warp
            - name: dev-net-tun
              mountPath: /dev/net/tun
      volumes:
        - name: dev-net-tun
          hostPath:
            path: /dev/net/tun
            type: CharDevice
  volumeClaimTemplates:
    - metadata:
        name: warp-data
      spec:
        accessModes:
          - ReadWriteOnce
        resources:
          requests:
            storage: 1Gi
---
apiVersion: v1
kind: Service
metadata:
  name: cloudflare-mesh-sidecar
spec:
  selector:
    app: cloudflare-mesh-sidecar
  ports:
    - name: http
      port: 8080
      targetPort: http

3. 验证 sidecar

kubectl apply -f cloudflare-mesh-sidecar.yaml
kubectl rollout status statefulset/cloudflare-mesh-sidecar
kubectl exec cloudflare-mesh-sidecar-0 -c mesh -- warp-cli status

运行时配置

参数 描述
MESH_NODE_TOKEN 首次注册时必填。在 Cloudflare 仪表板 ↗中的 Networking(网络) > Mesh 下,或通过 API 创建 token。
SRCNAT_ENABLED 控制源 NAT。默认值为 true。接受 true、false、1 或 0。
/var/lib/cloudflare-warp 存储注册状态。使用卷持久化此路径,以便在重新创建容器后保持稳定的 Mesh 身份。

所需能力和设备

能力 / 设备 需要的原因
NET_ADMIN 创建并配置隧道接口、路由和 nftables 规则。
NET_RAW 启用 ICMP 等原始套接字操作。Docker 通常默认授予此能力,但此处仍显式声明。
/dev/net/tun 创建 WARP TUN 接口。
IP 转发 sysctl 节点为路由子网转发流量时需要。

源 NAT

源 NAT(地址伪装)默认开启(SRCNAT_ENABLED=true)。Mesh 节点接收来自 Cloudflare 边缘的流量并将其转发到本地网络上的目标时,会将源 IP 从 Mesh CGNAT 地址(100.96.x.x)转换为节点自身的本地接口 IP。这确保返回流量正确路由,无需在 VPC 或本地网络中配置静态路由。

仅在连接的网络已具有通往 Mesh IP 范围(100.96.0.0/12)的返回路由时,才设置 SRCNAT_ENABLED=false。返回流量路由的更多详情,请参阅路由。

Kubernetes 上的高可用性

对于带有 CIDR 路由的高可用性部署:

  1. 在多个副本中使用同一个 Mesh 节点 token。
  2. 为每个 Pod 分配自己的 PersistentVolumeClaim。

Cloudflare 以主备模式运行副本。如果活动副本离线,流量会自动故障转移到备用副本。单个副本不提供冗余。

主机名路由

容器支持主机名路由。要通过主机名路由解析 Kubernetes Service,请确保主机名匹配集群实际的 DNS 后缀。默认后缀为 cluster.local,产生类似 service.namespace.svc.cluster.local 的 Service 名称。

站点间网络

在每个站点部署单独的 Mesh 节点容器,为每个节点身份使用单独的节点 token。每个节点应将其本地可访问的子网通告为 CIDR 路由。配置各站点的路由器或工作负载,将发往远程子网的流量通过本地 Mesh 节点发送。

当 SRCNAT_ENABLED=true 时,目标会看到 Mesh 节点的本地地址。禁用源 NAT 时,连接的网络需要通过其 Mesh 节点返回的路由。

故障排除

节点注册为普通 Cloudflare One Client 设备

确认 MESH_NODE_TOKEN 中设置了正确的 Mesh 节点 token。持久卷中现有的注册状态优先;只有明确希望丢弃该注册并创建新身份时,才移除该卷。

warp-cli status 一直显示 Connecting

检查 token、设备配置文件、Gateway 代理、拆分隧道配置、出站防火墙连接和容器日志:

docker logs cloudflare-mesh

无法解析 Kubernetes Service

确认主机名路由匹配集群实际的 DNS 后缀。通常默认后缀为 cluster.local,产生类似 service.namespace.svc.cluster.local 的 Service 名称。

主机名请求到达,但未返回响应

首先检查源 NAT 和返回路由。确认 SRCNAT_ENABLED 设置为 true,或网络具有通往 Mesh IP 范围的返回路由。

检查节点状态

docker exec -it cloudflare-mesh warp-cli status
kubectl exec cloudflare-mesh-0 -- warp-cli status

后续步骤

  • 添加路由 — 使 Mesh 中的任何设备都能访问容器化节点后方的子网。
  • 启用高可用性 — 运行多个副本,提升生产环境的韧性。
  • 从 Workers 连接 — 使用 VPC Network 绑定,从 Cloudflare Workers 访问私有服务。
  • 技巧与最佳实践 — 云 VPC 配置、MTU 调整以及与 Cloudflare Tunnel 并行运行。

这篇文档对您有帮助吗?