本页面介绍如何为 Pod 设置服务流量导向。
如需了解服务流量导向的工作原理,请参阅服务流量导向的工作原理。
要求
- GKE 1.30 版或更高版本。
限制
- 一个
ServiceFunctionChain
最多只能有一个服务功能。 - 我们建议最多使用 100 个节点外加 10 个
ServiceFunctionChain
和TrafficSelector
对。 - GKE 服务流量导向仅适用于运行 Container-Optimized OS 节点映像的节点。
- GKE 服务流量导向仅支持出站流量和目标 IP 地址。
- 服务流量导向不会处理在将具有相同前缀长度的多个流量选择器应用于同一主体时出现的冲突。为避免冲突,请主动设计具有不重叠 IP 地址范围和明确定义的选择条件的流量选择器。
实现服务流量导向
借助 GKE 服务流量导向,您可以自定义和控制集群内的网络流量流。本部分演示了如何使用 Web 网关示例实现服务流量导向。
请考虑一个应用场景,您希望创建一个 Web 网关来保护从最终用户客户端设备到互联网的流量。VPN 终止器使用安全隧道将流量引入托管式网关。最终用户流量会重定向到防火墙,然后再重定向到代理。代理会对流量执行来源网络地址转换 (SNAT),遮盖原始来源地址,然后将其向外发送到互联网。
如需实现 GKE 服务流量导向,请执行以下操作:
- 创建 MTU 为 8896 的 VPC。
- 创建 GKE 集群。
- 创建服务功能 Pod 和服务。
- 创建
ServiceFunctionChain
。 - 创建引用
ServiceFunctionChain
的TrafficSelector
资源。
准备工作
在开始之前,请确保您已执行以下任务:
- 启用 Google Kubernetes Engine API。 启用 Google Kubernetes Engine API
- 如果您要使用 Google Cloud CLI 执行此任务,请安装并初始化 gcloud CLI。 如果您之前安装了 gcloud CLI,请运行
gcloud components update
以获取最新版本。
价格
只有启用了 GKE Enterprise 的项目中的集群支持以下 Network Function Optimizer (NFO) 功能:
- 对 Pod 的多网络支持
- 对 Pod 的永久性 IP 地址支持(预览版)
- 多网络网络政策(预览版)
- 对 Pod 的服务流量导向支持(预览版)
如需了解启用 Google Kubernetes Engine (GKE) Enterprise 版本的相关费用,请参阅 GKE Enterprise 价格。
准备 VPC
准备 VPC。服务流量导向使用封装将流量重定向到相应的服务功能。封装涉及向每个数据包添加额外标头,这会增加数据包大小。服务流量导向不需要在 VPC 中进行特殊配置。在准备 VPC 时,我们建议您在确定 MTU 大小时考虑封装开销。如需了解详情,请参阅具有指定 MTU 的 VPC 网络。
以下命令会在您的 VPC 中设置 mtu 大小:
gcloud compute networks create VPC_NETWORK_NAME --mtu=8896
将 VPC_NETWORK_NAME
替换为包含子网的 VPC 网络的名称。
创建 GKE 集群
如需启用在 GKE 上实现服务流量导向所需的高级网络路由和 IP 地址管理功能,请create启用了 GKE Dataplane V2 的 GKE 集群,如下所示:
gcloud container clusters create CLUSTER_NAME \
--network VPC_NAME \
--release-channel RELEASE_CHANNEL \
--cluster-version CLUSTER_VERSION \
--enable-dataplane-v2 \
--enable-ip-alias
替换以下内容:
CLUSTER_NAME
:集群的名称。VPC_NAME
:要与集群关联的 VPC 的名称。RELEASE_CHANNEL
:发布渠道的名称。VERSION
:GKE 版本,必须为 1.30 或更高版本。您还可以使用--release-channel
标志来选择发布渠道。发布渠道必须具有默认版本 1.30 或更高版本。
创建 ServiceFunction
Pod
如需建立服务链,请在集群中部署 VPN 终止器 Pod 和所需服务功能 Pod。Pod 会封装执行网络功能的容器化应用。
VPN 终止器 Pod 通常是链中的第一个服务功能,它会终止通过 VPN 进入集群的流量。它随后会定向其他服务功能(例如防火墙和负载均衡)以进行进一步处理,然后再到达最终目标。
以下示例配置文件定义了以下三个组件,这些组件对于集群中的网络流量管理至关重要:
- VPN Pod:在集群中建立虚拟专用网 (VPN) 端点,从而实现集群与外部网络之间的安全和加密通信。
- 防火墙部署:部署防火墙 Pod 的多个副本,这些副本可提供安全性和负载均衡。
- 代理 DaemonSet:在集群的每个节点上部署代理 Pod,以确保网络流量可以在转发到其他服务(如防火墙)之前在本地进行处理。
将以下示例清单保存为 service_function.yaml
:
apiVersion: v1
kind: Pod
name: vpn
namespace: vpn
labels:
app: vpn
spec:
containers:
- name: vpn
image: openvpn
ports:
- containerPort: 51820
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: firewall
namespace: firewall
spec:
replicas: 3
selector:
matchLabels:
app: firewall
template:
metadata:
labels:
app: firewall
spec:
containers:
- name: firewall
image: firewall
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: proxy
namespace: proxy
spec:
selector:
matchLabels:
app: proxy
template:
metadata:
labels:
app: proxy
spec:
containers:
- name: proxy
image: proxy
应用清单:
kubectl apply -f service_function.yaml
创建“ServiceFunctionChains
”
如需定义供流量遍历的一系列网络功能,请创建一个流水线,其中每个功能(如防火墙、代理和负载均衡器)都会先执行其特定任务,再将流量传递给下一个功能。
将以下示例清单保存为 ServiceFunctionChain.yaml
:
apiVersion: networking.gke.io/v1
kind: ServiceFunctionChain
metadata:
name: firewall
spec:
sessionAffinity:
clientIpNoDestination:
timeoutSeconds: 3600 # 1hr
serviceFunctions:
- name: firewall
namespace: firewall
podSelector:
matchLabels:
app: firewall
---
apiVersion: networking.gke.io/v1
kind: ServiceFunctionChain
metadata:
name: proxy
spec:
sessionAffinity:
clientIpNoDestination: {}
serviceFunctions:
- name: proxy
namespace: proxy
podSelector:
matchLabels:
app: proxy
应用清单:
kubectl apply -f ServiceFunctionChain.yaml
服务功能使用 serviceFunctions
字段在 ServiceFunctionChain
中以内嵌方式定义。服务功能是一种端点选择器。
创建 TrafficSelector
资源
如需定义在哪里选择流量以及选择哪些流量进行服务流量导向,请创建引用 ServiceFunctionChains
以应用于所选流量的 TrafficSelector
资源。
将以下示例清单保存为 TrafficSelector.yaml
:
apiVersion: networking.gke.io/v1
kind: TrafficSelector
metadata:
name: vpn-to-firewall
spec:
serviceFunctionChain: firewall
subject:
pods:
namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: vpn
podSelector:
matchLabels:
app: vpn
egress:
to:
ipBlock:
cidr: 0.0.0.0/0
ports:
- allPorts:
protocol: UDP
- allPorts:
protocol: TCP
---
apiVersion: networking.gke.io/v1
kind: TrafficSelector
metadata:
name: firewall-to-proxy
spec:
serviceFunctionChain: proxy
subject:
pods:
namespaceSelector:
kubernetes.io/metadata.name: firewall
podSelector:
app: firewall
egress:
to:
ipBlock:
cidr: 0.0.0.0/0
ports:
- allPorts:
protocol: UDP
- allPorts:
protocol: TCP
应用清单:
kubectl apply -f TrafficSelector.yaml
排查服务流量导向问题
本部分介绍如何解决与 GKE 服务流量导向相关的问题。
网络流量不流动
您可以执行以下操作来调试此问题:
第 1 步:验证是否已在 ServiceFunctionChain
上设置 servicePathId
验证是否已在 ServiceFunctionChain
上设置 servicePathId
。每个 ServiceFunctionChain
对象都分配有唯一的 servicePathId
,如以下示例所示:
apiVersion: networking.gke.io/v1
kind: ServiceFunctionChain
metadata:
name: firewall
spec:
serviceFunctions:
- name: firewall
namespace: firewall
podSelector:
matchLabels:
app: firewal
status:
servicePathId: 1
第 2 步:验证是否对每个服务功能创建了 Kubernetes 服务
系统会自动为每个服务功能创建一个 ClusterIP 服务。您可以使用 kubectl
查看服务列表:
kubectl get svc -A -l networking.gke.io/managed-by=service-steering-controller.gke.io
第 3 步:验证对于每个服务功能,是否在每个节点上创建了一个 bpf 映射条目来存储服务 IP 地址
对于每个服务功能,系统会在每个节点上创建一个 bpf 映射条目来存储服务 IP 地址。
获取 anetd
Pod 的名称:
kubectl get pods -n kube-system -o wide -l k8s-app=cilium
记录与 anetd
类似的 Pod 名称。
运行以下命令:
kubectl -n kube-system exec -it ANETD-POD-NAME -- cilium bpf sfcpath list
将 ANETD-POD-NAME
替换为 anetd
Pod 的名称。
输出类似于以下内容:
PATH SERVICE FUNCTION ADDRESS
(1, 1) 10.4.10.124
第 4 步:验证是否在 sfcselect
映射中创建了 bpf 映射条目
在节点上,如果 TrafficSelector
选择了 Pod,则 sfcselect
映射中会创建相应 bpf 映射条目。以下示例显示从端点 (Pod) 3783 的任何端口到目标 IP 地址 10.0.2.12 的 TCP/UDP 流量会导向到 ServiceFunctionChain
。
运行以下命令:
kubectl -n kube-system exec -it ANETD-POD-NAME -- cilium bpf sfcselect list
将 ANETD-POD-NAME
替换为集群中 anetd Pod 的实际名称。
输出类似于以下内容:
SELECTOR PATH
3783, egress, 0/TCP, 10.0.2.12/32 /32 (1, 1)
3783, egress, 0/UDP, 10.0.2.12/32 /32 (1, 1)
第 5 步:在端口 7081 上使用 tcpdump 捕获和分析网络流量
服务流量导向会在 UDP 端口 7081 上执行 Geneve 封装。您可以在相关节点上使用 tcpdump 来分析流量流并查明可能出现问题的位置。