

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

# 网络安全
<a name="network-security"></a>

**提示**  
 通过 Amazon EKS 研讨会@@ [探索](https://aws-experience.com/emea/smb/events/series/get-hands-on-with-amazon-eks?trk=4a9b4147-2490-4c63-bc9f-f8a84b122c8c&sc_channel=el)最佳实践。

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

## 交通管制
<a name="_traffic_control"></a>
+ 网络策略
+ 安全组

## 网络加密
<a name="_network_encryption"></a>
+ 服务网格
+ 容器网络接口 (CNI)
+ 入口控制器和负载均衡器
+ Nitro 实例
+ 带证书管理器的 ACM 私有 CA

## 网络政策
<a name="iam-network-policy"></a>

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

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

**重要**  
首次配置 EKS 集群时，默认情况下不启用 VPC CNI 网络策略功能。确保您部署了支持的 VPC CNI Add-on 版本，并在 vpc-cni 插件`true`上将`ENABLE_NETWORK_POLICY`标志设置为以启用此功能。有关详细说明，请参阅 [Amazon EKS 用户指南](https://docs.aws.amazon.com/eks/latest/userguide/managing-vpc-cni.html)。

## 建议
<a name="_recommendations"></a>

### 网络策略入门-遵循最低权限原则
<a name="_getting_started_with_network_policies_follow_principle_of_least_privilege"></a>

#### 创建默认拒绝策略
<a name="_create_a_default_deny_policy"></a>

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

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

 **默认拒绝** 

![默认拒绝](http://docs.aws.amazon.com/zh_cn/eks/latest/best-practices/images/security/default-deny.jpg)


**注意**  
上图由 [Tufin](https://orca.tufin.io/netpol/) 的网络策略查看器创建。

#### 创建允许 DNS 查询的规则
<a name="_create_a_rule_to_allow_dns_queries"></a>

一旦设置了默认的 “全部拒绝” 规则，就可以开始对其他规则进行分层，例如允许 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
```

 **允许 dns-access** 

![允许 dns-access](http://docs.aws.amazon.com/zh_cn/eks/latest/best-practices/images/security/allow-dns-access.jpg)


#### 逐步添加规则，有选择地允许流量在两者之间流动 namespaces/pods
<a name="_incrementally_add_rules_to_selectively_allow_the_flow_of_traffic_between_namespacespods"></a>

了解应用程序要求并根据需要创建细粒度的入口和出口规则。以下示例显示了如何将端口 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
```

 **允许进入 app-one** 

![允许进入 app-one](http://docs.aws.amazon.com/zh_cn/eks/latest/best-practices/images/security/allow-ingress-app-one.png)


### 监控网络策略的执行
<a name="_monitoring_network_policy_enforcement"></a>
+  **使用网络策略编辑器** 
  +  [网络策略编辑器](https://networkpolicy.io/)可帮助从网络流日志中自动生成可视化、安全评分
  + 以交互方式制定网络策略
+  **审核日志** 
  + 定期查看 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
}
```

### 问题排查
<a name="_troubleshooting"></a>

#### 监控 vpc 网络策略控制器、节点代理日志
<a name="_monitor_the_vpc_network_policy_controller_node_agent_logs"></a>

启用 EKS 控制平面控制器管理器日志以诊断网络策略功能。您可以将控制平面日志流式传输到CloudWatch 日志组，并使用[CloudWatch日志见解](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AnalyzingLogData.html)来执行高级查询。从日志中，您可以查看哪些 Pod 端点对象已解析为网络策略、策略的协调状态以及调试策略是否按预期运行。

此外，Amazon VPC CNI 允许您从 EKS 工作节点收集策略执行日志并将其导出到 [Amazon Cloudwatch](https://aws.amazon.com/cloudwatch/)。启用后，您可以利用 Conta [CloudWatchiner Insig](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/ContainerInsights.html) hts 来提供与网络策略相关的使用情况的见解。

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

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

#### 记录网络流量元数据
<a name="_log_network_traffic_metadata"></a>

 [AWS VPC 流日志](https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html)会捕获有关流经 VPC 的流量的元数据，例如源和目标 IP 地址和端口以及accepted/dropped 数据包。可以对这些信息进行分析，以查找 VPC 内的资源（包括 Pod）之间是否存在可疑或异常活动。但是，由于 Pod 的 IP 地址在被替换时经常发生变化，因此 Flow Logs 本身可能还不够。Calico Enterprise 使用吊舱标签和其他元数据扩展了流日志，从而更容易破译吊舱之间的流量。

## 安全组
<a name="_security_groups"></a>

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

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

如果您需要控制在集群内运行的服务与在集群外运行的服务（例如 RDS 数据库）之间的通信，请考虑为 [Pod 设置安全组](https://docs.aws.amazon.com/eks/latest/userguide/security-groups-for-pods.html)。借助 Pod 的安全组，您可以将**现有**安全组分配给一组 Pod。

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

您可以通过创建`SecurityGroupPolicy`对象并指定`PodSelector`或来控制将哪些 Pod 分配给安全组`ServiceAccountSelector`。将选择器设置为`{}`会将中引用的 SG 分配给命名空间中的所有 pod 或命名空间中的所有服务帐户。`SecurityGroupPolicy`在为 pod 实施安全组之前，请务必熟悉所有[注意事项](https://docs.aws.amazon.com/eks/latest/userguide/security-groups-for-pods.html#security-groups-pods-considerations)。

**重要**  
如果您将 SG 用于 Pod，则**必须**创建允许端口 53 出站到集群安全组的 SG。同样，您**必须**更新集群安全组以接受来自 pod 安全组的端口 53 入站流量。

**重要**  
在 Pod 中使用[安全组时，安全组的限制](https://docs.aws.amazon.com/vpc/latest/userguide/amazon-vpc-limits.html#vpc-limits-security-groups)仍然适用，因此请谨慎使用安全组。

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

**重要**  
Pod 的安全组依赖于名为 [ENI 中继](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/container-instance-eni.html)的功能，该功能旨在提高 EC2 实例的 ENI 密度。将容器分配给 SG 时，VPC 控制器会将节点组中的分支 ENI 与该容器关联起来。如果在调度 Pod 时，节点组中没有足够的分支 ENI 可用，则该 Pod 将保持待处理状态。实例可以支持的分支 ENI 数量因实例 type/family而异。有关更多详细信息，请参阅 https://docs.aws.amazon.com/eks/latest/userguide/security-groups-for-pods.html \#supported-instance-types。

虽然 pod 的安全组提供了 AWS-native 一种无需策略守护程序开销即可控制集群内外的网络流量的方法，但还有其他选项可供选择。例如，Cilium 策略引擎允许您在网络策略中引用 DNS 名称。Calico Enterprise 包括一个用于将网络策略映射到 AWS 安全组的选项。如果您已经实现了像 Istio 这样的服务网格，则可以使用出口网关将网络出口限制为特定的、完全限定的域或 IP 地址。有关此选项的更多信息，请阅读 [Istio 中关于出口流量控制](https://istio.io/blog/2019/egress-traffic-control-in-istio-part-1/)的三部分系列。

## 何时对 Pod 使用网络策略与安全组？
<a name="_when_to_use_network_policy_vs_security_group_for_pods"></a>

### 何时使用 Kubernetes 网络策略
<a name="_when_to_use_kubernetes_network_policy"></a>
+  **控制 pod 到 Pod 的流量** 
  + 适用于控制集群内 Pod 之间的网络流量（东西向流量）
+  **在 IP 地址或端口级别（OSI 第 3 层或第 4 层）控制流量** 

### 何时使用适用于 Pod 的 AWS 安全组 (SGP)
<a name="_when_to_use_aws_security_groups_for_pods_sgp"></a>
+  **利用现有的 AWS 配置** 
  + 如果您已经有一组复杂的 EC2 安全组来管理 AWS 服务的访问权限，并且您正在将应用程序从 EC2 实例迁移到 EKS，那么 SGP 可能是一个不错的选择，允许您重复使用安全组资源并将其应用于您的 pod。
+  **控制对 AWS 服务的访问权限** 
  + 在 EKS 集群中运行的应用程序希望与其他 AWS 服务（RDS 数据库）通信，使用 SGP 作为控制从 pod 到 AWS 服务的流量的有效机制。
+  **隔离 Pod 和节点流量** 
  + 如果要将 Pod 流量与其余节点流量完全分开，请在`POD_SECURITY_GROUP_ENFORCING_MODE=strict`模式下使用 SGP。

### 为 Pod 使用安全组和网络策略的最佳实践
<a name="_best_practices_using_security_groups_for_pods_and_network_policy"></a>
+  **分层安全** 
  + 将 SGP 和 kubernetes 网络策略的组合用于分层安全方法
  + 使用 SGP 限制对不属于集群的 AWS 服务的网络级访问，而 kubernetes 网络策略可以限制集群内 Pod 之间的网络流量
+  **最低特权原则** 
  + 只允许 pod 或命名空间之间必要的流量
+  **对您的应用程序进行细分** 
  + 尽可能根据网络策略对应用程序进行分段，以便在应用程序受到威胁时缩小爆炸半径
+  **保持政策简单明了** 
  + Kubernetes 网络策略可能非常精细和复杂，最好让它们尽可能简单，以降低配置错误的风险并减轻管理开销
+  **缩小攻击面** 
  + 通过限制应用程序的暴露来最大限度地减少攻击面

**重要**  
Pod 的安全组提供两种强制模式：`strict`和`standard`。在 EKS 集群中同时使用网络策略和 Pod 安全组功能时，必须使用`standard`模式。

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

## 服务网格策略实施或 Kubernetes 网络策略
<a name="_service_mesh_policy_enforcement_or_kubernetes_network_policy"></a>

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

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

### 何时使用服务网格执行策略
<a name="_when_to_use_service_mesh_for_policy_enforcement"></a>
+ 对服务网格进行现有投资
+ 需要更高级的功能，例如流量管理、可观察性和安全性
  + 流量控制、负载平衡、断路、速率限制、超时等
  + 详细了解您的服务表现（延迟、错误率、每秒请求数、请求量等）
  + 你想实现和利用服务网格来实现 mTLS 等安全功能

### 选择 Kubernetes 网络策略以获得更简单的用例
<a name="_choose_kubernetes_network_policy_for_simpler_use_cases"></a>
+ 限制哪些 pod 可以相互通信
+ 与服务网格相比，网络策略需要的资源更少，因此非常适合更简单的用例或较小的集群，在这些群集中，运行和管理服务网格的开销可能不合理

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

## ThirdParty 网络策略引擎
<a name="_thirdparty_network_policy_engines"></a>

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

你可以在以下网址找到常见的 Kubernetes 网络策略列表。Calico https://github.com/ahmetb/kubernetes-network-policy-recipes. 的类似规则集可在以下网址找到 https://docs.projectcalico.org/security/calico-network-policy.

### 迁移到 Amazon VPC CNI 网络策略引擎
<a name="_migration_to_amazon_vpc_cni_network_policy_engine"></a>

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

#### 迁移工具
<a name="_migration_tool"></a>

为了帮助您完成迁移过程，我们开发了一种名为 [K8s 网络策略迁移器的工具，可将您现有的网络策略](https://github.com/awslabs/k8s-network-policy-migrator) CRD 转换为 Kubernetes 原生 Calico/Cilium 网络策略。转换后，您可以直接在运行 VPC CNI 网络策略控制器的新集群上测试转换后的网络策略。该工具旨在帮助您简化迁移过程并确保平稳过渡。

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

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

### 其他资源
<a name="_additional_resources"></a>
+  [Kubernetes & Tigera：网络策略、安全和审计](https://youtu.be/lEY2WnRHYpg) 
+  [印花布企业](https://www.tigera.io/tigera-products/calico-enterprise/) 
+  [Cilium](https://cilium.readthedocs.io/en/stable/intro/) 
+  [NetworkPolicy编辑](https://cilium.io/blog/2021/02/10/network-policy-editor) Cilium 的交互式策略编辑器
+  [Inspektor Gadget 建议网络策略小工具](https://www.inspektor-gadget.io/docs/latest/gadgets/advise/network-policy/)根据对网络流量的分析建议网络策略

## 传输中加密
<a name="_encryption_in_transit"></a>

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

### Nitro 实例
<a name="_nitro_instances"></a>

默认情况下，以下 Nitro 实例类型（例如 c5n、G4、i3en、m5dn、m5dn、m5n、p3dn、r5dn 和 r5n）之间交换的流量会自动加密。当有中间跳点（例如传输网关或负载均衡器）时，流量不会被加密。有关[传输中加密](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/data-protection.html#encryption-transit)的更多详细信息以及默认情况下支持网络加密的实例类型的完整列表，请参阅传输中的加密。

### 容器网络接口 (CNI)
<a name="_container_network_interfaces_cnis"></a>

 [WeaveNet](https://www.weave.works/oss/net/)可以配置为自动加密所有流量，使用 NaCl 加密套筒流量，使用 IPsec ESP 加密快速数据路径流量。

### 服务网格
<a name="_service_mesh"></a>

传输中的加密也可以使用 App Mesh、Linkerd v2 和 Istio 等服务网格来实现。 AppMesh 支持带有 X.509 证书的 [mTLS](https://docs.aws.amazon.com/app-mesh/latest/userguide/mutual-tls.html) 或 Envoy 的秘密发现服务 (SDS)。Linkerd 和 Istio 都支持 mTLS。

[aws-app-mesh](https://github.com/aws/aws-app-mesh-examples)-examples GitHub 存储库提供了使用 X.509证书配置 mTLS 和 SPIRE 作为你的 Envoy 容器的 SDS 提供者的演练：
+  [使用证书配置 mTLS X.509 ](https://github.com/aws/aws-app-mesh-examples/tree/main/walkthroughs/howto-k8s-mtls-file-based) 
+  [使用 SPIRE (SDS) 配置 TLS](https://github.com/aws/aws-app-mesh-examples/tree/main/walkthroughs/howto-k8s-mtls-sds-based) 

[App Mesh 还支持使用 AWS Certificate Manager](https://docs.aws.amazon.com/acm/latest/userguide/acm-overview.html) [(ACM) 颁发的私有证书或存储在虚拟节点本地文件系统中的证书进行 TLS 加密](https://docs.aws.amazon.com/app-mesh/latest/userguide/virtual-node-tls.html)。

[aws-app-mesh](https://github.com/aws/aws-app-mesh-examples)-examples GitHub 存储库提供了使用 ACM 颁发的证书和随你的 Envoy 容器打包的证书配置 TLS 的演练：
+  [使用文件提供的 TLS 证书配置 TLS](https://github.com/aws/aws-app-mesh-examples/tree/master/walkthroughs/howto-tls-file-provided) 
+  [使用 AWS Certifice Manager 配置 TLS](https://github.com/aws/aws-app-mesh-examples/tree/master/walkthroughs/tls-with-acm) 

### 入口控制器和负载均衡器
<a name="_ingress_controllers_and_load_balancers"></a>

入口控制器是您智能地将来自集群外部的 HTTP/S流量路由到集群内部运行的服务的一种方式。通常，这些 Ingress 前面有第 4 层负载均衡器，例如 Classic Load Balancer 或 Network Load Balancer (NLB)。加密流量可以在网络中的不同位置终止，例如在负载均衡器、入口资源或 Pod 上。终止 SSL 连接的方式和地点最终将由贵组织的网络安全策略决定。例如，如果您的策略要求端到端加密，则必须解密 Pod 上的流量。这将给你的 Pod 带来额外的负担，因为它必须花费周期来建立初始握手。总体 SSL/TLS 处理占用大量的 CPU 资源。因此，如果你有灵活性，可以尝试在 Ingress 或负载均衡器上执行 SSL 卸载。

#### 在 AWS 弹性负载均衡器中使用加密
<a name="_use_encryption_with_aws_elastic_load_balancers"></a>

[AWS Applicat](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html) ion Load Bal [ancer (ALB) 和网络负载均衡器](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/introduction.html) (NLB) 都支持传输加密（SSL 和 TLS）。ALB 的`alb.ingress.kubernetes.io/certificate-arn`注释允许您指定要向 ALB 添加哪些证书。如果您省略注释，控制器将尝试使用主机字段匹配可用的 [AWS Certificate Manager (ACM) 证书](https://docs.aws.amazon.com/acm/latest/userguide/acm-overview.html)，从而向需要该注释的侦听器添加证书。从 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 终止示例。
+  [使用 Contour 保护 EKS 入口然后我们来加密吧 GitOps ](https://aws.amazon.com/blogs/containers/securing-eks-ingress-contour-lets-encrypt-gitops/) 
+  [如何使用 ACM 终止亚马逊 EKS 工作负载上的 HTTPS 流量？](https://aws.amazon.com/premiumsupport/knowledge-center/terminate-https-traffic-eks-acm/) 

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

### 带证书管理器的 ACM 私有 CA
<a name="iam-cert-manager"></a>

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

#### Short-Lived 用于工作负载之间双向 TLS 的 CA 模式
<a name="iam-ca-mode"></a>

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

#### ACM 安装说明
<a name="_acm_setup_instructions"></a>

首先按照 [ACM 私有 CA 技术文档中提供的步骤创建私有 CA](https://docs.aws.amazon.com/acm-pca/latest/userguide/create-CA.html)。拥有私有 CA 后，请按照[常规](https://cert-manager.io/docs/installation/)安装说明安装证书管理器。[安装证书管理器后，按照中的设置说明安装私有 CA Kubernetes 证书管理器插件。 GitHub](https://github.com/cert-manager/aws-privateca-issuer#setup)该插件允许证书管理器向 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": "arn:aws:acm-pca:us-west-2:123456789012:certificate-authority/12345678-1234-1234-1234-123456789012"
        }
    ]
}
```

 也可以使用 [IAM 账户或 IRSA 的服务角色](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html)。有关完整示例，请参阅下面的 “其他资源” 部分。

在 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 的[证书资源指南](https://cert-manager.io/docs/usage/certificate/)。请@@ [在此处查看示例](https://github.com/cert-manager/aws-privateca-issuer/tree/main/config/samples/)。

### 带有 Istio 和证书管理器的 ACM 私有 CA
<a name="_acm_private_ca_with_istio_and_cert_manager"></a>

如果您在 EKS 集群中运行 Istio，则可以禁用 Istio 控制平面（特别是`istiod`）作为根证书颁发机构 (CA) 的功能，并将 ACM 私有 CA 配置为工作负载之间 mTLS 的根 CA。如果你要使用这种方法，可以考虑在 ACM 私有 *CA 中使用短暂的 CA 模式*。有关更多详细信息，请参阅[上一节](#iam-ca-mode)和此[博客文章](https://aws.amazon.com/blogs/security/how-to-use-aws-private-certificate-authority-short-lived-certificate-mode)。

#### 证书签名在 Istio 中的工作原理（默认）
<a name="_how_certificate_signing_works_in_istio_default"></a>

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](https://spiffe.io/) 身份的证书。此证书被称为 SPIFFE 可验证身份证件（或 SVID）。SVID 被分配给请求服务，用于识别和加密通信服务之间传输的流量。

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

![Istio 证书签名请求的默认流程](http://docs.aws.amazon.com/zh_cn/eks/latest/best-practices/images/security/default-istio-csr-flow.png)


#### 在 Istio 中如何使用 ACM 私有 CA 进行证书签名
<a name="_how_certificate_signing_works_in_istio_with_acm_private_ca"></a>

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

每当工作负载有 CSR 时，它就会被转发给 *istio-csr，后者将向* ACM Private CA 申请证书。*istio-csr* 和 ACM 私有 CA 之间的这种通信由 AW [S 私](https://github.com/cert-manager/aws-privateca-issuer)有 CA 颁发者插件启用。证书管理器使用此插件向 ACM 私有 CA 请求 TLS 证书。颁发者插件将与 ACM 私有 CA 服务通信，请求工作负载的签名证书。证书签名后，它将返回给 *istio-csr，后者将读取已签名的请求，并将其返回到启动 CSR* 的工作负载。

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

#### 带有私有 CA 设置说明的 Istio
<a name="_istio_with_private_ca_setup_instructions"></a>

1. 首先，按照[本节中相同的设置说明](#iam-cert-manager)完成以下操作：

1. 创建私有 CA

1. 安装证书管理器

1. 安装发行者插件

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

1. 创建`istio-system`命名空间。这是 Istio `istiod certificate` 和其他 Istio 资源将部署到此处。

1. 安装配置有 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"
   ```

1. 使用自定义配置安装 Istio，`cert-manager istio-csr`将其`istiod`替换为网格的证书提供商。这个过程可以使用 [Istio 运算符](https://tetrate.io/blog/what-is-istio-operator/)来执行。

   ```
   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
   ```

1. 部署您创建的上述自定义资源。

   ```
   istioctl operator init
   kubectl apply -f istio-custom-config.yaml
   ```

1. 现在，您可以将工作负载部署到 EKS 集群中的网格并[强制执行 mTLS](https://istio.io/latest/docs/reference/config/security/peer_authentication/)。

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

## 工具和资源
<a name="_tools_and_resources"></a>
+  [Amazon EKS 安全沉浸式研讨会-网络安全](https://catalog.workshops.aws/eks-security-immersionday/en-US/6-network-security) 
+  [如何实现证书管理器和 ACM 私有 CA 插件以在 EKS 中启用 TLS](https://aws.amazon.com/blogs/security/tls-enabled-kubernetes-clusters-with-acm-private-ca-and-amazon-eks-2/)。
+  使用@@ [新的 AWS Load Balancer 控制器和 ACM 私有 CA 在 Amazon EKS 上设置端到端 TLS 加密](https://aws.amazon.com/blogs/containers/setting-up-end-to-end-tls-encryption-on-amazon-eks-with-the-new-aws-load-balancer-controller/)。
+  [私有 CA Kubernetes 证书](https://github.com/cert-manager/aws-privateca-issuer)管理器插件已开启。 GitHub
+  [私有 CA Kubernetes 证书管理器插件](https://docs.aws.amazon.com/acm-pca/latest/userguide/PcaKubernetes.html)用户指南。
+  [如何使用 AWS 私有证书颁发机构短期证书模式](https://aws.amazon.com/blogs/security/how-to-use-aws-private-certificate-authority-short-lived-certificate-mode) 
+  [egress-operator 一个操作](https://github.com/monzo/egress-operator)员和 DNS 插件，无需协议检查即可控制来自集群的出口流量
+  [NeuVector 由 SUSE](https://www.suse.com/neuvector/) 开源提供的零信任容器安全平台提供策略网络规则、数据丢失防护 (DLP)、Web 应用程序防火墙 (WAF) 和网络威胁签名。