乐趣区

Kubernetes-Ingress实操带你见识Ingress模式背后的驱动力

导读:Ingress 是一个规则,可以绘制出在集群内部的服务如何弥合鸿沟,暴露到客户可以使用它的外部世界。本文中,作者将帮助你了解 Ingress 模式背后的驱动力。

不知道你是否注意到一个奇怪的现象,尽管 Kubernetes Ingress API 仍然处于 beta 状态,但是已经有许多公司使用它来暴露 Kubernetes 服务。从事相关项目的工程师表示,Kubernetes Ingress API 越来越有可能摘下其 beta 标签。

实际上,Kubernetes Ingress API 处于 beta 状态已经持续了几年的时间,准确来说,是在 2015 年秋季开始进入该阶段的。但是,漫长的 beta 阶段可以让 Kubernetes 贡献者有时间来完善规范并使其与已经搭建好的实施软件(HAProxy、NGINX、Traefik 等)保持一致,从而使 API 标准化以反映最常见并且有需求的功能。

随着该功能 GA 的临近,那么现在应该是一个合适的时机可以帮助新手快速了解 Ingress 的工作方式。简而言之,Ingress 是一个规则,可以绘制出在集群内部的服务如何弥合鸿沟,暴露到客户可以使用它的外部世界。同时,称为 Ingress controller 的代理在集群网络的边缘进行侦听(监视要添加的规则),并将每个服务映射到特定的 URL 路径或域名以供公众使用。在 Kubernetes 维护者开发 API 的同时,其他开源项目也实现了 Ingress Controller 并为其代理添加了自己的独特功能。

在本文中,我将介绍这些概念,并帮助你了解 Ingress 模式背后的驱动力。

路由问题

在 Kubernetes 中创建 Pod 时,需要为其分配 selector 标签,如 Deployment manifest 的以下片段所示:

该 Deployment 创建了运行 Docker 镜像 my-app 的三个副本,并为其分配 app=foo 标签。除了直接访问 Pod,通常将它们分组在 Service 下,这使它们可以在单个集群 IP 地址上使用(但是只能在同一集群中使用)。Service 充当抽象层,隐藏了 pod 的周期短暂特性,可以随时增加或减少或替换它们。它还可以执行基本的循环负载均衡。

例如,以下 Service 定义收集所有带有 selector 标签 app = foo 的 Pod,并在其中平均路由流量。

但是,只能从集群内部以及运行在附近的其他 Pod 访问此服务。Kubernetes Operator 正在努力解决如何为集群外部的客户端提供访问权限。该问题在早期就已经出现,并且将两种机制直接集成到 Service 规范中进行处理。编写 service manifest 时,包括一个名为 type 的字段,该字段的值为 NodePort 或 LoadBalancer。这是一个将类型设置为 NodePort 的示例:

NodePort 类型的服务使用起来很简单。本质上,这些服务希望 Kubernetes API 为他们分配一个随机的 TCP 端口,并将其暴露到集群之外。这样做的方便之处在于,客户端可以使用该端口将集群中的任何节点作为目标,并且他们的消息将被中转到正确的位置。这就类似于你可以拨打美国境内的任何电话,而接听电话的人都会确保为你转接到合适的人。

缺点在于,该端口的值必须介于 30000 到 32767 之间,虽然这个范围安全地避开了常用端口的范围,但是与常见的 HTTP 端口 80 和 HTTPS 443 相比,该端口显然不是很标准。此外,随机性本身也是一个障碍,因为它意味着你事先不知道值是什么,这使得配置 NAT、防火墙规则更具挑战性——尤其是需要为每项服务设置不同的随机端口。

另一个选项是将类型设置为 LoadBalancer。但是,这有一些前提条件——仅当你在 GKE 或 EKS 之类的云托管环境中运行并且可以使用该云供应商的负载均衡器技术时,它才有效,因为它是自动选择并配置的。其缺点是比较昂贵,因为使用这种类型的服务会为每个服务启动一个托管的负载均衡器以及一个新的公共 IP 地址,这会产生额外的费用。

Ingress 路由

分配一个随机端口或外部负载均衡器是很容易操作的,但也带来了独特的挑战。定义许多 NodePort 服务会造成随机端口混乱,而定义许多负载均衡器服务会导致需要支付比实际所需更多的云资源费用。这些情况不可能完全避免,但也许可以减少它的使用范围,甚至你只需要分配 1 个随机端口或 1 个负载均衡器就能够暴露许多内部服务。因此,这一平台需要一个新的抽象层,该层可以在入口点(entrypoint)后面整合许多服务。

那时,Kubernetes API 引入了一种称为 Ingress 的新型 manifest,它为路由问题提供了新的思路。它的工作方式是这样的:你编写一个 Ingress manifest,声明你希望客户端如何路由到服务。manifest 实际上并不自行执行任何操作,你必须将 Ingress Controller 部署到你的集群中,以监视这些声明并对其执行操作。

与其他任何应用程序一样,Ingress controller 是 Pod,因此它们是集群的一部分并且可以看到其他 Pod。它们是使用在市场上已经发展了多年的反向代理搭建的,因此,你可以选择 HAProxy Ingress Controller、NGINX Ingress Controller 等。底层代理为其提供了第 7 层路由和负载均衡功能。不同的代理将自己的功能集放到表中。例如,HAProxy Ingress Controller 不需要像 NGINX Ingress Controller 那样频繁地重新加载,因为它为服务器分配了 slot,并使用 Runtime API 在运行时填充 slot。这使得该 Ingress Controller 拥有更好的性能。

Ingress Controller 本身位于集群内部,与其他 Kubernetes Pod 一样,也容易受到同一“监狱”的“监禁”。你需要通过 NodePort 或 LoadBalancer 类型的服务将它们暴露到外部。但是,现在你只有一个入口点,所有流量都将通过此处:一个服务连接到一个 Ingress Controller,Ingress Controller 依次连接到许多内部 Pod。Controller 具有检查 HTTP 请求的功能,可以根据其发现的特征(例如 URL 路径或域名)将客户端定向到正确的 Pod。

参考这个 Ingress 的示例,该示例定义了 URL 路径 /foo 应该如何连接到名为 foo-service 的后端服务,而 URL 路径 /bar 被定向到名称为 bar-service 的服务。

如上文所示,你依旧需要为你的 Pod 设置服务,但是你不需要在 Pod 上设置类型字段,因为路由和负载均衡将由 Ingress 层处理。服务的作用被简化为以通用名称对 Pod 进行分组。最终,两个路径,/foo 和 /bar,将由一个公共 IP 地址和域名提供服务,例如 example.com/foo 和 example.com/bar。本质上,这是 API 网关模式,在 API 网关中,单个地址将请求路由到多个后端应用程序。

添加 Ingress Controller

Ingress manifest 的声明式方法是你可以指定所需的内容,而无需知道如何实现。Ingress Controller 的工作之一是执行,它需要监控新的 ingress 规则并配置其底层代理以制定相应的路由。

你可以使用 Kubernetes 包管理工具 Helm 安装 HAProxy Ingress Controller。首先,通过下载 Helm 二进制文件并将其复制到 PATH 环境变量中包含的文件夹(例如 /usr/local/bin/)中来安装 Helm。接下来,添加 HAProxy Technologies Helm 库,并使用 helm install 命令部署 Ingress Controller。

通过运行命令 kubectl get service 列出所有正在运行的服务来验证是否已创建 Ingress Controller。

HAProxy Ingress Controller 在集群的 pod 中运行,并使用 NodePort 类型的 Service 资源发布对外部客户端的访问。在上面显示的输出中,你可以看到为 HTTP 选择了端口 31704,为 HTTPS 选择了端口 32255。你还可以在端口 30347 上查看 HAProxy 信息统计页面。HAProxy Ingress Controller 会提供有关流经它的流量的详细指标,因此你可以更好地观察到进入集群的流量。

在 controller 创建类型为 NodePort 的服务时,这意味着需要分配一个随机的端口并且端口编号往往很高,但是现在你只需管理几个此类端口,也就是只需管理连接到 Ingress Controller 的端口,无需再为每个服务创建一个端口。你也可以将其配置为使用 LoadBalancer 类型,只要在云端进行操作即可。它看起来如下:

总体而言,不需要管理太多 Ingress Controller。安装后,它基本上会在后台执行其工作。你只需要定义 Ingress manifest,controller 就会立即将它们连接起来。Ingress manifest 的定义与引用的服务有所区别,因此你可以控制何时暴露服务。

结 论

Ingress 资源通过允许 API 网关样式的流量路由,整合了外部客户端如何访问 Kubernetes 集群中的服务。代理服务通过公共入口点(entrypoint)进行中转,你可以使用 intent-driven、YAML 声明来控制何时以及如何公开服务。

当 Ingress API 这一功能 GA 之后,你一定会看到这种模式变得越来越流行。当然,可能产生一些细微的变化,主要是为了使 API 与现有 controller 中已经实现的功能保持一致。其他改进可能会指导 controller 如何继续发展以符合 Kubernetes 维护者的愿景。总而言之,现在是开始使用此功能的好时机!

退出移动版