通过ASM入口网关访问网格内gRPC服务

您可以通过ASM入口网关安全地访问网格内的gRPC服务,实现对gRPC服务的精确访问控制,提升服务治理能力,保障服务间通信的安全性。本文介绍如何通过入口网关访问网格内gRPC服务,并在gRPC的两个版本之间进行流量切换。

前提条件

步骤一:部署示例应用

部署名为istio-grpc-server-v1istio-grpc-server-v2的示例应用。

  1. 创建app.yaml。

    展开查看YAML

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: grpc-helloworld-py-v1
      labels:
        app: grpc-helloworld-py
        version: v1
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: grpc-helloworld-py
          version: v1
      template:
        metadata:
          labels:
            app: grpc-helloworld-py
            version: v1
        spec:
          containers:
            - name: grpc-helloworld-py
              image: registry.cn-hangzhou.aliyuncs.com/aliacs-app-catalog/istio-grpc-server:grpc-helloworld-py-v1.0
              imagePullPolicy: Always
              env:
                - name: podname
                  valueFrom:
                    fieldRef:
                      apiVersion: v1
                      fieldPath: metadata.name
              ports:
                - containerPort: 50051
                  name: grpc-port
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: grpc-helloworld-py-v2
      labels:
        app: grpc-helloworld-py
        version: v2
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: grpc-helloworld-py
          version: v2
      template:
        metadata:
          labels:
            app: grpc-helloworld-py
            version: v2
        spec:
          containers:
            - name: grpc-helloworld-py
              image: registry.cn-hangzhou.aliyuncs.com/aliacs-app-catalog/istio-grpc-server:grpc-helloworld-py-v1.0
              imagePullPolicy: Always
              env:
                - name: podname
                  valueFrom:
                    fieldRef:
                      apiVersion: v1
                      fieldPath: metadata.name
              ports:
                - containerPort: 50051
                  name: grpc-port
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: grpc-helloworld-py
      labels:
        app: grpc-helloworld-py
    spec:
      ports:
        - port: 50051
          name: grpc-port
      selector:
        app: grpc-helloworld-py
  2. 部署应用。

    kubectl apply -f app.yaml

步骤二:设置路由规则

创建网关规则、虚拟服务和目标规则,将流量全部指向istio-grpc-server-v1。

  1. 创建rules.yaml。

    apiVersion: networking.istio.io/v1beta1
    kind: Gateway
    metadata:
      name: grpc-gateway
    spec:
      selector:
        istio: ingressgateway
      servers:
      - port:
          number: 8080
          name: grpc
          protocol: GRPC
        hosts:
        - "*"
    ---
    apiVersion: networking.istio.io/v1beta1
    kind: DestinationRule
    metadata:
      name: dr-istio-grpc-server
    spec:
      host: grpc-helloworld-py
      trafficPolicy:
        loadBalancer:
          simple: ROUND_ROBIN
      subsets:
        - name: v1
          labels:
            version: "v1"
        - name: v2
          labels:
            version: "v2"    
    ---
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: grpc-vs
    spec:
      hosts:
      - "*"
      gateways:
      - grpc-gateway
      http:
        - match:
            - port: 8080
          route:
            - destination:
                host: grpc-helloworld-py
                port:
                  number: 50051
                subset: v1
              weight: 100
            - destination:
                host: grpc-helloworld-py
                port:
                  number: 50051
                subset: v2
              weight: 0        
  2. 部署规则。

    kubectl apply -f rules.yaml

步骤三:部署新入口网关或复用已有入口网关

新建入口网关

创建入口网关,在配置端口映射时添加8080端口。

已有入口网关添加8080端口

  1. 登录ASM控制台,在左侧导航栏,选择服务网格 > 网格管理

  2. 网格管理页面,单击目标实例名称,然后在左侧导航栏,选择ASM网关 > 入口网关

  3. 入口网关页面,单击目标网关名称,在网关概览页面的基本选项区域,单击端口配置右侧的Dingtalk_20230104170049.jpg图标,在端口映射对话框,单击添加端口,设置协议TCP服务端口8080,然后单击确认

步骤四:运行gRPC客户端

  1. 安装grpcurl命令行工具,运行以下命令:

    grpcurl -d '{"name": "Jack"}' -plaintext {入口网关IP地址}:8080 helloworld.Greeter/SayHello
  2. 返回以下结果,可以看到所有的请求都指向了v1。

     "message": "Hello, Jack! I'm from grpc-helloworld-py-v1-79b5dc9654-cg4dq!"
     "message": "Hello, Jack! I'm from grpc-helloworld-py-v1-79b5dc9654-cg4dq!"
     "message": "Hello, Jack! I'm from grpc-helloworld-py-v1-79b5dc9654-cg4dq!"
     "message": "Hello, Jack! I'm from grpc-helloworld-py-v1-79b5dc9654-cg4dq!"
     "message": "Hello, Jack! I'm from grpc-helloworld-py-v1-79b5dc9654-cg4dq!"     

步骤五:按比例将流量路由到v2

更新虚拟服务,将40%的流量指向v2,其余60%的流量仍然指向v1。

  1. 编辑虚拟服务。

    kubectl edit VirtualService grpc-vs

    按照以下内容修改route部分并保存。

    ....
          route:
            - destination:
                host: grpc-helloworld-py
                port:
                  number: 50051
                subset: v1
              weight: 60
            - destination:
                host: grpc-helloworld-py
                port:
                  number: 50051
                subset: v2
              weight: 40
  2. 继续使用grpcurl执行以下命令,访问网格内的gRPC服务。

    grpcurl -d '{"name": "Jack"}' -plaintext {入口网关IP地址}:8080 helloworld.Greeter/SayHello

    返回以下结果,可以看到40%的流量指向了v2。

    说明

    您的测试结果不一定总是100次中有40次指向v2,但从总体比例来看,将接近40%。

    "message": "Hello, Jack! I'm from grpc-helloworld-py-v1-79b5dc9654-cg4dq!"
    "message": "Hello, Jack! I'm from grpc-helloworld-py-v1-79b5dc9654-cg4dq!"
    "message": "Hello, Jack! I'm from grpc-helloworld-py-v2-7f56b49b7f-9vvr7!"
    "message": "Hello, Jack! I'm from grpc-helloworld-py-v1-79b5dc9654-cg4dq!"
    "message": "Hello, Jack! I'm from grpc-helloworld-py-v2-7f56b49b7f-9vvr7!"
    "message": "Hello, Jack! I'm from grpc-helloworld-py-v1-79b5dc9654-cg4dq!"
    "message": "Hello, Jack! I'm from grpc-helloworld-py-v2-7f56b49b7f-9vvr7!"
    "message": "Hello, Jack! I'm from grpc-helloworld-py-v1-79b5dc9654-cg4dq!"
    "message": "Hello, Jack! I'm from grpc-helloworld-py-v2-7f56b49b7f-9vvr7!"
    "message": "Hello, Jack! I'm from grpc-helloworld-py-v1-79b5dc9654-cg4dq!"