LoadBalancer类型Service使用pass-through能力
应用现状
Kubernetes集群可以将运行在一组Pod上的应用程序发布为服务,提供统一的四层访问入口。对于Loadbalancer类型的service,kube-proxy默认会将Service的status中LoadbalanceIP地址配置到节点本地的转发规则中,集群内部访问ELB的地址,流量就会在集群内部转发,而不会经过ELB转发。
集群内部转发功能是kube-proxy组件负责,kube-proxy有iptables和IPVS两种转发模式,iptables是一种简单的轮询转发,IPVS虽有多种转发模式,但也需要修改kube-proxy的启动参数,不能像ELB那样灵活配置转发策略,且无法利用ELB的健康检查能力。
解决方案
CCE服务支持pass-through能力,通过Loadbalance类型Service配置kubernetes.io/elb.pass-through的annotation实现集群内部访问Service的ELB地址时绕出集群,并通过ELB的转发最终转发到后端的Pod。
- 对于CCE集群:
集群内部客户端访问LB类型Service时,访问请求默认是通过集群服务转发规则(iptables或IPVS)转发到后端的容器实例。
当LB类型Service配置elb.pass-through后,集群内部客户端访问Service地址时会先访问到ELB,再通过ELB的负载均衡能力先访问到节点,然后通过集群服务转发规则(iptables或IPVS)转发到后端的容器实例。
- 对于CCE Turbo集群:
集群内部客户端访问LB类型Service时,访问请求默认也是通过集群服务转发规则(iptables或IPVS)转发到后端的容器实例。
当LB类型Service配置elb.pass-through后,集群内部客户端访问Service地址时会先访问到ELB,然后通过ELB直通容器的能力直接访问容器实例。
约束限制
- 独享型负载均衡配置pass-through后,在工作负载同节点和同节点容器内无法通过Service访问。
- 1.15及以下老版本集群暂不支持该能力。
- IPVS网络模式下,对接同一个ELB的Service需保持pass-through设置情况一致。
- 使用节点级别(Local)的服务亲和的场景下,会自动设置kubernetes.io/elb.pass-through为onlyLocal,开启pass-through能力。
操作步骤
下文以nginx镜像创建无状态工作负载,并创建一个具有pass-through的Service。
- 使用nginx镜像创建无状态负载。
apiVersion: apps/v1 kind: Deployment metadata: name: nginx spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - image: nginx:latest name: container-0 resources: limits: cpu: 100m memory: 200Mi requests: cpu: 100m memory: 200Mi imagePullSecrets: - name: default-secret
- Loadbalance类型的Service,并设置kubernetes.io/elb.pass-through为true。
apiVersion: v1 kind: Service metadata: annotations: kubernetes.io/elb.pass-through: "true" kubernetes.io/elb.class: union kubernetes.io/elb.autocreate: '{"type":"public","bandwidth_name":"cce-bandwidth","bandwidth_chargemode":"bandwidth","bandwidth_size":5,"bandwidth_sharetype":"PER","eip_type":"5_bgp","name":"james"}' labels: app: nginx name: nginx spec: externalTrafficPolicy: Local ports: - name: service0 port: 80 protocol: TCP targetPort: 80 selector: app: nginx type: LoadBalancer
此处是自动创建一个名为james的共享型ELB实例,需要通过kubernetes.io/elb.subnet-id指定ELB所在VPC子网,必须和集群在同一个VPC。
配置验证
查看上面创建的Service对应的ELB,名称为james,可以看到ELB的连接数为0,如下图所示。
使用kubectl连接集群,进入到某一个nginx容器中,然后访问ELB的地址。可以看到能够正常访问。
# kubectl get pod NAME READY STATUS RESTARTS AGE nginx-7c4c5cc6b5-vpncx 1/1 Running 0 9m47s nginx-7c4c5cc6b5-xj5wl 1/1 Running 0 9m47s # kubectl exec -it nginx-7c4c5cc6b5-vpncx -- /bin/sh # curl 120.46.141.192 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
稍微等待一段时间看ELB的监控数据,可以看到ELB有一个新建访问连接,这就证明了这次访问经过ELB,与预期一致。