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的负载均衡

相关推荐
圣殿骑士-Khtangc2 小时前
Go错误处理最佳实践进阶从error到panic的完整指南
golang
运维开发笔记2 小时前
3.6 Go defer 语句学习笔记
golang
存在morning4 小时前
【Python 开发实践 一】Python vs Go vs Java 三门语言对比
java·python·golang
圣殿骑士-Khtangc16 小时前
Go字符串高效拼接性能对比与底层原理分析
服务器·前端·golang
KeepSeek17 小时前
AI集群搭建k8s实战(docker)
k8s
xzlAwin20 小时前
Win10安装Go语言多版本管理器g工具
开发语言·golang
暖核21 小时前
Nginx 从入门到实践:部署、配置、反向代理与负载均衡全解
运维·nginx·负载均衡
FfHUCisI1 天前
Golang RESTful API 设计原则
开发语言·golang·restful
黑泽明*1 天前
LVS-负载均衡全解析
运维·负载均衡·lvs
大可-1 天前
Go Air 热重载安装配置指南
开发语言·后端·golang