网络安全 - Amazon EKS

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

网络安全

网络安全有几个方面。第一种是应用限制服务之间网络流量的规则。第二种方法涉及对传输中的流量进行加密。在 EKS 上实施这些安全措施的机制多种多样,但通常包括以下几项:

交通管制

  • 网络策略

  • 安全组

网络加密

  • 服务网格

  • 容器网络接口 (CNIs)

  • 入口控制器和负载均衡器

  • Nitro 实例

  • 带证书管理器的 ACM 私有 CA

网络政策

在 Kubernetes 集群中,默认情况下允许所有 Pod 到 Pod 的通信。尽管这种灵活性可能有助于促进实验,但它并不安全。Kubernetes 网络策略为您提供了一种机制,用于限制 Pod 之间的网络流量(通常称为东西向流量)以及 Pod 和外部服务之间的网络流量。Kubernetes 网络策略在 OSI 模型的第 3 层和第 4 层运行。网络策略使用 pod、命名空间选择器和标签来识别源和目标 Pod,但也可以包括 IP 地址、端口号、协议或这些内容的组合。网络策略可以应用于 Pod 的入站或出站连接,通常称为入口和出口规则。

借助 Amazon VPC CNI 插件的原生网络策略支持,您可以实施网络策略来保护 kubernetes 集群中的网络流量。它与上游的 Kubernetes 网络策略 API 集成,可确保兼容和遵守 Kubernetes 标准。您可以使用上游 API 支持的不同标识符来定义策略。默认情况下,所有入口和出口流量都允许进入一个 Pod。当指定带有 PolicyType Ingress 的网络策略时,只有来自容器节点的连接和入口规则允许的连接才能连接到 Pod。同样适用于出口规则。如果定义了多条规则,则在做出决定时会考虑所有规则的并集。因此,评估顺序不会影响策略结果。

重要

首次配置 EKS 集群时,默认情况下不启用 VPC CNI 网络策略功能。确保您部署了支持的 VPC CNI 插件版本,并将 vpc-cni 插件true上的ENABLE_NETWORK_POLICY标志设置为以启用此功能。有关详细说明,请参阅 Amazon EKS 用户指南

建议

网络策略入门-遵循最低权限原则

创建默认拒绝策略

与 RBAC 策略一样,建议在网络策略中遵循最低权限访问原则。首先创建一个 “全部拒绝” 策略,该策略限制命名空间中的所有入站和出站流量。

apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: default-deny namespace: default spec: podSelector: {} policyTypes: - Ingress - Egress

默认拒绝

默认拒绝
注意

上图由 Tufin 的网络策略查看器创建。

创建允许 DNS 查询的规则

一旦设置了默认的 “全部拒绝” 规则,就可以开始对其他规则进行分层,例如允许 pod 查询 CoreDNS 以获取名称解析的规则。

apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-dns-access namespace: default spec: podSelector: matchLabels: {} policyTypes: - Egress egress: - to: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: kube-system podSelector: matchLabels: k8s-app: kube-dns ports: - protocol: UDP port: 53

allow-dns-access

allow-dns-access

逐步添加规则以选择性地允许命名空间/容器之间的流量流动

了解应用程序要求并根据需要创建细粒度的入口和出口规则。以下示例显示了如何将端口 80 上的入口流量限制为 fro app-one m client-one。这有助于最大限度地减少攻击面并降低未经授权访问的风险。

apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-ingress-app-one namespace: default spec: podSelector: matchLabels: k8s-app: app-one policyTypes: - Ingress ingress: - from: - podSelector: matchLabels: k8s-app: client-one ports: - protocol: TCP port: 80

allow-ingress-app-one

allow-ingress-app-one

监控网络策略的执行

  • 使用网络策略编辑器

    • 网络策略编辑器可帮助从网络流日志中自动生成可视化、安全评分

    • 以交互方式制定网络策略

  • 审计日志

    • 定期查看 EKS 集群的审计日志

    • 审计日志提供了有关在集群上执行了哪些操作的大量信息,包括对网络策略的更改

    • 使用此信息跟踪网络策略随时间推移而发生的变化,并检测任何未经授权或意外的更改

  • 自动测试

    • 通过创建镜像生产环境的测试环境来实现自动化测试,并定期部署试图违反网络策略的工作负载。

  • 监控指标

    • 配置您的可观察性代理以从 VPC CNI 节点代理中获取 prometheus 指标,从而监控代理运行状况和 sdk 错误。

  • 定期审核网络策略

    • 定期审核您的网络策略,确保它们符合您当前的应用程序要求。随着应用程序的发展,审计使您有机会删除多余的入口和出口规则,并确保您的应用程序没有过多的权限。

  • 使用开放策略代理 (OPA) 确保存在网络策略

    • 使用如下所示的 OPA 策略,确保在加载应用程序 pod 之前始终存在网络策略。k8s-app: sample-app如果不存在相应的网络策略,则此政策将拒绝使用标签加载 k8s pod。

package kubernetes.admission
import data.kubernetes.networkpolicies

deny[msg] {
    input.request.kind.kind == "Pod"
    pod_label_value := {v["k8s-app"] | v := input.request.object.metadata.labels}
    contains_label(pod_label_value, "sample-app")
    np_label_value := {v["k8s-app"] | v := networkpolicies[_].spec.podSelector.matchLabels}
    not contains_label(np_label_value, "sample-app")
    msg:= sprintf("The Pod %v could not be created because it is missing an associated Network Policy.", [input.request.object.metadata.name])
}
contains_label(arr, val) {
    arr[_] == val
}

故障排除

监控节点 vpc-network-policy-controller代理日志

启用 EKS 控制平面控制器管理器日志以诊断网络策略功能。您可以将控制平面日志流式传输到CloudWatch 日志组,并使用CloudWatch日志见解来执行高级查询。从日志中,您可以查看哪些 Pod 端点对象已解析为网络策略、策略的协调状态以及调试策略是否按预期运行。

此外,Amazon VPC CNI 允许您从 EKS 工作节点收集策略执行日志并将其导出到 Amazon Cloudwatch。启用后,您可以利用 Conta CloudWatchiner Insig hts 来提供与网络策略相关的使用情况的见解。

Amazon VPC CNI 还发布了一个软件开发工具包,该软件开发工具包提供了与节点上的 eBPF 程序进行交互的接口。SDK aws-node 是在部署到节点上时安装的。你可以在节点的/opt/cni/bin目录下找到安装的 SDK 二进制文件。在发布时,SDK为基本功能提供支持,例如检查eBPF程序和地图。

sudo /opt/cni/bin/aws-eks-na-cli ebpf progs

记录网络流量元数据

AWS VPC 流日志会捕获有关流经 VPC 的流量的元数据,例如源和目标 IP 地址和端口,以及已接受/丢弃的数据包。可以对这些信息进行分析,以查找 VPC 内的资源(包括 Pod)之间是否存在可疑或异常活动。但是,由于 Pod 的 IP 地址在被替换时经常发生变化,因此 Flow Logs 本身可能还不够。Calico Enterprise 使用吊舱标签和其他元数据扩展了流日志,从而更容易破译吊舱之间的流量。

安全组

EK S 使用 AWS VPC 安全组 (SGs) 来控制 Kubernetes 控制平面和集群工作节点之间的流量。安全组还用于控制工作节点与其他 VPC 资源以及外部 IP 地址之间的流量。当您配置 EKS 集群(使用 Kubernetes 版本 1.14-eks.3 或更高版本)时,系统会自动为您创建一个集群安全组。此安全组允许 EKS 控制平面与托管节点组中的节点之间进行不受限制的通信。为简单起见,建议您将集群 SG 添加到所有节点组,包括非托管节点组。

在 Kubernetes 版本 1.14 和 EKS 版本 eks.3 之前,为 EKS 控制平面和节点组配置了单独的安全组。控制平面和节点组安全组的最低规则和建议规则可在 https://docs.aws.amazon.com/eks/latest/userguide/sec-group-reqs.html 中找到。控制平面安全组的最低规则允许端口 443 从工作节点 SG 入站。这条规则允许 kubelet 与 Kubernetes API 服务器进行通信。它还包括用于工作节点 SG 的出站流量的端口 10250;10250 是 kubelets 监听的端口。同样,最低节点组规则允许端口 10250 从控制平面 SG 入站,443 出站到控制平面 SG。最后,还有一条规则允许节点组内的节点之间不受限制地进行通信。

如果您需要控制在集群内运行的服务与在集群外运行的服务(例如 RDS 数据库)之间的通信,请考虑为 Pod 设置安全组。借助 Pod 的安全组,您可以将现有安全组分配给一组 Pod。

警告

如果您引用的安全组在创建 Pod 之前不存在,则不会调度这些 Pod。

您可以通过创建SecurityGroupPolicy对象并指定PodSelector或来控制将哪些 Pod 分配给安全组ServiceAccountSelector。将选择器设置为{}会将中 SGs 引用的分配给命名空间中的所有 pod 或命名空间中的所有服务帐户。SecurityGroupPolicy在为 pod 实施安全组之前,请务必熟悉所有注意事项

重要

如果您使用的 p SGs od SGs ,则必须创建允许端口 53 出站到集群安全组的容器。同样,您必须更新集群安全组以接受来自 pod 安全组的端口 53 入站流量。

重要

在 Pod 中使用安全组时,安全组的限制仍然适用,因此请谨慎使用安全组。

重要

必须为为 pod 配置的所有探测器为来自集群安全组 (kubelet) 的入站流量创建规则。

重要

Pod 的安全组依赖于名为 ENI 中继的功能,该功能旨在增加 EC2 实例的 ENI 密度。将容器分配给 SG 时,VPC 控制器会将节点组中的分支 ENI 与该容器关联起来。如果在调度 Pod 时,节点组中没有足够的分支 ENIs 可用,则 Pod 将保持待处理状态。实例可以支持的分支数量因 ENIs 实例类型/系列而异。有关更多详细信息,请参阅 https://docs.aws.amazon.com/eks/latest/userguide/security-groups-for-pods .html# supported-instance-types

虽然适用于 pod 的安全组提供了一种 AWS 原生方式来控制集群内外的网络流量,而不会产生策略守护程序的开销,但还有其他选项可供选择。例如,Cilium 策略引擎允许您在网络策略中引用 DNS 名称。Calico Enterprise 包括一个用于将网络策略映射到 AWS 安全组的选项。如果您已经实现了像 Istio 这样的服务网格,则可以使用出口网关将网络出口限制为特定的、完全限定的域或 IP 地址。有关此选项的更多信息,请阅读 Istio 中关于出口流量控制的三部分系列。

何时对 Pod 使用网络策略与安全组?

何时使用 Kubernetes 网络策略

  • 控制 pod-to-pod交通

    • 适用于控制集群内 Pod 之间的网络流量(东西向流量)

  • 在 IP 地址或端口级别(OSI 第 3 层或第 4 层)控制流量

何时使用适用于 Pod 的 AWS 安全组 (SGP)

  • 利用现有的 AWS 配置

    • 如果您已经有一组复杂 EC2 的安全组来管理 AWS 服务的访问权限,并且您正在将应用程序从 EC2实例迁移到 EKS, SGPs 那么允许您重复使用安全组资源并将其应用于您的 pod 可能是一个不错的选择。

  • 控制对 AWS 服务的访问权限

    • 在 EKS 集群中运行的应用程序希望与其他 AWS 服务(RDS 数据库)通信, SGPs 将其用作控制从 Pod 到 AWS 服务的流量的有效机制。

  • 隔离 Pod 和节点流量

    • 如果要将 Pod 流量与其余节点流量完全分开,请在POD_SECURITY_GROUP_ENFORCING_MODE=strict模式下使用 SGP。

为 Pod 使用安全组和网络策略的最佳实践

  • 分层安全

    • 将 SGP 和 kubernetes 网络策略的组合用于分层安全方法

    • 用于限制 SGPs 对不属于集群的 AWS 服务的网络级访问,而 kubernetes 网络策略可以限制集群内 Pod 之间的网络流量

  • 最低特权原则

    • 只允许 pod 或命名空间之间必要的流量

  • 对您的应用程序进行细分

    • 尽可能根据网络策略对应用程序进行分段,以便在应用程序受到威胁时缩小爆炸半径

  • 保持政策简单明了

    • Kubernetes 网络策略可能非常精细和复杂,最好让它们尽可能简单,以降低配置错误的风险并减轻管理开销

  • 缩小攻击面

    • 通过限制应用程序的暴露来最大限度地减少攻击面

重要

Pod 的安全组提供两种强制模式:strictstandard。在 EKS 集群中同时使用 Pod 的网络策略和安全组功能时,必须使用standard模式。

在网络安全方面,分层方法通常是最有效的解决方案。结合使用 kubernetes 网络策略和 SGP 可以为在 EKS 中运行的应用程序提供强大的 defense-in-depth策略。

服务网格策略实施或 Kubernetes 网络策略

A service mesh 是一个专用的基础架构层,您可以将其添加到应用程序中。它允许您透明地添加可观察性、流量管理和安全性等功能,而无需将其添加到自己的代码中。

服务网格在 OSI 模型的第 7 层(应用程序)强制执行策略,而 kubernetes 网络策略在第 3 层(网络)和第 4 层(传输)上运行。这个领域有许多产品,比如 AWS AppMesh、Istio、Linkerd 等,

何时使用服务网格执行策略

  • 对服务网格进行现有投资

  • 需要更高级的功能,例如流量管理、可观察性和安全性

    • 流量控制、负载平衡、断路、速率限制、超时等

    • 详细了解您的服务表现(延迟、错误率、每秒请求数、请求量等)

    • 你想实现和利用服务网格来实现 mTLS 等安全功能

选择 Kubernetes 网络策略以获得更简单的用例

  • 限制哪些 pod 可以相互通信

  • 与服务网格相比,网络策略需要的资源更少,因此非常适合更简单的用例或较小的集群,在这些群集中,运行和管理服务网格的开销可能不合理

注意

网络策略和服务网格也可以一起使用。使用网络策略在 Pod 之间提供基本的安全性和隔离,然后使用服务网格添加其他功能,例如流量管理、可观察性和安全性。

ThirdParty 网络策略引擎

如果您有高级策略要求,例如全球网络策略、支持基于DNS主机名的规则、第7层规则、基于规则和明确的 deny/log 操作等, ServiceAccount 可以考虑使用第三方网络策略引擎。CalicoTiger a的开源策略引擎,可以很好地与EKS配合使用。除了实现全套 Kubernetes 网络策略功能外,Calico 还支持具有更丰富功能的扩展网络策略,包括与 Istio 集成时对第 7 层规则(例如 HTTP)的支持。Calico 策略的范围可以限定为命名空间、Pod、服务帐号或全局。当策略的范围限定为服务帐号时,它会将一组 ingress/egress 规则与该服务帐号相关联。有了适当的 RBAC 规则,您就可以防止团队推翻这些规则,从而允许 IT 安全专业人员安全地委托对命名空间的管理。Cilium 的维护者Isovalent还将网络策略扩展到包括对第7层规则(例如HTTP)的部分支持。Cilium 还支持 DNS 主机名,这可用于限制 Kubernetes 与在您的 VPC 内外运行的资源 Services/Pods 之间的流量。相比之下,Calico Enterprise 包含一项功能,允许你将 Kubernetes 网络策略映射到 AWS 安全组以及 DNS 主机名。

你可以在以下网址找到常用 Kubernetes 网络策略的列表。https://github.com/ahmetb/kubernetes-network-policy-recipesCalico 也有一套类似的规则,网址为 https://docs.projectcalico。 org/security/calico-网络政策

迁移到 Amazon VPC CNI 网络策略引擎

为了保持一致性并避免意外的 pod 通信行为,建议在集群中仅部署一个网络策略引擎。如果您想从 3P 迁移到 VPC CNI 网络策略引擎,我们建议您在启用 VPC CNI 网络策略支持之前将现有的 3P NetworkPolicy CRDs 转换为 Kubernetes NetworkPolicy 资源。而且,在生产环境中应用迁移的策略之前,在单独的测试集群中对其进行测试。这使您可以识别和解决 Pod 通信行为中的任何潜在问题或不一致之处。

迁移工具

为了帮助您完成迁移过程,我们开发了一种名为 K8s 网络策略迁移器的工具,可将您现有的网络策略转换为 Kubernetes 原生 Calico/Cilium 网络策略 CRDs 。转换后,您可以直接在运行 VPC CNI 网络策略控制器的新集群上测试转换后的网络策略。该工具旨在帮助您简化迁移过程并确保平稳过渡。

重要

迁移工具只会转换与原生 kubernetes 网络策略 api 兼容的 3P 策略。如果您使用的是3P插件提供的高级网络策略功能,则迁移工具将跳过并报告它们。

请注意,AWS VPC CNI 网络策略工程团队目前不支持迁移工具,而是尽最大努力向客户提供该工具。我们鼓励您使用此工具来简化您的迁移过程。如果您在使用该工具时遇到任何问题或错误,我们恳请您创建GitHub问题。您的反馈对我们来说非常宝贵,将有助于我们不断改进服务。

其他资源

传输中加密

需要符合 PCI、HIPAA 或其他法规的应用程序可能需要在传输数据时对其进行加密。如今,TLS已成为加密网络流量的事实选择。TLS 与其前身 SSL 一样,使用加密协议通过网络提供安全的通信。TLS 使用对称加密,其中加密数据的密钥是根据在会话开始时协商的共享密钥生成的。以下是您可以在 Kubernetes 环境中加密数据的几种方法。

Nitro 实例

默认情况下,以下 Nitro 实例类型(例如 c5n、G4、i3en、m5dn、m5dn、m5n、p3dn、r5dn 和 r5n)之间交换的流量会自动加密。当有中间跳点(例如传输网关或负载均衡器)时,流量不会被加密。有关传输中加密的更多详细信息以及默认情况下支持网络加密的实例类型的完整列表,请参阅传输中的加密。

容器网络接口 (CNIs)

WeaveNet可以配置为使用加密套筒流量自动加密所有流量,尤其是对快速数据路径流量使用 NaCl 加密来加密所有流量。 IPsec

服务网格

传输中的加密也可以使用 App Mesh、Linkerd v2 和 Istio 等服务网格来实现。 AppMesh 支持带有 X.509 证书或 Envoy 的秘密发现服务 (SD S) 的 mTLS。Linkerd 和 Istio 都支持 mTLS。

aws-app-mesh-examplesGitHub 存储库提供了使用 X.509 证书配置 mTLS 和 SPIRE 作为 SDS 提供者使用 Envoy 容器配置 mTLS 的演练:

App Mesh 还支持使用 AWS Certificate Manager (ACM) 颁发的私有证书或存储在虚拟节点本地文件系统中的证书进行 TLS 加密

aws-app-mesh-examplesGitHub 存储库提供了使用 ACM 颁发的证书和与 Envoy 容器一起打包的证书配置 TLS 的演练:

入口控制器和负载均衡器

入口控制器是您智能路由HTTP/S traffic that emanates from outside the cluster to services running inside the cluster. Oftentimes, these Ingresses are fronted by a layer 4 load balancer, like the Classic Load Balancer or the Network Load Balancer (NLB). Encrypted traffic can be terminated at different places within the network, e.g. at the load balancer, at the ingress resource, or the Pod. How and where you terminate your SSL connection will ultimately be dictated by your organization’s network security policy. For instance, if you have a policy that requires end-to-end encryption, you will have to decrypt the traffic at the Pod. This will place additional burden on your Pod as it will have to spend cycles establishing the initial handshake. Overall SSL/TLS处理的一种方式,处理非常占用 CPU。因此,如果你有灵活性,可以尝试在 Ingress 或负载均衡器上执行 SSL 卸载。

在 AWS 弹性负载均衡器中使用加密

AWS Applicat ion Load Bal ancer (ALB) 和网络负载均衡器 (NLB) 都支持传输加密(SSL 和 TLS)。ALB 的alb.ingress.kubernetes.io/certificate-arn注释允许您指定要向 ALB 添加哪些证书。如果您省略注释,控制器将尝试使用主机字段匹配可用的 AWS Certificate Manager (ACM) 证书,从而向需要该注释的侦听器添加证书。从 EKS v1.15 开始,你可以将service.beta.kubernetes.io/aws-load-balancer-ssl-cert注释与 NLB 一起使用,如下例所示。

apiVersion: v1 kind: Service metadata: name: demo-app namespace: default labels: app: demo-app annotations: service.beta.kubernetes.io/aws-load-balancer-type: "nlb" service.beta.kubernetes.io/aws-load-balancer-ssl-cert: "<certificate ARN>" service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "443" service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "http" spec: type: LoadBalancer ports: - port: 443 targetPort: 80 protocol: TCP selector: app: demo-app //--- kind: Deployment apiVersion: apps/v1 metadata: name: nginx namespace: default labels: app: demo-app spec: replicas: 1 selector: matchLabels: app: demo-app template: metadata: labels: app: demo-app spec: containers: - name: nginx image: nginx ports: - containerPort: 443 protocol: TCP - containerPort: 80 protocol: TCP

以下是其他 SSL/TLS 终止示例。

重要

某些 Ingress,比如 AWS LB 控制器, SSL/TLS 使用注解来实现,而不是作为 Ingress 规范的一部分。

带证书管理器的 ACM 私有 CA

您可以使用 ACM 私有证书颁发机构 (CA) 和证书管理器(一种流行的 Kubernetes 附加组件,用于分发、续订和吊销证书)启用 TLS 和 m TLS,以保护入口、容器上和 Pod 之间的 EKS 应用程序工作负载。ACM Private CA 是一种高度可用、安全、托管的 CA,无需管理自己的 CA 所需的前期成本和维护成本。如果您使用的是默认 Kubernetes 证书颁发机构,则有机会提高安全性并满足 ACM 私有 CA 的合规性要求。与存储在内存中编码的密钥的默认 CA(不太安全)相比,ACM Private CA 在 FIPS 140-2 3 级硬件安全模块中保护私钥(非常安全)。集中式 CA 还可让您更好地控制 Kubernetes 环境内部和外部的私有证书,并提高其可审计性。

用于工作负载之间双向 TLS 的短期 CA 模式

在 EKS 中对 mTLS 使用 ACM 私有 CA 时,建议您在短期 CA 模式下使用短期证书。尽管可以在通用 CA 模式下签发短期证书,但对于需要经常颁发新证书的用例,使用短期 CA 模式更具成本效益(比普通模式便宜约 75%)。除此之外,您还应尝试将私有证书的有效期与 EKS 集群中 pod 的生命周期保持一致。在此处@@ 了解有关 ACM 私有 CA 及其优势的更多信息

ACM 安装说明

首先按照 ACM 私有 CA 技术文档中提供的步骤创建私有 CA。拥有私有 CA 后,请按照常规安装说明安装证书管理器。安装证书管理器后,按照中的设置说明安装私有 CA Kubernetes 证书管理器插件。 GitHub该插件允许证书管理器向 ACM 私有 CA 请求私有证书。

现在你已经有了私有 CA 和一个安装了证书管理器和插件的 EKS 集群,是时候设置权限并创建颁发者了。更新 EKS 节点角色的 IAM 权限以允许访问 ACM 私有 CA。用您的私<CA_ARN>有 CA 中的值替换:

{ "Version": "2012-10-17", "Statement": [ { "Sid": "awspcaissuer", "Action": [ "acm-pca:DescribeCertificateAuthority", "acm-pca:GetCertificate", "acm-pca:IssueCertificate" ], "Effect": "Allow", "Resource": "<CA_ARN>" } ] }

也可以使用 IAM 账户或 IRSA 的服务角色。有关完整示例,请参阅下面的 “其他资源” 部分。

在 Amazon EKS 中创建名为 cluster-issuer.yaml 的自定义资源定义文件,其中包含以下文本,用您的私有 CA 替换<CA_ARN><Region>信息。

apiVersion: awspca.cert-manager.io/v1beta1 kind: AWSPCAClusterIssuer metadata: name: demo-test-root-ca spec: arn: <CA_ARN> region: <Region>

部署您创建的发行者。

kubectl apply -f cluster-issuer.yaml

您的 EKS 集群已配置为向私有 CA 请求证书。现在,您可以使用 cert-manager 的Certificate资源来颁发证书,方法是将该issuerRef字段的值更改为您在上面创建的私有 CA 颁发者。有关如何指定和请求证书资源的更多详细信息,请查看 cert-manager 的证书资源指南。请@@ 在此处查看示例

带有 Istio 和证书管理器的 ACM 私有 CA

如果您在 EKS 集群中运行 Istio,则可以禁用 Istio 控制平面(特别是istiod)作为根证书颁发机构 (CA) 的功能,并将 ACM 私有 CA 配置为工作负载之间 mTLS 的根 CA。如果你要使用这种方法,可以考虑在 ACM 私有 CA 中使用短暂的 CA 模式。有关更多详细信息,请参阅上一节和此博客文章

证书签名在 Istio 中的工作原理(默认)

Kubernetes 中的工作负载是使用服务帐户识别的。如果您未指定服务帐户,Kubernetes 将自动为您的工作负载分配一个服务帐户。此外,服务帐号会自动挂载关联的令牌。该令牌由服务账户用于工作负载,以根据 Kubernetes API 进行身份验证。服务账号可能足以作为 Kubernetes 的身份,但是 Istio 有自己的身份管理系统和 CA。当工作负载使用其 envoy sidecar 代理启动时,它需要从 Istio 分配一个身份才能被视为值得信赖并允许与网格中的其他服务进行通信。

为了从 Istio 获取此身份,会向 Istio 控制平面istio-agent发送一个名为证书签名请求(或 CSR)的请求。此 CSR 包含服务帐户令牌,因此可以在处理工作负载之前验证其身份。此验证过程由istiod同时充当注册机构(或 RA)和 CA 的机构处理。RA 充当看门人,确保只有经过验证的 CSR 才能进入 CA。CSR 通过验证后,将转发给 CA,然后由证书颁发包含服务账户的 SPIFFE 身份的证书。此证书被称为 SPIFFE 可验证身份证件(或 SVID)。SVID 被分配给请求服务,用于识别和加密通信服务之间传输的流量。

Istio 证书签名请求的默认流程:

Istio 证书签名请求的默认流程

在 Istio 中如何使用 ACM 私有 CA 进行证书签名

你可以使用名为 Istio 证书签名请求代理 (istio-csr) 的证书管理器插件将 Ist io 与 ACM 私有 CA 集成。该代理允许证书管理器颁发者(在本例中为 ACM Private CA)保护 Istio 工作负载和控制平面组件。istio-csr 代理公开的服务与 i stiod 在验证传入的默认配置中提供的服务相同。 CSRs但是,在验证后,它会将请求转换为证书管理器支持的资源(即与外部 CA 颁发机构的集成)。

每当工作负载有 CSR 时,它都会被转发给 istio-csr,后者将向 ACM Private CA 申请证书。istio-csr 和 ACM 私有 CA 之间的这种通信由 AW S 私有 CA 颁发者插件启用。证书管理器使用此插件向 ACM 私有 CA 请求 TLS 证书。颁发者插件将与 ACM 私有 CA 服务通信,请求工作负载的签名证书。证书签名后,它将返回给 istio-csr,后者将读取已签名的请求,并将其返回到启动 CSR 的工作负载。

使用 istio-csr 提交 Istio 证书签名请求流程

图片:: istio-csr-with-acm-private-ca.png [使用 istio-csr 进行 Istio 证书签名请求的流程]

带有私有 CA 设置说明的 Istio

  1. 首先,按照本节中相同的设置说明完成以下操作:

  2. 创建私有 CA

  3. 安装证书管理器

  4. 安装发行者插件

  5. 设置权限并创建颁发者。颁发者代表 CA,用于签署istiod和网格化工作负载证书。它将与 ACM 私有 CA 通信。

  6. 创建istio-system命名空间。这是 Istio istiod certificate 和其他 Istio 资源的部署地点。

  7. 安装配置有 AWS 私有 CA 发行者插件的 Istio CSR。您可以保留工作负载的证书签名请求,以验证它们是否获得批准和签名 (preserveCertificateRequests=true)。

    helm install -n cert-manager cert-manager-istio-csr jetstack/cert-manager-istio-csr \ --set "app.certmanager.issuer.group=awspca.cert-manager.io" \ --set "app.certmanager.issuer.kind=AWSPCAClusterIssuer" \ --set "app.certmanager.issuer.name=<the-name-of-the-issuer-you-created>" \ --set "app.certmanager.preserveCertificateRequests=true" \ --set "app.server.maxCertificateDuration=48h" \ --set "app.tls.certificateDuration=24h" \ --set "app.tls.istiodCertificateDuration=24h" \ --set "app.tls.rootCAFile=/var/run/secrets/istio-csr/ca.pem" \ --set "volumeMounts[0].name=root-ca" \ --set "volumeMounts[0].mountPath=/var/run/secrets/istio-csr" \ --set "volumes[0].name=root-ca" \ --set "volumes[0].secret.secretName=istio-root-ca"
  8. 使用自定义配置安装 Istio,cert-manager istio-csr将其istiod替换为网格的证书提供商。这个过程可以使用 Istio 运算符来执行。

    apiVersion: install.istio.io/v1alpha1 kind: IstioOperator metadata: name: istio namespace: istio-system spec: profile: "demo" hub: gcr.io/istio-release values: global: # Change certificate provider to cert-manager istio agent for istio agent caAddress: cert-manager-istio-csr.cert-manager.svc:443 components: pilot: k8s: env: # Disable istiod CA Sever functionality - name: ENABLE_CA_SERVER value: "false" overlays: - apiVersion: apps/v1 kind: Deployment name: istiod patches: # Mount istiod serving and webhook certificate from Secret mount - path: spec.template.spec.containers.[name:discovery].args[7] value: "--tlsCertFile=/etc/cert-manager/tls/tls.crt" - path: spec.template.spec.containers.[name:discovery].args[8] value: "--tlsKeyFile=/etc/cert-manager/tls/tls.key" - path: spec.template.spec.containers.[name:discovery].args[9] value: "--caCertFile=/etc/cert-manager/ca/root-cert.pem" - path: spec.template.spec.containers.[name:discovery].volumeMounts[6] value: name: cert-manager mountPath: "/etc/cert-manager/tls" readOnly: true - path: spec.template.spec.containers.[name:discovery].volumeMounts[7] value: name: ca-root-cert mountPath: "/etc/cert-manager/ca" readOnly: true - path: spec.template.spec.volumes[6] value: name: cert-manager secret: secretName: istiod-tls - path: spec.template.spec.volumes[7] value: name: ca-root-cert configMap: defaultMode: 420 name: istio-ca-root-cert
  9. 部署您创建的上述自定义资源。

    istioctl operator init kubectl apply -f istio-custom-config.yaml
  10. 现在,您可以将工作负载部署到 EKS 集群中的网格并强制执行 mTLS

Istio 证书签名请求

图片:: istio-csr-requests .png [Istio 证书签名请求]

工具和资源