EMQ X Team 提供了 Helm chart 方便用户在 kubernetes 集群上一键部署 EMQ X [MQTT 服务器](https://www.emqx.io/cn/products/broker), 这是 EMQ X Team 最推荐的在 kubernetes 或 k3s 集群上部署 EMQ X MQTT 服务器的方法。 本文将使用手写 yaml 文件的方法从零开始部署一个 EMQ X MQTT 服务器的 K8S 集群, 分析部署中的细节与技巧,方便用户在实际部署中灵活使用。
阅读本文需要用户了解 kubernetes 的基本概念,并有一个可操作的 kubernetes 集群。
## 在 K8S 上部署单个 EMQ X MQTT服务器节点
### 使用 Pod 直接部署 EMQ X Broker
在Kubernetes中,最小的管理元素不是一个个独立的容器,而是 [Pod](https://kubernetes.io/zh/docs/concepts/workloads/pods/pod-overview/),Pod 是 Kubernetes 应用程序的基本执行单元,即它是 Kubernetes 对象模型中创建或部署的最小和最简单的单元。Pod 表示在 [集群](https://kubernetes.io/zh/docs/reference/glossary/?all=true#term-cluster) 上运行的进程。
EMQ X Broker 在 [docker hub](https://hub.docker.com/r/emqx/emqx) 上提供了镜像, 因此可以很方便的在单个的 pod 上部署 EMQ X Broker,使用 `kubectl run` 命令创建一个运行着 EMQ X Broker 的 Pod:
```
$ kubectl run emqx --image=emqx/emqx:v4.1-rc.1 --generator=run-pod/v1
pod/emqx created
```
查看 EMQ X Broker 的状态:
```
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE
emqx 1/1 Running 0 3m13s
$ kubectl exec emqx -- emqx_ctl status
Node '[email protected]' is started
emqx 4.1-rc.1 is running
```
删除 Pod:
```
$ kubectl delete pods emqx
pod "emqx" deleted
```
Pod 并不是被设计成一个持久化的资源,它不会在调度失败,节点崩溃,或者其他回收中(比如因为资源的缺乏,或者其他的维护中)幸存下来,因此,还需要一个控制器来管理 Pod。
### 使用 Deoloyment 部署 Pod
[Deployment](https://kubernetes.io/zh/docs/concepts/workloads/controllers/deployment/) 为 Pod 和 ReplicaSet 提供了一个声明式定义(declarative)方法,用来替代以前的[ReplicationController](https://www.kubernetes.org.cn/replication-controller-kubernetes) 来方便的管理应用。典型的应用场景包括:
- 定义Deployment来创建Pod和ReplicaSet
- 滚动升级和回滚应用
- 扩容和缩容
- 暂停和继续Deployment
使用 Deployment 部署一个 EMQ X Broker Pod:
+ 定义 Deployment:
```
$ cat deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: emqx-deployment
labels:
app: emqx
spec:
replicas: 1
selector:
matchLabels:
app: emqx
template:
metadata:
labels:
app: emqx
spec:
containers:
- name: emqx
image: emqx/emqx:v4.1-rc.1
ports:
- name: mqtt
containerPort: 1883
- name: mqttssl
containerPort: 8883
- name: mgmt
containerPort: 8081
- name: ws
containerPort: 8083
- name: wss
containerPort: 8084
- name: dashboard
containerPort: 18083
```
+ 部署 Deployment:
```
$ kubectl apply -f deployment.yaml
deployment.apps/emqx-deployment created
```
+ 查看部署情况:
```
$ kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/emqx-deployment 3/3 3 3 74s
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
pod/emqx-deployment-7c44dbd68-8j77l 1/1 Running 0 74s
$ kubectl exec pod/emqx-deployment-7c44dbd68-8j77l -- emqx_ctl status
Node '[email protected]' is started
emqx 4.1-rc.1 is running
```
+ 尝试手动删除 Pod
```
$ kubectl delete pods emqx-deployment-7c44dbd68-8j77l
pod "emqx-deployment-7c44dbd68-8j77l" deleted
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
emqx-deployment-68fcb4bfd6-2nhh6 1/1 Running 0 59s
```
输出结果表明成功用 Deployment 部署了 EMQ X Broker Pod,即使是此 Pod 被意外终止,Deployment 也会重新创建一个新的 Pod。
### 使用 Services 公开 EMQ X Broker Pod 服务
Kubernetes [Pods](https://kubernetes.io/docs/concepts/workloads/pods/pod-overview/) 是有生命周期的。他们可以被创建,而且销毁不会再启动。 如果使用 [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) 来运行应用程序,则它可以动态创建和销毁 Pod。
每个 Pod 都有自己的 IP 地址,但是在 Deployment 中,在同一时刻运行的 Pod 集合可能与稍后运行该应用程序的 Pod 集合不同。
这导致了一个问题:如果使用 EMQ X Broker Pod 为 **MQTT 客户端**提供服务,那么客户端应该如何如何找出并跟踪要连接的 IP 地址,以便客户端使用 EMQ X Broker 服务呢?
答案是:Service
Service 是将运行在一组 [Pods](https://kubernetes.io/docs/concepts/workloads/pods/pod-overview/) 上的应用程序公开为网络服务的抽象方法。
使用 Service 将 EMQ X Broker Pod 公开为网络服务:
+ 定义 Service:
```
$cat service.yaml
apiVersion: v1
kind: Service
metadata:
name: emqx-service
spec:
selector:
app: emqx
ports:
- name: mqtt
port: 1883
protocol: TCP
targetPort: mqtt
- name: mqttssl
port: 8883
protocol: TCP
targetPort: mqttssl
- name: mgmt
port: 8081
protocol: TCP
targetPort: mgmt
- name: ws
port: 8083
protocol: TCP
targetPort: ws
- name: wss
port: 8084
protocol: TCP
targetPort: wss
- name: dashboard
port: 18083
protocol: TCP
targetPort: dashboard
```
+ 部署 Service:
```
$ kubectl apply -f service.yaml
service/emqx-service created
```
+ 查看部署情况
```
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
emqx-service ClusterIP 10.96.54.205 1883/TCP,8883/TCP,8081/TCP,8083/TCP,8084/TCP,18083/TCP 58s
```
+ 使用 Service 提供的 IP 查看 EMQ X Broker 的 API
```
$ curl 10.96.54.205:8081/status
Node [email protected] is started
emqx is running
```
至此,单个 EMQ X Broker 节点在 kubernetes 上部署完毕,通过 Deployment 管理 EMQ X Broker Pod,通过 Service 将 EMQ X Broker 服务暴露出去。
## 通过 kubernetes 自动集