在 K8s 叢集中建立 DERP 伺服器

東風微鳴雲原生發表於2022-11-23

前言

本文的目的是在 K8s 叢集內搭建 Tailscale 的 DERP 伺服器。

背景知識

Tailscale

Tailscale 允許您輕鬆管理對私有資源的訪問(本質上是個 VPN 工具),快速 SSH 進入網路上的裝置,並且可以在世界上的任何地方安全地工作。

在您的裝置、虛擬機器和伺服器之間建立一個安全的 WireGuard 網狀網路 -- 即使它們被防火牆或子網隔開。

DERP

Tailscale 執行 DERP 中繼伺服器來幫助連線您的節點。除了使用 tailscale 提供的 DERP 伺服器之外,您還可以執行自己的伺服器。

Tailscale 執行分佈在世界各地的 DERP 中繼伺服器,將您的 Tailscale 節點點對點作為 NAT 遍歷期間的一個邊通道,並作為 NAT 遍歷失敗和無法建立直接連線的備用。

Tailscale 在許多地方執行 DERP 伺服器。截至 2022 年 9 月,這份名單包括:

  • Australia (Sydney)
  • Brazil (São Paulo)
  • Canada (Toronto)
  • Dubai (Dubai)
  • France (Paris)
  • Germany (Frankfurt)
  • Hong Kong (Hong Kong)
  • India (Bangalore)
  • Japan (Tokyo)
  • Netherlands (Amsterdam)
  • Poland (Warsaw)
  • Singapore (Singapore)
  • South Africa (Johannesburg)
  • Spain (Madrid)
  • United Kingdom (London)
  • United States (Chicago, Dallas, Denver, Honolulu, Los Angeles, Miami, New York City, San Francisco, and Seattle)

?Notes:

不包括中國。

Tailscale 客戶端自動選擇最近的低延遲中繼。為了提供低延遲連線,Tailscale 正在根據需要不斷擴充套件和增加更多的 DERP 伺服器。

為了實現低延遲穩定性, 因此需要搭建 DERP 伺服器。

步驟

根據最後參考文件中的任選一份最簡的 docker-compose 配置,轉換為 K8s 的配置(可以使用工具:kompose 轉換), 轉換後的配置如下:

?Notes:

為了方便以 Env 方式配置域名,這裡使用了 StatefulSets.

---
apiVersion: v1
kind: Service
metadata:
  name: derper-tok
  labels:
    io.kompose.service: derper-tok
spec:
  ports:
  - port: 443
    name: https
  - port: 80
    name: http
  - protocol: UDP
    port: 3478
    name: stun
  clusterIP: None
  selector:
    io.kompose.service: derper-tok
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  annotations:
    kompose.cmd: kompose convert -f docker-compose.yml
    kompose.version: 1.26.1 (a9d05d509)
  labels:
    io.kompose.service: derper-tok
  name: derper-tok
  namespace: tailscale
spec:
  replicas: 3
  selector:
    matchLabels:
      io.kompose.service: derper-tok
  serviceName: derper-tok
  template:
    metadata:
      annotations:
        kompose.cmd: kompose convert -f docker-compose.yml
        kompose.version: 1.26.1 (a9d05d509)
      labels:
        io.kompose.service: derper-tok
    spec:
      containers:
      - env:
        - name: MY_POD_NAME
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: metadata.name
        - name: DOMAIN
          value: example.com
        - name: DERP_ADDR
          value: :443
        - name: DERP_CERT_DIR
          value: /app/certs
        - name: DERP_CERT_MODE
          value: letsencrypt
        - name: DERP_DOMAIN
          value: $(MY_POD_NAME).$(DOMAIN)
        - name: DERP_HTTP_PORT
          value: "80"
        - name: DERP_STUN
          value: "true"
        - name: DERP_VERIFY_CLIENTS
          value: "true"
        image: fredliang/derper:latest
        imagePullPolicy: Always
        name: derper-tok
        securityContext:
          capabilities:
            add:
            - NET_ADMIN
          privileged: true
        volumeMounts:
        - mountPath: /var/run/tailscale/tailscaled.sock
          name: tailscale-socket
      hostNetwork: true
      volumes:
      - hostPath:
          path: /run/tailscale/tailscaled.sock
          type: Socket
        name: tailscale-socket
  updateStrategy:
    rollingUpdate:
      partition: 0
    type: RollingUpdate

具體說明如下:

  • 為什麼用 StatefulSets, 而不是 Deployment 或 DaemonSet, 主要是我自己的期望如下:

    • 希望可以使用 derper-tok-{1..3}.example.com 這樣的域名,這樣的話,使用 StatefulSets 的話,derper-tok-1 就是 POD Name, 方便配置。
    • 如果用 Deployment 或 DaemonSet, Pod name 隨機,域名就需要想辦法一個一個配置了。
  • 這裡 K8s 的 Service 純粹是因為建立 StatefulSets 需要一個 service 而已,實際上並沒用到
  • 透過 MY_POD_NAME DOMAIN DERP_DOMAIN 就將域名根據 POD name 組合起來了
  • DERP_CERT_MODE 現在新版的 DERP 支援 let's encrypt 自動申請證書,比之前方便很多
  • DERP_VERIFY_CLIENTS: true 保證只有自己能使用自己的 DERP 伺服器,需要配合 tailscale 使用
  • fredliang/derper:latest 映象直接是使用的該映象
  • securityContext 需要確保有 NET_ADMIN 的能力,privileged: true 也最好加上保證更大的許可權。
  • hostNetwork: true 直接使用主機網路,也就是:443, 3478 埠直接監聽 K8s Node 的埠,簡單粗暴。如果埠有衝突需要調整埠,或者不要使用這種模式。
  • volumeMountsvolumes: 這裡我安裝的 tailscale 在該 K8s Node 上的 socket 為:/run/tailscale/tailscaled.sock, 將其掛載到 DERP 容器的 /var/run/tailscale/tailscaled.sock, 配合 DERP_VERIFY_CLIENTS: true, DERP 伺服器就會自動驗證客戶端,保證安全。

就這樣,kubectl apply 即可。

???

總結

本文比較純粹,就是說明了一個場景:在 K8s 中安裝 DERP 伺服器。相關的上下文介紹不多,感興趣的可以自行了解。

後面有時間可能會出一篇 K8s 中安裝 tailscale 的文章。

安裝完成後,在 tailscale 控制檯上配置 ACL, 加入本次新建的幾個 DERP 域名到 derpMap 即可。
最後可以透過:tailscale netcheck 進行驗證。

參考文件

本文由部落格一文多發平臺 OpenWrite 釋出!

相關文章