Go 微服務架構實戰 中篇:2- 基於 k8s 部署服務和註冊中心,驗證服務註冊和發現
Go 微服務架構實戰
本系列文章主要是針對雲原生領域微服務架構的實戰,包括網關,k8s,etcd 以及 grpc 等相關技術的應用,同時也會把服務發現與註冊,熔斷,降級,限流以及分佈式鎖等加入到系列當中作爲補充,課程的最後也會安排分佈式鏈路追蹤框架的學習,監控平臺的搭建以及灰度發佈等技術服務,所以總體來講,課程範圍涉及技術領域較廣,知識面比較寬,大家下來各取所需儘量做到熟悉和應用,之後有時間了在研究下源碼,樂哉!
上篇已經完成,大家可以看下,我這裏貼出來了,中篇從這周開始陸續爲大家產出,因爲太耗費精力,所以還望大家多多支持!
- 微服務架構上篇
1. grpc 技術介紹
2. grpc+protobuf + 網關實戰
3. etcd 技術介紹
4. 基於 etcd 的服務發現與註冊
5. 基於 etcd 的分佈式鎖實戰
- 微服務架構中篇
- 基於 pod 和 deployment 的容器化部署 =============================
對於 k8s 來說,所有資源對象都有 yaml 文件來創建,k8s 提供一個工具kubectl
來和 API server 交互,從而創建相應的資源對象。
我們的項目有一個服務端,有一個客戶端,還有一個服務發現和註冊中心 etcd。
我們原來就是裸機用 supervisor 去託管各個服務進程,比較簡單直接,現在用 k8s 嘗試去部署一下。
- 創建 server pod 的步驟
- 首先爲了讓 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"] //運行服務 指定參數是端口
-
用 docker build 構建鏡像
docker build -t k8s-grpc-demo -f ./Dockerfile .
-
用剛纔的鏡像創建 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 //容器端口
-
用 kubectl 創建 pod
kubectl apply -f server.yaml
沒有指定 namespace,默認是在 default 空間。 -
創建之後看下 pod 是否起來
kubectl get pod
查看發現 server 的 pod 已經 running 了。
爲了多測試幾個服務,我們複製創建相同的 Dockerfile 和 server.yaml,比如 Dockerfile1 Dockerfile2 以及 server1.yaml 和 server2.yaml,這裏就不把配置粘貼出來,可以從 github 地址查看哈。
- 創建 client 的 pod 的步驟
- 創建 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"]
-
構建 Dockerfile
docker build -t k8s-grpc-demo3 -f ./Dockerfile3 .
-
用剛纔的鏡像創建 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
-
用 kubectl 創建 pod
kubectl apply -f client.yaml
沒有指定 namespace,默認是在 default 空間。 -
創建之後看下 pod 是否起來
kubectl get pod
查看發現 client 的 pod 已經 running 了。 -
創建 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
查看
但是有 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
我們看下是否創建成功:
接下來做點小改動,就可以實現服務註冊和發現了。
- 服務註冊
因爲我們的 pod 也是有 ip 的,所以服務註冊之前得先獲取 pod 的 ip。代碼如下:
//獲取本地eth0 IP 大家下來在源碼中可以看到實現哈
func GetLocalIP() string
然後有兩個地方需要修改:
-
註冊中心的地址 (etcd address) 從原來的 localhost 改爲 http://etcd3:2379,至於爲什麼,我可以做個簡單介紹,因爲不同 pod 之間 localhost 是不通的,localhost 只能在同一個 Pod 中的容器之間相互通信,不同 pod 是沒有辦法通信的。所以需要通信的 pod 必須通過 etcd 的 svc 名稱去訪問,k8s 集羣內提供了相關 dns 自動會解析到 svc ip 的,所以 pod 就可以訪問 etcd 註冊中心。
-
把原來服務默認監聽的 localhost 改爲從本地獲取 ip
1,2 修改代碼如下:
- 客戶端發現
客戶端也需要修改註冊中心地址:
- 驗證
等以上修改完成之後,我們還需要經歷上述的重新構建步驟和部署步驟,因爲代碼改動了哦。
我們重新部署完成之後,在最後啓動客戶端的時候發現日誌中有了多個服務端的請求,而且是 RR 輪循返回的響應,我們可以看下客戶端和服務的 pod 列表:
客戶端日誌如下:
至此我們基於 k8s 的服務部署和服務註冊中心就搭建起來了,後續爲大家帶來故障轉移,滾動更新以及擴縮容等內容,歡迎大家關注,分享和點贊。
github 地址:
https://github.com/guojiangli/k8s-grpc-demo
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/eIkYx7UvXrNN1nsioduubg