设置 Google Kubernetes Engine 和无代理 gRPC 服务

本指南介绍如何配置 Google Kubernetes Engine、gRPC 应用以及 Cloud Service Mesh 所需的负载均衡组件。

在按照本指南中的说明执行操作之前,请参阅准备使用无代理 gRPC 服务设置 Cloud Service Mesh

概览

使用 GKE 和无代理 gRPC 服务设置 Cloud Service Mesh 涉及以下内容:

  1. 准备 GKE 集群。
  2. 将 gRPC 服务器应用部署为 Kubernetes 服务。为 GKE 部署规范添加注释,以自动为服务创建网络端点组 (NEG)。
  3. 使用 NEG 和其他 Google Cloud 负载平衡组件配置 Cloud Service Mesh。
  4. 使用无代理 gRPC 客户端应用向 gRPC 服务器应用发送流量,以验证部署是否正常运行。

为 Cloud Service Mesh 配置 GKE 集群

本部分介绍如何将 GKE 集群与 Cloud Service Mesh 搭配使用。

GKE 集群要求

GKE 集群必须满足以下要求:

  • 必须启用网络端点组支持。如需了解详情和示例,请参阅独立网络端点组。独立的 NEG 功能现已面向 Cloud Service Mesh 推出正式版。
  • 集群节点实例的服务账号必须有权访问 Cloud Service Mesh API。如需详细了解所需权限,请参阅启用服务账号以访问 Cloud Service Mesh API
  • 容器必须有权访问受 OAuth 身份验证保护的 Cloud Service Mesh API。如需了解详情,请参阅主机配置

创建 GKE 集群

以下示例展示了如何在 us-central1-a zone 中创建名为 grpc-td-cluster 的 GKE 集群。

控制台

如需使用 Google Cloud 控制台创建集群,请执行以下步骤:

  1. 转到 Google Cloud 控制台中的 Kubernetes Engine 菜单。

    转到 Google Kubernetes Engine 菜单

  2. 点击创建集群

  3. 选择标准集群模板,或者为您的工作负载选择一个合适的模板

  4. 自定义模板(如有必要)。以下字段是必填字段:

    • 名称:输入 grpc-td-cluster
    • 位置类型Zonal
    • 区域us-central1-a
    • 节点池
  5. 在左侧菜单中,点击 default-pool

  6. 名称更改为 grpc-td-cluster

  7. 大小下,输入要创建的节点数。您必须具有节点及其资源(例如防火墙路由)的可用资源配额

  8. 在左侧菜单中,点击节点

  9. 机器配置下的机器系列中,点击计算优化

  10. 选择机器类型。如需了解机器类型价格信息,请参阅 Compute Engine 价格页面

  11. 网络下,添加网络标记 allow-health-checks

  12. 在左侧菜单中,点击节点安全

  13. 访问权限范围下方,选择允许所有 Cloud API 的全面访问权限

  14. 点击创建

在 Google Cloud 控制台中创建集群后,您需要配置 kubectl 以与该集群进行交互。如需了解详情,请参阅生成 kubeconfig 条目

gcloud

创建集群。

gcloud container clusters create grpc-td-cluster \
   --zone us-central1-a \
   --scopes=https://www.googleapis.com/auth/cloud-platform \
   --tags=allow-health-checks \
   --enable-ip-alias

获取所需的 GKE 集群权限

通过发出以下命令切换到刚创建的集群。这会将 kubectl 指向正确的集群。

gcloud

gcloud container clusters get-credentials grpc-td-cluster \
    --zone us-central1-a

配置 GKE 服务

本部分介绍如何准备 GKE 部署规范以使用 Cloud Service Mesh。这包括使用 NEG 注释配置 GKE helloworld 示例服务。

helloworld 示例服务是一个 gRPC 服务器应用,会返回消息来响应 gRPC 客户端的请求。请注意,helloworld 服务没有特殊要求。它不是无代理 gRPC 服务,并且可以响应来自任何 gRPC 客户端的请求。

仅当 gRPC 客户端应用连接到 Cloud Service Mesh、了解 helloworld 服务,然后可以将流量发送到与 helloworld 关联的 Pod,而无需依赖 IP 地址或基于 DNS 的名称解析时,“无代理”部分才会发挥作用。

使用 NEG 配置 GKE 服务

配置 GKE 服务以与 Cloud Service Mesh 搭配使用的第一步是通过 NEG 公开服务。要通过 NEG 公开,每项规范都必须具有以下注释,并与要公开的端口匹配。

...
metadata:
  annotations:
    cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}'

此注释会在您首次部署服务时创建独立的 NEG。此 NEG 包含 Pod 的 IP 地址和端口。如需了解详情和示例,请参阅独立网络端点组

在以下示例中,您将部署一个在端口 8080 上公开的 helloworld Kubernetes 服务。这是服务在集群中可见的端口。Pod 中的 gRPC 服务正在侦听 targetPort 50051。这是将请求发送到的 Pod 上的端口。通常,为方便起见,porttargetPort 设置为相同的值,但此示例使用不同的值来指示要在 NEG 注释中使用的正确值。

cat << EOF > grpc-td-helloworld.yaml
apiVersion: v1
kind: Service
metadata:
  name: helloworld
  annotations:
    cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}'
spec:
  ports:
  - port: 8080
    name: helloworld
    protocol: TCP
    targetPort: 50051
  selector:
    run: app1
  type: ClusterIP

---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: app1
  name: app1
spec:
  selector:
    matchLabels:
      run: app1
  replicas: 2
  template:
    metadata:
      labels:
        run: app1
    spec:
      containers:
      - image: grpc/java-example-hostname:1.50.2
        name: app1
        ports:
        - protocol: TCP
          containerPort: 50051
EOF
kubectl apply -f grpc-td-helloworld.yaml

验证是否已创建新的 helloworld 服务:

kubectl get svc

kubectl get svc 的输出应如下所示:

NAME           TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
helloworld     ClusterIP   10.71.9.71   <none>        8080/TCP  41m
[..skip..]

验证应用 Pod 是否正在运行:

kubectl get pods

kubectl get pods 的输出应如下所示:

NAME                        READY     STATUS    RESTARTS   AGE
app1-6db459dcb9-zvfg2   1/1       Running   0          6m
app1-6db459dcb9-hlvhj   1/1       Running   0          6m
[..skip..]

验证 NEG 名称是否正确。

控制台

如需查看网络端点组的列表,请转到 Google Cloud Console 中的“网络端点组”页面。您会看到一个名为 example-grpc-server 的 NEG。
转到“网络端点组”页面

gcloud

# List the NEGs
gcloud compute network-endpoint-groups list \
    --filter "name=example-grpc-server" --format "value(name)"

# Optionally examine the NEG
gcloud compute network-endpoint-groups describe example-grpc-server \
    --zone us-central1-a

# Optionally examine the endpoint(s) contained
gcloud compute network-endpoint-groups list-network-endpoints example-grpc-server \
    --zone us-central1-a

使用负载均衡组件配置 Cloud Service Mesh

本部分介绍如何为服务配置 Google Cloud 负载均衡组件。这些组件包含配置信息,无代理 (gRPC) 客户端可利用此类信息与 GKE 服务通信。

下面的 Cloud Service Mesh 配置示例做出了以下假设:

  • NEG 和所有其他资源是在区域 us-central1-a 的自动模式默认网络中创建发。
  • 使用 Google Cloud CLI 时,集群的 NEG 名称为 example-grpc-server

创建健康检查、防火墙规则和后端服务

在本部分中,您将创建健康检查以及健康检查的防火墙规则。健康检查必须使用 gRPC 健康检查协议。防火墙规则允许健康检查探测连接到部署中的虚拟机。--use-serving-port 指令由健康检查用于为每个端点获取配置的侦听端口。

防火墙规则允许与您网络中的实例建立传入健康检查连接。

在本部分中,您将创建负载均衡方案为 INTERNAL_SELF_MANAGED 且协议为 GRPC 的全局后端服务,然后将健康检查与后端服务相关联。

如需了解详情,请参阅创建健康检查

gcloud

  1. 创建健康检查。

    gcloud compute health-checks create grpc grpc-gke-helloworld-hc \
     --use-serving-port
    
  2. 创建防火墙规则。

    gcloud compute firewall-rules create grpc-gke-allow-health-checks \
      --network default --action allow --direction INGRESS \
      --source-ranges 35.191.0.0/16,130.211.0.0/22 \
      --target-tags allow-health-checks \
      --rules tcp:50051
    
  3. 创建后端服务。

    gcloud compute backend-services create grpc-gke-helloworld-service \
       --global \
       --load-balancing-scheme=INTERNAL_SELF_MANAGED \
       --protocol=GRPC \
       --health-checks grpc-gke-helloworld-hc
    
  4. 将后端 NEG 添加到后端服务。

    gcloud compute backend-services add-backend grpc-gke-helloworld-service \
       --global \
       --network-endpoint-group example-grpc-server \
       --network-endpoint-group-zone us-central1-a \
       --balancing-mode RATE \
       --max-rate-per-endpoint 5
    

创建路由规则映射

在本部分中,您将创建网址映射、路径匹配器和主机规则,以根据主机名和路径路由服务的流量。以下示例使用 helloworld-gke 作为服务名称。gRPC 客户端在连接到 helloworld 服务时会在目标 URI 中使用此服务名称。您还将创建目标 gRPC 代理和转发规则。

如需了解详情,请参阅路由规则映射

以下示例使用服务名称 helloworld-gke 和端口 8000。这意味着 gRPC 客户端必须使用 xds:///helloworld-gke:8000 连接到此服务,并且必须在网址映射中配置主机规则 helloworld-gke:8000。请注意,Cloud Service Mesh 不使用上一部分中 Kubernetes 服务规范中显示的服务端口 8080,因为 helloworld-gke:8000 直接解析为侦听 targetPort 50051 的 NEG 端点。通常,为方便起见,网址映射主机规则中的端口以及 Kubernetes 服务规范 porttargetPort 都设置为相同的值,但此示例使用不同的值来表明服务中的 port 规范不由 Cloud Service Mesh 使用。

gcloud

  1. 创建网址映射。

    gcloud compute url-maps create grpc-gke-url-map \
    --default-service grpc-gke-helloworld-service
    
  2. 创建路径匹配器。

    gcloud compute url-maps add-path-matcher grpc-gke-url-map \
    --default-service grpc-gke-helloworld-service \
    --path-matcher-name grpc-gke-path-matcher \
    --new-hosts helloworld-gke:8000
    
  3. 创建目标 gRPC 代理。

    gcloud compute target-grpc-proxies create grpc-gke-proxy \
    --url-map grpc-gke-url-map \
    --validate-for-proxyless
    
  4. 创建转发规则。

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

现在,已将 Cloud Service Mesh 配置为针对网址映射中指定的服务,跨 NEG 中的端点进行流量负载均衡。

验证配置

配置过程完成后,验证是否可以使用无代理 gRPC 客户端访问 helloworld gRPC 服务器。此客户端连接到 Cloud Service Mesh,获取有关 helloworld 服务的信息(使用 grpc-gke-helloworld-service 后端服务通过 Cloud Service Mesh 配置),并使用此信息将流量发送到服务的后端。

您还可以检查 Google Cloud 控制台中的 Cloud Service Mesh 部分,获取已配置服务 helloworld-gke 的相关信息,并查看后端是否被报告为运行状况良好。

使用无代理 gRPC 客户端进行验证

在以下示例中,您以不同语言使用 gRPC 客户端,或使用 grpcurl 工具验证 Cloud Service Mesh 是否在网格中正确路由流量。您创建一个客户端 Pod,然后打开 shell 并从 shell 运行验证命令。

设置环境变量和引导文件

客户端应用需要引导配置文件。通过添加生成引导文件的 initContainer 和传输文件所需的卷来修改 Kubernetes 应用部署规范。更新现有容器以查找该文件。

将以下 initContainer 添加到应用部署规范:

      initContainers:
      - args:
        - --output
        - "/tmp/bootstrap/td-grpc-bootstrap.json"
        image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0

        imagePullPolicy: IfNotPresent
        name: grpc-td-init
        resources:
          limits:
            cpu: 100m
            memory: 100Mi
          requests:
            cpu: 10m
            memory: 100Mi
        volumeMounts:
        - name: grpc-td-conf
          mountPath: /tmp/bootstrap/
      volumes:
      - name: grpc-td-conf
        emptyDir:
          medium: Memory

更新应用容器的 env 部分,使其包含以下内容:

        env:
        - name: GRPC_XDS_BOOTSTRAP
          value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
        volumeMounts:
        - name: grpc-td-conf
          mountPath: /tmp/grpc-xds/

这是客户端 Kubernetes 规范的完整示例:

cat << EOF  | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    run: client
  name: sleeper
spec:
  selector:
    matchLabels:
      run: client
  template:
    metadata:
      labels:
        run: client
    spec:
      containers:
      - image: openjdk:8-jdk
        imagePullPolicy: IfNotPresent
        name: sleeper
        command:
        - sleep
        - 365d
        env:
        - name: GRPC_XDS_BOOTSTRAP
          value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
        resources:
          limits:
            cpu: "2"
            memory: 2000Mi
          requests:
            cpu: 300m
            memory: 1500Mi
        volumeMounts:
        - name: grpc-td-conf
          mountPath: /tmp/grpc-xds/
      initContainers:
      - args:
        - --output
        - "/tmp/bootstrap/td-grpc-bootstrap.json"
        image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
        imagePullPolicy: IfNotPresent
        name: grpc-td-init
        resources:
          limits:
            cpu: 100m
            memory: 100Mi
          requests:
            cpu: 10m
            memory: 100Mi
        volumeMounts:
        - name: grpc-td-conf
          mountPath: /tmp/bootstrap/
      volumes:
      - name: grpc-td-conf
        emptyDir:
          medium: Memory
EOF

部署准备就绪后,打开客户端 Pod 的 shell。

kubectl exec -it $(kubectl get pods -o custom-columns=:.metadata.name \
    --selector=run=client) -- /bin/bash

如需验证配置,请在 Pod shell 中运行相应的示例。

Java

如需使用 gRPC Java 客户端验证服务,请执行以下操作:

  1. 下载最新版本的 gRPC Java,然后使用最新的补丁程序并构建 xds-hello-world 客户端应用。

     curl -L https://github.com/grpc/grpc-java/archive/v1.37.0.tar.gz | tar -xz
     cd grpc-java-1.37.0/examples/example-xds
     ../gradlew --no-daemon installDist
     

  2. 运行客户端,其中 "world" 作为客户端名称,"xds:///helloworld-gke:8000" 作为服务 URI 和端口。

    ./build/install/example-xds/bin/xds-hello-world-client "world" \
    xds:///helloworld-gke:8000
    

Go

如需使用 gRPC Go 客户端验证服务,请执行以下操作:

  1. 下载最新版本的 gRPC Go,然后使用最新的补丁程序并构建 xds-hello-world 客户端应用。

    apt-get update -y
    apt-get install -y golang git
    curl -L https://github.com/grpc/grpc-go/archive/v1.37.0.tar.gz | tar -xz
    cd grpc-go-1.37.0/examples/features/xds/client
    go get google.golang.org/grpc@v1.37.0
    go build .
    
  2. 运行客户端,其中 "world" 作为客户端名称,"xds:///helloworld-gke:8000" 作为服务 URI 和端口。

    ./client "world" xds:///helloworld-gke:8000
    

C++

如需使用 gRPC C++ 客户端验证服务,请执行以下操作:

  1. 下载最新版本的 gRPC C++ 以及最近的补丁程序,然后构建 helloworld 客户端示例。

    apt-get update -y
    apt-get install -y build-essential cmake git
    git clone --recurse-submodules -b v1.37.1 https://github.com/grpc/grpc
    cd grpc
    mkdir -p cmake/build
    pushd cmake/build
    cmake ../..
    make
    make install
    popd
    mkdir -p third_party/abseil-cpp/cmake/build
    pushd third_party/abseil-cpp/cmake/build
    cmake ../..
    make
    make install
    popd
    cd examples/cpp/helloworld
    mkdir -p cmake/build
    cd cmake/build/
    cmake ../..
    make
    
  2. 运行客户端,其中将“xds:///helloworld-gke:8000”作为服务 URI 和端口。

    ./greeter_client --target=xds:///helloworld-gke:8000
    

grpcurl

grpcurl 工具也可以充当无代理 gRPC 客户端。在这种情况下,grpcurl 使用环境变量和引导信息来连接到 Cloud Service Mesh。接着,它会了解 helloworld 服务,该服务通过 grpc-gke-helloworld-service 后端服务使用 Cloud Service Mesh 配置。

如需使用 grpcurl 工具验证您的配置,请执行以下操作:

  1. 下载并安装 grpcurl 工具。

    curl -L https://github.com/fullstorydev/grpcurl/releases/download/v1.8.1/grpcurl_1.8.1_linux_x86_64.tar.gz | tar -xz
    
  2. 运行 grpcurl 工具,其中“xds:///helloworld-gke:8000”作为服务 URI,helloworld.Greeter/SayHello 作为服务名称和要调用的方法。使用 -d 选项传递 SayHello 方法的参数。

    ./grpcurl --plaintext \
      -d '{"name": "world"}' \
      xds:///helloworld-gke:8000 helloworld.Greeter/SayHello
    

Python

如需使用 gRPC Python 客户端验证服务,请运行以下命令。使用包含最新补丁程序的最新版 gRPC。

apt-get update -y
apt-get install python3-pip -y
pip3 install virtualenv
curl -L https://github.com/grpc/grpc/archive/v1.37.1.tar.gz | tar -xz
cd grpc-1.37.1/examples/python/xds
virtualenv venv -p python3
source venv/bin/activate
pip install -r requirements.txt
python client.py  xds:///helloworld-gke:8000

Ruby

如需使用 gRPC Ruby 客户端验证服务,请运行以下命令。使用包含最新补丁程序的最新版 gRPC。

apt-get update -y
apt-get install -y ruby-full
gem install grpc
curl -L https://github.com/grpc/grpc/archive/v1.37.1.tar.gz | tar -xz
cd grpc-1.37.1/examples/ruby
ruby greeter_client.rb john xds:///helloworld-gke:8000

PHP

如需使用 gRPC PHP 客户端验证服务,请运行以下命令。使用包含最新补丁程序的最新版 gRPC。

apt-get update -y
apt-get install -y php7.3 php7.3-dev php-pear phpunit python-all zlib1g-dev git
pecl install grpc
curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer
curl -L https://github.com/grpc/grpc/archive/v1.37.1.tar.gz | tar -xz
cd grpc-1.37.1
export CC=/usr/bin/gcc
./tools/bazel build @com_google_protobuf//:protoc
./tools/bazel build src/compiler:grpc_php_plugin
cd examples/php
composer install
../../bazel-bin/external/com_google_protobuf/protoc --proto_path=../protos \
--php_out=. --grpc_out=. \
--plugin=protoc-gen-grpc=../../bazel-bin/src/compiler/grpc_php_plugin \
../protos/helloworld.proto
php -d extension=grpc.so greeter_client.php john xds:///helloworld-gke:8000

Node.js

如需使用 gRPC Node.js 客户端验证服务,请运行以下命令。使用包含最新补丁程序的最新版 gRPC。

apt-get update -y
apt-get install -y nodejs npm
curl -L https://github.com/grpc/grpc/archive/v1.34.0.tar.gz | tar -xz
cd grpc-1.34.0/examples/node/xds
npm install
node ./greeter_client.js --target=xds:///helloworld-gke:8000

您应该会看到如下所示的输出,其中 INSTANCE_HOST_NAME 是虚拟机实例的主机名:

Greetings: Hello world, from INSTANCE_HOST_NAME

这将验证无代理 gRPC 客户端是否已成功连接到 Cloud Service Mesh,并使用 xds 名称解析器了解 helloworld-gke 服务的后端。客户端向服务的其中一个后端发送请求,无需了解 IP 地址或执行 DNS 解析。

后续步骤