EMQTT StatefulSet 與 k8s 服務發現

用 StatefulSet + Headless Service 部署 EMQTT 叢集,叢集成員透過 Kubernetes API 自動發現,不需要手動填 master IP。這是比 Deployment + HPA 那份 更穩定的做法。

檔案

Headless Service

clusterIP: None 讓每個 Pod 都有獨立的 DNS 記錄,Erlang 節點才能直接互相連線:

apiVersion: v1
kind: Service
metadata:
  name: emqtt
  namespace: emqtt
spec:
  clusterIP: None
  ports:
    - port: 1883
      name: mqtt
    - port: 4369
      name: mapping
  selector:
    app: emqtt

叢集自動發現

關鍵在這幾個環境變數,EMQ 會去問 Kubernetes API 有哪些同伴:

env:
  - name: EMQ_CLUSTER__DISCOVERY
    value: "k8s"
  - name: EMQ_CLUSTER__K8S__APISERVER
    value: "https:\\/\\/kubernetes.default:443"
  - name: EMQ_CLUSTER__K8S__SERVICE_NAME
    value: "emqtt"
  - name: EMQ_CLUSTER__K8S__ADDRESS_TYPE
    value: "ip"
  - name: EMQ_CLUSTER__AUTOHEAL
    value: "on"
  - name: EMQ_CLUSTER__AUTOCLEAN
    value: "5m"

環境變數如何變成設定

start.sh 掃過所有 EMQ_ 開頭的環境變數,把名稱轉成設定檔的鍵再 sedemq.conf

VAR_NAME=$(echo "$VAR" | sed -r "s/EMQ_(.*)=.*/\1/g" \
  | tr '[:upper:]' '[:lower:]' | sed -r "s/__/\./g")

所以 EMQ_CLUSTER__K8S__APISERVER 對應到設定檔裡的 cluster.k8s.apiserver。雙下底線就是設定層級的分隔符號。

腳本同時做了健康監控:連續 5 次(約 25 秒)偵測到 emqttd 沒在執行就讓容器結束,交給 Kubernetes 重啟,而不是無聲地卡住。

部署

kubectl create namespace emqtt
kubectl apply -f mqtt.yaml

# 確認兩個 Pod 都成為叢集成員
kubectl -n emqtt exec emqtt-0 -- emqttd_ctl cluster status

# 擴展
kubectl -n emqtt scale statefulset emqtt --replicas=5

需要更新的地方


← 回到 EMQTT Autoscale

本目錄檔案