节点加入失败常见端口 4369 被占用,如何修改 epmd 端口并重新完成集群组建?

解读

在国内生产环境,尤其是云主机、容器平台或混合部署场景,4369 端口被系统服务、旧 Erlang 节点或其他中间件抢占是 CouchDB 集群扩容失败的高频根因。面试官想验证两点:

  1. 你是否理解 Erlang Port Mapper Daemon(epmd)在 CouchDB 集群发现中的角色;
  2. 能否在不中断现有业务的前提下,优雅地修改 epmd 端口并重新完成节点加入,而不是粗暴地 kill 进程或重启整机。

知识点

  1. epmd 作用:维护 Erlang 节点名称到实际监听端口的映射表,CouchDB 节点通过 TCP 4369 查询彼此。
  2. 环境变量 ERL_EPMD_PORT:启动前导出该变量即可让 epmd 监听新端口,所有节点必须保持一致
  3. systemd 覆盖:国内 CentOS/AlmaLinux 默认用 systemd 管理 CouchDB,需在 /etc/systemd/system/couchdb.service.d/epmd.conf 写入 Environment=ERL_EPMD_PORT=43690,再 systemctl daemon-reload
  4. 防火墙与安全组:腾讯云、阿里云安全组默认只开 4369,需同步放行新端口;iptables/firewalld 同理。
  5. 节点加入命令curl -X POST http://admin:pwd@existing:5984/_cluster_setup -d '{"action":"enable_cluster","bind_address":"0.0.0.0","port":5984,"node_count":3,"username":"admin","password":"pwd"}',完成后 {"action":"add_node","host":"newnode","port":5984}必须保证新旧节点 epmd 端口一致,否则 add_node 报 nxdomainconnection refused
  6. 验证epmd -names -port 43690 应列出所有节点;netstat -lnpt | grep beam 确认 Erlang 监听随机端口与 epmd 映射一致。

答案

  1. 所有节点统一修改 epmd 端口:
    export ERL_EPMD_PORT=43690
    
    写入 /etc/environment 或 systemd 覆盖文件,确保重启仍生效。
  2. 停止 CouchDB 与 epmd:
    systemctl stop couchdb
    epmd -kill   # 若仍有残留
    
  3. 启动新 epmd:
    epmd -daemon -port 43690
    
  4. 启动 CouchDB:
    systemctl start couchdb
    
  5. 在安全组/防火墙放行 43690/tcp
  6. 在已有节点执行:
    curl -X POST http://admin:pwd@existing:5984/_cluster_setup \
         -H "Content-Type: application/json" \
         -d '{"action":"add_node","host":"newnode","port":5984,"username":"admin","password":"pwd"}'
    
  7. 返回 {"ok":true} 后,再 {"action":"finish_cluster"} 完成组建。
  8. 验证:
    curl http://admin:pwd@any:5984/_membership
    
    应看到所有节点状态为 cluster_enabled

拓展思考

  • 零停机迁移:若 4369 已被核心系统占用且不能改,可先在新节点组用 43690 拉起独立集群,再用 _replicator 做全量+增量同步,最后通过应用层双写+蓝绿切换完成迁移,避免业务中断。
  • 容器场景:Kubernetes 下可把 ERL_EPMD_PORT 写进 ConfigMap,通过 StatefulSet 的 headless service 固定 Pod DNS,使节点重启后仍能被找回;同时把 43690 加入 NetworkPolicy 白名单。
  • 监控告警:使用 Prometheus + epmd_exporter 监听新端口,采集 epmd_upepmd_node_count 指标,防止端口再次冲突导致节点“幽灵掉线”。