EKS中通过Terraform创建NLB服务时目标组未注册问题排查
我使用Terraform在EKS集群中创建LoadBalancer类型的服务,服务及NLB均已成功创建,但除一个目标组外,其余目标组均无注册目标,集群共有6个节点。
使用的Terraform代码如下:
resource "kubernetes_service" "ml" { count = (var.enabled_environments[var.namespace] == true && var.namespace != "prod" && var.namespace != "demo" ? 1 : 0) metadata { namespace = var.namespace name = "${var.namespace}-xyz-ml-service" labels = { "app.kubernetes.io/component" = "${var.namespace}-xyz-ml" } annotations = { "service.beta.kubernetes.io/aws-load-balancer-type" = "nlb" "service.beta.kubernetes.io/aws-load-balancer-nlb-target-type" = "instance" "service.beta.kubernetes.io/aws-load-balancer-internal" = "true" } } spec { type = "LoadBalancer" port { name = "abc-0" port = 8110 target_port = 8110 } port { name = "abc-1" port = 8111 target_port = 8111 } port { name = "abc-2" port = 8112 target_port = 8112 } port { name = "abc-3" port = 8113 target_port = 8113 } selector = { app = "xyz-ml" } } }
问题原因及修复方案
Pod端口监听不完整
检查xyz-mlPod是否同时监听了8110、8111、8112、8113这四个端口。如果某个端口未被Pod监听,对应的目标组就不会注册任何节点——因为Kubernetes只会将运行了对应端口Pod的节点加入目标组。缺少健康检查配置
使用instance类型目标时,AWS需要通过健康检查确认节点是否能接收流量。默认健康检查规则可能不匹配你的服务,需要手动添加注解:
在Service的annotations块中补充:"service.beta.kubernetes.io/aws-load-balancer-healthcheck-port" = "traffic-port" "service.beta.kubernetes.io/aws-load-balancer-healthcheck-protocol" = "TCP"traffic-port会自动使用每个目标组对应的端口执行TCP健康检查,确保节点能正常响应该端口的流量。节点安全组限制
确认节点安全组允许NLB的健康检查流量(默认是TCP目标端口),同时允许节点内部转发流量到Pod的对应端口。如果安全组拦截了这些流量,目标组会判定节点不健康,不会完成注册。Pod分布与状态异常
执行kubectl get pods -n ${var.namespace}查看xyz-mlPod的运行状态和分布节点。如果只有部分节点上有Pod,且这些Pod仅监听了其中一个端口,就会出现只有对应目标组有注册节点的情况。
可选优化方案
如果希望所有端口的目标组都能关联到所有运行xyz-ml Pod的节点(或直接关联Pod IP),可以将目标类型改为ip:
修改注解中的目标类型:
"service.beta.kubernetes.io/aws-load-balancer-nlb-target-type" = "ip"
这种模式下,NLB会直接将流量转发到Pod的IP地址,每个端口对应的目标组会自动包含所有匹配selector的Pod,无需依赖节点端口转发,更适合多端口服务场景。
内容的提问来源于stack exchange,提问作者vishal mehra

