每个 Pod 的安全组 - Amazon EKS

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

每个 Pod 的安全组

AWS安全组充当EC2实例的虚拟防火墙,用于控制入站和出站流量。默认情况下,Amazon VPC CNI 将在节点ENI上使用与主节点关联的安全组。更具体地说,与该实例ENI关联的每个实例都将具有相同EC2的安全组。因此,节点上的每个 Pod 都与其运行所在的节点共享相同的安全组。

如下图所示,在工作节点上运行的所有应用程序 Pod 都将有权访问RDS数据库服务(考虑到RDS入站允许节点安全组)。安全组太粗糙了,因为它们适用于节点上运行的所有 Pod。Pods 安全组为工作负载提供网络分段,这是良好的深度防御策略的重要组成部分。

连接安全组的节点的插图 RDS

借助 Pod 的安全组,您可以通过在共享计算资源上运行具有不同网络安全要求的应用程序来提高计算效率。多种类型的安全规则(例如 Pod-to-Pod和 Pod-to-ExternalAWS服务)可以通过EC2安全组在同一个地方定义,并应用于使用 Kubernetes 原生的工作负载。APIs下图显示了在 Pod 级别应用的安全组,以及它们如何简化您的应用程序部署和节点架构。Pod 现在可以访问亚马逊RDS数据库了。

带有不同安全组的 pod 和节点连接的插图 RDS

您可以通过设置为 ENABLE_POD_ENI=true Pod 启用安全组VPCCNI。启用后,在控制平面上运行的VPC资源控制器(由管理EKS)会创建名为 “`aws-k8” 的中继接口并将其连接到节s-trunk-eni点。中继接口充当连接到实例的标准网络接口。要管理中继接口,您必须将AmazonEKSVPCResourceController托管策略添加到 Amazon 集群附带的EKS集群角色中。

控制器还创建名为 “aws-k8s-branch-eni” 的分支接口,并将它们与中继接口相关联。使用SecurityGroupPolicy自定义资源为 Pod 分配了一个安全组,并与分支接口关联。由于安全组是通过网络接口指定的,因此我们现在可以在这些额外的网络接口上安排需要特定安全组的 Pod。查看 Pod 安全组的EKS用户指南部分,包括部署先决条件。

带有与之关联的安全组的工作器子网的插图 ENIs

分支接口容量是辅助 IP 地址的现有实例类型限制的补充。使用安全组的 Pod 不包含在 max-pods 公式中,当你对 Pod 使用安全组时,你需要考虑提高 max-pods 值,或者可以运行的容量少于节点实际支持的数量。

m5.large 最多可以有 9 个分支网络接口和最多 27 个辅助 IP 地址分配给其标准网络接口。如下例所示,m5.large 的默认最大容量为 29,并将使用安全组的 Pod EKS 计入最大 Pod 数。有关如何更改节点的最大 pod 数的说明,请参阅EKS用户指南

当 Pod 的安全组与自定义网络结合使用时,将使用 Pod 的安全组中定义的安全组,而不是中指定的安全组ENIConfig。因此,启用自定义联网后,在使用每个 Pod 的安全组时,请仔细评估安全组的顺序。

建议

禁用 Liveness Probe 的TCP早期解复用

如果你使用的是存活或就绪探针,你还需要禁用TCP早期的解复用器,这样 kubelet 就可以通过连接到分支网络接口上的 Pod。TCP只有在严格模式下才需要这样做。为此,请运行以下命令:

kubectl edit daemonset aws-node -n kube-system

在该initContainer部分下,将的值更改为 DISABLE_TCP_EARLY_DEMUX true.

使用适用于 Pod 的安全组来利用现有的AWS配置投资。

通过安全组,可以更轻松地限制对RDS数据库或EC2实例等VPC资源的网络访问。每个 Pod 的安全组的一个明显优势是可以重复使用现有AWS的安全组资源。如果您使用安全组作为网络防火墙来限制对AWS服务的访问,我们建议使用分支将安全组应用于 Pod ENIs。如果您要将应用程序从EC2实例转移到实例,EKS并通过安全组限制对其他AWS服务的访问,请考虑为 Pod 使用安全组。

配置 Pod 安全组强制模式

亚马逊VPCCNI插件版本 1.11 添加了一个名为POD_SECURITY_GROUP_ENFORCING_MODE(“强制模式”)的新设置。强制模式既控制哪些安全组适用于 pod,也控制源NAT是否已启用。您可以将强制模式指定为严格模式或标准模式。strict 是默认值,反映了ENABLE_POD_ENI设置为VPCCNI的之前的行为true

在严格模式下,仅强制执行分支ENI安全组。源也NAT被禁用。

在标准模式下,将应用与主节点ENI和分支机构关联的安全组ENI(与 Pod 关联)。网络流量必须符合两个安全组的要求。

警告

任何模式更改都只会影响新推出的 Pod。现有 Pod 将使用创建 Pod 时配置的模式。如果客户想要改变流量行为,则需要使用安全组回收现有 Pod。

强制模式:使用严格模式隔离 Pod 和节点流量:

默认情况下,Pod 的安全组设置为 “严格模式”。如果您必须将 Pod 流量与节点的其余流量完全分开,请使用此设置。在严格模式下,源NAT处于关闭状态,因此可以使用分支机构ENI出站安全组。

警告

启用严格模式后,所有来自 Pod 的出站流量都将离开节点并进入VPC网络。同一节点上 Pod 之间的流量将通过VPC. 这会增加VPC流量并限制基于节点的功能。严格模式 NodeLocal DNSCache不支持。

强制模式:在以下情况下使用标准模式

Pod 中的容器可以看到客户端源 IP

如果您需要保持 Pod 中的容器可见客户端源 IP,请考虑POD_SECURITY_GROUP_ENFORCING_MODE将其设置为standard。Kubernetes 服务支持 externalTrafficPolicy =local 以支持保留客户端源 IP(默认类型的集群)。现在,你可以在标准模式下运行类型为 Kubernetes 的服务, NodePort 并 LoadBalancer 使用 externalTrafficPolicy 设置为 “本地” 的实例目标。 Local保留客户端源 IP,避免再次跳转 LoadBalancer 并 NodePort 键入服务。

正在部署 NodeLocal DNSCache

为 Pod 使用安全组时,请将标准模式配置为支持使用的 Pod NodeLocal DNSCache。 NodeLocal DNSCache通过在群集节点上运行DNS缓存代理来提高群集DNS性能 DaemonSet。这将帮助DNSQPS要求最高的 pod 查询具有本地缓存的本地 kube-DNS/CoreDNS,从而缩短延迟。

NodeLocal DNSCache在严格模式下不支持,因为所有网络流量,甚至是流向节点的流量,都会进入VPC。

支持 Kubernetes 网络政策

对于关联安全组的 Pod 使用网络策略时,我们建议使用标准强制模式。

我们强烈建议使用适用于 Pod 的安全组来限制对不属于集群的AWS服务的网络级访问。考虑使用网络策略来限制集群内 Pod 之间的网络流量,通常称为东/西流量。

识别每个 Pod 与安全组的不兼容性

基于 Windows 的实例和非硝基实例不支持 Pod 的安全组。要将安全组与 Pod 一起使用,实例必须使用标记 isTrunkingEnabled。如果您的 Pod 不依赖于您内部或外部的任何AWS服务,请使用网络策略来管理 Pod 之间的访问权限,而不是安全组VPC。

使用每个 Pod 的安全组来有效地控制流向AWS服务的流量

如果在EKS集群中运行的应用程序必须与中的其他资源(例如RDS数据库)通信VPC,则可以考虑使用 for p SGs od。虽然有些策略引擎允许您指定CIDR或DNS名称,但在与终端节点位于中的AWS服务通信时,它们并不是最佳选择VPC。

相比之下,Kubernetes 网络策略提供了一种控制集群内外的入口和出口流量的机制。如果您的应用程序对其他服务的依赖性有限,则应考虑 Kubernetes 网络策略。AWS您可以配置网络策略,根据CIDR范围指定出口规则,以限制对AWS服务的访问,而不是像这样的AWS本机语义。SGs您可以使用 Kubernetes 网络策略来控制 Pod 之间的网络流量(通常称为东西向流量)以及 Pod 与外部服务之间的网络流量。Kubernetes 网络策略是在第 3 OSI 级和第 4 级实施的。

亚马逊EKS允许您使用 C alicoC ilium 等网络策略引擎。默认情况下,不安装网络策略引擎。有关如何设置的说明,请查看相应的安装指南。有关如何使用网络策略的更多信息,请参阅EKS安全最佳实践。DNS主机名功能在网络策略引擎的企业版中可用,该功能可用于控制 Kubernetes Services/Pod 与在外部运行的资源之间的流量。AWS此外,您可以考虑为默认不支持安全组的AWS服务提供DNS主机名支持。

标记单个安全组以使用AWS负载均衡器控制器

当为一个 Pod 分配了多个安全组时,Amazon EKS 建议将单个安全组标记为kubernetes.io/cluster/$name共享或所有安全组。该标签允许AWS负载均衡器控制器更新安全组的规则,将流量路由到 Pod。如果只为 Pod 分配了一个安全组,则标签的分配是可选的。在安全组中设置的权限是累加的,因此标记单个安全组就足以让负载均衡器控制器找到和协调规则。它还有助于遵守安全组定义的默认配额

NAT为出站流量进行配置

对于来自分配了安全组NAT的 Pod 的出站流量,源被禁用。对于使用需要访问互联网的安全组的 Pod,在配置有网NAT关或实例的私有子网上启动工作节点,并在SNAT中启用外部。CNI

kubectl set env daemonset -n kube-system aws-node AWS_VPC_K8S_CNI_EXTERNALSNAT=true

将带有安全组的 Pod 部署到私有子网

分配了安全组的 Pod 必须在部署到私有子网的节点上运行。请注意,已分配安全组部署到公共子网的 Pod 将无法访问互联网。

在 Pod 规格文件中验证terminationGracePeriod秒数

确保terminationGracePeriodSeconds在 Pod 规范文件中该值为非零(默认为 30 秒)。VPCCNI要让 Amazon 从工作节点中删除 Pod 网络,这是必不可少的。设置为零时,CNI插件不会从主机上移除 Pod 网络,ENI也不会有效地清理分支。

对带有 Fargate 的 Pod 使用安全组

在 Fargate 上运行的 Pod 的安全组的工作方式与在工作节点上EC2运行的 Pod 非常相似。例如,在与 Fargate Pod 关联的 Fargate Pod 中引用安全组之前, SecurityGroupPolicy 您必须先创建安全组。默认情况下,如果您没有明确分配给 Fargate 容器,则会将集群安全组分配给 SecurityGroupPolicy 所有 Fargate Pod。为简单起见,你可能需要将集群安全组添加到 Fagate Pod 中, SecurityGroupPolicy 否则你必须向你的安全组添加最低安全组规则。你可以使用 describe API-cluster 来找到集群安全组。

aws eks describe-cluster --name CLUSTER_NAME --query 'cluster.resourcesVpcConfig.clusterSecurityGroupId'
cat >my-fargate-sg-policy.yaml <<EOF apiVersion: vpcresources.k8s.aws/v1beta1 kind: SecurityGroupPolicy metadata: name: my-fargate-sg-policy namespace: my-fargate-namespace spec: podSelector: matchLabels: role: my-fargate-role securityGroups: groupIds: - cluster_security_group_id - my_fargate_pod_security_group_id EOF

列出了最低安全组规则。这些规则允许 Fargate Pods 与 kube-apiserver、kubelet 和 Core 等集群内服务进行通信。DNS您还需要添加规则以允许进出您的 Fargate Pod 的入站和出站连接。这将允许你的 Pod 与你中的其他 Pod 或资源通信VPC。此外,您还必须包括规则,让 Fargate 从亚马逊ECR或其他容器注册表(例如)提取容器镜像。 DockerHub有关更多信息,请参阅《AWS一般参考》中的 AWS IP 地址范围。

您可以使用以下命令来查找应用于 Fargate Pod 的安全组。

kubectl get pod FARGATE_POD -o jsonpath='{.metadata.annotations.vpc\.amazonaws\.com/pod-eni}{"\n"}'

记下 eniId 来自上面的命令。

aws ec2 describe-network-interfaces --network-interface-ids ENI_ID --query 'NetworkInterfaces[*].Groups[*]'

必须删除并重新创建现有的 Fargate 容器才能应用新的安全组。例如,以下命令启动示例应用程序的部署。要更新特定的 pod,可以在以下命令中更改命名空间和部署名称。

kubectl rollout restart -n example-ns deployment example-pod

📝 编辑此页面 GitHub