腾讯云TKE-Ingress案例: Nginx-Ingress 实现grpc转发

2020-10-26 20:47:11 浏览数 (1)

背景

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

那么在TKE如何将gRPC服务暴露到公网提供给客户使用呢?本次将给大家展示使用Nginx-Ingress 暴露gRPC服务到公网.

在腾讯云TKE-Ingress案例: TKE-Ingress与Nginx-Ingress共存文章中已经介绍了如何在TKE中部署nginx-ingress,这里就不详细赘述.

部署gRPC服务

服务代码以及镜像构建(以下为gRPC的server demo仅供演示使用,地址: https://github.com/lmdkfs/grpc-demo)

文件结构:

代码语言:txt复制
 ~/d/g/grpc-demo    tree                                                                                                                  一 10/26 12:23:41 2020
.
├── Dockerfile
├── Makefile
├── README.md
├── bin
│   └── grpc-server
├── go.mod
├── go.sum
├── grpcapi
│   ├── grpcapi.pb.go
│   └── grpcapi.proto
└── server.go

2 directories, 9 files

server.go 代码:

代码语言:txt复制
package main

import (
	"context"
	"fmt"
	"os/signal"

	"log"
	"net"
	"os"

	"grpc-demo/grpcapi"
	"google.golang.org/grpc"
	"google.golang.org/grpc/reflection"
)

type grpcServer struct{}

func (*grpcServer) GrpcService(ctx context.Context, req *grpcapi.GrpcRequest) (*grpcapi.GrpcResponse, error) {
	fmt.Printf("grpcServer %vn", req)
	name, _ := os.Hostname()

	input := req.GetInput()
	result := "Got input "   input   " server host: "   name
	res := &grpcapi.GrpcResponse{
		Response: result,
	}
	return res, nil
}

func main() {
	fmt.Println("Starting Server...")

	log.SetFlags(log.LstdFlags | log.Lshortfile)

	hostname := os.Getenv("SVC_HOST_NAME")

	if len(hostname) <= 0 {
		hostname = "0.0.0.0"
	}

	port := os.Getenv("SVC_PORT")

	if len(port) <= 0 {
		port = "50051"
	}

	lis, err := net.Listen("tcp", hostname ":" port)
	if err != nil {
		log.Fatalf("Failed to listen: %v", err)
	}

	opts := []grpc.ServerOption{}
	s := grpc.NewServer(opts...)
	grpcapi.RegisterGrpcServiceServer(s, &grpcServer{})

	// reflection service on gRPC server.
	reflection.Register(s)

	go func() {
		fmt.Println("Server running on ", (hostname   ":"   port))
		if err := s.Serve(lis); err != nil {
			log.Fatalf("failed to serve: %v", err)
		}
	}()

	// Wait for Control C to exit
	ch := make(chan os.Signal, 1)
	signal.Notify(ch, os.Interrupt)

	// Block until a signal is received
	<-ch
	fmt.Println("Stopping the server")
	s.Stop()
	fmt.Println("Closing the listener")
	lis.Close()
	fmt.Println("Server Shutdown")

}

grpcapi/grpcapi.proto

代码语言:txt复制
syntax = "proto3";

package greet;
option go_package="grpcapi";


message GrpcRequest {
    string input = 1;
}

message GrpcResponse {
    string response = 1;
}

service GrpcService{
  
    rpc grpcService(GrpcRequest) returns (GrpcResponse) {};

}

生成go代码(在grpcapi 目录下执行):

代码语言:txt复制
protoc --go_out=plugins=grpc:. grpcapi.proto
代码语言:txt复制
> 注意mac下安装protoc命令: brew install protobuf

执行完成之后会生成 grpcapi.pb.go 文件

打包并生成镜像:

代码语言:txt复制
make linux

make docker

将打包好的镜像push到TCR的镜像仓库(我这边测试的地址为: ccr.ccs.tencentyun.com/ruiqingzhu-tke/grpc-server:0.1)

部署grpc-server 服务:

Xnip2020-10-26_20-32-32.pngXnip2020-10-26_20-32-32.png

通过nginx-ingress 暴露gRPC 服务

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

生成key: openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout ssl_ingress.key -out ssl_ingress.pem -subj "/CN=grpc.example.com"

生成secret:

kubectl create secret tls grpcserver-secret --cert ssl_ingress.pem --key ssl_ingress.key -n grpcserver

gRPC的访问地址: grpc.example.com:443

ingress.yaml文件内容如下:

代码语言:txt复制
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
  name: grpcserver
  namespace: grpcserver
spec:
  rules:
    - host: grpc.example.com
      http:
        paths:
          - backend:
              serviceName: grpcserver
              servicePort: 50051
  tls:
# This secret must exist beforehand
# The cert must also contain the subj-name grpc.example.com
# https://github.com/kubernetes/ingress-nginx/blob/master/docs/examples/PREREQUISITES.md#tls-certificates
    - secretName: grpcserver-secret
      hosts:
         - grpc.example.com

部署: kubectl apply -f ingress.yaml

测试调用

测试工具使用grpcurl(mac安装命令: brew install grpcurl)

在本地写hosts: xxx grpc.example.com

代码语言:txt复制
> xxx 为nginx-controller的公网ip查看方法:
代码语言:txt复制
➜  test_grpc grpcurl -insecure grpc.test.example:443 list
greet.GrpcService
grpc.reflection.v1alpha.ServerReflection

测试调用:

代码语言:txt复制
➜  test_grpc grpcurl -insecure grpc.example.com:443 greet.GrpcService/grpcService

{
  "response": "Got input  server host: grpc-demo-5c4567f989-4p69n"
}

测试成功

0 人点赞