面向 VPN 用户的 Pod IP、ClusterIP 与内部负载均衡器
在 Pod 被替换之前,Pod IP 可以通过 VPN 路由。比较直接访问 Pod、ClusterIP 与内部负载均衡器,以及各自的代价。
使用 VPC CNI 时,Pod 可以从 VPC 取得地址,拥有正确路由的 VPN 用户可以直接访问它。这让直接访问 Pod 看起来是最简单的选择,事实也确实如此,直到 Pod 被替换。用户记住的地址应当属于应用,而不是某个副本。比较这三种入口,最终归结为地址归哪个对象所有,以及工作负载迁移时什么必须继续工作。
先按生命周期选择,再按网络为了让入口可达需要做到什么来选择。
三种入口,三种生命周期
Pod IP 归 Pod 所有:随 Pod 一起分配,并在结束时释放。ClusterIP 归 Service 所有,是虚拟地址,只有在集群的服务路由存在的地方才有意义。内部负载均衡器归云资源所有,由集群控制器用后端来配置。这些归属模型预示了你会遇到的故障:地址过期、名字无法解析,或者后端集合未更新。
在做出选择之前,先把比较写下来。一旦说出所有者和故障,选择通常就自己浮现了。
| Entry | Owner | Failure when the workload moves |
|---|---|---|
| Pod IP | The Pod | Address changes and saved links break |
| ClusterIP | The Service | Virtual address with no meaning outside cluster routing |
| Internal balancer | Cloud resource plus controller | Backends update, but the DNS view is yours to maintain |
直接访问 Pod:有用,但只是临时的
对于受控检查,直接访问确实有用:一个管理员、一次短会话、一个特定端口。但对用户它是糟糕的契约,因为地址是实现细节,每次发布都会改变。把它记进 wiki,正是一项正常服务变成传闻的方式。
它还会招来过宽的规则。允许一个管理员访问一个 Pod,并不等于允许访问节点子网中的每个地址,而通常写下的正是后者。
ClusterIP:设计上局限于集群
ClusterIP 之所以有效,是因为集群的数据平面在集群内部为它编程路由。从 VPN 上的笔记本看,除非有东西刻意暴露它,这个地址毫无意义。以 svc.cluster.local 结尾的名字属于集群 DNS,因此把它复制到使用其他解析器的客户端上,得到的是不存在的名字,而不是路由错误。
对于集群内部的调用方,包括其他工作负载,ClusterIP 仍然是正确的入口。它只是不是面向集群路由域之外用户的发布机制。
内部负载均衡器:被发布的路径
内部负载均衡器为你提供稳定的私有地址,以及你自己的区域可以指向的名字,同时控制器让后端集合保持最新,正如 EKS 负载均衡指南 所述。它才是能在普通 Pod 替换后依然存在、无需任何人改文档的入口。它的代价是一个云资源、一份控制器配置和一条来自 VPN 的路由,而这些正是人们低估的部分。
使用集群实际运行的控制器模型。为一种集成编写的注解不适用于另一种。
源地址是谁
安全组看到的是到达其边界的源,具体取决于 VPN 与负载均衡路径,它可能是已连接的客户端,也可能是转换后的地址。在基于 EC2 的节点上,普通 VPC CNI Pod 默认继承节点的 ENI 安全组,而受支持的配置可以挂载 Pod 专属的安全组。请按文档化的路径写规则,而不是按猜想的笔记本地址。
把应用自身的监听器和身份验证作为独立的控制手段。允许流量的网络规则不是授权决定,也不应被当作授权决定。
该交给用户什么
交给用户的是服务名,而不是地址。把名字发布到私有区域,让它指向内部入口,然后在客户端保持同一名字打开的情况下替换一个后端 Pod 来验证。这个练习检验的正是真正重要的性质:例行部署之后仍能到达同一个应用。
把直接访问 Pod 保留为有明确范围的、有文档记载的运维例外,远离面向用户的说明。