Επιστροφή στις microservices με το Istio. Μέρος 2

Επιστροφή στις microservices με το Istio. Μέρος 2

Σημείωση. μετάφρ.: Το πρώτο μέρος Αυτή η σειρά ήταν αφιερωμένη στην εισαγωγή των δυνατοτήτων του Istio και στην επίδειξή τους στην πράξη. Τώρα θα μιλήσουμε για πιο σύνθετες πτυχές της διαμόρφωσης και της χρήσης αυτού του πλέγματος υπηρεσιών, και ειδικότερα, για τη λεπτομερή δρομολόγηση και τη διαχείριση της κυκλοφορίας δικτύου.

Σας υπενθυμίζουμε επίσης ότι το άρθρο χρησιμοποιεί διαμορφώσεις (μανιφέστα για Kubernetes και Istio) από το αποθετήριο ιστιο-μαεστρία.

διαχείριση της κυκλοφορίας

Με το Istio, εμφανίζονται νέες δυνατότητες στο σύμπλεγμα για να παρέχουν:

  • Δυναμική δρομολόγηση αιτημάτων: κυκλοφορία καναρινιών, δοκιμή A/B.
  • Εξισορρόπηση φορτίου: απλό και συνεπές, βασισμένο σε κατακερματισμούς.
  • Ανάρρωση μετά από πτώσεις: χρονικά όρια, επαναλήψεις, διακόπτες κυκλώματος.
  • Εισαγωγή σφαλμάτων: καθυστερήσεις, απόρριψη αιτημάτων κ.λπ.

Καθώς το άρθρο συνεχίζει, αυτές οι δυνατότητες θα απεικονιστούν χρησιμοποιώντας την επιλεγμένη εφαρμογή ως παράδειγμα και νέες έννοιες θα εισαχθούν στην πορεία. Η πρώτη τέτοια ιδέα θα είναι DestinationRules (δηλαδή κανόνες σχετικά με τον παραλήπτη της κίνησης/αιτημάτων - περίπου μετάφρ.), με τη βοήθεια του οποίου ενεργοποιούμε το A/B testing.

Δοκιμές A/B: DestinationRules στην πράξη

Η δοκιμή A/B χρησιμοποιείται σε περιπτώσεις όπου υπάρχουν δύο εκδόσεις μιας εφαρμογής (συνήθως είναι οπτικά διαφορετικές) και δεν είμαστε 100% σίγουροι ποια θα βελτιώσει την εμπειρία χρήστη. Επομένως, εκτελούμε και τις δύο εκδόσεις ταυτόχρονα και συλλέγουμε μετρήσεις.

Για να αναπτύξετε τη δεύτερη έκδοση του frontend, που απαιτείται για την επίδειξη της δοκιμής A/B, εκτελέστε την ακόλουθη εντολή:

$ kubectl apply -f resource-manifests/kube/ab-testing/sa-frontend-green-deployment.yaml
deployment.extensions/sa-frontend-green created

Η δήλωση ανάπτυξης για την πράσινη έκδοση διαφέρει σε δύο σημεία:

  1. Η εικόνα βασίζεται σε διαφορετική ετικέτα - istio-green,
  2. Οι λοβοί έχουν ετικέτα version: green.

Δεδομένου ότι και οι δύο αναπτύξεις έχουν μια ετικέτα app: sa-frontend, αιτήματα που δρομολογούνται από την εικονική υπηρεσία sa-external-services για σέρβις sa-frontend, θα ανακατευθυνθεί σε όλες τις παρουσίες του και το φορτίο θα διανεμηθεί μέσω αλγόριθμος round-robin, η οποία θα οδηγήσει στην ακόλουθη κατάσταση:

Επιστροφή στις microservices με το Istio. Μέρος 2
Τα αρχεία που ζητήθηκαν δεν βρέθηκαν

Αυτά τα αρχεία δεν βρέθηκαν επειδή ονομάζονται διαφορετικά σε διαφορετικές εκδόσεις της εφαρμογής. Ας βεβαιωθούμε για αυτό:

$ curl --silent http://$EXTERNAL_IP/ | tr '"' 'n' | grep main
/static/css/main.c7071b22.css
/static/js/main.059f8e9c.js
$ curl --silent http://$EXTERNAL_IP/ | tr '"' 'n' | grep main
/static/css/main.f87cd8c9.css
/static/js/main.f7659dbb.js

Αυτό σημαίνει ότι index.html, ζητώντας μια έκδοση στατικών αρχείων, μπορεί να σταλεί από το load balancer σε pods που έχουν διαφορετική έκδοση, όπου, για προφανείς λόγους, τέτοια αρχεία δεν υπάρχουν. Επομένως, για να λειτουργήσει η εφαρμογή, πρέπει να ορίσουμε έναν περιορισμό:η ίδια έκδοση της εφαρμογής που εξυπηρετούσε το index.html θα πρέπει να εξυπηρετεί επόμενα αιτήματα».

Θα φτάσουμε εκεί με συνεπή εξισορρόπηση φορτίου που βασίζεται σε κατακερματισμό (Συνεπής εξισορρόπηση φόρτωσης κατακερματισμού). Σε αυτή την περίπτωση Τα αιτήματα από τον ίδιο πελάτη αποστέλλονται στην ίδια παρουσία υποστήριξης, για την οποία χρησιμοποιείται μια προκαθορισμένη ιδιότητα - για παράδειγμα, μια κεφαλίδα HTTP. Υλοποιήθηκε χρησιμοποιώντας DestinationRules.

Κανόνες προορισμού

Μετά VirtualService έστειλε ένα αίτημα στην επιθυμητή υπηρεσία, χρησιμοποιώντας το DestinationRules μπορούμε να ορίσουμε πολιτικές που θα εφαρμόζονται στην κίνηση που προορίζεται για περιπτώσεις αυτής της υπηρεσίας:

Επιστροφή στις microservices με το Istio. Μέρος 2
Διαχείριση κυκλοφορίας με πόρους Ιστιοίου

Σημείωση: Ο αντίκτυπος των πόρων Istio στην κυκλοφορία του δικτύου παρουσιάζεται εδώ με τρόπο που είναι εύκολο να κατανοηθεί. Για την ακρίβεια, η απόφαση σε ποια περίπτωση να σταλεί το αίτημα λαμβάνεται από τον Απεσταλμένο στην Πύλη Εισόδου που έχει διαμορφωθεί στο CRD.

Με τους κανόνες προορισμού, μπορούμε να διαμορφώσουμε την εξισορρόπηση φορτίου ώστε να χρησιμοποιεί συνεπείς κατακερματισμούς και να διασφαλίσουμε ότι η ίδια παρουσία υπηρεσίας ανταποκρίνεται στον ίδιο χρήστη. Η ακόλουθη διαμόρφωση σάς επιτρέπει να το επιτύχετε αυτό (destinationrule-sa-frontend.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: sa-frontend
spec:
  host: sa-frontend
  trafficPolicy:
    loadBalancer:
      consistentHash:
        httpHeaderName: version   # 1

1 - θα δημιουργηθεί κατακερματισμός με βάση τα περιεχόμενα της κεφαλίδας HTTP version.

Εφαρμόστε τη διαμόρφωση με την ακόλουθη εντολή:

$ kubectl apply -f resource-manifests/istio/ab-testing/destinationrule-sa-frontend.yaml
destinationrule.networking.istio.io/sa-frontend created

Τώρα εκτελέστε την παρακάτω εντολή και βεβαιωθείτε ότι έχετε τα σωστά αρχεία όταν καθορίσετε την κεφαλίδα version:

$ curl --silent -H "version: yogo" http://$EXTERNAL_IP/ | tr '"' 'n' | grep main

Σημείωση: Για να προσθέσετε διαφορετικές τιμές στην κεφαλίδα και να δοκιμάσετε τα αποτελέσματα απευθείας στο πρόγραμμα περιήγησης, μπορείτε να χρησιμοποιήσετε αυτή η επέκταση στο Chrome με αυτό για Firefox - περίπου. μετάφρ.).

Γενικά, το DestinationRules έχει περισσότερες δυνατότητες στον τομέα της εξισορρόπησης φορτίου - ελέγξτε για λεπτομέρειες στο επίσημη τεκμηρίωση.

Πριν μελετήσουμε περαιτέρω το VirtualService, ας διαγράψουμε την "πράσινη έκδοση" της εφαρμογής και τον αντίστοιχο κανόνα κατεύθυνσης κυκλοφορίας εκτελώντας τις ακόλουθες εντολές:

$ kubectl delete -f resource-manifests/kube/ab-testing/sa-frontend-green-deployment.yaml
deployment.extensions “sa-frontend-green” deleted
$ kubectl delete -f resource-manifests/istio/ab-testing/destinationrule-sa-frontend.yaml
destinationrule.networking.istio.io “sa-frontend” deleted

Mirroring: Εικονικές υπηρεσίες στην πράξη

Σκιάζει («θωράκιση») ή Mirroring («καθρέφτισμα») χρησιμοποιείται σε περιπτώσεις όπου θέλουμε να δοκιμάσουμε μια αλλαγή στην παραγωγή χωρίς να επηρεάσουμε τους τελικούς χρήστες: για να γίνει αυτό, αντιγράφουμε αιτήματα («mirror») σε μια δεύτερη περίπτωση όπου έχουν γίνει οι επιθυμητές αλλαγές και εξετάζουμε τις συνέπειες. Με απλά λόγια, αυτή είναι η στιγμή που ο συνάδελφός σας επιλέγει το πιο κρίσιμο ζήτημα και κάνει ένα αίτημα έλξης με τη μορφή ενός τόσο τεράστιου όγκου βρωμιάς που κανείς δεν μπορεί πραγματικά να το ελέγξει.

Για να δοκιμάσουμε αυτό το σενάριο στην πράξη, ας δημιουργήσουμε μια δεύτερη παρουσία του SA-Logic με σφάλματα (buggy) εκτελώντας την ακόλουθη εντολή:

$ kubectl apply -f resource-manifests/kube/shadowing/sa-logic-service-buggy.yaml
deployment.extensions/sa-logic-buggy created

Και τώρα ας εκτελέσουμε την εντολή για να βεβαιωθούμε ότι όλες οι περιπτώσεις με app=sa-logic Έχουν επίσης ετικέτες με τις αντίστοιχες εκδόσεις:

$ kubectl get pods -l app=sa-logic --show-labels
NAME                              READY   LABELS
sa-logic-568498cb4d-2sjwj         2/2     app=sa-logic,version=v1
sa-logic-568498cb4d-p4f8c         2/2     app=sa-logic,version=v1
sa-logic-buggy-76dff55847-2fl66   2/2     app=sa-logic,version=v2
sa-logic-buggy-76dff55847-kx8zz   2/2     app=sa-logic,version=v2

Υπηρεσίες sa-logic στοχεύει λοβούς με ετικέτα app=sa-logic, έτσι όλα τα αιτήματα θα διανεμηθούν σε όλες τις περιπτώσεις:

Επιστροφή στις microservices με το Istio. Μέρος 2

... αλλά θέλουμε τα αιτήματα να αποστέλλονται σε παρουσίες v1 και να αντικατοπτρίζονται σε παρουσίες v2:

Επιστροφή στις microservices με το Istio. Μέρος 2

Αυτό θα το πετύχουμε μέσω του VirtualService σε συνδυασμό με το DestinationRule, όπου οι κανόνες θα καθορίζουν τα υποσύνολα και τις διαδρομές της VirtualService σε ένα συγκεκριμένο υποσύνολο.

Ορισμός υποσυνόλων στους κανόνες προορισμού

Υποσύνολα (υποσύνολα) καθορίζονται από την ακόλουθη διαμόρφωση (sa-logic-subsets-destinationrule.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: sa-logic
spec:
  host: sa-logic    # 1
  subsets:
  - name: v1        # 2
    labels:
      version: v1   # 3
  - name: v2
    labels:
      version: v2

  1. οικοδεσπότης (host) ορίζει ότι αυτός ο κανόνας ισχύει μόνο για τις περιπτώσεις που η διαδρομή πηγαίνει προς την υπηρεσία sa-logic;
  2. Τίτλοι (name) Τα υποσύνολα χρησιμοποιούνται κατά τη δρομολόγηση σε παρουσίες υποσυνόλου.
  3. Ετικέτα (label) ορίζει τα ζεύγη κλειδιού-τιμής που πρέπει να ταιριάζουν οι παρουσίες για να γίνουν μέρος του υποσυνόλου.

Εφαρμόστε τη διαμόρφωση με την ακόλουθη εντολή:

$ kubectl apply -f resource-manifests/istio/shadowing/sa-logic-subsets-destinationrule.yaml
destinationrule.networking.istio.io/sa-logic created

Τώρα που ορίζονται τα υποσύνολα, μπορούμε να προχωρήσουμε και να διαμορφώσουμε την VirtualService ώστε να εφαρμόζει κανόνες σε αιτήματα στο sa-logic έτσι ώστε:

  1. Δρομολογήθηκε σε ένα υποσύνολο v1,
  2. Αντικατοπτρίζεται σε ένα υποσύνολο v2.

Το παρακάτω μανιφέστο σάς επιτρέπει να επιτύχετε τα σχέδιά σας (sa-logic-subsets-shadowing-vs.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sa-logic
spec:
  hosts:
    - sa-logic          
  http:
  - route:
    - destination:
        host: sa-logic  
        subset: v1      
    mirror:             
      host: sa-logic     
      subset: v2

Δεν χρειάζεται εξήγηση εδώ, οπότε ας το δούμε στην πράξη:

$ kubectl apply -f resource-manifests/istio/shadowing/sa-logic-subsets-shadowing-vs.yaml
virtualservice.networking.istio.io/sa-logic created

Ας προσθέσουμε το φορτίο καλώντας την ακόλουθη εντολή:

$ while true; do curl -v http://$EXTERNAL_IP/sentiment 
    -H "Content-type: application/json" 
    -d '{"sentence": "I love yogobella"}'; 
    sleep .8; done

Ας δούμε τα αποτελέσματα στο Grafana, όπου μπορείτε να δείτε ότι η έκδοση με σφάλματα (buggy) οδηγεί σε αποτυχία για το ~60% των αιτημάτων, αλλά καμία από αυτές τις αποτυχίες δεν επηρεάζει τους τελικούς χρήστες καθώς ανταποκρίνεται μια υπηρεσία που εκτελείται.

Επιστροφή στις microservices με το Istio. Μέρος 2
Επιτυχείς απαντήσεις διαφορετικών εκδόσεων της υπηρεσίας sa-logic

Εδώ είδαμε για πρώτη φορά πώς εφαρμόζεται το VirtualService στους Απεσταλμένους των υπηρεσιών μας: πότε sa-web-app κάνει ένα αίτημα σε sa-logic, περνά από το sidecar Envoy, το οποίο - μέσω VirtualService - έχει ρυθμιστεί να δρομολογεί το αίτημα στο υποσύνολο v1 και να αντικατοπτρίζει το αίτημα στο υποσύνολο v2 της υπηρεσίας sa-logic.

Ξέρω, ίσως πιστεύετε ήδη ότι οι Εικονικές Υπηρεσίες είναι απλές. Στην επόμενη ενότητα, θα επεκταθούμε σε αυτό λέγοντας ότι είναι επίσης πραγματικά υπέροχα.

Canary Rollouts

Το Canary Deployment είναι η διαδικασία διάθεσης μιας νέας έκδοσης μιας εφαρμογής σε μικρό αριθμό χρηστών. Χρησιμοποιείται για να βεβαιωθείτε ότι δεν υπάρχουν προβλήματα στην κυκλοφορία και μόνο μετά από αυτό, έχοντας ήδη εμπιστοσύνη για την ποιότητά του (της κυκλοφορίας), διανείμετε το σε άλλους χρήστες.оμεγαλύτερο κοινό.

Για να δείξουμε την κυκλοφορία καναρινιών, θα συνεχίσουμε να εργαζόμαστε με ένα υποσύνολο buggy у sa-logic.

Ας μην χάνουμε χρόνο σε μικροπράγματα και ας στείλουμε αμέσως το 20% των χρηστών στην έκδοση με σφάλματα (αυτό θα αντιπροσωπεύει την κυκλοφορία του καναρινιού μας) και το υπόλοιπο 80% στην κανονική υπηρεσία. Για να το κάνετε αυτό, χρησιμοποιήστε την ακόλουθη VirtualService (sa-logic-subsets-canary-vs.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sa-logic
spec:
  hosts:
    - sa-logic    
  http:
  - route: 
    - destination: 
        host: sa-logic
        subset: v1
      weight: 80         # 1
    - destination: 
        host: sa-logic
        subset: v2
      weight: 20 # 1

1 είναι το βάρος (weight), το οποίο καθορίζει το ποσοστό των αιτημάτων που θα απευθύνονται σε έναν παραλήπτη ή σε ένα υποσύνολο του παραλήπτη.

Ας ενημερώσουμε την προηγούμενη διαμόρφωση VirtualService για sa-logic με την ακόλουθη εντολή:

$ kubectl apply -f resource-manifests/istio/canary/sa-logic-subsets-canary-vs.yaml
virtualservice.networking.istio.io/sa-logic configured

... και θα δούμε αμέσως ότι ορισμένα αιτήματα οδηγούν σε αποτυχίες:

$ while true; do 
   curl -i http://$EXTERNAL_IP/sentiment 
   -H "Content-type: application/json" 
   -d '{"sentence": "I love yogobella"}' 
   --silent -w "Time: %{time_total}s t Status: %{http_code}n" 
   -o /dev/null; sleep .1; done
Time: 0.153075s Status: 200
Time: 0.137581s Status: 200
Time: 0.139345s Status: 200
Time: 30.291806s Status: 500

Οι VirtualServices ενεργοποιούν την κυκλοφορία καναρινιών: Σε αυτήν την περίπτωση, έχουμε περιορίσει τον πιθανό αντίκτυπο των προβλημάτων στο 20% της βάσης χρηστών. Εκπληκτικός! Τώρα, σε κάθε περίπτωση που δεν είμαστε σίγουροι για τον κωδικό μας (με άλλα λόγια - πάντα...), μπορούμε να χρησιμοποιήσουμε mirroring και canary rollouts.

Χρονικά άουτ και επαναλήψεις

Αλλά τα σφάλματα δεν καταλήγουν πάντα στον κώδικα. Στη λίστα από το "8 Παρανοήσεις σχετικά με τον Κατανεμημένο Υπολογισμό«Στην πρώτη θέση βρίσκεται η εσφαλμένη πεποίθηση ότι «το δίκτυο είναι αξιόπιστο». Στην πραγματικότητα το δίκτυο όχι αξιόπιστο και γι' αυτό χρειαζόμαστε τάιμ άουτ (τάιμ άουτ) και ξαναπροσπαθεί (επαναπροσπαθεί).

Για επίδειξη θα συνεχίσουμε να χρησιμοποιούμε την ίδια προβληματική έκδοση sa-logic (buggy), και θα προσομοιώσουμε την αναξιοπιστία του δικτύου με τυχαίες αστοχίες.

Αφήστε την υπηρεσία μας με σφάλματα να έχει 1/3 πιθανότητες να καθυστερήσει να ανταποκριθεί, 1/3 πιθανότητες να τελειώσει με εσωτερικό σφάλμα διακομιστή και 1/3 πιθανότητα να επιστρέψει επιτυχώς η σελίδα.

Για να μετριαστεί ο αντίκτυπος τέτοιων προβλημάτων και να βελτιώσουμε τη ζωή των χρηστών, μπορούμε:

  1. προσθέστε ένα χρονικό όριο αν η υπηρεσία χρειάζεται περισσότερο από 8 δευτερόλεπτα για να απαντήσει,
  2. επαναλάβετε εάν το αίτημα αποτύχει.

Για την υλοποίηση, θα χρησιμοποιήσουμε τον ακόλουθο ορισμό πόρων (sa-logic-retries-timeouts-vs.yaml):

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sa-logic
spec:
  hosts:
    - sa-logic
  http:
  - route: 
    - destination: 
        host: sa-logic
        subset: v1
      weight: 50
    - destination: 
        host: sa-logic
        subset: v2
      weight: 50
    timeout: 8s           # 1
    retries:
      attempts: 3         # 2
      perTryTimeout: 3s # 3

  1. Το χρονικό όριο για το αίτημα έχει οριστεί σε 8 δευτερόλεπτα.
  2. Τα αιτήματα δοκιμάζονται ξανά 3 φορές.
  3. Και κάθε προσπάθεια θεωρείται ανεπιτυχής εάν ο χρόνος απόκρισης υπερβαίνει τα 3 δευτερόλεπτα.

Αυτή είναι μια βελτιστοποίηση γιατί ο χρήστης δεν θα χρειαστεί να περιμένει περισσότερο από 8 δευτερόλεπτα και θα κάνουμε τρεις νέες προσπάθειες για να λάβουμε απάντηση σε περίπτωση αποτυχίας, αυξάνοντας την πιθανότητα επιτυχούς απόκρισης.

Εφαρμόστε την ενημερωμένη διαμόρφωση με την ακόλουθη εντολή:

$ kubectl apply -f resource-manifests/istio/retries/sa-logic-retries-timeouts-vs.yaml
virtualservice.networking.istio.io/sa-logic configured

Και ελέγξτε στα γραφήματα Grafana ότι ο αριθμός των επιτυχημένων απαντήσεων έχει αυξηθεί παραπάνω:

Επιστροφή στις microservices με το Istio. Μέρος 2
Βελτιώσεις στα στατιστικά στοιχεία επιτυχημένης απόκρισης μετά την προσθήκη χρονικών ορίων και επαναλήψεων

Πριν προχωρήσετε στην επόμενη ενότητα (ή μάλλον, στο επόμενο μέρος του άρθρου, γιατί σε αυτό δεν θα υπάρχουν άλλα πρακτικά πειράματα - περίπου μετάφρ.), διαγραφή sa-logic-buggy και VirtualService εκτελώντας τις ακόλουθες εντολές:

$ kubectl delete deployment sa-logic-buggy
deployment.extensions “sa-logic-buggy” deleted
$ kubectl delete virtualservice sa-logic
virtualservice.networking.istio.io “sa-logic” deleted

Μοτίβα διακόπτη κυκλώματος και διαφράγματος

Μιλάμε για δύο σημαντικά μοτίβα στην αρχιτεκτονική microservice που σας επιτρέπουν να επιτύχετε αυτο-ανάκτηση (αυτοθεραπεία) Υπηρεσίες.

Διακόπτης κυκλώματος ("Διακόπτης κυκλώματος") χρησιμοποιείται για τον τερματισμό αιτημάτων που έρχονται σε μια παρουσία μιας υπηρεσίας που θεωρείται ανθυγιεινή και την επαναφορά της, ενώ τα αιτήματα πελατών ανακατευθύνονται σε υγιείς παρουσίες αυτής της υπηρεσίας (πράγμα που αυξάνει το ποσοστό επιτυχών απαντήσεων). (Σημείωση: Μπορείτε να βρείτε μια πιο λεπτομερή περιγραφή του μοτίβου, για παράδειγμα, εδώ.)

Διάφραγμα ("χώρισμα") απομονώνει τις αποτυχίες της υπηρεσίας ώστε να μην επηρεάζουν ολόκληρο το σύστημα. Για παράδειγμα, η Υπηρεσία Β είναι κατεστραμμένη και μια άλλη υπηρεσία (ο πελάτης της Υπηρεσίας Β) κάνει ένα αίτημα στην Υπηρεσία Β, με αποτέλεσμα να εξαντλήσει το νήμα της και να μην μπορεί να εξυπηρετήσει άλλα αιτήματα (ακόμα και αν δεν είναι από την Υπηρεσία Β). (Σημείωση: Μπορείτε να βρείτε μια πιο λεπτομερή περιγραφή του μοτίβου, για παράδειγμα, εδώ.)

Θα παραλείψω τις λεπτομέρειες υλοποίησης αυτών των μοτίβων επειδή είναι εύκολο να βρεθούν επίσημη τεκμηρίωση, και επίσης θέλω πραγματικά να δείξω τον έλεγχο ταυτότητας και την εξουσιοδότηση, τα οποία θα συζητηθούν στο επόμενο μέρος του άρθρου.

ΥΓ από τον μεταφραστή

Διαβάστε επίσης στο blog μας:

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο