Kubernetes+Istio
微服務、SpringCloud、k8s、Istio雜談

一、微服務與SOA
“微服務”是一個名詞,沒有這個名詞之前也有“微服務”,一個朗朗上口的名詞能讓大家產生一個認知共識,這對推動一個事務的發展挺重要的,不然你叫微服務他叫小服務的大家很難集中到一個點上。
業界對微服務與SOA的區別爭論比較多大多都是在微觀上對比他們的區別什么微服務粒度更細啊、微服務沒有ESB啊、微服務通訊相比SOA采用更輕量級的協議啊等等,但是從微觀談區別本身就有悖論,
這些區別只是微服務的一種”最佳實踐“而已。我個人理解微服務與SOA靈魂上的不同是
微服務是互聯網時代的產物而SOA是系統集成的產物,微服務是對系統的打散而SOA是對系統的整合。
二、 微服務與SpringCloud
因為SpringCloud的流行很多人就把SpringCloud等同於微服務,這也沒有錯共識的人多了就是對的。准確點說SpringCloud是適合實現微服務的一套基礎框架,SpringCloud有助於訊速的落地微服務架構。SpringCloud是以Java庫的形式工作所以它的工作層面是在應用層(研發層)。
SpringCloud通過提供一籃子解決方案來應對微服務中的各種需求和通點,通過Eureka提供服務注冊與發現,Ribbon實現客戶端的負載均衡,Feign牛逼的將REST變成強類型的接口調用,Config提供方便但不靈活的配置中心,Hystrix提供熔斷方案,Zuul提供網關方案等。
優點:
1、提供較全的微服務治理全套解決方案
2、對開發人員友好(對代碼侵入強)
缺點:
1、只能java平台技術棧使用,當然提供了SideCar用於集成異構技術但是限制比較大
2、對開發人員友好(對代碼侵入強)
三、Kubernetes(k8s)
k8s並不是因為微服務而生而是因為docker而生只是天時地利人和正好趕上了微服務流行的時代,docker的特性正好特別適用於微服務,而k8s進一步對docker方便的編排。
從基礎設施方向來講k8s可以比作是IDC機房和機房工作人員,對物理服務器(docker)的存放與管理,上機架、裝系統、接網絡等等。
從微服務的角度來講,k8s通過基礎設施的方式通過邏輯抽象出service等概念提供了對微服務的另一種實現,就好比用N台電腦聯網提供了FTP服務。
優點:
1、在基礎層提供了抽象,對代碼無侵入
缺點:
1、對微服務治理比較弱,如熔斷限流等,當然這也不應該是k8s做的。
四、Istio
Istio的理論概念是Service Mesh(服務網絡),我們不必糾結於概念實際也是微服務的一種落地形式有點類似上面的SideCar模式,它的主要思想是關注點分離,即不像SpringCloud一樣交給研發來做,也不集成到k8s中產生職責混亂,Istio是通過為服務配 Agent代理來提供服務發現、負截均衡、限流、鏈路跟蹤、鑒權等微服務治理手段。
Istio開始就是與k8s結合設計的,Istio結合k8s可以牛逼的落地微服務架構。
優點:
1、關注點分離,對代碼無侵入
2、服務治理相關較全面
缺點:
1、老子學不動了
五、我理想中的微服務架構
k8s+istio:流量控制之灰度發布
通過Kubernetes+Istio的流量控制實現灰度發布,主要演示通過流量權重實現藍綠,通過http自定義頭實現金絲雀
准備環境
k8s和istio不想自己裝的話可以在雲上買個按量付費集群,用完即刪,推薦華為雲。
項目中用到的代碼
用的springboot+springcloud feign做rest強類型調用,放到github了
https://github.com/assionyang/istio-test.git
代碼結構說明
istio-service-union #聚合服務項目,用來測試調用user服務,也做為入口 |-Dockerfile #dockerfile istio-service-user #用戶服務,用來演示版本切換 |-Dockerfile #dockerfile istio-service-user-api #類庫,使用feign暴露client與dto,union服務依賴user-api k8s #k8s&istio發布文件目錄 |-config |- istio-service-union.yaml # union服務ConfigMap |- istio-service-user-v1.yaml # user服務v1版本ConfigMap |- istio-service-user-v2.yaml # user服務v2版本ConfigMap |- istio-service-union-deployment.yaml #union無狀態發布 |- istio-service-union-service.yaml # union服務 |- istio-service-gateway.yaml # ingress網關,對外暴露union |- istio-service-user-deployment-v1.yaml # user版本v1無狀態發布 |- istio-service-user-deployment-v2.yaml # user版本v2無狀態發布 |- istio-service-user-service.yaml # user服務 |- istio-service-user-virtualservice-v1.yaml # user路由到v1版 |- istio-service-user-virtualservice-v2.yaml # user路由到v2版 |- istio-service-user-virtualservice-weight.yaml # user路由流量權重 |- istio-service-user-virtualservice-jsq.yaml # user路由金絲雀
測試步驟
1)打好user、union兩個項目的docker iamge並上傳鏡像倉庫
docker build -t istio-service-union:v1 . docker tag istio-service-union:v1 swr.ap-southeast-1.myhuaweicloud.com/mk-develop/istio-service-union:v1 docker push swr.ap-southeast-1.myhuaweicloud.com/mk-develop/istio-service-union:v1 docker build -t istio-service-user:v1 . docker tag istio-service-user:v1 swr.ap-southeast-1.myhuaweicloud.com/mk-develop/istio-service-user:v1 docker push swr.ap-southeast-1.myhuaweicloud.com/mk-develop/istio-service-user:v1
2) 創建ConfigMap配置項
kubectl apply -f config/istio-service-user-v1.yaml kubectl apply -f config/istio-service-user-v2.yaml kubectl apply -f config/istio-service-union.yaml
3)發布負載、服務、目標規則、網關
kubectl apply -f istio-service-user-deployment-v1.yaml #user服務v1版負載與目標規則 kubectl apply -f istio-service-user-deployment-v2.yaml #user服務v2版負載與目標規則 kubectl apply -f istio-service-user-service.yaml #user服務 kubectl apply -f istio-service-union-deployment.yaml #union負載 kubectl apply -f istio-service-union-service.yaml #union服務 kubectl apply -f istio-service-union-gateway.yaml #union網關,ingressgateway
第一步我們發布了應用與服務,創建了默認規則,並且通過ingressgateway對外暴露了endpoint,這時候默認的目標規則是輪訓user服務的v1和v2版本,我們可以測試幾次發現變化
{"userVersion":"v1","userException":""} {"userVersion":"v2","userException":""} {"userVersion":"v1","userException":""} {"userVersion":"v2","userException":""} ……
4)創建默認路由
kubectl apply -f istio-service-union-virtualservice-v1.yaml #使用v1版本
測試訪問結果,發現全部是v1版本
{"userVersion":"v1","userException":""} {"userVersion":"v1","userException":""} {"userVersion":"v1","userException":""} {"userVersion":"v1","userException":""}
kubectl apply -f istio-service-union-virtualservice-v2.yaml #使用v2版本
測試訪問結果,發現全部是v2版本
{"userVersion":"v2","userException":""} {"userVersion":"v2","userException":""} {"userVersion":"v2","userException":""} {"userVersion":"v2","userException":""}
5)流量權重
kubectl apply -f istio-service-union-virtualservice-weight.yaml #使用流量權重路由,v1分70%流量,v2分30%流量
測試訪問結果,大致相同
{"userVersion":"v1","userException":""} {"userVersion":"v1","userException":""} {"userVersion":"v1","userException":""} {"userVersion":"v2","userException":""} {"userVersion":"v1","userException":""} {"userVersion":"v2","userException":""} {"userVersion":"v1","userException":""} {"userVersion":"v1","userException":""} {"userVersion":"v2","userException":""} {"userVersion":"v1","userException":""}
6)金絲雀發布
演示是跟據請求頭設置lab=assion來訪問v2版本,無此請求頭訪問v1版本。
注:因為我們使用的是feign,union通過feign調用user服務都不會帶上原始header的,需要做一下feign的透傳把header信息傳遞下去
kubectl apply -f istio-service-union-virtualservice-jsq.yaml #使用金絲雀發布,http header頭lab=assion訪問user v2版,不帶訪問user v1版
我們可以用postman測試一下看下效果