Η ιδέα ενός χειριστή κελύφους είναι αρκετά απλή: εγγραφείτε σε συμβάντα από αντικείμενα Kubernetes και όταν ληφθούν αυτά τα συμβάντα, ξεκινήστε ένα εξωτερικό πρόγραμμα, παρέχοντάς του πληροφορίες σχετικά με το συμβάν:
Η ανάγκη για αυτό προέκυψε όταν κατά τη λειτουργία των clusters άρχισαν να εμφανίζονται μικρές εργασίες που θέλαμε πολύ να αυτοματοποιήσουμε με τον σωστό τρόπο. Όλες αυτές οι μικρές εργασίες επιλύθηκαν χρησιμοποιώντας απλά σενάρια bash, αν και, όπως γνωρίζετε, είναι καλύτερο να γράφετε τελεστές στο Golang. Προφανώς, η επένδυση στην ανάπτυξη πλήρους κλίμακας ενός χειριστή για κάθε τόσο μικρή εργασία θα ήταν αναποτελεσματική.
Χειριστής σε 15 λεπτά
Ας δούμε ένα παράδειγμα του τι μπορεί να αυτοματοποιηθεί σε ένα σύμπλεγμα Kubernetes και πώς μπορεί να βοηθήσει ο χειριστής του κελύφους. Ένα παράδειγμα θα ήταν το εξής: αναπαραγωγή ενός μυστικού για πρόσβαση στο μητρώο του docker.
Οι ομάδες που χρησιμοποιούν εικόνες από ένα ιδιωτικό μητρώο πρέπει να περιέχουν στο μανιφέστο τους έναν σύνδεσμο προς ένα μυστικό με δεδομένα για πρόσβαση στο μητρώο. Αυτό το μυστικό πρέπει να δημιουργηθεί σε κάθε χώρο ονομάτων πριν από τη δημιουργία ομάδων. Αυτό μπορεί να γίνει χειροκίνητα, αλλά αν ρυθμίσουμε δυναμικά περιβάλλοντα, τότε ο χώρος ονομάτων για μία εφαρμογή θα γίνει πολύς. Κι αν επίσης δεν υπάρχουν 2-3 εφαρμογές... ο αριθμός των μυστικών γίνεται πολύ μεγάλος. Και κάτι ακόμα για τα μυστικά: Θα ήθελα να αλλάζω το κλειδί για πρόσβαση στο μητρώο από καιρό σε καιρό. Τελικά, χειρωνακτικές λειτουργίες ως λύση εντελώς αναποτελεσματική — πρέπει να αυτοματοποιήσουμε τη δημιουργία και την ενημέρωση των μυστικών.
Απλός αυτοματισμός
Ας γράψουμε ένα σενάριο φλοιού που εκτελείται μία φορά κάθε N δευτερόλεπτα και ελέγχει τους χώρους ονομάτων για την παρουσία ενός μυστικού, και αν δεν υπάρχει μυστικό, τότε δημιουργείται. Το πλεονέκτημα αυτής της λύσης είναι ότι μοιάζει με script shell in cron - μια κλασική και κατανοητή προσέγγιση για όλους. Το μειονέκτημα είναι ότι στο μεσοδιάστημα μεταξύ των εκκινήσεών του μπορεί να δημιουργηθεί ένας νέος χώρος ονομάτων και για κάποιο χρονικό διάστημα θα παραμείνει χωρίς μυστικό, γεγονός που θα οδηγήσει σε σφάλματα κατά την εκκίνηση pods.
Αυτοματισμός με χειριστή κελύφους
Για να λειτουργήσει σωστά το σενάριό μας, η κλασική εκκίνηση του cron πρέπει να αντικατασταθεί με μια εκκίνηση όταν προστίθεται ένας χώρος ονομάτων: σε αυτήν την περίπτωση, μπορείτε να δημιουργήσετε ένα μυστικό πριν το χρησιμοποιήσετε. Ας δούμε πώς μπορείτε να το εφαρμόσετε χρησιμοποιώντας το shell-operator.
Αρχικά, ας δούμε το σενάριο. Τα σενάρια με όρους κελύφους χειριστή ονομάζονται hook. Κάθε γάντζος όταν τρέχει με μια σημαία --config ενημερώνει τον χειριστή του κελύφους για τις δεσμεύσεις του, δηλ. σχετικά με τις εκδηλώσεις που θα πρέπει να ξεκινήσει. Στην περίπτωσή μας θα χρησιμοποιήσουμε onKubernetesEvent:
#!/bin/bash
if [[ $1 == "--config" ]] ; then
cat <<EOF
{
"onKubernetesEvent": [
{ "kind": "namespace",
"event":["add"]
}
]}
EOF
fi
Περιγράφεται εδώ ότι μας ενδιαφέρει να προσθέσουμε συμβάντα (add) αντικείμενα του τύπου namespace.
Τώρα πρέπει να προσθέσετε τον κώδικα που θα εκτελεστεί όταν συμβεί το συμβάν:
#!/bin/bash
if [[ $1 == "--config" ]] ; then
# конфигурация
cat <<EOF
{
"onKubernetesEvent": [
{ "kind": "namespace",
"event":["add"]
}
]}
EOF
else
# реакция:
# узнать, какой namespace появился
createdNamespace=$(jq -r '.[0].resourceName' $BINDING_CONTEXT_PATH)
# создать в нём нужный секрет
kubectl create -n ${createdNamespace} -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
...
data:
...
EOF
fi
Εξαιρετική! Το αποτέλεσμα ήταν ένα μικρό, όμορφο σενάριο. Για να την «αναβιώσετε», απομένουν δύο βήματα: προετοιμάστε την εικόνα και εκκινήστε την στο σύμπλεγμα.
Προετοιμασία εικόνας με γάντζο
Αν κοιτάξετε το σενάριο, μπορείτε να δείτε ότι χρησιμοποιούνται οι εντολές kubectl и jq. Αυτό σημαίνει ότι η εικόνα πρέπει να έχει τα ακόλουθα στοιχεία: το άγκιστρο μας, έναν χειριστή φλοιού που θα ακούει συμβάντα και θα εκτελεί το άγκιστρο και τις εντολές που χρησιμοποιεί το άγκιστρο (kubectl και jq). Το Hub.docker.com έχει ήδη μια έτοιμη εικόνα στην οποία είναι συσκευασμένα shell-operator, kubectl και jq. Το μόνο που μένει είναι να προσθέσετε ένα απλό γάντζο Dockerfile:
Ας δούμε ξανά το άγκιστρο και αυτή τη φορά γράψτε ποιες ενέργειες και με ποια αντικείμενα εκτελεί στο σύμπλεγμα:
εγγράφεται σε συμβάντα δημιουργίας χώρου ονομάτων.
δημιουργεί ένα μυστικό σε χώρους ονομάτων διαφορετικούς από αυτόν στον οποίο εκκινείται.
Αποδεικνύεται ότι το pod στο οποίο θα εκκινηθεί η εικόνα μας πρέπει να έχει δικαιώματα για να κάνει αυτές τις ενέργειες. Αυτό μπορεί να γίνει δημιουργώντας τον δικό σας Λογαριασμό Υπηρεσίας. Η άδεια πρέπει να γίνει με τη μορφή ClusterRole και ClusterRoleBinding, επειδή μας ενδιαφέρουν αντικείμενα από ολόκληρο το σύμπλεγμα.
Η τελική περιγραφή στο YAML θα μοιάζει κάπως έτσι:
Αυτό είναι όλο: ο χειριστής του κελύφους θα ξεκινήσει, θα εγγραφεί σε συμβάντα δημιουργίας χώρου ονομάτων και θα εκτελέσει το άγκιστρο όταν χρειάζεται.
Έτσι, η ένα απλό σενάριο φλοιού μετατράπηκε σε πραγματικό χειριστή για το Kubernetes και λειτουργεί ως μέρος ενός συμπλέγματος. Και όλα αυτά χωρίς την περίπλοκη διαδικασία ανάπτυξης χειριστών στο Golang:
Υπάρχει ένα άλλο παράδειγμα για αυτό το θέμα...
Θα αποκαλύψουμε το νόημά του με περισσότερες λεπτομέρειες σε μία από τις ακόλουθες δημοσιεύσεις.
φιλτράρισμα
Η παρακολούθηση αντικειμένων είναι καλή, αλλά συχνά υπάρχει ανάγκη αντίδρασης αλλαγή ορισμένων ιδιοτήτων αντικειμένων, για παράδειγμα, για να αλλάξετε τον αριθμό των αντιγράφων στο Deployment ή για να αλλάξετε τις ετικέτες αντικειμένων.
Όταν φθάνει ένα συμβάν, ο χειριστής φλοιού λαμβάνει το μανιφέστο JSON του αντικειμένου. Μπορούμε να επιλέξουμε τις ιδιότητες που μας ενδιαφέρουν σε αυτό το JSON και να εκτελέσουμε το άγκιστρο μόνο όταν αλλάζουν. Υπάρχει πεδίο για αυτό jqFilter, όπου πρέπει να καθορίσετε την έκφραση jq που θα εφαρμοστεί στο μανιφέστο JSON.
Για παράδειγμα, για να απαντήσετε σε αλλαγές σε ετικέτες για αντικείμενα ανάπτυξης, πρέπει να φιλτράρετε το πεδίο labels έξω από το γήπεδο metadata. Η διαμόρφωση θα είναι ως εξής:
Αυτή η έκφραση jqFilter μετατρέπει το μακρύ μανιφέστο JSON του Deployment σε σύντομο JSON με ετικέτες:
Ο χειριστής φλοιού θα εκτελέσει το άγκιστρο μόνο όταν αλλάξει αυτό το σύντομο JSON και οι αλλαγές σε άλλες ιδιότητες θα αγνοηθούν.
Πλαίσιο εκκίνησης γάντζου
Το hook config σάς επιτρέπει να καθορίσετε πολλές επιλογές για συμβάντα - για παράδειγμα, 2 επιλογές για συμβάντα από το Kubernetes και 2 χρονοδιαγράμματα:
Μια μικρή παρέκκλιση: ναι, υποστηρίζει το shell-operator εκτέλεση σεναρίων σε στυλ crontab. Περισσότερες λεπτομέρειες μπορείτε να βρείτε στο τεκμηρίωση.
Για να διακρίνει γιατί ξεκίνησε το άγκιστρο, ο χειριστής του κελύφους δημιουργεί ένα προσωρινό αρχείο και μεταβιβάζει τη διαδρομή προς αυτό σε μια μεταβλητή στο άγκιστρο BINDING_CONTEXT_TYPE. Το αρχείο περιέχει μια περιγραφή JSON για τον λόγο εκτέλεσης του άγκιστρου. Για παράδειγμα, κάθε 10 λεπτά το άγκιστρο θα λειτουργεί με το ακόλουθο περιεχόμενο:
Τα περιεχόμενα των πεδίων μπορούν να γίνουν κατανοητά από τα ονόματά τους και περισσότερες λεπτομέρειες μπορείτε να διαβάσετε τεκμηρίωση. Ένα παράδειγμα λήψης ονόματος πόρου από ένα πεδίο resourceName Η χρήση jq έχει ήδη παρουσιαστεί σε ένα άγκιστρο που αναπαράγει μυστικά:
jq -r '.[0].resourceName' $BINDING_CONTEXT_PATH
Μπορείτε να αποκτήσετε άλλα πεδία με παρόμοιο τρόπο.
Ποιο είναι το επόμενο;
Στο αποθετήριο του έργου, στο /examples καταλόγους, υπάρχουν παραδείγματα αγκίστρων που είναι έτοιμα να τρέξουν σε ένα σύμπλεγμα. Όταν γράφετε τα δικά σας άγκιστρα, μπορείτε να τα χρησιμοποιήσετε ως βάση.
Υπάρχει υποστήριξη για τη συλλογή μετρήσεων χρησιμοποιώντας το Prometheus - οι διαθέσιμες μετρήσεις περιγράφονται στην ενότητα ΜΕΤΡΕΣ.
Όπως μπορείτε να μαντέψετε, ο τελεστής κελύφους είναι γραμμένος στο Go και διανέμεται με άδεια ανοιχτού κώδικα (Apache 2.0). Θα είμαστε ευγνώμονες για οποιαδήποτε αναπτυξιακή βοήθεια έργο στο GitHub: και αστέρια, και ζητήματα, και αιτήματα έλξης.
Αίροντας το πέπλο της μυστικότητας, θα σας ενημερώσουμε επίσης ότι η shell-operator είναι μικρό μέρος του συστήματός μας που μπορεί να διατηρεί ενημερωμένα τα πρόσθετα εγκατεστημένα στο σύμπλεγμα Kubernetes και να εκτελεί διάφορες αυτόματες ενέργειες. Διαβάστε περισσότερα για αυτό το σύστημα είπα κυριολεκτικά τη Δευτέρα στο HighLoad++ 2019 στην Αγία Πετρούπολη - σύντομα θα δημοσιεύσουμε το βίντεο και τη μεταγραφή αυτής της αναφοράς.
Έχουμε ένα σχέδιο για να ανοίξουμε το υπόλοιπο σύστημα: τον χειριστή του πρόσθετου και τη συλλογή μας από άγκιστρα και μονάδες. Παρεμπιπτόντως, ο τελεστής πρόσθετου είναι ήδη διαθέσιμο στο github, αλλά η τεκμηρίωση για αυτό είναι ακόμα στο δρόμο. Η κυκλοφορία της συλλογής των ενοτήτων έχει προγραμματιστεί για το καλοκαίρι.