您现在的位置是:首页 >技术杂谈 >EMQX4.x版本-Docker集群部署与Nginx负载均衡网站首页技术杂谈
EMQX4.x版本-Docker集群部署与Nginx负载均衡
安装
版本选用,因为emqx5.x版本不支持tlsv1,因此选用4.x版本。
Docker安装
docker pull emqx/emqx:v4.0.0
docker run -d --name emqx -p 1883:1883 -p 8081:8081 -p 8083:8083 -p 8883:8883 -p 8084:8084 -p 18083:18083 emqx/emqx:v4.0.0
# 1883 MQTT 协议端口
# 8883 MQTT/SSL 端口
# 8083 MQTT/WS 协议端口
# 8084 MQTT/WSS 协议端口
# 18083 Dashboard 管理控制台端口
# 8081 ???
docker exec -it emqx /bin/sh
身份认证
修改配置文件etc/emqx.conf,并配置匿名认证开关allow_anonymous 为false;acl_nomatch为deny
## Allow anonymous authentication by default if no auth plugins loaded.
## Notice: Disable the option in production deployment!
##
## Value: true | false
allow_anonymous = false
## Allow or deny if no ACL rules matched.
##
## Value: allow | deny
acl_nomatch = deny
启用内置身份校验插件emqx_auth_username,需在 EMQX 启动时就默认启动某插件,则直接在 data/loaded_plugins
添加需要启动的插件名称。
{emqx_management, true}.
{emqx_recon, true}.
{emqx_retainer, true}.
{emqx_dashboard, true}.
{emqx_rule_engine, true}.
{emqx_bridge_mqtt, false}.
{emqx_auth_username, true}. ## 加这一行,备注不要加
然后配置身份校验的用户名和密码,修改文件etc/plugins/emqx_auth_username.conf
# 之后可能需要用到acl,因此这里加两个用户
auth.user.1.username = root
auth.user.1.password = zhkjhivemqroot@00239
auth.user.2.username = user
auth.user.2.password = zhkjhivemquser@002396
连接测试(这里使用mosquitto进行测试)
mosquitto_sub -h 10.27.106.14 -t '/device/1123/upward' -u root -p 1883 -P zhkjhivemqroot@002396
mosquitto_pub -h 10.27.106.14 -t '/device/1123/upward' -u root -p 1883 -P zhkjhivemqroot@002396 -m "hello"
能够在订阅界面获取到对应的消息,说明订阅和发布都成功了。
这里遇到一个坑,通过配置文件配置的用户名密码,没法通过配置文件进行修改,需要通过HTTP API修改。
更改指定用户名的密码
指定用户名,传递新密码进行更改,再次连接时需要使用新密码进行连接:
API 定义:
# Request
PUT api/v4/auth_username/${username}
{
"password": "emqx_new_p"
}
# Response
{
"code": 0
}
查看指定用户名信息
指定用户名,查看相关用户名、密码信息,注意此处返回的密码是使用配置文件指定哈希方式加密后的密码:
API 定义:
# Request
GET api/v4/auth_username/${username}
# Response
{
"code": 0,
"data": {
"username": "emqx_u",
"password": "091dc8753347e7dc5d348508fe6323735eecdb84fa800548870158117af8a0c0"
}
}
TLS认证开启
生成秘钥文件的配置文件openssl.cnf内容如下:
# CA key
openssl genrsa -out ca.key 2048
# CA csr
openssl req -new -subj "/CN=ca" -key ca.key -out ca.csr
# CA crt
openssl x509 -req -in ca.csr -out ca.crt -signkey ca.key -days 3650
# server key
openssl genrsa -out server.key 2048
# server.csr
openssl req -new -subj "/CN=aec.starnetuc.com" -key server.key -out server.csr
# server.crt
openssl x509 -req -in server.csr -out server.crt -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650
# server.crt verify
openssl verify -CAfile ca.crt server.crt
# client key
openssl genrsa -out client.key 2048
# client.csr
openssl req -new -subj "/CN=aec.starnetuc.com" -key client.key -out client.csr
# client.crt
openssl x509 -req -in client.csr -out client.crt -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650
# client.crt verify
openssl verify -CAfile ca.crt client.crt
## 一次性复制
openssl genrsa -out ca.key 2048
openssl req -new -subj "/CN=ca" -key ca.key -out ca.csr
openssl x509 -req -in ca.csr -out ca.crt -signkey ca.key -days 3650
openssl genrsa -out server.key 2048
openssl req -new -subj "/CN=aec.starnetuc.com" -key server.key -out server.csr
openssl x509 -req -in server.csr -out server.crt -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650
openssl verify -CAfile ca.crt server.crt
openssl genrsa -out client.key 2048
openssl req -new -subj "/CN=aec.starnetuc.com" -key client.key -out client.csr
openssl x509 -req -in client.csr -out client.crt -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650
openssl verify -CAfile ca.crt client.crt# 生成 CA key
openssl genrsa -out ca.key 2048
# 生成 EMQX 的根证书
openssl req -x509 -new -subj "/CN=aec.starnetuc.com" -nodes -key ca.key -sha256 -days 3650 -out ca.pem
# 查看 CA 证书信息(可选):
openssl x509 -in ca.pem -noout -text
# 生成 EMQX 的 key 即 服务端的key
openssl genrsa -out emqx.key 2048
# 生成 EMQX 服务端的csr文件
openssl req -new -key ./emqx.key -config openssl.cnf -out emqx.csr
# 根证书来签发 EMQX 的实体证书证书
openssl x509 -req -in ./emqx.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out emqx.pem -days 3650 -sha256 -extensions v3_req -extfile openssl.cnf
# 查看 EMQX 实体证书(可选):
openssl x509 -in emqx.pem -noout -text
# 验证 EMQX 实体证书,确定证书是否正确
openssl verify -CAfile ca.pem emqx.pem
准备好证书后,我们就可以启用 EMQX 的 TLS/SSL 功能了。
将以上所有文件拷贝到 EMQX 某个目录,这里我放的是/opt/emqx/tls-conf下,并参考如下配置修改 emqx.conf
## Path to the file containing the user's private PEM-encoded key.
##
## See: http://erlang.org/doc/man/ssl.html
##
## Value: File
listener.ssl.external.keyfile = /opt/emqx/tls-conf/server.key
## Path to a file containing the user certificate.
##
## See: http://erlang.org/doc/man/ssl.html
##
## Value: File
listener.ssl.external.certfile = /opt/emqx/tls-conf/server.crt
## Path to the file containing PEM-encoded CA certificates. The CA certificates
## are used during server authentication and when building the client certificate chain.
##
## Value: File
listener.ssl.external.cacertfile = /opt/emqx/tls-conf/ca.crt
# 开启对端验证,并强制要求客户端提供证书
## A server only does x509-path validation in mode verify_peer,
## as it then sends a certificate request to the client (this
## message is not sent if the verify option is verify_none).
## You can then also want to specify option fail_if_no_peer_cert.
## More information at: http://erlang.org/doc/man/ssl.html
##
## Value: verify_peer | verify_none
listener.ssl.external.verify = verify_peer
## Used together with {verify, verify_peer} by an SSL server. If set to true,
## the server fails if the client does not have a certificate to send, that is,
## sends an empty certificate.
##
## Value: true | false
listener.ssl.external.fail_if_no_peer_cert = true
当配置完成并重启 EMQX 后。
连接测试(这里使用mosquitto进行测试)
mosquitto_pub -h aec.starnetuc.com -t /device/1123/upward -u root -p 8883 -P zhkjhivemqroot@002396 --cafile /home/data/mosquitto/tls-conf/ca.crt --cert /home/data/mosquitto/tls-conf/client.crt --key /home/data/mosquitto/tls-conf/client.key -m "hello word"
mosquitto_sub -h aec.starnetuc.com -t /device/1123/upward -u root -p 8883 -P zhkjhivemqroot@002396 --cafile /home/data/mosquitto/tls-conf/ca.crt --cert /home/data/mosquitto/tls-conf/client.crt --key /home/data/mosquitto/tls-conf/client.key
支持多个版本的TLS
默认情况下emqx支持tlsv1.2,要同时支持其他版本,需要在etc/emqx.conf
新增以下参数
## TLS versions only to protect from POODLE attack.
##
## See: http://erlang.org/doc/man/ssl.html
##
## Value: String, seperated by ','
listener.ssl.external.tls_versions = tlsv1.2,tlsv1.1,tlsv1
这样emqx就能够支持tlsv1.2,tlsv1.1,tlsv1三个版本了。
常用命令
emqx restart
# 设置日志级别,临时的,容器重启就没了
emqx_ctl log set-level debug
集群部署
这里是调研,因此采用最简单的手动(manual)方式来管理集群,manual也是默认方式。
EMQ X 默认开启的 MQTT 服务 TCP 端口:
端口 | 说明 |
---|---|
1883 | MQTT 协议端口 |
8883 | MQTT/SSL 端口 |
8083 | MQTT/WebSocket 端口 |
8084 | MQTT/WebSocket/SSL 端口 |
8081 | 管理 API 端口 |
18083 | Dashboard 端口 |
防火墙根据使用的 MQTT 接入方式,开启上述端口的访问权限。
EMQ X 节点集群使用的 TCP 端口:
端口 | 说明 |
---|---|
4369 | 集群节点发现端口 |
5369 | 集群节点 PRC 通道 |
6369 | 集群节点控制通道 |
集群节点间如有防护墙,需开启上述 TCP 端口互访权限。
集群节点如下
节点名 | 主机名 (FQDN) | IP 地址 |
---|---|---|
emqx@10.27.106.14 | - | 10.27.106.14 |
emqx@10.27.106.200 | - | 10.27.106.200 |
注意: 节点名格式为Name@Host, Host 必须是 IP 地址或 FQDN (主机名。域名)
以14为例,部署方式需要进行变更,如下:
docker run -d --network host --name emqx
-e EMQX_LISTENER__TCP__EXTERNAL=1883
-e EMQX_NAME=emqx
-e EMQX_HOST=10.27.106.14
-e EMQX_MANAGEMENT__LISTENER__HTTP=18080
-e EMQX_CLUSTER__NAME=aec_emqx_cluster
-e EMQX_CLUSTER__DISCOVERY=manual
-e EMQX_NODE__DIST_LISTEN_MIN=6369
-e EMQX_NODE__DIST_LISTEN_MAX=7369
-e EMQX_NODE__COOKIE=emqxsecretcookie
emqx/emqx:v4.0.0
注意:
- EMQX_NODE__COOKIE和EMQX_CLUSTER__NAME在集群内部要保持一致
1、配置节点名称
配置emqx@10.27.106.14节点,修改emqx/etc/emqx.conf:
node.name = emqx@10.27.106.14
注意: 节点启动加入集群后,节点名称不能变更。
配置emqx@10.27.106.200节点,修改emqx/etc/emqx.conf:
node.name = emqx@10.27.106.200
2、节点加入集群
启动两个节点之后,任选一个节点,加入另一个节点的集群
这里选择14去加入200
emqx_ctl cluster join emqx@10.27.106.200
Join the cluster successfully.
Cluster status: #{running_nodes => ['emqx@10.27.106.14','emqx@10.27.106.200'],
stopped_nodes => []}
在任意节点上查询集群状态:
emqx_ctl cluster status
Cluster status: #{running_nodes => ['emqx@10.27.106.14','emqx@10.27.106.200'],
stopped_nodes => []}
说明集群部署成功了。
集群效果为:
当某个客户端1连接节点A订阅的主题,在其他的节点收到消息之后,节点A也能够收到消息然后通知给客户端1。
补充退出节点的命令
emqx_ctl cluster leave
Nginx负载均衡
安装时,需要额外编译nginx的其他模块,因此在执行./configure
时需要携带额外参数
## 其中--with-stream --with-http_ssl_module --with-stream_ssl_module为额外参数
./configure --with-stream --with-http_ssl_module --with-stream_ssl_module --prefix=/usr/local/nginx
编译完成之后对nginx.conf进行配置,需要加入的配置如下:
stream {
upstream stream_backend {
hash $remote_addr;
server 10.27.106.14:1883 max_fails=2 fail_timeout=30s;
server 10.27.106.200:1883 max_fails=2 fail_timeout=30s;
# server 192.168.0.3:1883 max_fails=2 fail_timeout=30s;
}
server {
listen 38888 ssl;
proxy_pass stream_backend;
proxy_buffer_size 4k;
ssl_handshake_timeout 15s;
ssl_certificate /home/data/emqx/tls-conf/server.crt;
ssl_certificate_key /home/data/emqx/tls-conf/server.key;
}
}
## 其中ssl_certificate与emqx的certificate一致
## ssl_certificate_key与key文件一致
这里Nginx将会终结TLS。