作者:Mohamad Fadhil翻译:Bach(才云)
在构建裸机 Kubernetes 集群时,我们常常会遇到这么一个问题:除了使用 NodePort 之外,我们要如何向网络公开 Kubernetes Service?如果使用 NodePort 服务类型,它需要分配一个要打开的端口,并且要让防火墙规则连接到这些端口,但这种行为对基础架构并不安全,尤其是在将服务器暴露于外部网络时。
其实还有一种简洁的方法可以将 Kubernetes Service 公开到网络上,并使用其原始端口号。如果我们想将 Kubernetes 集群中的 MySQL 服务通过 3306 端口,而不是 32767 端口暴露给外界,我们就可以用到这种方法:使用 Kubernetes 外部 IP service 类型。
K8sMeetup
什么是外部 IP Service
从 Kubernetes 官网文档,我们可以看看外部 IP 的相关描述:
如果外部的 IP 路由到集群中一个或多个 Node 上,KubernetesService
会被暴露给这些externalIPs
。通过外部 IP(作为目的 IP 地址)进入到集群,传到Service
的端口上的流量,将会被路由到Service
的 Endpoint 上。externalIPs
不会被 Kubernetes 管理,它属于集群管理员的职责范畴。
这里最重要的一点就是确保使用哪个 IP 来访问 Kubernetes 集群。使用外部 IP Service 类型,我们可以将 Service 绑定到连接集群的 IP。
另外还有一点重要的是要知道 Kubernetes 网络与 Overlay 网络一起工作。这意味着,我们只要到达了集群中的任何节点(主节点或工作节点),就可以访问集群中的所有节点。
在上图中,节点 1 和节点 2 都有一个 IP 地址。节点 1 上的 IP 地址 1.2.3.4 绑定到 Pod 驻留在节点 2 中的 httpd 服务,而 IP 地址 1.2.3.6 绑定到 nginx 服务,因为 Pod 驻留在节点 1 中。curl IP 地址 1.2.3.4 时,我们应该可以看到来自 httpd 服务的响应,而 curl IP 地址 1.2.3.5 时,响应会来自 nginx 服务。
K8sMeetup
为什么不使用 Ingress?
即使使用 Ingress 将服务公开给外部,Ingress 还是为 L7 路由构建的,这意味着它支持 HTTP( 80 端口)或 HTTPS(443 端口)流量,但不支持其他端口。Ingress 只能充当基于主机的路由,或类似于 Web Server 世界中的虚拟主机。
K8sMeetup
外部 IP 的优缺点
外部 IP 的优点:
- 我们可以完全控制所使用的 IP,使用属于自己 ASN 的 IP,而不是云提供商的 ASN。
外部 IP 的缺点:
- 我们这些简单的设置不会具有高可用性,这意味着如果节点死亡,该服务将不再可用,我们要手动修复问题。
- 管理 IP 需要手动。IP 不是动态配置的,因此需要人工操作。
K8sMeetup
如何使用外部 IP Service
这里的图与上文节点图类似,但 IP 地址和主机名不同。这可能不是一个很好的现实示例,但是在验证设置时,我们可以很容易地区分 IP 地址和主机。在实际示例中,我们可以在一个外部 IP 上公开 MySQL DB,在另一个外部 IP 上公开 Kafka 集群。
本文配置了 2 个 VM。k3s-external-ip-master
是我们的 Kubernetes 主节点,IP 为 1.2.4.120。k3s-external-ip-worker
是 Kubernetes 工作节点,IP 为 1.2.4.114。
步骤 1:设置 Kubernetes 集群
我们现在主节点上安装 K3,再让另一个节点加入集群:
然后现在应该可以看到类似下面的内容:
步骤 2:创建 Kubernetes deployment
我们先创建 nginx deployment 和 httpd deployments:
现在应该看到:
步骤 3:将 deployment 公开为外部 IP 类型
我们先看看 Nginx deployment:
公开 httpd deployment:
kubectl:
现在 Kubernetes Service 应该是下面的样子:
我们有可能会在这里看到服务类型为 ClusterIP,它没有正确显示为“外部 IP”。
步骤 4:观察
现在让我们 curl httpd service ,应该可以看到 Apache 默认页面响应:
接下来 curl nginx 服务,我们可以看到 nginx 默认页面响应:
K8sMeetup
其他
专用于 Service 的浮动 IP
现在大多数云提供商都提供浮动 IP 服务。浮动 IP 允许我们拥有一个 IP,并可以将该 IP 动态分配给所需的任何 IP。在这种情况下,我们可以将 IP 分配给 Kubernetes 集群中的任何工作节点。
在实际情况中,我们可以使用 API 调用将 IP 重新分配给其他 VM,这意味着在其他 VM 发生故障时可以快速主动地将 IP 重新分配给其他 VM,或者可以定期 rotate IP。
图中,我们可以拥有 1 个浮动 IP 1.2.3.6,该 IP 首先分配给节点 1,并且会在节点 1 不可用时切换到节点 2。IP 1.2.3.6 适用于我们的 MySQL 服务,并将置入应用程序配置中。
Anycast IP
我们使用 Anycast IP 用作外部 IP,以提高可用性。对于不熟悉 Anycast IP 的用户而言,这意味着 1 个 IP 可能会路由到 2 个或更多服务器。这是个运行外部 IP Service 的不错方法。
K8sMeetup
结论
我们可以通过许多方法为裸机 Kubernetes 集群获取 IP,例如使用 Inlets 和 MetalLB。本文的设置可能不是最合适的,但也是个相当不错的方法。