設定 Google Kubernetes Engine 和無 Proxy 的 gRPC 服務

本指南說明如何設定 Google Kubernetes Engine、gRPC 應用程式,以及 Cloud Service Mesh 要求的負載平衡元件。

按照本指南中的說明操作之前,請先參閱「準備設定使用無 Proxy gRPC 服務的 Cloud Service Mesh」。

總覽

使用 GKE 和無 Proxy gRPC 服務設定 Cloud Service Mesh 時,需要執行下列步驟:

  1. 準備 GKE 叢集。
  2. 將 gRPC 伺服器應用程式部署為 Kubernetes 服務。為 GKE 部署規格加上註解,自動為服務建立網路端點群組 (NEG)。
  3. 使用 NEG 和其他 Google Cloud 負載平衡元件設定 Cloud Service Mesh。
  4. 使用無 Proxy gRPC 用戶端應用程式將流量傳送至 gRPC 伺服器應用程式,確認部署作業正常運作。

為 Cloud Service Mesh 設定 GKE 叢集

本節說明如何啟用 GKE 叢集,以便與 Cloud Service Mesh 搭配使用。

GKE 叢集需求

GKE 叢集必須符合下列要求:

  • 您必須啟用網路端點群組支援功能。如需更多資訊和範例,請參閱「獨立網路端點群組」。獨立 NEG 功能現已正式推出,適用於 Cloud Service Mesh。
  • 叢集節點執行個體服務帳戶必須具有存取 Cloud Service Mesh API 的權限。如要進一步瞭解必要權限,請參閱「啟用服務帳戶以存取 Cloud Service Mesh API」。
  • 容器必須有權存取 Cloud Service Mesh API,並受 OAuth 驗證保護。詳情請參閱主機設定

建立 GKE 叢集

下列範例說明如何在 us-central1-a zone 中建立名為 grpc-td-cluster 的 GKE 叢集。

控制台

如要使用 Google Cloud 控制台建立叢集,請執行下列步驟:

  1. 前往 Google Cloud 控制台的 Kubernetes Engine 選單。

    前往 Google Kubernetes Engine 選單

  2. 點選「建立叢集」

  3. 選擇 [Standard cluster] (標準叢集) 範本,或者為您的工作負載選擇適當的範本

  4. 視需要自訂範本。以下均為必填欄位:

    • 名稱:輸入 grpc-td-cluster
    • 位置類型: Zonal
    • 區域: us-central1-a
    • 節點集區:
  5. 按一下左側選單中的「default-pool」

  6. 將「Name」(名稱) 變更為 grpc-td-cluster

  7. 在「大小」下方,輸入要建立的節點數量。您必須要有可用於節點及其資源 (例如防火牆路徑) 的資源配額

  8. 在左側選單中,按一下「節點」

  9. 在「機器設定」下,按一下「機器家族」中的「運算最佳化」

  10. 選取「機型」。如需機型的定價資訊,請參閱 Compute Engine 定價頁面

  11. 在「Networking」(網路) 下方,新增「Network tag」(網路標記) allow-health-checks

  12. 按一下左側選單中的「節點安全性」

  13. 在 [Access scopes] (存取權範圍) 下,選取 [Allow full access to all Cloud APIs] (允許所有 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 搭配使用。此程序包含設定 GKE helloworld 範例服務,並加入 NEG 註解。

helloworld 範例服務是 gRPC 伺服器應用程式,會傳回訊息來回應 gRPC 用戶端的要求。請注意,helloworld 服務沒有任何特殊之處。這不是無 Proxy 的 gRPC 服務,可以回應任何 gRPC 用戶端的要求。

只有在 gRPC 用戶端應用程式連線至 Cloud Service Mesh、瞭解 helloworld 服務,然後將流量傳送至與 helloworld 相關聯的 Pod 時,「無 Proxy」部分才會發揮作用,不需要依賴 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 位址和通訊埠。如需更多資訊和範例,請參閱獨立網路端點群組

在下列範例中,您部署的 helloworld Kubernetes 服務會公開通訊埠 8080。這是服務在叢集中顯示的通訊埠。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 控制台的「Network Endpoint Groups」(網路端點群組) 頁面。您會看到名為「example-grpc-server」的 NEG。
前往「Network Endpoint Groups」(網路端點群組) 頁面

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 負載平衡 Google Cloud 元件。這些元件包含設定資訊,可讓無 Proxy 的 gRPC 用戶端與 GKE 服務通訊。

下列 Cloud Service Mesh 設定範例假設:

  • NEG 和其他所有資源都會在 us-central1-a 區域中,以自動模式建立在預設網路。
  • 使用 Google Cloud CLI 時,叢集的 NEG 名稱為 example-grpc-server

建立健康狀態檢查、防火牆規則和後端服務

在本節中,您將建立健康狀態檢查和健康狀態檢查的防火牆規則。健康狀態檢查必須使用 gRPC 健康狀態檢查通訊協定。防火牆規則可讓健康狀態檢查探測器連線至部署中的 VM。健康狀態檢查會使用 --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 Proxy 和轉送規則。

詳情請參閱轉送規則對應

以下範例使用服務名稱 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 Proxy。

    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 端點之間,進行負載平衡。

驗證設定

設定程序完成後,請確認您可以使用無 Proxy gRPC 用戶端連上 helloworld gRPC 伺服器。這個用戶端會連線至 Cloud Service Mesh,取得 helloworld 服務的相關資訊 (使用 grpc-gke-helloworld-service 後端服務設定 Cloud Service Mesh),並使用這項資訊將流量傳送至服務的後端。

您也可以在 Google Cloud 控制台中查看「Cloud Service Mesh」專區,瞭解已設定的服務 helloworld-gke 資訊,並確認後端是否回報為正常。

使用無 Proxy gRPC 用戶端進行驗證

在下列範例中,您可以使用不同語言的 gRPC 用戶端或 grpcurl 工具,確認 Cloud Service Mesh 是否在網格中正確轉送流量。您會建立用戶端 Pod,然後開啟殼層,並從殼層執行驗證指令。

設定環境變數和啟動檔案

用戶端應用程式需要啟動設定檔。新增 initContainer,產生啟動程序檔案和傳輸檔案的磁碟區,藉此修改 Kubernetes 應用程式部署規格。更新現有容器,找出該檔案。

在應用程式部署規格中新增下列 initContainer

      initContainers:
      - args:
        - --output
        - "/tmp/bootstrap/td-grpc-bootstrap.json"
        image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.19.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.19.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 的殼層。

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 工具也可以做為無 Proxy 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. 使用「xds:///helloworld-gke:8000」做為服務 URI,並以 helloworld.Greeter/SayHello 做為要叫用的服務名稱和方法,執行 grpcurl 工具。SayHello 方法的參數會透過 -d 選項傳遞。

    ./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 是 VM 執行個體的主機名稱:

Greetings: Hello world, from INSTANCE_HOST_NAME

這項作業會驗證無 Proxy gRPC 用戶端是否已成功連線至 Cloud Service Mesh,並使用 xds 名稱解析器瞭解 helloworld-gke 服務的後端。用戶端將要求傳送至其中一個服務後端,不必瞭解 IP 位址或執行 DNS 解析。

後續步驟