使用自动 Envoy 注入设置 Google Kubernetes Engine Pod

概览

在服务网格中,您的应用代码不需要了解网络配置。相反,您的应用通过数据平面进行通信,该数据平面由处理服务网络的控制平面进行配置。在本指南中,Cloud Service Mesh 是您的控制平面,而 Envoy Sidecar 代理是您的数据平面。

Google 托管的 Envoy Sidecar 注入器会将 Envoy Sidecar 代理添加到您的 Google Kubernetes Engine Pod 中。在 Envoy Sidecar 注入器添加代理时,它还会设置该代理以处理应用流量并连接到 Cloud Service Mesh 以进行配置。

本指南将逐步介绍 Google Kubernetes Engine 的 Cloud Service Mesh 设置。这些步骤为扩展到高级使用场景奠定了基础,例如扩展到多个 Google Kubernetes Engine 集群以及 Compute Engine 虚拟机的服务网格。 如果您要使用共享 VPC 配置 Cloud Service Mesh,也可以按照这些说明操作。

设置过程包括:

  1. 为您的工作负载创建 GKE 集群。
  2. 安装 Envoy Sidecar 注入器并启用注入。
  3. 部署样本客户端并验证注入。
  4. 部署 Kubernetes 服务以进行测试。
  5. 使用 Cloud Load Balancing 组件配置 Cloud Service Mesh,以将流量路由到测试服务。
  6. 从示例客户端向测试服务发送请求以验证配置。
在此设置指南中部署的组件概览(点击可放大)
在此设置指南中部署的组件概览(点击可放大)

前提条件

在按照本指南中的说明操作之前,请先完成准备使用 Envoy 和无代理工作负载设置服务路由 API 中所述的前提任务。

如需了解受支持的 Envoy 版本,请参阅 Cloud Service Mesh 版本说明

使用共享 VPC 的其他前提条件

如果您要在共享 VPC 环境中设置 Cloud Service Mesh,请确保满足以下条件。

  • 您拥有共享 VPC 的正确权限和角色。
  • 您已正确设置项目和结算。
  • 您已在项目中启用结算功能。
  • 您已在每个项目(包括宿主项目)中启用 Cloud Service Mesh 和 GKE API。
  • 您已为每个项目设置了正确的服务账号。
  • 您已创建 VPC 网络和子网。
  • 您已启用共享 VPC。

如需了解详情,请参阅共享 VPC

配置 IAM 角色

此 IAM 角色配置示例假定共享 VPC 的宿主项目有两个子网,并且共享 VPC 中有两个服务项目。

  1. 在 Cloud Shell 中,创建一个工作文件夹 (WORKDIR)),您可以在其中创建与本部分关联的文件:

    mkdir -p ~/td-shared-vpc
    cd ~/td-shared-vpc
    export WORKDIR=$(pwd)
    
  2. 在宿主项目中配置 IAM 权限,以便服务项目可以使用共享 VPC 中的资源。

    在此步骤中,您将配置 IAM 权限,使服务项目 1 可以访问 subnet-1,服务项目 2 可以访问 subnet-2。您将 Compute Network User IAM 角色 (roles/compute.networkUser) 分配给每个子网的各服务项目中的 Compute Engine 计算默认服务账号和 Google Cloud API 服务账号。

    1. 对于服务项目 1,为 subnet-1 配置 IAM 权限:

      export SUBNET_1_ETAG=$(gcloud beta compute networks subnets get-iam-policy subnet-1 --project ${HOST_PROJECT} --region ${REGION_1} --format=json | jq -r '.etag')
      
      cat > subnet-1-policy.yaml <<EOF
      bindings:
      - members:
        - serviceAccount:${SVC_PROJECT_1_API_SA}
        - serviceAccount:${SVC_PROJECT_1_GKE_SA}
        role: roles/compute.networkUser
      etag: ${SUBNET_1_ETAG}
      EOF
      
      gcloud beta compute networks subnets set-iam-policy subnet-1 \
      subnet-1-policy.yaml \
          --project ${HOST_PROJECT} \
          --region ${REGION_1}
      
    2. 对于服务项目 2,为 subnet-2 配置 IAM 权限:

      export SUBNET_2_ETAG=$(gcloud beta compute networks subnets get-iam-policy subnet-2 --project ${HOST_PROJECT} --region ${REGION_2} --format=json | jq -r '.etag')
      
      cat > subnet-2-policy.yaml <<EOF
      bindings:
      - members:
        - serviceAccount:${SVC_PROJECT_2_API_SA}
        - serviceAccount:${SVC_PROJECT_2_GKE_SA}
        role: roles/compute.networkUser
      etag: ${SUBNET_2_ETAG}
      EOF
      
      gcloud beta compute networks subnets set-iam-policy subnet-2 \
      subnet-2-policy.yaml \
          --project ${HOST_PROJECT} \
          --region ${REGION_2}
      
  3. 对于每个服务项目,您必须将 Kubernetes Engine Host Service Agent User IAM 角色 (roles/container.hostServiceAgentUser) 授予宿主项目中的 GKE 服务账号:

    gcloud projects add-iam-policy-binding ${HOST_PROJECT} \
        --member serviceAccount:${SVC_PROJECT_1_GKE_SA} \
        --role roles/container.hostServiceAgentUser
    
    gcloud projects add-iam-policy-binding ${HOST_PROJECT} \
        --member serviceAccount:${SVC_PROJECT_2_GKE_SA} \
        --role roles/container.hostServiceAgentUser
    

    此角色允许服务项目的 GKE 服务账号使用宿主项目的 GKE 服务账号来配置共享网络资源。

  4. 对于每个服务项目,向 Compute Engine 默认服务账号授予宿主项目中的 Compute Network Viewer IAM 角色 (roles/compute.networkViewer)。

    gcloud projects add-iam-policy-binding ${SVC_PROJECT_1} \
        --member serviceAccount:${SVC_PROJECT_1_COMPUTE_SA} \
        --role roles/compute.networkViewer
    
    gcloud projects add-iam-policy-binding ${SVC_PROJECT_2} \
        --member serviceAccount:${SVC_PROJECT_2_COMPUTE_SA} \
        --role roles/compute.networkViewer
    

    Envoy 边车代理连接到 xDS 服务 (Traffic Director API) 后,该代理将使用 Compute Engine 虚拟机主机或 GKE 节点实例的服务账号。该服务账号必须具有 compute.globalForwardingRules.get 项目级层 IAM 权限。使用 Compute Network Viewer 角色足以完成此步骤。

配置项目信息

如果您尚未创建 Google Cloud 项目或安装 Google Cloud CLI,请按照这些说明操作。如果您尚未安装 kubectl,请按照以下说明操作。

# The project that contains your GKE cluster.
export CLUSTER_PROJECT_ID=YOUR_CLUSTER_PROJECT_NUMBER_HERE
# The name of your GKE cluster.
export CLUSTER=YOUR_CLUSTER_NAME
# The channel of your GKE cluster. Eg: rapid, regular, stable. This channel
# should match the channel of your GKE cluster.
export CHANNEL=YOUR_CLUSTER_CHANNEL
# The location of your GKE cluster, Eg: us-central1 for regional GKE cluster,
# us-central1-a for zonal GKE cluster
export LOCATION=ZONE

# The network name of the traffic director load balancing API.
export MESH_NAME=default
# The project that holds the mesh resources.
export MESH_PROJECT_NUMBER=YOUR_PROJECT_NUMBER_HERE

export TARGET=projects/${MESH_PROJECT_NUMBER}/global/networks/${MESH_NAME}

gcloud config set project ${CLUSTER_PROJECT_ID}

如果您使用的是新的服务路由 API,请按照以下说明设置 MESH_NAMEMESH_PROJECT_NUMBERTARGET

# The mesh name of the traffic director load balancing API.
export MESH_NAME=YOUR_MESH_NAME
# The project that holds the mesh resources.
export MESH_PROJECT_NUMBER=YOUR_PROJECT_NUMBER_HERE

export TARGET=projects/${MESH_PROJECT_NUMBER}/locations/global/meshes/${MESH_NAME}

在大多数情况下,CLUSTER_PROJECT_IDMESH_PROJECT_NUMBER 是指同一项目。不过,如果您设置了其他项目(例如使用共享 VPC 时),CLUSTER_PROJECT_ID 是指包含 GKE 集群的项目 ID,MESH_PROJECT_NUMBER 是指包含资源的项目编号。确保您已配置适当的权限,以允许注入的 Envoy 从

启用 Mesh Config API

启用以下 API 即可开始使用 Google 托管的 Sidecar 注入器。

gcloud services enable --project=${CLUSTER_PROJECT_ID} meshconfig.googleapis.com

为您的工作负载创建 GKE 集群

GKE 集群必须满足以下要求才能支持 Cloud Service Mesh:

创建 GKE 集群

在您的首选可用区(例如 us-central1-a)中创建一个 GKE 集群。

gcloud container clusters create YOUR_CLUSTER_NAME \
  --zone ZONE \
  --scopes=https://www.googleapis.com/auth/cloud-platform \
  --enable-ip-alias

将 kubectl 指向新创建的集群

发出以下命令,将 kubectl 的当前上下文更改为新创建的集群:

gcloud container clusters get-credentials traffic-director-cluster \
    --zone ZONE

应用用于更改性网络钩子的配置

以下部分提供了将 MutatingWebhookConfiguration 应用于集群的说明。创建 Pod 时,系统会调用集群内准入控制器。准入控制器会与托管的 Sidecar 注入器通信,以将 Envoy 容器添加到 pod。

将以下更改型网络钩子配置应用于您的集群。

cat <<EOF | kubectl apply -f -
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
  labels:
    app: sidecar-injector
  name: td-mutating-webhook
webhooks:
- admissionReviewVersions:
  - v1beta1
  - v1
  clientConfig:
    url: https://meshconfig.googleapis.com/v1internal/projects/${CLUSTER_PROJECT_ID}/locations/${LOCATION}/clusters/${CLUSTER}/channels/${CHANNEL}/targets/${TARGET}:tdInject
  failurePolicy: Fail
  matchPolicy: Exact
  name: namespace.sidecar-injector.csm.io
  namespaceSelector:
    matchExpressions:
    - key: td-injection
      operator: Exists
  reinvocationPolicy: Never
  rules:
  - apiGroups:
    - ""
    apiVersions:
    - v1
    operations:
    - CREATE
    resources:
    - pods
    scope: '*'
  sideEffects: None
  timeoutSeconds: 30
EOF

启用 Sidecar 注入

以下命令为 default 命名空间启用注入。Sidecar 注入器会将 Sidecar容器注入在此命名空间下创建的 pod:

kubectl label namespace default td-injection=enabled

您可以运行以下命令来验证 default 命名空间已正确启用:

kubectl get namespace -L td-injection

此时应返回:

NAME              STATUS   AGE     TD-INJECTION
default           Active   7d16h   enabled

如果您使用 Envoy 为 Cloud Service Mesh 配置服务安全,请返回到该设置指南中的设置测试服务部分。

部署示例客户端并验证注入

本部分介绍如何部署运行 Busybox 的示例 pod,它提供了一个简单的接口,可连接测试服务。在实际部署中,您应改为部署自己的客户端应用。

cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: client
  name: busybox
spec:
  replicas: 1
  selector:
    matchLabels:
      run: client
  template:
    metadata:
      labels:
        run: client
    spec:
      containers:
      - name: busybox
        image: busybox
        command:
        - sh
        - -c
        - while true; do sleep 1; done
EOF

Busybox pod 由两个容器组成。第一个容器是基于 Busybox 映像的客户端,第二个容器是由 Sidecar 注入器注入的 Envoy 代理。您可以运行以下命令来获取有关该 pod 的更多信息:

kubectl describe pods -l run=client

此时应返回:

…
Init Containers:
# Istio-init sets up traffic interception for the pod.
  Istio-init:
…
Containers:
# busybox is the client container that runs application code.
  busybox:
…
# Envoy is the container that runs the injected Envoy proxy.
  envoy:
…

Cloud Service Mesh 代理

托管式 Sidecar 注入器将使用 Cloud Service Mesh 代理映像作为代理。Cloud Service Mesh 代理是一个边车容器,负责为启用了网格的实例启动 Envoy 代理。代理映像使用 OSS envoy 映像以及负责启动 envoy、提供引导配置和对 envoy 进行健康检查的代理代理。Cloud Service Mesh 代理映像版本与 OSS Envoy 版本保持一致。您可以在此处跟踪可用的代理映像:https://gcr.io/gke-release/asm/csm-mesh-proxy

注入的 Cloud Service Mesh Mesh 代理因用户为 GKE 集群选择的渠道而异。Envoy 版本会根据当前的 OSS Envoy 版本定期更新,并会与特定 GKE 版本一起进行测试,以确保兼容性。

Cloud Service Mesh 代理版本

下表显示了当前 GKE 集群渠道与 Cloud Service Mesh 代理版本的映射:

渠道 Cloud Service Mesh 代理版本
快速 1.29.9-gke.3
常规 1.28.7-gke.3
稳定版 1.27.7-gke.3

Cloud Service Mesh 代理升级

强烈建议升级到最新版本。虽然控制平面和代理处于不同版本时服务网格正常运行,但我们建议您更新代理,使其使用新的 Cloud Service Mesh 版本进行配置。

托管式 Sidecar 注入器会负责 Envoy 的版本,始终注入 Google 认证的最新 Envoy 版本。如果 Cloud Service Mesh 代理版本比代理版本更新,请为您的服务重启代理。

kubectl rollout restart deployment -n YOUR_NAMESPACE_HERE

部署 Kubernetes 服务以进行测试

下文将介绍如何设置测试服务,您将在本指南的后面部分使用该测试服务提供设置的端到端验证。

使用 NEG 配置 GKE 服务

GKE 服务必须通过网络端点组 (NEG) 公开,以便您可以将它们配置为 Cloud Service Mesh 后端服务的后端。将 NEG 注释添加到 Kubernetes 服务规范并选择一个名称(替换以下示例中的 NEG-NAME),以便于日后查找。当您将 NEG 附加到 Cloud Service Mesh 后端服务时,将需要该名称。如需详细了解如何为 NEG 添加注释,请参阅为 NEG 命名

...
metadata:
  annotations:
    cloud.google.com/neg: '{"exposed_ports": {"80":{"name": "service-test-neg"}}}'
spec:
  ports:
  - port: 80
    name: service-test
    protocol: TCP
    targetPort: 8000

此注释创建一个独立的 NEG,其中包含与服务 pod 的 IP 地址和端口相对应的端点。如需了解详情和示例,请参阅独立网络端点组

以下示例服务包括 NEG 注释。该服务在端口 80 上通过 HTTP 提供主机名。使用以下命令获取该服务并将其部署到 GKE 集群。

wget -q -O - \
https://storage.googleapis.com/traffic-director/demo/trafficdirector_service_sample.yaml \
| kubectl apply -f -

验证新服务是否已创建,以及应用 pod 是否正在运行:

kubectl get svc

输出应类似如下所示:

NAME             TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service-test     ClusterIP   10.71.9.71   none          80/TCP    41m
[..skip..]

验证与此服务关联的应用 pod 是否正在运行:

kubectl get pods
此操作会返回:
NAME                        READY     STATUS    RESTARTS   AGE
app1-6db459dcb9-zvfg2       2/2       Running   0          6m
busybox-5dcf86f4c7-jvvdd    2/2       Running   0          10m
[..skip..]

保存 NEG 的名称

找到在上述示例中创建的 NEG 并记下其名称,以用于下一部分的 Cloud Service Mesh 配置。

gcloud compute network-endpoint-groups list

此示例会返回以下内容:

NAME                       LOCATION            ENDPOINT_TYPE       SIZE
service-test-neg           ZONE     GCE_VM_IP_PORT      1

将 NEG 的名称保存在 NEG_NAME 变量中:

NEG_NAME=$(gcloud compute network-endpoint-groups list \
| grep service-test | awk '{print $1}')

使用 Cloud Load Balancing 组件配置 Cloud Service Mesh

本部分使用 Compute Engine 负载均衡资源配置 Cloud Service Mesh。这样一来,示例客户端的边车代理即可接收来自 Cloud Service Mesh 的配置。来自示例客户端的出站请求由 Sidecar 代理处理并路由到测试服务。

您必须配置以下组件:

创建健康检查和防火墙规则

请按照以下说明创建健康检查以及健康检查探测所需的防火墙规则。如需了解详情,请参阅健康检查的防火墙规则

控制台

  1. 转到 Google Cloud 控制台中的“健康检查”页面。
    转到“健康检查”页面
  2. 点击创建健康检查
  3. 对于名称,请输入 td-gke-health-check
  4. 对于协议,请选择 HTTP
  5. 点击创建

  6. 进入 Google Cloud 控制台中的防火墙政策页面。
    进入“防火墙政策”页面

  7. 点击创建防火墙规则

  8. 在“创建防火墙规则”页面上,提供如下信息:

    • 名称:提供规则的名称。本示例使用的是 fw-allow-health-checks
    • 网络:选择一个 VPC 网络。
    • 优先级:输入一个表示优先级的数字。这个数字越小,优先级就越高。请确保防火墙规则的优先级高于可能会拒绝入站流量的其他规则的优先级。
    • 流量方向:选择入站
    • 对匹配项执行的操作:选择允许
    • 目标:选择网络中的所有实例
    • 来源过滤条件:选择正确的 IP 地址范围类型。
    • 来源 IP 地址范围35.191.0.0/16,130.211.0.0/22
    • 目标过滤条件:选择 IP 类型。
    • 协议和端口:点击指定的端口和协议,然后勾选 tcp。TCP 是所有健康检查协议的底层协议。
    • 点击创建

gcloud

  1. 创建健康检查

    gcloud compute health-checks create http td-gke-health-check \
      --use-serving-port
    
  2. 创建防火墙规则以允许健康检查程序 IP 地址范围。

    gcloud compute firewall-rules create fw-allow-health-checks \
      --action ALLOW \
      --direction INGRESS \
      --source-ranges 35.191.0.0/16,130.211.0.0/22 \
      --rules tcp
    

创建后端服务

使用负载平衡方案 INTERNAL_SELF_MANAGED 创建全局后端服务。在 Google Cloud 控制台中,负载均衡方案是隐式设置的。请将健康检查添加到后端服务。

控制台

  1. 前往 Google Cloud 控制台中的 Cloud Service Mesh 页面。

    前往 Cloud Service Mesh 页面

  2. 服务标签页上,点击创建服务

  3. 点击继续

  4. 对于服务名称,请输入 td-gke-service

  5. 选择您在 Cloud Service Mesh ConfigMap 中配置的网络

  6. 后端类型下,选择网络端点组

  7. 选择您创建的网络端点组。

  8. RPS 上限设置为 5

  9. 均衡模式设置为速率

  10. 点击完成

  11. 健康检查下,选择 td-gke-health-check,这是您创建的健康检查。

  12. 点击继续

gcloud

  1. 创建后端服务并将健康检查与后端服务相关联。

    gcloud compute backend-services create td-gke-service \
     --global \
     --health-checks td-gke-health-check \
     --load-balancing-scheme INTERNAL_SELF_MANAGED
    
  2. 将之前创建的 NEG 作为后端添加到后端服务。 如果您使用目标 TCP 代理配置 Cloud Service Mesh,则必须使用 UTILIZATION 均衡模式。如果您使用的是 HTTP 或 HTTPS 目标代理,则可以使用 RATE 模式。

    gcloud compute backend-services add-backend td-gke-service \
     --global \
     --network-endpoint-group ${NEG_NAME} \
     --network-endpoint-group-zone ZONE \
     --balancing-mode [RATE | UTILIZATION] \
     --max-rate-per-endpoint 5
    

创建路由规则映射

路由规则映射定义了 Cloud Service Mesh 如何路由您的流量。作为路由规则映射的一部分,您可以配置虚拟 IP (VIP) 地址和一组关联的流量管理规则,例如基于主机的路由。当应用向 VIP 发送请求时,附加的 Envoy Sidecar 代理将执行以下操作:

  1. 拦截请求。
  2. 根据网址映射中的流量管理规则对其进行评估。
  3. 根据请求中的主机名选择后端服务。
  4. 选择与所选后端服务关联的后端或端点。
  5. 将流量发送到该后端或端点。

控制台

在 Console 中,目标代理已与转发规则相结合。创建转发规则时,Google Cloud 会自动创建目标 HTTP 代理并将其附加到网址映射。

路由规则由转发规则以及主机和路径规则(也称为网址映射)组成。

  1. 前往 Google Cloud 控制台中的 Cloud Service Mesh 页面。

    前往 Cloud Service Mesh 页面

  2. 点击路由规则映射

  3. 点击创建路由规则

  4. 输入 td-gke-url-map 作为网址映射的名称

  5. 点击添加转发规则

  6. 对于转发规则名称,请输入 td-gke-forwarding-rule

  7. 选择您的网络。

  8. 选择您的内部 IP

  9. 点击保存

  10. (可选)添加自定义主机和路径规则,或将路径规则保留为默认值。

  11. 将主机设置为 service-test

  12. 点击保存

gcloud

  1. 创建将 td-gke-service 用作默认后端服务的网址映射。

    gcloud compute url-maps create td-gke-url-map \
       --default-service td-gke-service
    
  2. 创建网址映射路径匹配器和主机规则,以根据主机名和路径为您的服务路由流量。此示例使用 service-test 作为服务名称,并使用默认路径匹配器来匹配此主机的所有路径请求 (/*)。

    gcloud compute url-maps add-path-matcher td-gke-url-map \
       --default-service td-gke-service \
       --path-matcher-name td-gke-path-matcher
    
    gcloud compute url-maps add-host-rule td-gke-url-map \
       --hosts service-test \
       --path-matcher-name td-gke-path-matcher
    
  3. 创建目标 HTTP 代理。

    gcloud compute target-http-proxies create td-gke-proxy \
       --url-map td-gke-url-map
    
  4. 创建转发规则。

    gcloud compute forwarding-rules create td-gke-forwarding-rule \
      --global \
      --load-balancing-scheme=INTERNAL_SELF_MANAGED \
      --address=0.0.0.0 \
      --target-http-proxy=td-gke-proxy \
      --ports 80 --network default
    

此时,Cloud Service Mesh 将您的 Sidecar 代理配置为将指定 service-test 主机名的请求路由到 td-gke-service 的后端。在此示例中,这些后端是与您之前部署的 Kubernetes 测试服务关联的网络端点组中的端点。

验证配置

本部分介绍如何验证从示例 Busybox 客户端发送的流量是否路由到您的 service-test Kubernetes 服务。如需发送测试请求,您可以在其中一个容器上访问 shell并执行以下验证命令。service-test pod 应返回服务 pod 的主机名。

# Get the name of the pod running Busybox.
BUSYBOX_POD=$(kubectl get po -l run=client -o=jsonpath='{.items[0].metadata.name}')

# Command to execute that tests connectivity to the service service-test at
# the VIP 10.0.0.1. Because 0.0.0.0 is configured in the forwarding rule, this
# can be any VIP.
TEST_CMD="wget -q -O - 10.0.0.1; echo"

# Execute the test command on the pod.
kubectl exec -it $BUSYBOX_POD -c busybox -- /bin/sh -c "$TEST_CMD"

验证配置的方法如下:

  • 示例客户端发送一个指定service-test主机名的请求。
  • 示例客户端具有由 Envoy Sidecar 注入器注入的 Envoy Sidecar 代理。
  • Sidecar 代理拦截该请求。
  • Envoy 使用网址映射将 service-test 主机名与 td-gke-service Cloud Service Mesh 服务进行匹配。
  • Envoy 从与 td-gke-service 关联的网络端点组中选择一个端点。
  • Envoy 将请求发送到与 service-test Kubernetes 服务关联的 pod。

如何迁移到托管的 Sidecar 注入器

本教程将引导您将应用从 GKE 上的旧版 Cloud Service Mesh Sidecar 注入器(使用集群内 Sidecar 注入器)迁移到使用代管式 Sidecar 注入器的应用。

停用集群内 Sidecar 注入

以下命令可为默认命名空间停用旧版集群内 Sidecar 注入器

kubectl label namespace default istio-injection-

清理集群内 Sidecar 注入器

下载并解压缩旧版 Envoy Sidecar 注入器。

wget https://storage.googleapis.com/traffic-director/td-sidecar-injector-xdsv3.tgz
tar -xzvf td-sidecar-injector-xdsv3.tgz
cd td-sidecar-injector-xdsv3

删除集群内 Sidecar 注入器资源

kubectl delete -f specs/

后续步骤