安裝環境依賴
- docker-desktop >= 4.1.1
- kubernetes >= 1.21.5
- go >= 1.17
- protobuf >= 3.17.3
- istioctl >= 1.11.4
下載安裝 Docker Desktop ,並啟動內建的 Kubernetes 叢集。
# 安裝 Go
brew install go
# 安裝 Protobuf
brew install protobuf
# 安裝 Istio
brew install istioctl
kubectl config use-context docker-desktop
istioctl install -y
專案地址
拉取程式碼:
git clone git@github.com:jxlwqq/grpc-lb.git
cd grpc-lb
Makefile 介紹
命令 | 說明 |
---|---|
make init |
安裝 protoc-gen-go 和 protoc-gen-grpc |
make protoc |
基於 proto 檔案,生成 *_pb.go 和 *_grpc.pb.go |
make docker-build |
構建 docker 映象 |
make kube-deploy |
在叢集中部署服務 |
make kube-delete |
刪除服務 |
make istio-inject |
注入 Istio 邊車 |
具體邏輯,請檢視 Makefile 檔案。
L4 vs L7 負載均衡
所謂的四層就是基於 IP + 埠的負載均衡,而七層就是基於 URL 等應用層資訊的負載均衡; Kubernetes 內建的 Service 負載均衡基於 iptables/ipvs 實現,僅支援 L4。換句話說, Service 支援 HTTP/1.1 協議,不支援 HTTP/2 協議。
而 Envoy(Istio) 則更為全能,支援被 gRPC 請求和響應的作為路由和負載均衡底層的所有 HTTP/2 功能。
專案架構
本專案分別測試 Service 和 Envoy(Istio) 對 HTTP/RPC 負載均衡的支援情況。
- cmd/server/main.go: 服務端,同時提供 HTTP 和 RPC 服務。響應的資料為服務端容器所在的 Pod 名稱,(基於 Downward API)。
- cmd/client-http/main.go: HTTP 客戶端,透過 HTTP 方式,迴圈呼叫服務端介面,並列印返回值。
- cmd/client-grpc/main.go: gRPC 客戶端,透過 RPC 方式,迴圈遠端呼叫服務端方法,並列印返回值。
測試原理
服務端 server 在 Kubernetes 叢集中以 Deployment 的方式部署 3 個副本,3 個副本的 Pod 名稱各不相同,而 client-http 和 client-grpc 則會每秒呼叫一次服務端,並列印返回值。如果返回值中,三個 Pod 的名稱都存在,則表明正在進行有效的負載均衡,否則,則表明未進行有效的負載均衡。
測試 Service
構建映象:
make docker-build # 構建映象(構建好的映象,不 push 到遠端倉庫中)
檢視映象:
docker images ls
返回:
REPOSITORY TAG IMAGE ID CREATED SIZE
grpc-lb/client-grpc latest 95d32ead8d9b 12 seconds ago 16.6MB
grpc-lb/client-http latest dbf0341206f6 22 seconds ago 11.5MB
grpc-lb/server latest 1ef346785b2a 29 seconds ago 18.2MB
部署到叢集中:
make kube-deploy # 在叢集中部署服務
檢視 Pod:
kubectl get pods
返回:
NAME READY STATUS RESTARTS AGE
client-grpc-6c565594f4-tdf75 1/1 Running 0 2m48s
client-http-55d95c744d-f7nx4 1/1 Running 0 2m49s
server-7c4bfd74d-29c69 1/1 Running 0 2m51s
server-7c4bfd74d-4btvw 1/1 Running 0 2m51s
server-7c4bfd74d-fk8zf 1/1 Running 0 2m51s
檢視 client-http Pod 的日誌:
export CLIENT_HTTP_POD=$(kubectl get pod -l app=client-http -o jsonpath={.items..metadata.name})
kubectl logs "${CLIENT_HTTP_POD}"
返回:
#1: server-7c4bfd74d-4btvw
#2: server-7c4bfd74d-4btvw
#3: server-7c4bfd74d-29c69
#4: server-7c4bfd74d-fk8zf
#5: server-7c4bfd74d-fk8zf
#6: server-7c4bfd74d-29c69
#7: server-7c4bfd74d-fk8zf
#8: server-7c4bfd74d-4btvw
#9: server-7c4bfd74d-fk8zf
檢視 client-grpc Pod 的日誌:
export CLIENT_GRPC_POD=$(kubectl get pod -l app=client-grpc -o jsonpath={.items..metadata.name})
kubectl logs "${CLIENT_GRPC_POD}"
返回:
#1: server-7c4bfd74d-fk8zf
#2: server-7c4bfd74d-fk8zf
#3: server-7c4bfd74d-fk8zf
#4: server-7c4bfd74d-fk8zf
#5: server-7c4bfd74d-fk8zf
#6: server-7c4bfd74d-fk8zf
#7: server-7c4bfd74d-fk8zf
#8: server-7c4bfd74d-fk8zf
#9: server-7c4bfd74d-fk8zf
可以看出,HTTP 請求在進行有效負載,而 RPC 請求在進行無效負載。
測試 Envoy(Istio)
我們在叢集中已經部署了一個 Istio,但是沒有設定自動注入的命令空間,所以我們在這裡進行手動注入。
手動注入:
make istio-inject # 注入 Istio 邊車
檢視 Pod:
kubectl get pods
返回:
NAME READY STATUS RESTARTS AGE
client-grpc-7864f57779-f6blx 2/2 Running 0 17s
client-http-f8964854c-jclkd 2/2 Running 0 21s
server-7846bd6bb4-bcfws 2/2 Running 0 27s
server-7846bd6bb4-fv29s 2/2 Running 0 40s
server-7846bd6bb4-hzqj6 2/2 Running 0 34s
檢視 client-http Pod 的日誌:
export CLIENT_HTTP_POD=$(kubectl get pod -l app=client-http -o jsonpath={.items..metadata.name})
kubectl logs "${CLIENT_HTTP_POD}"
返回:
#1: server-7846bd6bb4-hzqj6
#2: server-7846bd6bb4-fv29s
#3: server-7846bd6bb4-hzqj6
#4: server-7846bd6bb4-hzqj6
#5: server-7846bd6bb4-hzqj6
#6: server-7846bd6bb4-hzqj6
#7: server-7846bd6bb4-hzqj6
#8: server-7846bd6bb4-bcfws
#9: server-7846bd6bb4-fv29s
檢視 client-grpc Pod 的日誌:
export CLIENT_GRPC_POD=$(kubectl get pod -l app=client-grpc -o jsonpath={.items..metadata.name})
kubectl logs "${CLIENT_GRPC_POD}"
返回:
#1: server-7846bd6bb4-fv29s
#2: server-7846bd6bb4-hzqj6
#3: server-7846bd6bb4-fv29s
#4: server-7846bd6bb4-bcfws
#5: server-7846bd6bb4-fv29s
#6: server-7846bd6bb4-hzqj6
#7: server-7846bd6bb4-fv29s
#8: server-7846bd6bb4-bcfws
#9: server-7846bd6bb4-fv29s
可以看出,HTTP 請求 和 RPC 請求均在進行有效負載。
清理
make kube-delete
istioctl experimental uninstall --purge
本作品採用《CC 協議》,轉載必須註明作者和本文連結