搬砖武士|手把手教你在容器服务 TKE 上使用 LB直通 Pod
时间:2022-07-25
本文章向大家介绍搬砖武士|手把手教你在容器服务 TKE 上使用 LB直通 Pod,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
roc,腾讯工程师,负责腾讯云TKE的售中、售后的技术支持,根据客户需求输出合理技术方案与最佳实践,为客户业务保驾护航。
什么是 LB 直通 Pod ?
Kubernetes 官方提供了 NodePort 类型的 Service,即给所有节点开一个相同端口用于暴露这个 Service,大多云上 LoadBalancer 类型 Service 的传统实现也都基于 NodePort,即 LB 后端绑各节点的 NodePort,LB 接收外界流量,转发到其中一个节点的 NodePort 上,再通过 Kubernetes 内部的负载均衡,使用 iptables 或 ipvs 转发到 Pod:
TKE 默认的 LoadBalancer 类型 Service 与默认的 Ingress 也都是这样实现的,但目前也支持了 LB 直通 Pod 的方式,即 LB 后端直接绑 Pod IP+Port,不绑节点的 NodePort:
为什么需要 LB 直通 Pod ?
LB 直接绑 NodePort 来实现云上的 Ingress 或 LoadBalancer 类型 Service 是最简单通用的方法,那为什么有了这种实现还不够,还要搞个 LB 直通 Pod 的模式?
首先,我们分析下传统 NodePort 实现方式存在的一些问题:
- 流量从 LB 转发到 NodePort 之后还需要进行 SNAT,再转发到 Pod,会带来一些额外的性能损耗。
- 如果流量过于集中到某几个 NodePort 时(比如使用 nodeSelector 部署网关到固定几台节点上),可能导致源端口耗尽,或者 conntrack 插入冲突。
- NodePort 本身也充当负载均衡器,LB 绑定过多节点 NodePort 可能导致负载均衡状态过于分散,导致全局负载不均。
如果使用 LB 直通 Pod 的方式,以上问题都将消失,并且还有一些其它好处:
- 由于没有 SNAT,获取源 IP 不再需要
externalTrafficPolicy: Local
。 - 实现会话保持更简单,只需要让 CLB 开启会话保持即可,不需要设置 Service 的
sessionAffinity
。
所以使用 LB 直通 Pod 的场景通常有:
- 在四层获取客户端真实源 IP,但又不希望通过使用
externalTrafficPolicy: Local
的方式。 - 希望进一步提升网络性能。
- 让会话保持更容易。
- 解决全局连接调度的负载不均。
需要什么前提条件 ?
使用 LB 直通 Pod,需要满足以下前提条件:
-
Kubernetes
集群版本需要高于 1.12,因为 LB 直绑 Pod,检查 Pod 是否 Ready,除了看 Pod 是否 Running、是否通过 readinessProbe 外, 还需要看 LB 对 Pod 的健康探测是否通过,这依赖于ReadinessGate
特性,该特性在 Kubernetes 1.12 才开始支持。 - 集群网络模式必须开启
VPC-CNI
弹性网卡模式,因为目前 LB 直通 Pod 的实现是基于弹性网卡的,普通的网络模式暂时不支持,这个在未来将会支持。
怎么用 ?
由于目前 LB 直通 Pod 依赖 VPC-CNI,需要保证 Pod 使用了弹性网卡:
- 如果集群创建时选择的是 VPC-CNI 网络插件,那么创建的 Pod 默认就使用了弹性网卡。
- 如果集群创建时选择的是 Global Router 网络插件,后来开启了 VPC-CNI 支持,即两种模式混用,创建的 Pod 默认不使用弹性网卡,需要使用 yaml 创建工作负载,为 Pod 指定
tke.cloud.tencent.com/networks: tke-route-eni
这个 annotation 来声明使用弹性网卡,并且为其中一个容器加上tke.cloud.tencent.com/eni-ip: "1"
这样的 requests 与 limits,示例:
apiVersion: apps/v1kind: Deploymentmetadata: labels: app: nginx name: nginx-deployment-enispec: replicas: 3 selector: matchLabels: app: nginx template: metadata: annotations: tke.cloud.tencent.com/networks: tke-route-eni labels: app: nginx spec: containers: - image: nginx name: nginx resources: requests: tke.cloud.tencent.com/eni-ip: "1" limits: tke.cloud.tencent.com/eni-ip: "1"
当你用 LoadBalancer 的 Service 暴露服务时,需要声明使用直连模式:
- 如果通过控制台创建 Service,可以勾选
采用负载均衡直连Pod模式
:
- 如果通过 yaml 创建 Service,需要为 Service 加上
service.cloud.tencent.com/direct-access: "true"
的 annotation:
apiVersion: v1kind: Servicemetadata: annotations: service.cloud.tencent.com/direct-access: "true" labels: app: nginx name: nginx-service-enispec: externalTrafficPolicy: Cluster ports: - name: 80-80-no port: 80 protocol: TCP targetPort: 80 selector: app: nginx sessionAffinity: None type: LoadBalancer
当使用 Ingress 暴露服务时,同样也需要声明使用直连模式:
- 如果通过控制台创建 Ingress,可以勾选
采用负载均衡直连Pod模式
:
- 如果通过 yaml 创建 Ingress,需要为 Ingress 加上
ingress.cloud.tencent.com/direct-access: "true"
的 annotation:
apiVersion: networking.k8s.io/v1beta1kind: Ingressmetadata: annotations: ingress.cloud.tencent.com/direct-access: "true" kubernetes.io/ingress.class: qcloud name: test-ingress namespace: defaultspec: rules: - http: paths: - backend: serviceName: nginx servicePort: 80 path: /
参考资料
- TKE基于弹性网卡直连Pod的网络负载均衡:https://mp.weixin.qq.com/s/fJtlm5Qjm2BfzekC4RegCQ
- 集群开启 VPC-CNI 模式网络: https://cloud.tencent.com/document/product/457/34993
- VPC-CNI 网络模式使用指引: https://cloud.tencent.com/document/product/457/48040
- Android源码开发之添加/删除系统应用
- 按键事件处理
- Android6.0锁屏源码分析之界面布局分析
- Android6.0源码分析之menu键弹出popupwindow菜单流程分析
- Android中初步自定义view
- Android中View研究自学之路 Android6.0源码分析之View(一)Android6.0源码分析之View(二)
- Android蓝牙配对弹出框过程分析 Android蓝牙配对弹出框过程分析
- Android6.0之修改或者查看系统属性值
- linux下Android7.0多用户编译问题
- 带你解锁蓝牙skill(0)
- WiFiAp探究实录--功能实现与源码分析
- Android7.1.1系统设置默认值大全
- Androidstudio编译c/c++jni方法
- 带你解锁蓝牙skill(三)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 【Lighthouse教程】scrapy爬虫初探
- python 手把手教你基于搜索引擎实现文章查重
- Intellij IDEA 如何自动生成 serialVersionUID
- Spring事务是如何应用到你的业务场景中的?
- BFE.dev前端刷题#9. 解密消息 (Facebook面试题)
- JUnit 5 测试问题 must be static unless the test class is
- Intellij IDEA 如何自动生成 serialVersionUID
- 图解面试题:SQL存储过程有什么用?
- LeetCode-6.Z 字形变换 - 消费补偿算法
- python + redis 实现 分布式队列任务
- Git error: hint: Updates were rejected because the remote contains work that you do hint: not have l
- 500 行代码写一个俄罗斯方块游戏
- k8s——资源限制
- k8s群集之动态扩缩容——HPA
- k8s群集的三种Web-UI界面部署