SpringBoot、Kubernetes和Istio微服務網格演示原始碼
如果單純使用kubernetes的pod部署Spring微服務,K8s的負載平衡以及代理設定和你微服務應用之間不是非常的智慧銜接,。無論如何,部署新的應用程式版本pod需要更加軟化的方法。以下是典型的需求:
- 智慧調撥流量,在部署新的應用程式版本容器時,您經常需要以某種比例(即金絲雀Canary測試)分割新容器和當前生產之間的流量
- 藍綠部署,在部署新的應用程式版本pod時,假設您需要藍色/綠色部署
- 在部署新的應用程式版本pod時,讓我們說只有HTTP cookie識別的一些使用者可以測試新版本
所有這些問題都可以透過名為istio的神奇工具來解決。
Istio安裝
首先是在Istio安裝之前,需要以至少4GB的記憶體啟動 Minikube ,否則將無法啟動pilot ,閱讀stackoverflow討論;第二個重要的是始終使用Istio Custom Resources Definitions開始安裝:
$ kubectl apply -f <ISTIO_INSTALL_HOME> /install/kubernetes/helm/istio/templates/crds.yaml |
這是安裝後所需的輸出:
kubernetes tomask79$ kubectl get pods -n istio-system NAME READY STATUS RESTARTS AGE grafana-59b8896965-6jcb8 1/1 Running 4 7d istio-citadel-856f994c58-jwdp2 1/1 Running 4 7d istio-cleanup-secrets-glmrz 0/1 Completed 0 7d istio-egressgateway-5649fcf57-5b885 1/1 Running 4 7d istio-galley-7665f65c9c-89wsz 1/1 Running 13 7d istio-grafana-post-install-z9v7z 0/1 Completed 0 7d istio-ingressgateway-6755b9bbf6-qrvq8 1/1 Running 4 7d istio-pilot-698959c67b-xpqnj 2/2 Running 11 7d istio-policy-6fcb6d655f-8mkf4 2/2 Running 18 7d istio-security-post-install-jn4sr 0/1 Completed 0 7d istio-sidecar-injector-768c79f7bf-p8xqr 1/1 Running 4 7d istio-telemetry-664d896cf5-zc8sr 2/2 Running 17 7d istio-tracing-6b994895fd-wpc2c 1/1 Running 7 7d prometheus-76b7745b64-hqnrq 1/1 Running 4 7d servicegraph-5c4485945b-jql54 1/1 Running 12 7d |
演示示例
在向您展示Istio流量管理魔術之前,我們將介紹第一個非常簡單的Spring Boot MVC應用程式,我們將在兩個版本中部署到kubernetes。
版本1:
@RestController public class ControllerV1 { @GetMapping(path = "/service") public String getResult() { return "Hello I'm V1!"; } } |
下面是這個版本的k8s的部署,標記mvc-service開始部分:
(mvc-1/istio/kubernetes-deploy/v1-deploy.yaml)
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: mvc-service spec: replicas: 1 template: metadata: labels: app: mvc-service version: v1 spec: containers: - name: mvc-service image: service-v1:0.0.1-SNAPSHOT imagePullPolicy: IfNotPresent ports: - containerPort: 8080 |
版本2:
@RestController public class ControllerV2 { @GetMapping(path = "/service") public String getResult() { return "Hello i'm V2!"; } } |
下面是這個版本的k8s的部署,標記mvc-service開始部分:
(mvc-2/istio/kubernetes-deploy/v2-deploy.yaml)
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: mvc-service-v2 spec: replicas: 1 template: metadata: labels: app: mvc-service version: v2 spec: containers: - name: mvc-service image: service-v2:0.0.1-SNAPSHOT imagePullPolicy: IfNotPresent ports: - containerPort: 8080 |
我們在標有“mvc-service”字串的pod中有兩個版本的應用程式。因此kubernetes服務還應該使用標籤'mvc-service'來定位pod後端:(mvc-1/istio/kubernetes-deploy/v1-deploy.yaml)
apiVersion: v1 kind: Service metadata: name: mvc-service labels: app: mvc-service spec: type: NodePort ports: - port: 8080 name: http selector: app: mvc-service |
使用Istio支援部署到Kubernetes
好的,我們已經準備好了kubernetes清單,但還沒有部署任何東西!為了能夠使用Istio流量管理,您需要向您的pod 注入sidecar代理。如果沒有istio邊車,你就不會形成服務網格。你有兩個選擇:
我選擇了第一個選項並將邊車sidecar設定注入到這樣的清單中:
istioctl kube-inject -f v1-deploy.yaml >> v1-deploy-istio.yaml |
對於第二個版本(資料夾mvc-2 / istio / kubernetes-deploy)同樣這麼做:
istioctl kube-inject -f v2-deploy.yaml >> v2-deploy-istio.yaml |
現在部署生成的kubernetes清單注入istio-sidecar:
kubectl apply -f v1-deploy-istio.yaml |
然後部署第二個版本:
kubectl apply -f v2-deploy-istio.yaml |
這是部署後所需的輸出:
kubectl get pods NAME READY STATUS RESTARTS AGE mvc-service-76ffb4bc9f-sdrtn 2/2 Running 10 10d mvc-service-v2-59ff7d6886-v87jt 2/2 Running 10 10d |
每個POD都有兩個容器,因為它執行app容器和istio代理邊車容器。要檢視為pod啟動的邊車代理,只需鍵入:
kubernetes - deploy tomask79 $ kubectl describe pod mvc - service - 76 ffb4bc9f - sdrtn |
檢查事件:
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal SandboxChanged 8m41s kubelet, minikube Pod sandbox changed, it will be killed and re-created. Normal Pulled 8m37s kubelet, minikube Container image "docker.io/istio/proxy_init:1.0.5" already present on machine Normal Created 8m35s kubelet, minikube Created container Normal Started 8m34s kubelet, minikube Started container Normal Pulled 8m34s kubelet, minikube Container image "service-v1:0.0.1-SNAPSHOT" already present on machine Normal Created 8m33s kubelet, minikube Created container Normal Started 8m33s kubelet, minikube Started container Normal Pulled 8m33s kubelet, minikube Container image "docker.io/istio/proxyv2:1.0.5" already present on machine Normal Created 8m33s kubelet, minikube Created container Normal Started 8m33s kubelet, minikube Started container |
Istio形成服務網格
好的,部署了兩個版本的Spring Boot MVC應用程式。現在我打賭你對像VirtualService,DestinationRule這樣的Istio物件感到困惑......什麼時候使用它們,你還在Kubernetes服務嗎?在stackoverflow有一個非常好的討論,這對我來說非常有用。簡而言之:
在我們的Spring MVC演示中,我們獲得了名為mvc-service的kubernetes 服務。這將是DestinationRule 物件中的主機引數,因為這是提供目標服務的後端。現在我們的mvc-service提供了兩個版本的Spring MVC應用程式v1和v2 ,它們將構成服務網格,因此DestinationRule看起來像:
apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: mvc-service spec: host: mvc-service subsets: - name: v1 labels: version: v1 - name: v2 labels: version: v2 |
在我們的演示中,透過kubectl部署它:
spring-kubernetes-istio tomask79$ kubectl apply -f istio-destionation-rule.yaml |
現在VirtualService進入遊戲:
VirtualService定義了一組要在主機被定址時應用的流量路由規則。每個路由規則定義特定協議的流量的匹配標準。如果流量匹配,則將其傳送到登錄檔中定義的命名目標服務(或其子集 /版本)。
換句話說,您首先部署K8s部署和服務。然後,透過Istio DestionRule定義微服務的網路,然後透過VirtualService設定HTTP路由規則。
用Istio進行金絲雀測試
因此,假設我們的演示SpringMVC應用程式的第二個版本(在服務網格中,子集v2)不夠穩定,無法處理滿負載,因此我們只將20%的流量路由到它。
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: service-gateway spec: hosts: - "*" gateways: - service-gateway http: - match: - uri: exact: /service route: - destination: host: mvc-service subset: v1 weight: 80 - destination: host: mvc-service subset: v2 weight: 20 |
這真的很容易。作為最後一步,我們需要公開服務閘道器,即Istio-Ingress閘道器 ,它從服務網格外部獲取流量並將其轉發到該閘道器。
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: service-gateway spec: selector: istio: ingressgateway # use istio default controller servers: - port: number: 80 name: http protocol: HTTP hosts: - "*" |
在這個repo中提到的閘道器和虛擬服務都在istio-gateway.yaml檔案中,所以讓我們部署它:
spring-kubernetes-istio tomask79$ kubectl apply -f istio-gateway.yaml |
好的,這是測試之前所需的輸出,服務網格在前:
istioctl get destinationrules -o yaml apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: annotations: kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"networking.istio.io/v1alpha3","kind":"DestinationRule","metadata":{"annotations":{},"name":"mvc-service","namespace":"default"},"spec":{"host":"mvc-service","subsets":[{"labels":{"version":"v1"},"name":"v1"},{"labels":{"version":"v2"},"name":"v2"}]}} creationTimestamp: null name: mvc-service namespace: default resourceVersion: "5722" spec: host: mvc-service subsets: - labels: version: v1 name: v1 - labels: version: v2 name: v2 --- |
然後是virtualservices:
istioctl get virtualservices -o short VIRTUAL-SERVICE NAME GATEWAYS HOSTS HTTP TCP NAMESPACE AGE mvc-service mvc-service 1 0 default 11d service-gateway service-gateway * 1 0 default 11d |
金絲雀測試
我們需要獲取istio-ingress閘道器和埠的IP地址。
kubectl get service istio-ingressgateway -n istio-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE istio-ingressgateway LoadBalancer 10.111.15.19 <pending> 80:31380/TCP,443:31390/TCP,31400:31400/TCP,15011:32464/TCP,8060:30626/TCP,853:30365/TCP,15030:31121/TCP,15031:31359/TCP 13d |
istio-ingress文件如是說:
如果設定了EXTERNAL-IP值,則您的環境具有可 用於入口閘道器的外部負載平衡器。如果EXTERNAL-IP值為<none>(或永久<pending>),則您的環境 不會為入口閘道器提供外部負載平衡器。在這種情況下,您可以 使用service s節點埠訪問閘道器。
這意味著呼叫我們的金絲雀版本,我們將繼續:
minikube ip 192.168.99.110 |
現在終於呼叫了後臺,請注意文件中指出的nodeport埠:
10個點選中:2個進入V2版本,8個點選進入V1。
tomask79:spring-kubernetes-istio tomask79$ curl http://192.168.99.110:31380/service Hello I'm V1!tomask79:spring-kubernetes-istio tomask79$ curl http://192.168.99.110:31380/service Hello I'm V1!tomask79:spring-kubernetes-istio tomask79$ curl http://192.168.99.110:31380/service Hello I'm V1!tomask79:spring-kubernetes-istio tomask79$ curl http://192.168.99.110:31380/service Hello i'm V2!tomask79:spring-kubernetes-istio tomask79$ curl http://192.168.99.110:31380/service Hello I'm V1!tomask79:spring-kubernetes-istio tomask79$ curl http://192.168.99.110:31380/service Hello I'm V1!tomask79:spring-kubernetes-istio tomask79$ curl http://192.168.99.110:31380/service Hello I'm V1!tomask79:spring-kubernetes-istio tomask79$ curl http://192.168.99.110:31380/service Hello I'm V1!tomask79:spring-kubernetes-istio tomask79$ curl http://192.168.99.110:31380/service Hello i'm V2!tomask79:spring-kubernetes-istio tomask79$ curl http://192.168.99.110:31380/service Hello I'm V1!tomask79:spring-kubernetes-istio tomask79$ |
使用Istio進行藍/綠部署
現在讓我們說我們的應用程式的V2版本足夠穩定,我們可以將100%的流量路由到它。要使用Istio實現這一點,我們將更改VirtualService中的規則:
將istio-gateway.yaml檔案中的VirtualService修改為:
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: service-gateway spec: hosts: - "*" gateways: - service-gateway http: - match: - uri: exact: /service route: - destination: host: mvc-service subset: v2 |
重新部署:
tomask79:spring-kubernetes-istio tomask79$ kubectl apply -f istio-gateway.yaml gateway.networking.istio.io/service-gateway unchanged virtualservice.networking.istio.io/service-gateway configured |
測試藍/綠部署
現在V2版本應該成為我們的生產版本並處理100%的流量:
tomask79:spring-kubernetes-istio tomask79$ curl http://192.168.99.110:31380/service Hello i'm V2!tomask79:spring-kubernetes-istio tomask79$ curl http://192.168.99.110:31380/service Hello i'm V2!tomask79:spring-kubernetes-istio tomask79$ curl http://192.168.99.110:31380/service Hello i'm V2!tomask79:spring-kubernetes-istio tomask79$ curl http://192.168.99.110:31380/service Hello i'm V2!tomask79:spring-kubernetes-istio tomask79$ curl http://192.168.99.110:31380/service Hello i'm V2!tomask79:spring-kubernetes-istio tomask79$ curl http://192.168.99.110:31380/service Hello i'm V2!tomask79:spring-kubernetes-istio tomask79$ curl http://192.168.99.110:31380/service Hello i'm V2!tomask79:spring-kubernetes-istio tomask79$ curl http://192.168.99.110:31380/service Hello i'm V2!tomask79:spring-kubernetes-istio tomask79$ curl http://192.168.99.110:31380/service Hello i'm V2!tomask79:spring-kubernetes-istio tomask79$ curl http://192.168.99.110:31380/service Hello i'm V2!tomask79:spring-kubernetes-istio tomask79$ |
總結
Istio看起來對我來說是超級強大的工具。但它的學習曲線有點長。此外,他們還在配置模型之間進行了重大更改。無論如何,他們支援粘性會話甚至websockets。例如,對於我在EmbedIT中使用的系統,這是兩個“必須擁有”的東西。像istio這樣的另一個類似工具是Linkerd。你也可以看一下:)
相關文章
- 【連載】微服務網格Istio(一)微服務
- Kubernetes,Istio和Java MicroProfile微服務雲原生案例 - heidloffJava微服務
- Istio旨在成為容器化微服務的網格管道微服務
- 服務網格Istio、Linkerd和Cilium效能比較
- 服務網格(Envoy+Istio)
- Istio 1.2服務網格釋出
- 為微服務構建服務網格的Istio自身卻走向微服務的反面單體架構 – Christian Posta微服務架構
- spring cloud springboot mybatis 分散式 微服務 架構原始碼CloudSpring BootMyBatis分散式微服務架構原始碼
- 微服務2.0時代:Spring Cloud Netflix與 Kubernetes&Istio比較微服務SpringCloud
- servicemesher/istio-handbook:服務網格Istio中文思維導圖
- dotnet core微服務框架Jimu ~部署和呼叫演示微服務框架
- 服務網格大比拼:Istio、Linkerd、Linkerd2和Consul
- 5分鐘安裝Kubernetes+帶你輕鬆安裝istio服務網格指南
- 服務網格istio概念應知應會
- hystrix對比服務網格istio的destinationrule
- 使用Istio服務網格實現流量映象
- 服務網格大戰,再見 Istio! - Fossas
- 跨語言微服務框架-Istio簡紹和概念微服務框架
- 從微服務治理的角度看RSocket,. Envoy和. Istio微服務
- Quarkus和MongoDB微服務簡單案例原始碼MongoDB微服務原始碼
- 微服務是否真的需要服務網格?微服務
- 初識 Istio - 服務網格管理工具
- 服務網格GCP (GKE, Istio, MSA) 搖滾組合GC
- 服務網格大事:Istio釋出1.0版本
- 分析原始碼:istio mixer原始碼
- ABP VNext 微服務演示,專案狀態和路線圖微服務
- 服務網格:微服務進入2.0時代微服務
- 從零搭建一個基於Istio的服務網格
- k8s-服務網格實戰-入門IstioK8S
- 幽默:最簡單的SpringBoot微服務程式碼Spring Boot微服務
- Kubernetes 微服務最佳實踐微服務
- 使用Kubernetes和Istio實現藍綠部署
- 線上學習安裝Istio和Kubernetes
- springboot 事務建立流程原始碼分析Spring Boot原始碼
- 經驗分享:修復服務網格Istio大量503錯誤
- SpringBoot 微服務打包 Docker 映象Spring Boot微服務Docker
- 學習微服務三-SpringBoot微服務Spring Boot
- 基於Istio/gRPC/Redis/BigQuery/Spring Boot/Spring Cloud和Stackdriver的微服務案例RPCRedisSpring BootCloud微服務