亚马逊AWS官方博客
使用 AWS Load Balancer Controller 的 TargetGroupBinding 功能实现灵活的负载均衡器管理
AWS Load Balancer Controller 是一个控制器,可帮助管理 Kubernetes 集群的 Elastic Load Balancer。
- 它通过部署和配置 Application Load Balancers – ALB 来提供 Kubernetes Ingress 资源。
- 它通过部署和配置 Network Load Balancers – NLB 来提供 Kubernetes Service 资源。
我们在之前的博客中介绍了 如何通过 AWS Load Balancer Controller 实现在 AWS EKS 平台上发布 K8S 服务,包括通过新的Annotation: alb.ingress.kubernetes.io/group.name注释来支持在不同的Ingress对象上共享同一个ALB;以及通过使用Network Load Balancer + IP模式实现南北向 HTTP(S) 流量的导入等。
通过 AWS Load Balancer Controller,在创建 Kubernetes Service 和 Ingress 资源时,Controller 会自动创建 AWS NLB 或 ALB 资源以及相应的 Target Group,将 Pod 注册到 Target Group 中(通过 instance 模式或 IP 模式),并配置侦听器和相应的转发规则以便将流量发送给 Pod。当 Kubernetes Service 或 Ingress 删除时,对应的 NLB/ALB 和 Target Group 资源也一并被删除。另外,如果客户手工在 NLB/ALB 上添加了其他侦听器或转发规则,在 Controller Reconcile 时会被删除掉,Controller 会使所有的侦听器和规则与 Service/Ingress yaml 中的定义保持一致。
在一些实际场景中,客户希望在 Amazon Elastic Kubernetes Service (Amazon EKS) 集群之外统一管理 ALB/NLB,由客户自己而不是 AWS Load Balancer Controller 管理 ALB/NLB 和 Target Group 的生命周期;或者,需要 EKS Service 和 集群外的服务共享同一个 ALB/NLB,需要在 ALB/NLB 上手工配置其他转发规则且不希望 Controller Reconcile 时被删除。
在上面的两种场景中,我们可以使用 AWS Load Balancer Controller 中的新功能 TargetGroupBinding,它允许客户在 EKS 集群之外自己创建和管理 NLB/ALB 和 TargetGroup,或者在 NLB/ALB 上自己创建和管理其他的侦听器和规则。通过 TargetGroupBinding 可以将 Kubnernetes Service和指定的 Target Group 进行关联,帮助客户管理Pod 到 Target Group 的注册和注销;同时,它也只会管理与 Service 关联的特定 Target Group,而不会修改或删除同一个 NLB/ALB 上的任何其他内容。
本文通过实验演示 TargetGroupBinding 的创建和功能,实验以 ALB 为例,使用 NLB 时的配置和步骤一样。实验包括以下几个步骤:
- 在 EKS 集群之外创建 ALB,Target Group(IP 模式和 instance 模式)
- IP 模式下,在 EKS 集群内创建 Service,然后创建 TargetGroupBinding 将 Service 关联到 Target Group;验证 Target Group 中自动注册了 Target(Pod),且通过 ALB 相应端口可正常访问 Pod 内服务
- Instance 模式下,在 EKS 集群内创建 Service,然后创建 TargetGroupBinding 将 Service 关联到 Target Group;验证 Target Group 中自动注册了 Target(EC2),且通过 ALB 相应端口可正常访问 Pod 内服务
- (以 IP 模式为例)扩容 Service 中的副本数,验证关联的 Target Group 中 Target 数也相应扩容;删除 TargetGroupBinding(即取消 Service 与 Target Group 的关联),验证Target Group 中的 Target 也相应注销
创建 ALB, Target Group 和 Listener
在 EKS 集群外,我们通过命令行创建一个 internet-facing 的 ALB,一个 IP 模式的 Target Group 和 一个 instance 模式的 Target Group,并在这个 ALB 上为两个 Target Group 分别创建两个 Listener。
创建 ALB
将下面的 子网、安全组 等内容替换为您自己环境中的实际值。创建完成后,记录下返回的 ALB ARN 值以便后续使用。
创建 IP 模式的 Target Group 和对应的 Listener
创建 Target Group:将下面 VPC ID 替换成您自己环境中的实际值(EKS 集群所在 VPC)。创建完成后,记录下返回的 Target Group ARN 以便后续使用。
$ aws elbv2 create-target-group --name test-tg-ip --protocol HTTP --port 80 --vpc-id <VPC_ID> --target-type ip
创建 Listener:将下面 ALB ARN 和 Target Group ARN 替换成您自己环境中的实际值(刚才创建返回的值)。
$ aws elbv2 create-listener --load-balancer-arn <ALB_ARN> --protocol HTTP --port 28080 --default-actions Type=forward,TargetGroupArn=<TG_IP_ARN>
创建 instance 模式的 Target Group 和对应的 Listener
创建 Target Group:将下面 VPC ID 替换成您自己环境中的实际值(EKS 集群所在 VPC)。创建完成后,记录下返回的 Target Group ARN 以便后续使用。
在 instance 模式下,ALB 会通过 NodePort 将流量转发到 Pod,因此我们指定了 30001 作为 Target Group 的端口,后面创建 K8S Service 时也会使用对应的这个端口。
$ aws elbv2 create-target-group --name test-tg-instance --protocol HTTP --port 30001 --vpc-id <VPC_ID> --target-type instance
创建 Listener:将下面 ALB ARN 和 Target Group ARN 替换成您自己环境中的实际值(刚才创建返回的值)。
$ aws elbv2 create-listener --load-balancer-arn <ALB_ARN> --protocol HTTP --port 38080 --default-actions Type=forward,TargetGroupArn=<TG_INSTANCE_ARN>
ALB 和两个 Target Group 及对应的 Listener 创建完成后,我们可以通过控制台进行查看。
TargetGroupBinding 参数介绍
TargetGroupBinding Specification
TargetGroupBinding Specification 包括:
- targetGroupARN
String. 要关联到 Kubnernetes Service 的 Target Group ARN。Target Group 需要在 EKS 之外创建。
- serviceRef
name: string. 要关联的 Service 名称。
port: IntOrString. 可选。要关联的 Service 的端口,如果没定义,则会根据关联 Service 的端口自动填充。
- NetworkingIngressRule
NetworkingIngressRule 定义了允许 ALB/NLB 访问 Target Group 中 Targets 的网络规则。如果没有在 TargetGroupBinding 中定义规则,则需要手工配置 EKS Worker Node 的安全组放行相应端口。其中,
from 可定义为:
- securityGroup: string,针对 ALB 使用,定义可访问 Targets 的安全组 ID。一般我们可写为 ALB 的安全组 ID。
- ipBlock: string,针对 NLB 使用,定义可访问 Targets 的IP CIDR 段。由于 NLB 没有安全组,并且当 Target Group 以 IP 方式注册时,会将访问 Targets 的 IP 替换成 NLB的私有 IP。因此我们可写为 NLB 所在子网的 CIDR 段。
port可定义为:
可选。允许ALB/NLB 访问Targets 的网络端口。如果定义了端口,则会在 EKS Worker Node 安全组上放行相应端口;如果没有定义,则默认为放行所有端口。
TargetGroupBinding 示例
ALB TargetGroupBinding yaml 文件示例:
NLB TargetGroupBinding yaml 文件示例:
IP 模式下的 TargetGroupBinding
在 EKS 集群中创建 Service
创建一个 Headless Service 用于关联到 IP 模式的 Target Group。
Service yaml 文件如下:
创建 Service:
$ kubectl apply -f nginx-tgb-svc-alb-ip.yaml
创建 TargetGroupBinding
TargetGroupBinding yaml 文件如下,其中,将 targetGroupARN 替换成您自己刚才创建的 IP 模式的 Target Group ARN 值,ALB_SG_ID 替换成您的 ALB 安全组 ID。
创建 TargetGroupBinding:
$ kubectl apply -f tgb-alb-ip.yaml
验证 Pod 已成功注册到 Target Group 中并可正常访问
通过控制台可以看到,当 TargetGroupBinding 创建完成后,Service 对应的 Pod 就成功注册到 Target Group 中。
与 Service 对应的 Pod 是一致的:
查看 EKS Worker Node 所在安全组,可以看到TargetGroupBinding 增加了一条安全组规则(在描述中有 elbv2.k8s.aws/targetGroupBinding=shared 字样),允许来自 ALB SG 的所有 TCP 流量,与我们在 yaml 文件中定义的一致。
通过 ALB 及对应的端口(28080)访问该 Service,注意要为 ALB 的安全组放行 28080 端口。
Instance 模式下的 TargetGroupBinding
在 EKS 集群中创建 Service
创建一个 NodePort 类型的 Service 用于关联到 instance 模式的 Target Group,nodePort 指定为 30001 与 Target Group 一致。
Service yaml 文件如下:
创建 Service:
$ kubectl apply -f nginx-tgb-svc-alb-instance.yaml
创建 TargetGroupBinding
TargetGroupBinding yaml 文件如下,其中,将 targetGroupARN 替换成您自己刚才创建的 instance 模式的 Target Group ARN 值,ALB_SG_ID 替换成您的 ALB 安全组 ID。
创建 TargetGroupBinding:
$ kubectl apply -f tgb-alb-instance.yaml
验证 EC2 Instance 已成功注册到 Target Group 中并可正常访问
通过控制台可以看到,当 TargetGroupBinding 创建完成后,EKS Node 所在的 EC2 instance 就成功注册到 Target Group 中。
查看 EKS Worker Node 所在安全组,可以看到TargetGroupBinding 增加了一条安全组规则(在描述中有 elbv2.k8s.aws/targetGroupBinding=shared 字样),允许来自 ALB SG 的 30001 端口的 TCP 流量,与我们在 yaml 文件中定义的一致。
通过 ALB 及对应的端口(38080)访问该 Service,注意要为ALB 的安全组放行 38080 端口。
Service 的更新与取消关联
我们以 IP 模式为例,验证 Service 在扩容和删除时,TargetGroupBinding 会自动更新对应 Target Group 中的 Target。
Service 扩容
将 Service 对应的 deployment 副本数从 1 个修改为 4 个,观察 Target Group 的变化。
$ kubectl scale deployment nginx-deployment --replicas 4
deployment.apps/nginx-deployment scaled
通过控制台可以看到,当 Service 扩容后,新创建的 Pod 成功注册到 Target Group 中。
与 Service 对应的 Pod 是一致的:
Service 与 Target Group 取消关联
将 IP 模式对应的 TargetGroupBinding 删除,观察 Target Group 的变化。
查看现有的 TargetGroupBinding
删除 my-tgb-alb-ip
$ kubectl delete targetgroupbindings.elbv2.k8s.aws my-tgb-alb-ip
targetgroupbinding.elbv2.k8s.aws "my-tgb-alb-ip" deleted
通过控制台可以看到,当 Service 删除后,对应的 Pod 从 Target Group 中注销。而我们自己创建的 ALB 和 Target Group 仍然保持。
通过上面的实验演示,我们介绍了如何通过AWS Load Balancer Controller 中的新功能 TargetGroupBinding,让客户更加灵活的实现在 Amazon EKS 集群之外自己创建和管理 NLB/ALB 和 TargetGroup,或者在 NLB/ALB 上自己创建和管理其他的侦听器和规则。希望本文的内容能帮助您在更多业务场景中更好的采用 Amazon EKS。
参考资料
- https://github.com/kubernetes-sigs/aws-load-balancer-controller
- https://kubernetes-sigs.github.io/aws-load-balancer-controller/latest/guide/targetgroupbinding/spec/