Βέλτιστες πρακτικές Kubernetes

Συζητούσα με έναν πρώην SRE του Google που (σωστά) επεσήμανε ότι ο Kubernetes εξελίσσεται πολύ γρήγορα (πολύ γρήγορα για να διατηρήσει το νόμισμα), χρησιμοποιεί (πολλές) καινοτόμες έννοιες και ότι υπάρχουν (πολύ) τρόποι επίλυσης του ίδιου προβλήματος.

Πολλά από αυτά είναι αληθινά και όχι απαραίτητα κακά πράγματα, ούτε απαραίτητα διαφορετικά από οποιαδήποτε άλλη τεχνολογία. Εκεί που διαφωνώ είναι ότι αυτοί οι παράγοντες έχουν αποθαρρύνει την υιοθέτησή του από τους Kubernetes. Θα ήθελα να σας ενθαρρύνω να βουτήξετε μέσα. Η Kubernetes είναι η επιτυχία * παρά τις * αυτές (εύλογες) ανησυχίες επειδή είναι τόσο πολύ καλή.

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

Σε καμία συγκεκριμένη σειρά:

  1. Αφήστε κάποιον άλλο να κάνει μάσκα!

Χρησιμοποιήστε μια υπηρεσία Kubernetes όπως η μηχανή Kubernetes. Αν δεν είστε διανοητικά περίεργοι, ένας προγραμματιστής που εργάζεται στο Kubernetes ή είστε πάροχος πλατφόρμας που έχει πελάτες που ζητούν υπηρεσίες Kubernetes, σώστε την ταλαιπωρία και χρησιμοποιήστε μια υπηρεσία Kubernetes. Δημιούσατε το σπίτι σας και το αυτοκίνητό σας; Ή μήπως σας αρέσει να κοιμάστε σε ένα μέρος που ο Wolf δεν μπορεί να εκραγεί και να οδηγήσει ένα αυτοκίνητο που σας μεταφέρει αξιόπιστα από το Α σε Β;

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

Τα clusters κοντέινερ gcloud beta δημιουργούν $ {CLUSTER} ...
gcloud δέσμες δοχείων beta για να πάρει πιστοποιήσεις $ {CLUSTER} ...

Και τότε, είστε έτοιμοι να πάτε με:

kubectl apply --filename = marvels.yaml

2. Προσπαθήστε να σκεφτείτε "Kubernetes"

Αυτό * μπορεί να είναι περισσότερο μια πρόκληση με τον Kubernetes Engine από ό, τι σε άλλες πλατφόρμες αλλά στην πλατφόρμα Google Cloud είστε αναγκασμένοι να διατηρήσετε μια κατανόηση της κατάστασης των πόρων σας στα Kubernetes (π.χ. Κόμβοι, Ingress) και ταυτόχρονα , τους υποκείμενους πόρους στο Compute Engine (π.χ. VMs, HTTP / S Load Balancers). Αυτό το πρόβλημα δυαδικότητας κύματος σωματιδίων είναι ατυχές. Ευχαριστώ τον Dale H. για την πρώτη μου άρθρωση.

Όπου είναι δυνατόν, προσπαθήστε να παραμείνετε στο μυαλό από την άποψη των πόρων του Kubernetes και αγνοήστε τους υποκείμενους πόρους GCE. Έχοντας πλέον περάσει πάνω από ένα χρόνο να επηρεάσει το έργο μου στον Kubernetes, είναι πιο εύκολο να σκεφτούμε καθαρά από την άποψη του "κάποιου αριθμού" υποκειμένων που εκτίθενται από τις υπηρεσίες (και Ingresses).

3. Ονόματα Χώρων, Ονόματα Χώρων, Ονόματα Χώρων

Ενημέρωση: Χάρη στον Michael Hausenblas για την εκπαίδευση μου σχετικά με την καλύτερη πρακτική της * μη * αναφοράς των ονομάτων χώρου μέσα από τα αρχεία YAML του Kubernetes. Ενώ πρέπει πάντα να χρησιμοποιείτε χώρους ονομάτων, προσδιορίζοντάς τα όταν εφαρμόζετε το αρχείο παρέχει μεγαλύτερη ευελιξία και τη δυνατότητα χρήσης των ίδιων αρχείων YAML, π.χ. διαφορετικά τοπία. Δείτε το άρθρο του Μιχαήλ εδώ.

Ο Mike Altarace και εγώ blogged πριν από φεγγάρια σχετικά με τους Ονόματα Χώρων στην Kubernetes και πού πρέπει να τα χρησιμοποιήσετε. Έκτοτε, αγνοούσα λίγο τις δικές μου συμβουλές, σκέπτοντας ότι οι περιπτώσεις χρήσης μου ήταν τόσο δευτερεύουσες ώστε η χρήση του Namespaces θα ήταν υπερβολική. Εκανα λάθος. Χρησιμοποιήστε το Namespaces, πάντα.

Καθώς τα δοχεία προορίζονται για διαδικασίες, τα Ονόματα Χώρων είναι για έργα Kubernetes. Ανεξάρτητα από το όριο ασφαλείας που μεταφέρουν οι Namespaces, είναι ένας εξαιρετικός τρόπος για να χωρίσετε την εργασία σας και παρέχουν έναν εξαιρετικό τρόπο επαναφοράς ή διαγραφής:

kubectl διαγραφή ονομάτων χώρου / $ WORKING_PROJECT

Το μόνο μειονέκτημα είναι ότι, όταν χρησιμοποιείτε το μη-προεπιλεγμένο χώρο ονομάτων, θα πρέπει να καθορίσετε το χώρο εργασίας σας --namespace = $ WORKING_PROJECT στις εντολές kubectl που κατά τη γνώμη μου μπορεί να είναι μια καλή πρακτική διασφάλισης. Ωστόσο, μπορείτε πάντα --all-namespaces ή να ορίσετε διαφορετικό χώρο ονομάτων ως προεπιλογή (σύνδεσμος).

4. Πολλοί τρόποι επίλυσης ενός προβλήματος

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

  • Τα αρχεία YAML είναι γνώση στην ψυκτική αποθήκευση (βλ. # 5)
  • Τα δοχεία σας πρέπει να κάνουν ένα πράγμα καλά (βλ. "Ασυνείδητο")
  • Πραγματοποιήστε πάντα ανάπτυξη (βλ. # 6)
  • Αν θέλετε L7 aka HTTP / S Load-Balancing χρήση Ingress (δείτε # 7 - ha!)
  • Διαχειριστείτε τα διαπιστευτήρια με ασφάλεια χρησιμοποιώντας τα μυστικά (σύνδεσμος)

5. Bias to kubectl apply - όνομα φακέλου πάνω σε εναλλακτικές λύσεις

Είναι εύκολο να πάρετε ένα γρήγορο χτύπημα με το kubectl create namespace / $ {WORKING_DIR} αλλά, μετά από πολλές τέτοιες εντολές, ίσως να αναρωτηθείτε πώς φτάσατε στην τρέχουσα κατάσταση και - το πιο σημαντικό - πώς να αναδημιουργήσετε αυτό το κράτος. Σας ενθαρρύνω να δημιουργήσετε αρχεία YAML για να περιγράψετε τους πόρους σας αντί για την αντίστοιχη εντολή δημιουργίας kub ectl.

Σας ενθαρρύνω να εξοικειωθείτε με την τεκμηρίωση APY * Kubernetes (link, link και 1.10) που είναι εξαντλητική, ακριβής και εύκολη στην πλοήγηση (ίσως την τέλεια τεκμηρίωση!). Αλλά, ακόμη και με αυτό το ισχυρό εργαλείο, μερικές φορές είναι λίγο δύσκολο να πάρετε μια εντολή kubectl που λειτουργεί για σας και να την μετατρέψετε σε YAML. Δεν είναι:

kubectl πάρτε την ανάπτυξη / $ {MY_DEPLOYMENT} --output = yaml
kubectl πάρει υπηρεσία / $ {MY_SERVICE} --output = yaml
kubectl πάρει οτιδήποτε / $ {MY_ANYTHING} --output = yaml

Μεταφέρετε τα αποτελέσματα σε ένα αρχείο αν θέλετε, αλλά χρησιμοποιήστε τα ως βάση για ισοδύναμο (!) Αρχείο YAML. Θα χρειαστεί να αφαιρέσετε τυχόν αναφορές στιγμιότυπων.

Μόλις δημιουργήσετε το masterpiece.yaml, σας ενθαρρύνω να εφαρμόζετε πάντα για να κάνετε την αρχική δημιουργία, να κάνετε αίτηση για τυχόν μεταγενέστερες ενημερώσεις και, εάν πρέπει να διαγράψετε. Αυτό είναι!

kubectl apply --filename = masterpiece.yaml
kubectl delete --filename = masterpiece.yaml

Μικρή διορατικότητα: δεν χρειάζεται να τραβήξετε τοπικά αρχεία YAML για να τα αναπτύξετε. Μπορείτε να δώσετε το kubectl apply - filename με τις διευθύνσεις URL και, εφόσον εξαρτημένα αρχεία είναι τοπικές αναφορές, η ανάπτυξη θα λειτουργήσει.

Μικρή διορατικότητα: το μόνο μέρος που βλέπω ότι χρησιμοποιείται είναι στο Kubernetes-land αλλά είναι μια νόμιμη πρακτική, μπορείτε να συνδυάσετε πολλά αρχεία YAML σε ένα αρχείο YAML με διαχωριστές --- και .... Επομένως, αντί ενός YAML χώρου ονομάτων, ενός YAML ανάπτυξης και μιας υπηρεσίας YAML, μπορεί να έχετε ένα mega-YAML ενοποιώντας και τα τρία αρχεία σε ένα.

Αυτό είναι έγκυρο YAML (αντιγράψτε και επικολλήστε το π.χ. σε YAML Lint). Είναι * άκυρο * Kubernetes spec | YAML επειδή κάθε spec είναι ελλιπής, αλλά αν ολοκληρώθηκε ο καθένας, αυτό είναι πολύ ωραίο YAML και ένας καλός τρόπος για να διατηρηθούν οι πόροι που συσχετίζονται.

Βλέπε #B (Xsonnet) για μια κριτική.

6. Χρησιμοποιήστε τις εφαρμογές

Υπάρχει μια δέσμη εξουσίας στις Εγκαταστάσεις, αρκεί η καθοδήγησή μου να πω: χρησιμοποιήστε τις υλοποιήσεις συνεχώς, κάθε φορά. Ακόμη και όταν αναπτύσσετε το πρώτο σας μοναδικό podnginx. Οι αναπτύξεις είναι ταξίδια "πρώτης κατηγορίας" για την τιμή του Coach, μπορείτε να πέσετε σε κυλιόμενες εκδηλώσεις, να κάνετε λάθος, να κάνετε ξανά εφαρμογή και ο Kubernetes φροντίζει να σκοτώσει τα άτακτα λοβούς και να τα αντικαταστήσει με καλά συμπεριφερόμενα.

7. LoadBalancer και Ingress

Αυτά προκαλούν σύγχυση. Στο μυαλό μου (και ίσως να κάνω λάθος), όταν δημιουργώ τις υπηρεσίες χρησιμοποιώντας --type = LoadBalancer, θέλω | να αποκτήσω ένα δίκτυο LB. Αν θέλω HTTP / S (Επίπεδο 7) Load-Balancing, πρέπει να δημιουργήσω ένα Ingress. Το Ingress είναι μια συγκεχυμένη πηγή Kubernetes. Αρκεί να πούμε, L7 == Ingress (και ως αποτέλεσμα πολλή δύναμη διαμόρφωσης).

Ο μηχανισμός Kubernetes εκδηλώνει πόρους Ingress ως GCE HTTP / S Load-Balancers. Ο Κρίστοφερ Γκραντ κάνει μια πολύ καλή δουλειά που αποσυνθέτει τον Ingress στις θέσεις του (εδώ και εδώ).

8. NodePorts

Δεν έχω (ποτέ;) δημιουργήσει άμεσα ένα ClusterIP. Έκανα πράγματα με τα Kubernetes που είχαν ως αποτέλεσμα υπηρεσίες που εκτέθηκαν από το ClusterIPs. Κυρίως (!) Δημιούργησα το NodePorts ή κάνω πράγματα (π.χ. δημιουργώ πόρους Ingress) που χρησιμοποιούν το NodePorts.

Τα NodePorts συνδέονται με κόμβους Kubernetes και είναι Ports. Η ισχυρή δυνατότητα που παρέχουν είναι ότι * κάθε * κόμβος στο σύμπλεγμα (ή είναι αυτό το NodePool; [[TODO]]) εκθέτουν την ίδια υπηρεσία στην ίδια θύρα (κόμβος).

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

Το Google Cloud SDK (aka gcloud) περιλαμβάνει ένα πρόγραμμα-πελάτη ssh που καθιστά ασήμαντο τη σύνδεση με τα Compute Engine VMs (τα οποία, όπως υπενθυμίζετε, είναι κόμβοι συμπλέγματος Kubernetes). Ο πελάτης ssh περιλαμβάνει μια δυνατότητα προώθησης θυρών. Έτσι, αν θέλουμε να συνδεθούμε με μια υπηρεσία Kubernetes και μπορούμε να κοιτάξουμε το NodePort της υπηρεσίας, τότε μπορούμε να προσφέρουμε με ευκολία (!) Port-forward προς αυτή την υπηρεσία μέσω port-forwarding (χρησιμοποιώντας το gcloud ή οποιοδήποτε ssh client) στη θύρα σε οποιαδήποτε Κόμβος.

Το ακόλουθο παράδειγμα χρησιμοποιεί το kubectl για να αρπάξει τον 0ο κόμβο στο σύμπλεγμα. Το όνομα του κόμβου Kubernetes Engine είναι το ίδιο με το όνομα VM του Compute Engine. Δεδομένης μιας υπηρεσίας που ονομάζεται $ {MY_SERVICE} σε ένα χώρο ονομάτων που ονομάζεται $ {MY_NAMESPACE}, προσδιορίζουμε το NodePort της υπηρεσίας. Στη συνέχεια, μεταβαίνουμε στο gcloud και χρησιμοποιούμε το ενσωματωμένο ssh στο port-forward (χρησιμοποιώντας το --ssh-flag = "- L XXXX: localhost: XXXX).

NODE_HOST = $ (\
  kubectl get κόμβους \
  --output = jsonpath = "{. στοιχεία [0] .metadata.name}")
NODE_PORT = $ (\
  kubectl πάρει υπηρεσίες / $ {MY_SERVICE} \
  --namespace = $ {MY_NAMESPACE} \
  --output = jsonpath = "{. spec.ports [0] .nodePort}")
echo $ {NODE_PORT}
gcloud υπολογίζει ssh $ {NODE_HOST} \
--ssh-flag = "- L $ {NODE_PORT}: localhost: $ {NODE_PORT}" \
--project = $ {YOUR_PROJECT}

Τι είναι τόσο ισχυρό για αυτό; Τώρα, μπορείτε να έχετε πρόσβαση στην υπηρεσία σαν να ήταν τοπική και χωρίς να χτυπάτε τρύπες σε ένα τείχος προστασίας.

Τα NodePorts είναι θύρες υψηλών αριθμών (~ 30.000-32.767).

9. Hacking kubectl χρήση JSON

Το Cloud SDK της Google (γνωστός και ως gcloud) είναι πραγματικά εξαιρετικό, αλλά το kubectl (Kubernetes CLI) είναι πιο περίεργο (sic). Ένα ισχυρό χαρακτηριστικό είναι η μορφοποίηση και η διήθηση της εξόδου. Αυτό επιτρέπει μη-κωδικοποιητικούς τρόπους (χωρίς API) να επεκτείνουν σενάρια και άλλα εργαλεία με πληροφορίες από τα clusters της Kubernetes.

Όλη η κατάσταση πόρων του Kubernetes είναι προσβάσιμη μέσω π.χ. kubectl get (κατά την εμπειρία μου πιο χρήσιμο για το σκοπό αυτό από ό, τι περιγράφει kubectl) εντολές. Στη συνέχεια, το μόνο που έχει απομείνει είναι να βρει τη βελόνα σε ό, τι μπορεί να είναι ένα άχυρο του JSON.

Το τέχνασμα είναι:

kubectl να πάρει [resource] / [resource-name] --output = JSON

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

kubectl να πάρει [resource] / [resource-name] --output = jsonpath = ". στοιχεία [*]"

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

kubectl να πάρει κόμβους --output = json
kubectl να πάρει κόμβους --output = jsonpath = "{. items [*]}
kubectl να πάρει κόμβους --output = jsonpath = "{. items [0]}
kubectl να πάρει κόμβους --output = jsonpath = "{. items [0] .metadata.name}

Τέλος, υπάρχει ένα αξιοπρεπές επιχείρημα (και ένα δόγμα στο * nix) για την εκμάθηση ενός εργαλείου ανάλυσης JSON και την εφαρμογή αυτού του εργαλείου σε όλες τις ανάγκες αναλύσεων JSON. Σε αυτή την περίπτωση, υπάρχει κάποιος λογικός ανταγωνιστής στο jq; Υποψιάζομαι όχι.

Plus jq έχει μια εξαιρετική παιδική χαρά (jqplay.org).

A. Χρησιμοποιήστε ετικέτες

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

Μια Υπηρεσία Kubernetes εκθέτει έναν αυθαίρετο αριθμό Podubs Kubernetes. Οι Υπηρεσίες δεν * εκθέτουν τα Pods που ονομάζονται "Henry" ή τα Pods που περιλαμβάνουν ένα ReplicaSet. Αντίθετα, μια Υπηρεσία εκθέτει τα Pods, των οποίων οι ετικέτες πληρούν τα κριτήρια που καθορίζονται κατά τη διάρκεια των προδιαγραφών της Υπηρεσίας, και οι ετικέτες αυτές, φυσικά, ορίζονται από το χρήστη.

ΣΗΜΕΙΩΣΗ Στο παραπάνω παράδειγμα, χρησιμοποιούμε ένα χώρο ονομάτων που ονομάζεται project-x και αυτό το spec ονομάτων εμφανίζεται στο χώρο ονομάτων (όταν δημιουργείται), την ανάπτυξη για να καθορίσετε πού υπάρχει η ανάπτυξη και στην υπηρεσία. Η ανάπτυξη (η οποία ονομάζεται microservice-y) θα δημιουργήσει ένα ReplicaSet (καθορίζεται σιωπηρά εδώ, είναι αυτό που δημιουργούν οι υλοποιήσεις) που θα διατηρούν 100 pods. Κάθε Pod θα έχει εφαρμογή ετικέτας: publicname-a και θα περιέχει ένα περιέκτη που ονομάζεται grpc-proxy με βάση μια εικόνα που ονομάζεται image-grpc-proxy. Η Υπηρεσία ονομάζεται service-p. Βασικά, η Υπηρεσία επιλέγει (!) Pods (μόνο στο χώρο ονομάτων έργου-x) που διαθέτουν εφαρμογή ετικέτας: publicname-a. Η υπηρεσία θα επιλέξει οποιοδήποτε Pod (στο χώρο ονομάτων έργου-x) που έχει αυτό το ζεύγος ετικέτας (key: value) * όχι * μόνο εκείνα τα pods που δημιουργήθηκαν σε αυτήν την ανάπτυξη. Η υπηρεσία δεν αναφέρει τα Pods με το όνομά τους (το οποίο βασίζεται στο όνομα ανάπτυξης), το όνομα του κοντέινερ τους και το όνομα της εικόνας του δοχείου, μόνο τις ετικέτες που σχετίζονται με το pod.

Σημείωση: Αυτό δεν είναι μια καλή πρακτική αλλά αποδεικνύει το σημείο. Αν έπρεπε να εκτελέσετε μια διαμόρφωση παρόμοια με την παραπάνω και στη συνέχεια ξεχωριστά να δημιουργήσετε π.χ. ένα Pod που τρέχει το Nginx (στο χώρο ονομάτων project-x) και στη συνέχεια προσθέσετε την εφαρμογή ετικέτας: publicname-a σε αυτό, θα ενσωματωθεί γρήγορα στο σύνολο των Pods που συγκεντρώνονται από την υπηρεσία service-p. Εάν αφαιρέσατε την ετικέτα από οποιαδήποτε από τις Pods που συγκεντρώθηκαν από την Υπηρεσία, το Pod θα σταματούσε να συμπεριλαμβάνεται.

Αυτή η δυνατότητα αποτελεί παράδειγμα από κυλιόμενες ενημερώσεις, όπου η ανάπτυξη δημιουργεί ένα νέο ReplicaSet που περιλαμβάνει νέα pods για την έκδοση X ', διαφορετικό από το ReplicaSet και το Pods για την έκδοση X. Η υπηρεσία μπορεί να οριστεί για να εκθέσει τη διασταύρωση των Pods που τρέχουν και στις δύο αυτές εκδόσεις, δεν ορίζεται από πλευράς ReplicaSets ή συγκεκριμένων Pods, αλλά από ετικέτες καθορισμένες από το χρήστη ("επιλογείς") που εφαρμόζονται από εσάς όταν δημιουργούνται οι Pods.

Αυτό είναι πολύ ισχυρό!

Β. Χρησιμοποιήστε το Jsonnet, πιθανώς Ksonnet

Δύο προκλήσεις με όλες τις δομημένες μορφές (!?) (YAML, JSON, XML, CSV ;-) είναι αυτοαναφορές και μεταβλητές. Καθώς δημιουργείτε τις προδιαγραφές marvellous.yaml για την ανάπτυξη Kubernetes σας, θα αντιμετωπίσετε αυτό το πρόβλημα εύκολα. Θα βρείτε τον εαυτό σας χρησιμοποιώντας κυριολεκτικά (για παράδειγμα, για ονόματα εικόνων και digests) και, ακόμη και με τις αξιόλογες αναπτύξεις, επαναλαμβάνοντας ονόματα και επιλογείς.

Δεν υπάρχει λύση σε αυτά τα θέματα εάν περιορίσετε τον εαυτό σας σε YAML και JSON. Η Google δημιούργησε εν μέρει την Jsonnet για την αντιμετώπιση αυτών των προβλημάτων. Οι έξυπνοι άνθρωποι Heptio έχουν επεκτείνει την Jsonnet στην Kubernetes με ... Ksonnet.

Και οι δύο είναι γλώσσες που αντιμετωπίζουν τα προβλήματα που περιγράφονται παραπάνω (και περισσότερα). Σας ενθαρρύνω να εξετάσετε το Jsonnet. Όπως και με τη σύστασή μου να εξετάσετε τη χρήση του jq, μάθετε μία φορά τη Jsonnet και την εφαρμόζετε παντού όπου χρησιμοποιείτε το JSON. Το Ksonnet είναι ειδικό για τους Kubernetes και - στην περιορισμένη μου εμπειρία (!) Βρήκα ότι τα οφέλη που αποκτήθηκαν από αυτή την ιδιαιτερότητα δεν πρέπει να αντισταθμίζονται από την καμπύλη μάθησης.

C. YAML ή JSON

Ο Kubernetes αντιμετωπίζει το YAML και το JSON ως επί το πλείστον εξίσου. Προσωπικά, βρίσκω το YAML προτιμότερο για τα αρχεία διαμόρφωσης που μπορώ να εφαρμόσω επειδή το YAML είναι πιο συνοπτικό από το JSON. Αν και βρίσκω το YAML πιο δύσκολο να γράψω.

Ωστόσο, όταν πρόκειται για την κατανόηση της δομής και της ανάλυσης, προτιμώ να --output = JSON και επίσης επειδή - output = JSONPATH. Είμαι ένας τεράστιος ανεμιστήρας Golang, αλλά τα πρότυπα Go δεν είναι τόσο έξυπνα και δεν τα χρησιμοποιώ.

δευτερεύουσα εικόνα: Το YAML είναι ένα υπερσύνολο του JSON (σύνδεση) ... περιμένετε! τι;

D. Downward Dog API και config

Το "Downward API" για να του δώσει το σωστό, αν και μάλλον συγχέοντας όνομα, είναι μια εγκατάσταση στο Kubernetes με την οποία τα Pods μπορούν να αποκτήσουν μια αίσθηση του cluster γύρω τους. Υποθέτω ότι η κανονική ροή είναι από τον έξω κόσμο μέχρι το Pod και τα εμπορευματοκιβώτια *, αλλά * υπάρχουν φορές που είναι χρήσιμο για ένα δοχείο (!) Να αποκτήσει πληροφορίες για το περιβάλλον του, π.χ. το όνομα του κόμβου | IP, το όνομα του δομοστοιχείου (space) | IP.

Οι τιμές API Downward εμφανίζονται στο κοντέινερ μέσω μεταβλητών περιβάλλοντος. Οι μεταβλητές περιβάλλοντος χρησιμοποιούνται (όπως και αλλού) για να παρέχουν στο κοντέινερ ή άλλη κατάσταση στα δοχεία. Μια πολύ ωραία συνέπεια της χρήσης μεταβλητών περιβάλλοντος και της εφαρμογής του Downward API (με μια μικρή προειδοποίηση) είναι ότι το δοχείο παραμένει αποσυνδεδεμένο από τα Kubernetes.

Ακολουθεί ένα παράδειγμα από τον φίλο μου - Sal Rashid - που χρησιμοποιεί το Downward API για να συγκεντρώσει την κατάσταση κόμβων και pod και να τις παρουσιάσει στον χρήστη:

https://github.com/salrashid123/istio_helloworld/blob/master/all-istio.yaml

Σημείωση Σημειώστε τις ενότητες που αρχίζουν στις γραμμές 76, 80, 84, 88 όπου παρέχεται το Όνομα υποδιαιρέσεως, ο χώρος ονομάτων, το IP και το όνομα κόμβου κατά το χρόνο εκτέλεσης από το Downward API στο κοντέινερ που ονομάζεται myapp-container.

Το Downward API είναι ο μοναδικός, πρακτικός τρόπος συγκέντρωσης αυτών των δεδομένων για ένα δοχείο. Έτσι είναι περισσότερο μια "μόνο πρακτική" παρά μια "βέλτιστη πρακτική".

Σε πολλές από τις δημοσιεύσεις μου, καθώς δημιουργώ λύσεις για τους Kubernetes, δοκιμάζω τη διαδικασία τοπικά και έξω από ένα δοχείο, έπειτα σε ένα δοχείο (καθορίζοντας μεταβλητές περιβάλλοντος), στη συνέχεια σε ένα συγκρότημα Kubernetes. Οι μηχανισμοί μεταφοράς εμπορευματοκιβωτίων είναι συνεπείς (βλ. Παρακάτω), παρόλο που συνήθως εκτελείται στο Docker και ένα στο Kubernetes.

Σε μια δημοσίευση που έγραψα πρόσφατα στο λειτουργικό σύστημα Optimizer Container της Google, επιδεικνύω ένα κοντέινερ που εκτελείται τοπικά κάτω από το Docker, απομακρυσμένα κάτω από OS και από το Kubernetes.

Εδώ τρέχει κάτω από το Docker σε τοπικό επίπεδο. Παρατηρήστε πώς χρησιμοποιούνται οι μεταβλητές περιβάλλοντος (-env) για την παροχή ρυθμίσεων στο gcr.io/${PROJECT}/datastore.

τρέξιμο ελλιμενισμού \
--διαδραστικό \
--tty \
--publish = 127.0.0.1: 8080: 8080 \
--env = GCLOUD_DATASET_ID = $ {PROJECT} \
--env = GOOGLE_APPLICATION_CREDENTIALS = / tmp / $ {ROBOT} .key.json \
- volume = $ PWD / $ {ROBOT} .key.json: / tmp / $ {ROBOT} .key.json \
gcr.io/${PROJECT}/datastore

Εδώ είναι το ίδιο αποτέλεσμα που περιβάλλει την ανάπτυξη στην δημιουργία ενός VM Optimized Container. Αυτή τη φορά ελέγξτε τις τιμές που παρέχονται στη σημαία container-env:

gcloud βήτα compute εμφανίσεις create-with-container $ {INSTANCE} \
--zone = $ {ZONE} \
--image-οικογένεια = cos-σταθερό \
--image-project = cos-cloud \
--container-image=gcr.io/${PROJECT}/${IMAGE}@${DIGEST} \
--container-reboot-policy = πάντα \
--container-env = \
GCLOUD_DATASET_ID = $ {PROJECT}, \
GOOGLE_APPLICATION_CREDENTIALS = / tmp / $ {ROBOT} .key.json \
--container-mount-host-path = \
mount-path = / tmp, \
host-path = / tmp, \
mode = rw \
--project = $ {PROJECT}

Και, τέλος, εδώ είναι το απόσπασμα YAML της εφαρμογής για Kubernetes:

δοχεία:
      - όνομα: datastore
        εικόνα: gcr.io/${PROJECT}/datastore
        imagePullPolicy: Πάντα
        volumeMounts:
          - όνομα: datastore
            mountPath: / var / secrets / google
        env:
        - όνομα: GOOGLE_APPLICATION_CREDENTIALS
          αξία: /var/secrets/google/datastore.key.json
        - όνομα: GCLOUD_DATASET_ID
          αξία: $ {PROJECT}
        λιμάνια:
        - όνομα: http
          containerPort: 8080

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

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

E. Sidecars και γιατί τα Pods δεν είναι πάντα συνώνυμα με τα εμπορευματοκιβώτια

Κονιάκ 5 cl
2 cl τριπλά δευτερόλεπτα
2 cl χυμό λεμονιού
Προετοιμασία Ρίξτε όλα τα συστατικά σε αναδευτήρα κοκτέιλ γεμάτο με πάγο. Ανακινήστε καλά και στραγγίστε σε ποτήρι κοκτέιλ.

Μεγάλο μέρος του χρόνου, θα δημιουργήσετε τα Kubernetes Pods που περιέχουν μεμονωμένα δοχεία και θα αναρωτηθείτε γιατί υπάρχουν όλα τα γενικά έξοδα ενός Pod όταν χρειάζεστε μόνο ένα δοχείο. Οι pods είναι πιο ανάλογες με ένα περιβάλλον υποδοχής που μπορεί να τρέξει πολλά δοχεία. Υπάρχουν πολλές φορές που θα εξετάσετε στη συνέχεια τη λειτουργία πολλαπλών κοντέινερ σε ένα Pod ...

... και μόνο μια φορά που θα έπρεπε :-)

Πιθανώς περισσότερα από ένα, αλλά ας κολλήσουμε σε μια μόνο φορά.

Το αντίθετο πρότυπο (μην το κάνετε αυτό) είναι να εξετάσετε την τρέχουσα διαμόρφωσή σας (ας υποθέσουμε έναν διακομιστή ιστού και ένα backend βάσης δεδομένων) και να εμπλακείτε σε ένα Pod. Αυτό δεν είναι * μια καλή ιδέα * εκτός αν * κάθε παρουσία web-server πρέπει να είναι άρρηκτα συνδεδεμένο και για πάντα συνδεδεμένο με μια συγκεκριμένη περίπτωση βάσης δεδομένων. Αυτό είναι απίθανο.

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

Πότε θα πρέπει να εξετάσετε πολλά δοχεία ανά Pod; Η μία φορά που αυτό * πάντα * έχει νόημα είναι όταν θέλετε να συμπληρώσετε, να επεκτείνετε ή να εμπλουτίσουν τη συμπεριφορά του πρωτεύοντος Pod σε ένα δοχείο. Ας επανεξετάσουμε το παράδειγμα του web-server και της βάσης δεδομένων από πάνω. Σε αυτό το σενάριο, ελπίζουμε ότι τώρα είστε πεπεισμένοι ότι θα αναπτύξετε δύο υπηρεσίες (και δύο αναπτύξεις), μία για το frontend και μία για το backend.

Είναι μια καλή και συνηθισμένη πρακτική να προωθήσετε την ίδια την παρουσία σας του διακομιστή ιστού με αντίστροφη-πληρεξούσιο. Συνήθως αυτό θα είναι είτε Nginx είτε HAProxy και γίνεται ολοένα και πιο συνηθισμένο να χρησιμοποιείτε τον απεσταλμένο (συνιστώ, εάν εξετάζετε πληρεξούσιους, να εξετάσετε τον απεσταλμένο, δείτε #F Istio). Ένας αντίστροφος διακομιστής μεσολάβησης παρέχει συνεκτικότητα (χρησιμοποιούμε μόνο π.χ. τον απεσταλμένο) ακόμα κι αν χρησιμοποιείτε διαφορετικούς διακομιστές ιστού (π.χ. Apache, Tomcat w / Java κ.λπ.), ακόμη και αν έχετε ένα συνδυασμό HTTP, gRPC, Web Sockets κ.λπ. , ακόμη και αν θέλετε να κατευθύνετε κάποια επισκεψιμότητα στο διακομιστή ιστού σας και κάποια κυκλοφορία σε μια προσωρινή μνήμη (π.χ. βερνίκι).

Σε όλα τα προηγούμενα σενάρια, θα ήταν λογικό να χρησιμοποιείται το μοντέλο "sidecar". Σε αυτό το μοντέλο, το κύριο δοχείο (ο διακομιστής ιστού σας) έχει βοηθητικά, συμπληρωματικά δοχεία (proxy αποστολέα, cache βερνικιού κλπ.). Αυτά πρέπει να συνδέονται στενά με ένα συγκεκριμένο παράδειγμα διακομιστή web * και * λειτουργικά, ο συνδυασμός είναι η "μονάδα".

Είναι πολύ συνηθισμένο να βλέπουμε την υλοτομία, την παρακολούθηση, τα ίχνη και άλλα συστατικά στοιχεία υποδομής που παρέχονται και ως sidecars. Ένα κίνητρο εδώ είναι να διαχωριστούν οι ανησυχίες. Για να παρέχει στους προγραμματιστές μια συνεπή απαίτηση που παράγει κώδικα που είναι «διαχειρίσιμο» και παρέχει στην SRE την ευελιξία να επιλέγει τα προτιμώμενα εργαλεία, γνωρίζοντας ότι όλος ο κώδικας στο σύνολο του στόλου θα καταγραφεί, θα εκπέμψει μετρήσεις, θα ανιχνευθεί, θα εφαρμόσει auth με συνέπεια κ.λπ. που αποτελεί το θεμέλιο των ματιών των υπηρεσιών (βλ. # F Istio). Αυτή είναι η τελική καλύτερη, αν και εκκολαπτόμενη πρακτική.

F. Χρησιμοποιήστε το Istio

Χρησιμοποιήστε προσεκτικά το Istio.

Το Istio (και άλλα πλέγματα υπηρεσιών) είναι σχετικές τεχνολογίες που γεννιούνται από εταιρείες (συμπεριλαμβανομένης της Google) που έχουν εκτελέσει δοχεία μαζικής κλίμακας. Τα πλέγματα υπηρεσιών τοποθετούν τυχαία μια γενική (στην περίπτωση του Istio, Envoy) πληρεξούσιο σε κάθε Ποντίκι σε κάθε Ανάπτυξη σε κάθε Χώρο Ονόματος σε κάθε σύμπλεγμα.

Το αποτέλεσμα είναι ένα σταθερό υπόστρωμα διαχείρισης που επιτρέπει τη χαλαρή σύζευξη της διαχείρισης (θα χρησιμοποιήσουμε το Stackdriver Trace σήμερα, αλλά υπάρχει σχέδιο να μεταναστεύσουμε στον Jaeger, έχουμε δρομολογήσει την παρακολούθηση Prometheus) και τις υπηρεσίες ελέγχου (γνωρίζουμε ότι όλες οι υπηρεσίες μας είναι ασφαλείς, εμείς «δρομολογεί το 10% της κυκλοφορίας στις κατασκευές των καναρίων των υπηρεσιών Α, Β και Γ».

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

Αυτό ήταν παιδιά!