Mein Name ist Viktor Yagofarov, und ich bin als technischer Leiter für die Entwicklung des Kubernetes-Systems bei DomClick im Bereich Operations tätig. Ich möchte über die Struktur unserer Dev Ops-Prozesse, die Besonderheiten des Betriebs eines der größten K8s-Cluster in Russland sowie über die DevOps/SRE-Praktiken sprechen, die unser Team anwendet.

Operations-Team
Im Operations-Team arbeiten derzeit 15 Personen. Drei von ihnen sind für das Büro zuständig, zwei sind in einer anderen Zeitzone tätig und stehen auch nachts zur Verfügung. Somit ist immer jemand aus dem Ops-Team am Monitor und bereit, auf Vorfälle jeder Art zu reagieren. Wir haben keine Nachtdienste, was unsere Psyche schützt und es allen ermöglicht, auszuschlafen und die Freizeit nicht nur vor dem Computer zu verbringen.

Die Kompetenzen sind vielfältig: Netzwerkadministratoren, Datenbankadministratoren, ELK-Stack-Spezialisten, Kubernetes-Administratoren/-Entwickler, Monitoring-Experten, Virtualisierungsspezialisten, Hardware-Profis usw. Was uns vereint, ist das: Jeder kann in gewissem Maße jeden von uns ersetzen. Das bedeutet zum Beispiel, neue Knoten in ein k8s-Cluster einfügen, PostgreSQL aktualisieren, eine CI/CD-Pipeline mit Ansible schreiben, etwas mit Python/Bash/Go automatisieren oder Hardware im Rechenzentrum anschließen. Starke Kompetenzen in einem bestimmten Bereich hindern nicht daran, die Richtung zu wechseln und in einem anderen Bereich weiterzulernen. Zum Beispiel habe ich mich als PostgreSQL-Spezialist in einem Unternehmen beworben, und jetzt ist mein Hauptverantwortungsbereich die Kubernetes-Cluster-Administration. Im Team wird persönliches Wachstum stets begrüßt und das Gefühl der Unterstützung ist sehr ausgeprägt.
Übrigens, wir sind auf der Suche nach neuen Talenten. Die Anforderungen an die Bewerber sind ziemlich Standard. Besonders wichtig ist mir, dass die Person gut ins Team passt, konfliktfähig ist, aber auch in der Lage ist, ihre Meinung zu vertreten, den Wunsch hat, sich weiterzuentwickeln und keine Angst hat, Neues zu probieren und eigene Ideen einzubringen. Außerdem sind Programmierkenntnisse in Skriptsprachen sowie Grundkenntnisse in Linux und Englisch erforderlich. Englisch ist notwendig, damit die Person im Falle eines Fehlers innerhalb von 10 Sekunden eine Lösung googeln kann, und nicht innerhalb von 10 Minuten. Es ist leider schwierig, Fachkräfte mit fundierten Linux-Kenntnissen zu finden: Es ist zwar komisch, aber zwei von drei Kandidaten können die Frage nicht beantworten: „Was ist der Load Average? Woraus setzt er sich zusammen?“ und sie betrachten die Frage „Wie erstellt man einen Core Dump aus einem C-Programm?“ als etwas aus der Welt der Supermenschen… oder Dinosaurier. Damit müssen wir uns abfinden, da die Menschen in der Regel stark in anderen Kompetenzen sind, und das „Linux“ bringen wir ihnen bei. Warum all das für einen DevOps-Ingenieur in der modernen Cloud-Welt wichtig ist, kann ich hier nicht im Detail erläutern, aber wenn ich es in drei Worten sagen müsste: Das alles ist notwendig.
Team Tools
Ein wesentlicher Bestandteil der Automatisierung ist das Team Tools. Ihre Hauptaufgabe besteht darin, benutzerfreundliche grafische und CLI-Tools für Entwickler zu erstellen. Zum Beispiel ermöglicht unser internes Tool Confer, mit nur wenigen Klicks eine Anwendung in Kubernetes auszurollen, die Ressourcen und Schlüsseln aus einem Vault zu konfigurieren usw. Zuvor verwendeten wir Jenkins + Helm 2, aber es war notwendig, ein eigenes Tool zu entwickeln, um Copy-Paste zu vermeiden und Einheitlichkeit im Software-Lebenszyklus zu gewährleisten.
Das Ops-Team schreibt keine Pipelines für die Entwickler, kann jedoch bei Fragen zur Erstellung beraten (einige verwenden immer noch Helm 3).
DevOps
Was DevOps betrifft, so verstehen wir es so:
Die Dev-Teams schreiben Code und stellen ihn über Confer in dev -> qa/stage -> prod bereit. Die Verantwortung dafür, dass der Code flüssig läuft und keine Fehler aufweist, liegt bei den Dev- und Ops-Teams. Während der Tageszeit sollte in erster Linie der diensthabende Ops-Mitarbeiter auf Vorfälle mit seiner Anwendung reagieren. In den Abend- und Nachtstunden muss der Ops-Administrator den diensthabenden Entwickler benachrichtigen, wenn er sicher ist, dass das Problem nicht in der Infrastruktur liegt. Alle Metriken und Alarme im Monitoring erscheinen automatisch oder halbautomatisch.
Der Verantwortungsbereich von Ops beginnt mit der Bereitstellung der Anwendung in der Produktion, doch die Verantwortung von Dev endet damit nicht — wir arbeiten zusammen und befinden uns im selben Boot.
Entwickler beraten die Administratoren, wenn Hilfe beim Schreiben eines Admin-Microservices benötigt wird (zum Beispiel Go-Backend + HTML5), während die Administratoren die Entwickler zu allen Infrastrukturfragen oder Fragen im Zusammenhang mit k8s beraten.
Übrigens haben wir überhaupt kein Monolithen, sondern nur Microservices. Ihre Anzahl schwankt derzeit zwischen 900 und 1000 im Prod-k8s-Cluster, gemessen an der Anzahl. deployments. Die Anzahl der Pods variiert zwischen 1700 und 2000. Im Prod-Cluster befinden sich derzeit etwa 2000 Pods.
Genaue Zahlen kann ich nicht nennen, da wir uns um unnötige Mikrodienste kümmern und diese in einem halbautomatischen Modus entfernen. Die Überwachung überflüssiger Entitäten in k8s erfolgt durch , was Ressourcen und Kosten erheblich spart.
Ressourcenmanagement
Überwachung
Ein gut strukturiertes und informatives Monitoring ist der Schlüssel zum Betrieb eines großen Clusters. Bisher haben wir keine universelle Lösung gefunden, die 100 % aller Anforderungen an das Monitoring abdeckt, deshalb entwickeln wir regelmäßig verschiedene maßgeschneiderte Lösungen in diesem Bereich.
- Zabbix. Die bewährte Überwachung, die in erster Linie dazu dient, den allgemeinen Zustand der Infrastruktur zu überwachen. Sie informiert uns, wenn ein Knoten aufgrund von CPU, RAM, Speicher, Netzwerk usw. ausfällt. Nichts Aufregendes, aber wir haben auch ein separates DaemonSet von Agenten, mit denen wir beispielsweise den Zustand von DNS im Cluster überwachen: wir suchen nach hängenden Pods von coredns und überprüfen die Erreichbarkeit externer Hosts. Man könnte sich fragen, warum man sich damit beschäftigen sollte, aber bei hohem Traffic ist dieses Element ein ernstzunehmender Ausfallpunkt. Zuvor habe ich bereits , wie ich mit der DNS-Leistung im Cluster umgegangen bin.
- Prometheus Operator. Eine Reihe von verschiedenen Exporteuren bietet einen umfassenden Überblick über alle Clusterkomponenten. Anschließend visualisieren wir all das auf großen Dashboards in Grafana und verwenden alertmanager für die Benachrichtigungen.
Ein weiteres nützliches Werkzeug für uns war . Wir haben es entwickelt, nachdem wir mehrmals mit der Situation konfrontiert wurden, dass ein Team die Ingress-Pfade eines anderen Teams überschneidet, was zu 50x-Fehlern führte. Jetzt überprüfen die Entwickler vor dem Deployment in die Produktion, dass niemand betroffen ist. Für mein Team ist es ein nützliches Werkzeug zur Erstdiagnose von Problemen mit Ingress. Lustig dabei ist, dass es ursprünglich für Admins geschrieben wurde und relativ „grobschlächtig“ aussah, aber nachdem es bei den Entwicklungsteams beliebt wurde, hat es sich stark verändert und sieht nicht mehr aus wie „ein Admin, der eine Weboberfläche für Admins erstellt hat“. Bald werden wir dieses Tool aufgeben und ähnliche Situationen werden bereits vor dem Rollout der Pipeline validiert.
Teamressourcen im „Kubernetes“
Bevor wir mit den Beispielen beginnen, sollten wir erklären, wie die Ressourcenzuteilung bei uns funktioniert. Mikrodiensten.
Um zu verstehen, welche Teams und in welchen Mengen ihre Ressourcen (CPU, RAM, lokales SSD) nutzen, weisen wir jeder Gruppe ihre eigenen zu. namespace In Kubernetes definieren wir die maximalen Ressourcen für CPU, RAM und Speicher und besprechen im Voraus die Anforderungen der Teams. In der Regel wird ein Team nicht den gesamten Cluster für sich beanspruchen und Tausende von Kernen sowie Terabytes an RAM reservieren. Der Zugang zu Namespaces wird über AD (wir verwenden RBAC) verwaltet. Namespaces und ihre Limits werden über Pull-Requests im GIT-Repository hinzugefügt, und anschließend wird alles automatisch durch die Ansible-Pipeline bereitgestellt.
Beispiel für die Ressourcenzuweisung an ein Team:
namespaces:
chat-team:
pods: 23
limits:
cpu: 11
memory: 20Gi
requests:
cpu: 11
memory: 20Gi
Requests und Limits
In Kubernetes Request ist die Menge der garantiert reservierten Ressourcen für pod (einen oder mehrere Docker-Container) im Cluster. Das Limit ist der nicht garantierte Höchstwert. Oft sieht man in Grafiken, dass ein Team sich für alle seine Anwendungen zu viele Requests zugewiesen hat und seine Anwendung nicht im Kubernetes bereitstellen kann, da alle Requests für ihren Namespace bereits "verbraucht" sind.
Die richtige Lösung in einem solchen Fall: Das tatsächliche Ressourcenverbrauch analysieren und mit der angeforderten Menge (Request) vergleichen.


Auf den obigen Screenshots ist zu sehen, dass die „angeforderten“ (Requested) CPUs an die tatsächliche Anzahl der Threads angepasst werden, während die Limits die tatsächliche Anzahl der CPU-Threads überschreiten können =)
Schauen wir uns nun ausführlich einen Namespace an (ich habe den Namespace kube-system gewählt – den System-Namespace für die Komponenten von Kubernetes) und vergleichen wir die tatsächlich genutzte CPU-Zeit und den Speicher mit dem Angeforderten:

Offensichtlich ist der Speicher und die CPU, die für die Systemdienste reserviert sind, deutlich höher als tatsächlich genutzt wird. Im Fall von kube-system ist dies gerechtfertigt: Es gab Zeiten, in denen der NGINX Ingress Controller oder node-local-dns zu Spitzenzeiten die CPU-Auslastung erreicht haben und sehr viel RAM verbraucht wurde, daher ist hier ein solcher Puffer sinnvoll. Zudem können wir uns nicht nur auf die Grafiken der letzten 3 Stunden verlassen: Es wäre wünschenswert, historische Metriken über einen längeren Zeitraum zu sehen.
Ein System von „Empfehlungen“ wurde entwickelt. Hier kann man zum Beispiel sehen, welche Ressourcen es besser wäre, um die „Limits“ (oberste zulässige Grenze) zu erhöhen, um „Throttling“ zu vermeiden: den Moment, in dem die CPU oder der Speicher bereits für den zugewiesenen Zeitquantums aufgebraucht wurden und darauf wartet, bis sie „aufgetaut“ werden:

Hier sind die Pods, bei denen eine Drosselung angebracht wäre:

Über Drosselung + Über das Monitoring von Ressourcen ließen sich zahlreiche Artikel schreiben, fragen Sie also gerne in den Kommentaren. Kurz gesagt, die Automatisierung solcher Metriken ist eine anspruchsvolle Aufgabe, die viel Zeit und Geschick mit „Window“-Funktionen und „CTE“ in Prometheus / VictoriaMetrics erfordert (diese Begriffe habe ich in Anführungszeichen gesetzt, da es in PromQL kaum Vergleichbares gibt, und man gezwungen ist, komplexe Abfragen von mehreren Bildschirmen Text zu kreieren und diese zu optimieren).
Letztendlich verfügen die Entwickler über Werkzeuge zur Überwachung ihrer Namespaces im „Kubernetes“, und sie können selbst entscheiden, wo und wann in welchen Anwendungen Ressourcen „reduziert“ werden können, während andere Pods die gesamte CPU über Nacht erhalten können.
Methodologien
In unserem Unternehmen, wie es gerade angesagt ist, halten wir uns an DevOps- undSRE -Praktiken. Bei 1000 Mikrodiensten, etwa 350 Entwicklern und 15 Admins für die gesamte Infrastruktur wird es notwendig, „modisch“ zu sein: hinter all diesen „Buzzwords“ steckt ein dringender Bedarf an Automatisierung aller Prozesse, und die Admins dürfen nicht das Engpassproblem im Ablauf sein.-praktisch. Wenn es in einem Unternehmen 1000 Mikrodienste, etwa 350 Entwickler und 15 Administratoren für die gesamte Infrastruktur gibt, muss man "trendy" sein: hinter all diesen "Buzzwords" verbirgt sich ein akuter Bedarf an Automatisierung von allem und jedem, und die Administratoren dürfen kein Flaschenhals in den Prozessen sein.
Als Ops bieten wir verschiedene Metriken und Dashboards für Entwickler an, die mit der Antwortgeschwindigkeit der Dienste und deren Fehlern zusammenhängen.
Wir verwenden Methoden wie: , und , die wir miteinander kombinieren. Wir versuchen, die Anzahl der Dashboards zu minimieren, damit auf einen Blick klar ist, welcher Dienst derzeit eine Verschlechterung aufweist (zum Beispiel Antwortcodes pro Sekunde, Antwortzeiten im 99. Perzentil) usw. Sobald neue Metriken für allgemeine Dashboards benötigt werden, erstellen wir diese sofort und fügen sie hinzu.
Ich habe seit einem Monat keine Grafiken mehr erstellt. Das ist wahrscheinlich ein gutes Zeichen: Das heißt, dass die meisten „Wünsche“ bereits umgesetzt wurden. In der Vergangenheit kam es vor, dass ich in einer Woche mindestens einmal am Tag ein neues Diagramm erstellt habe.


Das Ergebnis ist wertvoll, da die Entwickler nun recht selten bei den Admins nachfragen, wo sie eine bestimmte Metrik einsehen können.
Implementierung Service Mesh Es ist nicht mehr weit und wird allen das Leben erheblich erleichtern. Die Kollegen aus dem Tools-Team stehen kurz vor der Implementierung des abstrakten „Istio des gesunden Menschen“: Der Lebenszyklus jeder HTTP(s)-Anforderung wird im Monitoring sichtbar sein, und man kann jederzeit nachvollziehen, „an welchem Punkt es schiefgelaufen ist“ beim internen (und nicht nur) Service-Austausch. Abonnieren Sie die Neuigkeiten des Unternehmens-Hubs DomKlik. =)
Unterstützung der Kubernetes-Infrastruktur
Historisch haben wir eine gepatchte Version verwendet Kubespray — eine Ansible-Rolle zum Bereitstellen, Erweitern und Aktualisieren von Kubernetes. Irgendwann wurde die Unterstützung für Non-kubeadm-Installationen aus dem Hauptzweig entfernt, und ein Übergangsprozess zu kubeadm wurde nicht angeboten. Infolgedessen hat das Unternehmen Southbridge einen eigenen Fork erstellt (mit Unterstützung für kubeadm und schneller Behebung kritischer Probleme).
Der Aktualisierungsprozess aller k8s-Cluster sieht so aus:
- Wir nehmen Kubespray von Southbridge, vergleichen mit unserem Branch und mergen.
- Wir rollen das Update in Stress-„Kube“.
- Wir führen das Update node für node (in Ansible „serial: 1“) durch in Dev-„Kube“.
- Aktualisieren Prod am Samstagabend node für node.
Für die Zukunft gibt es Pläne, Kubespray durch etwas Schnelleres zu ersetzen und zu kubeadm zu wechseln..
Wir haben insgesamt drei „Cubes“: Stress, Dev und Prod. Wir planen, noch einen weiteren (Hot Standby) Prod-Cube im zweiten Rechenzentrum zu starten. Stress und Dev Sie laufen in „Virtuellen Maschinen“ (oVirt für Stress und VMWare Cloud für Dev). Prod-Der Cube läuft auf „bare metal”: es sind identische Nodes mit 32 CPU-Threads, 64-128 GB RAM und 300 GB SSD RAID 10 – insgesamt 50 Stück. Drei „dünne“ Nodes sind für die „Master“ reserviert. Prod-Cubes: 16 GB RAM, 12 CPU-Threads.
Für den Prod-Bereich bevorzugen wir „bare metal“ und vermeiden zusätzliche Schichten wie OpenStack: wir wollen keine „lauten Nachbarn“ und CPU Steal Time. Außerdem erhöht sich die Komplexität der Verwaltung etwa um das Doppelte bei in-house OpenStack.
Für CI/CD der Cubes und anderer Infrastrukturkomponenten verwenden wir einen separaten GIT-Server, Helm 3 (der Umstieg von Helm 2 war recht schmerzhaft, aber wir freuen uns über die Option Atomic), Jenkins, Ansible und Docker. Wir lieben Feature-Branches und Deployments in verschiedene Umgebungen aus einem einzigen Repository.
Fazit

So sieht im Großen und Ganzen der DevOps-Prozess bei der Firma DomClick aus der Sicht eines Betriebstechnikers aus. Der Artikel ist weniger technisch geworden, als ich erwartet hatte: Halten Sie also die Augen offen für Neuigkeiten von DomClick auf Habré: Es werden „härtere“ Artikel zu Kubernetes und mehr kommen.
Quelle: habr.com
