Pavel Selivanov, Solutions Architect bei Southbridge und Dozent bei Slurm, hielt einen Vortrag auf der DevOpsConf 2019. Dieser Vortrag ist Teil eines der Themen im vertieften Kurs zu Kubernetes „Slurm Mega“.
findet in Moskau vom 18. bis 20. November statt.
— Moskau, 22. bis 24. November.
sind jederzeit verfügbar.

Unter dem Cut — die Entschlüsselung des Vortrags.
Guten Tag, Kollegen und sympathisierende! Heute werde ich über Sicherheit sprechen.
Ich sehe, dass heute viele Sicherheitsbeauftragte im Raum sind. Ich entschuldige mich im Voraus, wenn ich Begriffe aus der Sicherheitswelt verwende, die nicht ganz so sind, wie ihr sie gewohnt seid.
Es ist so gekommen, dass mir vor etwa einem halben Jahr ein öffentlicher Kubernetes-Cluster in die Hände fiel. Öffentlich bedeutet, dass es eine beliebige Anzahl von Namespaces gibt, in diesen Namespaces sind Benutzer, die in ihrem Namespace isoliert sind. Alle diese Benutzer gehören verschiedenen Unternehmen. Nun, es war angedacht, diesen Cluster als CDN zu verwenden. Das heißt, man bekommt einen Cluster, gibt einen Benutzer dazu, man kommt in seinen Namespace und deployt seine Frontends.
Meiner vorherigen Firma wurde versucht, eine solche Dienstleistung zu verkaufen. Und ich wurde gebeten, den Cluster daraufhin zu testen, ob eine solche Lösung geeignet ist oder nicht.
Ich kam in diesen Cluster. Mir wurden eingeschränkte Rechte und ein eingeschränkter Namespace gegeben. Dort verstanden die Leute, was Sicherheit ist. Sie wussten, was Role-based Access Control (RBAC) in Kubernetes ist — und sie hatten es so eingestellt, dass ich Pods nicht separat von Deployments starten konnte. Ich kann mich nicht an die Aufgabe erinnern, die ich zu lösen versuchte, als ich einen Pod ohne Deployment starten wollte, aber ich wollte einfach einen Pod starten. Ich beschloss, zum Glück zu sehen, welche Rechte ich im Cluster habe, was ich kann, was ich nicht kann, was sie da gemacht haben. Nebenbei werde ich erzählen, was in ihrem RBAC falsch konfiguriert ist.
Es kam so, dass ich nach zwei Minuten Admin-Rechte für ihren Cluster erhielt, in alle benachbarten Namespaces schaute, sah, dass dort produktive Frontends von Unternehmen liefen, die den Dienst bereits gekauft und sich deployed hatten. Ich konnte mich kaum zurückhalten, nicht zu jemandem ins Frontend zu gehen und auf die Hauptseite ein obszönes Wort zu platzieren.
Ich werde an Beispielen zeigen, wie ich das geschafft habe und wie man sich davon schützen sollte.
Aber zuerst möchte ich mich vorstellen. Mein Name ist Pawel Selivanov. Ich bin Architekt bei der Firma Southbridge. Ich kenne mich mit Kubernetes, DevOps und verschiedenen modernen Technologien aus. Gemeinsam mit den Ingenieuren von Southbridge arbeite ich an diesen Themen, während ich berate.
Neben unserer Haupttätigkeit haben wir kürzlich ein Projekt gestartet, das wir Slerms nennen. Wir versuchen, unser Wissen über Kubernetes in die Breite zu tragen und anderen Menschen beizubringen, wie sie ebenfalls mit K8s arbeiten können.
Worüber ich heute sprechen werde. Das Thema meines Vortrags ist offensichtlich – es geht um die Sicherheit von Kubernetes-Clustern. Ich möchte jedoch gleich zu Beginn klarstellen, dass dieses Thema sehr umfangreich ist – und ich möchte von vornherein festhalten, worüber ich sicher nicht sprechen werde. Ich werde keine abgedroschenen Begriffe behandeln, die im Internet bereits zum hundertsten Mal durchgekaut wurden. Dinge wie RBAC und Zertifikate.
Ich werde darüber sprechen, was mir und meinen Kollegen in Bezug auf die Sicherheit in Kubernetes-Clustern Sorgen bereitet. Wir sehen diese Probleme sowohl bei Anbietern, die Kubernetes-Cluster bereitstellen, als auch bei den Kunden, die zu uns kommen. Und sogar bei Kunden, die von anderen beratenden Administrationsunternehmen zu uns kommen. Das Ausmaß der Tragödie ist in der Tat sehr groß.
Ich werde heute über drei Punkte sprechen:
- Benutzerrechte vs. Pod-Rechte. Benutzerrechte und Pod-Rechte sind nicht dasselbe.
- Informationssammlung über den Cluster. Ich werde zeigen, dass man aus einem Cluster alle benötigten Informationen sammeln kann, ohne besondere Rechte in diesem Cluster zu haben.
- DoS-Angriff auf den Cluster. Wenn wir keine Informationen sammeln können, können wir den Cluster dennoch in jedem Fall lahmlegen. Ich werde über DoS-Angriffe auf die Steuerelemente des Clusters sprechen.
Ein weiteres allgemeines Thema, auf das ich hinweisen möchte – worauf ich all dies getestet habe und worüber ich sicher sagen kann, dass es funktioniert.
Als Grundlage verwenden wir die Installation eines Kubernetes-Clusters mit Hilfe von Kubespray. Falls jemand es nicht weiß: Das ist im Grunde genommen eine Sammlung von Rollen für Ansible. Wir verwenden es ständig in der Arbeit. Es hat den Vorteil, dass es überall eingespielt werden kann – sowohl auf Hardware als auch in der Cloud. Eine Installationsmethode ist grundsätzlich für alles geeignet.
In diesem Cluster werde ich Kubernetes v1.14.5 verwenden. Der gesamte Kubernetes-Cluster, den wir betrachten werden, ist in Namespaces unterteilt, jeder Namespace gehört zu einem bestimmten Team, und die Mitglieder dieses Teams haben Zugriff auf ihren Namespace. Sie können nicht in andere Namespaces gehen, nur in ihren eigenen. Es gibt jedoch ein Admin-Konto, das Rechte für den gesamten Cluster hat.

Ich habe versprochen, dass das Erste, was wir tun werden, der Erhalt von Administratorrechten für den Cluster sein wird. Wir benötigen einen speziell vorbereiteten Pod, der den Kubernetes-Cluster angreift. Alles, was wir tun müssen, ist, ihn im Kubernetes-Cluster anzuwenden.
kubectl apply -f pod.yamlDieser Pod wird auf einen der Master des Kubernetes-Clusters gelangen. Und der Cluster wird uns danach erfreut eine Datei zurückgeben, die admin.conf genannt wird. In dieser Datei werden alle Admin-Zertifikate aufbewahrt, und der API-Zugang zum Cluster ist ebenfalls konfiguriert. So einfach kann man Administrationszugang erhalten, ich denke, zu 98 % der Kubernetes-Cluster.
Ich wiederhole, dieser Pod wurde von einem Entwickler in Ihrem Cluster erstellt, der Zugriff hat, um seine Vorschläge in einen kleinen Namespace zu deployen, der vollständig durch RBAC eingeschränkt ist. Er hatte keinerlei Rechte. Und dennoch kam das Zertifikat zurück.
Jetzt zum speziell vorbereiteten Pod. Wir starten mit einem beliebigen Image. Zum Beispiel nehmen wir debian:jessie.
Wir haben so etwas:
tolerations:
- effect: NoSchedule
operator: Exists
nodeSelector:
node-role.kubernetes.io/master: "" Was ist eine Toleranz? Die Master im Kubernetes-Cluster sind normalerweise mit einer Sache markiert, die taint („Toxizität“ auf Englisch) genannt wird. Das Wesen dieser "Toxizität" besagt, dass auf Master-Nodes keine Pods zugewiesen werden können. Aber niemand hindert einen Pod daran, zu deklarieren, dass er gegen diese "Toxizität" tolerant ist. Der Abschnitt Toleration sagt genau, dass, wenn auf einem Node NoSchedule steht, unser Pod gegen diese Toxizität tolerant ist – und es gibt keine Probleme.
Als Nächstes sagen wir, dass unser Pod nicht nur tolerant ist, sondern auch speziell auf den Master gelangen möchte. Denn auf den Mastern befinden sich die wertvollsten Dinge, die wir benötigen – alle Zertifikate. Daher geben wir nodeSelector an – und wir haben ein Standardlabel auf den Mastern, das es uns ermöglicht, aus allen Nodes des Clusters genau die Nodes auszuwählen, die Master sind.
Mit diesen beiden Abschnitten wird der Pod definitiv auf dem Master ankommen. Und es wird ihm erlaubt, dort zu leben.
Aber nur auf den Master zu gelangen, reicht nicht aus. Das bringt uns nichts. Daher haben wir als Nächstes diese beiden Dinge:
hostNetwork: true
hostPID: true Wir geben an, dass unser Pod, den wir starten, im Kern-Namensraum, im Netzwerk-Namensraum und im PID-Namensraum leben wird. Sobald der Pod auf dem Master läuft, kann er alle echten, aktiven Schnittstellen dieses Knotens sehen, den gesamten Verkehr abhören und die PID aller Prozesse sehen.
Danach ist es einfach. Nehmen Sie etcd und lesen Sie, was Sie wollen.
Das Interessanteste ist diese Möglichkeit von Kubernetes, die dort standardmäßig vorhanden ist.
volumeMounts:
- mountPath: /host
name: host
volumes:
- hostPath:
path: /
type: Verzeichnis
name: host Und die Essenz davon ist, dass wir im Pod, den wir starten, auch ohne Rechte auf diesen Cluster sagen können, dass wir ein Volume des Typs hostPath erstellen wollen. Das bedeutet, wir nehmen den Pfad vom Host, auf dem wir gestartet werden — und verwenden ihn als Volume. Und weiter benennen wir es name: host. Dieses gesamte hostPath montieren wir in den Pod. In diesem Beispiel in das Verzeichnis /host.
Ich wiederhole es noch einmal. Wir haben dem Pod gesagt, er solle auf den Master kommen, das hostNetwork und hostPID erhalten — und den gesamten Root des Masters in diesen Pod einbinden.
Sie verstehen, dass wir auf Debian Bash laufen haben und dieses Bash unter Root arbeitet. Das heißt, wir haben gerade Root auf dem Master erhalten, obwohl wir keine speziellen Berechtigungen im Kubernetes-Cluster haben.
Die gesamte Aufgabe besteht nun darin, in den Pod in das Verzeichnis /host /etc/kubernetes/pki zu gehen, falls ich mich nicht irre, und dort alle Master-Zertifikate des Clusters anzufordern und somit Admin des Clusters zu werden.
Wenn man so schaut, sind das einige der gefährlichsten Berechtigungen in Pods — unabhängig von den Rechten, die der Benutzer hat:

Wenn ich das Recht habe, einen Pod in einem bestimmten Namesraum des Clusters zu starten, hat dieser Pod diese Rechte standardmäßig. Ich kann privilegierte Pods starten, und das bedeutet so gut wie alle Rechte, praktisch Root auf dem Knoten.
Mein Favorit — Root-Benutzer. Und Kubernetes hat diese Option 'Run As Non-Root'. Das ist ein gewisser Schutz vor Hackern. Wissen Sie, was ein 'moldawischer Virus' ist? Wenn Sie plötzlich Hacker sind und in meinen Kubernetes-Cluster gekommen sind, dann bitten wir, arme Administratoren: 'Bitte geben Sie in Ihren Pods, mit denen Sie meinen Cluster hacken wollen, run as non-root an. Sonst kann es passieren, dass Sie einen Prozess in Ihrem Pod als Root starten und es Ihnen sehr einfach sein wird, mich zu hacken. Schützen Sie sich bitte selbst.'
Das Host-Path-Volume — meiner Meinung nach der schnellste Weg, das gewünschte Ergebnis vom Kubernetes-Cluster zu erhalten.
Aber was sollen wir mit all dem machen?
Gedanken, die jedem normalen Administrator kommen sollten, der mit Kubernetes konfrontiert ist: „Ah, ich habe es doch gesagt, Kubernetes funktioniert nicht. Es hat Löcher. Und das ganze Ding ist Mist.“ Tatsächlich gibt es so etwas wie Dokumentation, und wenn man dort nachschaut, gibt es einen Abschnitt .
Das ist ein yaml-Objekt – wir können es im Kubernetes-Cluster erstellen – das Aspekte der Sicherheit genau in der Beschreibung von Pods kontrolliert. Das bedeutet, dass es die Berechtigungen zum Nutzen von hostNetwork, hostPID und bestimmten Typen von Volumes, die in Pods beim Start vorhanden sind, steuert. Mit Hilfe von Pod Security Policy kann all dies beschrieben werden.
Das Interessanteste an der Pod Security Policy ist, dass alle Installationen von PSP im Kubernetes-Cluster nicht einfach beschrieben sind, sie sind standardmäßig deaktiviert. Die Pod Security Policy wird mithilfe eines Admission-Plugins aktiviert.
Okay, wir werden die Pod Security Policy im Cluster bereitstellen und sagen, dass wir bestimmte Service-Pods im Namespace haben, auf den nur Administratoren zugreifen können. Nehmen wir an, in allen anderen Pods sind die Berechtigungen eingeschränkt. Denn wahrscheinlich benötigen die Entwickler keine privilegierten Pods in Ihrem Cluster.
Und es scheint alles in Ordnung zu sein. Und unser Kubernetes-Cluster kann nicht in zwei Minuten gehackt werden.
Es gibt ein Problem. Höchstwahrscheinlich, wenn Sie einen Kubernetes-Cluster haben, ist in Ihrem Cluster Überwachung eingerichtet. Ich wage sogar vorherzusagen, dass, wenn in Ihrem Cluster Überwachung vorhanden ist, diese Prometheus heißt.
Das, was ich jetzt sagen werde, gilt sowohl für den Prometheus-Operator als auch für Prometheus, der als reines Produkt bereitgestellt wird. Die Frage ist, dass, wenn ich im Cluster nicht so schnell einen Administrator bekommen kann, das bedeutet, dass ich mehr suchen muss. Und ich kann mit Ihrer Überwachung suchen.
Wahrscheinlich haben alle die gleichen Artikel auf Habr gelesen, und die Überwachung befindet sich im Namespace monitoring. Das Helm-Chart heißt bei allen ungefähr gleich. Ich nehme an, wenn Sie helm install stable/prometheus ausführen, werden Sie ungefähr die gleichen Namen erhalten. Und wahrscheinlich muss ich den DNS-Namen in Ihrem Cluster nicht erraten. Weil er standardmäßig ist.

Dann haben wir einen gewissen dev ns, in dem wir einen bestimmten Pod starten können. Und dann können wir aus diesem Pod ganz einfach Folgendes machen:
$ curl http://prometheus-kube-state-metrics.monitoring prometheus-kube-state-metrics ist einer der Prometheus-Exporter, der Metriken aus der Kubernetes-API sammelt. Es gibt eine Menge Daten darüber, was in Ihrem Cluster läuft, wie es läuft und welche Probleme Sie damit haben.
Ein einfaches Beispiel:
kube_pod_container_info{namespace="kube-system",pod="kube-apiserver-k8s-1",container="kube-apiserver",image=
"gcr.io/google-containers/kube-apiserver:v1.14.5"
,image_id="docker-pullable://gcr.io/google-containers/kube-apiserver@sha256:e29561119a52adad9edc72bfe0e7fcab308501313b09bf99df4a9638ee634989",container_id="docker://7cbe7b1fea33f811fdd8f7e0e079191110268f2853397d7daf08e72c22d3cf8b"} 1
Mit einer einfachen curl-Anfrage aus einem nicht privilegierten Pod können Sie solche Informationen erhalten. Wenn Sie nicht wissen, welche Version von Kubernetes Sie verwenden, wird es Ihnen dies leicht erklären.
Und das Interessanteste ist, dass Sie neben dem Zugriff auf kube-state-metrics auch direkt auf Prometheus zugreifen können. Sie können Metriken von dort sammeln. Sie können sogar Metriken daraus erstellen. Theoretisch können Sie eine Anfrage aus dem Cluster an Prometheus stellen, die es einfach ausschaltet. Und Ihre Überwachung wird vollständig aufhören, im Cluster zu funktionieren.
Hier stellt sich die Frage, ob irgendeine externe Überwachung Ihre Überwachung überwacht. Gerade jetzt hatte ich die Möglichkeit, im Kubernetes-Cluster ohne Folgen für mich zu handeln. Sie werden nicht einmal merken, dass ich dort tätig bin, da es keine Überwachung mehr gibt.
Ebenso wie mit PSP scheint es, als läge das Problem darin, dass all diese modernen Technologien – Kubernetes, Prometheus – einfach nicht funktionieren und voller Löcher sind. In Wirklichkeit ist das nicht der Fall.
Es gibt so etwas – .
Wenn Sie ein normaler Administrator sind, wissen Sie wahrscheinlich, dass eine Network Policy ein weiteres YAML ist, von denen es im Cluster bereits viele gibt. Und einige Network Policies sind definitiv nicht notwendig. Selbst wenn Sie gelesen haben, dass Network Policy eine YAML-Firewall von Kubernetes ist, die den Zugriff zwischen Namespaces und Pods einschränkt, haben Sie wahrscheinlich entschieden, dass eine Firewall im YAML-Format in Kubernetes nur ein weiteres abstraktes Konzept ist... Nein, das ist definitiv nicht notwendig.
Selbst wenn Ihre Sicherheitsexperten nicht darüber informiert wurden, dass Sie mit Ihrem Kubernetes ganz einfach eine sehr granulierte Firewall erstellen können. Wenn sie das noch nicht wissen und Sie nicht fragen: „Nun, geben Sie, geben Sie…“ In jedem Fall benötigen Sie Network Policies, um den Zugriff auf einige Dienststellen zu sperren, die Sie aus Ihrem Cluster abrufen können, ohne jegliche Autorisierung.
Wie im Beispiel, das ich angeführt habe, können Sie kube state metrics aus jedem Namespace im Kubernetes-Cluster abrufen, ohne dafür irgendwelche Rechte zu haben. Die Network Policies haben den Zugriff aus allen anderen Namespaces auf den Monitoring-Namespace gesperrt, und das war's: Kein Zugriff, keine Probleme. In allen Charts, die vorhanden sind – sowohl im Standard-Prometheus als auch in dem Prometheus, der im Operator ist – gibt es einfach in den Helm-Werten eine Option, die Network Policies für sie zu aktivieren. Sie müssen es einfach aktivieren, und sie werden funktionieren.
Es gibt hier tatsächlich ein Problem. Als normaler, bärtiger Administrator haben Sie wahrscheinlich entschieden, dass Network Policies nicht notwendig sind. Und nachdem Sie verschiedene Artikel auf Seiten wie Habr gelesen haben, haben Sie entschieden, dass Flannel, insbesondere im Host-Gateway-Modus, das Beste ist, was Sie wählen können.
Was tun?
Sie können versuchen, die Netzwerklösung, die Sie in Ihrem Kubernetes-Cluster haben, neu zu deployen und sie durch etwas Funktionaleres zu ersetzen. Zum Beispiel durch dasselbe Calico. Aber ich möchte gleich sagen, dass die Aufgabe, die Netzwerklösung in einem produktiven Kubernetes-Cluster zu ändern, ziemlich anspruchsvoll ist. Ich habe es zweimal gelöst (beide Male theoretisch), aber wir haben sogar in den Slorum gezeigt, wie man das macht. Für unsere Schulungsteilnehmer haben wir gezeigt, wie man die Netzwerklösung in einem Kubernetes-Cluster ändert. Prinzipiell können Sie versuchen, dies so zu machen, dass es im Produktionscluster keine Ausfallzeiten gibt. Aber wahrscheinlich wird es Ihnen nicht gelingen.
Und das Problem lässt sich tatsächlich ganz einfach lösen. Im Cluster gibt es Zertifikate, und Sie wissen, dass die Zertifikate nach einem Jahr ablaufen. Nun, und normalerweise ist die übliche Lösung mit Zertifikaten im Cluster – warum sollten wir uns damit herumschlagen, wir heben daneben einen neuen Cluster an, im alten kann er ablaufen, und wir deployen alles neu. Das Problem ist, wenn es abläuft, werden wir einen ganzen Tag darauf warten müssen, aber dafür haben wir einen neuen Cluster.
Beim Erstellen des neuen Clusters sollten Sie auch Calico anstelle von Flannel einfügen.
Was tun, wenn Sie Zertifikate haben, die für hundert Jahre ausgestellt wurden und Sie den Cluster nicht neu bereitstellen möchten? Es gibt so ein Ding namens Kube-RBAC-Proxy. Es handelt sich um eine sehr coole Entwicklung, die es ermöglicht, sich als Sidecar-Container in jeden Pod im Kubernetes-Cluster einzufügen. Und es fügt diesem Pod tatsächlich die Autorisierung über RBAC von Kubernetes hinzu.
Es gibt ein Problem. Früher war diese Lösung Kube-RBAC-Proxy in dem Prometheus-Operator integriert. Aber das gibt es jetzt nicht mehr. Die modernen Versionen stützen sich darauf, dass Sie eine Netzwerk-Policy haben und diese verwenden, um zu schließen. Daher müssen Sie das Chart ein wenig umschreiben. Wenn Sie tatsächlich in den , dort finden Sie Beispiele, wie man dies als Sidecars verwenden kann, und die Charts müssen minimal umgeschrieben werden.
Es gibt noch ein kleines Problem. Nicht nur Prometheus gibt seine Metriken einfach so weiter. Auch unsere gesamten Cluster-Komponenten im Kubernetes können ihre Metriken bereitstellen.
Aber wie ich schon sagte, wenn Sie keinen Zugang zum Cluster haben und keine Informationen sammeln können, können Sie zumindest etwas Schaden anrichten.
Ich werde Ihnen also schnell zwei Möglichkeiten zeigen, wie man die Gesundheit eines Kubernetes-Clusters beeinträchtigen kann.
Sie werden lachen, wenn ich das erzähle, es sind zwei Fälle aus dem echten Leben.
Erste Methode. Ressourcenerschöpfung.
Wir starten einen weiteren speziellen Pod. Er wird so eine Sektion haben.
resources:
requests:
cpu: 4
memory: 4Gi Wie Sie wissen, sind die Requests die Menge an CPU und Speicher, die auf dem Host für bestimmte Pods mit Requests reserviert wird. Wenn wir einen vierkernigen Host im Kubernetes-Cluster haben und ein Pod mit vier CPU-Requests darauf kommt, kann kein weiterer Pod mit Requests auf diesen Host kommen.
Wenn ich einen solchen Pod starte und dann den Befehl ausführe:
$ kubectl scale special-pod --replicas=...Dann kann sich niemand mehr im Kubernetes-Cluster bereitstellen. Denn auf allen Knoten sind die Requests erschöpft. Auf diese Weise werde ich Ihren Kubernetes-Cluster anhalten. Wenn ich das abends mache, kann ich Deployments ziemlich lange stoppen.
Wenn wir ein weiteres Mal in die Dokumentation von Kubernetes schauen, werden wir etwas sehen, das als Limit Range bezeichnet wird. Es legt die Ressourcen für Clusterobjekte fest. Sie können ein YAML-Objekt für Limit Range schreiben, es in bestimmte Namespaces anwenden – und dann können Sie in diesem Namespace angeben, dass Sie Standard-, Maximal- und Minimalressourcen für Pods haben.
Mit einem solchen Mechanismus können wir die Benutzer in bestimmten produktbezogenen Namespaces der Teams daran hindern, bei ihren Pods irgendwelchen Müll anzugeben. Aber leider, selbst wenn Sie dem Benutzer sagen, dass er keine Pods mit Anfragen über eine CPU starten darf, gibt es diesen wunderbaren Befehl scale, oder über das Dashboard können sie skalieren.
Und hier kommt der zweite Weg ins Spiel. Wir starten 11 111 111 111 111 Pods. Das sind elf Milliarden. Das ist nicht, weil ich mir diese Zahl ausgedacht habe, sondern weil ich es selbst gesehen habe.
Echte Geschichte. Spät am Abend wollte ich gerade das Büro verlassen. Ich schaue, in der Ecke sitzt eine Gruppe von Entwicklern und macht etwas hektisch mit Laptops. Ich gehe zu den Jungs und frage: „Was ist passiert?“
Etwa früher, gegen neun Uhr abends, wollte einer der Entwickler nach Hause gehen. Und er dachte: „Ich werde jetzt meine Anwendung auf eins skalieren“. Er drückte die Eins, aber das Internet hat ein bisschen gestockt. Er drückte noch einmal auf die Eins, er drückte auf die Eins, klickte auf Enter. Er klickte auf alles, was er konnte. Dann lebte das Internet wieder auf – und alles begann, auf diese Zahl zu skalieren.
Tatsächlich fand diese Geschichte nicht auf Kubernetes statt, damals war es Nomad. Das Ganze endete damit, dass nach einer Stunde unserer Versuche, Nomad von seinen hartnäckigen Versuchen zu skalieren abzuhalten, Nomad antwortete, dass es nicht aufhören würde zu skalieren und sich um nichts anderes kümmern würde. „Ich habe genug, ich gehe.“ Und schloss sich.
Ich habe natürlich versucht, dasselbe auf Kubernetes zu machen. Elf Milliarden Pods haben Kubernetes nicht erfreut, er sagte: „Kann ich nicht. Überschreitet interne Limits“. Aber 1 000 000 000 Pods hat es geschafft.
Als Antwort auf eine Milliarde begann Kubernetes tatsächlich zu skalieren. Je weiter der Prozess fortschritt, desto mehr Zeit benötigte er für das Erstellen neuer Pods. Aber der Prozess lief weiter. Das einzige Problem ist, dass ich, wenn ich Pods in meinem Namespace unbegrenzt starten kann, auch ohne Requests und Limits eine so große Anzahl an Pods mit bestimmten Aufgaben starten kann, dass die Knoten durch diese Aufgaben im Hinblick auf den Speicher und die CPU überlastet werden. Wenn ich so viele Pods starte, muss die Information aus ihnen in den Speicher gelangen, sprich etcd. Und wenn zu viele Informationen dort ankommen, beginnt der Speicher sehr langsam zu reagieren — und Kubernetes hat Leistungseinbußen.
Und ein weiteres Problem… Wie Sie wissen, bestehen die Steuerungselemente von Kubernetes nicht aus einem einzigen zentralen Element, sondern aus mehreren Komponenten. Dort gibt es unter anderem einen Controller-Manager, einen Scheduler und so weiter. All diese Komponenten beginnen gleichzeitig, unnötige, ineffiziente Arbeiten zu verrichten, die mit der Zeit immer mehr Zeit in Anspruch nehmen. Der Controller-Manager wird neue Pods erstellen. Der Scheduler wird versuchen, ihnen einen neuen Knoten zuzuweisen. Neue Knoten in Ihrem Cluster werden Ihnen wahrscheinlich bald ausgehen. Das Kubernetes-Cluster wird immer langsamer arbeiten.
Aber ich habe beschlossen, noch weiter zu gehen. Wie Sie wissen, gibt es in Kubernetes eine Funktion, die als Service bezeichnet wird. In der Regel arbeitet dieser Service in Ihren Clustern wahrscheinlich mit IP Tables.
Wenn man beispielsweise eine Milliarde Pods startet und dann mit einem Skript Kubernetes anweist, neue Services zu erstellen:
for i in {1..1111111}; do
kubectl expose deployment test --port 80
--overrides="{"apiVersion": "v1",
"metadata": {"name": "nginx$i"}}";
done Auf allen Knoten des Clusters werden ungefähr gleichzeitig immer neue IP-Tables-Regeln generiert. Für jeden Service werden eine Milliarde IP-Tables-Regeln generiert.
Ich habe das Ganze bei mehreren Tausend, bis zu einem Dutzend überprüft. Und das Problem ist, dass es schon auf dieser Schwelle ziemlich schwierig ist, eine SSH-Verbindung zu einem Knoten herzustellen. Weil Pakete, die durch so viele Ketten gehen, nicht gerade gut abschneiden.
Und auch das alles wird mit Kubernetes gelöst. Es gibt so ein Objekt namens Resource Quota. Es legt die Anzahl der verfügbaren Ressourcen und Objekte für den Namespace im Cluster fest. Wir können ein YAML-Objekt in jedem Namespace des Kubernetes-Clusters erstellen. Mit diesem Objekt können wir sagen, dass für diesen Namespace eine bestimmte Anzahl von Requests, Limits bereitgestellt wird, und dann können wir sagen, dass in diesem Namespace 10 Services und 10 Pods erstellt werden können. Und der Entwickler kann abends machen, was er will. Kubernetes wird ihm sagen: „Sie können Ihre Pods nicht bis zu dieser Anzahl skalieren, weil es die Ressourcenkontingent überschreitet“. Das war's, das Problem ist gelöst. .
Ein problematischer Punkt taucht in diesem Zusammenhang auf. Sie spüren, wie schwierig es wird, in Kubernetes einen Namespace zu erstellen. Um ihn zu erstellen, müssen wir viele Dinge berücksichtigen.
Resource Quota + Limit Range + RBAC
• Namespace erstellen
• Limit Range innerhalb erstellen
• Resource Quota innerhalb erstellen
• Service Account für CI erstellen
• Role Binding für CI und Benutzer erstellen
• Optional die benötigten Service Pods starten
Daher möchte ich die Gelegenheit nutzen, um meine Entwicklungen zu teilen. Es gibt so eine Sache, die Operator SDK heißt. Dies ist eine Möglichkeit, im Kubernetes-Cluster Operatoren für ihn zu schreiben. Sie können Operatoren mit Ansible schreiben.
Zuerst hatten wir es mit Ansible geschrieben, und dann habe ich gesehen, dass es das Operator SDK gibt und die Ansible-Rolle in einen Operator umgeschrieben. Dieser Operator ermöglicht es, im Kubernetes-Cluster ein Objekt zu erstellen, das als Kommando bezeichnet wird. Innerhalb des Kommandos ermöglicht es, in YAML die Umgebung für dieses Kommando zu beschreiben. Und innerhalb der Umgebung des Kommandos erlaubt es zu beschreiben, welche Ressourcen wir zuweisen.
Klein .
Und abschließend. Was soll man mit alldem tun?
Erstens. Pod Security Policy — das ist gut. Und obwohl keiner der Kubernetes Installer sie bis heute verwendet, sollten sie in Ihren Clustern verwendet werden.
Network Policy — das ist keine weitere unnötige Funktion. Das ist es, was im Cluster tatsächlich benötigt wird.
Limit Range/Resource Quota — es wird Zeit, das zu verwenden. Wir haben schon lange damit begonnen, und ich war lange überzeugt, dass alle das umfassend anwenden. Es stellte sich heraus, dass es eine Seltenheit ist.
Neben dem, was ich in meinem Vortrag erwähnt habe, gibt es nicht dokumentierte Funktionen, die es ermöglichen, den Cluster anzugreifen. Kürzlich veröffentlicht. .
Einige Dinge sind so traurig und ärgerlich. Zum Beispiel können unter bestimmten Bedingungen die Kubelets im Kubernetes-Cluster den Inhalt des Warlocks-Verzeichnisses an nicht autorisierte Benutzer weitergeben.
Es gibt Anleitungen, wie man alles reproduzieren kann, was ich beschrieben habe. Dort liegen Dateien mit Produktionsbeispielen, wie ResourceQuota und Pod Security Policy aussehen. Und all dies kann ausprobiert werden.
Vielen Dank an alle.
Quelle: habr.com
