Go 微服務架構實戰 中篇:2- 基於 k8s 部署服務和註冊中心,驗證服務註冊和發現

Go 微服務架構實戰

本系列文章主要是針對雲原生領域微服務架構的實戰,包括網關,k8s,etcd 以及 grpc 等相關技術的應用,同時也會把服務發現與註冊,熔斷,降級,限流以及分佈式鎖等加入到系列當中作爲補充,課程的最後也會安排分佈式鏈路追蹤框架的學習,監控平臺的搭建以及灰度發佈等技術服務,所以總體來講,課程範圍涉及技術領域較廣,知識面比較寬,大家下來各取所需儘量做到熟悉和應用,之後有時間了在研究下源碼,樂哉!

上篇已經完成,大家可以看下,我這裏貼出來了,中篇從這周開始陸續爲大家產出,因爲太耗費精力,所以還望大家多多支持!

Go 微服務架構實戰目錄

  1. 微服務架構上篇

1. grpc 技術介紹

2. grpc+protobuf + 網關實戰

3. etcd 技術介紹

4. 基於 etcd 的服務發現與註冊

5. 基於 etcd 的分佈式鎖實戰

  1. 微服務架構中篇

1. k8s 架構介紹

  1. 基於 pod 和 deployment 的容器化部署 =============================

對於 k8s 來說,所有資源對象都有 yaml 文件來創建,k8s 提供一個工具kubectl來和 API server 交互,從而創建相應的資源對象。

我們的項目有一個服務端,有一個客戶端,還有一個服務發現和註冊中心 etcd。

我們原來就是裸機用 supervisor 去託管各個服務進程,比較簡單直接,現在用 k8s 嘗試去部署一下。

  1. 創建 server pod 的步驟

  1. 首先爲了讓 server 進行容器化部署,得現有 Dockerfile,我們來看看 server 的 (Dockerfile):
FROM golang AS build-env //從Docker鏡像倉庫找golang鏡像 
ADD . /go/src/app
WORKDIR /go/src/app
RUN GOOS=linux GOARCH=386 go build -mod vendor cmd/svr/svr.go //構建鏡像

FROM alpine //構建二進制鏡像

COPY --from=build-env /go/src/app/svr /usr/local/bin/svr //從golang盡享copy到二進制鏡像內

CMD [ "svr""-port""50009"] //運行服務 指定參數是端口
  1. 用 docker build 構建鏡像docker build -t k8s-grpc-demo -f ./Dockerfile .

  2. 用剛纔的鏡像創建 server 的 yaml(server.yaml):

apiVersion: apps/v1
kind: Deployment //Deployment就是管理Pod資源的對象
metadata:
  name: k8sdemo-deploy //Pod名稱
  labels:
    app: k8sdemo //Pod標籤 爲service提供負載均衡使用
spec:
  replicas: 1 //副本爲1
  selector:
    matchLabels:
      app: k8sdemo
  template:
    metadata:
      labels:
        app: k8sdemo
    spec:
      containers:
      - name: k8sdemo //容器名稱
        image: k8s-grpc-demo:latest //用剛纔生成的本地鏡像
        imagePullPolicy: Never //從本地構建
        ports:
        - containerPort: 50007 //容器端口
  1. 用 kubectl 創建 podkubectl apply -f server.yaml沒有指定 namespace,默認是在 default 空間。

  2. 創建之後看下 pod 是否起來kubectl get pod查看發現 server 的 pod 已經 running 了。

爲了多測試幾個服務,我們複製創建相同的 Dockerfile 和 server.yaml,比如 Dockerfile1 Dockerfile2 以及 server1.yaml 和 server2.yaml,這裏就不把配置粘貼出來,可以從 github 地址查看哈。

  1. 創建 client 的 pod 的步驟

  1. 創建 Dockerfile(Dockerfile3)
FROM golang AS build-env
ADD . /go/src/app
WORKDIR /go/src/app
RUN GOOS=linux GOARCH=386 go build -mod vendor cmd/cli/cli.go

FROM alpine

COPY --from=build-env /go/src/app/cli /usr/local/bin/cli

CMD [ "cli"]
  1. 構建 Dockerfiledocker build -t k8s-grpc-demo3 -f ./Dockerfile3 .

  2. 用剛纔的鏡像創建 client 的 yaml(client.yaml):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: k8sdemo-cli-deploy //客戶端pod名稱
  labels:
    app: k8sdemo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: k8sdemo
  template:
    metadata:
      labels:
        app: k8sdemo
    spec:
      containers:
      - name: k8sdemocli
        image: k8s-grpc-demo3:latest //用剛纔構建的鏡像
        imagePullPolicy: Never
        ports:
        - containerPort: 50010
  1. 用 kubectl 創建 podkubectl apply -f client.yaml沒有指定 namespace,默認是在 default 空間。

  2. 創建之後看下 pod 是否起來kubectl get pod查看發現 client 的 pod 已經 running 了。

  3. 創建 etcd 的 pod 的步驟


因爲 etcd 鏡像我們用 Docker 官網裏面的,所以不用自己構建了,這裏直接把創建 etcd 的 pod 的 yaml 貼出來。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: etcd3 //etcd名稱
  labels:
    name: etcd3
spec:
  replicas: 1
  selector:
    matchLabels:
      app: etcd3
  template:
    metadata:
      labels:
        app: etcd3
    spec:
      containers:
        - name: etcd3 //容器名稱
          image: quay.io/coreos/etcd:latest //etcd鏡像
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - mountPath: /data //數據存儲掛載路徑
              name: etcd-data
          env:
            - name: host_ip
              valueFrom:
                fieldRef:
                  fieldPath: status.podIP
          command: ["/bin/sh","-c"]
          args: //啓動etcd
            - /usr/local/bin/etcd //etcd的可執行文件
              --name etcd3 //etcd集羣的名稱
              --initial-advertise-peer-urls http://0.0.0.0:2380
              --listen-peer-urls http://0.0.0.0:2380
              --listen-client-urls http://0.0.0.0:2379
              --advertise-client-urls http://0.0.0.0:2379
              --initial-cluster-token etcd-cluster-1
              --initial-cluster etcd3=http://0.0.0.0:2380
              --initial-cluster-state new
              --data-dir=/data


      volumes:
        - name: etcd-data
          emptyDir: {} //當前容器作爲存儲路徑

然後用 kubectl 命令直接創建 pod

kubectl apply -f etc.yaml

kubectl get pod查看發現 etcd 的 pod 是 running 了。

但是有 pod 不一定有對內提供服註冊和發現能力,得需要 service 對內 pod 提供服務,因此創建 etcd 的 service 如下:

apiVersion: v1
kind: Service
metadata:
  name: etcd3 //service的名稱 服務註冊和發現的時候使用 很重要
spec:
  ports:
    - name: client
      port: 2379 //service對內pod的client訪問端口
      targetPort: 2379
    - name: etcd3
      port: 2380 //service對內pod的server訪問端口
      targetPort: 2380
  selector:
    app: etcd3 //找到需要關聯的etcd pod 即上面創建的etcd pod

我們看下是否創建成功:bingo。至此服務,客戶端以及以及 etcd 的服務註冊和發現中心部署好了。

接下來做點小改動,就可以實現服務註冊和發現了。

  1. 服務註冊

因爲我們的 pod 也是有 ip 的,所以服務註冊之前得先獲取 pod 的 ip。代碼如下:

//獲取本地eth0 IP 大家下來在源碼中可以看到實現哈
func GetLocalIP() string

然後有兩個地方需要修改:

  1. 註冊中心的地址 (etcd address) 從原來的 localhost 改爲 http://etcd3:2379,至於爲什麼,我可以做個簡單介紹,因爲不同 pod 之間 localhost 是不通的,localhost 只能在同一個 Pod 中的容器之間相互通信,不同 pod 是沒有辦法通信的。所以需要通信的 pod 必須通過 etcd 的 svc 名稱去訪問,k8s 集羣內提供了相關 dns 自動會解析到 svc ip 的,所以 pod 就可以訪問 etcd 註冊中心。

  2. 把原來服務默認監聽的 localhost 改爲從本地獲取 ip

1,2 修改代碼如下:

  1. 客戶端發現

客戶端也需要修改註冊中心地址:

  1. 驗證

等以上修改完成之後,我們還需要經歷上述的重新構建步驟和部署步驟,因爲代碼改動了哦。

我們重新部署完成之後,在最後啓動客戶端的時候發現日誌中有了多個服務端的請求,而且是 RR 輪循返回的響應,我們可以看下客戶端和服務的 pod 列表:

客戶端日誌如下:

至此我們基於 k8s 的服務部署和服務註冊中心就搭建起來了,後續爲大家帶來故障轉移,滾動更新以及擴縮容等內容,歡迎大家關注,分享和點贊。

github 地址:

https://github.com/guojiangli/k8s-grpc-demo

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/eIkYx7UvXrNN1nsioduubg