1. 为什么要在K8s上部署EMQX?
EMQX作为一款开源的大规模分布式MQTT消息服务器,在物联网和实时消息领域有着广泛应用。而Kubernetes(K8s)作为容器编排的事实标准,为EMQX的部署带来了诸多优势:
- 弹性伸缩:K8s可以根据消息负载自动扩缩容EMQX节点
- 高可用保障:通过K8s的Pod调度和健康检查机制确保服务连续性
- 资源利用率提升:共享K8s集群资源,避免独立部署的资源浪费
- 运维简化:统一的配置管理和部署流程
但在实际生产环境中,数据持久化是K8s部署EMQX时最关键的挑战之一。EMQX的核心数据包括:
- 客户端会话状态(Session)
- 消息队列(Message Queue)
- 订阅关系(Subscription)
- 插件数据(如规则引擎、认证数据等)
这些数据一旦丢失,将导致客户端重连、消息丢失等严重问题。接下来我将分享经过生产验证的完整部署方案。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 部署前的环境准备
2.1 K8s集群要求
建议使用以下配置的K8s集群:
- 版本:v1.20+
- 网络插件:Calico/Flannel(需支持NetworkPolicy)
- 存储类:支持动态供给的StorageClass
- 资源配额:每个EMQX节点至少需要
- CPU: 2核
- 内存: 4GB
- 存储: 20GB(根据消息保留策略调整)
注意:EMQX集群节点间通信需要开放4370(Erlang分布式端口)和5369(集群RPC端口)
2.2 持久化存储选型
根据实际场景选择合适的存储方案:
| 存储类型 | 适用场景 | 性能表现 | 注意事项 |
|---|---|---|---|
| Local PV | 高性能需求 | 最佳 | 需保证节点稳定性 |
| Ceph RBD | 生产推荐 | 良好 | 需要Ceph集群 |
| NFS | 测试环境 | 一般 | 存在单点风险 |
| EBS/GPD | 云环境 | 良好 | 注意区域限制 |
我们生产环境选择Ceph RBD,因其兼具性能和可靠性。以下是StorageClass示例配置:
yaml复制apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: emqx-data
provisioner: rbd.csi.ceph.com
parameters:
clusterID: ceph-cluster
pool: rbd
imageFormat: "2"
imageFeatures: layering
csi.storage.k8s.io/provisioner-secret-name: csi-rbd-secret
csi.storage.k8s.io/provisioner-secret-namespace: default
reclaimPolicy: Retain
allowVolumeExpansion: true
3. EMQX集群部署实战
3.1 Helm Chart定制化安装
推荐使用官方Helm Chart进行部署:
bash复制helm repo add emqx https://repos.emqx.io/charts
helm repo update
创建values.yaml配置文件,关键参数说明:
yaml复制replicaCount: 3 # 节点数量
persistence:
enabled: true
storageClass: "emqx-data"
size: 20Gi
accessModes: ["ReadWriteOnce"]
resources:
requests:
cpu: "2"
memory: "4Gi"
limits:
cpu: "4"
memory: "8Gi"
emqxConfig:
EMQX_NAME: "emqx-cluster"
EMQX_CLUSTER__DISCOVERY: "k8s"
EMQX_CLUSTER__K8S__APISERVER: "https://kubernetes.default.svc:443"
EMQX_CLUSTER__K8S__SERVICE_NAME: "emqx-headless"
EMQX_CLUSTER__K8S__NAMESPACE: "default"
EMQX_LISTENER__TCP__EXTERNAL: 1883
执行安装命令:
bash复制helm install emqx emqx/emqx -f values.yaml
3.2 集群状态验证
部署完成后,检查集群状态:
bash复制kubectl exec -it emqx-0 -- emqx_ctl cluster status
预期输出应显示所有节点均为"healthy"状态:
code复制Cluster status: #{running_nodes => ['emqx@emqx-0.emqx-headless.default.svc.cluster.local',
'emqx@emqx-1.emqx-headless.default.svc.cluster.local',
'emqx@emqx-2.emqx-headless.default.svc.cluster.local'],
stopped_nodes => []}
3.3 网络暴露配置
根据实际需求选择服务暴露方式:
-
NodePort(测试环境):
yaml复制service: type: NodePort ports: mqtt: 31883 -
LoadBalancer(云环境):
yaml复制service: type: LoadBalancer annotations: service.beta.kubernetes.io/aws-load-balancer-type: "nlb" -
Ingress(需要TLS终止):
yaml复制ingress: enabled: true hosts: - host: mqtt.example.com paths: ["/"] tls: - secretName: emqx-tls hosts: - mqtt.example.com
4. 数据持久化深度配置
4.1 核心数据持久化策略
EMQX的持久化数据主要分为三类,需要分别配置:
-
消息存储:
yaml复制emqxConfig: EMQX_PERSISTENT_MESSAGE_STORE: "on" EMQX_PERSISTENT_MESSAGE_STORE__BACKEND: "leveldb" EMQX_PERSISTENT_MESSAGE_STORE__LEVELDB__DIR: "/opt/emqx/data/message" -
会话存储:
yaml复制emqxConfig: EMQX_SESSION_PERSISTENCE: "on" EMQX_SESSION_PERSISTENCE__BACKEND: "mnesia" EMQX_SESSION_PERSISTENCE__MNESIA__DIR: "/opt/emqx/data/session" -
插件数据:
yaml复制volumes: - name: plugin-data persistentVolumeClaim: claimName: emqx-plugin-data volumeMounts: - mountPath: "/opt/emqx/data/plugins" name: plugin-data
4.2 存储扩容实战
当需要扩容存储时,按以下步骤操作:
-
编辑PVC扩容请求:
bash复制
kubectl edit pvc emqx-data-emqx-0修改
spec.resources.requests.storage字段 -
执行文件系统扩容(针对块存储):
bash复制kubectl exec -it emqx-0 -- df -h /opt/emqx/data kubectl exec -it emqx-0 -- resize2fs /dev/pv-emqx-data
重要:扩容期间应避免节点重启,建议逐个节点操作
4.3 备份与恢复方案
-
定期快照备份:
bash复制# 创建快照 kubectl exec -it emqx-0 -- tar czvf /tmp/emqx-backup-$(date +%Y%m%d).tar.gz /opt/emqx/data # 拷贝到本地 kubectl cp emqx-0:/tmp/emqx-backup-20230801.tar.gz ./ -
灾难恢复流程:
- 创建与原PVC相同配置的新PVC
- 将备份文件解压到新PVC挂载路径
- 修改Deployment指向新PVC
- 滚动更新Pod
5. 生产环境调优指南
5.1 性能关键参数
在values.yaml中添加以下调优参数:
yaml复制emqxConfig:
EMQX_LISTENER__TCP__EXTERNAL__MAX_CONNECTIONS: 100000
EMQX_LISTENER__SSL__EXTERNAL__MAX_CONNECTIONS: 50000
EMQX_ZONE__EXTERNAL__MAX_SUBSCRIPTIONS: 100
EMQX_ZONE__EXTERNAL__MAX_INFLIGHT: 32
EMQX_MQTT__MAX_PACKET_SIZE: "10MB"
EMQX_LOG__LEVEL: "warning"
5.2 监控与告警配置
-
启用Prometheus监控:
yaml复制prometheus: enabled: true serviceMonitor: enabled: true interval: 15s -
关键监控指标告警规则示例:
yaml复制- alert: HighConnectionRate expr: rate(emqx_connections_count[1m]) > 1000 for: 5m labels: severity: critical annotations: summary: "High connection rate detected ({{ $value }} connections/sec)"
5.3 常见问题排查
问题1:集群节点无法发现
-
检查项:
bash复制kubectl get endpoints emqx-headless kubectl logs emqx-0 | grep "cluster" -
解决方案:
确保headless服务DNS解析正常,检查网络策略是否允许4370/5369端口通信
问题2:存储性能瓶颈
- 现象:消息发布延迟高,EMQX日志出现"write timeout"
- 优化方案:
- 改用本地SSD存储
- 调整leveldb参数:
yaml复制EMQX_PERSISTENT_MESSAGE_STORE__LEVELDB__WRITE_BUFFER_SIZE: "64MB" EMQX_PERSISTENT_MESSAGE_STORE__LEVELDB__CACHE_SIZE: "512MB"
经过生产环境验证,这套方案可以支撑10万+的MQTT连接,消息吞吐量达到50K/s。关键在于:
- 合理规划存储容量和性能
- 完善的监控覆盖
- 定期的备份演练
最后分享一个实用技巧:在K8s环境中,可以通过给EMQX Pod添加以下annotation实现优雅终止:
yaml复制annotations:
lifecycle.preStop.exec.command: ["/opt/emqx/bin/emqx_ctl", "cluster", "leave"]
这能确保节点在终止前主动退出集群,避免脑裂问题。
