RabbitMQ SSL证书自动续期后无法重载SSL缓存问题求助
基础部署信息
- VPS云服务器部署RabbitMQ社区版Docker容器
- 宿主机通过Let's Encrypt签发SSL证书,证书目录以挂载方式映射到容器内使用
- 证书自动续期采用webroot校验模式:将宿主机目录绑定挂载到容器内
/plugins/rabbitmq_management-{rmq-version}/priv/www路径,续期时--webroot-path参数指定为该目录,利用Cowboy静态资源服务完成域名所有权校验,全程无需停止RabbitMQ服务。
故障表现
证书续期流程执行成功后,不重启Docker容器的前提下,RabbitMQ始终无法加载新证书。
尝试通过清除RabbitMQ证书缓存的方案修复时,执行命令抛出如下报错:
unable to connect to epmd (port 4369) on {cluster-name}.localdomain: nxdomain (non-existing domain)
对照排查指引检查服务器/etc/hosts文件,发现当前仅配置了127.0.0.1 localhost条目,缺少localhost.localdomain相关配置,排查中断。
修复步骤
1. 先解决epmd连接报错
该报错本质是RabbitMQ CLI工具默认会将当前主机名拼接.localdomain后缀,尝试连接4369端口的epmd服务,hosts中无对应解析就会返回nxdomain错误。
两种修复方式二选一即可:
- 临时修复:进入容器编辑
/etc/hosts,在127.0.0.1那行追加配置,修改后内容如下:127.0.0.1 localhost localhost.localdomain <容器实际hostname> - 永久修复:启动容器时通过
--hostname参数指定固定主机名,同时在启动参数中追加--add-host <你的hostname>.localdomain:127.0.0.1,避免容器重建后配置丢失。
配置完成后在容器内执行epmd -names,能正常返回4369端口下的RabbitMQ节点注册信息,即代表解析修复完成。
2. 触发SSL证书热重载,无需重启容器
仅清除PEM缓存不足以让RabbitMQ加载新证书,需要主动触发SSL监听器的上下文重载:
- 进入RabbitMQ容器内部:
docker exec -it <你的RabbitMQ容器名称> bash - 执行证书重载命令:
rabbitmqctl eval 'ssl:clear_pem_cache(), {ok, SslOpts} = application:get_env(rabbit, ssl_options), rabbit_networking:reload_ssl_context(SslOpts).' - 验证加载结果:执行openssl命令校验AMQPS端口证书有效期
返回的openssl s_client -connect 127.0.0.1:5671 -servername <你的证书绑定域名> | openssl x509 -noout -datesnotAfter时间为新证书的到期时间,即代表加载成功。
3. 配置续期自动重载
在Let's Encrypt的续期配置中增加--deploy-hook参数,指定续期成功后自动执行重载命令,参考命令如下(在宿主机执行即可,无需进容器):
docker exec <你的RabbitMQ容器名称> rabbitmqctl eval 'ssl:clear_pem_cache(), {ok, SslOpts} = application:get_env(rabbit, ssl_options), rabbit_networking:reload_ssl_context(SslOpts).'
配置完成后后续证书自动续期完成后,会自动触发证书重载,全程无需人工操作、无需重启容器。
注意:如果挂载Let's Encrypt证书时直接挂载的是
live目录下的证书文件,由于Let's Encrypt续期后会替换符号链接指向,Docker挂载的符号链接可能不会自动跟随指向新文件,建议直接挂载/etc/letsencrypt/archive/<你的域名>目录下的实际证书文件,避免符号链接导致的文件读取异常。
内容的提问来源于stack exchange,提问作者Uche Ozoemena

