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

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

前提条件

步骤一:部署示例应用

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

  1. 登录容器服务管理控制台,在左侧导航栏选择集群

  2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择工作负载 > 无状态

  3. 无状态页面上方,选择目标命名空间,然后在右上角单击使用YAML创建资源

    说明

    当前选中的命名空间应当已标注自动注入Sidecar,即包含istio-injection=enabled标签。具体操作,请参见启用自动注入

  4. 创建页面,选择自定义示例模板,配置以下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

步骤二:设置服务网格ASM的路由规则

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

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

  2. 网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理

  3. 创建网关规则

    1. 在网格详情页面左侧导航栏,选择ASM网关 > 网关规则,然后在右侧页面,单击使用YAML创建

    2. 创建页面,设置命名空间default,选择任意场景模版,配置以下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:
          - "*"
  4. 创建目标规则

    1. 在网格详情页面左侧导航栏,选择流量管理中心 > 目标规则,然后在右侧页面,单击使用YAML创建

    2. 创建页面,设置命名空间default,选择任意场景模版,配置以下YAML,然后单击创建

      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"    
  5. 创建虚拟服务

    1. 在网格详情页面左侧导航栏,选择流量管理中心 > 虚拟服务,然后在右侧页面,单击使用YAML创建

    2. 创建页面,设置命名空间default,选择任意场景模版,配置以下YAML,然后单击创建

      展开查看YAML

      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        

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

在入口网关中,如果不存在8080端口,需要添加8080端口。

新建入口网关

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

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

  3. 入口网关页面,单击创建,配置相关信息,然后单击创建

    部分配置项说明如下。关于配置项的更多信息,请参见入口网关配置项说明

    配置项

    说明

    部署集群

    选择要部署入口网关的集群。

    负载均衡CLB类型

    此处指定负载均衡的类型为公网访问

    负载均衡

    选择负载均衡。

    • 使用已有负载均衡:从已有负载均衡列表中选择。

    • 新建负载均衡CLB:单击新建负载均衡CLB,从下拉列表中选择所需的负载均衡规格。

    说明

    建议您为每个Kubernetes服务分配一个CLB。如果多个Kubernetes服务复用同一个CLB,存在以下风险和限制:

    • 使用已有的CLB会强制覆盖已有监听,可能会导致您的应用不可访问。

    • Kubernetes通过Service创建的CLB不能复用,只能复用您手动在控制台(或调用OpenAPI)创建的CLB。

    • 复用同一个CLB的多个Service不能有相同的前端监听端口,否则会造成端口冲突。

    • 复用CLB时,监听的名字以及虚拟服务器组的名字被Kubernetes作为唯一标识符。请勿修改监听和虚拟服务器组的名字。

    • 不支持跨集群复用CLB。

    端口映射

    设置协议TCP服务端口8080

在已有入口网关添加8080端口

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

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

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

步骤四:运行gRPC客户端

  1. grpcurl是一个命令行工具,用于与gRPC服务进行交互。它提供了一种简单的方式来测试和调试gRPC服务,以及查看服务的定义和元数据。具体如何下载安装可以参考https://github.com/fullstorydev/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. 登录ASM控制台,在左侧导航栏,选择服务网格 > 网格管理

  2. 网格管理页面,单击目标实例名称,然后在左侧导航栏,选择流量管理中心 > 虚拟服务

  3. 虚拟服务页面,在grpc-vs虚拟服务右侧的操作列下,单击查看YAML

  4. 编辑对话框,更新以下YAML内容,单击确定

    ....
          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
  5. 继续使用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!"