【译】别用大炮打蚊子—ServiceMesh的替代方案

译者序

最近看到一篇文章,笔者深以为然:

  • 复杂度只能有限消失和转移,不可能完全(甚至是大部分)消失,所以我们做软件架构往往追求的是 转移,用 专人专事 来应对复杂度,以提升效率
  • 在做技术选型的时候,简单性 (控制复杂度)也是我们的一个重要考量,不能因为要解决一个问题而引入了更多问题

正文

服务网格是一项热门技术,有时甚至被吹捧为微服务成功的必要条件。然而,像许多抽象一样,服务网格可以节省实施时间,但不能节省学习时间。事实上,许多小平台团队都因为服务网格所增加的复杂性而感到不堪重负,尤其是在部署完成后的运维工作中。

自然地,人们会问:额外的复杂性是否真的超过了收益?

在这篇文章中,我们提出了一些在采用服务网格之前值得考虑的替代方案。

服务网格最受欢迎的优势有:

  1. 认证;
  2. Ingress 加密;
  3. 集群内网络加密;
  4. 通信隔离。

对于每一个优势,我们都将展示相应的替代方案。在我们的经验中,这些方案更接近系统管理员已经熟悉的方案。对于缺乏专业知识或平台工程的团队来说,这些方案可能更具吸引力。

在某些情况下,你会需要服务网格,例如,当你需要让多个kubernetes 集群之间的 Pod 到 Pod 的通信更加安全稳固之时。通过排除不满足你需求的解决方案,你将进一步说服自己为什么一开始会选择服务网格。

优势 1:使用 OAuth2 代理进行认证

许多应用团队需要在其微服务前面添加一个认证层。举个例子,完全实现 OAuth2 或 OpenID 涉及许多复杂的工作,应用团队更希望“某些组件”直接向其应用程序提供具有正确声明的 JWT token,以便他们能专注于应用特定的访问控制,而不是编写许多通用的、非业务差异化的样板代码。

我们以前在博客中介绍了如何将 Istio 与 OAuth2 代理集成来达到这个目的。但是,如果这是你想通过 Istio 实现的唯一目的,那么采用它则有点过犹不及。

替代方案:Nginx Ingress Controller

这是一个我认为更简单的解决方案,特别是对已经习惯于 Nginx 的团队来说。如果你仅仅需要传统的 oauth2 代理,Nginx Ingress Controller 已经能够和它进行集成了。你只需使用 auth-url 注解,Controller 会完成其余的工作。下图说明了此方案的原理:

【译】别用大炮打蚊子—ServiceMesh的替代方案_第1张图片

我认为这个解决方案更简单的原因是,它实际上只影响流量如何进入你的 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 token。要确保你的应用程序获取细粒度的访问控制所需的声明,你必须做到两点:
• 给 Oauth2 代理添加 --set-authorization-header 命令行选项:这可以确保 Oauth2 代理生成 HTTP 认证 header。
• 给你的 Ingress 添加以下注解: nginx.ingress.kubernetes.io/auth-response-headers: “authorization”。这确保了 Nginx Ingress Controller 会将 Oauth2 代理添加的 HTTP A认证 header 转发到你的应用程序。

更多细节和开箱即用的代码片段:

优势 2:Ingress 加密

许多法规要求对不可信网络上的网络流量进行加密。例如,PCI-DSS 条例 4 规定:“通过加密将持卡人数据传输到开放的公共网络中。” GDPR 和瑞典医疗保健法包含类似的规定。

解决方案很简单:添加 TLS 终结。但是,TLS 终结并不具备业务差异性和应用相关性。理想情况下,平台应该“自动实现它”。我经常看到团队仅为此一项功能而采用服务网格,但实际上有一个更简单的替代方案。

替代方案:证书管理器

你可以安装 cert-manager,创建 ClusterIssuer,并通过注解将你的 Ingress 与该 ClusterIssuer 关联。证书管理器会和 LetsEncrypt 沟通并提供TLS证书,并在证书过期前轮转。

【译】别用大炮打蚊子—ServiceMesh的替代方案_第2张图片

上图对此进行了说明,以及开箱即用的代码片段[https://elastisys.io/compliantkubernetes/user-guide/network-m...]。请参阅 cert-manager.io/cluster-issuer 注解。

优势 3:集群内网络加密  

准备好面对一些争议。

我经常看见企业采用服务网格,仅仅是因为“mTLS 和 Pod 到 Pod 的加密很酷,并且由某些法规要求”。下面是我对这个话题的看法。

首先,你很少(如果有的话)需要 Pod 到 Pod 的加密。如上所述,PCI-DSS 和瑞典医疗保健法只要求在开放(即不可信)网络上加密。我经常听说团队采用 Pod 到 Pod 加密来“以防万一”底层网络不可信。如果你无法信任你的基础设施提供商,请更换提供商。因为再多的加密都无法阻止他们窃取你内存中未加密的数据。

其次,假设你真的需要集群内加密。例如,你想要在 2 个通过不可信网络连接的数据中心中搭建 Kubernetes 集群。或者,你想避免与两个数据中心之间的网络提供商签订另一份类似GDPR的数据保护协议(DPA)。

替代方案:CNI级别加密

在这种情况下,只需在你的容器网络接口(CNI)提供商中启用 WireGuard 和/或 IPsec。这可以实现节点(node 而非 pod)到节点的网络流量加密的效果。至少 Calico 和 Flannel 支持此功能。例如,如果你使用 Kubespray 来配置 Calico,配置方式非常简单:

calico_wireguard_enabled: true

优势4:网络通信隔离

服务网格带来另一个功能:它为每个 Pod 提供一个身份(identity),然后通过相互认证(mTLS)来实现基于身份的访问控制。这带来了两个好处:

  • 首先,你的 Pod “不与陌生人交谈”,这可以让某些漏洞更难利用,如臭名昭著的 Log4Shell
  • 其次,它减小了爆炸半径:如果一个 Pod 被攻破,攻击者会发现横向移动更加困难(译注:也就是很难从一个 pod攻破另一个 pod)。

替代方案:网络策略

然而,使用网络策略可以以更简单和更标准化的方式达到相同的目的。它们就像容器化世界中的防火墙规则或安全组。本质上,随着 Pod 在每次部署后更改IP 地址,网络策略将 Pod 标识转换为基于 IP 的防火墙规则,由 Linux 内核强制执行。

一个网络策略由两部分组成:selector 和 rules。selector 选择网络策略应用于哪些 Pod,可以匹配 Pod 标签或命名空间标签。rules 指定哪些到/从所选 Pod 的入口和出口流量是被允许的。Safeguards 可以用来确保每个 Pod 都能被某个网络策略选择到。

在一些组织中,网络安全性和应用安全性是不同团队的责任。这可以通过网络策略和 Kubernetes RBAC 来完成技术上的实现。只有网络团队被授权编辑网络策略,而应用团队只被授权在给定的命名空间中部署。

最后的建议:将命名空间视为“内部API”。由于命名空间最终成为集群 DNS 名称的一部分,所以最好根据它提供的服务(例如“auth”、“database”、“licensing”)而不是团队名称(“team-green”、“team-yellow”等)来给命名空间取名字。这种做法也简化了网络安全团队设置网络策略的过程。

结论

简单性和可理解性是安全性的关键。尽管服务网格带来很大的好处,但在采用它们之前应考虑更简单的替代方案。我的经验是,网络和网络安全本身已经足够复杂。添加额外的一层会带来一定的风险:让你的平台团队不堪重负,还会给他们带来 on-call 的焦虑。

当然,有许多服务网格功能目前还没有更简单的替代方案,例如跨集群的安全通信,联邦网络的可观察性。如果你确实需要更高级的功能,我们希望本文能够帮助你作出明智的决定和拥抱新增的技术。

Kubernetes 网络和服务网格都在快速发展。就在最近几个月,Calico 增加了一个 eBPF 数据平面Istio 被捐赠给CNCF。这样的事件可以很快推动采用或不采用服务网格的决策。我们当然会观察最新情况,并继续书写关于Kubernetes 网络的文章。

原文

Alternatives to Consider Before Investing in Service Mesheshttps://elastisys.com/dont-use-a-canon-to-shoot-a-mosquito-al...

你可能感兴趣的:(【译】别用大炮打蚊子—ServiceMesh的替代方案)