הגדרה של רשת שירותים של gRPC ללא proxy ב-GKE

בדף הזה מוסבר איך פורסים שרת ולקוח לדוגמה של gRPC בלי שרת Proxy ב-Cloud Service Mesh.

דרישות מוקדמות

כנקודת מוצא, במדריך הזה אנחנו יוצאים מנקודת הנחה שכבר:

דרישות

בקטע הזה מפורטות הדרישות לשירותים נתמכים:

  • ‫gRPC C++‎ – גרסה 1.68.1 ואילך
  • ‫gRPC Java – גרסה 1.68.2 ואילך
  • ‫gRPC Go – גרסה 1.68.0 ואילך
  • ‫gRPC Python – גרסה 1.68.1 ואילך

הגדרת שירות gRPC בלי שרת Proxy

במדריך הזה מפורטות שתי שיטות להגדרת שירות gRPC בלי שרת Proxy ב-Service mesh:

שיטה 1: הגדרה ידנית

בשיטה הזו צריך להגדיר ידנית את הרכיבים הנדרשים לשירות gRPC בלי שרת Proxy.

  • InitContainer: משתמשים ב-initContainer במפרט של ה-pod כדי להפעיל את מחולל ה-Bootstrap של gRPC ב-Traffic Director. הגנרטור הזה יוצר את ההגדרה הנדרשת לשירות שלכם.
  • Volume Mount: הרכבת נפח שמכיל את התצורה שנוצרה מ-initContainer. כך תוכלו לוודא שלאפליקציה שלכם יש גישה להגדרות הנדרשות.
  • משתני סביבה: כוללים את משתני הסביבה המתאימים כדי לאפשר פליטה של מדדי CSM Observability מהאפליקציה. המדדים האלה מספקים תובנות חשובות לגבי הביצועים של השירות.

שיטה 2: אוטומטית באמצעות Proxyless Bootstrap Injector

במקום להגדיר ידנית את שירות ה-gRPC ללא שרת proxy, אפשר לבחור בגישה פשוטה יותר באמצעות Proxyless Bootstrap Injector.

התכונה הזו מאפשרת להגדיר את השירות באופן אוטומטי, וכך לפרוס אותו בקלות רבה יותר. כדי להפעיל אותו, מוסיפים את התווית mesh.cloud.google.com/csm-injection=proxyless למרחב השמות.

אם מוסיפים את התווית הזו למרחב השמות, ה-injector מטפל בכל ההגדרות הנדרשות, וכך חוסך לכם זמן ומאמץ.

אם אתם צריכים שליטה פרטנית יותר, אתם יכולים גם להחיל את התווית הזו ישירות על פודים בודדים. כך אפשר לבטל את ההגדרה ברמת מרחב השמות ולהתאים אישית את התנהגות ההחדרה על בסיס כל pod.

אם תפעלו לפי אחת מהשיטות האלה, תוכלו להגדיר בהצלחה שירות gRPC בלי שרת Proxy ב-Service mesh.

גלילה ידנית

  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.4
        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 Bootstrap Injector במרחב השמות proxyless-example:

    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.4
        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. מוודאים שה-Pods נוצרו:

    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
    

    לפני שממשיכים, צריך להמתין עד שכל ה-Pods יהיו מוכנים ויופיעו עם הסטטוס Status Running.

  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
    

    הפקודה הזו יוצרת HTTPRoute בשם app1 ושולחת את כל ה-RPC לשירות helloworld.

    שימו לב שהשירות parentRef הוא גם helloworld, כלומר HTTPRoute שלנו מצורף לשירות הזה ויעבד את כל ה-RPC שמיועדים לשירות הזה. במקרה של gRPC ללא proxy, הכוונה היא לכל לקוח ששולח RPCs בערוץ gRPC ליעד xds:///helloworld.proxyless-example.svc.cluster.local:50051.

  3. מוודאים שנוצר HTTPRoute חדש בשם app1:

    kubectl get httproute -n proxyless-example
    

    הפלט אמור להיראות כך:

    NAME   HOSTNAMES   AGE
    app1               72s
    

הגדרת לקוח gRPC ללא שרת proxy

בקטע הזה מוסבר איך להשתמש בלקוח 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 ל-Prometheus (אופציונלי)

אפשר לפרוס את המשאב השירות המנוהל של Google Cloud ל-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, כל localhost:9464/metrics של פוד תואם ייסרק כל 10 שניות והתוצאות ייובאו ל-Cloud Monitoring.

כדי לראות את המדדים ב-Cloud Monitoring:

אפשר לעבור לקטע Metrics Explorer במסוףGoogle Cloud , לבחור באפשרות Prometheus Target > Grpc כדי למצוא את המדדים.

לדף Metrics Explorer

אפשר לראות את עומסי העבודה והשירותים שנפרסו בקטע Service Mesh במסוף. Google Cloud

כניסה אל Service Mesh

פתרון בעיות בניראות (observability) של Cloud Service Mesh

בקטע הזה מוסבר איך לפתור בעיות נפוצות.

המדדים לא מיוצאים או מוצגים

מוודאים שכל הקבצים הבינאריים הרלוונטיים (גם בצד הלקוח וגם בצד השרת) מוגדרים עם יכולת תצפית.

אם אתם משתמשים ב-Prometheus exporter, ודאו שכתובת ה-URL של Prometheus exporter מוגדרת כמו שצריך.

מוודאים שהערוצים של gRPC מופעלים ב-Cloud Service Mesh. היעד של הערוצים צריך להיות בפורמט xds:///. שרתי gRPC תמיד מופעלים ב-Cloud Service Mesh.

לא מיוצאים מדדים / ערך מאפיין במדד מופיע כלא ידוע

התכונה Cloud Service Mesh Observability קובעת את המידע הטופולוגי של הרשת באמצעות תוויות סביבה. מוודאים שבמפרט של ה-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