远程过程调用gRPC(Google Remote Procedure Call)是基于HTTP/2协议标准和ProtoBuf(Protocol Buffers)序列化协议开发设计,且支持众多开发语言,继而提供了连接多路复用、头部压缩、流控等特性,极大地提高了客户端与服务端的通信效率。本文介绍如何通过阿里云容器服务Ingress Controller实现gRPC协议的服务后端的路由功能。
背景信息
gRPC是Google开源的一个高性能RPC通信框架,通过Protocol Buffers作为其IDL,在不同语言开发的平台上使用,同时gRPC基于HTTP/2协议实现,提供了多路复用、头部压缩、流控等特性,极大地提高了客户端与服务端的通信效率。
在gRPC服务中,客户端应用可以同本地方法一样调用到位于不同服务器上的服务端应用方法,可以很方便地创建分布式应用和服务。同其他RPC框架一样,gRPC也需要定义一个服务接口,同时指定被远程调用的方法和返回类型。服务端需要实现被定义的接口,同时运行一个gRPC服务器来处理客户端请求。
前提条件
已创建Kubernetes集群。具体操作,请参见创建Kubernetes托管版集群。
已安装Nginx Ingress Controller组件且其版本不低于0.22.0。关于Ingress Controller组件的版本信息,请参见Nginx Ingress Controller。
已使用kubectl工具连接Kubernetes集群。具体操作,请参见获取集群KubeConfig并通过kubectl工具连接集群。
已安装gRPCurl工具。具体操作,请参见gRPCurl。
gRPC服务示例
定义如下gRPC服务,客户端可调用helloworld.Greeter服务的SayHello接口:
option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
关于gRPC服务示例的源码,请参见gRPC Hello World。
示例说明
NGINX Ingress Controller中,gRPC服务只运行在HTTPS端口(默认443)上,因此在生产环境中,需要域名和对应的SSL证书。本示例使用 grpc.example.com
和自签SSL证书。
本示例基于1.20.4-aliyun集群,Nginx Ingress Controller组件版本为v0.44.0.3-8e83e7dc6-aliyun。
若您已有gRPC服务,可直接执行步骤三:创建Ingress路由规则。
步骤一:申请SSL证书
使用Ingress转发gRPC服务需要对应域名拥有SSL证书,使用TLS协议进行通信。
您可以在数字证书管理服务控制台购买证书,也可以通过Let's Encrypt等第三方平台申请免费的SSL证书。
本示例使用OpenSSL生成的自签证书。
复制以下内容并保存至/tmp/openssl.cnf文件中。
[ req ] #default_bits = 2048 #default_md = sha256 #default_keyfile = privkey.pem distinguished_name = req_distinguished_name attributes = req_attributes req_extensions = v3_req [ req_distinguished_name ] countryName = Country Name (2 letter code) countryName_min = 2 countryName_max = 2 stateOrProvinceName = State or Province Name (full name) localityName = Locality Name (eg, city) 0.organizationName = Organization Name (eg, company) organizationalUnitName = Organizational Unit Name (eg, section) commonName = Common Name (eg, fully qualified host name) commonName_max = 64 emailAddress = Email Address emailAddress_max = 64 [ req_attributes ] challengePassword = A challenge password challengePassword_min = 4 challengePassword_max = 20 [v3_req] # Extensions to add to a certificate request basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment subjectAltName = @alt_names [alt_names] DNS.1 = grpc.example.com
执行以下命令签署证书请求。
openssl req -new -nodes -keyout grpc.key -out grpc.csr -config /tmp/openssl.cnf -subj "/C=CN/ST=Zhejiang/L=Hangzhou/O=AlibabaCloud/OU=ContainerService/CN=grpc.example.com"
执行以下命令签署证书。
openssl x509 -req -days 3650 -in grpc.csr -signkey grpc.key -out grpc.crt -extensions v3_req -extfile /tmp/openssl.cnf
命令执行成功后,可得到证书grpc.crt与私钥文件grpc.key。
执行以下命令将名称为grpc-secret的TLS Secret添加到集群中。
或可通过控制台将TLS Secret添加到集群中。具体操作,请参见创建保密字典。
kubectl create secret tls grpc-secret --key grpc.key --cert grpc.crt
步骤二:创建gRPC服务所需资源
在集群中创建使用gRPC协议的后端服务。本示例使用镜像registry.cn-hangzhou.aliyuncs.com/acs-sample/grpc-server
创建gRPC服务。
复制以下YAML内容创建grpc.yaml文件。
apiVersion: apps/v1 kind: Deployment metadata: name: grpc-service spec: replicas: 1 selector: matchLabels: run: grpc-service template: metadata: labels: run: grpc-service spec: containers: - image: registry.cn-hangzhou.aliyuncs.com/acs-sample/grpc-server:latest imagePullPolicy: Always name: grpc-service ports: - containerPort: 50051 protocol: TCP restartPolicy: Always --- apiVersion: v1 kind: Service metadata: name: grpc-service spec: ports: - port: 50051 protocol: TCP targetPort: 50051 selector: run: grpc-service sessionAffinity: None type: NodePort
执行以下命令创建gRPC Deployment资源以及对应的服务。
kubectl apply -f grpc.yaml
预期输出:
deployment.apps/grpc-service created service/grpc-service created
执行以下命令查看Pod。
kubectl get pod
预期输出:
NAME READY STATUS RESTARTS AGE grpc-service-57884679-2bkbr 1/1 Running 0 98s
从预期输出可得,grpc-service-57884679-2bkbr的状态为Running,已成功启动。
步骤三:创建Ingress路由规则
复制以下YAML内容创建grpc-ingress.yaml文件。
重要部署gRPC服务所使用的Ingress需要在annotation中加入
nginx.ingress.kubernetes.io/backend-protocol
,值为GRPC。本示例使用的域名为
grpc.example.com
,请根据实际情况修改。
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: grpc-ingress annotations: # 注意这里:必须要配置以指明后端服务为gRPC服务 nginx.ingress.kubernetes.io/backend-protocol: "GRPC" spec: # 指定证书 tls: - hosts: - grpc.example.com secretName: grpc-secret rules: # gRPC服务域名 - host: grpc.example.com http: paths: - path: / pathType: Prefix backend: service: # gRPC服务 name: grpc-service port: number: 50051
执行以下命令创建Ingress路由规则。
kubectl apply -f grpc-ingress.yaml
预期输出:
ingress.networking.k8s.io/grpc-ingress created
结果验证
本地安装gRPCurl工具后,输入grpcurl <域名>:443 list
验证请求是否成功转发到后端服务。
本示例中使用域名grpc.example.com
以及自签证书,执行以下命令验证请求是否成功转发到后端服务。
grpcurl -insecure -authority grpc.example.com <ip_address>:443 list
ip_address为Nginx Ingress Controller的Service外部IP,可通过kubectl get ingress
获取。
预期输出:
grpc.reflection.v1alpha.ServerReflection
helloworld.Greeter
从预期输出可得,流量被Ingress成功转发到后端gRPC服务。
后续步骤
关于如何通过Ingress Controller实现gRPC服务的灰度发布,请参见通过Nginx Ingress实现灰度发布和蓝绿发布。
由于Nginx grpc_pass的限制,目前对于gRPC服务,暂不支持service-weight的配置。
- 本页导读 (1)