Java進階專題(二十八) Service Mesh初體驗

有夢想的老王發表於2021-04-01

前言

​ ⽬前,微服務的架構⽅式在企業中得到了極⼤的發展,主要原因是其解決了傳統的單體架構中存在的問題。當單體架構拆分成微服務架構就可以⾼枕⽆憂了嗎? 顯然不是的。微服務架構體系中同樣也存在很多的挑戰,

​ ⽐如:原來的單個應⽤拆分成了許多分散的微服務,它們之間相互調⽤才能完成⼀個任務,而⼀旦某個過程出錯(元件越多,出錯的概率也就越⼤),就⾮常難以排查。

​ 如果⽤戶請求的響應太慢,我們就需要知道到底哪些地⽅⽐較慢?整個鏈路的調⽤各階段耗時是多少?哪些調⽤是併發執⾏的,哪些是串⾏的?這些問題需要我們能⾮常清楚整個叢集的調⽤以及流量情況。

​ 微服務拆分成這麼多元件,如果單個元件出錯的概率不變,那麼整體有地⽅出錯的概率就會增⼤。服務調⽤的時候如果沒有錯誤處理機制,那麼會導致⾮常多的問題。

​ 應⽤數量的增多,對於⽇常的應⽤釋出來說也是個難題。應⽤的釋出需要⾮常謹慎,如果應⽤都是⼀次性升級的,出現錯誤會導致整個線上應⽤不可⽤,影響範圍太⼤。

​ 很多情況我們需要同時存在不同的版本,使⽤AB 測試驗證哪個版本更好。

​ 如果版本升級改動了API,並且互相有依賴,那麼我們還希望能⾃動地控制釋出期間不同版本訪問不同的地址。這些問題都需要智慧的流量控制機制。

​ 為了保證整個系統的安全性,每個應⽤都需要實現⼀套相似的認證、授權、HTTPS、限流等功能。

等等一系列問題,那麼有沒有什麼方案可以解決這些問題?沒錯,Service Mesh就是為了解決以上問題才出的。

什麼是Service Mesh

Service Mesh主要解決的問題就希望開發⼈員對於業務的聚焦,服務發現、服務註冊、負載均衡等對於開發⼈員透明,可以更加專注業務邏輯的實現。

如果將為微服務提供通訊服務的這部分邏輯從應⽤程式程式中抽取出來,作為⼀個單獨的程式進⾏部署,並將其作為服務間的通訊代理,可以得到如下圖所示的架構:

Sidecar,翻譯成中⽂是邊⻋,⾮常的形象。

當服務⼤量部署時,隨著服務部署的Sidecar代理之間的連線形成了⼀個如下圖所示的⽹格,該⽹格成為了微服務的通訊基礎設施層,承載了微服務之間的所有流量,被稱之為Service Mesh(服務⽹格)。

服務⽹格⽤來描述組成這些應⽤程式的微服務⽹絡以及它們之間的互動。隨著服務⽹格的規模和複雜性不斷的增⻓,它將會變得越來越難以理解和管理。它的需求包括服務發現、負載均衡、故障恢復、度量和監控等。服務⽹格通常還有更復雜的運維需求,⽐如A/B 測試、⾦絲雀釋出、速率限制、訪問控制和端到端認證。所有就有了二代Service Mesh出現:

為了更⽅便地對服務⽹格中的代理進⾏統⼀集中控制,在服務⽹格上增加了控制⾯元件。

第一代Service Mesh由一系列獨立執行的單機代理服務構成,為了提供統一的上層運維入口,演化出了集中式控制皮膚,所有的單機代理元件通過和控制皮膚互動進行網路拓撲策略的更新和單機資料的彙報。這就是以Istio為代表的第二代Service Mesh。

Service Mesh的定義

服務網格是一個基礎設施層,用於處理服務間通訊。雲原生應用有著複雜的服務拓撲,服務網格保證請求在這些拓撲中可靠地穿梭。在實際應用當中,服務網格通常是由一系列輕量級的網路代理組成的,它們與應用程式部署在一起,但對應用程式透明。

關鍵名詞解釋:

  • 基礎設施層、請求可在這些拓撲中可靠地穿梭:這兩個詞加起來描述了Service Mesh的定位和功能,是不是似曾識?沒錯,你一定想到了TCP;

  • 網路代理:這描述了Service Mesh的實現形態;

  • 對應用透明:這描述了Service Mesh的關鍵特點,正是由於這個特點,Service Mesh能夠解決以Spring Cloud為代表的第二代微服務框架所面臨的三個本質問題;

Service Mesh優點

  • 遮蔽分散式系統通訊的複雜性(負載均衡、服務發現、認證授權、監控追蹤、流量控制等等),服務只用關注業務邏輯;
  • 真正的語言無關,服務可以用任何語言編寫,只需和Service Mesh通訊即可;
  • 對應用透明,Service Mesh元件可以單獨升級;

Service Mesh目前也面臨一些挑戰

  • Service Mesh元件以代理模式計算並轉發請求,一定程度上會降低通訊系統效能,並增加系統資源開銷;
  • Service Mesh元件接管了網路流量,因此服務的整體穩定性依賴於Service Mesh,同時額外引入的大量Service Mesh服務例項的運維和管理也是一個挑戰;

好了到這裡,我相信你應該大概知道Serive Mesh到底是個什麼思想了,下面我看看基於Service Mesh思想的產品有哪些?

Service Mesh 產品

CNCF

CNCF 是⼀個開源軟體基⾦會,致⼒於使雲原⽣計算具有普遍性和可持續性。 雲原⽣計算使⽤開源軟體技術棧將應⽤程式部署為微服務,將每個部分打包到⾃⼰的容器中,並動態編排這些容器以優化資源利⽤率。 雲原⽣技術使軟體開發⼈員能夠更快地構建出⾊的產品。
常⽤的已經畢業的雲原⽣項⽬:Kubernetes、Prometheus、Jaeger、Envoy、Containerd

Linkerd

Linkerd是Buoyant公司2016年率先開源的⾼效能⽹絡代理程式,是業界的第⼀款Service Mesh產品,甚⾄可以說Linkerd的誕⽣標誌著Service Mesh時代的開始,其引領後來Service Mesh的快速發展。
其主要⽤於解決分散式環境中服務之間通訊⾯臨的⼀些問題,⽐如⽹絡不可靠、不安全、延遲丟包等問題。Linkerd使⽤Scala語⾔編寫,運⾏於JVM,底層基於Twitter的Finagle庫,並對其做相應的擴充套件。
最主要的是Linkerd具有快速、輕量級、⾼效能等特點,每秒以最⼩的時延及負載處理萬級請求,易於⽔平擴充套件,經過⽣產線測試及驗證,可運⾏任何平臺的產線級Service Mesh⼯具。

Envoy

Envoy也是⼀款⾼效能的⽹絡代理程式,於2016年10⽉份由Lyft公司開源,為雲原⽣應⽤⽽設計可作為邊界⼊⼝,處理外部流量,當然,也作為內部服務間通訊代理,實現服務間可靠通訊。
Envoy的實現借鑑現有產線級代理及負載均衡器,如Nginx、HAProxy、硬體負載均衡器及雲負載衡器的實踐經驗,同時基於C++編寫及Lyft公司產線實踐證明,Envoy效能⾮常優秀、穩定。
Envoy既可⽤作獨⽴代理層運⾏,也可作為Service Mesh架構中資料平⾯層,因此通常Envoy跟服運⾏在⼀起,將應⽤的⽹絡功能抽象化,Envoy提供通⽤⽹絡功能,實現平臺及語⾔⽆關。

Istio

2017年5⽉24⽇,Google, IBM 和Lyft 共同釋出Istio 的第⼀個公開版本(0.1)。Istio為⼀款開源的微服務提供服務間連線、管理以及安全保障的平臺軟體,⽀持運⾏在Kubernetes、Mesos等容器管理⼯具,但不限Kubernetes、Mesos,其底層依賴於Envoy。
Istio提供⼀種簡單的⽅法實現服務間的負載均衡、服務間認證、監控等功能,⽽且⽆需應⽤層代調整。其控制平⾯由Pilot、Citadel 和Galley組成,資料平⾯由Envoy實現,通常情況下,資料平⾯理Envoy以sidecar模式部署,使得所有服務間的⽹絡通訊均由Envoy實現,⽽Istio的控制平⾯則負責務間流量管理、安全通訊策略等功能。

Conduit

Conduit於2017年12⽉釋出,作為由Buoyant繼Linkerd後贊助的另⼀個開源項⽬。Conduit旨在徹底簡
化⽤戶在Kubernetes使⽤服務⽹格的複雜度,提⾼⽤戶體驗,⽽不是像Linkerd⼀樣針對各種平臺進⾏
優化。

國內產品

國內很多團隊也已經在著⼿研究了,這些團隊主要分為四類體系:

  • 以螞蟻⾦服為⾸的開源系:螞蟻⾦服⾃研的SOFA (Scalable Open Financial Architecture)Mesh 在開始的時候⾛的就是開源路線,他們參考了Istio 及Envoy 的設計思想,重新實現了⾃⼰的Service Mesh 系統,旁路⽹關(Sidecar)基於Go 語⾔,該系統的前身是已經開源的SOFA RPC 框架。螞蟻⾦服於2018 年7 ⽉正式將其開源,正式的可以⽤於⽣產的框架可能還需要⼀些時間。

  • 以華為為代表的⾃研系:華為可能在Service Mesh 概念出來前就已經有類似的想法了,只是沒有抽取出⼀個公共的概念。⽆論是華為早期的HSA 還是之後出現的CSE Mesher,都是對ServiceMesh 的探索。CSE Mesher 的整個架構都是基於華為⾃身微服務架構經驗研發的,其Sidecar 也是⽤Go 語⾔編寫的。如其官⽅⽂檔所述,其資源佔⽤⾮常⼩,常規狀態下僅為30MB。

  • 以騰訊為代表的拿來主義系:騰訊的Tencent Service Mesh對開源的產品(如Istio)進⾏定製,強化吸收後再加⼊⾃身特殊的業務邏輯。騰訊選擇的Sidecar是Envoy,使⽤C++編寫,⽐較符合騰訊的技術棧。其公開的技術並不多,仍然以內部⼩範圍使⽤為主。

  • 以UCloud 為代表的適配系:主要也是依賴開源⽅案,但不是完全將其產品引⼊,只是對其中⼏個關鍵部分新增介面卡,以適應企業現有產品,以最⼩的變更成本引⼊Service Mesh 體系。

我們今天主要研究下Istio

Istio簡介

Istio架構

實際上Istio 就是Service Mesh 架構的⼀種實現,服務之間的通訊(⽐如這⾥的Service A 訪問ServiceB)會通過代理(預設是Envoy)來進⾏。

⽽且中間的⽹絡協議⽀持HTTP/1.1,HTTP/2,gRPC 或者TCP,可以說覆蓋了主流的通訊協議。代理這⼀層,稱之為資料平⾯。

控制平⾯做了進⼀步的細分,分成了Pilot、Citadel 和Galley,它們的各⾃功能如下:

  • Pilot:為Envoy 提供了服務發現,流量管理和智慧路由(AB 測試、⾦絲雀釋出等),以及錯誤處理(超時、重試、熔斷)功能。

  • Citadel:為服務之間提供認證和證書管理,可以讓服務⾃動升級成TLS 協議。

  • Galley:Galley 是Istio 的配置驗證、提取、處理和分發元件。它負責將其餘的Istio 元件與從底層平臺(例如Kubernetes)獲取⽤戶配置的細節隔離開來。

為什麼使用Istio

通過負載均衡、服務間的身份驗證、監控等⽅法,Istio 可以輕鬆地建立⼀個已經部署了服務的⽹絡,⽽服務的程式碼只需很少更改甚⾄⽆需更改。通過在整個環境中部署⼀個特殊的sidecar 代理為服務新增Istio 的⽀持,⽽代理會攔截微服務之間的所有⽹絡通訊,然後使⽤其控制平⾯的功能來配置和管理Istio,這包括:

  • 為HTTP、gRPC、WebSocket 和TCP 流量⾃動負載均衡。

  • 通過豐富的路由規則、重試、故障轉移和故障注⼊對流量⾏為進⾏細粒度控制。

  • 可插拔的策略層和配置API,⽀持訪問控制、速率限制和配額。

  • 叢集內(包括叢集的⼊⼝和出⼝)所有流量的⾃動化度量、⽇志記錄和追蹤。

  • 在具有強⼤的基於身份驗證和授權的叢集中實現安全的服務間通訊。

Istio 為可擴充套件性⽽設計,可以滿⾜不同的部署需求。

Istio核心特性

Istio 以統⼀的⽅式提供了許多跨服務⽹絡的關鍵功能。

流量管理

Istio 簡單的規則配置和流量路由允許您控制服務之間的流量和API 調⽤過程。
Istio 簡化了服務級屬性(如熔斷器、超時和重試)的配置,並且讓它輕⽽易舉的執⾏重要的任務(如A/B 測試、⾦絲雀釋出和按流量百分⽐劃分的分階段釋出)。
有了更好的對流量的可視性和開箱即⽤的故障恢復特性,就可以在問題產⽣之前捕獲它們,⽆論⾯對什麼情況都可以使調⽤更可靠,⽹絡更健壯。

安全

Istio 的安全特性解放了開發⼈員,使其只需要專注於應⽤程式級別的安全。

Istio 提供了底層的安全通訊通道,併為⼤規模的服務通訊管理認證、授權和加密。有了Istio,服務通訊在預設情況下就是受保護的,可以讓您在跨不同協議和運⾏時的情況下實施⼀致的策略——⽽所有這些都只需要很少甚⾄不需要修改應⽤程式。

Istio 是獨⽴於平臺的,可以與Kubernetes(或基礎設施)的⽹絡策略⼀起使⽤。但它更強⼤,能夠在⽹絡和應⽤層⾯保護pod到pod 或者服務到服務之間的通訊。

可觀察性

Istio 健壯的追蹤、監控和⽇志特性讓您能夠深⼊的瞭解服務⽹格部署。

通過Istio 的監控能⼒,可以真正的瞭解到服務的效能是如何影響上游和下游的;⽽它的定製Dashboard 提供了對所有服務效能的視覺化能⼒,並讓您看到它如何影響其他程式。

Istio 的Mixer 元件負責策略控制和遙測資料收集。它提供了後端抽象和中介,將⼀部分Istio 與後端的基礎設施實現細節隔離開來,併為運維⼈員提供了對⽹格與後端基礎實施之間互動的細粒度控制。

所有這些特性都使您能夠更有效地設定、監控和加強服務的SLO。當然,底線是您可以快速有效地檢測到並修復出現的問題。

平臺支援

Istio 獨⽴於平臺,被設計為可以在各種環境中運⾏,包括跨雲、內部環境、Kubernetes、Mesos 等等。您可以在Kubernetes 或是裝有Consul 的Nomad 環境上部署Istio。Istio ⽬前⽀持:Kubernetes 上的服務部署/基於Consul 的服務註冊/服務運⾏在獨⽴的虛擬機器上

Istio快速入門

搭建Kubernetes叢集

Istio運⾏在kubernetes平臺是最佳的選擇,所以我們先搭建kubernetes環境。

準備3臺Centos7虛擬機器:node1 192.168.31.106 node1 192.168.31.106 node3 192.168.31.108

前置工作

搭建K8S之前,需要⼀些前置的準備⼯作,否則不能完成叢集的搭建。

#修改主機名
hostnamectl set-hostname node2
hostnamectl set-hostname node3

#更新yum源,並且完成yum update操作
mv/etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
wget -O/etc/yum.repos.d/CentOS-Base.repo
https://mirrors.aliyun.com/repo/Centos-7.repo
yum makecache
yum -yupdate

#安裝docker
yum install -yyum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repohttps://mirrors.aliyun.com/dockerce/linux/centos/docker-ce.repo
yum makecache fast
yum -yinstall docker-ce

#啟動docker服務
systemctl startdocker.service
#開機⾃啟
systemctl enable docker.service

#新增docker阿⾥雲加速器
sudo mkdir -p/etc/docker
sudo tee/etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://c6n8vys4.mirror.aliyuncs.com"]
}
EOF

sudo systemctl daemon-reload
sudo systemctl restartdocker

#測試⼀下,看下載速度怎麼樣
docker pull redis
docker rmi redis:latest

#關閉防⽕牆
systemctl stopfirewalld.service
systemctl disable firewalld.service

#新增hosts對映
vim/etc/hosts
192.168.31.106 node1
192.168.31.107 node2
192.168.31.108 node3

scp /etc/hosts node2:/etc/
scp /etc/hosts node3:/etc/

#設定node1到node2、node3免登陸
ssh-keygen #⼀路下⼀步操作
ssh-copy-id node2
ssh-copy-id node3

#測試
sshnode2
sshnode3

叢集搭建

#修改系統引數
# 將SELinux 設定為permissive 模式(相當於將其禁⽤)
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/'/etc/selinux/config

# 禁⽤swap⽂件,編輯/etc/fstab,註釋掉引⽤swap 的⾏
vim/etc/fstab
swapoff -a

# 設定⽹橋引數
vim/etc/sysctl.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
net.ipv4.tcp_tw_recycle = 0
scp /etc/sysctl.conf node2:/etc/
scp /etc/sysctl.conf node3:/etc/

#⽴即⽣效
sysctl -p

#安裝kubectl
vim/etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=0
yum list kubectl –showduplicates
yum install -ykubectl.x86_64
kubectl version
yum install -ykubelet kubeadm --disableexcludes=kubernetes

#拉取所需要的映象
kubeadm config images pull --image-repository=registry.cnhangzhou.aliyuncs.com/itcast --kubernetes-version=v1.18.6

#如果拉取失敗,嘗試這個:kubeadm config images pull --image-repository=lank8s.cn --kubernetes-version=v1.18.6
#開始初始化,如果使⽤lank8s.cn拉取的映象,需要指定--image-repository=lank8s.cn
kubeadm init --apiserver-advertise-address 192.168.31.106 --pod-networkcidr=10.244.0.0/16 --image-repository=registry.cn-hangzhou.aliyuncs.com/itcast
--kubernetes-version=v1.18.6
#當看到Your Kubernetes control-plane has initialized successfully! 說明初始化成功了!

#拷⻉admin.conf到home⽬錄,否則出錯:The connection to the server localhost:8080
was refused - did you specify the right host or port?
mkdir -p $HOME/.kube
sudo cp -i/etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

#設定⽹絡kube-flannel.yml ⽂件在資料中
kubectl apply -fkube-flannel.yml

#測試
[root@node1 k8s]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
node1 Ready master 23m v1.18.6

#將node2、node3加⼊到叢集,token要替換成⾃⼰的
kubeadm join 192.168.31.106:6443 --tokenekw4eu.cfi77sji1jyczhj6 --discoverytoken-ca-cert-hash
sha256:21de4177eaf76353dd060f2a783c9dafe17636437ade020bc40d60a8ab903483

#測試
[root@node1 k8s]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
node1 Ready master 31m v1.18.6
node2 Ready <none> 6m46s v1.18.6
node3 Ready <none> 2m21s v1.18.6

#說明叢集元件成功了
#如果需要刪除叢集,執⾏kubeadm reset ,3臺機器都需要執⾏
#檢視正在執⾏的pod
kubectl getpod --all-namespaces -owide

檢視正在執⾏的pod,kubectl get pod --all-namespaces -o wide

搭建Istio環境

下載Istio

下載Istio,下載內容將包含:安裝⽂件、示例和istioctl 命令⾏⼯具。

  1. 訪問 Istio release ⻚⾯下載與您作業系統對應的安裝⽂件。在macOS 或Linux 系統中,也可以通過以下命令下載最新版本的Istio:
$ curl -Lhttps://istio.io/downloadIstio | sh -
  1. 切換到Istio 包所在⽬錄下。例如:Istio 包名為 istio-1.6.5,則:

    $ cdistio-1.6.5
    

    安裝⽬錄包含如下內容:
    samples/ ⽬錄下,有示例應⽤程式
    bin/ ⽬錄下,包含 istioctl 的客戶端⽂件。istioctl ⼯具⽤於⼿動注⼊Envoy sidecar 代理。

  2. 將 istioctl 客戶端路徑增加到path 環境變數中,macOS 或Linux 系統的增加⽅式如下:

    $ export PATH=$PWD/bin:$PATH
    

    安裝bash ⾃動補全⽂件
    如果您使⽤bash,istioctl ⾃動補全的⽂件位於tools ⽬錄。通過複製istioctl.bash ⽂件到您的home
    ⽬錄,然後新增下⾏內容到您的.bashrc ⽂件執⾏istioctl tab 補全⽂件:

source~/istioctl.bash

如果istioctl 補全⽂件已經正確安裝,在您輸⼊istioctl 命令時通過按Tab 鍵,它會返回⼀組推薦命令供您選擇:

$ istioctlproxy-<TAB>
proxy-config proxy-status

安裝Istio

請按照以下步驟在您所選的平臺上使⽤demo 配置⽂件安裝Istio。

  1. 安裝 demo 配置

    $ istioctlmanifest apply --set profile=demo
    
  2. 為了驗證是否安裝成功,需要先確保以下Kubernetes 服務正確部署,然後驗證除 jaegeragent 服務外的其他服務,是否均有正確的 CLUSTER-IP:

$ kubectl getsvc -nistio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP 
PORT(S) 
AGE
grafana ClusterIP  172.21.211.123 <none> 
3000/TCP 
2m
istio-citadel ClusterIP  172.21.177.222 <none> 
8060/TCP,15014/TCP 
2m
istio-egressgateway ClusterIP  172.21.113.24 <none> 
80/TCP,443/TCP,15443/TCP 
2m
istio-galley ClusterIP  172.21.132.247 <none> 
443/TCP,15014/TCP,9901/TCP 
2m
istio-ingressgateway LoadBalancer  172.21.144.254  52.116.22.242 
15020:31831/TCP,80:31380/TCP,443:31390/TCP,31400:31400/TCP,15029:30318/TCP
,15030:32645/TCP,15031:31933/TCP,15032:31188/TCP,15443:30838/TCP 2m
istio-pilot ClusterIP  172.21.105.205 <none> 
15010/TCP,15011/TCP,8080/TCP,15014/TCP 
2m
istio-policy ClusterIP  172.21.14.236 <none> 
9091/TCP,15004/TCP,15014/TCP 
2m
istio-sidecar-injector ClusterIP  172.21.155.47 <none> 
443/TCP,15014/TCP 
2m
istio-telemetry ClusterIP  172.21.196.79 <none> 
9091/TCP,15004/TCP,15014/TCP,42422/TCP 
2m
jaeger-agent ClusterIP None <none> 
5775/UDP,6831/UDP,6832/UDP 
2m
jaeger-collector ClusterIP  172.21.135.51 <none> 
14267/TCP,14268/TCP 
2m
jaeger-query ClusterIP  172.21.26.187 <none> 
16686/TCP 
2m
kiali ClusterIP  172.21.155.201 <none> 
20001/TCP 
2m
prometheus ClusterIP  172.21.63.159 <none> 
9090/TCP 
2m
tracing ClusterIP  172.21.2.245 <none> 
80/TCP 
2m
zipkin ClusterIP  172.21.182.245 <none> 
9411/TCP 
2m

如果叢集運⾏在⼀個不⽀持外部負載均衡器的環境中(例如:minikube),istioingressgateway 的 EXTERNAL-IP 將顯示為 狀態。請使⽤服務的 NodePort或 端⼝轉發來訪問⽹關。

請確保關聯的Kubernetes pod 已經部署,並且 STATUS 為 Running:

$ kubectl getpods -nistio-system
NAME READY 
STATUS RESTARTS AGE
grafana-f8467cc6-rbjlg  1/1 
Running  01m
istio-citadel-78df5b548f-g5cpw  1/1 
Running  01m
istio-egressgateway-78569df5c4-zwtb5  1/1 
Running  01m
istio-galley-74d5f764fc-q7nrk  1/1 
Running  01m
istio-ingressgateway-7ddcfd665c-dmtqz  1/1 
Running  01m
istio-pilot-f479bbf5c-qwr28  1/1 
Running  01m
istio-policy-6fccc5c868-xhblv  1/1 
Running  21m
istio-sidecar-injector-78499d85b8-x44m6  1/1 
Running  01m
istio-telemetry-78b96c6cb6-ldm9q  1/1 
Running  21m
istio-tracing-69b5f778b7-s2zvw  1/1 
Running  01m
kiali-99f7467dc-6rvwp  1/1 
Running  01m
prometheus-67cdb66cbb-9w2hm  1/1 
Running  01m

Bookinfo示例

這個示例部署了⼀個⽤於演示多種Istio 特性的應⽤,該應⽤由四個單獨的微服務構成。 這個應⽤模仿線上書店的⼀個分類,顯示⼀本書的資訊。 ⻚⾯上會顯示⼀本書的描述,書籍的細節(ISBN、⻚數等),以及關於這本書的⼀些評論。

Bookinfo 應⽤分為四個單獨的微服務:

productpage. 這個微服務會調⽤ details 和 reviews 兩個微服務,⽤來⽣成⻚⾯。
details. 這個微服務中包含了書籍的資訊。
reviews. 這個微服務中包含了書籍相關的評論。它還會調⽤ ratings 微服務。
ratings. 這個微服務中包含了由書籍評價組成的評級資訊。

reviews 微服務有3 個版本:

v1 版本不會調⽤ ratings 服務。
v2 版本會調⽤ ratings 服務,並使⽤1 到5 個⿊⾊星形圖示來顯示評分資訊。
v3 版本會調⽤ ratings 服務,並使⽤1 到5 個紅⾊星形圖示來顯示評分資訊。

下圖展示了這個應⽤的端到端架構。

Bookinfo 應⽤中的⼏個微服務是由不同的語⾔編寫的。 這些服務對Istio 並⽆依賴,但是構成了⼀個有代表性的服務⽹格的例⼦:它由多個服務、多個語⾔構成,並且 reviews 服務具有多個版本。

部署應用

要在Istio 中運⾏這⼀應⽤,⽆需對應⽤⾃身做出任何改變。 您只要簡單的在Istio 環境中對服務進⾏配置和運⾏,具體⼀點說就是把Envoy sidecar 注⼊到每個服務之中。 最終的部署結果將如下圖所示:

所有的微服務都和Envoy sidecar 整合在⼀起,被整合服務所有的出⼊流量都被sidecar 所劫持,這樣就為外部控制準備了所需的Hook,然後就可以利⽤Istio 控制平⾯為應⽤提供服務路由、遙測資料收集以及策略實施等功能。

啟動服務

  1. 進⼊Istio 安裝⽬錄。
  2. Istio 預設⾃動注⼊Sidecar. 請為 default 名稱空間打上標籤 istio-injection=enabled:
$ kubectl label namespace default istio-injection=enabled
  1. 使⽤ kubectl 部署應⽤:
$ kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml

如果您在安裝過程中禁⽤了Sidecar ⾃動注⼊功能⽽選擇⼿動注⼊Sidecar,請在部署應⽤之前使⽤ istioctl kube-inject 命令修改 bookinfo.yaml ⽂件。

$ kubectl apply -f <(istioctl kube-inject -f
samples/bookinfo/platform/kube/bookinfo.yaml)

上⾯的命令會啟動全部的四個服務,其中也包括了reviews 服務的三個版本(v1、v2 以及v3)。在實際部署中,微服務版本的啟動過程需要持續⼀段時間,並不是同時完成的。

  1. 確認所有的服務和Pod 都已經正確的定義和啟動:
$ kubectl getservices
NAME CLUSTER-IP EXTERNAL-IP PORT(S) 
AGE
details  10.0.0.31 <none>  9080/TCP 
6m
kubernetes  10.0.0.1 <none>  443/TCP 
7d
productpage  10.0.0.120 <none>  9080/TCP 
6m
ratings  10.0.0.15 <none>  9080/TCP 
6m
reviews  10.0.0.170 <none>  9080/TCP 
6m

還有:

$ kubectl getpods
NAME READY STATUS RESTARTS 
AGE
details-v1-1520924117-48z17  2/2 Running  0 
6m
productpage-v1-560495357-jk1lz  2/2 Running  0 
6m
ratings-v1-734492171-rnr5l  2/2 Running  0 
6m
reviews-v1-874083890-f0qf0  2/2 Running  0 
6m
reviews-v2-1343845940-b34q5  2/2 Running  0 
6m
reviews-v3-1813607990-8ch52  2/2 Running  0 
6m
  1. 要確認Bookinfo 應⽤是否正在運⾏,請在某個Pod 中⽤ curl 命令對應⽤傳送請求,例如ratings:
$ kubectlexec -it $(kubectl get pod -l app=ratings -o
jsonpath='{.items[0].metadata.name}') -cratings -- curl
productpage:9080/productpage | grep -o "<title>.*</title>"
<title>Simple Bookstore App</title>

確定Ingress 的IP

現在Bookinfo 服務啟動並運⾏中,您需要使應⽤程式可以從外部訪問Kubernetes 叢集,例如使⽤瀏覽器。可以⽤Istio Gateway 來實現這個⽬標。

  1. 為應⽤程式定義Ingress ⽹關:
$ kubectlapply -fsamples/bookinfo/networking/bookinfo-gateway.yaml
  1. 確認⽹關建立完成:

    $ kubectl getgateway
    NAME AGE
    bookinfo-gateway 32s
    
  2. 設定訪問⽹關的 INGRESS_HOST 和 INGRESS_PORT 變數。確認並設定。

#設定ingress 端⼝
export INGRESS_PORT=$(kubectl -n istio-system get service istioingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istioingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}')
#設定ingress IP
export INGRESS_HOST=$(kubectl get po -l istio=ingressgateway -n istiosystem -o jsonpath='{.items[0].status.hostIP}')
  1. 設定 GATEWAY_URL:

    export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
    

可以⽤瀏覽器開啟⽹址 http://$GATEWAY_URL/productpage,來瀏覽應⽤的Web ⻚⾯。如果重新整理⼏次應⽤的⻚⾯,就會看到 productpage ⻚⾯中會隨機展示 reviews 服務的不同版本的效果(紅⾊、⿊⾊的星形或者沒有顯示)。reviews 服務出現這種情況是因為我們還沒有使⽤Istio 來控制版本的路由。

應⽤預設⽬標規則

在使⽤Istio 控制Bookinfo 版本路由之前,您需要在⽬標規則中定義好可⽤的版本,命名為 subsets 。

#設定
kubectl apply -fsamples/bookinfo/networking/destination-rule-all.yaml
#查詢
kubectl getdestinationrules -oyaml

⾄此,Istio 完成了全部的接管

體驗Istio

按照版本路由
reviews有三個版本,預設情況下,會進⾏輪詢,也就是我們看到的,每⼀次重新整理都會有不同的效果。如果,我們需要將請求全部切換到某⼀個版本,需要Istio是⾮常簡單的,只需要新增虛擬服務即可。示例:

#virtual-service-all-v1.yaml是官⽅提供的示例⽂件
kubectl apply -fsamples/bookinfo/networking/virtual-service-all-v1.yaml

經過測試,發現reviews不再切換樣式。

還可以將部分流量轉移到v3版本,基於此可以實現灰度釋出、A/B測試等:

#將50%的流程轉移到v3
kubectl apply -fsamples/bookinfo/networking/virtual-service-reviews-50-v3.yaml

重新整理瀏覽器中的/productpage ⻚⾯,⼤約有50% 的⼏率會看到⻚⾯中出帶 紅⾊ 星級的評價內容。這是因為v3 版本的reviews 訪問了帶星級評級的ratings 服務,但v1 版本卻沒有。
如果認為reviews:v3 微服務已經穩定,可以通過應⽤此virtual service 規則將100% 的流量路由到reviews:v3:

kubectl apply -fsamples/bookinfo/networking/virtual-service-reviews-v3.yaml

這樣,所有的請求都轉向到了v3了。
如果需要刪除虛擬⽹絡,可以執⾏:

kubectl delete -fsamples/bookinfo/networking/virtual-service-all-v1.yaml

相關文章