手把手教你在容器服务 TKE 上使用 LB 直通 Pod

什么是 LB 直通 Pod ?

Kubernetes 官方提供了 NodePort 类型的 Service,即给全部节点开一个相同端口用于暴露这个 Service,大多云上 LoadBalancer 类型 Service 的传统实现也都基于 NodePort,即 LB 后端绑各节点的 NodePort,LB 接收外界流量,转发到其中一个节点的 NodePort 上,再经过 Kubernetes 内部的负载均衡,使用 iptables 或 ipvs 转发到 Pod:node

TKE 默认的 LoadBalancer 类型 Service 与默认的 Ingress 也都是这样实现的,但目前也支持了 LB 直通 Pod 的方式,即 LB 后端直接绑 Pod IP+Port,不绑节点的 NodePort:nginx

为何须要 LB 直通 Pod ?

LB 直接绑 NodePort 来实现云上的 Ingress 或 LoadBalancer 类型 Service 是最简单通用的方法,那为何有了这种实现还不够,还要搞个 LB 直通 Pod 的模式?后端

首先,咱们分析下传统 NodePort 实现方式存在的一些问题:api

  1. 流量从 LB 转发到 NodePort 以后还须要进行 SNAT,再转发到 Pod,会带来一些额外的性能损耗。
  2. 若是流量过于集中到某几个 NodePort 时(好比使用 nodeSelector 部署网关到固定几台节点上),可能致使源端口耗尽,或者 conntrack 插入冲突。
  3. NodePort 自己也充当负载均衡器,LB 绑定过多节点 NodePort 可能致使负载均衡状态过于分散,致使全局负载不均。

若是使用 LB 直通 Pod 的方式,以上问题都将消失,而且还有一些其它好处:网络

  1. 因为没有 SNAT,获取源 IP 再也不须要 externalTrafficPolicy: Local
  2. 实现会话保持更简单,只须要让 CLB 开启会话保持便可,不须要设置 Service 的 sessionAffinity

因此使用 LB 直通 Pod 的场景一般有:session

  1. 在四层获取客户端真实源 IP,但又不但愿经过使用 externalTrafficPolicy: Local 的方式。
  2. 但愿进一步提高网络性能。
  3. 让会话保持更容易。
  4. 解决全局链接调度的负载不均。

须要什么前提条件 ?

使用 LB 直通 Pod,须要知足如下前提条件:app

  1. Kubernetes集群版本须要高于 1.12,由于 LB 直绑 Pod,检查 Pod 是否 Ready,除了看 Pod 是否 Running、是否经过 readinessProbe 外, 还须要看 LB 对 Pod 的健康探测是否经过,这依赖于 ReadinessGate 特性,该特性在 Kubernetes 1.12 才开始支持。
  2. 集群网络模式必须开启VPC-CNI弹性网卡模式,由于目前 LB 直通 Pod 的实现是基于弹性网卡的,普通的网络模式暂时不支持,这个在将来将会支持。

怎么用 ?

因为目前 LB 直通 Pod 依赖 VPC-CNI,须要保证 Pod 使用了弹性网卡:负载均衡

  1. 若是集群建立时选择的是 VPC-CNI 网络插件,那么建立的 Pod 默认就使用了弹性网卡。性能

  2. 若是集群建立时选择的是 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,示例:spa

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx-deployment-eni
spec:
  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 暴露服务时,须要声明使用直连模式:

  1. 若是经过控制台建立 Service,能够勾选 采用负载均衡直连Pod模式:

  1. 若是经过 yaml 建立 Service,须要为 Service 加上 service.cloud.tencent.com/direct-access: "true" 的 annotation:
apiVersion: v1
kind: Service
metadata:
  annotations:
    service.cloud.tencent.com/direct-access: "true"
  labels:
    app: nginx
  name: nginx-service-eni
spec:
  externalTrafficPolicy: Cluster
  ports:
  - name: 80-80-no
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
  sessionAffinity: None
  type: LoadBalancer

当使用 Ingress 暴露服务时,一样也须要声明使用直连模式:

  1. 若是经过控制台建立 Ingress,能够勾选 采用负载均衡直连Pod模式:

  1. 若是经过 yaml 建立 Ingress,须要为 Ingress 加上 ingress.cloud.tencent.com/direct-access: "true" 的 annotation:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  annotations:
    ingress.cloud.tencent.com/direct-access: "true"
    kubernetes.io/ingress.class: qcloud
  name: test-ingress
  namespace: default
spec:
  rules:
  - http:
      paths:
      - backend:
          serviceName: nginx
          servicePort: 80
        path: /

参考资料

【腾讯云原生】云说新品、云研新术、云游新活、云赏资讯,扫码关注同名公众号,及时获取更多干货!!

相关文章
相关标签/搜索