网络知识 娱乐 tke上nginx-ingress实现grpc转发

tke上nginx-ingress实现grpc转发

gRPC是Google开源的一个高性能RPC通信框架,通过Protocol Buffers作为其IDL,可以在不同语言开发的平台上使用,同时基于HTTP/2协议实现,继而提供了连接多路复用、头部压缩、流控等特性,极大地提高了客户端与服务端的通信效率。

在 gRPC 中,客户端应用程序可以直接调用不同机器上的服务器应用程序上的方法,就像它是本地对象一样,使您更容易创建分布式应用程序和服务。与许多 RPC 系统一样,gRPC 基于定义服务的思想,指定可以远程调用的方法及其参数和返回类型。在服务端,服务端实现这个接口并运行一个 gRPC 服务器来处理客户端调用。在客户端,客户端有一个存根(在某些语言中仅称为客户端),它提供与服务器相同的方法。

下面我们在演示下在tke上部署一个grpc的demo,然后通过nginx-ingress来实现对grpc服务的转发。注意下面的所有资源都部署在weixnie这个命名空间下,如果需要部署到自己的命名空间,需要修改下yaml。

1. 部署grpc-server

可以参考yaml部署下grpc-server

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    k8s-app: grpc-service
    qcloud-app: grpc-service
  name: grpc-service
  namespace: weixnie
spec:
  progressDeadlineSeconds: 600
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      k8s-app: grpc-service
      qcloud-app: grpc-service
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  template:
    metadata:
      labels:
        k8s-app: grpc-service
        qcloud-app: grpc-service
    spec:
      containers:
      - image: ccr.ccs.tencentyun.com/niewx-k8s/grpc:latest
        imagePullPolicy: Always
        name: grpc-service
        resources:
          limits:
            cpu: 500m
            memory: 1Gi
          requests:
            cpu: 250m
            memory: 256Mi
        securityContext:
          privileged: false
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      imagePullSecrets:
      - name: qcloudregistrykey
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}

2. 配置ingress转发grpc服务

Ingress Nginx暴露gRPC服务的时候,暂时只支持TLS(HTTPS)的方式,而不能通过普通HTTP方式,所以我们要配置TLS secret。

这里获取证书的方式有2种,一种可以用命令生成

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=grpc.example.com/O=grpc.example.com"

还有一种就是去腾讯云上申请一年有效的证书

证书生成好之后,我们用secret配置下证书

kubectl create secret tls grpc-secret  --cert tls.crt --key tls.key -n weixnie

然后创建下ingress

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx-intranet
    nginx.ingress.kubernetes.io/backend-protocol: GRPC
  name: grpc-ingress
  namespace: weixnie
spec:
  rules:
  - host: grpc.example.com
    http:
      paths:
      - backend:
          serviceName: grpc-service
          servicePort: 50051
        path: /
        pathType: ImplementationSpecific
  tls:
  - hosts:
    - grpc.example.com
    secretName: grpc-secret

注意ingress.class配置成自己的class名称,nginx-ingress实现grpc转发,必须要配置上这个注解nginx.ingress.kubernetes.io/backend-protocol:GRPC

3. 测试grpc服务访问

创建好ingress后,我们来用grpcurl来测试访问下,如果你本地没有grpcurl这个工具,可以通过下面yaml起一个grpcurl工具pod,然后在容器里用grpcurl 去测试

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    k8s-app: grpcurl
    qcloud-app: grpcurl
  name: grpcurl
  namespace: weixnie
spec:
  progressDeadlineSeconds: 600
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      k8s-app: grpcurl
      qcloud-app: grpcurl
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        k8s-app: grpcurl
        qcloud-app: grpcurl
    spec:
      containers:
      - args:
        - 70d
        command:
        - sleep
        image: ccr.ccs.tencentyun.com/niewx-k8s/grpcurl:latest
        imagePullPolicy: Always
        name: grpcurl
        resources: {}
        securityContext:
          privileged: false
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      hostAliases:
      - hostnames:
        - grpc.example.com
        ip: 172.16.0.14
      imagePullSecrets:
      - name: qcloudregistrykey
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30

因为grpc.example.com这个域名没有配置解析,所以需要在容器里面配置下host,将域名解析到nginx-ingress控制器入口serivce的ip上。

pod起来后,我们直接到容器测试下

# 查看gRPC服务端提供的所有服务:
# grpcurl -insecure grpc.example.com:443 list


# 查看helloworld.Greeter服务的接口方法
# grpcurl -insecure grpc.example.com:443 list helloworld.Greeter

# 描述SayHello方法的具体协议参数
# grpcurl -insecure grpc.example.com:443 describe helloworld.Greeter.SayHello

# 调用SayHello方法并传递name参数
# grpcurl -insecure -d '{"name": "gRPC"}' grpc.example.com:443 helloworld.Greeter.SayHello

# grpcurl -insecure -d '{"name": "world"}' grpc.example.com:443 helloworld.Greeter.SayHello

这里测试调用成功