服务网格是一项热门技术,有时甚至被吹捧为微服务成功的必要条件。但是,与许多抽象一样,服务网格可以节省时间,但不会节省学习时间。事实上,许多小型平台团队对服务网格增加的复杂性感到不知所措,尤其是在涉及到长时间的操作时。
很自然地会问一个问题:额外的复杂性真的超过了好处吗?
在这篇文章中,我们提出了在投资服务网格之前要考虑的替代方案。服务网格最流行的好处是:
- 验证;
- 入口加密;
- 集群内网络加密;
- 通讯隔离。
对于这些好处中的每一个,我们将展示根据我们的经验更接近管理员已经熟悉的替代方案。对于专业知识或平台工程带宽稀缺的组织,这些可能更具吸引力。
在某些情况下,您将需要服务网格,例如当您需要跨多个 Kubernetes 集群的安全 Pod 到 Pod 通信时。通过排除不能满足您需求的解决方案,您将进一步说服自己为什么选择服务网格开始。
Service Mesh 优势 1 - 使用 OAuth2-proxy 进行身份验证
许多应用程序团队需要在他们的微服务前面添加一个身份验证层。例如,完全实现 OAuth2 或 OpenID 涉及相当多的跳转。与其编写大量样板代码(这与应用程序非特定和非业务差异化相比),团队更愿意“某物”只是将具有正确声明的 JWT 令牌交给他们的应用程序,以便专注于特定于应用程序的访问控制。
我们之前写过关于如何将 Istio 与 OAuth2-proxy 集成以实现这一目标的博客。但是,如果这是您从 Istio 中唯一需要的东西,那么采用它可能有点过头了。
服务网格的替代方案:Nginx Ingress Controller
让我举例说明一个我认为更简单的解决方案,尤其是对于已经使用 Nginx 的团队。如果你只需要一些好的 oauth2-proxy,Nginx Ingress Controller 很容易与之集成。只需使用 auth-url 注释,控制器将完成其余的工作。下图说明了这是如何工作的。
我认为这个解决方案更简单的原因是它只会影响流量进入 Kubernetes 集群的方式。Pod 到 Pod 的通信和以前一样工作。
如果您熟悉 Nginx,但害怕 Ingress Controller 在其周围添加的自动化,您可以通过键入以下内容直接检查 Nginx 的配置方式:
kubectl exec -ti \
-n ingress-nginx \
$(kubectl get pod \
-n ingress-nginx \
-l app.kubernetes.io/component=controller \
-o name \
| head -1 \
) \
-- \
cat /etc/nginx/nginx.conf
默认情况下,您的应用程序不会获得 JWT 令牌。为了确保您的应用程序获得细粒度访问控制的声明,您必须做两件事:
- 首先,将--set-authorization-header命令行选项添加到 oauth2-proxy:这可确保 oauth2-proxy 生成 HTTP 授权标头。
- 其次,将以下注释添加到您的 Ingress:nginx.ingress.kubernetes.io/auth-response-headers: “authorization” 。这可确保 Nginx 入口控制器将 HTTP 授权标头从 oauth2-proxy 转发到您的应用程序。
如果您需要更多详细信息,可以在此处找到现成的代码片段。
- https://github.com/elastisys/compliantkubernetes/blob/main/user-demo/deploy/oauth2-proxy.yaml
- https://elastisys.io/compliantkubernetes/user-guide/network-model/#ingress
Service Mesh 优势二:入口加密
许多法规要求对不受信任网络上的网络流量进行加密。例如,PCI-DSS 要求 4 规定:“通过在开放的公共网络上加密来传输持卡人数据。” GDPR 和瑞典医疗保健(“Behandling av personuppgifter iöppna nät”“通过开放网络处理个人数据”)包含类似规定。
解决方案很简单:添加 TLS 终止。但是,TLS 终止不是业务差异化,也不是特定于应用程序的。理想情况下,平台应该“做它”。我经常看到团队仅针对这一功能采用服务网格,但还有一种更简单的替代方案。
服务网格的替代品:Cert-manager
您可以安装cert-manager,创建 ClusterIssuer 并通过注解使用该 ClusterIssuer 配置您的 Ingress。Cert-manager 将发挥与 LetsEncrypt 对话的魔力,提供 TLS 证书并在其到期前轮换它。
这在上图和相同的即用型代码片段中进行了说明。请参阅cert-manager.io/cluster-issuer注释。
Service Mesh 优势三:集群内网络加密
为一些争议做好准备。
我经常看到组织添加服务网格,因为 mTLS 和 Pod 到 Pod 加密很酷,并且可能是某些法规要求的。这是我对这个话题的看法。
首先,您很少(如果有的话)需要 Pod 到 Pod 加密。如上所述,PCI-DSS 和瑞典医疗保健都只需要对开放(即不受信任)网络进行加密。我经常听到团队争论 Pod 到 Pod 加密“以防万一”底层网络不受信任。如果您不能信任您的基础设施提供商,请更换提供商。再多的加密都不会阻止他们在内存中未加密时访问您的数据。
其次,假设您确实需要集群内加密。例如,您希望将 Kubernetes 集群扩展到通过不受信任的网络连接的两个数据中心。或者,您希望避免与两个数据中心之间的网络提供商签署另一个 GDPR 风格的数据保护协议 (DPA)。
服务网格的替代方案:CNI 级加密
在这种情况下,只需在您的容器网络接口 (CNI) 提供程序中启用 WireGuard 或 IPsec。这样就达到了加密网络流量Node-to-Node的效果。至少Calico和Flannel对此有支持。例如,如果您使用 Kubespray 设置 Calico,只需添加:
calico_wireguard_enabled: true
Service Mesh 的优势四:网络通信的隔离
服务网格带来了另一个特性:它们为每个 Pod 赋予一个身份,然后通过相互身份验证 (mTLS) 实施基于身份的访问控制。这带来了两个好处:首先,您的 Pod “不要与陌生人交谈”,这有助于使某些漏洞更难被利用,例如臭名昭著的Log4Shell。其次,它减少了爆炸半径:如果 Pod 被闯入,攻击者会发现很难横向移动。
服务网格的替代方案:NetworkPolicies
但是使用 NetworkPolicies 可以更简单、更标准化地实现相同的好处。它们就像容器化世界中的防火墙规则或安全组。由于 Pod 在每次部署时都会更改 IP 地址,因此 NetworkPolicies 本质上会将 Pod 身份转换为基于 IP 的防火墙规则,由 Linux 内核强制执行。
NetworkPolicy 由两部分组成:选择器和规则。选择器选择 NetworkPolicy 应用于哪些 Pod,匹配 Pod 标签或命名空间标签。规则指定允许进出所选 Pod 的入口和出口流量。可以设置安全措施以确保每个 Pod 都由 NetworkPolicy 选择。
在某些组织中,网络安全和应用程序安全是不同团队的责任。这可以通过 NetworkPolicies 和 Kubernetes RBAC 在技术上强制执行。只有网络团队被授予编辑 NetworkPolicies 的权限,而应用程序团队仅被授予在选定的命名空间中部署的权限。
最后一条建议:将命名空间视为“内部 API”。由于命名空间最终成为集群内 DNS 名称的一部分,因此最好通过它提供的服务(例如,“auth”、“database”、“licensing”)来命名命名空间,而不是团队名称(“team-green ”、“team-yellow”等)。这种做法还简化了网络安全团队设置 NetworkPolicies 的过程。
结论
简单性和可理解性是安全的关键。虽然安全网格带来了巨大的好处,但在采用它们之前请考虑更简单的替代方案。我的经验是网络和网络安全已经足够复杂。添加另一层可能会使您的平台团队不堪重负,并给他们带来“待命焦虑”。
当然,有许多出色的服务网格特性缺乏更简单的替代方案,例如多集群安全通信和联合网络可观察性。如果您确实需要更高级的功能,我们希望这篇博文可以帮助您做出明智的决定并接受新增的技术。
Kubernetes 网络和服务网格都在快速发展。就在最近几个月,Calico 添加了一个 eBPF 数据平面,并且 Istio 被捐赠给了 CNCF。此类事件可以有利于决策者决定倾向于采用或不采用服务网格。