Service Mesh(服務網格)概念及Istio初體驗


分布式架構發展史:

單機小型機時代:

  1969年,阿帕網誕生,最初是為了軍事目的,后來衍變成Internet。2000年左右,互聯網在中國開始盛行起來,但是那時候網民數較少,所以多數企業服務單一,采用集中式部署的方式就能滿足需求

   但是這樣的部署方式帶來了一定的問題,一旦小型機或者數據庫出現問題,會導致整個系統的故障,而且功能修改發布也不方便,所以不妨把大系統拆分成多個子系統,比如“用戶”,“商品”,“論壇“等,也就是”垂直拆分“,並且每個子系統都有各自的硬件

集群化負載均衡時代:

  用戶量越來越大,就意味着需要更多的小型機,價格昂貴,操作維護成本高,不妨把小型機換成普通的PC機,采用多台PC機部署同一個應用的方案,但是此時就需要對這些應用做負載均衡,因為客戶端不知道請求哪一個。

  負載均衡可以分為硬件和軟件,硬件比如F5,軟件比如LVS(Linux Virtual Server),nginx,haproxy。負載均衡的思路是對外暴露一個統一的接口,然后根據用戶的請求進行對應規則的轉發。同時負載均衡還可以做健康檢查、限流等有了負載均衡,后端的應用就可以根據流量的大小進行動態的擴縮容了,也就是“水平擴展”。

服務化時代:

  此時發現在用戶,商品和訂單等中有重復的功能,比如登錄、注冊、郵件等。一旦項目大了,集群部署多了,這些重復的功能無疑是浪費資源,不妨把重復的功能抽取出來,起個名字叫“服務Service”。其實對於“服務”現在已經比較廣泛了,比如“基礎設施即服務IaaS”、“平台即服務PaaS”、“軟件即服務SaaS“等。這時候急需解決的就是服務之間的調用問題,RPC(Remote Procedure Call),同時這種調用關系得維護起來,比如某個服務在哪里,是不是得知道?所以不僅僅要解決服務調用的問題,還要解決服務治理的問題,比如像Dubbo,默認采用Zookeeper作為注冊中心,Spring Cloud使用Eureka作為注冊中心當然,要關注的還有很多,比如限流、降級、負載均衡、容錯等

分布式微服務時代:

  在分布式架構下,服務可能拆分的沒那么細,可以進一步的拆分 Microservices。Java中微服務主流解決方案Spring Cloud,Spring Cloud可以通過引入幾個注解,寫少量代碼完成微服務架構中的開發,相比Dubbo而言方便很多。並且使用的是HTTP協議,所以對多語言也可以很好地支持。

Service Mesh(服務網格)時代:

  微服務時代有了Spring Cloud就完美了嗎?不妨想一想會有哪些問題

  • 最初是為了業務而寫代碼,比如登錄功能、支付功能等,到后面會發現要解決網絡通信的問題,雖然有Spring Cloud里面的組件幫我們解決了,但是細想一下它是怎么解決的?引入以來dependency,加注解,寫配置,最后將這些非業務功能的代碼打包一起部署,和業務代碼在一起,稱為“侵入式框架”;
  • 微服務中的服務支持不同語言開發,維護不同語言和非業務代碼的成本;
  • 業務代碼開發者應該把更多的精力投入到業務熟悉度上,而不應該是非業務上,Spring Cloud雖然能解決微服務領域的很多問題,但是學習成本還是較大的;
  • 對於Spring Cloud而言,並不是微服務領域的所有問題都有對應的解決方案,也就是功能有限,比如Content Based Routing和Version Based Routing。當然可以將Spring Cloud和Service Mesh結合起來使用,也就是對SC的補充、擴展和加強等;
  • 互聯網公司產品的版本升級是非常頻繁的,為了維護各個版本的兼容性、權限、流量等,因為SpringCloud是“代碼侵入式的框架”,這時候版本的升級就注定要讓非業務代碼一起,一旦出現問題,再加上多語言之間的調用,工程師會非常痛苦;
  • 其實大家有沒有發現,服務拆分的越細,只是感覺上輕量級解耦了,但是維護成本卻越高了,那么怎么辦呢?網絡的問題當然還是要交給網絡本身來解決

   從微服務發展的角度上來說,我們所面臨的首要的問題就是網絡問題,TCP/IP協議解決了計算機之間的通信問題。微服務的出現帶來了服務與服務之間的通信問題,我們應該知道,對於開發者而言,最好的方式是能實現服務與服務之間就好比計算機與計算機之間的通信一樣,是無感知的。

 問題解決思路:

  本質上是要解決服務之間通信的問題,不應該將非業務的代碼融合到業務代碼中,也就是從客戶端發出的請求,要能夠順利到達對應的服務,這中間的網絡通信的過程要和業務代碼盡量無關

  通信的問題:服務發現、負載均衡、版本控制、藍綠部署等

  在很早之前的單體架構中,其實通信問題也是需要寫在業務代碼中的,那時候怎么解決的呢?把網絡通信,流量轉發等問題放到了計算機網絡模型中的TCP/UDP層,也就是非業務功能代碼下沉

  那就不妨把這些通信的問題都交給計算機網絡模型組織去解決咯?別人肯定不會答應,怎么辦?既然不答應,那我們就自己想辦法解決通信問題,搞一些產品豈不快哉?沒錯,代理嘛

  不妨這樣在幫每個服務配置一個代理,所有通信的問題都交給這個代理去做大家肯定接觸過,比如最初Nginx、HaProxy等,其實它們做反向代理把請求轉發給其他服務器,也就為Service Mesh的誕生和完成提供了一個解決思路

一些公司對於代理的探索Sidecar:

  很多公司借鑒了Proxy模式,推出了Sidecar的產品,比如像14年Netflix的Prana、15年唯品會的local proxy其實Sidecar模式和Proxy很類似,但是Sidecar功能更全面,也就是Sidecar功能和侵入式框架的功能對應

  這種Sidecar是為特定的基礎設施而設計的,也就是跟公司原有的框架技術綁定在一起,不能成為通用性的產品,所以還需要繼續探索。

Service Mesh之Linkerd:

  2016年1月,離開Twitter的基礎設施工程師William Morgan和Oliver Gould,在github上發布了Linkerd 0.0.7版本,從而第一個Service Mesh項目由此誕生。並且Linkerd是基於Twitter的Finagle開源項目,實現了通用性。后面又出現了Service Mesh的第二個項目Envoy,並且在17年都加入了CNCF項目。

  Linkerd解決了通用性問題,在Linkerd思想要求所有的流量都走Sidecar,而原來的Sidecar方式可以走可以直連,這樣一來Linkerd就幫業務人員屏蔽了通信細節,也不需要侵入到業務代碼中,讓業務開發者更加專注於業務本身。

  但是Linkerd的設計思想在傳統運維方式中太難部署和維護了,所以就后來沒有得到廣泛的關注,其實主要的問題是Linkerd只是實現了數據層面的問題,但沒有對其進行很好的管理。

Service Mesh之Istio:

  由Google、IBM和Lyft共同發起的開源項目,17年5月發布0.1 release版本,17年10月發布0.2 release版本,18年7月發布1.0 release版本。很明顯Istio不僅擁有“數據平面(Data Plane)”,而且還擁有“控制平面(Control Plane),也就是擁有了數據接管與集中控制能力。

  官網:https://istio.io/docs/concepts/what-is-istio

What is a service mesh?

  隨着單片應用程序向分布式微服務體系結構的轉變,Istio解決了開發人員和操作人員面臨的挑戰。要了解如何做到這一點,請更詳細地查看Istio的服務網格。術語ServiceMesh(服務網格)用於描述組成這些應用程序的微服務網絡以及它們之間的交互。隨着服務網格的規模和復雜性的增長,它會變得更加難以理解和管理。它的需求可以包括發現、負載平衡、故障恢復、度量和監視。服務網格通常還有更復雜的操作需求,比如A/B測試、canary推出、速率限制、訪問控制和端到端身份驗證。Istio提供了對整個服務網格的行為洞察和操作控制,提供了一個完整的解決方案來滿足微服務應用程序的各種需求。

  為何Service Mesh能夠迅速走紅?隨着微服務和容器化技術的發展,使得開發和運維的方式變得非常方便。從而讓服務能夠方便地遷移到不同的雲平台上。回顧一下Service Mesh的發展歷程

  • 借鑒反向代理,對Proxy模式進行探索,讓非業務的代碼下沉
  • 使用Sidecar彌補Proxy模式功能的不足,解決“侵入式框架”中非業務代碼的問題
  • Linkerd解決傳統Sidecar模式中通用性的問題
  • Istio增加了控制平面,解決整個系統中的流量完全控制的問題

what is Istio ?

  基於Sidecar模式、數據平面和控制平台、主流Service Mesh解決方案

  雲平台為使用它們的組織提供了大量的好處。然而,不可否認采用雲會給DevOps團隊帶來壓力。開發人員必須使用微服務來構建可移植性,同時運營商也在管理非常大的混合和多雲部署。Istio允許您連接、保護、控制和觀察服務。在高層次上,Istio有助於降低這些部署的復雜性,並減輕開發團隊的壓力。它是一個完全開源的服務網格,透明地分層到現有的分布式應用程序上。它也是一個平台,包括一些api,可以將其集成到任何日志平台、遙測技術或策略系統中。Istio的多樣化特性集使您能夠成功、高效地運行分布式微服務體系結構,並提供統一的方式來保護、連接和監視微服務。

Why use Istio ?

  通過負載平衡、service-to-service身份驗證、監視等方法,Istio可以輕松地創建部署的服務網絡,而服務代碼中的代碼更改很少或沒有更改。通過在整個環境中部署一個特殊的sidecar代理來攔截微服務之間的所有網絡通信,從而向服務添加Istio支持,然后使用其控制平面功能來配置和管理Istio,其中包括:

  • HTTP、gRPC、WebSocket和TCP流量的自動負載平衡。
  • 通過豐富的路由規則、重試、故障轉移和故障注入對流量行為進行細粒度控制。
  • 支持訪問控制、速率限制和配額的可插拔策略層和配置API。
  • 集群內所有流量的自動度量、日志和跟蹤,包括集群入口和出口。
  • 在具有強大的基於身份的身份驗證和授權的集群中實現安全的服務到服務通信。

  Istio是為可擴展性而設計的,可以滿足不同的部署需求。Sidecar的方式解決了數據通信的問題,而在Istio中還加入了控制平面,所有的流量都能夠有效地被控制,也就是通過控制平面可以控制整個系統。

  在Istio中到底能解決哪些問題:

  • 針對HTTP、gRPC、WebSocket等協議的自動負載均衡
  • 故障的排查、應用的容錯、眾多路由
  • 流量控制、全鏈路安全訪問控制與認證
  • 請求遙測、日志分析以及全鏈路跟蹤
  • 應用的升級發布、頻率限制和配合等

 

Istio Architecture:

  有了感性的認知和功能了解之后,接下來就要考慮落地的問題了,也就是Istio的架構圖該如何設計。說白了就是根據數據平面和控制平面的理念,該怎么設計架構圖,這個官方已經幫我們考慮好了。

  Architecutre :https://istio.io/docs/ops/deployment/architecture/

  Istio服務網格在邏輯上分為數據平面和控制平面。數據平面由一組部署為邊車(Sidecar)的智能代理(Envoy)組成。這些代理負責協調和控制微服務之間的所有網絡通信,以及一個通用策略和遙測中心。控制平面管理並將代理配置為路由流量。此外,控制平面配置混頻器來執行策略和收集遙測數據。下圖顯示了組成每個平面的不同組件:

 

Envoy:

  Istio使用Envoy代理的擴展版本。Envoy是用c++開發的高性能代理,用於協調服務網格中所有服務的所有入站和出站流量。特使代理是唯一與數據飛機通信交互的Istio組件。Envoy代理被部署為服務的sidecars,在邏輯上增加了Envoy的許多內置特性,例如:

  • 動態服務發現
  • 負載平衡
  • TLS終止
  • HTTP/2和gRPC代理
  • 斷路器
  • 健康檢查
  • 分階段推出基於%的流量分割
  • 故障注入
  • 豐富的指標

  這種sidecar部署允許Istio提取大量關於流量行為的信號作為屬性。反過來,Istio可以在混合器中使用這些屬性來執行策略決策,並將它們發送到監控系統以提供關於整個網格的行為的信息。sidecar代理模型還允許您向現有部署添加Istio功能,而不需要重新架構或重寫代碼。您可以閱讀更多關於為什么我們在設計目標中選擇這種方法的信息。由Envoy代理啟用的一些Istio功能和任務包括:

  • 流量控制功能:通過豐富的HTTP、gRPC、WebSocket和TCP流量路由規則來執行細粒度的流量控制。
  • 網絡彈性特性:設置重試、故障轉移、斷路器和故障注入。
  • 安全性和身份驗證特性:執行安全性策略和通過配置API定義的訪問控制和速率限制。

Kubernetes CRD(K8s資源拓展):

  官網:https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/

  Kubernetes平台對於分布式服務部署的很多重要的模塊都有系統性的支持,借助如下一些平台資源可以滿足大多數分布式系統部署和管理的需求。

  但是在不同應用業務環境下,對於平台可能有一些特殊的需求,這些需求可以抽象為Kubernetes的擴展資源,而Kubernetes的CRD(CustomResourceDefinition)為這樣的需求提供了輕量級的機制,保證新的資源的快速注冊和使用。在更老的版本中,TPR(ThirdPartyResource)是與CRD類似的概念,但是在1.9以上的版本中被棄用,而CRD則進入的beta狀態。Istio就是使用CRD在Kubernetes上建構出一層Service Mesh的實現

  這里就是需要創建 istio-1.0.6/install/kubernetes/helm/istio/templates/crds.yaml 這個資源.

安裝 Istio:

  官網:https://istio.io/docs/setup/getting-started/ 需要Kuberbetes 集群做支撐

  Before you can install Istio, you need a cluster running a compatible version of Kubernetes. Istio 1.4 has been tested with Kubernetes releases 1.13, 1.14, 1.15.Create a cluster by selecting the appropriate platform-specific setup instructions.

1.下載 istio-1.0.6-linux.tar.gz

2.解壓 tar -zxvf istio-1.x.y.tar.gz,進入到istio文件目錄下

3.將itsioctl添加到環境變量中

export PATH=$PWD/bin:$PATH

4.進入查看 istio-1.0.6/install/kubernetes/istio-demo.yaml 文件 。提前准備好鏡像,所有節點

docker pull registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/proxy_init:1.0.6 docker pull registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/hyperkube:v1.7.6_coreos.0 docker pull registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/galley:1.0.6 docker pull registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/proxyv2:1.0.6 docker pull registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/grafana:5.2.3 docker pull registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/mixer:1.0.6 docker pull registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/pilot:1.0.6 docker pull registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/prometheus:v2.3.1 docker pull registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/citadel:1.0.6 docker pull registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/servicegraph:1.0.6 docker pull registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/sidecar_injector:1.0.6 docker pull registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/all-in-one:1.5

5.把阿里雲鏡像倉庫的鏡像打成原有的tag

docker tag registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/proxy_init:1.0.6            docker.io/istio/proxy_init:1.0.6 docker tag registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/hyperkube:v1.7.6_coreos.0   quay.io/coreos/hyperkube:v1.7.6_coreos.0 docker tag registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/galley:1.0.6                docker.io/istio/galley:1.0.6 docker tag registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/proxyv2:1.0.6               docker.io/istio/proxyv2:1.0.6 docker tag registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/grafana:5.2.3               grafana/grafana:5.2.3 docker tag registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/mixer:1.0.6                 docker.io/istio/mixer:1.0.6 docker tag registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/pilot:1.0.6                 docker.io/istio/pilot:1.0.6 docker tag registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/prometheus:v2.3.1           docker.io/prom/prometheus:v2.3.1 docker tag registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/citadel:1.0.6               docker.io/istio/citadel:1.0.6 docker tag registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/servicegraph:1.0.6          docker.io/istio/servicegraph:1.0.6 docker tag registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/sidecar_injector:1.0.6      docker.io/istio/sidecar_injector:1.0.6 docker tag registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/all-in-one:1.5              docker.io/jaegertracing/all-in-one:1.5

6.刪除阿里雲鏡像倉庫下載的鏡像

docker rmi registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/proxy_init:1.0.6
docker rmi registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/hyperkube:v1.7.6_coreos.0
docker rmi registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/galley:1.0.6
docker rmi registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/proxyv2:1.0.6
docker rmi registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/grafana:5.2.3
docker rmi registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/mixer:1.0.6
docker rmi registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/pilot:1.0.6
docker rmi registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/prometheus:v2.3.1
docker rmi registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/citadel:1.0.6
docker rmi registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/servicegraph:1.0.6
docker rmi registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/sidecar_injector:1.0.6
docker rmi registry.cn-hangzhou.aliyuncs.com/wuzz-istio-k8s/all-in-one:1.5

 7.安裝istio核心組件,根據istio-1.0.6/install/kubernetes/istio-demo.yaml創建資源

  kubectl apply -f istio-demo.yaml

  第一次創建出現:unable to recognize "install/kubernetes/istio.yaml": no matches for config.istio.io/, Kind=attributemanifest 。耐心等待一下就行,資源較多,速度沒那么快。

  kubectl get pods -n istio-system

  kubectl get svc -n istio-system   可以給某個service配置一個ingress規則,訪問試試

  大家都知道,K8s中是通過Pod來部署業務,流量的進出是直接跟Pod打交道的那在Istio中如何體現sidecar的作用呢?在Pod中除了業務的container,再增加一個container為sidecar豈不是快哉?

手動注入sidecar:

   准備一個資源 first-istio.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: first-istio
spec:
  selector:
    matchLabels:
      app: first-istio
  replicas: 1
  template:
    metadata:
      labels:
        app: first-istio
    spec:
      containers:
      - name: first-istio
        image: registry.cn-hangzhou.aliyuncs.com/wuzz-docker/test-docker-image:v1.0
        ports:
        - containerPort: 8080  
---
apiVersion: v1
kind: Service
metadata:
  name: first-istio
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app: first-istio
  type: ClusterIP

  kubectl apply -f first-istio.yaml

  kubectl get pods   -> # 注意該pod中容器的數量  可以看到這里只有一個。

  kubectl get svc

  curl 10.103.54.200:8080/dockerfile  

  刪除上述資源,重新創建,使用手動注入sidecar的方式

  kubectl delete -f first-istio.yaml

  istioctl kube-inject -f first-istio.yaml | kubectl apply -f -

  可以看到這里產生了2個容器,那么我們看看這生成的另一個容器是什么?

   kubectl describe pod  pod-name -n istio-system

  很明顯,這個新的容器就是Envoy-proxy

  這樣一來,就手動給pod中注入了sidecar的container,也就是envoy sidecar。其實這塊是先改變了yaml文件的內容,然后再創建的pod:kubectl get pod pod-name -o yaml

   刪除資源: istioctl kube-inject -f first-istio.yaml | kubectl delete -f -

自動注入sidecar:

  上述每次都進行手動創建肯定不爽咯,一定會有好事之者來做這件事情。這塊需要命名空間的支持,比如有一個命名空間為istio-demo,可以讓該命名空間下創建的pod都自動注入sidecar。

1.創建命名空間  :kubectl create namespace istio-demo

2.給命名空間加上label :kubectl label namespace istio-demo istio-injection=enabled

3.創建資源 :kubectl apply -f first-istio.yaml -n istio-demo

4.查看資源。這個時候達到的效果跟上面是一致的,只不過已經自動創建了 Envoy-proxy

kubectl get pods -n istio-demo kubectl describe pod pod-name -n istio-demo kubectl get svc -n istio-demo

5.刪除資源:kubectl delete -f first-istio.yaml -n istio-demo

Istio 與 prometheus和grafana:

  其實istio已經默認幫我們安裝好了grafana和prometheus,只是對應的Service是ClusterIP,我們按照之前K8s的方式配置一下Ingress訪問規則即可,但是要提前有Ingress Controller的支持哦

1.尋找prometheus的yaml配置(搜索istio-demo.yaml文件)找到下面這個:

# Source: istio/charts/prometheus/templates/service.yaml apiVersion: v1 kind: Service metadata: name: prometheus # 主要是為了定位到prometheus的Service
namespace: istio-system

2.配置prometheus的Ingress規則 :

#ingress apiVersion: extensions/v1beta1 kind: Ingress metadata: name: prometheus-ingress namespace: istio-system spec: rules: - host: prometheus.istio.wuzz.com http: paths: - path: / backend: serviceName: prometheus servicePort: 9090

3.訪問grafana的配置(istio-demo.yaml文件)

apiVersion: v1 kind: Service metadata: name: grafana namespace: istio-system

4.配置grafan的Ingress規則 :

#ingress apiVersion: extensions/v1beta1 kind: Ingress metadata: name: grafana-ingress namespace: istio-system spec: rules: - host: grafana.istio.wuzz.com http: paths: - path: / backend: serviceName: grafana servicePort: 3000

 

5.根據兩個ingress創建資源

  kubectl get ingress -n istio-system

   訪問 prometheus

   訪問 grafana:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM