使用 Istio 的网络策略
Kubernetes 网络策略如何与 Istio 策略相关联。
使用网络策略来保护在 Kubernetes 上运行的应用程序,现在已成为业界普遍接受的最佳实践。鉴于 Istio 也支持策略,我们想花一些时间来解释 Istio 策略和 Kubernetes 网络策略是如何相互作用和相互支持,从而安全地交付您的应用程序。
让我们从基础开始:为什么要同时使用 Istio 和 Kubernetes 网络策略?简而言之,它们擅长不同的方面。考虑 Istio 和网络策略之间的主要区别(我们将描述“典型”实现,例如 Calico,但实现细节可能因不同的网络提供商而异)。
| Istio 策略 | 网络策略 | |
|---|---|---|
| 层 | “服务” - L7 | “网络” - L3-4 |
| 实现 | 用户空间 | 内核 |
| 强制执行点 | Pod | 节点 |
层
Istio 策略在您的网络应用程序的“服务”层运行。从 OSI 模型的角度来看,这是第 7 层(应用程序),但云原生应用程序的事实模型是第 7 层实际上至少包含两层:服务层和内容层。服务层通常是 HTTP,它封装了实际的应用程序数据(内容层)。Istio 的 Envoy 代理就在这个 HTTP 服务层运行。相比之下,网络策略在 OSI 模型的第 3 层(网络)和第 4 层(传输)运行。
在服务层运行使 Envoy 代理能够基于其理解的协议(目前包括 HTTP/1.1 和 HTTP/2(gRPC 在 HTTP/2 上运行))拥有一组丰富的属性来制定策略决策。因此,您可以根据虚拟主机、URL 或其他 HTTP 标头应用策略。将来,Istio 将支持各种第 7 层协议,以及通用的 TCP 和 UDP 传输。
相比之下,在网络层运行的优势在于通用性,因为所有网络应用程序都使用 IP。在网络层,您可以应用策略,而不管第 7 层协议是什么:DNS、SQL 数据库、实时流和大量不使用 HTTP 的其他服务都可以得到保护。网络策略并不局限于经典防火墙的 IP 地址、协议和端口元组。Istio 和网络策略都了解丰富的 Kubernetes 标签,以描述 Pod 端点。
实现
Istio 的代理基于 Envoy,它在数据平面中作为用户空间守护进程实现,使用标准套接字与网络层进行交互。这使其在处理方面具有很大的灵活性,并允许它以容器的形式进行分布式部署(和升级)!
网络策略数据平面通常在内核空间实现(例如使用 iptables、eBPF 过滤器,甚至自定义内核模块)。在内核空间,它们可以非常快,但不像 Envoy 代理那样灵活。
强制执行点
使用 Envoy 代理的策略强制执行是在 Pod 内实现的,作为同一网络命名空间中的 sidecar 容器。这允许采用简单的部署模型。一些容器被授予重新配置其 Pod 内网络的权限 (CAP_NET_ADMIN)。如果这样的服务实例遭到破坏,或出现故障(如恶意租户),则可以绕过代理。
虽然这不会让攻击者访问其他启用 Istio 的 Pod(只要它们配置正确),但它会打开几个攻击向量。
- 攻击未受保护的 Pod
- 试图通过发送大量流量来拒绝受保护的 Pod 的服务
- 泄露在 Pod 中收集的数据
- 攻击集群基础设施(服务器或 Kubernetes 服务)
- 攻击网格外部的服务,如数据库、存储阵列或传统系统。
网络策略通常在主机节点上强制执行,在访客 Pod 的网络命名空间之外。这意味着被破坏或行为异常的 Pod 必须侵入 root 命名空间才能避免强制执行。随着 Kubernetes 1.8 中将要添加的 egress 策略,这种差异使网络策略成为保护您的基础设施免受受损工作负载攻击的关键部分。
示例
让我们来逐步了解一些您可能想要使用 Kubernetes 网络策略来处理启用 Istio 的应用程序的情况。考虑 Bookinfo 示例应用程序。我们将涵盖以下网络策略用例。
- 减少应用程序入口的攻击面
- 在应用程序内强制执行细粒度隔离
减少应用程序入口的攻击面
我们的应用程序入口控制器是应用程序从外部世界进入的主要入口点。快速浏览一下 istio.yaml(用于安装 Istio)定义了 Istio 入口如下。
apiVersion: v1
kind: Service
metadata:
name: istio-ingress
labels:
istio: ingress
spec:
type: LoadBalancer
ports:
- port: 80
name: http
- port: 443
name: https
selector:
istio: ingress
istio-ingress 公开了端口 80 和 443。让我们将传入流量限制到这两个端口。Envoy 有一个 内置的管理界面,我们不希望配置错误的 istio-ingress 镜像意外地将我们的管理界面暴露给外部世界。这是一个纵深防御的例子:正确配置的镜像不应该公开该界面,而正确配置的网络策略会阻止任何人连接到它。无论哪一个失败或配置错误,我们都仍然受到保护。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: istio-ingress-lockdown
namespace: default
spec:
podSelector:
matchLabels:
istio: ingress
ingress:
- ports:
- protocol: TCP
port: 80
- protocol: TCP
port: 443
在应用程序内强制执行细粒度隔离
这是 Bookinfo 应用程序的服务图。
此图显示了正常运行的应用程序应该允许的所有连接。所有其他连接(例如,从 Istio 入口直接到 Rating 服务的连接)都不属于应用程序。让我们锁定这些无关的连接,以防止攻击者利用它们。例如,假设入口 Pod 被利用,攻击者可以运行任意代码。如果我们只允许使用网络策略连接到 Product Page Pod,那么即使攻击者破坏了服务网格的成员,他们也无法获得更多对我的应用程序后端的访问权限。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: product-page-ingress
namespace: default
spec:
podSelector:
matchLabels:
app: productpage
ingress:
- ports:
- protocol: TCP
port: 9080
from:
- podSelector:
matchLabels:
istio: ingress
您可以并且应该为每个服务编写类似的策略,以强制执行哪些其他 Pod 允许访问每个服务。
总结
我们的观点是,Istio 和网络策略在应用策略方面各有优劣。Istio 了解应用程序协议并非常灵活,使其成为在支持操作目标(如服务路由、重试、断路器等)以及在应用程序层执行安全操作(如令牌验证)时应用策略的理想选择。网络策略是通用的、高效的,并且与 Pod 隔离,使其成为在支持网络安全目标时应用策略的理想选择。此外,在网络堆栈的不同层运行的策略是一件好事,因为它为每个层提供了特定的上下文,而不会混杂状态,并允许职责分离。
这篇文章基于 Istio 团队成员 Spike Curtis 在 Tigera 的三部分博客系列。完整的系列可以在以下位置找到:https://www.projectcalico.org/using-network-policy-in-concert-with-istio/