Go Grpc部署到 k8s

网上关于grpc在k8s上的负载均衡不少,我这里就不在重复了,直接看代码吧: 个人grpc客户端和服务段都是用beego实现的,【我这里比较偷懒,直接把源码放到 k8s的一个master上】,首先须要说明如下个人k8s版本html

  Server:

协议在protos\hello.proto以下:node

syntax = "proto3";
option go_package = "./;proto";  
package protos;

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) ;
}
 
message HelloRequest {
  string name = 1;
}
 
message HelloReply {
  string message = 1;
}

而后到路径下 执行 protoc --go_out=plugins=grpc:./ ./hello.protolinux

服务端我为了省事直接在main.go文件添加方法:nginx

package main

import (
    "context"
    "fmt"
    pb "grpcdemo/protos"
    _ "grpcdemo/routers"
    "net"

    "github.com/astaxie/beego"
    "google.golang.org/grpc"
    "google.golang.org/grpc/reflection"
)

func main() {
    go GPRCServer()
    beego.Run()
}

type server struct{}

func NewServer() *server {
    return &server{}
}

func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
    msg := "Resuest By:" + in.Name + " Response By :" + LocalIp()
    fmt.Println("GRPC Send: ", msg)
    return &pb.HelloReply{Message: msg}, nil
}

func GPRCServer() {
    // 监听本地端口
    listener, err := net.Listen("tcp", ":9090")
    if err != nil {
        return
    }
    s := grpc.NewServer()                  // 建立GRPC
    pb.RegisterGreeterServer(s, &server{}) // 在GRPC服务端注册服务

    reflection.Register(s)
    fmt.Println("grpc serve 9090")
    err = s.Serve(listener)
    if err != nil {
        fmt.Println(fmt.Sprintf("failed to serve: %v", err))
    }

}

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
}

服务的其余几个文件以下:Dockerfilegit

FROM golang:1.15.6

RUN mkdir -p /app
RUN mkdir -p /app/conf
RUN mkdir -p /app/logs

WORKDIR /app
 
ADD main /app/main

EXPOSE 8080
EXPOSE 9090
 
CMD ["./main"]

build.shgithub

#!/bin/bash
#cd $WORKSPACE
export GOPROXY=https://goproxy.io
 
 #根据 go.mod 文件来处理依赖关系。
go mod tidy
 
# linux环境编译
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o main
 
# 构建docker镜像,项目中须要在当前目录下有dockerfile,不然构建失败

docker build -t grpcserver .
docker tag  grpcserver 192.168.100.30:8080/go/grpcserver:2021

docker login -u admin -p '123456' 192.168.100.30:8080
docker push 192.168.100.30:8080/go/grpcserver
 
docker rmi  grpcserver
docker rmi 192.168.100.30:8080/go/grpcserver:2021

deploy.yamlgolang

apiVersion: apps/v1
kind: Deployment
metadata:
  name: grpcserver
  namespace: go
  labels:
    name: grpcserver
spec:
  replicas: 3
  minReadySeconds: 10 
  selector:
    matchLabels:
      name: grpcserver
  template:
    metadata:
      labels:
        name: grpcserver
    spec:
      imagePullSecrets:
      - name: regsecret
      containers:
      - name: grpcserver
        image: 192.168.100.30:8080/go/grpcserver:2021
        ports:
        - containerPort: 8080
        - containerPort: 9090
        imagePullPolicy: Always

---

apiVersion: v1 
kind: Service 
metadata:
  name: grpcserver
  namespace: go 
spec:
  ports:
    - port: 8080 
      targetPort: 8080 
      name: httpserver
      protocol: TCP
    - port: 9090 
      targetPort: 9090 
      name: grpcserver
      protocol: TCP
  selector:
    name: grpcserver

---

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  namespace: go
  name: grpcserver
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
spec:
  rules:
  - host: rpc.ingress.local
    http:
      paths:
      - backend:
          serviceName: grpcserver
          servicePort: 9090
  tls:
  - secretName: grpcs-secret
    hosts:
      - rpc.ingress.local

Client:

调用主要在controllers/default.godocker

package controllers

import (
    "context"
    "fmt"
    pb "grpcclient/protos"
    "net"

    "github.com/astaxie/beego"
    "google.golang.org/grpc"
)

type MainController struct {
    beego.Controller
}

func (c *MainController) Get() {
    conn, err := grpc.Dial("grpcserver:9090", grpc.WithInsecure())
    if err != nil {
        msg := fmt.Sprintf("grpc client did not connect: %v\r\n", err)

        c.Ctx.WriteString(msg)
        return
    }
    defer conn.Close()

    client := pb.NewGreeterClient(conn)
    req := pb.HelloRequest{Name: "gavin_" + LocalIp()}

    res, err := client.SayHello(context.Background(), &req)
    if err != nil {
        msg := fmt.Sprintf("grpc client  client.SayHello  has err:%v\r\n", err)
        c.Ctx.WriteString(msg)
        return
    }

    c.Ctx.WriteString("GRPC Clinet Received:" + res.Message)
}

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
}

其余相关文件:Dockerfilevim

FROM golang:1.15.6

RUN mkdir -p /app
RUN mkdir -p /app/conf
RUN mkdir -p /app/logs

WORKDIR /app
 
ADD main /app/main

EXPOSE 8080
 
CMD ["./main"]

build.shapi

#!/bin/bash
#cd $WORKSPACE

export GOPROXY=https://goproxy.io
 
 #根据 go.mod 文件来处理依赖关系。
go mod tidy
 
# linux环境编译
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o main
 
# 构建docker镜像,项目中须要在当前目录下有dockerfile,不然构建失败

docker build -t grpcclient .
docker tag  grpcclient 192.168.100.30:8080/go/grpcclient:2021

docker login -u admin -p '123456' 192.168.100.30:8080
docker push 192.168.100.30:8080/go/grpcclient
 
docker rmi  grpcclient
docker rmi 192.168.100.30:8080/go/grpcclient:2021

deploy.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: grpcclient
  namespace: go
  labels:
    name: grpcclient
spec:
  replicas: 3
  minReadySeconds: 10 
  selector:
    matchLabels:
      name: grpcclient
  template:
    metadata:
      labels:
        name: grpcclient
    spec:
      imagePullSecrets:
      - name: regsecret
      containers:
      - name: grpcserver
        image: 192.168.100.30:8080/go/grpcclient:2021
        ports:
        - containerPort: 8080
        - containerPort: 9090
        imagePullPolicy: Always

---

apiVersion: v1 
kind: Service 
metadata:
  name: grpcclient
  namespace: go 
spec:
  type: ClusterIP
  ports:
    - port: 8080 
      targetPort: 8080 
      protocol: TCP
  selector:
    name: grpcclient

Deploy

准备阶段:

#安装grpcurl
wget https://github.com/fullstorydev/grpcurl/releases/download/v1.8.0/grpcurl_1.8.0_linux_x86_64.tar.gz
tar -xvf  grpcurl_1.8.0_linux_x86_64.tar.gz
chmod +x grpcurl
#我本地是有共的环境
mv grpcurl /usr/local/go/bin 

#证书
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout grpcs.key -out grpcs.crt -subj "/CN=*.ingress.local/O=ingress.local"
ls
grpcs.crt  grpcs.key

kubectl create secret tls grpcs-secret --key grpcs.key --cert grpcs.crt
#kubectl delete secret  grpcs-secret

部署都是进入目录 执行build.sh 而后 kubectl apply -f deploy.yaml

1  clusterIP 有值的结果以下:

2.grpc client 长链接

如今咱们修改程序 让grpc client用长链接 在controller下面新建init.go文件

package controllers

import (
    "fmt"
    pb "grpcclient/protos"

    "github.com/astaxie/beego/logs"
    "google.golang.org/grpc"
)

var GrpcClient pb.GreeterClient

func init() {
    conn, err := grpc.Dial("grpcserver:9090", grpc.WithInsecure())
    if err != nil {
        msg := fmt.Sprintf("grpc client did not connect: %v\r\n", err)
        logs.Error(msg)
    }
    GrpcClient = pb.NewGreeterClient(conn)
}

default.go 以下:

package controllers

import (
    "context"
    "fmt"
    pb "grpcclient/protos"
    "net"

    "github.com/astaxie/beego"
)

type MainController struct {
    beego.Controller
}

func (c *MainController) Get() {

    client := GrpcClient
    req := pb.HelloRequest{Name: "gavin_" + LocalIp()}

    res, err := client.SayHello(context.Background(), &req)
    if err != nil {
        msg := fmt.Sprintf("grpc client  client.SayHello  has err:%v\r\n", err)
        c.Ctx.WriteString(msg)
        return
    }

    c.Ctx.WriteString("GRPC Clinet Received:" + res.Message)
}

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
}

运行结果:

 

 3  clusterIP=None有值的结果以下:

4.Ingress 以下:

用 kubectl get ingress -n go  查看信息  而后 修改  vim /etc/hosts

kubectl get ingress -n go  
grpcurl -insecure rpc.ingress.local:443 list
grpcurl -insecure -d '{"name": "gRPC"}' rpc.ingress.local:443 protos.Greeter.SayHello

个人grpc客服端没有跑通【go在新版本的tsl有些区别,能够参考 go学习笔记 Windows Go 1.15 以上版本的 GRPC 通讯【自签CA和双向认证】 】,用其余域名也出现过其余错误【不知道是否是ingress的问题】

5. istio

安装:

#https://istio.io/latest/docs/setup/getting-started/
curl -L https://istio.io/downloadIstio | sh -
#curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.9.2 TARGET_ARCH=x86_64 sh -
cd istio-1.9.2
istioctl install --set profile=demo -y

为指定namespace注入istio的sidecar功能
# kubectl label namespace default istio-injection=enable
禁止注入istio的sidecar功能
# kubectl label namespace default istio-injection-
查看istio的sidecar的信息
kubectl get namespace -L istio-injection
#kubectl apply -f samples/addons
#kubectl get svc -n istio-system

科普一下:

Istio 提供一种简单的方式来为已部署的服务创建网络,该网络具备负载均衡、服务间认证、监控等功能,只须要对服务的代码进行一点或不须要作任何改动。想要让服务支持 Istio,只须要在您的环境中部署一个特殊的 sidecar 代理,使用 Istio 控制平面功能配置和管理代理,拦截微服务之间的全部网络通讯:

  • HTTP、gRPC、WebSocket 和 TCP 流量的自动负载均衡。
  • 经过丰富的路由规则、重试、故障转移和故障注入,能够对流量行为进行细粒度控制。
  • 可插入的策略层和配置 API,支持访问控制、速率限制和配额。
  • 对出入集群入口和出口中全部流量的自动度量指标、日志记录和追踪。
  • 经过强大的基于身份的验证和受权,在集群中实现安全的服务间通讯。

Istio 旨在实现可扩展性,知足各类部署需求

stio简单的几个概念

在Service Mesh中,咱们须要了解Data Plane和Control Plane两个概念:

  1. Data Plane:做用是处理网格内服务间的通讯,并完成服务发现、负载均衡、流量管理、健康检查等功能;
  2. Control Plane:做用是管理和配置智能代理用于路由流量,同时配置Mixers来应用策略、收集指标。

Istio核心组件

  1. Envoy:Istio 使用 Envoy调解服务网格中全部服务的入站和出站流量。属于数据平面。
  2. Mixer:负责在服务网格上执行访问控制和使用策略,以及收集从Envoy和其余服务自动监控到的数据。
  3. Pilot:为 Envoy sidecar 提供服务发现功能,为智能路由(例如 A/B 测试、金丝雀部署等)和弹性(超时、重试、熔断器等)提供流量管理功能。属于控制平面。
  4. Citadel:提供访问控制和用户身份认证功能。

Istio可视化管理组件

  1. Vistio:用于近乎实时地监控应用程序和集群之间的网络流量。
  2. Kiali:提供可视化服务网格拓扑、断路器和请求率等功能。Kiali还包括 Jaeger Tracing,能够提供开箱即用的分布式跟踪功能。
  3. jaeger:用于展现istio微服务调用链关系,以及微服务工做状态监测。注意,在生产环境中,应使用Elasticsearch或cassandra持久化存储jaeger数据。

参考:

http://www.kailing.pub/article/index/arcid/327.html

https://blog.csdn.net/weixin_38166686/article/details/102452691

https://blog.csdn.net/weixin_33782386/article/details/89729502

相关文章
相关标签/搜索