K8S集群发布微服务进行负载均衡测试

一、配置集群

首先配置集群,具体配置看我的这篇文章:centos7安装k8s1.23.6
集群拓扑图

二、在windows电脑上创建好grpc的通讯流程代码

2.1首先创建hello.proto接口

//hello.proto
syntax="proto3";
//package go_rpc;
option go_package="/hello";
service HelloServer{
    //创建第一个接口
    rpc SayHello(HelloRequest) returns (HelloReply){}
}


message HelloRequest{
    string from=1;
    string to=2;
    string msg=3;
}

message HelloReply{
    string from=1;
    string to=2;
    string msg=3;
}

2.2再编写servera和serverb的代码

//SERVERA.go
package main

import (
	"context"
	"fmt"
	gr "hello"
	"net"
	"net/http"
	"strings"

	"google.golang.org/grpc"
)

const (
	SERVERB = "localhost:18081"
	// SERVERB = "serverb:18081"
	// SERVERC = ""
	// SERVERD = ""
	// SERVERE = ""
)

func main() {
	http.HandleFunc("/", indexHandler)
	http.HandleFunc("/b", serverb)
	http.ListenAndServe(":8080", nil)
}

func indexHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "this is serverA,ip: "+LocalIp())
}

func serverb(w http.ResponseWriter, r *http.Request) {
	//客户端连接服务器
	conn, err := grpc.Dial(SERVERB, grpc.WithInsecure())
	if err != nil {
		fmt.Println("连接服务器2失败", err)
	}
	defer conn.Close()
	//获得grpc句柄
	client := gr.NewHelloServerClient(conn)
	from := "SERVERA: " + LocalIp()
	//远程调用SayHello接口
	re, err := client.SayHello(context.Background(), &gr.HelloRequest{From: from, To: "", Msg: ""})
	if err != nil {
		fmt.Println("SEVERA COULDN'T CONNECT SERVERB ..", err)
		return
	}

	fmt.Fprint(w, re)
}

// func LocalIp() string {
// 	addrs, _ := net.InterfaceAddrs()
// 	var ip string = "localhost"
// 	for _, address := range addrs {
// 		if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
// 			if ipnet.IP.To4() != nil {
// 				ip = ipnet.IP.String()
// 			}
// 		}
// 	}
// 	return ip
// }

// getLocalIpV4 获取 IPV4 IP,没有则返回空,只能检测单网卡,多网卡只要获取第一个
func LocalIp() string {
	inters, err := net.Interfaces()
	if err != nil {
		panic(err)
	}

	for _, inter := range inters {
		// 判断网卡是否开启,过滤本地环回接口
		if inter.Flags&net.FlagUp == 0 || strings.HasPrefix(inter.Name, "lo") {
			continue
		}
		// 获取网卡下所有的地址
		addrs, err := inter.Addrs()
		if err != nil {
			continue
		}
		for _, addr := range addrs {
			ipnet, ok := addr.(*net.IPNet)
			if !ok || ipnet.IP.IsLoopback() {
				continue
			}

			//判断是否存在IPV4 IP 如果没有过滤
			if ipnet.IP.To4() != nil {
				return ipnet.IP.String()
			}
		}
	}

	return ""
}

//SERVERB.go
package main

import (
	"context"
	"fmt"
	gr "hello"
	"net"
	"strings"

	"google.golang.org/grpc"
)

const (
	SERVERB = ":18081"

// SERVERC = ""
// SERVERD = ""
// SERVERE = ""
)

// 对象要和proto内定义的服务一样
type server struct{}

func main() {
	ln, err := net.Listen("tcp", SERVERB)
	if err != nil {
		fmt.Println("网络异常:", err)
	}

	//创建一个grpc句柄
	srv := grpc.NewServer()

	//将server结构体注册到grpc服务中
	gr.RegisterHelloServerServer(srv, &server{})

	//监听grpc服务
	err = srv.Serve(ln)
	if err != nil {
		fmt.Println("网络异常:", err)
	}

}
func (s *server) SayHello(ctx context.Context, in *gr.HelloRequest) (*gr.HelloReply, error) {
	//in.Msg := "this is serverb,hello " + in.From
	msg := "Requset By: " + in.From + "Response By: " + LocalIp() + "This is SERVERB.Hello!"
	return &gr.HelloReply{Msg: msg}, nil
}

// func LocalIp() string {
// 	addrs, _ := net.InterfaceAddrs()
// 	var ip string = "localhost"
// 	for _, address := range addrs {
// 		if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
// 			if ipnet.IP.To4() != nil {
// 				ip = ipnet.IP.String()
// 			}
// 		}
// 	}
// 	return ip
// }

func LocalIp() string {
	inters, err := net.Interfaces()
	if err != nil {
		panic(err)
	}

	for _, inter := range inters {
		// 判断网卡是否开启,过滤本地环回接口
		if inter.Flags&net.FlagUp == 0 || strings.HasPrefix(inter.Name, "lo") {
			continue
		}
		// 获取网卡下所有的地址
		addrs, err := inter.Addrs()
		if err != nil {
			continue
		}
		for _, addr := range addrs {
			ipnet, ok := addr.(*net.IPNet)
			if !ok || ipnet.IP.IsLoopback() {
				continue
			}

			//判断是否存在IPV4 IP 如果没有过滤
			if ipnet.IP.To4() != nil {
				return ipnet.IP.String()
			}
		}
	}

	return ""
}

2.3在windows上试运行的结果如下:

在这里插入图片描述
在这里插入图片描述

2.4因为需要在k8s系统上部署,使用service发布,所以修改一下代码中的ip指向。

//SERVERA.go
package main

import (
	"context"
	"fmt"
	gr "hello"
	"net"
	"net/http"
	"strings"

	"google.golang.org/grpc"
)

const (
	// SERVERB = "localhost:18081"
	SERVERB = "serverb:18081"
	// SERVERC = ""
	// SERVERD = ""
	// SERVERE = ""
)

func main() {
	http.HandleFunc("/", indexHandler)
	http.HandleFunc("/b", serverb)
	http.ListenAndServe(":8080", nil)
}

func indexHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "this is serverA,ip: "+LocalIp())
}

func serverb(w http.ResponseWriter, r *http.Request) {
	//客户端连接服务器
	conn, err := grpc.Dial(SERVERB, grpc.WithInsecure())
	if err != nil {
		fmt.Println("连接服务器2失败", err)
	}
	defer conn.Close()
	//获得grpc句柄
	client := gr.NewHelloServerClient(conn)
	from := "SERVERA: " + LocalIp()
	//远程调用SayHello接口
	re, err := client.SayHello(context.Background(), &gr.HelloRequest{From: from, To: "", Msg: ""})
	if err != nil {
		fmt.Println("SEVERA COULDN'T CONNECT SERVERB ..", err)
		return
	}

	fmt.Fprint(w, re)
}

// func LocalIp() string {
// 	addrs, _ := net.InterfaceAddrs()
// 	var ip string = "localhost"
// 	for _, address := range addrs {
// 		if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
// 			if ipnet.IP.To4() != nil {
// 				ip = ipnet.IP.String()
// 			}
// 		}
// 	}
// 	return ip
// }

// getLocalIpV4 获取 IPV4 IP,没有则返回空,只能检测单网卡,多网卡只要获取第一个
func LocalIp() string {
	inters, err := net.Interfaces()
	if err != nil {
		panic(err)
	}

	for _, inter := range inters {
		// 判断网卡是否开启,过滤本地环回接口
		if inter.Flags&net.FlagUp == 0 || strings.HasPrefix(inter.Name, "lo") {
			continue
		}
		// 获取网卡下所有的地址
		addrs, err := inter.Addrs()
		if err != nil {
			continue
		}
		for _, addr := range addrs {
			ipnet, ok := addr.(*net.IPNet)
			if !ok || ipnet.IP.IsLoopback() {
				continue
			}

			//判断是否存在IPV4 IP 如果没有过滤
			if ipnet.IP.To4() != nil {
				return ipnet.IP.String()
			}
		}
	}

	return ""
}

三、编写Dockerfile,将镜像打包上传到仓库

3.1 编写Dockerfile:

### 3.1.1 FROM命令:
### 3.1.2 RUN命令:
### 3.1.3 COPY命令:
### 3.1.4 ADD命令:
### 3.1.5 WORKDIR命令:
### 3.1.6 CDM命令:
### 3.1.7 EMTERPOINT命令:
### 3.1.8 ENV命令:
### 3.1.9 EXPOSE命令:
EXPOSE是Dockerfile中的一条指令,它用于声明容器运行时所监听的网络端口。当其他人阅读该Dockerfile时,可以很清楚地了解该容器所需要打开哪些端口。EXPOSE并不会真正将宿主机上的端口暴露出来,它只是一个元数据,方便用户了解容器的网络设置。
#SERVERA的Dockerfile
FROM golang:alpine

WORKDIR /app

COPY . .

EXPOSE 8080
EXPOSE 18081

RUN go build -o Server_A Server_A.go 
# 运行应用
CMD ["./Server_A"]
#SERVERB的Dockerfile
FROM golang:alpine

WORKDIR /app

COPY . .

EXPOSE 18081

RUN go build -o Server_B Server_B.go 
# 运行应用
CMD ["./Server_B"]

3.2 打包上传镜像

(base) PS D:\STUDY_ALONE\GO\go_demo\go_http_v2\SERVERA> docker login -u 2228776283     
Password: 
Login Succeeded

Logging in with your password grants your terminal complete access to your account.    
For better security, log in with a limited-privilege personal access token. Learn more 
at https://docs.docker.com/go/access-tokens/
(base) PS D:\STUDY_ALONE\GO\go_demo\go_http_v2\SERVERA> docker build -it servera .     
unknown shorthand flag: 'i' in -it
See 'docker buildx build --help'.
(base) PS D:\STUDY_ALONE\GO\go_demo\go_http_v2\SERVERA> docker build -t servera .      
[+] Building 42.8s (10/10) FINISHED                                     docker:default 
 => [internal] load build definition from Dockerfile                              0.0s 
 => => transferring dockerfile: 191B                                              0.0s 
 => [internal] load .dockerignore                                                 0.0s 
 => => transferring context: 2B                                                   0.0s 
 => [internal] load metadata for docker.io/library/golang:alpine                  4.8s 
 => [auth] library/golang:pull token for registry-1.docker.io                     0.0s 
 => [1/4] FROM docker.io/library/golang:alpine@sha256:4bc6541af94a67d9dcabba982  20.2s 
 => => resolve docker.io/library/golang:alpine@sha256:4bc6541af94a67d9dcabba9826  0.0s 
 => => sha256:cc37b24bb09971feb8bf4882e861bce9db0c985a16a900 284.69kB / 284.69kB  2.4s 
 => => sha256:94517ad51c70c15adb540d431b757078be8f6214a2f1d21 67.00MB / 67.00MB  11.1s 
 => => sha256:4bc6541af94a67d9dcabba9826c36e4e9497dacf4e8755ac50 1.65kB / 1.65kB  0.0s 
 => => sha256:3380a7e42c62007b14a7285882f764255d92e933ca7b31ae18 1.16kB / 1.16kB  0.0s 
 => => sha256:ba29250af387de3f8daa10fe591b0911922513ea635082b904 6.32kB / 6.32kB  0.0s 
 => => sha256:96526aa774ef0126ad0fe9e9a95764c5fc37f409ab9e97021e 3.40MB / 3.40MB  3.2s 
 => => sha256:2087470b845b2224ab3a61dafcdf2abbf9540f77be63368c3346b8 155B / 155B  3.0s 
 => => extracting sha256:96526aa774ef0126ad0fe9e9a95764c5fc37f409ab9e97021e7b477  0.2s 
 => => extracting sha256:cc37b24bb09971feb8bf4882e861bce9db0c985a16a900adb0dc9de  0.1s 
 => => extracting sha256:94517ad51c70c15adb540d431b757078be8f6214a2f1d2181afc945  8.3s 
 => => extracting sha256:2087470b845b2224ab3a61dafcdf2abbf9540f77be63368c3346b85  0.0s 
 => [internal] load build context                                                 0.2s 
 => => transferring context: 60.10kB                                              0.2s 
 => [2/4] WORKDIR /app                                                            0.7s 
 => [3/4] COPY . .                                                                0.4s 
 => [4/4] RUN go build -o Server_A Server_A.go                                   15.3s 
 => exporting to image                                                            1.2s 
 => => exporting layers                                                           1.2s 
 => => writing image sha256:5a6d46943a1594dad3f76acd4c0da42ab9b27cf07047c78175a0  0.0s 
 => => naming to docker.io/library/servera                                        0.0s 

What's Next?
  View summary of image vulnerabilities and recommendations → docker scout quickview   
(base) PS D:\STUDY_ALONE\GO\go_demo\go_http_v2\SERVERA> docker tag servera 2228776283/go_http_server_a:v2
(base) PS D:\STUDY_ALONE\GO\go_demo\go_http_v2\SERVERA> docker push 2228776283/go_http_server_a:v2
The push refers to repository [docker.io/2228776283/go_http_server_a]
59d2f110c469: Pushed
947650eef097: Pushed
99d7e31980c9: Pushed
8e14b8a46471: Mounted from library/golang
bc295b46334c: Mounted from library/golang
f6a51e30f545: Mounted from library/golang
cc2447e1835a: Mounted from library/golang
v2: digest: sha256:40f3633ee3d599a35813ec6c438074a159d516cf173ec8efa7e60e546353d620 size: 1787
(base) PS D:\STUDY_ALONE\GO\go_demo\go_http_v2\SERVERA> 

在这里插入图片描述
然后在K8S集群的每一台需要安装这些镜像的节点上pull他们

docker pull 2228776283/go_http_server_a:v2
docker pull 2228776283/go_http_server_b:v2

四、编写deployment和service

#Servera_deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: go-http-server-a
  name: go-http-server-a
  namespace: default
spec:
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: go-http-server-a
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: go-http-server-a
    spec:
      containers:
      - name: go-http-server-a
        image: 2228776283/go_http_server_a:v2
        imagePullPolicy: IfNotPresent
        resources:
          requests:
            cpu: '20m'
            memory: '56Mi'
          limits:
            cpu: '20m'
            memory: '56Mi'
      restartPolicy: Always
      terminationGracePeriodSeconds: 30
#Serverb_deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: go-http-server-b
  name: go-http-server-b
  namespace: default
spec:
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: go-http-server-b
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: go-http-server-b
    spec:
      containers:
      - name: go-http-server-b
        image: 2228776283/go_http_server_b:v2
        imagePullPolicy: IfNotPresent
        resources:
          requests:
            cpu: '20m'
            memory: '56Mi'
          limits:
            cpu: '20m'
            memory: '56Mi'
      restartPolicy: Always
      terminationGracePeriodSeconds: 30
[root@k8s-master deployments]# vim Servera-deployment.yaml
[root@k8s-master deployments]# kubectl apply -f Servera-deployment.yaml
deployment.apps/go-http-server-a created
[root@k8s-master deployments]# vim Serverb-deployment.yaml
[root@k8s-master deployments]# kubectl apply -f Serverb-deployment.yaml
deployment.apps/go-http-server-b created

然后对这两个deployment进行以CPU使用率为指标的自动扩缩容

kubectl autoscale deploy go-http-server-a --cpu-percent=20 --min=2 --max=5
kubectl autoscale deploy go-http-server-b --cpu-percent=20 --min=2 --max=5
[root@k8s-master deployments]# kubectl get deployments
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
go-http-server-a   2/2     2            2           4m40s
go-http-server-b   2/2     2            2           4m11s
nginx-deploy       2/2     2            2           77d
[root@k8s-master deployments]# kubectl get pods
NAME                                READY   STATUS    RESTARTS         AGE
busybox                             1/1     Running   1331 (42m ago)   66d
dns-test                            1/1     Running   1 (79d ago)      79d
fluentd-lv52k                       1/1     Running   0                78d
fluentd-nlnfd                       1/1     Running   0                78d
front                               1/1     Running   56 (20h ago)     66d
go-http-server-a-7bdcf69d65-49llh   1/1     Running   0                4m46s
go-http-server-a-7bdcf69d65-sx2zw   1/1     Running   0                4m41s
go-http-server-b-547d5f74df-jqrc9   1/1     Running   0                4m11s
go-http-server-b-547d5f74df-mk4cs   1/1     Running   0                4m17s
golang                              1/1     Running   0                41d
nginx-demo                          1/1     Running   0                82d
nginx-deploy-56696fbb5-2bqrg        1/1     Running   0                77d
nginx-deploy-56696fbb5-5fg8k        1/1     Running   0                77d
web-0                               1/1     Running   0                56m
web-1                               1/1     Running   0                56m
[root@k8s-master deployments]# kubectl get hpa
NAME               REFERENCE                     TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
go-http-server-a   Deployment/go-http-server-a   <unknown>/20%   2         5         2          66d
go-http-server-b   Deployment/go-http-server-b   <unknown>/20%   2         5         2          66d
nginx-deploy       Deployment/nginx-deploy       0%/20%          2         5         2          77d

然后编写deploymenta和deploymentb的service

#servera_service.yaml
apiVersion: v1
kind: Service
metadata:
  name: servera
  labels: 
    app: go-http-server-a
spec:
  selector:
    app: go-http-server-a
  ports:
  - port: 8080
    targetPort: 8080
    name: servera
  type: NodePort
#serverb_service.yaml
apiVersion: v1
kind: Service
metadata:
  name: serverb
  labels: 
    app: go-http-server-b
spec:
  selector:
    app: go-http-server-b
  ports:
  - port: 18081
    targetPort: 18081
    name: serverb
  type: NodePort
[root@k8s-master services]# kubectl apply -f Severb-service.yaml
service/serverb created
[root@k8s-master services]# kubectl apply -f Severa-service.yaml
service/servera created
[root@k8s-master services]# curl servera:8080
curl: (6) Could not resolve host: servera; Unknown error
[root@k8s-master services]# kubectl get svc
NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)           AGE
kubernetes           ClusterIP   10.96.0.1       <none>        443/TCP           83d
nginx                ClusterIP   None            <none>        80/TCP            80d
nginx-svc            NodePort    10.101.46.34    <none>        80:30833/TCP      76d
nginx-svc-external   ClusterIP   10.107.106.21   <none>        80/TCP            75d
servera              NodePort    10.103.159.46   <none>        8080:30700/TCP    29s
serverb              NodePort    10.97.253.128   <none>        18081:31474/TCP   33s
[root@k8s-master services]# kubectl get pods -o wide
NAME                                READY   STATUS    RESTARTS         AGE   IP               NODE        NOMINATED NODE   READINESS GATES
busybox                             1/1     Running   1331 (49m ago)   66d   10.244.36.124    k8s-node1   <none>           <none>
dns-test                            1/1     Running   1 (79d ago)      79d   10.244.36.70     k8s-node1   <none>           <none>
fluentd-lv52k                       1/1     Running   0                78d   10.244.169.135   k8s-node2   <none>           <none>
fluentd-nlnfd                       1/1     Running   0                78d   10.244.36.74     k8s-node1   <none>           <none>
front                               1/1     Running   56 (21h ago)     66d   10.244.169.175   k8s-node2   <none>           <none>
go-http-server-a-7bdcf69d65-49llh   1/1     Running   0                11m   10.244.169.182   k8s-node2   <none>           <none>
go-http-server-a-7bdcf69d65-sx2zw   1/1     Running   0                11m   10.244.36.86     k8s-node1   <none>           <none>
go-http-server-b-547d5f74df-jqrc9   1/1     Running   0                11m   10.244.36.87     k8s-node1   <none>           <none>
go-http-server-b-547d5f74df-mk4cs   1/1     Running   0                11m   10.244.169.183   k8s-node2   <none>           <none>

在这里插入图片描述

在这里插入图片描述

[root@k8s-node2 hjw]# kubectl exec -it front -- sh
/home # curl http://servera:8080
this is serverA,ip: 10.244.169.182/home #
/home # curl http://servera:8080/b
msg:"Requset By: SERVERA: 10.244.36.86     Response By: 10.244.169.183     This                                                              is SERVERB.Hello!"/home #

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值