You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将VM上的Consul客户端接入Kubernetes中的Consul集群?

问题:外部VM的Consul客户端无法加入K8s内的Consul集群

环境说明

  • 物理服务器上运行4台VM:
    • k8s master
    • k8s worker 1(IP:192.168.1.207)
    • k8s worker 2(IP:192.168.1.208)
    • vm1(外部VM,IP:192.168.1.230)
  • 通过Helm Chart在K8s集群部署Consul,每个worker节点运行1个server和1个client,集群内部服务发现正常。

当前Consul Helm配置

global:
  name: consul
  enabled: true
  datacenter: dc1
  gossipEncryption:
    autoGenerate: true
  tls:
    enabled: true
    enableAutoEncrypt: true
    verify: true
  acls:
    manageSystemACLs: true
# client:
#   exposeGossipPorts: true
server:
  replicas: 2
  # exposeGossipAndRPCPorts: true
  # ports:
  #   serflan:
  #     port: 9301
  extraConfig: |
    { "log_level": "debug" }
  exposeService:
    enabled: true
    type: NodePort
    nodePort:
      http: 31500 # 8500 + 23k
      https: 31501 # 8501 + 23k
      grpc: 31503 # 8503 + 23k
      serf: 32301 # 9301 + 23k
      rpc: 31300 # 8300 + 23k
  securityContext:
    runAsNonRoot: false
    runAsUser: 0
  storageClass: nfs-synology-test
connectInject:
  enabled: true
controller:
  enabled: true
syncCatalog:
  enabled: true
dns:
  enabled: true

外部VM(vm1)的Consul客户端配置

{
  "server": false,
  "domain": "consul",
  "datacenter": "dc1",
  "data_dir": "/etc/consul/data",
  "tls": {
    "defaults": {
      "ca_file": "/etc/consul/tls/ca/tls.crt",
      "verify_incoming": false,
      "verify_outgoing": true
    },
    "internal_rpc": {
      "verify_server_hostname": true
    }
  },
  "auto_encrypt": { "tls": true },
  "encrypt": "redacted",
  "log_level": "DEBUG",
  "enable_syslog": true,
  "leave_on_terminate": true,
  "retry_join": [
    "192.168.1.207:32301",
    "192.168.1.208:32301",
    "10.233.94.138:8300",
    "10.233.119.94:8300"
  ],
  "advertise_addr": "192.168.1.230",
  "bind_addr": "0.0.0.0",
  "ports": { "server": 31300 },
  "acl": {
    "tokens": {
      "agent": "redacted",
      "default": "redacted"
    }
  }
}

ACL策略(用于客户端token)

node_prefix "" {
  policy = "write"
}
service_prefix "" {
  policy = "read"
}

遇到的错误

  • UDP连接失败
  • 客户端自动尝试连接K8s内部集群IP(未加入retry_join列表)
  • 超时错误,以及rpc error: lead thread didn't get connection

解决方案

1. 补全Gossip的UDP端口暴露

Consul的Serf Gossip同时依赖UDP和TCP,你当前只暴露了TCP端口,需要在Helm配置中新增UDP端口映射:

server:
  exposeService:
    enabled: true
    type: NodePort
    nodePort:
      # ... 保留原有端口配置
      serfUdp: 32302    # 新增:UDP 9301映射到NodePort 32302

更新后重新部署:helm upgrade consul hashicorp/consul -f your-values.yaml

2. 清理无效的retry_join地址

删掉K8s内部Cluster IP(10.233.x.x),这些地址对外部VM不可访问,修改客户端的retry_join为:

"retry_join": [
  "192.168.1.207:32301",
  "192.168.1.208:32301"
]

3. 删除客户端无用的端口配置

客户端节点不需要ports.server配置,直接删掉这一行,避免混淆:

// 移除该行
"ports": { "server": 31300 },

4. 补充ACL权限

当前策略缺少客户端注册自身agent的权限,更新ACL策略:

node_prefix "" {
  policy = "write"
}
service_prefix "" {
  policy = "read"
}
agent_prefix "" {
  policy = "write"
}

重新生成token并替换客户端配置中的acl.tokens值。

5. 验证网络连通性

在vm1上执行以下命令确认端口可达:

# 验证UDP Gossip端口
nc -uvz 192.168.1.207 32302
nc -uvz 192.168.1.208 32302

# 验证TCP RPC端口
nc -vz 192.168.1.207 31300

6. 修正Consul Server的宣告地址

确保K8s内的Consul Server对外宣告Worker节点的外部IP,在Helm配置中添加:

server:
  extraConfig: |
    { 
      "log_level": "debug",
      "advertise_addr": "{{ GetInterfaceIP \"eth0\" }}"
    }

如果Worker节点IP是静态的,也可以直接写死IP,比如"advertise_addr": "192.168.1.207"(每个server对应自身Worker节点IP)。


内容的提问来源于stack exchange,提问作者Lukáš Stuchlík

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 01:01:04