• [干货]kubenertes ingress负载grpc


    概述

    一般情况下,我们的系统对外暴露HTTP/HTTPS的接口,内部使用rpc(GRPC)通讯,这时GRPC在服务之间通过service访问,本地调试时通过service nodePort方式调用。
    但随着业务壮大,需要跨集群的GRPC通讯,或者pod数量太多、nodePort端口管理混乱时,就可以考虑用ingress来统一管理和暴露GRPC服务了。

    本文详细介绍如何在kubernetes用ingress负载grpc服务。

    • 首先需要特别留意:ingress-nginx不支持负载明文的grpc(这个官方居然没明说,巨坑,详情请自行搜索github上的issues),所以只能在443端口上用TLS来负载。

    搭建

    生成公私钥

    前面说了ingress只支持在443端口上负载加密的grpc,所以在正式搭建前需要准备一组公私钥。

    这里我们可以自行生成一组普通的公私钥,下面的命令将在当前目录生成一组公私钥文件:

    $ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout grpcs.key -out grpcs.crt -subj "/CN=*.grpcs.aurayou/O=grpcs.aurayou"
    $ ls
    grpcs.crt  grpcs.key
    

    参数说明:

    • grpcs.key: 私钥文件名
    • grpcs.crt: 公钥文件名
    • .grpcs.aurayou: 域名后缀,后续所有使用此公私钥对的域名必须以.grpcs.aurayou为后缀

    创建secret

    将刚才生成的公私钥对导入k8s secret,创建名为grpcs-secret的secret:

    $ kubectl create secret tls grpcs-secret --key grpcs.key --cert grpcs.crt
    $ kube get secret
    NAME                  TYPE                                  DATA      AGE
    default-token-bhp5l   kubernetes.io/service-account-token   3         88d
    grpcs-secret          kubernetes.io/tls                     2         6h
    

    创建ingress

    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: data-product
      namespace: aurayou
    spec:
      rules:
      - host: data-product.grpcs.aurayou
        http:
          paths:
          - backend:
              serviceName: data-product
              servicePort: 50051
      tls:
      - secretName: grpcs-secret
        hosts:
          - data-product.grpcs.aurayou
    

    参数说明:

    • 启用nginx:kubernetes.io/ingress.class: "nginx"
    • 启用TLS,下面两项2选1:
    • 由nginx负责tls,服务内部还是用明文传输:nginx.ingress.kubernetes.io/ssl-redirect: "true"、nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
    • 由服务自行实现TLS,nginx只负责路由:nginx.ingress.kubernetes.io/backend-protocol: "GRPCS"
    • 域名:rules.host、tls.hosts这两个是该grpc服务的ingress域名,可以自定义,但必须以前面生成公私钥对时使用的后缀结尾
    • 服务: grpc服务的服务名和端口由rules.http.backend配置
    • 公私钥: tls.secretName指向前面创建的grpcs-secret

    注意:ingress-nginx的搭建,最好使用官方的yaml文件,自定义的配置可能会有冲突之处。

    访问

    前面已经搭建好了grpc服务的ingress,外部服务访问该ingress时,需要加载刚才生成的公钥文件,golang代码关键点:

    • 访问明文的服务时,选项使用grpc.WithInsecure()
    • 访问加密的ingress时,选项使用grpc.WithTransportCredentials,并用credentials.NewClientTLSFromFile加载前面生成的公钥并指定需要访问的域名
    	tcp_port := viper.GetString("server.tcp.port")
    	tcp_host := viper.GetString("server.tcp.host")
    
    	tcp_address := tcp_host + tcp_port
    
    	var dailOpts []grpc.DialOption
    	if tcp_port == ":443" {
    		// 走ingress 443端口,加密传输
    		// NewClientTLSFromFile()函数的参数1是前面生成的公钥文件,参数2是待访问的域名
    		creds, err := credentials.NewClientTLSFromFile("./grpcs.crt", "data-product.grpcs.aurayou")
    		if err != nil {
    			log.Fatalf("Failed to create TLS credentials %v", err)
    		}
    		dailOpts = append(dailOpts, grpc.WithTransportCredentials(creds))
    	} else {
    		// 访问明文的集群内部服务
    		dailOpts = append(dailOpts, grpc.WithInsecure())
    	}
    	
    	// Set up a connection to the server.
    	conn, err := grpc.Dial(tcp_address, dailOpts...)
    	if err != nil {
    		log.Fatalf("did not connect: %v", err)
    	}
    
  • 相关阅读:
    小项目中建立列表页时间需要注意的
    【腾讯Bugly干货分享】总结一个技术总监的教训和经验
    【腾讯优测干货分享】如何降低App的待机内存(四)——进阶:内存原理
    【腾讯Bugly干货分享】微信终端跨平台组件 Mars 系列
    【腾讯Bugly干货分享】微信终端跨平台组件 mars 系列(二)
    【腾讯Bugly干货分享】程序员们也该知道的事——“期权和股票”
    【腾讯Bugly干货分享】彻底弄懂 Http 缓存机制
    【腾讯优测干货分享】如何降低App的待机内存(三)——探索内存增长的原因
    【腾讯优测干货分享】如何降低App的待机内存(二)——规范测试流程及常见问题
    【腾讯Bugly干货分享】聊聊苹果的Bug
  • 原文地址:https://www.cnblogs.com/JoZSM/p/11417093.html
Copyright © 2020-2023  润新知