通过ASM入口网关实现HTTP请求网格内gRPC服务
ASM入口网关支持协议转码的能力。客户端可以使用HTTP/JSON访问服务网格内的gRPC服务。本文介绍如何通过ASM入口网关实现HTTP请求网格内gRPC服务。
前提条件
已创建ASM企业版或旗舰版实例。具体操作,请参见创建ASM实例。
- 已添加集群到ASM实例。
已部署入口网关服务,并暴露9996(gRPC)端口。具体操作,请参见创建入口网关服务。
已安装Protocol工具。更多信息,请参见Protocol Buffers v3.14.0。
背景信息
Envoy作为服务网格ASM数据平面的Proxy组件,内置多种HTTP扩展过滤器,包括HTTP到gRPC的转码器。为了启用该过滤器,Envoy定义了相应的过滤器协议。ASM的控制平面需要定义一个EnvoyFilter来声明某个阶段启用这个过滤器,然后下发该EnvoyFilter在指定环节启用转码器。
转码流程
ASM入口网关可将HTTP/JSON转码为gRPC。下图为完整的HTTP请求、gRPC转码以及gRPC请求流程。
序号 | 说明 |
① | ASM控制平面下发用于gRPC转码的EnvoyFilter,用于路由到gRPC服务端口的规则配置Gateway和VirtualService到ASM入口网关,入口网关接收后即时加载生效。 |
② | 入口网关收到客户端HTTP协议的请求后,将进行路由规则匹配和协议转换,然后以gRPC协议请求服务网格内的gRPC服务。 |
③ | 入口网关收到后端服务的gRPC响应,再将其转换为HTTP的响应返回给请求方。 |
步骤一:部署示例应用
创建grpc-best命名空间,开启自动注入,并同步自动注入至Kubernetes集群。
- 登录ASM控制台,在左侧导航栏,选择 。
- 在网格管理页面,单击目标实例名称,然后在左侧导航栏,选择 。
在全局命名空间页面单击新建,然后在新建命名空间面板,配置名称为grpc-best,单击确定。
在操作列,单击grpc-best对应的启用 Sidecar 自动注入,在确认对话框,单击确定。
在页面上方,单击同步自动注入至Kubernetes集群。
在数据面集群的grpc-best命名空间中部署一个可访问的gRPC服务。
使用以下YAML,创建grpc-server.yaml。
apiVersion: apps/v1 kind: Deployment metadata: namespace: grpc-best name: grpc-server-java labels: app: grpc-server-deploy version: v1 spec: replicas: 1 selector: matchLabels: app: grpc-server-deploy version: v1 template: metadata: labels: app: grpc-server-deploy version: v1 spec: serviceAccountName: grpc-best-sa containers: - name: grpc-server-deploy image: feuyeux/grpc_with_api_server_java:1.0.0 imagePullPolicy: Always ports: - containerPort: 9996 name: grpc-port --- apiVersion: v1 kind: Service metadata: namespace: grpc-best name: grpc-server-svc labels: app: grpc-server-svc spec: ports: - port: 9996 name: grpc-port selector: app: grpc-server-deploy
执行以下命令,部署gRPC服务。
kubectl apply -f grpc-server.yaml
在ASM实例中创建网关规则、虚拟服务和目标规则。
使用以下内容,创建gateway-sr-vs.yaml。
本示例的ASM网关名称为
ingressgateway
。apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: namespace: grpc-best name: grpc-gateway spec: selector: istio: ingressgateway servers: - port: number: 9996 name: grpc protocol: GRPC hosts: - "*" --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: namespace: grpc-best name: grpc-server-vs spec: hosts: - "*" gateways: - grpc-gateway http: - match: - port: 9996 route: - destination: host: grpc-server-svc subset: v1 weight: 100 --- apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: namespace: grpc-best name: grpc-server-dr spec: host: grpc-server-svc subsets: - name: v1 labels: version: v1 - name: v2 labels: version: v2 - name: v3 labels: version: v3 - name: v4 labels: version: v4 - name: v5 labels: version: v5
执行以下命令,部署网关规则、虚拟服务和目标规则。
kubectl apply -f gateway-sr-vs.yaml
步骤二:补充转码声明,生成Proto Descriptors文件
您可以修改服务的.proto文件,使用gRPC协议实现gRPC请求转码成HTTP请求。
在.proto文件的实践方法中增加支持转码的声明,以支持HTTP转码gRPC。
option(google.api.http) = { get: "/v1/talk/{data}/{meta}" };
以hello-servicemesh-rpc示例中的.proto为例,补充转码声明后的.proto如下。关于hello-servicemesh-grpc的详细信息,请参见hello-servicemesh-grpc。
import "google/api/annotations.proto"; service LandingService { //Unary RPC rpc talk (TalkRequest) returns (TalkResponse) { option(google.api.http) = { get: "/v1/talk/{data}/{meta}" }; } ... } message TalkRequest { string data = 1; string meta = 2; }
将googleapis和hello-servicemesh-grpc克隆到本地。
在Protocol工具上执行以下命令,使用
protoc
命令从landing.proto
生成landing.proto-descriptor
文件。# https://github.com/AliyunContainerService/hello-servicemesh-grpc proto_path={path/to/hello-servicemesh-grpc}/grpc/proto # https://github.com/googleapis/googleapis/tree/master/ proto_dep_path={path/to/googleapis} protoc \ --proto_path=${proto_path} \ --proto_path=${proto_dep_path} \ --include_imports \ --include_source_info \ --descriptor_set_out=landing.proto-descriptor \ "${proto_path}"/landing.proto
步骤三:启用协议转码插件
ASM控制台内置了ASM网关HTTP-gRPC协议转码插件,便于您进行相关配置。
使用以下Python脚本,将
landing.proto-descriptor
文件进行Base64编码。import base64 with open("landing.proto-descriptor", 'rb') as fin, open("encoded.txt", 'w', encoding='utf-8') as fout: proto = fin.read() encoded = base64.b64encode(proto) fout.write(bytes.decode(encoded)) # 最终在encoded.txt文件中拷贝Base64编码后的结果。
配置ASM网关HTTP-gRPC协议转码。
- 登录ASM控制台,在左侧导航栏,选择 。
- 在网格管理页面,单击目标实例名称,然后在左侧导航栏,选择 。
在插件市场页面,单击ASM网关HTTP-gRPC协议转码卡片,然后单击插件配置页签。
在插件配置页签的插件生效范围区域,单击网关生效,单击添加网关生效范围,选中目标网关(本示例为ingressgateway),单击
,然后单击确定。
在插件配置区域,配置YAML,然后打开生效开关。
YAML字段说明如下。
字段
类型
是否必选
默认值
说明
port_number
string
是
-
配置需要在网关上进行协议转码的服务端口。
proto_services
string array
是
["org.feuyeux.grpc.LandingService"]
配置在Proto文件中声明的服务,格式为{包名}.{服务名},例如
"org.feuyeux.grpc.LandingService"
。proto_descriptor
string
是
-
生成Proto Descriptor文件后,将文件内容进行Base64编码后的结果。
步骤四:使用HTTP请求网格内的gRPC服务
执行以下命令,通过HTTP请求访问网关的9996端口(该端口暴露了一个gRPC服务)。
curl http://$INGRESS_IP:9996/v1/talk/0/java
预期输出:
{
"status": 200,
"results": [
{
"id": "69988257608****",
"type": "OK",
"kv": {
"data": "Hello",
"meta": "JAVA",
"id": "8c175d5c-d8a3-4197-a7f8-****",
"idx": "0"
}
}
]
}
该JSON由后端的gRPC服务返回,表明使用HTTP请求通过ASM网关访问网格内的gRPC服务成功。