服務網格-istio初體驗


什么是Istio

istio是一個開源的實現了服務網格的平台,基於k8s平台,具有負載均衡、服務間認證、監控等功能,為業務應用服務。

安裝Istio

istio的安裝是基於k8s平台的,本地測試可以使用minikube搭建k8s本平台,具體看我的minikube安裝 https://github.com/qq1141000259/k8s-learning/tree/master/Minikube

  • 通過istioctl 安裝

    curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.5.1 sh 下載

    istioctl profile list 查看安裝規則一般選擇 demo,istioctl manifest apply --set profile=demo

    你能夠看到很多服務組件都是安裝在 namespace istio-system下

    查看安裝的服務 kubectl get svc -n istio-system

    安裝kiali

    • 修改kiali

      kubectl edit svc kiali -n istio-system

      將type: clustIP 改為 type: NodePort,這樣更好測試訪問

    • 給kiali添加密碼,其實就是給kilia service掛載一個Secret

      USERNAME=$(echo -n 'admin' | base64)
      PASSPHRASE=$(echo -n 'admin' | base64)
      NAMESPACE=istio-system
      kubectl create namespace $NAMESPACE
      cat <<EOF | kubectl apply -f -
      apiVersion: v1
      kind: Secret
      metadata:
      name: kiali
      namespace: $NAMESPACE
      labels:
        app: kiali
      type: Opaque
      data:
      username: $USERNAME
      passphrase: $PASSPHRASE
      EOF
    • 查看kiali映射在宿主機的端口

      k describe svc kiali -n istio-system 找到 NodePort(這個端口號是變換的)

      NodePort:                 http-kiali  30717/TCP

      接下來訪問kiali: http://本機ip:30717/ ,效果如下:

 

安裝應用 bookinfo

這是一個 istio的應用范例

  • 我們在默認的namespace下創建我們的應用, 給default添加標簽

    kubectl label namespace default istio-injection=enabled

  • 到istio的安裝包下安裝bookinfo的應用

    kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml

    這些應用安裝在default下:kubectl get pods

 

安裝bookinfo-gateway

  kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml

  查看安裝: kubectl get gateway

  查看網關:kubectl get svc istio-ingressgateway -n istio-system

 

 

其中 80:30833對應的就是的外網訪問端口

訪問bookinfo http://本機IP:30833/productpage

在kiali中你能看到每個應用的調用關系

istio-kiali-bookinfo

 

Itsio的路由過程

1. 在簡單的搭建好一個服務網格的系統之后,我們接下來就主要關注於在這個網格里,是如何上線一個應用的

首先實現外部請求訪問服務網格的應用,本質就是實現外部訪問k8s,在上述例子中使用的其實是Istio部署的LoadBalancer服務

執行kubectl get svc -n istio-system -l istio=ingressgateway -o yaml查看這個服務詳情

apiVersion: v1
items:
- apiVersion: v1
  kind: Service
  metadata:
      ...
  spec:
    clusterIP: 10.96.121.156
    externalTrafficPolicy: Cluster
    ports:
    - name: status-port
      nodePort: 32362
      port: 15020
      protocol: TCP
      targetPort: 15020
    - name: http2
      nodePort: 30833
      port: 80
      protocol: TCP
      targetPort: 80
    ...
    selector:
      app: istio-ingressgateway

在selector中,它指定了一個標簽為app=istio-ingressgateway的pod,也就是說所有發送給這個loadblance服務的請求,都會被發送到這個pod,且對外的端口30833對應的是pod的端口80

找到這個podkubectl get pods -l app=istio-ingressgateway -n istio-system

你好,歡迎使用kubectl
NAME                                    READY   STATUS    RESTARTS   AGE
istio-ingressgateway-649f9646d4-m2cz2   1/1     Running   0          5d2h

而這個pod則是通過一個叫 istio-ingressgateway的deployment(具有k8s rc的所有特性,還能進行版本控制)進行管理

 

2. 我們已經知道了外界與服務網格間通信是通過一個叫 istio-ingressgateway 的 LoadBlance 服務實現的,那從LB到我們的應用productpage又是怎么走的呢

回顧之前,我們在namepspace為default下創建bookinfo應用時,也創建了一個bookinfo-gateway的gateway資源, 顯而易見,這個bookiinfo-gateway就是控制着任何要進入我們的應用的請求

查看bookiinfo-gateway:kubectl get gw bookinfo-gateway -o yaml

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
    ...
spec:
  selector:
    istio: ingressgateway
  servers:
  - hosts:
    - '*'
    port:
      name: http
      number: 80
      protocol: HTTP

整個定義內容的意思:所有符合標簽 istio=ingressgateway的pod將去監聽 80 端口,且接受來自所有主機的請求

我們來看看是這個Gateway作用在哪個pod上,其實這里涉及到一個問題,我們實際去查看的時候,在namespace為 default下是沒有標簽為這個的pod,反而在istio-system下存在這個pod

kubectl get pods -l istio=ingressgateway -n istio-system

你好,歡迎使用kubectl
NAME                                    READY   STATUS    RESTARTS   AGE
istio-ingressgateway-649f9646d4-m2cz2   1/1     Running   0          5d4h

且這個pod就是我們上面說的LB服務轉發的pod,也就是通過deployment創建生成的那個pod,且這個pod是跨命名空間的,也就說雖然bookinfo的bookinfo-gateway和我們的deployment istio-ingressgateway不在一個namespace,但在default下的bookinfo-gateway還是能夠作用到istio-ingressgateway上。

當我們沒有啟動bookinfo應用時,進入到這個istio-ingressgateway的pod,查看端口監聽情況,是沒有找到80端口被監聽,但當我們啟動了bookinfo的bookinfo-gateway就能很快發現多了一個監聽端口 80。

到此我們已經能夠從k8s集群之外(也就是 istio 框架外)訪問到我們的服務網格的網關istio-ingressgateway,通過網關又能找到我們應用網關bookinfo-gateway

 

 3. 現在我們知道了從外部請求到應用的網關bookinfo-gateway,那么又是如何進入到應用的呢

還是通過創建bookinfo-gateway的yaml來分析,發現在創建gateway資源的同時還創建了VirtualService, samples/bookinfo/networking/bookinfo-gateway.yaml

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: bookinfo
spec:
  hosts:
  - "*"
  gateways:
  - bookinfo-gateway
  http:
  - match:
    - uri:
        exact: /productpage
    - uri:
        prefix: /static
    - uri:
        exact: /login
    - uri:
        exact: /logout
    - uri:
        prefix: /api/v1/products
    route:
    - destination:
        host: productpage
        port:
          number: 9080

在istio框架中,虛擬服務(Virtual service)和目標規則(destination rule),是流量路由功能的關鍵組成。其中spec.gateways的gatewaysbookinfo-gateway,也就是說這個gateway收到的請求會匹配到http中的uri下,並且轉發的目標地址為productpage服務下的9080端口,我們可以看下這個productpage服務

你好,歡迎使用kubectl
NAME          TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
productpage   ClusterIP   10.96.41.204   <none>        9080/TCP   4d22h

再查看這個服務作用的pod為app=productpage

你好,歡迎使用kubectl
NAME                              READY   STATUS    RESTARTS   AGE
productpage-v1-596598f447-wkvxj   2/2     Running   0          5d1h

如果你用kubectl exec -it productpage-v1-596598f447-wkvxj /bin/bash進入,你就會發現這個productpage其實是一個Flask(python的web框架)的應用,代碼里用requests發起請求去訪問另外三個服務 ratings, reviews, details, 通過ClushIP進行容器間通信, 在pod內進入python命令行模式我們進行測試

>>> res = requests.get("http://reviews:9080/reviews/1")
>>> res
<Response [200]>
>>> res.text
'{"id": "1","reviews": [{  "reviewer": "Reviewer1",  "text": "An extremely entertaining play by Shakespeare. The slapstick humour is refreshing!", "rating": {"stars": 5, "color": "black"}},{  "reviewer": "Reviewer2",  "text": "Absolutely fun and entertaining. The play lacks thematic depth when compared to other plays by Shakespeare.", "rating": {"stars": 4, "color": "black"}}]}'

再回到宿主機,我們來查看另外三個服務

kubectl get svc
你好,歡迎使用kubectl
NAME          TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
details       ClusterIP   10.96.132.128   <none>        9080/TCP   5d1h
kubernetes    ClusterIP   10.96.0.1       <none>        443/TCP    5d17h
productpage   ClusterIP   10.96.41.204    <none>        9080/TCP   4d23h
ratings       ClusterIP   10.96.95.141    <none>        9080/TCP   5d1h
reviews       ClusterIP   10.96.235.173   <none>        9080/TCP   5d1h

其中kubernetes 是minikube所生成的,在看它們作用的pod

kubectl get pods
你好,歡迎使用kubectl
NAME                              READY   STATUS    RESTARTS   AGE
details-v1-78d78fbddf-p98fn       2/2     Running   0          5d1h
productpage-v1-596598f447-wkvxj   2/2     Running   0          5d1h
ratings-v1-6c9dbf6b45-v8nqg       2/2     Running   0          5d1h
reviews-v1-7bb8ffd9b6-hsdb7       2/2     Running   0          5d1h
reviews-v2-d7d75fff8-2hw7m        2/2     Running   0          5d1h
reviews-v3-68964bc4c8-6hllk       2/2     Running   0          5d1h

我們會發現這個reviews居然有三個pod,還分成了1,2,3版本。這里其實是對review這個應用起了三個deployment來管理三個版本的pod

kubek get deployment
你好,歡迎使用kubectl
NAME             READY   UP-TO-DATE   AVAILABLE   AGE
details-v1       1/1     1            1           5d1h
productpage-v1   1/1     1            1           5d1h
ratings-v1       1/1     1            1           5d1h
reviews-v1       1/1     1            1           5d1h
reviews-v2       1/1     1            1           5d1h
reviews-v3       1/1     1            1           5d1h

而這三個版本就是deployement資源的特征,在管理pod的時候又能進行版本控制,三個版本對應的效果

V1: 在productpage頁面不會顯示評分信息

V2: 在productpage頁面顯示1到5個黑色評分信息

V3: 在productpage頁面顯示1到5個紅色評分信息

在默認的情況下,你對 reviews服務發起請求,將會被均勻的分配在這三個版本的應用上,你不斷在http://9.134.114.175:30833/productpage 這個頁面刷新觀察評分就能看到這樣的效果。

但是,如果我想取消掉某個應用的請求,或分配權重,我們可以通過給reviews服務增加virtualService + DestinationRule來控制轉發, samples/bookinfo/networking/virtual-service-reviews-v2-v3.yaml

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
    - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v2
      weight: 50
    - destination:
        host: reviews
        subset: v3
      weight: 50

如你所見,我們在為 reviews這個host配置了權重為50的轉發規則,它們的subset 分別是v2和v3,這個subset將會指引我們去DestinationRule中找到對應的pod

samples/bookinfo/networking/destination-rule-reviews.yaml

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: reviews
spec:
  host: reviews
  trafficPolicy:
    loadBalancer:
      simple: RANDOM
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
  - name: v3
    labels:
      version: v3

我們能夠看到對於subsets下分別分配了不同的label屬性--version,其實這些就是我們的reviews服務下的所有pod

kubectl get pods -l app=reviews --show-labels
你好,歡迎使用kubectl
NAME                          READY   STATUS    RESTARTS   AGE    LABELS
reviews-v1-7bb8ffd9b6-hsdb7   2/2     Running   0          5d1h   app=reviews,pod-template-hash=7bb8ffd9b6,security.istio.io/tlsMode=istio,version=v1
reviews-v2-d7d75fff8-2hw7m    2/2     Running   0          5d1h   app=reviews,pod-template-hash=d7d75fff8,security.istio.io/tlsMode=istio,version=v2
reviews-v3-68964bc4c8-6hllk   2/2     Running   0          5d1h   app=reviews,pod-template-hash=68964bc4c8,security.istio.io/tlsMode=istio,version=v3

接下來,我們分別應用這兩個配置,必須兩個都要

k apply -f destination-rule-reviews.yamlkubectl apply -f virtual-service-reviews-v2-v3.yaml

k get virtual-service
你好,歡迎使用kubectl
NAME       GATEWAYS             HOSTS       AGE
bookinfo   [bookinfo-gateway]   [*]         5d1h
reviews                         [reviews]   16s

k get destinationrule
你好,歡迎使用kubectl
NAME      HOST      AGE
reviews   reviews   5s

至此整個路由關系已經打通了

 

 

 

附上我的k8s學習項目- https://github.com/qq1141000259/k8s-learning

 


免責聲明!

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



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