go服务k8s容器化之grpc负载均衡

理论:

1.grpc基于HTTP/2实现,HTTP2是长连接的,io多路复用,即在一条tcp连接上可以发起多个rpc请求, 请求通过流id 也就是streamID划分。

2.k8s是L4层负载均衡,也就是TCP那层,支持tcp的流量转发,如果是grpc服务部署在k8s,且通过k8s clusterIP访问 就会出现负载不均衡的情况;

3.istio-服务网络,支持7层代理,可以解决grpc服务容器化后负载不均的问题,实现L7的负载均衡;

部署istio

https://www.cnblogs.com/gdut17/p/15144052.html

istio配置镜像拉取策略

https://blog.csdn.net/weixin_60092693/article/details/124599364

命名空间自动注入

kubectl label namespace default istio-injection=enabled --overwrite

去掉自动注入标签

kubectl label ns default istio-injection-

手动注入

yaml 复制代码
istioctl kube-inject -f helloworld_deploy.yaml | kubectl apply -f -

deploy.yaml

yaml 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: helloworld
  name: helloworld
spec:
  replicas: 1
  selector:
    matchLabels:
      app: helloworld
  template:
    metadata:
      labels:
        app: helloworld
    spec:
      containers:
      - image: helloworld:1.0
        imagePullPolicy: Never
        name: service
        command:
        - /main
        - --listen=:80

svc.yaml

yaml 复制代码
[root@localhost grpc]# cat svc.yaml 
apiVersion: v1
kind: Service
metadata:
  labels:
    app: helloworld
  name: helloworld
spec:
  selector:
    app: helloworld
  ports:
  - name: http-admin
    port: 8078
    protocol: TCP
    targetPort: 8078
  - name: grpc
    port: 80
    protocol: TCP
    targetPort: 80
[root@localhost grpc]# cat svc2.yaml 
cat: svc2.yaml: No such file or directory
[root@localhost grpc]# cat svc2
apiVersion: v1
kind: Service
metadata:
  labels:
    app: helloworld2
  name: helloworld2
spec:
  selector:
    app: helloworld2
  ports:
  - name: http-admin
    port: 8078
    protocol: TCP
    targetPort: 8078
  - name: grpc
    port: 80
    protocol: TCP
    targetPort: 80

验证负载均衡

go 复制代码
package main

import (
	"context"
	"flag"
	"fmt"
	pb "gg/demo"
	"log"
	"time"

	"google.golang.org/grpc"
)

var addr = flag.String("addr", "", "")

func main() {
	flag.Parse()

	fmt.Printf("addr=%s\n", *addr)

	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()

	cc, err := grpc.DialContext(ctx, *addr, grpc.WithInsecure(), grpc.WithBlock())
	if err != nil {
		fmt.Println(err)
		return
	}

	cli := pb.NewDemoClient(cc)

	for i := 0; i < 3; i++ {
		resp, err := cli.Hello(context.Background(), &pb.HelloReq{Req: "aa"})
		log.Printf("resp %+v %v\n", resp, err)
	}
}

测试结果:

bash 复制代码
[root@localhost grpc]# q get po -o wide
NAME                           READY   STATUS    RESTARTS   AGE   IP            NODE                    NOMINATED NODE   READINESS GATES
helloworld-5ffbf6c758-lsckl    2/2     Running   0          16m   10.244.0.52   localhost.localdomain   <none>           <none>
helloworld-5ffbf6c758-pjgrw    2/2     Running   0          18m   10.244.0.49   localhost.localdomain   <none>           <none>
helloworld-5ffbf6c758-tdqsd    2/2     Running   0          16m   10.244.0.51   localhost.localdomain   <none>           <none>
helloworld2-567465468b-9qbxj   1/1     Running   0          16m   10.244.0.54   localhost.localdomain   <none>           <none>
helloworld2-567465468b-gffxk   1/1     Running   0          16m   10.244.0.53   localhost.localdomain   <none>           <none>
helloworld2-567465468b-jsdqb   1/1     Running   0          17m   10.244.0.50   localhost.localdomain   <none>           <none>

1.未注入sidecar的容器调用

bash 复制代码
[root@localhost grpc]# q logs -f -lapp=helloworld2 --prefix --tail=1
[pod/helloworld2-567465468b-9qbxj/service] 2024/04/16 15:26:57 Hello req:req:"aa" 
[pod/helloworld2-567465468b-9qbxj/service] 2024/04/16 15:26:57 Hello req:req:"aa" 
[pod/helloworld2-567465468b-9qbxj/service] 2024/04/16 15:26:57 Hello req:req:"aa" 

root@helloworld2-567465468b-9qbxj:/# ./multi_cli -addr helloworld2.default.svc.cluster.local:80
addr=helloworld2.default.svc.cluster.local:80
2024/04/16 15:26:57 resp msg:"aa"  <nil>
2024/04/16 15:26:57 resp msg:"aa"  <nil>
2024/04/16 15:26:57 resp msg:"aa"  <nil>

2.注入sidecar的容器调用

bash 复制代码
[root@localhost grpc]# q logs -f -lapp=helloworld --prefix -c service --tail=1
[pod/helloworld-5ffbf6c758-lsckl/service] 2024/04/16 15:28:58 Hello req:req:"aa" 
[pod/helloworld-5ffbf6c758-pjgrw/service] 2024/04/16 15:28:58 Hello req:req:"aa" 
[pod/helloworld-5ffbf6c758-tdqsd/service] 2024/04/16 15:28:58 Hello req:req:"aa" 


root@helloworld-5ffbf6c758-lsckl:/# ./multi_cli -addr helloworld.default.svc.cluster.local:80
addr=helloworld.default.svc.cluster.local:80
2024/04/16 15:28:58 resp msg:"aa"  <nil>
2024/04/16 15:28:58 resp msg:"aa"  <nil>
2024/04/16 15:28:58 resp msg:"aa"  <nil>

[root@localhost grpc]# q logs -f helloworld-5ffbf6c758-lsckl -c istio-proxy --tail=3
[2024-04-16T15:28:58.013Z] "POST /demo.demo/hello HTTP/2" 200 - "-" "-" 9 9 1 0 "-" "grpc-go/1.26.0" "2185d68d-f1e2-97b9-b8ae-56499db339b4" "helloworld.default.svc.cluster.local:80" "10.244.0.52:80" outbound|80||helloworld.default.svc.cluster.local 10.244.0.52:57827 10.1.190.110:80 10.244.0.52:41260 - default
[2024-04-16T15:28:58.015Z] "POST /demo.demo/hello HTTP/2" 200 - "-" "-" 9 9 7 6 "-" "grpc-go/1.26.0" "a8c05f17-ee23-98f1-a339-cea010103b16" "helloworld.default.svc.cluster.local:80" "10.244.0.49:80" outbound|80||helloworld.default.svc.cluster.local 10.244.0.52:56795 10.1.190.110:80 10.244.0.52:41260 - default
[2024-04-16T15:28:58.023Z] "POST /demo.demo/hello HTTP/2" 200 - "-" "-" 9 9 28 27 "-" "grpc-go/1.26.0" "c439064b-29a9-9374-869d-8281e189dd14" "helloworld.default.svc.cluster.local:80" "10.244.0.51:80" outbound|80||helloworld.default.svc.cluster.local 10.244.0.52:36740 10.1.190.110:80 10.244.0.52:41260 - default

可以看到,注入sidecar的容器,连续3次rpc调用都打到了不同的pod上,实现了L7的负载均衡

相关推荐
龙门吹雪43 分钟前
GO 语言处理多个布尔选项的实现方案
开发语言·后端·golang·布尔选项·标识位
源代码•宸1 小时前
Golang原理剖析(map面试与分析)
开发语言·后端·算法·面试·职场和发展·golang·map
AC赳赳老秦3 小时前
技术文档合著:DeepSeek辅助多人协作文档的风格统一与内容补全
android·大数据·人工智能·微服务·golang·自动化·deepseek
小Ti客栈4 小时前
Nginx进阶配置实战全攻略:SSL部署、防盗链、压缩、代理、限流、请求合并
nginx·负载均衡·ssl
Grassto4 小时前
9 Go Module 依赖图是如何构建的?源码解析
开发语言·后端·golang·go module
bing.shao4 小时前
基于 Go + Ollama 开发智能日志分析工具完整实战
开发语言·后端·golang
Hello.Reader5 小时前
连接四元组它为什么重要,以及它和端口复用(SO_REUSEPORT)的关系(Go 实战)
开发语言·后端·golang
浮尘笔记6 小时前
Go语言上下文:context.Context类型详解
开发语言·后端·golang
weixin199701080166 小时前
安家 GO item_area - 获取地区类列表数据接口对接全攻略:从入门到精通
java·数据库·golang