基于云原生网关实现gRPC服务的路由转发

gRPC使用HTTP/2协议,支持双向流、头部压缩和多路复用等特性,从而提高了网络传输的效率。本文介绍如何在容器服务 Kubernetes 版集群部署gRPC应用,并使用云原生网关实现gRPC服务的路由转发。

前提条件

步骤一:使用容器服务部署gRPC应用

应用部署的具体操作,请参见创建无状态工作负载Deployment

在本示例中,使用容器服务K8s原生的服务发现方式,即通过声明式Service API资源将后端服务注册到CoreDNS。本示例中使用grpcbin应用作为后端服务示例,该应用提供了多个gRPC服务的实现。在容器服务ACK中应用如下资源。

说明

gRPC服务在Kubernetes service中port字段下的name必须包含grpc。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: grpcbin
spec:
  replicas: 1
  selector:
    matchLabels:
      app: grpcbin
  template:
    metadata:
      labels:
        app: grpcbin
    spec:
      serviceAccountName: grpcbin
      containers:
      - image: docker.io/moul/grpcbin
        imagePullPolicy: IfNotPresent
        name: grpcbin
        ports:
        - containerPort: 9000
        - containerPort: 9001
        resources:
            requests:
              cpu: '1'
              memory: 2Gi
            limit:
              cpu: '1'
              memory: 2Gi
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: grpcbin
---
apiVersion: v1
kind: Service
metadata:
  name: grpcbin-grpc
  labels:
    app: grpcbin
spec:
  ports:
  - name: grpc
    port: 9000
    targetPort: 9000
  selector:
    app: grpcbin

以下代码展示该gRPC服务的proto定义。

syntax = "proto3";

package grpcbin;

service GRPCBin {
  rpc Index(EmptyMessage) returns (IndexReply) {}
  // 无参数调用的方法,调用后回返回一个空响应
  rpc Empty(EmptyMessage) returns (EmptyMessage) {}
  // 响应会返回请求的参数
  rpc DummyUnary(DummyMessage) returns (DummyMessage) {}
  // 响应为流式的调用,会分10次响应消息
  rpc DummyServerStream(DummyMessage) returns (stream DummyMessage) {}
  // 请求为流式的调用,会接受10次请求并返回最后一次的body
  rpc DummyClientStream(stream DummyMessage) returns (DummyMessage) {}
  // 请求响应都为流式的方法
  rpc DummyBidirectionalStreamStream(stream DummyMessage) returns (stream DummyMessage) {}
  // 该方法会返回指定的grpc错误
  rpc SpecificError(SpecificErrorRequest) returns (EmptyMessage) {}
  // 该方法调用会随机返回一个错误
  rpc RandomError(EmptyMessage) returns (EmptyMessage) {}
  // 该方法调用会返回header
  rpc HeadersUnary(EmptyMessage) returns (HeadersMessage) {}
  // 该方法调用不会返回响应
  rpc NoResponseUnary(EmptyMessage) returns (EmptyMessage) {}
}

message HeadersMessage {
  message Values {
    repeated string values = 1;
  }
  map<string, Values> Metadata = 1;
}

message SpecificErrorRequest {
  uint32 code = 1;
  string reason = 2;
}

message EmptyMessage {}

message DummyMessage {
  message Sub {
    string f_string = 1;
  }
  enum Enum {
    ENUM_0 = 0;
    ENUM_1 = 1;
    ENUM_2 = 2;
  }
  string f_string = 1;
  repeated string f_strings = 2;
  int32 f_int32 = 3;
  repeated int32 f_int32s = 4;
  Enum f_enum = 5;
  repeated Enum f_enums = 6;
  Sub f_sub = 7;
  repeated Sub f_subs = 8;
  bool f_bool = 9;
  repeated bool f_bools = 10;
  int64 f_int64 = 11;
  repeated int64 f_int64s= 12;
  bytes f_bytes = 13;
  repeated bytes f_bytess = 14;
  float f_float = 15;
  repeated float f_floats = 16;
}

message IndexReply {
  message Endpoint {
    string path = 1;
    string description = 2;
  }
  string description = 1;
  repeated Endpoint endpoints = 2;
}

gRPC服务底层基于HTTP/2协议,其路径格式为{包名}.{服务名}/{方法名}。基于此,MSE云原生网关可以在Path字段中实现对gRPC协议的路由。例如,如果使用gRPC访问grpcbin的Index方法,在协议中,该Path字段值为grpcbin.GRPCBin/Index。

步骤二:使用云原生网关作为gRPC的路由分发

添加ACK集群作为网关的服务来源并添加grpcbin服务。

添加服务来源

  1. 登录MSE网关管理控制台,并在顶部菜单栏选择地域。

  2. 在左侧导航栏,选择云原生网关 > 网关列表,单击目标网关名称。

  3. 在左侧导航栏,选择路由管理,然后选择来源页签。

  4. 单击创建来源。在创建来源面板,服务来源选择容器服务,配置相关参数,然后单击确定

    配置项

    说明

    ACK/ACK Serverless 集群

    选择后端服务所在的集群。

    说明

    您在创建网关时需要选择和后端集群相同的VPC,那么服务来源添加时会自动获取该VPC下的集群。

    监听K8s Ingress

    • 开启监听Ingress配置后,云原生网关会自动监听Ingress资源的变化,并使Ingress资源中域名、路由的相关配置生效。

    • 关闭监听Ingress配置后,云原生网关会放弃监听Ingress资源,并失效之前已监听的Ingress资源中的域名、路由相关配置,请您谨慎操作。

    重要

    通过管控手动配置的域名、路由的相关配置,其优先级高于Ingress资源。

    IngressClass

    监听关联指定IngressClass的Ingress资源。

    • 当配置成空值时,监听集群中所有的Ingress资源。

    • 当配置成具体值时(仅支持单个值,暂不支持批量配置),监听集群中带有class注解或者Spec.IngressClassName的值与配置值一致的Ingress资源。例如,当配置成nginx时,监听的Ingress资源包括:IngressClass为nginx或者未关联任何IngressClass的Ingress资源。

    命名空间

    监听指定命名空间的Ingress资源。

    • 当配置成空值时,监听集群中所有命名空间中的Ingress资源。

    • 当配置成具体值时(仅支持单个值,暂不支持批量配置),监听集群中指定命名空间中的Ingress资源。

    更新IngressStatus

    开启更新IngressStatus后,被监听的Ingress的Status中IP地址会被修改为云原生网关关联的SLB IP地址。

    说明

    网关版本为1.2.9及以上才能修改此行为。

    安全组授权

    容器集群的节点池上配置有安全组。通常情况下,集群外的组件要想访问到集群内的服务,就必须在安全组上开放服务所需的全部端口。

    您可以对安全组进行修改。具体操作,请参见设置安全组规则

添加服务

  1. 登录MSE管理控制台,并在顶部菜单栏选择地域。

  2. 在左侧导航栏,选择云原生网关 > 网关列表,单击目标网关名称。

  3. 在左侧导航栏,选择路由管理,然后选择服务页签。

  4. 单击创建服务并配置面板中的相关参数,然后单击确定

    配置项

    说明

    服务来源

    选择容器服务

    命名空间

    选择目标集群的命名空间。

    服务列表

    在服务列表中选择服务。

添加网关到grpcbin服务的路由

  1. 登录MSE管理控制台,并在顶部菜单栏选择地域。

  2. 在左侧导航栏,选择云原生网关 > 网关列表,单击目标网关名称。

  3. 在左侧导航栏,单击路由管理,然后选择路由页签。

  4. 单击创建路由。在创建路由页面,配置路由相关参数,然后单击保存并发布。具体操作,请参见创建路由

    配置项

    说明

    路由名称

    设置为grpc。

    域名

    选择默认域名*。

    路径

    选择匹配条件为前缀是,Path以/grpcbin.GRPCBin开头。

    说明

    gRPC服务的路径名格式为{包名}.{服务名}/{方法名},因此可以配置对应的前缀路由。

    使用场景

    选择该路由的使用场景为单服务

    后端服务

    选择目标服务以及服务端口。

结果验证

使用bloomrpc测试gRPC服务的可用性,若服务端正常返回响应,则表示gRPC服务可用。

同时您也可以使用其他gRPC客户端进行测试。测试gRPC服务可用性