我们从未见过像 Kubernetes 这样的工具引发开源产品的激增。这些构建块使 Kubernetes 成为事实上的容器编排器,可以安全可靠地运行服务。由于组织本身并不运行 Kubernetes,因此 Kubernetes 通常与其他工具一起部署,以解决 Kuberntes 本身无法解决的实际业务挑战。Google 在 Anthos 保护伞下提供了这些产品的托管集合。
在本文中,我们将演示组织如何利用 Anthos 使用多集群入口 ( MCI ) 和 Anthos Service Mesh ( ASM ) 集中管理互联网流量。
问题陈述
对于大型组织,职责分离是一个主要问题。正是这种担忧推动了云基础的设计。项目是为谷歌云平台提供的大部分资源创建最小权限策略的边界。因此,可以公平地假设不同的团队将有不同的项目来运行他们的工作负载。
这种职责分离也适用于网络管理。共享 VPC 是团队集中管理网络的工具之一。这允许多个项目共享同一个 VPC。Anthos 提供的某些功能也需要具有相同的 VPC。
在 Kubernetes 中运行的应用程序有时需要暴露在互联网上。可以使用负载均衡器来实现公开应用程序。负载均衡器的生命周期和配置管理是通过注释和自定义资源定义 (CRD) 完成的。MCI 是一个托管控制器,用于管理 Google Cloud Global Load Balancer (GLBC) 的生命周期,以便将在 Kubernetes 上运行的服务公开到互联网。不幸的是,GLBC 不支持跨项目后端。由于项目是实施最小特权策略的基础,因此一种解决方案是为每个项目部署一个 GLBC。这将为网络和安全团队带来的管理开销是巨大的。第二种解决方案是使用 MCI 部署一个 GLBC,并使用 ASM 路由跨项目的流量。
既然我们已经讨论了我们正在解决的问题以及我们将使用什么工具,那么让我们深入探讨一下我们将如何去做。
架构图

此架构显示了在多项目设置中支持 MCI 的建议解决方案。车队项目和服务项目共享同一个 VPC。共享 VPC 宿主项目未在图片中描述,但它是一个单独的项目。fleet项目是指启用了Fleet API的项目。属于同一个队列的所有集群也是同一个网格的一部分。Fleet GKE 集群之一托管 MCI 配置,但配置部署在两个 Fleet GKE 集群中以实现高可用性。在两个集群中部署相同的配置可以很容易地交换配置集群。
另一方面,服务项目承载工作负载。开发团队可以访问命名空间来部署他们管理的服务。
如何实施此解决方案
要实施此解决方案,深入了解流量的流动方式是关键。以下步骤描述了确保一切正常的过程。在开始之前,请执行以下操作:
确保已设置 MCI。
$ kubectl -n istio-system get controlplanerevision
NAME RECONCILED STALLED AGE
asm-managed-stable True False 34d
为入口网关和其他资源创建命名空间。
$ export INGRESS_NS=ingress
$ export ASM_REVISION=$(kubectl -n istio-system get controlplanerevision | awk '/asm/ {print $1}')
$ cat > ns_ingress.yaml << EOF
apiVersion: v1
kind: Namespace
metadata:
labels:
istio.io/rev: ${ASM_REVISION}
name: ${INGRESS_NS}
EOF
部署多集群服务资源并使用将流量发送到已部署的入口控制器的选择器。集群规范应该只链接 Fleet GKE 集群,因为这是部署 ASM 入口资源的地方。多集群服务资源创建网络端点组 (NEG)。
$ export INGRESS_NS=ingress
$ cat > mcs.yaml << EOF
apiVersion: networking.gke.io/v1
kind: MultiClusterService
metadata:
annotations:
networking.gke.io/app-protocols: '{"http":"HTTP"}'
name: mcs-service
namespace: ${INGRESS_NS}
spec:
clusters:
- link: us-east4/fleetclustereast
- link: us-central1/fleetclustercentral
template:
spec:
ports:
- name: https
port: 80
protocol: TCP
targetPort: 80
selector:
asm: ingressgateway # Same selector defined in the ingress controller
EOF
要创建 GLBC,应部署多集群入口资源。
cat > mci.yaml << EOF
apiVersion: networking.gke.io/v1
kind: MultiClusterIngress
metadata:
name: mci
spec:
template:
spec:
backend:
serviceName: mcs-service # name of the Multi Cluster Service
servicePort: 80
rules:
- host: "store.store.svc.cluster.local"
http:
paths:
- backend:
serviceName: mcs-service
servicePort: 80
EOF
为服务创建命名空间。以下配置应应用于所有集群。Anthos 配置管理 (ACM)可用于实现此目的。
$ export STORE_NS=store
$ export ASM_REVISION=$(kubectl -n istio-system get controlplanerevision | awk '/asm/ {print $1}')
$ cat > ns_store.yaml << EOF
apiVersion: v1
kind: Namespace
metadata:
labels:
istio.io/rev: ${ASM_REVISION}
name: ${STORE_NS}
EOF
创建将侦听为 MCI 部署的网关的虚拟服务。网关属性是命名空间和应该使用的网关名称的组合。此虚拟服务应在舰队 GKE 集群中创建。
$ export STORE_NS=store
cat > ingress_virtual_service.yaml << EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: frontend
namespace: ${STORE_NS}
spec:
hosts:
- "store.store.svc.cluster.local"
gateways:
- asmingress/ingressgateway
http:
- route:
- destination:
host: store
port:
number: 80
EOF
第二个虚拟服务应该在工作负载运行的集群中创建,与第一个虚拟服务的不同之处在于,在这种情况下使用的网关应该是网状的,因为入口网关部署在不同的项目中。
$ export STORE_NS=store
cat > virtual_service.yaml << EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: frontend
namespace: ${STORE_NS}
spec:
hosts:
- store.store.svc.cluster.local
gateways:
- mesh
http:
- route:
- destination:
host: store
port:
number: 80
EOF
在服务 GKE 集群中部署工作负载
$ export STORE_NS=store
$ cat > store.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: store
namespace: ${STORE_NS}
spec:
replicas: 2
selector:
matchLabels:
app: store
version: v1
template:
metadata:
labels:
app: store
version: v1
spec:
containers:
- name: whereami
image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1.2.11
ports:
- containerPort: 8080
EOF
在 Fleet GKE 集群和 Service 集群中部署部署服务,这是服务发现所必需的
$ export STORE_NS=store
$ cat > store_svc.yaml << EOF
apiVersion: v1
kind: Service
metadata:
name: store
namespace: ${STORE_NS}
spec:
selector:
app: store
ports:
- port: 80
targetPort: 8080
EOF
最后一步是测试服务是否应答。Curl 可用于此,例如:
$ curl --header "Host: store.store.svc.cluster.local" http://${GLBC_IP} -v
结论
在这篇博文中,我们看到即使 MCI 不支持不同项目中的后端,我们也可以使用 ASM 克服这一限制。这两种产品的组合使得集中流量管理和为不同项目中运行的工作负载重用相同的 GLBC 变得容易。确保检查 GKE 网络食谱存储库以获取更多 GKE 入口示例。