Consul注册必须显式配置Check字段,否则服务状态恒为critical;客户端查询须设PassingOnly: true,否则可能获取已下线的僵尸实例。

Consul注册必须显式传Check,否则服务状态永远是critical
很多Gin服务注册到Consul后,在consul members里能看到节点,但consul catalog services查不到,或Health UI里显示critical——根本原因是注册时漏了Check字段。Consul不会为没配置健康检查的服务自动标记passing,哪怕进程还活着。
实操建议:
- 注册时必须构造
api.AgentServiceRegistration并填入Checks切片,至少包含一个HTTP健康检查,比如&api.AgentServiceCheck{HTTP: "http://localhost:8080/health", Timeout: "2s", Interval: "5s"} - 别依赖Consul默认行为;即使你用
consul-k8s-control-plane做了双向同步,Gin服务自身的注册仍需独立完成健康检查配置 - 本地调试时可用
consul agent -dev,但生产环境务必关闭ui_config.enabled = true,避免暴露敏感接口
Gin的/health端点要轻量且与K8s探针严格对齐
K8s的livenessProbe和readinessProbe若调用Gin的/health失败,会直接触发重启或拒绝流量。而Consul的健康检查也复用这个端点——它必须同时满足两个系统的要求:快、稳、无副作用。
实操建议:
- 只返回HTTP 200 + 空JSON,例如
r.GET("/health", func(c *gin.Context) { c.JSON(200, gin.H{"status": "ok"}) }),禁止在此处做DB连接、Redis Ping或HTTP外部调用 - K8s Deployment中
livenessProbe.httpGet.port必须等于容器containerPort,且该端口必须与Gin实际r.Run(":8080")监听端口一致 - Consul注册里的
Address字段在K8s中不能写127.0.0.1;应设为""(让Consul自动填Pod IP)或用Downward API注入status.podIP
客户端查询Consul服务时PassingOnly: true不能省
Go客户端调用api.Health().Service("xxx", "", false, nil)默认返回所有服务实例,包括critical和warning状态的“僵尸节点”。这会导致负载均衡把请求发给已下线但未及时注销的服务,出现503或超时。
实操建议:
- 每次查询必须显式传
api.QueryOptions{AllowStale: false, PassingOnly: true},确保只拿到健康实例 - 不要缓存
api.ServiceEntry列表超过30秒;Consul服务列表变化有延迟,长缓存会放大故障面 - 如果用
go-micro/registry/consul,注意其Watch()返回的Watcher在连接中断后会自动重连并补事件;但etcd实现不会,混用时逻辑要区分
K8s Service与Consul服务名映射要靠consul-k8s-control-plane
单纯在Gin里注册Consul服务,只能被其他Consul客户端发现;K8s原生Service(如my-svc.default.svc.cluster.local)并不会自动变成Consul服务,反之亦然。想让K8s内部Pod通过DNS访问Consul服务,或让VM上的旧服务以K8s Service形式被调用,必须走consul-k8s-control-plane。
实操建议:
- 部署
consul-k8s-control-plane时,确认syncCatalog启用,并配置k8sNamespace白名单(默认只同步default) - Consul服务名若含下划线(如
user_srv),K8s DNS不支持;需在consul-k8s配置中启用enableNamespaces并设置serviceNamePrefix转义 - 不要手动在K8s里创建同名Service去“覆盖”consul-k8s生成的资源;它的OwnerReference指向Consul CRD,冲突会导致控制器反复覆盖
Check,查询时漏一个PassingOnly,K8s里containerPort和targetPort错一位,都会让整个链路静默失效。最常被忽略的是——Gin进程本身是否真的能被Consul从集群内网络访问到,这比代码逻辑更优先。


















