为 Kubernetes 网络策略配置集群
默认情况下,Kubernetes 对集群中任何 Pods 之间或 Pods 与任何其他网络中的资源之间的 IP 地址、端口或连接没有限制。您可以使用 Kubernetes 网络策略来限制进出 Pods 的网络流量。有关更多信息,请参阅 Kubernetes 文档中的网络策略
如果您的集群上有 1.13
版本或更早版本的 Amazon VPC CNI plugin for Kubernetes,则需要实施第三方解决方案来将 Kubernetes 网络策略应用于集群。1.14
版本或更高版本的插件可以实施网络策略,因此您无需使用第三方解决方案。在本主题中,您将了解如何将集群配置为在不使用第三方附加组件的情况下在集群上使用 Kubernetes 网络策略。
Amazon VPC CNI plugin for Kubernetes 中的网络策略在以下配置中受支持。
-
1.25
版本及更高版本的 Amazon EKS 集群。 -
集群上 1.14 版本或更高版本的 Amazon VPC CNI plugin for Kubernetes。
-
为
IPv4
或IPv6
地址配置的集群。 -
您可以将网络策略与 Pods 的安全组结合使用。通过网络策略,您可以控制集群内的所有通信。借助 Pods 的安全组,您可以控制从 Pod 中的应用程序对 Amazon Web Services 的访问。
-
您可以将网络策略与自定义网络和前缀委派结合使用。
注意事项
-
当使用 Amazon VPC CNI plugin for Kubernetes 将 Amazon VPC CNI plugin for Kubernetes 网络策略应用于集群时,您只能将策略应用于 Amazon EC2 Linux 节点。无法将策略应用于 Fargate 或 Windows 节点。
-
如果您的集群当前使用第三方解决方案来管理 Kubernetes 网络策略,则可以将这些策略与 Amazon VPC CNI plugin for Kubernetes 结合使用。但是,您必须删除现有的解决方案,使其不再管理相同的策略。
-
您可以对同一 Pod 应用多个网络策略。当配置两个或多个选择相同 Pod 的策略时,所有策略都将应用于 Pod。
-
网络策略中每个
ingress:
或egress:
选择器中每个协议的唯一端口组合数最多为 8 个。 -
对于任何 Kubernetes 服务,服务端口必须与容器端口相同。如果您使用的是命名端口,也请在服务规范中使用相同的名称。
-
Amazon VPC CNI plugin for Kubernetes 为容器组(pod)配置网络策略,同时进行容器组(pod)预置。在为新的容器组(pod)配置所有策略之前,新的容器组(pod)中的容器将从默认允许策略开始。允许所有进出新容器组(pod)的流量,除非这些流量根据现有策略进行了解析。
-
网络策略功能创建并需要一个名为
policyendpoints.networking.k8s.aws
的PolicyEndpoint
自定义资源定义(CRD)。自定义资源的PolicyEndpoint
对象由 Amazon EKS 管理。您不应该修改或删除这些资源。 -
如果您运行的容器组(pod)使用实例角色 IAM 凭证或连接到 EC2 IMDS,请注意检查是否存在会阻止访问 EC2 IMDS 的网络策略。您可能需要添加网络策略以允许访问 EC2 IMDS。有关更多信息,请参阅《适用于 Linux 实例的 Amazon EC2 用户指南》中的实例元数据和用户数据。
对服务账户使用 IAM 角色的容器组(pod)无法访问 EC2 IMDS。
-
默认情况下,网络策略功能使用节点上的端口
8162
获取指标。此外,该功能还使用端口8163
进行运行状况探测。如果您在需要使用这些端口的节点或 Pod 内运行其他应用程序,则该应用程序将无法运行。在 VPC CNI 版本v1.14.1
或更高版本中,您可以在以下位置更改这些端口:
先决条件
-
最低集群版本
现有 Amazon EKS 集群。要部署一个角色,请参阅 开始使用 Amazon EKS。集群必须是
1.25
版本或更高版本的 Kubernetes。该集群必须运行下表中列出的 Kubernetes 版本和平台版本之一。请注意,所有比所列版本更高的 Kubernetes 和平台版本也受支持。您可以通过将以下命令中的my-cluster
替换为集群名称,然后运行修改后的命令来检查当前的 Kubernetes 版本:aws eks describe-cluster --name
my-cluster
--query cluster.version --output textKubernetes 版本
平台版本
1.27.4
eks.5
1.26.7
eks.6
1.25.12
eks.7
-
最低 Amazon CNI 版本
集群上
1.14
版本或更高版本的 Amazon VPC CNI plugin for Kubernetes。您可以使用以下命令查看当前使用的版本。kubectl describe daemonset aws-node --namespace kube-system | grep amazon-k8s-cni: | cut -d : -f 3
如果您的版本低于
1.14
,请查看 更新 Amazon EKS 附加组件 将版本升级到1.14
版本或更高版本。 -
最低 Amazon 内核版本
您的节点必须具有 Linux 内核版本
5.10
或更高版本。您可以使用uname -r
检查您的内核版本。如果您使用的是最新版本的 Amazon EKS 优化版 Amazon Linux 和 Bottlerocket AMI,那么它们已经具有所需的内核版本。Amazon EKS 优化加速型 Amazon Linux AMI 具有内核
5.4
,因此这些 AMI 不能与网络策略结合使用。
将集群配置为使用 Kubernetes 网络策略
-
挂载 BPF 文件系统
注意
如果您的集群是版本
1.27
或更高版本,则可以跳过此步骤,因为所有 Amazon EKS 优化版 Amazon Linux 和 Bottlerocket AMI1.27
或更高版本都已具有此功能。对于所有其他集群版本,如果您将 Amazon EKS 优化版 Amazon Linux 升级到版本
v20230703
或更高版本,或者将 Bottlerocket AMI 升级到版本v1.0.2
或更高版本,则可以跳过此步骤。-
在每个节点上挂载 Berkeley Packet Filter(BPF)文件系统。
sudo mount -t bpf bpffs /sys/fs/bpf
-
然后,将相同的命令添加到 Amazon EC2 Auto Scaling 的启动模板中的用户数据。
-
-
在 VPC CNI 中启用网络策略
-
查看集群上当前安装的附加组件类型。根据您创建集群时使用的工具,您的集群上目前可能没有安装 Amazon EKS 附加组件类型。将
my-cluster
替换为您集群的名称。aws eks describe-addon --cluster-name
my-cluster
--addon-name vpc-cni --query addon.addonVersion --output text如果返回来的是版本号,则表明您的集群上安装有 Amazon EKS 类型的附加组件,而且此流程中其余的步骤,您也不需要走完。如果返回来的是一个错误,则表明您的集群上没有安装 Amazon EKS 类型的附加组件。
-
-
Amazon EKS 附加组件
-
自行管理的附加组件
-
-
-
确认
aws-node
容器组(pod)正在您的集群上运行。kubectl get pods -n kube-system | grep 'aws-node\|amazon'
示例输出如下。
aws-node-
gmqp7
2/2 Running 1 (24h ago) 24h aws-node-prnsh
2/2 Running 1 (24h ago) 24h如果启用网络策略,则
aws-node
容器组(pod)中有 2 个容器。在以前的版本中,如果禁用网络策略,则aws-node
容器组(pod)中只有 1 个容器。您现在可以将 Kubernetes 网络策略部署到集群。有关更多信息,请参阅Kubernetes 网络策略。
Stars 网络策略演示
该演示在您的 Amazon EKS 集群上创建前端、后端和客户端服务。该演示还创建管理图形用户界面,用于显示各服务之间可用的传入和传出路径。我们建议您在不运行生产工作负载的集群上完成演示。
在您创建任何网络策略之前,所有服务可以双向通信。在应用网络策略后,您可以看到客户端只能与前端服务进行通信,而后端只能接受来自前端的流量。
运行 Stars 策略演示
-
应用前端、后端、客户端和管理用户界面服务:
kubectl apply -f https://eksworkshop.com/beginner/120_network-policies/calico/stars_policy_demo/create_resources.files/namespace.yaml kubectl apply -f https://eksworkshop.com/beginner/120_network-policies/calico/stars_policy_demo/create_resources.files/management-ui.yaml kubectl apply -f https://eksworkshop.com/beginner/120_network-policies/calico/stars_policy_demo/create_resources.files/backend.yaml kubectl apply -f https://eksworkshop.com/beginner/120_network-policies/calico/stars_policy_demo/create_resources.files/frontend.yaml kubectl apply -f https://eksworkshop.com/beginner/120_network-policies/calico/stars_policy_demo/create_resources.files/client.yaml
-
请查看集群上的所有 Pods。
kubectl get pods -A
示例输出如下。
在输出中,您应该会在以下输出中显示的命名空间中看到容器。容器组(pod)的
NAMES
和READY
列中的容器组(pod)数量与以下输出中的不同。在看到具有相似名称的容器并且它们在STATUS
列中都具有Running
之前,请不要继续。NAMESPACE NAME READY STATUS RESTARTS AGE [...] client client-
xlffc
1/1
Running 05m19s
[...] management-ui management-ui-qrb2g
1/1
Running 05m24s
stars backend-sz87q
1/1
Running 05m23s
stars frontend-cscnf
1/1
Running 05m21s
[...] -
要连接到管理用户界面,请连接到集群上运行的
EXTERNAL-IP
服务:kubectl get service/management-ui -n management-ui
-
打开浏览器,进入上一步中的位置。您应该会看到管理用户界面。C 节点是客户端服务,F 节点是前端服务,B 节点是后端服务。每个节点都有到所有其他节点的完整通信访问权限(如粗体、彩色行所示)。
-
在
stars
和client
命名空间中应用以下网络策略,以将服务彼此隔离:kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: name: default-deny spec: podSelector: matchLabels: {}
您可以使用以下命令将策略应用于两个命名空间:
kubectl apply -n stars -f https://eksworkshop.com/beginner/120_network-policies/calico/stars_policy_demo/apply_network_policies.files/default-deny.yaml kubectl apply -n client -f https://eksworkshop.com/beginner/120_network-policies/calico/stars_policy_demo/apply_network_policies.files/default-deny.yaml
-
刷新您的浏览器。您可以看到管理用户界面不再能访问任何节点,因此它们不会显示在用户界面中。
-
应用以下不同的网络策略以允许管理用户界面访问这些服务。应用此策略以允许 UI:
kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: namespace: stars name: allow-ui spec: podSelector: matchLabels: {} ingress: - from: - namespaceSelector: matchLabels: role: management-ui
应用此策略以允许客户端:
kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: namespace: client name: allow-ui spec: podSelector: matchLabels: {} ingress: - from: - namespaceSelector: matchLabels: role: management-ui
您可以使用以下命令应用这两个策略:
kubectl apply -f https://eksworkshop.com/beginner/120_network-policies/calico/stars_policy_demo/apply_network_policies.files/allow-ui.yaml kubectl apply -f https://eksworkshop.com/beginner/120_network-policies/calico/stars_policy_demo/apply_network_policies.files/allow-ui-client.yaml
-
刷新您的浏览器。您可以看到管理用户界面可以再次访问节点,但各节点无法相互通信。
-
应用以下网络策略以允许流量从前端服务传到后端服务:
kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: namespace: stars name: backend-policy spec: podSelector: matchLabels: role: backend ingress: - from: - podSelector: matchLabels: role: frontend ports: - protocol: TCP port: 6379
-
刷新您的浏览器。您将看到前端可以与后端进行通信。
-
应用以下网络策略以允许流量从客户端传到前端服务:
kind: NetworkPolicy apiVersion: networking.k8s.io/v1 metadata: namespace: stars name: frontend-policy spec: podSelector: matchLabels: role: frontend ingress: - from: - namespaceSelector: matchLabels: role: client ports: - protocol: TCP port: 80
-
刷新您的浏览器。您将看到客户端可以与前端服务进行通信。前端服务仍可以与后端服务进行通信。
-
(可选)完成该演示后,您可以删除其资源。
kubectl delete -f https://eksworkshop.com/beginner/120_network-policies/calico/stars_policy_demo/create_resources.files/client.yaml kubectl delete -f https://eksworkshop.com/beginner/120_network-policies/calico/stars_policy_demo/create_resources.files/frontend.yaml kubectl delete -f https://eksworkshop.com/beginner/120_network-policies/calico/stars_policy_demo/create_resources.files/backend.yaml kubectl delete -f https://eksworkshop.com/beginner/120_network-policies/calico/stars_policy_demo/create_resources.files/management-ui.yaml kubectl delete -f https://eksworkshop.com/beginner/120_network-policies/calico/stars_policy_demo/create_resources.files/namespace.yaml
甚至在删除资源后,节点上仍可能存在网络策略端点,这些端点可能会以意想不到的方式干扰集群中的网络。删除这些规则的唯一可靠方法是重新启动节点或终止所有节点并将它们回收。要终止所有节点,请将自动扩缩组所需计数设置为 0,然后创建所需数量的备份,或者仅终止节点。
排查网络策略问题
您可以通过查看 网络策略日志 和运行 eBPF SDK 中的工具,对使用网络策略的网络连接进行问题排查和调查。
网络策略日志
网络策略是允许还是拒绝连接将记录在流日志中。每个节点上的网络策略日志包括每个具有网络策略的容器组(pod)流日志。网络策略日志存储在 /var/log/aws-routed-eni/network-policy-agent.log
。以下示例来自 network-policy-agent.log
文件:
{"level":"info","timestamp":"2023-05-30T16:05:32.573Z","logger":"ebpf-client","msg":"Flow Info: ","Src
IP":"192.168.87.155","Src Port":38971,"Dest IP":"64.6.160","Dest
Port":53,"Proto":"UDP","Verdict":"ACCEPT"}
将网络策略日志发送到 Amazon CloudWatch Logs
您可以使用 Amazon CloudWatch Logs 等服务监控网络策略日志。您可以使用以下方法将网络策略日志发送到 CloudWatch Logs。
对于 EKS 集群,策略日志将放在 /aws/eks/
下;对于自行管理的 K8S 集群,日志将放在 cluster-name
/cluster//aws/k8s-cluster/cluster
/ 下。
使用 Amazon VPC CNI plugin for Kubernetes 发送网络策略日志
如果启用网络策略,则会将第二个容器添加到节点代理的 aws-node
容器组(pod)。此节点代理可将网络策略日志发送到 CloudWatch Logs。
注意
节点代理仅发送网络策略日志。不包括 VPC CNI 生成的其他日志。
先决条件
-
将以下权限作为节或单独的策略添加到您用于 VPC CNI 的 IAM 角色中。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "logs:DescribeLogGroups", "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "*" } ] }
Amazon EKS 附加组件
自行管理的附加组件
使用 Fluent Bit 守护程序集发送网络策略日志
如果您在守护进程集中使用 Fluent Bit 从节点发送日志,则可以添加配置以包含来自网络策略的网络策略日志。您可以使用以下示例配置:
[INPUT] Name tail Tag eksnp.* Path /var/log/aws-routed-eni/network-policy-agent*.log Parser json DB /var/log/aws-routed-eni/flb_npagent.db Mem_Buf_Limit 5MB Skip_Long_Lines On Refresh_Interval 10
已包含 eBPF SDK
Amazon VPC CNI plugin for Kubernetes 在节点上安装 eBPF SDK 工具集。您可以使用 eBPF SDK 工具来识别网络策略问题。例如,以下命令列出了节点上正在运行的程序。
sudo /opt/cni/bin/aws-eks-na-cli ebpf progs
要运行此命令,您可以使用任何方法连接到节点。
Kubernetes 网络策略
要实施 Kubernetes 网络策略,您需要创建 Kubernetes NetworkPolicy
对象并将它们部署到集群。NetworkPolicy
对象的范围限定到命名空间。您可以实施策略,根据标签选择器、命名空间和 IP 地址范围来允许或拒绝 Pods 之间的流量。有关创建 NetworkPolicy
对象的更多信息,请参阅 Kubernetes 文档中的网络策略
Kubernetes NetworkPolicy
对象的执行是使用 Extended Berkeley Packet Filter (eBPF) 实施的。与基于 iptables
的实施相比,它具有更低的延迟和性能,包括降低 CPU 利用率和避免顺序查找。此外,eBPF 探测器还可以访问上下文丰富的数据,帮助调试复杂的内核级问题并提高可观测性。Amazon EKS 支持基于 eBPF 的导出器,该导出器利用探测器记录每个节点上的策略结果,并将数据导出到外部日志收集器以帮助调试。有关更多信息,请参阅 eBPF 文档