Kubernetes 等容器管理系统部署了一个网络模型,该模型为每个 pod(容器组)分配一个单独的 IP 地址。这确保了架构的简单性,避免了不必要的网络地址转换(NAT),并为每个单独的容器提供了全范围的端口号以供使用。这种模型的逻辑结果是,根据集群的大小和 pod 的总数,网络层必须管理大量的 IP 地址。

在传统上,安全策略基于 IP 地址过滤器。下面是一个简单的例子。如果所有具有标签 role=frontend 的 pod 应该被允许发起与所有具有标签 role=backend 的 pod 的连接,那么每个运行至少一个具有标签 role=backend 的 pod 的集群节点必须安装一个相应的过滤器,允许所有 role=frontend pod 的所有 IP 地址发起与所有本地 role=backend pod 的 IP 地址的连接。所有其他的连接请求都应该被拒绝。这可能看起来像这样。如果目标地址是 10.1.1.2,那么只有当源地址是下列之一时才允许连接 [10.1.2.2,10.1.2.3,20.4.9.1]

每次启动或停止带有 role=frontendrole=backend 标签的新 pod 时,必须更新运行任何此类 pod 的每个集群节点的规则,从允许的 IP 地址列表中添加或删除相应的 IP 地址。在大型分布式应用中,这可能意味着每秒多次更新数以千计的集群节点,这取决于部署的 pod 的流失率。更糟糕的是,新的 role=frontend pod 的启动必须推迟到所有运行 role=backend pod 的服务器都被更新了新的安全规则之后,否则来自新 pod 的连接尝试可能会被错误地放弃。这使得它难以有效地扩展。

为了避免这些可能限制扩展性和灵活性的复杂情况,Cilium 将安全与网络寻址分开。相反,安全是基于 pod 的身份,它是通过标签得出的。这个身份可以在 pod 之间共享。这意味着,当第一个 role=frontend pod 启动时,Cilium 会给该 pod 分配一个身份,然后允许它与 role=backend pod 的身份发起连接。随后启动额外的 role=frontend pod 只需要通过键值存储来解决这个身份,不需要在任何承载 role=backend pod 的集群节点上执行任何操作。一个新的 pod 的启动必须只延迟到 pod 的身份被解决,这比更新所有其他集群节点上的安全规则要简单得多。

image
基于身份的安全示意图