Istio Service Mesh 教程

本文是 Istio 管理 Java 微服務(wù)的案例教程,使用的所有工具和軟件全部基于開源方案,替換了?redhat-developer-demos/istio-tutorial?中的 minishift 環(huán)境,使用?kubernetes-vagrant-centos-cluster?替代,沿用了原有的微服務(wù)示例,使用 Zipkin 做分布式追蹤而不是 Jaeger。

本文中的代碼和 YAML 文件見?https://github.com/rootsongjc/istio-tutorial。

準(zhǔn)備環(huán)境

在進(jìn)行本教程前需要先準(zhǔn)備以下工具和環(huán)境。

8G 以上內(nèi)存

Vagrant 2.0+

Virtualbox 5.0 +

提前下載 kubernetes1.9.1 的 release 壓縮包

docker 1.12+

kubectl 1.9.1+

maven 3.5.2+

istioctl 0.7.1

git

curl、gzip、tar

kubetail

siege

安裝 Kubernetes

請參考?kubernetes-vagrant-centos-cluster?在本地啟動擁有三個節(jié)點的 kubernetes 集群。

git clone https://github.com/rootsongjc/kubernetes-vagrant-centos-cluster.git

cd kubernetes-vagrant-centos-cluster

vagrant up

安裝 Istio

在?kubernetes-vagrant-centos-cluster?中的包含 Istio 0.7.1 的安裝 YAML 文件,運行下面的命令安裝 Istio。

kubectl apply -f addon/istio/

運行示例

kubectl apply -n default -f <(istioctl kube-inject -f yaml/istio-bookinfo/bookinfo.yaml)

在您自己的本地主機(jī)的/etc/hosts文件中增加如下配置項。

172.17.8.102 grafana.istio.jimmysong.io

172.17.8.102 servicegraph.istio.jimmysong.io

172.17.8.102 zipkin.istio.jimmysong.io

我們可以通過下面的URL地址訪問以上的服務(wù)。

Service? ? ? ? ? ? ? ? ? URL

grafana? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?http://grafana.istio.jimmysong.io

servicegraph? ? ? ? ? ? ? ? ? ? ? ? http://servicegraph.istio.jimmysong.io/dotviz,? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?????????????????????????????????????????????http://servicegraph.istio.jimmysong.io/graph

zipkin? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?http://zipkin.istio.jimmysong.io

詳細(xì)信息請參閱? :?https://istio.io/docs/guides/bookinfo.html

部署示例應(yīng)用

在打包成鏡像部署到 kubernetes 集群上運行之前,我們先在本地運行所有示例。

本教程中三個服務(wù)之間的依賴關(guān)系如下:

customer → preference → recommendation

customer?和?preference?微服務(wù)是基于 Spring Boot 構(gòu)建的,recommendation?微服務(wù)是基于?vert.x?構(gòu)建的。

customer?和?preference?微服務(wù)的?pom.xml?文件中都引入了 OpenTracing 和 Jeager 的依賴。

本地運行

我們首先在本地確定所有的微服務(wù)都可以正常運行,然后再打包鏡像在 kubernetes 集群上運行。

啟動 Jaeger

使用 docker 來運行 jagger。

docker run -d \

? --rm \

? -p5775:5775/udp \

? -p6831:6831/udp \

? -p6832:6832/udp \

? -p16686:16686 \

? -p14268:14268 \

? jaegertracing/all-in-one:1.3

Jaeger UI 地址? ? ?http://localhost:16686

Customer

cd customer/java/springboot

JAEGER_SERVICE_NAME=customer mvn \

? spring-boot:run \

? -Drun.arguments="--spring.config.location=src/main/resources/application-local.properties"

服務(wù)訪問地址:?http://localhost:8280

Preference

cd preference/java/springboot

JAEGER_SERVICE_NAME=preference mvn \

? spring-boot:run \

? -Drun.arguments="--spring.config.location=src/main/resources/application-local.properties"

服務(wù)訪問地址http://localhost:8180

Recommendation

cd recommendation/java/vertx

mvn vertx:run

服務(wù)訪問地址:http://localhost:8080

所有服務(wù)都啟動之后,此時訪問?http://localhost:8280?將會看到如下輸出。

customer => preference => recommendation v1 from 'unknown': 1

每訪問一次最后的數(shù)字就會加 1。

Jaeger

此時訪問?http://localhost:16686?將看到 Jaeger query UI,所有應(yīng)用將 metrics 發(fā)送到 Jeager 中。

可以在 Jaeger UI 中搜索?customer?和?preference?service 的 trace 并查看每次請求的 tracing。

構(gòu)建鏡像

在本地運行測試無誤之后就可以構(gòu)建鏡像了。本教程中的容器鏡像都是在?fabric8/java-jboss-openjdk8-jdk?的基礎(chǔ)上構(gòu)建的。只要將 Java 應(yīng)用構(gòu)建出 Jar 包然后放到?/deployments?目錄下基礎(chǔ)鏡像就可以自動幫我們運行,所以我們看到著幾個應(yīng)用的?Dockerfile?文件中都沒有執(zhí)行入口,真正的執(zhí)行入口是?run-java.sh。

Customer

構(gòu)建 Customer 鏡像。

cd customer/java/springboot

mvn clean package

docker build -t jimmysong/istio-tutorial-customer:v1 .

docker push jimmysong/istio-tutorial-customer:v1

第一次構(gòu)建和上傳需要花費一點時間,下一次構(gòu)建就會很快。

Preference

構(gòu)建 Preference 鏡像。

cd preference/java/springboot

mvn clean package

docker build -t jimmysong/istio-tutorial-preference:v1 .

docker push jimmysong/istio-tutorial-preference:v1

Recommendation

構(gòu)建 Recommendation 鏡像。

cd recommendation/java/vertx

mvn clean package

docker build -t jimmysong/istio-tutorial-recommendation:v1 .

docker push jimmysong/istio-tutorial-recommendation:v1

現(xiàn)在三個 docker 鏡像都構(gòu)建完成了,我們檢查一下。

$ docker images | grep istio-tutorial

REPOSITORY? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? TAG? ? ? ? ? ? ? ? IMAGE ID? ? ? ? ? ? CREATED? ? ? ? ? ? SIZE

jimmysong/istio-tutorial-recommendation? v1? ? ? ? ? ? ? ? ? d31dd858c300? ? ? ? 51 seconds ago? ? ? 443MB

jimmysong/istio-tutorial-preference? ? ? v1? ? ? ? ? ? ? ? ? e5f0be361477? ? ? ? 6 minutes ago? ? ? 459MB

jimmysong/istio-tutorial-customer? ? ? ? v1? ? ? ? ? ? ? ? ? d9601692673e? ? ? ? 13 minutes ago? ? ? 459MB

部署到 Kubernetes

使用下面的命令將以上服務(wù)部署到 kubernetes。

# create new namespace

kubectl create ns istio-tutorial

# deploy recommendation

kubectl apply -f <(istioctl kube-inject -f recommendation/kubernetes/Deployment.yml) -n istio-tutorial

kubectl apply -f recommendation/kubernetes/Service.yml

# deploy preferrence

kubectl apply -f <(istioctl kube-inject -f preference/kubernetes/Deployment.yml) -n istio-tutorial

kubectl apply -f preference/kubernetes/Service.yml

# deploy customer

kubectl apply -f <(istioctl kube-inject -f customer/kubernetes/Deployment.yml) -n istio-tutorial

kubectl apply -f customer/kubernetes/Service.yml

注意:preference?和?customer?應(yīng)用啟動速度比較慢,我們將 livenessProb 配置中的?initialDelaySeconds?設(shè)置為?20秒。

查看 Pod 啟動狀態(tài):

kubectl get pod -w -n istio-tutorial

增加 Ingress 配置

為了在 kubernetes 集群外部訪問 customer 服務(wù),我們需要增加 ingress 配置。

kubectl apply -f ingress/ingress.yaml

修改本地的?/etc/hosts?文件,增加一條配置。

172.17.8.102 customer.istio-tutorial.jimmysong.io

現(xiàn)在訪問?http://customer.istio-tutorial.jimmysong.io?將看到如下輸出:

customer=> preference => recommendation v1 from '6fc97476f8-m2ntp': 1

批量訪問該地址。

./bin/poll_customer.sh

訪問?http://servicegraph.istio.jimmysong.io/dotviz?查看服務(wù)的分布式追蹤和依賴關(guān)系。

訪問?http://servicegraph.istio.jimmysong.io/dotviz?查看服務(wù)間的關(guān)系圖和 QPS。

訪問?http://grafana.istio.jimmysong.io?查看 Service Mesh 的監(jiān)控信息。

Istio 使用示例

為了試用 Istio 中的各種功能,我們需要為應(yīng)用構(gòu)建多個版本,我們?yōu)?recommendation 構(gòu)建 v2 版本的鏡像,看看如何使用 Istio 控制微服務(wù)的流量。

構(gòu)建 recommendation:v2

我們將構(gòu)建新版的?recommendation?服務(wù)的鏡像,并觀察?customer?對不同版本的?recommendataion?服務(wù)的訪問頻率。

修改?recommendation/java/vertx/src/main/java/com/redhat/developer/demos/recommendation/RecommendationVerticle.java?程序中代碼。

將?private static final String RESPONSE_STRING_FORMAT = "recommendation v1 from '%s': %d\n";?修改為?private static final String RESPONSE_STRING_FORMAT = "recommendation v2 from '%s': %d\n";

并構(gòu)建?recommendation:v2?鏡像。

cd recommendation/java/vertx

mvn clean package

docker build -t jimmysong/istio-tutorial-recommendation:v2 .

docker push jimmysong/istio-tutorial-recommendation:v2

將應(yīng)用部署到 kubernetes。

# deploy recommendation

kubectl apply -f <(istioctl kube-inject -f recommendation/kubernetes/Deployment-v2.yml) -n istio-tutorial

現(xiàn)在再訪問?customer?服務(wù),將看到如下輸出:

$ bin/poll_customer.sh

customer => preference => recommendation v2 from '77b9f6cc68-5xs27': 1

customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 3581

customer => preference => recommendation v2 from '77b9f6cc68-5xs27': 2

customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 3582

customer => preference => recommendation v2 from '77b9f6cc68-5xs27': 3

customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 3583

customer => preference => recommendation v2 from '77b9f6cc68-5xs27': 4

我們可以看到 v1 和 v2 版本的?recommendation?服務(wù)會被間隔訪問到。

我們再將 v2 版本的?recommendation?實例數(shù)設(shè)置成 2 個。

kubectl scale --replicas=2 deployment/recommendation-v2 -n istio-tutorial

kubectl get pod -w -n istio-tutorial

觀察?recommendation-v2?Pod 達(dá)到兩個之后再訪問?customer?服務(wù)。

$ bin/poll_customer.sh

customer => preference => recommendation v2 from '77b9f6cc68-j9fgj': 1

customer => preference => recommendation v2 from '77b9f6cc68-5xs27': 71

customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 3651

customer => preference => recommendation v2 from '77b9f6cc68-j9fgj': 2

customer => preference => recommendation v2 from '77b9f6cc68-5xs27': 72

customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 3652

customer => preference => recommendation v2 from '77b9f6cc68-j9fgj': 3

customer => preference => recommendation v2 from '77b9f6cc68-5xs27': 73

customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 3653

觀察輸出中 v1 和 v2 版本?recommendation?的訪問頻率。

將?recommendataion?服務(wù)的實例數(shù)恢復(fù)為 1。

kubectl scale --replicas=1 deployment/recommendation-v2

修改 Istio RouteRules

以下所有路有規(guī)則都是針對?recommendation?服務(wù),并在 repo 的根目錄下執(zhí)行。

將所有流量打給 v2

下面將演示如何動態(tài)的劃分不同版本服務(wù)間的流量,將所有的流量都打到?recommendation:v2。

istioctl create -f istiofiles/route-rule-recommendation-v2.yml -n istio-tutorial

現(xiàn)在再訪問?customer?服務(wù)將看到所有的流量都會打到?recommendation:v2。

刪除 RouteRules 后再訪問?customer?服務(wù)將看到又恢復(fù)了 v1 和 v2 版本的?recommendation?服務(wù)的間隔訪問。

istioctl delete routerule recommendation-default

切分流量

將 90% 的流量給 v1,10% 的流量給 v2。

istioctl create -f istiofiles/route-rule-recommendation-v1_and_v2.yml -n istio-tutorial

執(zhí)行bin/poll_customer.sh?觀察訪問情況。

要想動態(tài)切分流量只要修改 RouteRules 中的?weight?配置即可。

apiVersion:config.istio.io/v1alpha2kind:RouteRulemetadata:name:recommendation-v1-v2spec:destination:namespace:istio-tutorialname:recommendationprecedence:5route:-labels:version:v1weight:90-labels:version:v2weight:10

因為 RouteRule 有優(yōu)先級,為了繼續(xù)后面的實驗,在驗證完成后刪除該 RouteRule。

istioctl delete routerule recommendation-v1-v2 -n istio-tutorial

故障注入

有時候我們?yōu)榱嗽鰪娤到y(tǒng)的健壯性,需要對系統(tǒng)做混沌工程,故意注入故障,并保障服務(wù)可以自動處理這些故障。

注入 HTTP 503 錯誤

istioctl create -f istiofiles/route-rule-recommendation-503.yml -n istio-tutorial

有 50% 的幾率報 503 錯誤。

$ bin/poll_customer.sh

customer => preference => recommendation v2 from '77b9f6cc68-5xs27': 135

customer => 503 preference => 503 fault filter abort

customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 3860

customer => 503 preference => 503 fault filter abort

customer => 503 preference => 503 fault filter abort

customer => preference => recommendation v2 from '77b9f6cc68-5xs27': 136

customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 3861

customer => 503 preference => 503 fault filter abort

customer => 503 preference => 503 fault filter abort

customer => preference => recommendation v2 from '77b9f6cc68-5xs27': 137

customer => 503 preference => 503 fault filter abort

清理 RouteRule。

istioctl delete routerule recommendation-503 -n istio-tutorial

增加延遲

增加服務(wù)的訪問延遲。

istioctl create -f istiofiles/route-rule-recommendation-delay.yml -n istio-tutorial

會有 50% 的幾率訪問?recommendation?服務(wù)有 7 秒的延遲。百分比和延遲時間可以在 RouteRule 中配置。

清理 RouteRule。

istioctl delete routerule recommendation-delay -n istio-tutorial

重試

讓服務(wù)不是直接失敗,而是增加重試機(jī)制。

我們下面將同時應(yīng)用兩條 RouteRule,讓訪問?recommendation?服務(wù)時有 50% 的幾率出現(xiàn) 503 錯誤,并在出現(xiàn)錯誤的時候嘗試訪問 v2 版本,超時時間為 2 秒。

istioctl create -f istiofiles/route-rule-recommendation-v2_503.yml -n istio-tutorial

istioctl create -f istiofiles/route-rule-recommendation-v2_retry.yml -n istio-tutorial

執(zhí)行?bin/poll_customer.sh?我們看到一開始有些 503 錯誤,然后所有的流量都流向了 v2。

清理 RouteRules。

istioctl delete routerule recommendation-v2-retry -n istio-tutorial

istioctl delete routerule recommendation-v2-503 -n istio-tutorial

超時

設(shè)置超時時間,只有服務(wù)訪問超時才認(rèn)定服務(wù)訪問失敗。

取消注釋?recommendation/java/vertx/src/main/java/com/redhat/developer/demos/recommendation/RecommendationVerticle.java?中的下面一行,增加超時時間為 3 秒。

router.get("/").handler(this::timeout);

重新生成鏡像。

cd recommendation/java/vertx

mvn clean package

docker build -t jimmysong/istio-tutorial-recommendation:v2 .

docker push jimmysong/istio-tutorial-recommendation:v2

重新部署到 kubernetes。

kubectl delete -f recommendation/kubernetes/Deployment-v2.yml

因為我們重新構(gòu)建的鏡像使用了同樣的名字和 tag,而之前在?Deployment-v2.yml?中配置的鏡像拉取策略是?IfNotPresent,這樣的話即使我們構(gòu)建了新的鏡像也無法應(yīng)用到集群上,因此將鏡像拉取策略改成?Always?確保每次啟動 Pod 的時候都會拉取鏡像。

kubectl apply -f <(istioctl kube-inject -f recommendation/kubernetes/Deployment-v2.yml) -n istio-tutorial

啟用超時 RouteRules。

istioctl create -f istiofiles/route-rule-recommendation-timeout.yml -n istio-tutorial

訪問?customer?服務(wù)將看到如下輸出:

$ bin/poll_customer.sh

customer => 503 preference => 504 upstream request timeout

customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 4002

customer => 503 preference => 504 upstream request timeout

customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 4003

customer => 503 preference => 504 upstream request timeout

customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 4004

清理 RouteRules。

istioctl delete routerule recommendation-timeout -n istio-tutorial

基于 user-agent 的智能路由(金絲雀發(fā)布)

User-agent 是一個字符串,其中包含了瀏覽器的信息,訪問?https://www.whoishostingthis.com/tools/user-agent?獲取你的 user-agent。

我的 user-agent 是:

Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36

將所有的流量打到 v1。

istioctl create -f istiofiles/route-rule-recommendation-v1.yml -n istio-tutorial

將使用 Safari 瀏覽器訪問的流量打到 v2。

istioctl create -f istiofiles/route-rule-safari-recommendation-v2.yml -n istio-tutorial

誰用 Safari 或者 Chrome(Chrome 瀏覽器的 user-agent 中也包含 Safari 字段)訪問?http://customer.istio-tutorial.jimmysong.io/?在經(jīng)過 3 秒鐘(我們在前面重新編譯 v2 鏡像,設(shè)置了 3 秒超時時間)后將看到訪問 v2 的輸出。

或者使用 curl 訪問。

curl -A Safari http://customer.istio-tutorial.jimmysong.io/

curl -A Firefox http://customer.istio-tutorial.jimmysong.io/

觀察返回的結(jié)果。

將移動端用戶的流量導(dǎo)到 v2。

istioctl create -f istiofiles/route-rule-mobile-recommendation-v2.yml -n istio-tutorial

curl -A "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4(KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5" http://customer.istio-tutorial.jimmysong.io/

觀察輸出的結(jié)果。

清理 RouteRules。

istioctl delete routerule recommendation-mobile -n istio-tutorial

istioctl delete routerule recommendation-safari -n istio-tutorial

istioctl delete routerule recommendation-default -n istio-tutorial

鏡像流量

確保當(dāng)前至少運行了兩個版本的?recommendation?服務(wù),并且沒有 RouteRule。

注:可以使用?istioctl get routerule?獲取 RouteRule。

設(shè)置流量鏡像,將所有 v1 的流量都被鏡像到 v2。

istioctl create -f istiofiles/route-rule-recommendation-v1-mirror-v2.yml -n istio-tutorial

bin/poll_customer.sh

查看 recommendation-v2 的日志。

kubectl logs -f `oc get pods|grep recommendation-v2|awk '{ print $1 }'` -c recommendation

訪問控制

Istio 可以設(shè)置服務(wù)訪問的黑白名單,如果沒有權(quán)限的話會返回 HTTP 404 Not Found。

白名單

istioctl create -f istiofiles/acl-whitelist.yml -n istio-tutorial

此時訪問?customer?服務(wù)。

$ bin/poll_customer.sh

customer => 404 NOT_FOUND:preferencewhitelist.listchecker.istio-tutorial:customer is not whitelisted

重置環(huán)境。

istioctl delete -f istiofiles/acl-whitelist.yml -n istio-tutorial

黑名單

設(shè)置黑名單,所有位于黑名單中的流量將獲得 403 Forbidden 返回碼。

istioctl create -f istiofiles/acl-blacklist.yml -n istio-tutorial

此時訪問?customer?服務(wù)。

$ bin/poll_customer.sh

customer => 403 PERMISSION_DENIED:denycustomerhandler.denier.istio-tutorial:Not allowed

重置環(huán)境。

istioctl delete -f istiofiles/acl-blacklist.yml -n istio-tutorial

負(fù)載均衡

Kubernetes 中默認(rèn)的負(fù)載均衡策略是 round-robin,當(dāng)然我們可以使用 Istio 把它修改成 random。

增加 v1 的實例數(shù)。

kubectl scale deployment recommendation-v1 --replicas=2 -n istio-tutorial

持續(xù)訪問?customer?服務(wù)。

bin/poll_customer.sh

保持前臺輸出,觀察流量的行為。

應(yīng)用負(fù)載均衡策略。

istioctl create -f istiofiles/recommendation_lb_policy_app.yml -n istio-tutorial

觀察一段時間流量的行為后,重置環(huán)境。

istioctl delete -f istiofiles/recommendation_lb_policy_app.yml -n istio-tutorial

kubectl scale deployment recommendation-v1 --replicas=1 -n istio-tutorial

速率限制

暫時不可用

斷路器

當(dāng)達(dá)到最大連接數(shù)和最大掛起請求數(shù)時快速失敗。

將流量在 v1 和 v2 之間均分。

istioctl create -f istiofiles/route-rule-recommendation-v1_and_v2_50_50.yml -n istio-tutorial

未開啟斷路器的時候啟動負(fù)載測試。

$ siege -r 2 -c 20 -v customer.istio-tutorial.jimmysong.io

New configuration template added to /Users/jimmysong/.siege

Run siege -C to view the current settings in that file

** SIEGE 4.0.4

** Preparing 20 concurrent users for battle.

The server is now under siege...

HTTP/1.1 200? ? 0.10 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 200? ? 0.12 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 200? ? 0.13 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 200? ? 0.13 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 200? ? 0.13 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 200? ? 0.17 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 200? ? 3.12 secs:? ? ? 74 bytes ==> GET? /

HTTP/1.1 200? ? 3.14 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 200? ? 3.15 secs:? ? ? 74 bytes ==> GET? /

HTTP/1.1 200? ? 3.15 secs:? ? ? 74 bytes ==> GET? /

HTTP/1.1 200? ? 3.17 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 200? ? 3.17 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 200? ? 3.20 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 200? ? 3.20 secs:? ? ? 74 bytes ==> GET? /

HTTP/1.1 200? ? 0.05 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 200? ? 0.12 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 200? ? 3.15 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 200? ? 3.25 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 200? ? 3.26 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 200? ? 3.14 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 200? ? 3.58 secs:? ? ? 74 bytes ==> GET? /

HTTP/1.1 200? ? 6.15 secs:? ? ? 74 bytes ==> GET? /

HTTP/1.1 200? ? 6.16 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 200? ? 3.03 secs:? ? ? 74 bytes ==> GET? /

HTTP/1.1 200? ? 6.06 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 200? ? 6.04 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 200? ? 3.11 secs:? ? ? 74 bytes ==> GET? /

HTTP/1.1 200? ? 3.09 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 200? ? 6.15 secs:? ? ? 74 bytes ==> GET? /

HTTP/1.1 200? ? 6.71 secs:? ? ? 74 bytes ==> GET? /

HTTP/1.1 200? ? 3.52 secs:? ? ? 75 bytes ==> GET? /

^C

Lifting the server siege...

Transactions: ? ? ? ? ? 31 hits

Availability: ? ? ? 100.00 %

Elapsed time: ? ? ? ? 7.99 secs

Data transferred: ? ? ? ? 0.00 MB

Response time: ? ? ? ? 2.99 secs

Transaction rate: ? ? ? ? 3.88 trans/sec

Throughput: ? ? ? ? 0.00 MB/sec

Concurrency: ? ? ? 11.60

Successful transactions:? ? ? ? ? 31

Failed transactions: ? ? ? ? ? 0

Longest transaction: ? ? ? ? 6.71

Shortest transaction: ? ? ? ? 0.05

所有的請求都成功了,但是性能很差,因為 v2 版本設(shè)置了 3 秒的超時時間。

我們啟用下斷路器。

istioctl create -f istiofiles/recommendation_cb_policy_version_v2.yml -n istio-tutorial

重新測試一下。

$ siege -r 2 -c 20 -v customer.istio-tutorial.jimmysong.io

** SIEGE 4.0.4

** Preparing 20 concurrent users for battle.

The server is now under siege...

HTTP/1.1 200? ? 0.07 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 503? ? 0.07 secs:? ? ? 92 bytes ==> GET? /

HTTP/1.1 200? ? 0.07 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 503? ? 0.12 secs:? ? ? 92 bytes ==> GET? /

HTTP/1.1 503? ? 0.12 secs:? ? ? 92 bytes ==> GET? /

HTTP/1.1 200? ? 0.16 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 503? ? 0.16 secs:? ? ? 92 bytes ==> GET? /

HTTP/1.1 503? ? 0.21 secs:? ? ? 92 bytes ==> GET? /

HTTP/1.1 503? ? 0.21 secs:? ? ? 92 bytes ==> GET? /

HTTP/1.1 200? ? 0.24 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 200? ? 0.24 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 503? ? 0.14 secs:? ? ? 92 bytes ==> GET? /

HTTP/1.1 503? ? 0.29 secs:? ? ? 92 bytes ==> GET? /

HTTP/1.1 503? ? 0.13 secs:? ? ? 92 bytes ==> GET? /

HTTP/1.1 503? ? 0.18 secs:? ? ? 92 bytes ==> GET? /

HTTP/1.1 503? ? 0.13 secs:? ? ? 92 bytes ==> GET? /

HTTP/1.1 200? ? 0.11 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 200? ? 0.39 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 200? ? 0.24 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 503? ? 0.44 secs:? ? ? 92 bytes ==> GET? /

HTTP/1.1 200? ? 0.43 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 200? ? 0.44 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 503? ? 0.40 secs:? ? ? 92 bytes ==> GET? /

HTTP/1.1 200? ? 0.47 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 503? ? 0.42 secs:? ? ? 92 bytes ==> GET? /

HTTP/1.1 200? ? 0.42 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 200? ? 0.06 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 503? ? 0.07 secs:? ? ? 92 bytes ==> GET? /

HTTP/1.1 200? ? 0.15 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 200? ? 0.12 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 503? ? 0.57 secs:? ? ? 92 bytes ==> GET? /

HTTP/1.1 503? ? 0.18 secs:? ? ? 92 bytes ==> GET? /

HTTP/1.1 503? ? 0.52 secs:? ? ? 92 bytes ==> GET? /

HTTP/1.1 503? ? 0.65 secs:? ? ? 92 bytes ==> GET? /

HTTP/1.1 503? ? 0.42 secs:? ? ? 92 bytes ==> GET? /

HTTP/1.1 200? ? 0.09 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 200? ? 0.43 secs:? ? ? 75 bytes ==> GET? /

HTTP/1.1 503? ? 0.04 secs:? ? ? 92 bytes ==> GET? /

HTTP/1.1 200? ? 4.15 secs:? ? ? 74 bytes ==> GET? /

HTTP/1.1 200? ? 0.01 secs:? ? ? 75 bytes ==> GET? /

Transactions: ? ? ? ? ? 19 hits

Availability: ? ? ? 47.50 %

Elapsed time: ? ? ? ? 4.16 secs

Data transferred: ? ? ? ? 0.00 MB

Response time: ? ? ? ? 0.72 secs

Transaction rate: ? ? ? ? 4.57 trans/sec

Throughput: ? ? ? ? 0.00 MB/sec

Concurrency: ? ? ? ? 3.31

Successful transactions:? ? ? ? ? 19

Failed transactions: ? ? ? ? ? 21

Longest transaction: ? ? ? ? 4.15

Shortest transaction: ? ? ? ? 0.01

我們可以看到在啟用了斷路器后各項性能都有提高。

清理配置。

istioctl delete routerule recommendation-v1-v2 -n istio-tutorial

istioctl delete -f istiofiles/recommendation_cb_policy_version_v2.yml -n istio-tutorial

Pool Ejection

所謂的 Pool Ejection 就是當(dāng)某些實例出現(xiàn)錯誤(如返回 5xx 錯誤碼)臨時將該實例彈出一段時間后(窗口期,可配置),然后再將其加入到負(fù)載均衡池中。我們的例子中配置的窗口期是 15 秒。

將 v1 和 v2 的流量均分。

istioctl create -f istiofiles/route-rule-recommendation-v1_and_v2_50_50.yml -n istio-tutorial

增加 v2 的實例個數(shù)。

kubectl scale deployment recommendation-v2 --replicas=2 -n istio-tutorial

kubectl get pods -w

等待所有的 Pod 的狀態(tài)都啟動完成。

現(xiàn)在到 v2 的容器中操作。

$ kubectl exec recommendation-v2-785465d9cd-225ms -c recommendation /bin/bash

$ curl localhost:8080/misbehave

Following requests to '/' will return a 503

增加 Pool Ejection 配置。

istioctl create -f istiofiles/recommendation_cb_policy_pool_ejection.yml -n istio-tutorial

此時再訪問?customer?服務(wù)。

$ bin/poll_customer.sh

customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 10505

customer => preference => recommendation v2 from '785465d9cd-225ms': 2407

customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 10506

customer => preference => recommendation v2 from '785465d9cd-225ms': 2408

customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 10507

customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 10508

customer => preference => recommendation v1 from '6fc97476f8-m2ntp': 10509

customer => 503 preference => 503 recommendation misbehavior from '785465d9cd-ldc6j'

customer => preference => recommendation v2 from '785465d9cd-225ms': 2409

customer => preference => recommendation v2 from '785465d9cd-225ms': 2410

我們看到窗口期生效了,當(dāng)出現(xiàn) 503 錯誤后至少 15 秒后才會出現(xiàn)第二次。

即使有了負(fù)載均衡池彈出策略對于系統(tǒng)的彈性來說依然還不夠,如果你的服務(wù)有多個可用實例,可以將斷路器、重試Pool Ejection?等策略組合起來使用。

例如在以上的 Pool Ejection 的基礎(chǔ)上增加重試策略。

istioctl replace -f istiofiles/route-rule-recommendation-v1_and_v2_retry.yml -n istio-tutorial

現(xiàn)在再訪問?customer?服務(wù)就看不到 503 錯誤了。

清理配置。

kubectl scale deployment recommendation-v2 --replicas=1 -n istio-tutorial

istioctl delete routerule recommendation-v1-v2 -n istio-tutorial

istioctl delete -f istiofiles/recommendation_cb_policy_pool_ejection.yml -n istio-tutorial

Egress

Egress 是用來配置 Istio serivce mesh 中的服務(wù)對外部服務(wù)的訪問策略。

具體配置請參考?控制 Egress 流量。

以下示例還有問題,無法正常工作。

構(gòu)建示例鏡像 egresshttpbin。

cd egress/egresshttpbin/

mvn clean package

docker build -t jimmysong/istio-tutorial-egresshttpbin:v1 .

docker push jimmysong/istio-tutorial-egresshttpbin:v1

部署到 Kubernetes。

kubectl apply -f <(istioctl kube-inject -f egress/egresshttpbin/src/main/kubernetes/Deployment.yml) -n istio-toturial

kubectl create -f egress/egresshttpbin/src/main/kubernetes/Service.yml

為了在 kubernetes 集群外部訪問到該服務(wù),修改增加 ingress 配置并修改本地的/etc/hosts?文件,我們在前面已經(jīng)完成了,此處不再贅述。

構(gòu)建示例鏡像 egressgithub。

cd egress/egressgithub

mvn clean package

docker build -t jimmysong/istio-tutorial-egressgithub:v1 .

docker push jimmysong/istio-tutorial-egressgithub:v1

部署到 Kubernetes。

kubectl apply -f <(istioctl kube-inject -f egress/egressgithub/src/main/kubernetes/Deployment.yml) -n istio-tutorial

kubectl create -f egress/egressgithub/src/main/kubernetes/Service.yml

增加 Egress 配置。

istioctl create -f istiofiles/egress_httpbin.yml -n istio-tutorial

到 egresshttpbin 容器中測試。

kubectl exec -it $(oc get pods -o jsonpath="{.items[*].metadata.name}" -l app=egresshttpbin,version=v1) -c egresshttpbin /bin/bash

curl localhost:8080

curl httpbin.org/user-agent

curl httpbin.org/headers

exit

增加對?jimmysong.io?的 egress 配置。

cat <<EOF | istioctl create -f -

apiVersion: config.istio.io/v1alpha2

kind: EgressRule

metadata:

? name: jimmysong-egress-rule

? namespace: istio-tutorial

spec:

? destination:

? ? service: jimmysong.io

? ports:

? ? - port: 443

? ? ? protocol: https

EOF

增加 Egress 配置。

istioctl create -f istiofiles/egress_github.yml -n istio-tutorial

到 egressgithub 容器中測試。

kubectl exec -it $(oc get pods -o jsonpath="{.items[*].metadata.name}" -l app=egressgithub,version=v1) -c egressgithub /bin/bash

curl http://jimmysong:443

exit

清理環(huán)境。

istioctl delete egressrule httpbin-egress-rule jimmysong-egress-rule github-egress-rule -n istio-tutorial

參考

https://github.com/redhat-developer-demos/istio-tutorial

Book - Introducing Istio Service Mesh for Microservices

文章來源地址:https://jimmysong.io/posts/istio-tutorial/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Service Mesh新秀,初出茅廬便聲勢浩蕩,前有Google,IBM和Lyft傾情奉獻(xiàn),后有業(yè)界大佬俯首膜拜...
    燕京博士閱讀 7,299評論 3 19
  • Service Mesh新秀,初出茅廬便聲勢浩蕩,前有Google,IBM和Lyft傾情奉獻(xiàn),后有業(yè)界大佬俯首膜拜...
    datazhen閱讀 5,852評論 1 31
  • 齙牙兔,對姐姐抱怨她,越來越討厭她,,不知道她是否在門外偷聽,她很廢,心里沒數(shù),總覺得豐聰明,,內(nèi)心情感更豐富,,...
    時間的列車飛馳閱讀 307評論 0 0
  • 【耕秋有得】 ---古香老人 童真入道十余秋,弗改童真何復(fù)求? 烏墨不耽塵濁色,深心豈為利名憂。 青燈恒照孤...
    籬下老人閱讀 855評論 2 5
  • 路邊的妹妹摔倒了,手里小蛋糕掉在地上,妹妹哇哇大哭,小米一直站在旁邊傻看。 等小妹妹走遠(yuǎn)了,小米興奮地告訴我說:媽...
    米小讀書閱讀 250評論 0 6

友情鏈接更多精彩內(nèi)容