将流量从 Cloud Service Mesh 工作负载路由到 Cloud Run 服务

本页介绍了如何安全地将网络流量从 GKE 上的 Cloud Service Mesh 工作负载路由到 Cloud Run 服务。

请注意,从 GKE 将流量路由到 Cloud Run 时,Cloud Run 服务无需加入 Cloud Service Mesh。不过,Cloud Run 服务必须与 Cloud Service Mesh GKE 集群位于同一项目中。此功能在公开预览版阶段存在此限制。

准备工作

以下部分假定您已完成以下操作:

  1. 已启用 Cloud Service Mesh 的 GKE 集群
  2. 部署了 Cloud Run 服务

或者,您也可以运行以下命令来部署示例 Cloud Run 服务。

  1. 为集群生成 kubeconfig 上下文:

    gcloud container clusters get-credentials CLUSTER_NAME --project=PROJECT_ID  --location=CLUSTER_LOCATION
    

    其中:

    • CLUSTER_NAME 是集群的名称。
    • PROJECT_ID 是项目的项目 ID。
    • CLUSTER_LOCATION 是集群所在的区域或可用区。
  2. 部署 Cloud Run 服务示例:

    gcloud run deploy hello-world \
      --image=us-docker.pkg.dev/cloudrun/container/hello \
      --no-allow-unauthenticated \
      --port=8080 \
      --service-account=PROJECT_NUMBER-compute@developer.gserviceaccount.com \
      --region=us-central1 \
      --project=PROJECT_ID
    

    其中:

    • PROJECT_NUMBER 是您的项目的项目编号。
    • PROJECT_ID 是项目的项目 ID。

配置 IAM

如需调用 Cloud Run 服务,必须通过 Cloud Run Identity and Access Management (IAM) 检查。您必须向 Google 服务账号授予 Cloud Run Invoker 角色。您还必须配置 GKE Kubernetes 服务账号 (KSA) 以模拟 Google 服务账号。

请执行以下步骤,允许 Kubernetes 服务账号模拟 Google 服务账号。

  1. 向 IAM 服务账号添加 IAM 政策绑定:

    gcloud iam service-accounts add-iam-policy-binding PROJECT_NUMBER-compute@developer.gserviceaccount.com \
      --role roles/iam.workloadIdentityUser \
      --member "serviceAccount:PROJECT_ID.svc.id.goog[NAMESPACE/KSA]"
    

    其中:

    • NAMESPACE 是命名空间名称。在本指南中,您可以使用命名空间 default
    • KSA 是 Kubernetes 服务账号的名称。在本指南中,您可以使用 KSA default
  2. 为服务账号添加注解:

    kubectl annotate serviceaccount KSA \
      --namespace NAMESPACE \
      iam.gke.io/gcp-service-account=PROJECT_NUMBER-compute@developer.gserviceaccount.com
    
  3. 向 Google 服务账号授予 Cloud Run Invoker 角色:

    gcloud run services add-iam-policy-binding hello-world \
      --region=us-central1 \
      --member="serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com" \
      --role="roles/run.invoker"
    

将 Cloud Run 服务配置为 GCPBackend

在本部分中,您将使用 GCPBackend 将 Cloud Run 服务公开给 GKE 工作负载。GCPBackend 由以下部分组成:

  1. 前端信息,具体而言,是 GKE 工作负载用于调用此 GCPBackend 的主机名和端口。
  2. 后端信息 - Cloud Run 服务详细信息,例如服务名称、位置和项目编号。

GCPBackend 包含主机名和端口详细信息,以及 Cloud 服务详细信息(服务名称、位置和项目编号)。GKE 工作负载应在其 HTTP 请求中使用 GCPBackend 主机名和端口来访问 Cloud Run 服务。

若要使主机名 DNS 在集群内可解析(默认情况下不可解析),您必须配置 Google Cloud DNS,将所选主机名下的所有主机解析为任意 IP 地址。在您配置此 DNS 条目之前,请求会失败。 Google Cloud DNS 配置是针对每个自定义网域进行一次性设置。

  1. 创建托管式区域:

    gcloud dns managed-zones create prod \
        --description="zone for gcpbackend" \
        --dns-name=gcpbackend \
        --visibility=private \
        --networks=default
    

    在此示例中,DNS 名称为 gcpbackend,VPC 网络为 default

  2. 设置相应记录以使网域可解析:

    gcloud beta dns record-sets create *.gcpbackend \
      --ttl=3600 --type=A --zone=prod \
      --rrdatas=10.0.0.1
    
  3. 使用上一个网域下的主机名创建 GCPBackend:

    cat <<EOF > gcp-backend.yaml
    apiVersion: networking.gke.io/v1
    kind: GCPBackend
    metadata:
      name: cr-gcp-backend
      namespace: NAMESPACE
    spec:
      hostname: hello-world.gcpbackend
      type: CloudRun
      cloudrun:
        service: hello-world
        regions: [us-central1]
    EOF
    kubectl apply -f gcp-backend.yaml
    

    在此示例中,GCP_BACKEND_NAMEcr-gcp-backend

  4. 创建一个测试 Pod 以验证 GKE 与 Cloud Run 的连接:

    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: Pod
    metadata:
      name: testcurl
      namespace: default
    spec:
      containers:
      - name: curl
        image: curlimages/curl
        command: ["sleep", "3000"]
    EOF
    
    kubectl exec testcurl -c curl -- curl http://hello-world.gcpbackend/hello
    

    现在,您的 GKE 工作负载可以通过向 hello-world.gcpbackend/hello 发送 HTTP 请求来访问 Cloud Run 服务。

您应为 GCPBackend 使用不同的名称,以免与现有 Kubernetes 服务或 Istio 服务条目冲突。如果存在冲突,则优先级顺序(从高到低)为 Kubernetes Service、istio ServiceEntry 和 GCPBackend。

请注意,虚拟服务和 GCPBackend 必须位于同一命名空间中,并且 Cloud Run 服务必须与 Cloud Service Mesh GKE 集群位于同一项目中。

(可选)使用 Cloud Run 的主机名,而不是 Cloud DNS

每个 Cloud Run 服务都会分配一个主机名(例如 hello-world.us-central1.run.app),并且可通过 DNS 在全球范围内解析。您可以直接在 GCPBackend 主机名中使用此主机名,并跳过 Cloud DNS 配置。

cat <<EOF | kubectl apply -f -
apiVersion: networking.gke.io/v1
kind: GCPBackend
metadata:
  name: cr-gcp-backend
  namespace: NAMESPACE
spec:
  hostname: hello-world.us-central1.run.app
  type: CloudRun
  cloudrun:
    service: hello-world
    region: [us-central1]
EOF

现在,您的 GKE 工作负载可以通过向 hello-world.us-central1.run.app 发送 HTTP 请求来访问 Cloud Run 服务。

(可选)配置 Istio 虚拟服务和/或目标规则

您可以为 GCPBackend 主机名配置 Istio 虚拟服务或 Istio 目的地规则,以便为发送到 GCPBackend 的请求设置使用方或客户端政策。

以下示例会向 50% 的请求注入 5 秒的延迟,并向 10% 的 GCPBackend 请求注入中止(503 HTTP 状态代码)。

cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: cr-virtual-service
  namespace: NAMESPACE
spec:
  hosts:
  - hello-world.us-central1.run.app
  gateways:
  - mesh
  http:
  - fault:
      delay:
        percentage:
          value: 50  # Delay 50% of requests
        fixedDelay: 5s
      abort:
        percentage:
          value: 10  # Abort 10% of requests
        httpStatus: 503
  - route:
    - destination:
        host: hello-world.us-central1.run.app
EOF

在此示例中,VIRTUAL_SERVICE_NAMEcr-virtual-service

问题排查

本部分介绍如何排查 Cloud Service Mesh 和 Cloud Run 的常见错误。

Cloud Run 边车日志

Envoy 错误会记录在 Cloud Logging 中。

例如,如果未向 Cloud Run 服务账号授予网格项目中的 trafficdirector 客户端角色,系统会记录以下错误:

StreamAggregatedResources gRPC config stream to trafficdirector.googleapis.com:443 closed: 7, Permission 'trafficdirector.networks.getConfigs' denied on resource '//trafficdirector.googleapis.com/projects/525300120045/networks/mesh:test-mesh/nodes/003fb3e0c8927482de85f052444d5e1cd4b3956e82b00f255fbea1e114e1c0208dbd6a19cc41694d2a271d1ab04b63ce7439492672de4499a92bb979853935b03d0ad0' (or it may not exist).

CSDS

您可以使用 CSDS 检索 trafficdirector 客户端状态:

gcloud alpha container fleet mesh debug proxy-status --membership=<CLUSTER_MEMBERSHIP> --location=<CLUSTER_LOCATION>
External Clients:
....

后续步骤