本部署介绍如何将 Cloud Service Mesh 与 Cloud Load Balancing 结合使用,以将服务网格中的应用公开给互联网客户端。
您可以通过多种方式向客户端公开应用,具体取决于客户端所在的位置。本部署介绍了如何将 Cloud Load Balancing 与 Cloud Service Mesh 结合使用以向客户端公开应用,以将负载均衡器与服务网格集成在一起。本部署面向运行 Cloud Service Mesh 的高级从业人员,但也适用于 Google Kubernetes Engine 上的 Istio。
架构
下图展示了如何使用网格 Ingress 网关将负载均衡器与服务网格集成:
在上图的拓扑中,通过 GKE Gateway 编程的 Cloud 入站流量层从服务网格外部获取流量,并将该流量定向到网格入站流量层。然后,网格 Ingress 层会将流量定向到网格托管的应用后端。
上述拓扑有以下注意事项:
- Cloud 入站流量:在此参考架构中,通过 GKE Gateway 配置 Google Cloud 负载均衡器,以检查所公开健康检查端口上的网格入站流量代理的健康状况。
- 网格 Ingress:在网格应用中,您可以直接对后端执行健康检查,以便可以在本地运行负载均衡和流量管理。
上图说明了从客户端到 Google Cloud 负载均衡器、从负载均衡器到网格 Ingress 代理以及从 Ingress 代理到边车代理的 HTTPS 加密。
目标
- 在 Google Cloud 上部署 Google Kubernetes Engine (GKE) 集群。
- 在 GKE 集群上部署基于 Istio 的 Cloud Service Mesh。
- 配置 GKE Gateway 以终结公共 HTTPS 流量,并将该流量定向到服务网格托管的应用。
- 在您向互联网上的客户端公开的 GKE 集群上部署 Online Boutique 应用。
费用优化
在本文档中,您将使用 Google Cloud 的以下收费组件:
- Google Kubernetes Engine
- Compute Engine
- Cloud Load Balancing
- Certificate Manager
- Cloud Service Mesh
- Google Cloud Armor
- Cloud Endpoints
您可使用价格计算器根据您的预计使用情况来估算费用。
完成本文档中描述的任务后,您可以通过删除所创建的资源来避免继续计费。如需了解详情,请参阅清理。
准备工作
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
In the Google Cloud console, activate Cloud Shell.
您将通过 Cloud Shell 运行此部署中的所有终端命令。
升级到最新版本的 Google Cloud CLI:
gcloud components update
设置默认的 Google Cloud 项目:
export PROJECT=PROJECT export PROJECT_NUMBER=$(gcloud projects describe ${PROJECT} --format="value(projectNumber)") gcloud config set project ${PROJECT}
将
PROJECT
替换为您要用于此部署的项目 ID。创建工作目录:
mkdir -p ${HOME}/edge-to-mesh cd ${HOME}/edge-to-mesh export WORKDIR=`pwd`
完成此部署后,您可以删除工作目录。
创建 GKE 集群
此部署中介绍的功能需要使用 GKE 集群 1.16 或更高版本。
在 Cloud Shell 中,创建一个新的
kubeconfig
文件。此步骤确保不会导致与现有(默认)kubeconfig
文件冲突。touch edge2mesh_kubeconfig export KUBECONFIG=${WORKDIR}/edge2mesh_kubeconfig
为 GKE 集群定义环境变量:
export CLUSTER_NAME=edge-to-mesh export CLUSTER_LOCATION=us-central1
启用 Google Kubernetes Engine API:
gcloud services enable container.googleapis.com
创建 GKE Autopilot 集群:
gcloud container --project ${PROJECT} clusters create-auto \ ${CLUSTER_NAME} --region ${CLUSTER_LOCATION} --release-channel rapid
确保该集群正在运行:
gcloud container clusters list
输出类似于以下内容:
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS edge-to-mesh us-central1 1.27.3-gke.1700 34.122.84.52 e2-medium 1.27.3-gke.1700 3 RUNNING
安装服务网格
在本部分中,您将配置使用队列 API 的代管式 Cloud Service Mesh。
在 Cloud Shell 中,启用所需的 API:
gcloud services enable mesh.googleapis.com
在舰队上启用 Cloud Service Mesh:
gcloud container fleet mesh enable
将集群注册到舰队:
gcloud container fleet memberships register ${CLUSTER_NAME} \ --gke-cluster ${CLUSTER_LOCATION}/${CLUSTER_NAME}
将
mesh_id
标签应用于edge-to-mesh
集群:gcloud container clusters update ${CLUSTER_NAME} --project ${PROJECT} --region ${CLUSTER_LOCATION} --update-labels mesh_id=proj-${PROJECT_NUMBER}
启用自动控制平面管理和代管式数据平面:
gcloud container fleet mesh update \ --management automatic \ --memberships ${CLUSTER_NAME}
几分钟后,验证控制平面状态是否为
ACTIVE
:gcloud container fleet mesh describe
输出类似于以下内容:
... membershipSpecs: projects/892585880385/locations/us-central1/memberships/edge-to-mesh: mesh: management: MANAGEMENT_AUTOMATIC membershipStates: projects/892585880385/locations/us-central1/memberships/edge-to-mesh: servicemesh: controlPlaneManagement: details: - code: REVISION_READY details: 'Ready: asm-managed-rapid' state: ACTIVE dataPlaneManagement: details: - code: OK details: Service is running. state: ACTIVE state: code: OK description: 'Revision(s) ready for use: asm-managed-rapid.' updateTime: '2023-08-04T02:54:39.495937877Z' name: projects/e2m-doc-01/locations/global/features/servicemesh resourceState: state: ACTIVE ...
部署 GKE Gateway
在以下步骤中,您将通过 GKE Gateway Controller 部署外部应用负载均衡器。GKE Gateway 资源会自动预配负载均衡器和后端健康检查。此外,您还将使用 Certificate Manager 预配和管理 TLS 证书,并使用 Endpoints 自动为应用预配公共 DNS 名称。
安装服务网格入站流量网关
为保证安全性,我们建议在与控制层面不同的命名空间中部署入站流量网关。
在 Cloud Shell 中,创建一个专用的
asm-ingress
命名空间:kubectl create namespace asm-ingress
将命名空间标签添加到
asm-ingress
命名空间:kubectl label namespace asm-ingress istio-injection=enabled
输出类似于以下内容:
namespace/asm-ingress labeled
使用
istio-injection=enabled
为asm-ingress
命名空间添加标签会指示 Cloud Service Mesh 在部署应用时自动注入 Envoy 边车代理。创建入站流量网关使用的自签名证书,以终结 Google Cloud 负载均衡器(稍后通过 GKE Gateway Controller 配置)和入站流量网关之间的 TLS 连接,并将自签名证书存储为 Kubernetes Secret:
openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 \ -subj "/CN=frontend.endpoints.${PROJECT}.cloud.goog/O=Edge2Mesh Inc" \ -keyout frontend.endpoints.${PROJECT}.cloud.goog.key \ -out frontend.endpoints.${PROJECT}.cloud.goog.crt kubectl -n asm-ingress create secret tls edge2mesh-credential \ --key=frontend.endpoints.${PROJECT}.cloud.goog.key \ --cert=frontend.endpoints.${PROJECT}.cloud.goog.crt
如需更详细地了解入站流量网关证书的要求,请参阅安全后端协议注意事项指南。
运行以下命令以创建入站流量网关资源 YAML:
mkdir -p ${WORKDIR}/asm-ig/base cat <<EOF > ${WORKDIR}/asm-ig/base/kustomization.yaml resources: - github.com/GoogleCloudPlatform/anthos-service-mesh-samples/docs/ingress-gateway-asm-manifests/base EOF mkdir ${WORKDIR}/asm-ig/variant cat <<EOF > ${WORKDIR}/asm-ig/variant/role.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: asm-ingressgateway namespace: asm-ingress rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get", "watch", "list"] EOF cat <<EOF > ${WORKDIR}/asm-ig/variant/rolebinding.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: asm-ingressgateway namespace: asm-ingress roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: asm-ingressgateway subjects: - kind: ServiceAccount name: asm-ingressgateway EOF cat <<EOF > ${WORKDIR}/asm-ig/variant/service-proto-type.yaml apiVersion: v1 kind: Service metadata: name: asm-ingressgateway spec: ports: - name: status-port port: 15021 protocol: TCP targetPort: 15021 - name: http port: 80 targetPort: 8080 - name: https port: 443 targetPort: 8443 appProtocol: HTTP2 type: ClusterIP EOF cat <<EOF > ${WORKDIR}/asm-ig/variant/gateway.yaml apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: asm-ingressgateway spec: servers: - port: number: 443 name: https protocol: HTTPS hosts: - "*" # IMPORTANT: Must use wildcard here when using SSL, see note below tls: mode: SIMPLE credentialName: edge2mesh-credential EOF cat <<EOF > ${WORKDIR}/asm-ig/variant/kustomization.yaml namespace: asm-ingress resources: - ../base - role.yaml - rolebinding.yaml patches: - path: service-proto-type.yaml target: kind: Service - path: gateway.yaml target: kind: Gateway EOF
应用入站流量网关 CRD:
kubectl apply -k ${WORKDIR}/asm-ig/variant
确保所有部署都已启动并运行:
kubectl wait --for=condition=available --timeout=600s deployment --all -n asm-ingress
输出类似于以下内容:
deployment.apps/asm-ingressgateway condition met
应用服务网格入站流量网关健康检查
将服务网格入站流量网关集成到 Google Cloud 应用负载均衡器时,必须将应用负载均衡器配置为针对入站流量网关 Pod 执行健康检查。HealthCheckPolicy
CRD 提供了一个用于配置该健康检查的 API。
在 Cloud Shell 中,创建
HealthCheckPolicy.yaml
文件:cat <<EOF >${WORKDIR}/ingress-gateway-healthcheck.yaml apiVersion: networking.gke.io/v1 kind: HealthCheckPolicy metadata: name: ingress-gateway-healthcheck namespace: asm-ingress spec: default: checkIntervalSec: 20 timeoutSec: 5 #healthyThreshold: HEALTHY_THRESHOLD #unhealthyThreshold: UNHEALTHY_THRESHOLD logConfig: enabled: True config: type: HTTP httpHealthCheck: #portSpecification: USE_NAMED_PORT port: 15021 portName: status-port #host: HOST requestPath: /healthz/ready #response: RESPONSE #proxyHeader: PROXY_HEADER #requestPath: /healthz/ready #port: 15021 targetRef: group: "" kind: Service name: asm-ingressgateway EOF
应用
HealthCheckPolicy:
kubectl apply -f ${WORKDIR}/ingress-gateway-healthcheck.yaml
定义安全政策
Google Cloud Armor 提供的 DDoS 防御和可自定义的安全策略可通过 Ingress 资源关联至负载均衡器。在以下步骤中,您将创建安全政策,以使用预配置规则来阻止跨站脚本攻击 (XSS)。此规则有助于阻止与已知攻击签名匹配的流量,但允许所有其他流量。您的环境可能根据工作负载使用不同的规则。
在 Cloud Shell 中,创建一个名为
edge-fw-policy
的安全政策:gcloud compute security-policies create edge-fw-policy \ --description "Block XSS attacks"
创建使用预配置 XSS 过滤条件的安全政策规则:
gcloud compute security-policies rules create 1000 \ --security-policy edge-fw-policy \ --expression "evaluatePreconfiguredExpr('xss-stable')" \ --action "deny-403" \ --description "XSS attack filtering"
创建
GCPBackendPolicy.yaml
文件以附加到入站流量网关服务:cat <<EOF > ${WORKDIR}/cloud-armor-backendpolicy.yaml apiVersion: networking.gke.io/v1 kind: GCPBackendPolicy metadata: name: cloud-armor-backendpolicy namespace: asm-ingress spec: default: securityPolicy: edge-fw-policy targetRef: group: "" kind: Service name: asm-ingressgateway EOF
应用
GCPBackendPolicy.yaml
文件:kubectl apply -f ${WORKDIR}/cloud-armor-backendpolicy.yaml
配置 IP 寻址和 DNS
在 Cloud Shell 中,为 Google Cloud 负载均衡器创建全球静态 IP 地址:
gcloud compute addresses create e2m-gclb-ip --global
此静态 IP 地址由 GKE Gateway 资源使用,即使外部负载均衡器发生更改,该 IP 地址也可以保持不变。
获取静态 IP 地址:
export GCLB_IP=$(gcloud compute addresses describe e2m-gclb-ip \ --global --format "value(address)") echo ${GCLB_IP}
如需针对应用负载均衡器的静态 IP 地址创建易于使用的稳定映射,您必须具有公共 DNS 记录。您可以使用所需的任何 DNS 提供商和自动化功能。本部署使用 Endpoints 而不是创建托管式 DNS 区域。Endpoints 为公共 IP 地址提供免费的 Google 管理的 DNS 记录。
运行以下命令以创建名为
dns-spec.yaml
的 YAML 规范文件:cat <<EOF > ${WORKDIR}/dns-spec.yaml swagger: "2.0" info: description: "Cloud Endpoints DNS" title: "Cloud Endpoints DNS" version: "1.0.0" paths: {} host: "frontend.endpoints.${PROJECT}.cloud.goog" x-google-endpoints: - name: "frontend.endpoints.${PROJECT}.cloud.goog" target: "${GCLB_IP}" EOF
YAML 规范以
frontend.endpoints.${PROJECT}.cloud.goog
的形式定义公共 DNS 记录,其中${PROJECT}
是您的唯一项目标识符。在 Google Cloud 项目中部署
dns-spec.yaml
文件:gcloud endpoints services deploy ${WORKDIR}/dns-spec.yaml
输出类似于以下内容:
project [e2m-doc-01]... Operation "operations/acat.p2-892585880385-fb4a01ad-821d-4e22-bfa1-a0df6e0bf589" finished successfully. Service Configuration [2023-08-04r0] uploaded for service [frontend.endpoints.e2m-doc-01.cloud.goog]
在配置 IP 地址和 DNS 后,您可以生成公共证书来保护前端。如需与 GKE 网关集成,请使用 Certificate Manager TLS 证书。
预配 TLS 证书
在本部分中,您将使用 Certificate Manager 创建 TLS 证书,并通过证书映射条目将其与证书映射关联。通过 GKE Gateway 配置的应用负载均衡器使用该证书在客户端和 Google Cloud 之间提供安全通信。创建证书映射条目后,GKE Gateway 资源会引用该条目。
在 Cloud Shell 中,启用 Certificate Manager API:
gcloud services enable certificatemanager.googleapis.com --project=${PROJECT}
创建 TLS 证书:
gcloud --project=${PROJECT} certificate-manager certificates create edge2mesh-cert \ --domains="frontend.endpoints.${PROJECT}.cloud.goog"
创建证书映射:
gcloud --project=${PROJECT} certificate-manager maps create edge2mesh-cert-map
使用证书映射条目将证书与证书映射关联:
gcloud --project=${PROJECT} certificate-manager maps entries create edge2mesh-cert-map-entry \ --map="edge2mesh-cert-map" \ --certificates="edge2mesh-cert" \ --hostname="frontend.endpoints.${PROJECT}.cloud.goog"
部署 GKE Gateway 和 HTTPRoute
资源
在本部分中,您将配置 GKE Gateway 资源,该资源使用 gke-l7-global-external-managed
gatewayClass
预配 Google Cloud 应用负载均衡器。此外,您还将配置 HTTPRoute
资源,此资源将请求路由到应用,并执行从 HTTP 到 HTTP(S) 的重定向。
在 Cloud Shell 中,运行以下命令以将
Gateway
清单创建为gke-gateway.yaml
:cat <<EOF > ${WORKDIR}/gke-gateway.yaml kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: external-http namespace: asm-ingress annotations: networking.gke.io/certmap: edge2mesh-cert-map spec: gatewayClassName: gke-l7-global-external-managed # gke-l7-gxlb listeners: - name: http # list the port only so we can redirect any incoming http requests to https protocol: HTTP port: 80 - name: https protocol: HTTPS port: 443 addresses: - type: NamedAddress value: e2m-gclb-ip # reference the static IP created earlier EOF
应用
Gateway
清单以创建一个名为external-http
的Gateway
:kubectl apply -f ${WORKDIR}/gke-gateway.yaml
创建默认
HTTPRoute.yaml
文件:cat << EOF > ${WORKDIR}/default-httproute.yaml apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: default-httproute namespace: asm-ingress spec: parentRefs: - name: external-http namespace: asm-ingress sectionName: https rules: - matches: - path: value: / backendRefs: - name: asm-ingressgateway port: 443 EOF
应用默认的
HTTPRoute
:kubectl apply -f ${WORKDIR}/default-httproute.yaml
创建一个额外的
HTTPRoute.yaml
文件以执行从 HTTP 到 HTTP(S) 的重定向:cat << EOF > ${WORKDIR}/default-httproute-redirect.yaml kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-to-https-redirect-httproute namespace: asm-ingress spec: parentRefs: - name: external-http namespace: asm-ingress sectionName: http rules: - filters: - type: RequestRedirect requestRedirect: scheme: https statusCode: 301 EOF
应用重定向
HTTPRoute
:kubectl apply -f ${WORKDIR}/default-httproute-redirect.yaml
协调需要一些时间。在
programmed=true
之前,使用以下命令:kubectl get gateway external-http -n asm-ingress -w
安装 Online Boutique 示例应用
在 Cloud Shell 中,创建一个专用的
onlineboutique
命名空间:kubectl create namespace onlineboutique
向
onlineboutique
命名空间添加标签:kubectl label namespace onlineboutique istio-injection=enabled
使用
istio-injection=enabled
为onlineboutique
命名空间添加标签会指示 Cloud Service Mesh 在部署应用时自动注入 Envoy 边车代理。下载 Online Boutique 示例应用的 Kubernetes YAML 文件:
curl -LO \ https://raw.githubusercontent.com/GoogleCloudPlatform/microservices-demo/main/release/kubernetes-manifests.yaml
部署 Online Boutique 应用:
kubectl apply -f kubernetes-manifests.yaml -n onlineboutique
输出类似于以下内容(包括有关 GKE Autopilot 设置默认资源请求和限制的警告):
Warning: autopilot-default-resources-mutator:Autopilot updated Deployment onlineboutique/emailservice: adjusted resources to meet requirements for containers [server] (see http://g.co/gke/autopilot-resources) deployment.apps/emailservice created service/emailservice created Warning: autopilot-default-resources-mutator:Autopilot updated Deployment onlineboutique/checkoutservice: adjusted resources to meet requirements for containers [server] (see http://g.co/gke/autopilot-resources) deployment.apps/checkoutservice created service/checkoutservice created Warning: autopilot-default-resources-mutator:Autopilot updated Deployment onlineboutique/recommendationservice: adjusted resources to meet requirements for containers [server] (see http://g.co/gke/autopilot-resources) deployment.apps/recommendationservice created service/recommendationservice created ...
确保所有部署都已启动并运行:
kubectl get pods -n onlineboutique
输出类似于以下内容:
NAME READY STATUS RESTARTS AGE adservice-64d8dbcf59-krrj9 2/2 Running 0 2m59s cartservice-6b77b89c9b-9qptn 2/2 Running 0 2m59s checkoutservice-7668b7fc99-5bnd9 2/2 Running 0 2m58s ...
等待几分钟,让 GKE Autopilot 集群预配必要的计算基础设施以支持应用。
运行以下命令,将
VirtualService
清单创建为frontend-virtualservice.yaml
:cat <<EOF > frontend-virtualservice.yaml apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: frontend-ingress namespace: onlineboutique spec: hosts: - "frontend.endpoints.${PROJECT}.cloud.goog" gateways: - asm-ingress/asm-ingressgateway http: - route: - destination: host: frontend port: number: 80 EOF
VirtualService
是在应用命名空间 (onlineboutique
) 中创建的。通常,应用所有者会决定并配置将流量路由到frontend
应用的方式和内容,以便应用所有者部署VirtualService
。在您的集群中部署
frontend-virtualservice.yaml
:kubectl apply -f frontend-virtualservice.yaml
访问以下链接:
echo "https://frontend.endpoints.${PROJECT}.cloud.goog"
系统会显示您的 Online Boutique 前端。
如需显示证书的详情,请在浏览器的地址栏中点击
查看站点信息,然后点击证书(有效)。证书查看器会显示代管证书的详情,包括到期日期和颁发证书的人。
现在,您有一个全球 HTTPS 负载均衡器,作为服务网格托管应用的前端。
清理
完成本部署后,您可以清理您在 Google Cloud 上创建的资源,以免这些资源将来产生费用。您可以彻底删除项目,也可以删除集群资源,然后删除集群。
删除项目
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
逐个删除资源
如果您希望保留在此部署中使用的 Google Cloud 项目,请删除单个资源:
在 Cloud Shell 中,删除
HTTPRoute
资源:kubectl delete -f ${WORKDIR}/default-httproute-redirect.yaml kubectl delete -f ${WORKDIR}/default-httproute.yaml
删除 GKE Gateway 资源:
kubectl delete -f ${WORKDIR}/gke-gateway.yaml
删除 TLS 证书资源(包括证书映射条目及其父证书映射):
gcloud --project=${PROJECT} certificate-manager maps entries delete edge2mesh-cert-map-entry --map="edge2mesh-cert-map" --quiet gcloud --project=${PROJECT} certificate-manager maps delete edge2mesh-cert-map --quiet gcloud --project=${PROJECT} certificate-manager certificates delete edge2mesh-cert --quiet
删除 Endpoints DNS 条目:
gcloud endpoints services delete "frontend.endpoints.${PROJECT}.cloud.goog"
输出内容类似如下:
Are you sure? This will set the service configuration to be deleted, along with all of the associated consumer information. Note: This does not immediately delete the service configuration or data and can be undone using the undelete command for 30 days. Only after 30 days will the service be purged from the system.
当系统提示您继续时,请输入 Y。
输出内容类似如下:
Waiting for async operation operations/services.frontend.endpoints.edge2mesh.cloud.goog-5 to complete... Operation finished successfully. The following command can describe the Operation details: gcloud endpoints operations describe operations/services.frontend.endpoints.edge2mesh.cloud.goog-5
删除静态 IP 地址:
gcloud compute addresses delete ingress-ip --global
输出内容类似如下:
The following global addresses will be deleted: - [ingress-ip]
当系统提示您继续时,请输入 Y。
输出内容类似如下:
Deleted [https://www.googleapis.com/compute/v1/projects/edge2mesh/global/addresses/ingress-ip].
删除 GKE 集群:
gcloud container clusters delete $CLUSTER_NAME --zone $CLUSTER_LOCATION
输出类似于以下内容:
The following clusters will be deleted. - [edge-to-mesh] in [us-central1]
当系统提示您继续时,请输入 Y。
几分钟后,输出如下内容:
Deleting cluster edge-to-mesh...done. Deleted [https://container.googleapis.com/v1/projects/e2m-doc-01/zones/us-central1/clusters/edge-to-mesh].
后续步骤
- 了解 GKE Ingress 提供的可与服务网格配合使用的更多功能。
- 了解适用于 GKE 的不同类型的 Cloud Load Balancing。
- 了解 Cloud Service Mesh 提供的功能。
- 了解如何跨多个 GKE 集群部署 Ingress 以实现多地区负载均衡。
- 如需查看更多参考架构、图表和最佳实践,请浏览云架构中心。