本文将介绍在AWS Load Balancer Controller(V2)中发布的其他几项重要功能:通过在上篇中创建好的EKS集群中实验通过使用Network Load Balancer(NLB) + IP模式实现南北向HTTP(S)流量的导入,以及演示通过引入Target Group Bingding CRD来实现将EKS中的服务灵活地绑定到已有Target Group上的新功能。
操作步骤
使用Network Load Balancer(NLB) + IP模式实现南北向流量的导入
除了上篇中介绍的使用Application Load Balancer的基于七层的HTTP流量导入,我们很多时候也会有基于四层TCP流量的导入需求,在EKS平台我们可以使用NLB来实现这个需求。下面的实验分别演示使用NLB的几种方法。
部署示例服务nginx,并通过Classic Load Balancer(CLB)发布
运行下列命令生成样例程序nginx的K8S部署和服务,注意通过设置type: LoadBalancer将服务通过AWS负载均衡器(默认类型为CLB)发布到互联网
cat <<EoF > ~/environment/nginx.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: "nginx"
spec:
selector:
app: nginx
type: LoadBalancer
ports:
- protocol: TCP
port: 80
targetPort: 80
EoF
kubectl apply -f ~/environment/nginx.yaml
通过Kubectl命令查看新生成的ningx服务,运行下列命令可以看到除了默认的kubernetes服务之外新增加了一个nginx服务,这个服务的EXTERNAL-IP指向一个负载均衡器的域名
kubectl get svc
在EC2服务控制台查看Load Balancer,输入上一条命令生成的EXTERNAL-IP的值作为过滤条件就可以查验刚刚生成的nginx服务对应的CLB,验证列表中负载均衡器的Type为classic
通过Network Load Balancer(实例模式)发布
接下来,我们运行下列命令生成nginx-nlb-instance服务,其中绝大部分设置都和CLB实验中的服务相同,不同之处就是这里通过设置annotations的service.beta.kubernetes.io/aws-load-balancer-type: nlb
将负载均衡器的类型更改为Network Load Balancer(NLB)
cat <<EoF > ~/environment/nginx-nlb-instance.yaml
---
apiVersion: v1
kind: Service
metadata:
name: "nginx-nlb-instance"
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: nlb
spec:
selector:
app: nginx
type: LoadBalancer
ports:
- protocol: TCP
port: 80
targetPort: 80
EoF
kubectl apply -f ~/environment/nginx-nlb-instance.yaml
类似的,查看更改生成的nginx-nlb-instance服务
kubectl get svc nginx-nlb-instance
在EC2服务控制台查看Load Balancer,输入上一条命令生成的EXTERNAL-IP的值作为过滤条件就可以查验刚刚生成的nginx-nlb-instance服务对应的NLB,验证列表中的Type为network。
待该NLB的状态从provisioning变为active后,选中该NLB后点击Listeners选项页查看该NLB对应的Listener,查看默认行为中的转发目标:Target Group的值(类似k8s-default-nginxnlb-xxxxx),点击该Target Group跳转到Target Group页面,选择Targets选项页,可以看到已经注册到该Target Group中的两个Targets为EC2 Instance类型,即在EKS集群中创建好的两台EC2主机节点
通过Network Load Balancer(IP模式)发布
接下来,我们运行下列命令生成nginx-nlb-ip服务,并通过设置annotations的service.beta.kubernetes.io/aws-load-balancer-type: nlb-ip 将负载均衡器的类型更改为NLB + IP模式
cat <<EoF > ~/environment/nginx-nlb-ip.yaml
---
apiVersion: v1
kind: Service
metadata:
name: "nginx-nlb-ip"
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: nlb-ip
spec:
selector:
app: nginx
type: LoadBalancer
ports:
- protocol: TCP
port: 80
targetPort: 80
EoF
kubectl apply -f ~/environment/nginx-nlb-ip.yaml
运行下列命令查看更改生成的nginx-nlb-ip服务
kubectl get svc nginx-nlb-ip
类似的,根据nginx-nlb-ip服务的EXTERNAL-IP值在EC2的负载均衡器页面查看对应该服务的NLB。可以看到和上述nginx-nlb-instance服务所不同的是,service.beta.kubernetes.io/aws-load-balancer-type 设置为nlp-ip后NLB将Target类型有EC2 Instance类型变更为IP地址类型(192.168.x.x),如下图所示
通过运行下列系列命令查看nginx Pod的IP地址,可知上述IP地址列表中列出的IP正是Nginx Pod所使用的IP
kubectl get pod -o wide
Target Group Binding
TargetGroupBinding是在AWS Load Balancer Controller中引入的一种K8S的CRD(Custom Resource Definition),目的是用来将K8S中的服务绑定到已有的ALB或NLB的Target Group上从而进行更加灵活的服务发布,实现南北向流量导入。有了TargetGroupBinding的支持,可以使你能够使用EKS集群之外的Load Balanacer和Target Group。
通过以下命令查验安装AWS Load Balancer Controller过程中同时安装的TargetGroupBinding的CRD
kubectl get crd targetgroupbindings.elbv2.k8s.aws
运行下面的命令创建nginx-tgb-svc服务
cat <<EoF > ~/environment/nginx-tgb-svc.yaml
---
apiVersion: v1
kind: Service
metadata:
name: "nginx-tgb-svc"
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: nlb-ip
spec:
selector:
app: nginx
type: LoadBalancer
ports:
- protocol: TCP
port: 8080
targetPort: 80
EoF
kubectl apply -f ~/environment/nginx-tgb-svc.yaml
运行下列命令在EKS集群所在的VPC中创建一个名称为my-ip-targets的Target Group
export VPC_ID=$(aws ec2 describe-vpcs --filters Name=tag:Name,Values=eksctl-eksworkshop-albc* | jq -r '.Vpcs[].VpcId')
aws elbv2 create-target-group --name my-ip-targets --protocol TCP --port 8080 --target-type ip --vpc-id $VPC_ID
export TARGET_GROUP_ARN=$(aws elbv2 describe-target-groups --name my-ip-targets --query 'TargetGroups[0].TargetGroupArn')
接下来我们将这个Target Group绑定到服务nginx-nlb-ip对应的NLB上面(便于演示),运行下列命令
kubectl get svc nginx-nlb-ip
在EC2服务的Load Balancer子项的Load Balancer列表中输入上面命令生成的EXTERNAL-IP作为过滤条件查看服务nginx-nlb-ip对应的NLB实例,同时将此NLB的ARN复制替换到下列命令
export LOAD_BALANCER_ARN=<Replace with Above NLB ARN >
在nginx-nlb-ip对应的NLB实例上创建新的Listener并绑定刚刚创建好的Target Group
aws elbv2 create-listener --load-balancer-arn $LOAD_BALANCER_ARN --protocol TCP --port 8080 --default-actions
Type=forward,TargetGroupArn=$TARGET_GROUP_ARN
可以看到nginx-nlb-ip对应的NLB实例上新增加了一个Listener TCP:8080并与新建的Target Group:my-ip-targets成功关联
运行下列命令可以列出目前AWS Load Balancer Controller针对服务nginx-nlb-ip和nginx-tgb-svc创建的两个Target Group Binding
kubectl get targetgroupbindings
接下来运行下列命令创建一个名称为my-tgb-1的Target Group Binding,将Target Group:my-ip-targets的流量分发到服务nginx-tgb-svc上
cat <<EoF > ~/environment/tgb.yaml.template
---
apiVersion: elbv2.k8s.aws/v1beta1
kind: TargetGroupBinding
metadata:
name: my-tgb-1
spec:
serviceRef:
name: nginx-tgb-svc # route traffic to the awesome-service
port: 8080
targetGroupARN: $TARGET_GROUP_ARN
EoF
envsubst < ~/environment/tgb.yaml.template > ~/environment/tgb.yaml
kubectl apply -f ~/environment/tgb.yaml
重新运行下列命令查看新创建的Target Group Binding:my-tgb-1
kubectl get targetgroupbindings
运行下列命令可以验证刚刚创建的Target Group Binding:my-tgb-1成功将流量从nginx-nlb-ip服务对应的NLB的8080端口的Listener成功的转发到了服务nginx-tgb-svc上,两条curl命令的输出的内容相同且都包含Welcome to nginx!
export loadbalancer=$(kubectl get svc nginx-nlb-ip -o jsonpath='{.status.loadBalancer.ingress[*].hostname}')
curl $loadbalancer
curl $loadbalancer:8080
删除上文中创建的K8S对象
按照与上述创建各种资源相反的顺序删除创建的各种K8S对象
kubectl delete -f ~/environment/tgb.yaml
kubectl delete -f ~/environment/nginx-tgb-svc.yaml
kubectl delete -f ~/environment/nginx-nlb-ip.yaml
kubectl delete -f ~/environment/nginx-nlb-instance.yaml
kubectl delete -f ~/environment/nginx.yaml
删除EKS集群和Cloud9环境
删除EKS托管与非托管节点组,最后删除EKS集群。
eksctl delete nodegroup --cluster $EKS_CLUSTER_NAME --name $EKS_NODEGROUP_NAME
eksctl delete nodegroup --cluster $EKS_CLUSTER_NAME --name $EKS_MANAGED_NODEGROUP_NAME
eksctl delete cluster --name $EKS_CLUSTER_NAME
最后,在AWS控制台的Cloud9服务的环境列表中删除eksworksohp演示环境。
总结
在EKS平台我们可以使用AWS Load Balancer Controller与NLB轻松的实现四层TCP流量的导入,并同时支持EC2 Instance与IP模式。同时因为有了NLB + IP模式的支持,使得在EKS Fargate模式下也可以应用NLB+IP模式来实现无服务器的EKS四层应用南北向流量的导入。另外新增的Target Group Binding功能不仅仅使得AWS Load Balancer Controller的内部实现解耦、更加高效,也可以满足将EKS集群内部的服务绑定到集群外部ALB/NLB的Target Group上的需求。
参考资料
- Network load balancing on Amazon EKS https://docs.aws.amazon.com/eks/latest/userguide/load-balancing.html
- AWS Load Balancer Controller 官方博客 https://aws.amazon.com/blogs/containers/introducing-aws-load-balancer-controller/
- AWS Load Balancer Controller 在线文档 https://kubernetes-sigs.github.io/aws-load-balancer-controller/
- EKS 工作坊 https://www.eksworkshop.com/
本篇作者
田大鹏
AWS解决方案架构师,负责帮助客户进行上云架构的设计和咨询。在电商及互联网行业有丰富的咨询和架构设计经验。加入AWS前曾于全球领先的存储和虚拟化企业,担任研发主管工程师及研发经理多种职位,负责在线存储及备份系统的多个子系统的高并发、高可用系统架构设计,应用微服务化等敏捷项目。