一、配置集群
首先配置集群,具体配置看我的这篇文章: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 #