天天看點

非容器應用與K8s工作負載的服務網格化實踐-5 基于ASM的POD和VM混合流量轉移實踐

本系列的第一篇展示了WorkloadEntry帶來的VM與POD同等負載能力。第二、三篇展示了ASM VM PROXY帶來的VM流量轉移能力。本篇将結合這兩種能力,完整地展示ASM支援非容器應用網格化的流量管理能力。由于篇幅所限,安全相關能力不做展示,但網格化後VM中的應用間、及與POD互訪都具備了請求認證和來源認證的能力,再結合RBAC可以完整實作認證和授權。

1 搭建實驗環境

本篇實驗将完整展示端到端的全鍊路POD和VM混合流量轉移。示例需要一個ack叢集和2個ecs節點。在ack叢集中,包含hello1/hello2/hello3 各1個版本為

en

的POD,2個ecs節點各啟動一個hello2 app,每個app對應一個版本(

fr

/

es

)的hello容器。

請求從hello1 POD到hello2 service(endpoints包含ack中的一個hello2 POD和ecs中的2個hello2 app),再hello2到hello3 POD。在此基礎上,我們希望路由到hello2

en

fr

es

的流量比例為:30%:60%:10%。

非容器應用與K8s工作負載的服務網格化實踐-5 基于ASM的POD和VM混合流量轉移實踐
示例(http_hybrid_demo)

包含如下元素:

  • hello1/hello2/hello3 deployment(鏡像http_springboot_v1)
  • hello2 docker containers(鏡像http_springboot_v1/http_springboot_v2/http_springboot_v3)
  • 入口網關:istio-ingressgateway
  • 入口流量配置:gateway/virtualservice
  • hello1流量配置:hello1 service/hello1 virtualservice/hello1 destinationrule
  • hello2流量配置:hello2 service/hello2 virtualservice/hello2 destinationrule
  • hello3流量配置:hello3 service/hello3 virtualservice/hello3 destinationrule
  • hello2 serviceentry/hello2 workloadentry

hello2 POD和VM

本篇實驗的核心是将POD和VM作為同一Service下的負載。通過配置VirtualService流量比例,讓上遊服務按照配比路由到POD和VM。

首先來看hello2的

deployment

,示意如下。

  • 标簽

    app: hello2-deploy

    這個配置需要和餘文的workloadentry中的一緻
  • version: v1

    和鏡像

    http_springboot_v1

    決定了這是hello2 service中的版本1的endpoint
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: hybrid-hello
  name: hello2-deploy-v1
  labels:
    app: hello2-deploy
    version: v1
spec:
...
    spec:
      containers:
        - name: hello-v1-deploy
          image: registry.cn-beijing.aliyuncs.com/asm_repo/http_springboot_v1:1.0.1
          env:
            - name: HTTP_HELLO_BACKEND
              value: "hello3-svc.hybrid-hello.svc.cluster.local"
...           

緊接着,我們來看相應的hello2 v2和v3的執行個體。在VM中按如下指令啟動Docker Container:

sh vm/ssh2.sh

docker run \
--rm \
--network host \
--name http_v2 \
-e HTTP_HELLO_BACKEND=hello3-svc.hybrid-hello.svc.cluster.local \
registry.cn-beijing.aliyuncs.com/asm_repo/http_springboot_v2:1.0.1           
sh vm/ssh3.sh

docker run \
--rm \
--network host \
--name http_v3 \
-e HTTP_HELLO_BACKEND=hello3-svc.hybrid-hello.svc.cluster.local \
registry.cn-beijing.aliyuncs.com/asm_repo/http_springboot_v3:1.0.1           

然後,我們通過如下指令建立WorkloadEntry,将VM中的Docker Containers加入網格。

aliyun servicemesh AddVmAppToMesh \
--ServiceMeshId "$MESH_ID" \
--Namespace hybrid-hello \
--ServiceName hello2-svc \
--Ips "$VM_PRI_2","$VM_PRI_3" \
--Ports http:8001 \
--Labels app=hello2-deploy \
--Force true           

這裡定義的标簽

app=hello2-deploy

與前文中hello2 deployment中定義的一緻。

2 互訪驗證

執行如下腳本部署上述及其他CRD,完成實驗環境的基本搭建。腳本在

http_hybrid_demo/asm

路徑下,不再冗述。

sh asm/ack.deploy.sh
sh asm/asm.deploy.sh
sh vm/dns.fake.sh           

本篇的

互訪驗證

較之前兩篇,須重點關注從hello1到hello2各endpoints的情況。因為這是混合流量的關鍵點。

首先從hello1 POD出發,直接通路hello2的3個endpoints:

echo "1 Test access vm ip directly"

echo "curl to POD $hello2_ip"
k exec "$hello2_pod" -c hello-v1-deploy -n hybrid-hello -- curl -s localhost:8001/hello/eric
echo
VMS=("$VM_PRI_2" "$VM_PRI_3")
for vm in "${VMS[@]}"; do
  echo "curl to VM $vm"
  k exec "$hello1_pod" -c hello-v1-deploy -n hybrid-hello -- \
    curl -s "$vm":8001/hello/eric
  echo
done           

期待的結果如下,證明hello1 POD到hello2 endpoints之間的鍊路是通的。

curl to POD 172.18.0.194
Hello eric(172.18.0.194)<-Hello eric(172.18.0.254)
curl to VM 192.168.0.171
Bonjour eric(192.168.0.171)<-Hello eric(172.18.0.254)
curl to VM 192.168.0.172
Hola eric(192.168.0.172)<-Hello eric(172.18.0.254)           

然後我們在hello1 POD中請求hello2 service,驗證依次路由到這3個endpoints:

for i in {1..6}; do
  k exec "$hello1_pod" -c hello-v1-deploy -n hybrid-hello -- \
    curl -s hello2-svc.hybrid-hello.svc.cluster.local:8001/hello/eric
  echo
done           

期待的結果如下,證明3個hello2的各endpoints可以被hello2 service成功發現。這一步是最關鍵的。

因為hello1可以成功通路到hello2 service後面的3個endpoints,意味着作為同一個service的POD和VM混合流量管理基本驗證通過。

Hello eric(172.18.0.194)<-Hello eric(172.18.0.254)
Hola eric(192.168.0.172)<-Hello eric(172.18.0.254)
Bonjour eric(192.168.0.171)<-Hello eric(172.18.0.254)           

最後我們向hello1 service發起請求,确認3個service鍊路的情況:

for i in {1..6}; do
  resp=$(k exec "$hello1_pod" -c hello-v1-deploy -n hybrid-hello -- curl -s hello1-svc.hybrid-hello.svc.cluster.local:8003/hello/eric)
  echo $i "$resp"
done           

期待的結果如下,3個service的實體鍊路驗證完畢。

1 Hello eric(172.18.1.8)<-Bonjour eric(192.168.0.171)<-Hello eric(172.18.0.254)
2 Hello eric(172.18.1.8)<-Hello eric(172.18.0.194)<-Hello eric(172.18.0.254)
3 Hello eric(172.18.1.8)<-Hola eric(192.168.0.172)<-Hello eric(172.18.0.254)           

3 流量轉移

接下來,我們部署hello2的virtualservice和destinationrule,驗證混合POD和VM的流量轉移。

流量配置

sh asm/asm_traffic_shift.sh           

執行如下腳本驗證流量配比的配置已經生效:

m get virtualservice -n hybrid-hello hello2-vs -o jsonpath={.spec.http[0].route}                  

期待的結果如下:

[map[destination:map[host:hello2-svc subset:v1] weight:30] map[destination:map[host:hello2-svc subset:v2] weight:60] map[destination:map[host:hello2-svc subset:v3] weight:10]]           

編輯workloadentry,增加version标簽:

spec:
  address: 192.168.0.171
  labels:
    app: hello-workload
    version: v2           
spec:
  address: 192.168.0.172
  labels:
    app: hello-workload
    version: v3           

流量驗證

sh asm/test_mesh.sh

hello1_pod=$(k get pod -l app=hello1-deploy -n hybrid-hello -o jsonpath={.items..metadata.name})

for i in {1..100}; do
  resp=$(k exec "$hello1_pod" -c hello-v1-deploy -n hybrid-hello -- curl -s hello1-svc.hybrid-hello.svc.cluster.local:8003/hello/eric)
  echo "$resp" >>test_traffic_shift_result
done

echo "expected 30%(Hello eric)-60%(Bonjour eric)-10%(Hola eric):"
sort test_traffic_shift_result | uniq -c | sort -nrk1           
expected 30%(Hello eric)-60%(Bonjour eric)-10%(Hola eric):
  54 Hello eric(172.18.1.8)<-Bonjour eric(192.168.0.171)<-Hello eric(172.18.0.254)
  34 Hello eric(172.18.1.8)<-Hello eric(172.18.0.194)<-Hello eric(172.18.0.254)
  12 Hello eric(172.18.1.8)<-Hola eric(192.168.0.172)<-Hello eric(172.18.0.254)           

4 全鍊路

最後我們增加gateway進行端到端驗證。執行

asm_z.sh腳本

增加配置:

sh asm/asm_z.sh           

執行

test_z.sh腳本

進行全鍊路流量轉義的驗證。示意如下:

alias k="kubectl --kubeconfig $USER_CONFIG"
IP=$(k -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')

for i in {1..100}; do
  resp=$(curl -s "$IP":8003/hello/asm)
  echo $i "$resp"
  if [[ -z $resp ]]; then
    echo "error in accessing loop, stop."
    rm -rf z_result
    exit
  fi
  echo "$resp" >>z_result
done

echo "expected 30%(Hello eric)-60%(Bonjour eric)-10%(Hola eric):"
sort z_result | uniq -c | sort -nrk1           
expected 30%(Hello eric)-60%(Bonjour eric)-10%(Hola eric):
  61 Hello asm(172.18.0.245)<-Bonjour asm(192.168.0.170)<-Hello asm(172.18.0.247)
  28 Hello asm(172.18.0.245)<-Hello asm(172.18.0.246)<-Hello asm(172.18.0.247)
  11 Hello asm(172.18.0.245)<-Hola asm(192.168.0.172)<-Hello asm(172.18.0.247)           

到此,POD和VM混合流量轉移驗證完畢。實驗示例使用的是http協定,結合前一篇我們可以完成grpc協定的POD和VM混合流量轉移的實踐,不再冗述。

本篇示例完整示範了非容器應用網格化過程中最重要的場景。覆寫到從istio-ingressgateway到deployment、workloadentry等各種CRD的配置,完整地展示了POD和VM作為同一個service的混合流量的各技術點的配置。

接下來,我們将視角深入VM中,完成VM中應用的分組和同一分組的多個副本動态加入和删除的實作。