本文已超过一年。较旧的文章可能包含过时的内容。请检查页面中的信息自发布以来是否已变得不正确。

Kubernetes v1.26:Kubernetes 流量工程的进展

Kubernetes v1.26 包括网络流量工程方面的重大进展,其中两个功能(服务内部流量策略支持和 EndpointSlice 终止条件)已升级为 GA,第三个功能(代理终止端点)升级为 beta。这些增强功能的结合旨在解决人们今天面临的流量工程方面的不足,并为未来解锁新的功能。

滚动更新期间负载均衡器的流量丢失

在 Kubernetes v1.26 之前,当将 externalTrafficPolicy 字段设置为 Local 时,集群在滚动更新期间可能会遇到来自服务负载均衡器的流量丢失。这里有很多动态部分在发挥作用,因此快速概述 Kubernetes 如何管理负载均衡器可能会有所帮助!

在 Kubernetes 中,您可以创建 type: LoadBalancer 的服务,以使用负载均衡器在外部公开应用程序。负载均衡器实现因集群和平台而异,但该服务提供了一个通用的抽象,表示在所有 Kubernetes 安装中都一致的负载均衡器。

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app.kubernetes.io/name: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376
  type: LoadBalancer

在底层,Kubernetes 为服务分配一个 NodePort,然后 kube-proxy 使用该 NodePort 提供从 NodePort 到 Pod 的网络数据路径。然后,控制器会将集群中所有可用的节点添加到负载均衡器的后端池,使用服务的指定 NodePort 作为后端目标端口。

Figure 1: Overview of Service load balancers

图 1:服务负载均衡器概述

通常,为服务设置 externalTrafficPolicy: Local 会很有益,以避免在没有运行支持该服务的健康 Pod 的节点之间进行额外的跳转。当使用 externalTrafficPolicy: Local 时,会为运行状况检查目的分配一个额外的 NodePort,以便将不包含健康 Pod 的节点从负载均衡器的后端池中排除。

Figure 2: Load balancer traffic to a healthy Node, when externalTrafficPolicy is Local

图 2:当 externalTrafficPolicy 为 Local 时,负载均衡器流量到健康节点

可能发生流量丢失的一种情况是,当节点丢失了服务的所有 Pod 时,但外部负载均衡器尚未探测运行状况检查 NodePort。这种情况的可能性在很大程度上取决于负载均衡器上配置的运行状况检查间隔。间隔越大,这种情况发生的可能性就越大,因为即使 kube-proxy 删除了该服务的前向规则,负载均衡器也会继续向节点发送流量。当 Pod 在滚动更新期间开始终止时,也会发生这种情况。由于 Kubernetes 不会将终止的 Pod 视为“就绪”,因此在滚动更新期间,当任何给定节点上只有终止的 Pod 时,可能会发生流量丢失。

Figure 3: Load balancer traffic to terminating endpoints, when externalTrafficPolicy is Local

图 3:当 externalTrafficPolicy 为 Local 时,负载均衡器流量到终止端点

从 Kubernetes v1.26 开始,kube-proxy 默认启用 ProxyTerminatingEndpoints 功能,该功能在流量会被丢弃的情况下为终止端点添加自动故障转移和路由。更具体地说,当发生滚动更新并且节点仅包含终止的 Pod 时,kube-proxy 将根据其就绪情况将流量路由到终止的 Pod。此外,如果只有终止的 Pod 可用,kube-proxy 将主动使运行状况检查 NodePort 失败。通过这样做,kube-proxy 会提醒外部负载均衡器不应将新连接发送到该节点,但会优雅地处理现有连接的请求。

Figure 4: Load Balancer traffic to terminating endpoints with ProxyTerminatingEndpoints enabled, when externalTrafficPolicy is Local

图 4:当 externalTrafficPolicy 为 Local 时,启用 ProxyTerminatingEndpoints 后负载均衡器流量到终止端点

EndpointSlice 条件

为了支持 kube-proxy 中的这项新功能,EndpointSlice API 为端点引入了新的条件:servingterminating

Figure 5: Overview of EndpointSlice conditions

图 5:EndpointSlice 条件概述

serving 条件在语义上与 ready 相同,只是当 Pod 正在终止时,它可以为 truefalse,而 ready 由于兼容性原因,对于终止的 Pod 始终为 falseterminating 条件对于正在终止的 Pod(非空 deletionTimestamp)为 true,否则为 false。

添加这两个条件使此 API 的使用者能够了解以前不可能的 Pod 状态。例如,我们现在可以跟踪“就绪”和“未就绪”且正在终止的 Pod。

Figure 6: EndpointSlice conditions with a terminating Pod

图 6:具有终止 Pod 的 EndpointSlice 条件

EndpointSlice API 的使用者(如 Kube-proxy 和 Ingress 控制器)现在可以使用这些条件来协调连接耗尽事件,方法是继续转发现有连接的流量,但将新连接重新路由到其他非终止端点。

优化内部节点本地流量

类似于服务如何设置 externalTrafficPolicy: Local 以避免外部来源流量的额外跳转,Kubernetes 现在支持 internalTrafficPolicy: Local,以对集群内部的流量启用相同的优化,特别是对于使用服务集群 IP 作为目标地址的流量。此功能在 Kubernetes v1.24 中升级为 Beta,并在 v1.26 中升级为 GA。

服务默认将 internalTrafficPolicy 字段设置为 Cluster,其中流量随机分配给所有端点。

Figure 7: Service routing when internalTrafficPolicy is Cluster

图 7:当 internalTrafficPolicy 为 Cluster 时,服务路由

internalTrafficPolicy 设置为 Local 时,kube-proxy 仅当存在可用于同一本地节点的可用端点时,才会转发服务的内部流量。

Figure 8: Service routing when internalTrafficPolicy is Local

图 8:当 internalTrafficPolicy 为 Local 时,服务路由

参与其中

如果您对未来关于 Kubernetes 流量工程的讨论感兴趣,可以通过以下方式参与 SIG Network