亚马逊AWS官方博客

OpenSource | Kubernetes 1.9中的网络负载平衡器支持

 

在 Amazon Web Services 上部署的应用程序可利用 Elastic Load Balancing (ELB) 实现出色的容错能力,确保扩展性、性能和安全性。传入 ELB 的应用程序流量将分布到多个目标,例如 Amazon EC2 实例、容器和 IP 地址。除了 Classic Load Balancer 和 Application Load Balancer 之外,去年我们还推出了新的网络负载均衡器。它每秒能处理数百万项请求,同时保持超低延迟。Micah Hausler 在 Kubernetes 中添加了网络负载均衡器支持,而这篇由 Micah Hausler 所写的客座文章说明了如何为在 Kubernetes 上运行的应用程序提供此支持。

Arun


9 月份,AWS 发布了全新的网络负载均衡器,对于 AWS 社区中的许多人来说,这是负载均衡领域一次激动人心的进步。我最喜爱的部分功能包括无需任何额外设置即可保留原始源 IP,以及处理超长运行中连接的能力。在这篇博文中,我们将展示如何通过 AWS 上的 Kubernetes 集群创建网络负载均衡器。

Kubernetes 中的 Classic 负载均衡

我在 AWS 上使用 Kubernetes 迄今已有一年半时间,我发现将流量路由到 Kubernetes 工作负载的最简便方法莫过于使用 Kubernetes 负载均衡器服务。下面展示了服务的一种示例配置:

apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: default
  annotations: {}
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
type: LoadBalancer

这会创建一个 Classic ELB,将前端端口 80 上的 TCP 流量路由到 pod 的端口 80。最终结果就是客户端源 IP 丢失,被 ELB 的 IP 地址取而代之。解决方法包括启用代理协议,或者在带有 Kubernetes 元数据注释的 HTTP 或 HTTPS 侦听器上使用 X-Forwarded-For 标头。还有其他多种注释可用于配置 ELB 功能,比如请求日志、ACM 证书、连接耗尽等。

Kubernetes 中的网络负载均衡

在 Kubernetes 1.9 版本中,我添加了将全新网络负载均衡器与 Kubernetes 服务配合使用的支持。这是一项 Alpha 级别的功能,截至发文之日为止尚未准备好用于生产集群或工作负载,因此在试用之前请务必阅读有关 NLB 的文档。通过 NLB 公开服务的唯一要求就是添加此注释 service.beta.kubernetes.io/aws-load-balancer-type ,其值为 nlb

完整的示例如下所示:

apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: default
  labels:
    app: nginx
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
spec:
  externalTrafficPolicy: Local
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
type: LoadBalancer

要自行尝试,请参阅 Arun 所写的有关使用 Kops 管理 Kubernetes 集群的博文,并将 kubernetes-version 设置为 1.9.1。

kops create cluster \
--name cluster.kubernetes-aws.io \
--zones us-west-2a \
--kubernetes-version 1.9.1 \
--yes

创建集群之后,您需要授予 Kubernetes 主实例新权限,以创建 NLB。(在 kops 正式支持 Kubernetes 1.9 之后,就不需要再额外执行这一步骤了。)

网络负载均衡器可能需要几分钟的时间才能创建完成,并将节点注册为有效目标 (即便 NLB 主机名已回报给 Kubernetes)。您可以在 AWS 控制台中查看状态:

如果按照上文的示例操作,那么在目标组实例 (Kubernetes 节点) 完成初始设置之后,您就会看到一个节点标记为运行状况良好,另一个节点标记为运行状况不佳。


节点将按实例 ID 添加到 NLB,但为了对 Kubernetes 联网略加讲解,来自 NLB 的流量不会直接传入 pod。客户端流量会首先抵达集群指定的 nodePort 上的 kube-proxy,并传递到集群中所有匹配的 pod。在 spec.externalTrafficPolicy 设置为默认值 Cluster时,传入的 LoadBalancer 流量可能会由 kube-proxy 发送到该节点上的 pod,或者发送到其他节点上的 pod。使用这种配置,客户端 IP 将发送到 kube-proxy,但在数据包抵达末端 pod 时,客户端 IP 会显示为 kube-proxy 的本地 IP。

通过将 spec.externalTrafficPolicy 更改为 Local,kube-proxy 即可将源 IP 正确转发至末端 pod,但仅会将流量发送到 kube-proxy 在其上运行的节点上的 pod。Kube-proxy 还会开启另一个端口来执行 NLB 运行状况检查,保证流量仅发送到包含与服务选择器匹配的 pod 的节点。这可能很容易导致流量分布不均,因此应使用 DaemonSet 或指定 pod 反关联性,确保给定服务的一个节点上仅有一个 pod。

现在,网络负载均衡器便可以使用了!

新的网络负载均衡器与 Classic ELB 的工作方式还有另外几个不同之处,因此请务必阅读有关 NLB 的 Kubernetes 文档AWS NLB 文档

欢迎您为 Kubernetes 贡献力量!

添加 NLB 集成是我为 Kubernetes 做出的第一项贡献,这也是一次回报颇丰的经历。Kubernetes 社区组织由多个特别兴趣小组 (SIG) 组成,AWS SIG 素来热情待人、积极支持他人。感谢 SIG-AWS 以及 Amazon 的所有审核者和协作者提供的宝贵见解。

如果您有兴趣专门探索与 AWS 或 NLB 的更深入的集成,欢迎加入这个社区!参加 SIG-AWS 会议、提交功能请求或在 Github 上报告错误:正是社区的无私奉献才造就了今天的 Kubernetes!

包含上述代码段的 Gist:

https://gist.github.com/micahhausler/4f3a2ee540f5714e6dd91b4bacace3ae


Micah Hausler 是 Skuid 的高级网站运维工程师,负责管理 DevOps 团队,同时还是 Kubernetes 参与者。您可以在 Twitter、Github 和 Kubernetes Slack 上搜索 @micahhausler 找到他。

本博文中的内容和观点均源自第三方作者,AWS 对本博文中的内容或准确性不承担任何责任。

Arun Gupta

Arun Gupta

Arun Gupta 是 Amazon Web Services 的首席开源技术专家。他在 AWS 主要负责与容器和开源有关的所有事务。他还负责 AWS 内部的 CNCF 战略,积极参与 CNCF 董事和技术会议。他曾在 Sun、Oracle、Red Hat 和 Couchbase 组建和领导开发人员社区,在此方面拥有超过 12 年的经验。他有丰富的演讲经历,在 40 多个国家/地区就各种主题发表过演讲,并且连续四年荣膺 JavaOne Rock Star。Gupta 还在美国创立了 Devoxx4Kids 分会,并继续在儿童中推广技术教育。此外,Gupta 还是一位多产的博客作者并出版过多本书籍。他热爱跑步、喜欢环球旅行。这就是 Gupta,一位 Docker 队长、一个 Java 冠军、一名 JUG 领袖、一位 NetBeans 梦之队成员。您可以访问他的博客 @arungupta,了解更多信息。