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

相關文章
相關標籤/搜索