[干貨]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)
	}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM