在 GKE 中設定無 Proxy gRPC 服務網格

本頁面說明如何將無 Proxy gRPC 用戶端和伺服器範例部署至 Cloud Service Mesh。

事前準備

本指南假設您已具備以下條件:

需求條件

本節列出支援服務的相關規定:

  • gRPC C++ - 1.68.1 以上版本
  • gRPC Java - 1.68.2 以上版本
  • gRPC Go - 1.68.0 以上版本
  • gRPC Python - 1.68.1 以上版本

設定無 Proxy gRPC 服務

本指南將概略說明在服務網格中設定無 Proxy gRPC 服務的兩種方法:

方法 1:手動設定

使用這個方法時,您必須手動為無 Proxy gRPC 服務設定必要元件。

  • InitContainer:在 Pod 規格中使用 initContainer,執行 Cloud Service Mesh gRPC 啟動程序產生器。這個產生器會為服務產生必要的設定。
  • 磁碟區掛載:掛載包含 initContainer 產生設定的磁碟區。這可確保應用程式可存取必要的設定。
  • 環境變數:加入適當的環境變數,啟用應用程式中的 CSM 觀測度指標發送功能。這些指標可提供寶貴的洞察資料,讓您深入瞭解服務的效能。

方法 2:使用 Proxyless Bootstrap Injector 自動執行

您可以使用 Proxyless Bootstrap Injector,選擇簡化方法,而非手動設定無 Proxy gRPC 服務。

這項功能可自動執行設定程序,讓您更輕鬆地部署服務。如要啟用此功能,請將標籤 mesh.cloud.google.com/csm-injection=proxyless 新增至命名空間。

只要在命名空間中新增這個標籤,Injector 就會負責處理所有必要的設定,為您省下寶貴的時間和精力。

如果需要更精細的控管,您也可以直接將這個標籤套用至個別 Pod。這樣一來,您就能覆寫命名空間層級設定,並針對每個 Pod 自訂插入行為。

只要遵循上述任一方法,即可在服務網格中成功建立無 Proxy gRPC 服務。

手動

  1. 套用命名空間

    kubectl apply -f - <<EOF
    ---
    kind: Namespace
    apiVersion: v1
    metadata:
     name: proxyless-example
    EOF
    
  2. 部署 gRPC 服務:

C++

kubectl apply -f - <<EOF
---
apiVersion: v1
kind: Service
metadata:
  name: helloworld
  namespace: proxyless-example
spec:
  selector:
    app: psm-grpc-server
  ports:
  - port: 50051
    targetPort: 50051
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: psm-grpc-server
  namespace: proxyless-example
  labels:
    app: psm-grpc-server
spec:
  replicas: 2
  selector:
    matchLabels:
      app: psm-grpc-server
  template:
    metadata:
      labels:
        app: psm-grpc-server
        service.istio.io/canonical-name: deployment-psm-grpc-server
    spec:
      containers:
      - name: psm-grpc-server
        image: grpc/csm-o11y-example-cpp-server:v1.68.1
        imagePullPolicy: Always
        args:
          - "--port=50051"
        ports:
          - containerPort: 50051
        env:
          - name: GRPC_XDS_BOOTSTRAP
            value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: CONTAINER_NAME
            value: psm-grpc-server
          - name: NAMESPACE_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
          - name: CSM_WORKLOAD_NAME
            value: psm-grpc-server
          - name: CSM_CANONICAL_SERVICE_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.labels['service.istio.io/canonical-name']
          - name: CSM_MESH_ID
            value: proj-PROJECT_NUMBER
          - name: OTEL_RESOURCE_ATTRIBUTES
            value: k8s.pod.name=\$(POD_NAME),k8s.namespace.name=\$(NAMESPACE_NAME),k8s.container.name=\$(CONTAINER_NAME)
        volumeMounts:
          - mountPath: /tmp/grpc-xds/
            name: grpc-td-conf
            readOnly: true
      initContainers:
        - name: grpc-td-init
          image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
          imagePullPolicy: Always
          args:
            - "--output=/tmp/bootstrap/td-grpc-bootstrap.json"
            - "--vpc-network-name=default"
            - "--xds-server-uri=trafficdirector.googleapis.com:443"
            - "--generate-mesh-id"
          volumeMounts:
            - mountPath: /tmp/bootstrap/
              name: grpc-td-conf
      volumes:
        - name: grpc-td-conf
          emptyDir:
            medium: Memory
EOF

Java

kubectl apply -f - <<EOF
---
apiVersion: v1
kind: Service
metadata:
  name: helloworld
  namespace: proxyless-example
spec:
  selector:
    app: psm-grpc-server
  ports:
  - port: 50051
    targetPort: 50051
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: psm-grpc-server
  namespace: proxyless-example
  labels:
    app: psm-grpc-server
spec:
  replicas: 2
  selector:
    matchLabels:
      app: psm-grpc-server
  template:
    metadata:
      labels:
        app: psm-grpc-server
        service.istio.io/canonical-name: deployment-psm-grpc-server
    spec:
      containers:
      - name: psm-grpc-server
        image: grpc/csm-o11y-example-java-server:v1.68.2
        imagePullPolicy: Always
        args:
          - "50051"
          - "9464"
        ports:
          - containerPort: 50051
        env:
          - name: GRPC_XDS_BOOTSTRAP
            value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: CONTAINER_NAME
            value: psm-grpc-server
          - name: NAMESPACE_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
          - name: CSM_WORKLOAD_NAME
            value: psm-grpc-server
          - name: CSM_CANONICAL_SERVICE_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.labels['service.istio.io/canonical-name']
          - name: CSM_MESH_ID
            value: proj-PROJECT_NUMBER
          - name: OTEL_RESOURCE_ATTRIBUTES
            value: k8s.pod.name=\$(POD_NAME),k8s.namespace.name=\$(NAMESPACE_NAME),k8s.container.name=\$(CONTAINER_NAME)
        volumeMounts:
          - mountPath: /tmp/grpc-xds/
            name: grpc-td-conf
            readOnly: true
      initContainers:
        - name: grpc-td-init
          image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
          imagePullPolicy: Always
          args:
            - "--output=/tmp/bootstrap/td-grpc-bootstrap.json"
            - "--vpc-network-name=default"
            - "--xds-server-uri=trafficdirector.googleapis.com:443"
            - "--generate-mesh-id"
          volumeMounts:
            - mountPath: /tmp/bootstrap/
              name: grpc-td-conf
      volumes:
        - name: grpc-td-conf
          emptyDir:
            medium: Memory
EOF

Go

kubectl apply -f - <<EOF
---
apiVersion: v1
kind: Service
metadata:
  name: helloworld
  namespace: proxyless-example
spec:
  selector:
    app: psm-grpc-server
  ports:
  - port: 50051
    targetPort: 50051
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: psm-grpc-server
  namespace: proxyless-example
  labels:
    app: psm-grpc-server
spec:
  replicas: 2
  selector:
    matchLabels:
      app: psm-grpc-server
  template:
    metadata:
      labels:
        app: psm-grpc-server
        service.istio.io/canonical-name: deployment-psm-grpc-server
    spec:
      containers:
      - name: psm-grpc-server
        image: grpc/csm-o11y-example-go-server:v1.69.0
        imagePullPolicy: Always
        args:
          - "--port=50051"
        ports:
          - containerPort: 50051
        env:
          - name: GRPC_XDS_BOOTSTRAP
            value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: CONTAINER_NAME
            value: psm-grpc-server
          - name: NAMESPACE_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
          - name: CSM_WORKLOAD_NAME
            value: psm-grpc-server
          - name: CSM_CANONICAL_SERVICE_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.labels['service.istio.io/canonical-name']
          - name: CSM_MESH_ID
            value: proj-PROJECT_NUMBER
          - name: OTEL_RESOURCE_ATTRIBUTES
            value: k8s.pod.name=\$(POD_NAME),k8s.namespace.name=\$(NAMESPACE_NAME),k8s.container.name=\$(CONTAINER_NAME)
        volumeMounts:
          - mountPath: /tmp/grpc-xds/
            name: grpc-td-conf
            readOnly: true
      initContainers:
        - name: grpc-td-init
          image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
          imagePullPolicy: Always
          args:
            - "--output=/tmp/bootstrap/td-grpc-bootstrap.json"
            - "--vpc-network-name=default"
            - "--xds-server-uri=trafficdirector.googleapis.com:443"
            - "--generate-mesh-id"
          volumeMounts:
            - mountPath: /tmp/bootstrap/
              name: grpc-td-conf
      volumes:
        - name: grpc-td-conf
          emptyDir:
            medium: Memory
EOF

Python

kubectl apply -f - <<EOF
---
apiVersion: v1
kind: Service
metadata:
  name: helloworld
  namespace: proxyless-example
spec:
  selector:
    app: psm-grpc-server
  ports:
  - port: 50051
    targetPort: 50051
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: psm-grpc-server
  namespace: proxyless-example
  labels:
    app: psm-grpc-server
spec:
  replicas: 2
  selector:
    matchLabels:
      app: psm-grpc-server
  template:
    metadata:
      labels:
        app: psm-grpc-server
        service.istio.io/canonical-name: deployment-psm-grpc-server
    spec:
      containers:
      - name: psm-grpc-server
        image: grpc/csm-o11y-example-python-server:v1.68.1
        imagePullPolicy: Always
        args:
          - "--port=50051"
        ports:
          - containerPort: 50051
        env:
          - name: GRPC_XDS_BOOTSTRAP
            value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: CONTAINER_NAME
            value: psm-grpc-server
          - name: NAMESPACE_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
          - name: CSM_WORKLOAD_NAME
            value: psm-grpc-server
          - name: CSM_CANONICAL_SERVICE_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.labels['service.istio.io/canonical-name']
          - name: CSM_MESH_ID
            value: proj-PROJECT_NUMBER
          - name: OTEL_RESOURCE_ATTRIBUTES
            value: k8s.pod.name=\$(POD_NAME),k8s.namespace.name=\$(NAMESPACE_NAME),k8s.container.name=\$(CONTAINER_NAME)
        volumeMounts:
          - mountPath: /tmp/grpc-xds/
            name: grpc-td-conf
            readOnly: true
      initContainers:
        - name: grpc-td-init
          image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
          imagePullPolicy: Always
          args:
            - "--output=/tmp/bootstrap/td-grpc-bootstrap.json"
            - "--vpc-network-name=default"
            - "--xds-server-uri=trafficdirector.googleapis.com:443"
            - "--generate-mesh-id"
          volumeMounts:
            - mountPath: /tmp/bootstrap/
              name: grpc-td-conf
      volumes:
        - name: grpc-td-conf
          emptyDir:
            medium: Memory
EOF

輸出內容類似如下

namespace/proxyless-example created
service/helloworld created
deployment.apps/psm-grpc-server created

自動

  1. 套用命名空間

    kubectl apply -f - <<EOF
    ---
    kind: Namespace
    apiVersion: v1
    metadata:
     name: proxyless-example
    EOF
    
  2. 執行下列指令,在 proxyless-example 命名空間中啟用 Proxyless Bootstrap Injector:

    kubectl label namespace proxyless-example mesh.cloud.google.com/csm-injection=proxyless
    
  3. 部署 gRPC 服務:

C++

kubectl apply -f - <<EOF
---
apiVersion: v1
kind: Service
metadata:
  name: helloworld
  namespace: proxyless-example
spec:
  selector:
    app: psm-grpc-server
  ports:
  - port: 50051
    targetPort: 50051
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: psm-grpc-server
  namespace: proxyless-example
  labels:
    app: psm-grpc-server
spec:
  replicas: 2
  selector:
    matchLabels:
      app: psm-grpc-server
  template:
    metadata:
      labels:
        app: psm-grpc-server
    spec:
      containers:
      - name: psm-grpc-server
        image: grpc/csm-o11y-example-cpp-server:v1.68.1
        imagePullPolicy: Always
        args:
          - "--port=50051"
        ports:
          - containerPort: 50051
EOF

Java

kubectl apply -f - <<EOF
---
apiVersion: v1
kind: Service
metadata:
  name: helloworld
  namespace: proxyless-example
spec:
  selector:
    app: psm-grpc-server
  ports:
  - port: 50051
    targetPort: 50051
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: psm-grpc-server
  namespace: proxyless-example
  labels:
    app: psm-grpc-server
spec:
  replicas: 2
  selector:
    matchLabels:
      app: psm-grpc-server
  template:
    metadata:
      labels:
        app: psm-grpc-server
    spec:
      containers:
      - name: psm-grpc-server
        image: grpc/csm-o11y-example-java-server:v1.68.2
        imagePullPolicy: Always
        args:
          - "50051"
          - "9464"
        ports:
          - containerPort: 50051
EOF

Go

kubectl apply -f - <<EOF
---
apiVersion: v1
kind: Service
metadata:
  name: helloworld
  namespace: proxyless-example
spec:
  selector:
    app: psm-grpc-server
  ports:
  - port: 50051
    targetPort: 50051
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: psm-grpc-server
  namespace: proxyless-example
  labels:
    app: psm-grpc-server
spec:
  replicas: 2
  selector:
    matchLabels:
      app: psm-grpc-server
  template:
    metadata:
      labels:
        app: psm-grpc-server
    spec:
      containers:
      - name: psm-grpc-server
        image: grpc/csm-o11y-example-go-server:v1.69.0
        imagePullPolicy: Always
        args:
          - "--port=50051"
        ports:
          - containerPort: 50051
EOF

Python

kubectl apply -f - <<EOF
---
apiVersion: v1
kind: Service
metadata:
  name: helloworld
  namespace: proxyless-example
spec:
  selector:
    app: psm-grpc-server
  ports:
  - port: 50051
    targetPort: 50051
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: psm-grpc-server
  namespace: proxyless-example
  labels:
    app: psm-grpc-server
spec:
  replicas: 2
  selector:
    matchLabels:
      app: psm-grpc-server
  template:
    metadata:
      labels:
        app: psm-grpc-server
    spec:
      containers:
      - name: psm-grpc-server
        image: grpc/csm-o11y-example-python-server:v1.68.1
        imagePullPolicy: Always
        args:
          - "--port=50051"
        ports:
          - containerPort: 50051
EOF

輸出內容類似如下

namespace/proxyless-example created
service/helloworld created
deployment.apps/psm-grpc-server created
  1. 確認 Pod 是否已建立:

    kubectl get pods -n proxyless-example
    

    輸出內容類似如下

    NAME                               READY   STATUS    RESTARTS   AGE
    psm-grpc-server-65966bf76d-2wwxz   1/1     Running   0          13s
    psm-grpc-server-65966bf76d-nbxd2   1/1     Running   0          13s
    

    請等待所有 Pod 都準備就緒,並顯示 Status 運作狀態,再繼續操作。

  2. 部署 HTTPRoute:

    kubectl apply -f - <<EOF
    apiVersion: gateway.networking.k8s.io/v1beta1
    kind: HTTPRoute
    metadata:
      name: app1
      namespace: proxyless-example
    spec:
      parentRefs:
      - name: helloworld
        namespace: proxyless-example
        kind: Service
        group: ""
      rules:
      - backendRefs:
        - name: helloworld
          port: 50051
    EOF
    

    這項指令會建立名為 app1 的 HTTPRoute,並將所有 RPC 傳送至 helloworld 服務。

    請注意,parentRef 服務也是 helloworld,這表示 HTTPRoute 會附加至此服務,並處理所有傳送至此服務的 RPC。在無 Proxy gRPC 的情況下,這表示任何用戶端在 gRPC 管道上傳送 RPC 至目標 xds:///helloworld.proxyless-example.svc.cluster.local:50051

  3. 確認已建立新的 app1 HTTPRoute:

    kubectl get httproute -n proxyless-example
    

    輸出內容類似如下

    NAME   HOSTNAMES   AGE
    app1               72s
    

設定無 Proxy gRPC 用戶端

本節說明如何使用 gRPC 用戶端,確認 Cloud Service Mesh 是否正確地在網格中轉送流量。

就像設定服務一樣,您可以透過兩種方式設定用戶端:

方法 1:手動設定

這種做法需要為用戶端手動設定必要元件,以便複製手動服務設定。

方法 2:使用 Proxyless Bootstrap Injector 自動執行

或者,您也可以使用自動插入器來簡化用戶端設定程序。這麼做可簡化設定,並減少手動介入的情形。這可透過在命名空間上套用標籤來達成。

這兩種選項都會為客戶提供必要的功能。請選擇最符合需求和偏好的方法。

手動

執行 gRPC 用戶端,並指示其使用 HTTPRoute 指定的轉送設定:

C++

kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: psm-grpc-client
  namespace: proxyless-example
  labels:
    app: psm-grpc-client
spec:
  replicas: 1
  selector:
    matchLabels:
      app: psm-grpc-client
  template:
    metadata:
      labels:
        app: psm-grpc-client
        service.istio.io/canonical-name: deployment-psm-grpc-client
    spec:
      containers:
      - name: psm-grpc-client
        image: grpc/csm-o11y-example-cpp-client:v1.68.1
        imagePullPolicy: Always
        args:
          - "--target=xds:///helloworld.proxyless-example.svc.cluster.local:50051"
        env:
          - name: GRPC_XDS_BOOTSTRAP
            value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
          - name: CSM_WORKLOAD_NAME
            value: psm-grpc-client
          - name: CSM_CANONICAL_SERVICE_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.labels['service.istio.io/canonical-name']
          - name: CSM_MESH_ID
            value: proj-PROJECT_NUMBER
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: NAMESPACE_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
          - name: CONTAINER_NAME
            value: psm-grpc-client
          - name: OTEL_RESOURCE_ATTRIBUTES
            value: k8s.pod.name=\$(POD_NAME),k8s.namespace.name=\$(NAMESPACE_NAME),k8s.container.name=\$(CONTAINER_NAME)
        volumeMounts:
          - mountPath: /tmp/grpc-xds/
            name: grpc-td-conf
            readOnly: true
      initContainers:
        - name: grpc-td-init
          image:  gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
          imagePullPolicy: Always
          args:
            - "--output=/tmp/bootstrap/td-grpc-bootstrap.json"
            - "--vpc-network-name=default"
            - "--xds-server-uri=trafficdirector.googleapis.com:443"
            - "--generate-mesh-id"
          volumeMounts:
            - mountPath: /tmp/bootstrap/
              name: grpc-td-conf
      volumes:
        - name: grpc-td-conf
          emptyDir:
            medium: Memory

EOF

Java

kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: psm-grpc-client
  namespace: proxyless-example
  labels:
    app: psm-grpc-client
spec:
  replicas: 1
  selector:
    matchLabels:
      app: psm-grpc-client
  template:
    metadata:
      labels:
        app: psm-grpc-client
        service.istio.io/canonical-name: deployment-psm-grpc-client
    spec:
      containers:
      - name: psm-grpc-client
        image: grpc/csm-o11y-example-java-client:v1.68.2
        imagePullPolicy: Always
        args:
          - "world"
          - "xds:///helloworld.proxyless-example.svc.cluster.local:50051"
          - "9464"
        env:
          - name: GRPC_XDS_BOOTSTRAP
            value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
          - name: CSM_WORKLOAD_NAME
            value: psm-grpc-client
          - name: CSM_CANONICAL_SERVICE_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.labels['service.istio.io/canonical-name']
          - name: CSM_MESH_ID
            value: proj-PROJECT_NUMBER
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: NAMESPACE_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
          - name: CONTAINER_NAME
            value: psm-grpc-client
          - name: OTEL_RESOURCE_ATTRIBUTES
            value: k8s.pod.name=\$(POD_NAME),k8s.namespace.name=\$(NAMESPACE_NAME),k8s.container.name=\$(CONTAINER_NAME)
        volumeMounts:
          - mountPath: /tmp/grpc-xds/
            name: grpc-td-conf
            readOnly: true
      initContainers:
        - name: grpc-td-init
          image:  gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
          imagePullPolicy: Always
          args:
            - "--output=/tmp/bootstrap/td-grpc-bootstrap.json"
            - "--vpc-network-name=default"
            - "--xds-server-uri=trafficdirector.googleapis.com:443"
            - "--generate-mesh-id"
          volumeMounts:
            - mountPath: /tmp/bootstrap/
              name: grpc-td-conf
      volumes:
        - name: grpc-td-conf
          emptyDir:
            medium: Memory

EOF

Go

kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: psm-grpc-client
  namespace: proxyless-example
  labels:
    app: psm-grpc-client
spec:
  replicas: 1
  selector:
    matchLabels:
      app: psm-grpc-client
  template:
    metadata:
      labels:
        app: psm-grpc-client
        service.istio.io/canonical-name: deployment-psm-grpc-client
    spec:
      containers:
      - name: psm-grpc-client
        image: grpc/csm-o11y-example-go-client:v1.69.4
        imagePullPolicy: Always
        args:
          - "--target=xds:///helloworld.proxyless-example.svc.cluster.local:50051"
        env:
          - name: GRPC_XDS_BOOTSTRAP
            value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
          - name: CSM_WORKLOAD_NAME
            value: psm-grpc-client
          - name: CSM_CANONICAL_SERVICE_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.labels['service.istio.io/canonical-name']
          - name: CSM_MESH_ID
            value: proj-PROJECT_NUMBER
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: NAMESPACE_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
          - name: CONTAINER_NAME
            value: psm-grpc-client
          - name: OTEL_RESOURCE_ATTRIBUTES
            value: k8s.pod.name=\$(POD_NAME),k8s.namespace.name=\$(NAMESPACE_NAME),k8s.container.name=\$(CONTAINER_NAME)
        volumeMounts:
          - mountPath: /tmp/grpc-xds/
            name: grpc-td-conf
            readOnly: true
      initContainers:
        - name: grpc-td-init
          image:  gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
          imagePullPolicy: Always
          args:
            - "--output=/tmp/bootstrap/td-grpc-bootstrap.json"
            - "--vpc-network-name=default"
            - "--xds-server-uri=trafficdirector.googleapis.com:443"
            - "--generate-mesh-id"
          volumeMounts:
            - mountPath: /tmp/bootstrap/
              name: grpc-td-conf
      volumes:
        - name: grpc-td-conf
          emptyDir:
            medium: Memory

EOF

Python

kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: psm-grpc-client
  namespace: proxyless-example
  labels:
    app: psm-grpc-client
spec:
  replicas: 1
  selector:
    matchLabels:
      app: psm-grpc-client
  template:
    metadata:
      labels:
        app: psm-grpc-client
        service.istio.io/canonical-name: deployment-psm-grpc-client
    spec:
      containers:
      - name: psm-grpc-client
        image: grpc/csm-o11y-example-python-client:v1.68.1
        imagePullPolicy: Always
        args:
          - "--target=xds:///helloworld.proxyless-example.svc.cluster.local:50051"
        env:
          - name: GRPC_XDS_BOOTSTRAP
            value: "/tmp/grpc-xds/td-grpc-bootstrap.json"
          - name: CSM_WORKLOAD_NAME
            value: psm-grpc-client
          - name: CSM_CANONICAL_SERVICE_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.labels['service.istio.io/canonical-name']
          - name: CSM_MESH_ID
            value: proj-PROJECT_NUMBER
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: NAMESPACE_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
          - name: CONTAINER_NAME
            value: psm-grpc-client
          - name: OTEL_RESOURCE_ATTRIBUTES
            value: k8s.pod.name=\$(POD_NAME),k8s.namespace.name=\$(NAMESPACE_NAME),k8s.container.name=\$(CONTAINER_NAME)
        volumeMounts:
          - mountPath: /tmp/grpc-xds/
            name: grpc-td-conf
            readOnly: true
      initContainers:
        - name: grpc-td-init
          image:  gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
          imagePullPolicy: Always
          args:
            - "--output=/tmp/bootstrap/td-grpc-bootstrap.json"
            - "--vpc-network-name=default"
            - "--xds-server-uri=trafficdirector.googleapis.com:443"
            - "--generate-mesh-id"
          volumeMounts:
            - mountPath: /tmp/bootstrap/
              name: grpc-td-conf
      volumes:
        - name: grpc-td-conf
          emptyDir:
            medium: Memory

EOF

自動

執行 gRPC 用戶端,並指示其使用 HTTPRoute 指定的轉送設定:

C++

kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: psm-grpc-client
  namespace: proxyless-example
  labels:
    app: psm-grpc-client
spec:
  replicas: 1
  selector:
    matchLabels:
      app: psm-grpc-client
  template:
    metadata:
      labels:
        app: psm-grpc-client
    spec:
      containers:
      - name: psm-grpc-client
        image: grpc/csm-o11y-example-cpp-client:v1.68.1
        imagePullPolicy: Always
        args:
          - "--target=xds:///helloworld.proxyless-example.svc.cluster.local:50051"
EOF

Java

kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: psm-grpc-client
  namespace: proxyless-example
  labels:
    app: psm-grpc-client
spec:
  replicas: 1
  selector:
    matchLabels:
      app: psm-grpc-client
  template:
    metadata:
      labels:
        app: psm-grpc-client
    spec:
      containers:
      - name: psm-grpc-client
        image: grpc/csm-o11y-example-java-client:v1.68.2
        imagePullPolicy: Always
        args:
          - "world"
          - "xds:///helloworld.proxyless-example.svc.cluster.local:50051"
          - "9464"
EOF

Go

kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: psm-grpc-client
  namespace: proxyless-example
  labels:
    app: psm-grpc-client
spec:
  replicas: 1
  selector:
    matchLabels:
      app: psm-grpc-client
  template:
    metadata:
      labels:
        app: psm-grpc-client
    spec:
      containers:
      - name: psm-grpc-client
        image: grpc/csm-o11y-example-go-client:v1.69.4
        imagePullPolicy: Always
        args:
          - "--target=xds:///helloworld.proxyless-example.svc.cluster.local:50051"
EOF

Python

kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: psm-grpc-client
  namespace: proxyless-example
  labels:
    app: psm-grpc-client
spec:
  replicas: 1
  selector:
    matchLabels:
      app: psm-grpc-client
  template:
    metadata:
      labels:
        app: psm-grpc-client
    spec:
      containers:
      - name: psm-grpc-client
        image: grpc/csm-o11y-example-python-client:v1.68.1
        imagePullPolicy: Always
        args:
          - "--target=xds:///helloworld.proxyless-example.svc.cluster.local:50051"
EOF

輸出內容類似如下

deployment.apps/psm-grpc-client created

如要確認用戶端是否能夠連上服務,請查看用戶端的記錄:

kubectl logs -n proxyless-example $(kubectl get po -n proxyless-example | grep psm-grpc-client | awk '{print $1;}') -f

輸出結果會與下列內容類似:

Defaulted container "psm-grpc-client" out of: psm-grpc-client, grpc-td-init (init)
Greeter received: Hello from psm-grpc-server-xxxxxxx-xxxx world

設定 Google Cloud Managed Service for Prometheus (選用)

您可以部署 Google Cloud Managed Service for Prometheus PodMonitoring 資源,將指標匯出至 Cloud Monitoring。

  • 如為伺服器,請執行下列指令:

    kubectl apply -f - <<EOF
    apiVersion: monitoring.googleapis.com/v1
    kind: PodMonitoring
    metadata:
      name: psm-grpc-server-gmp
      namespace: proxyless-example
    spec:
      selector:
        matchLabels:
          app: psm-grpc-server
      endpoints:
      - port: 9464
        interval: 10s
    EOF
    
  • 如要套用至用戶端,請執行下列指令:

    kubectl apply -f - <<EOF
    apiVersion: monitoring.googleapis.com/v1
    kind: PodMonitoring
    metadata:
      name: psm-grpc-client-gmp
      namespace: proxyless-example
    spec:
      selector:
        matchLabels:
          app: psm-grpc-client
      endpoints:
      - port: 9464
        interval: 10s
    EOF
    

    部署 PodMonitoring 資源後,系統會每 10 秒擷取每個相符 Pod 的 localhost:9464/metrics,並將結果匯出至 Cloud Monitoring。

如要在 Cloud Monitoring 中查看指標,請執行下列步驟:

您可以前往Google Cloud 控制台的「Metrics Explorer」部分,選取「Prometheus Target」>「Grpc」,即可找到指標。

前往 Metrics Explorer

您可以在 Google Cloud 控制台的「Service Mesh」部分觀察已部署的工作負載和服務。

前往服務網格

排解 Cloud Service Mesh 觀測能力問題

本節說明如何排解常見問題。

系統未匯出 / 顯示指標

請確認所有相關二進位檔 (包括用戶端和伺服器) 都已設定可觀察性

如果您使用 Prometheus 匯出器,請確認 Prometheus 匯出器的網址已如預期設定。

請確認已為 gRPC 管道啟用 Cloud Service Mesh。管道應具有 xds:/// 的目標。Cloud Service Mesh 一律會啟用 gRPC 伺服器。

沒有匯出的指標 / 指標上的屬性值顯示為不明

Cloud Service Mesh 監控功能會透過環境標籤判斷網格拓撲資訊。請確認用戶端和服務的 Pod 或服務規格都指定了所有標籤,如範例所述。

  1. 說明 psm-grpc-server 部署作業:

    kubectl describe Deployment psm-grpc-server -n proxyless-example \
    | grep "psm-grpc-server:" -A 12
    

    輸出結果會與下列內容類似:

    psm-grpc-server:
    Image:      grpc/csm-example-server:2024-02-13
    Port:       50051/TCP
    Host Port:  0/TCP
    Args:
      --port=50051
    Environment:
      GRPC_XDS_BOOTSTRAP:          /tmp/grpc-xds/td-grpc-bootstrap.json
      POD_NAME:                     (v1:metadata.name)
      NAMESPACE_NAME:               (v1:metadata.namespace)
      CSM_WORKLOAD_NAME:           psm-grpc-server
      OTEL_RESOURCE_ATTRIBUTES:    k8s.pod.name=$(POD_NAME),k8s.namespace.name=$(NAMESPACE_NAME),k8s.container.name=$(CONTAINER_NAME)
    
  2. 說明 psm-grpc-client 部署作業:

    kubectl describe Deployment psm-grpc-client -n proxyless-example \
    | grep "psm-grpc-client:" -A 12
    

    輸出結果會與下列內容類似:

    psm-grpc-client:
    Image:      grpc/csm-example-client:2024-02-13
    Port:       <none>
    Host Port:  <none>
    Args:
      --target=xds:///helloworld.proxyless-example.svc.cluster.local:50051
    Environment:
      GRPC_XDS_BOOTSTRAP:          /tmp/grpc-xds/td-grpc-bootstrap.json
      CSM_WORKLOAD_NAME:           test-workload-name
      POD_NAME:                     (v1:metadata.name)
      NAMESPACE_NAME:               (v1:metadata.namespace)
      CONTAINER_NAME:              psm-grpc-client