Wir erstellen eine Kubernetes-Plattform bei Pinterest

Im Laufe der Jahre hat Pinterest 300 Millionen Nutzer, die über 200 Milliarden Pins auf mehr als 4 Milliarden Pinnwänden erstellt haben. Um diesen enormen Nutzerstamm und das umfangreiche Content-Portfolio zu unterstützen, hat die Plattform Tausende von Diensten entwickelt. Diese reichen von Mikroservices, die mit wenigen CPUs auskommen, bis hin zu riesigen Monolithen, die auf einem ganzen Park virtueller Maschinen laufen. Und dann kam der Moment, als das Unternehmen den Blick auf Kubernetes richtete. Was hat es „Pinterest“ an diesem „Kuben“ gereizt? Dies erfahren Sie in unserem Artikel aus der Pinterest Engineering-Blog.

Wir erstellen eine Kubernetes-Plattform bei Pinterest

Also, Hunderte Millionen Nutzer und Hunderte von Milliarden Pins. Um diese Nutzergemeinschaft und das umfangreiche Content-Portfolio zu bedienen, haben wir Tausende von Diensten entwickelt, von Mikroservices, die mit wenigen CPUs auskommen, bis hin zu großen Monolithen, die auf einem umfangreichen Park virtueller Maschinen betrieben werden. Darüber hinaus nutzen wir verschiedene Frameworks, die ebenfalls CPU, Speicher oder Zugriff auf Ein- und Ausgabeoperationen erfordern können.

Bei der Unterstützung dieses Tool-Zoos sieht sich das Entwicklungsteam mit einer Reihe von Herausforderungen konfrontiert:

  • Die Ingenieure haben keinen einheitlichen Ansatz zur Bereitstellung von Arbeitsumgebungen. Stateless-Dienste, Stateful-Dienste und in aktiver Entwicklung befindliche Projekte basieren auf völlig unterschiedlichen Technologiestacks. Dies hat zur Erstellung eines umfassenden Schulungskurses für Ingenieure geführt und erschwert die Arbeit unseres Infrastrukturteams erheblich.
  • Entwickler, die über einen eigenen Pool von virtuellen Maschinen verfügen, setzen die internen Administratoren stark unter Druck. So werden selbst einfache Aufgaben wie das Aktualisieren des Betriebssystems oder der AMI über Wochen und Monate hinausgezogen. Dies führt zu einer erhöhten Belastung in scheinbar alltäglichen Situationen.
  • Herausforderungen bei der Schaffung globaler Infrastrukturmanagement-Tools über bereits bestehende Lösungen hinweg. Die Situation wird zusätzlich kompliziert, da es schwierig ist, die Eigentümer der virtuellen Maschinen zu identifizieren. Das bedeutet, dass wir nicht wissen, ob es sicher ist, diese Ressourcen für andere Bereiche unserer Infrastruktur abzuziehen.

Container-Orchestrierungssysteme bieten eine einheitliche Methode zur Verwaltung von Arbeitslasten. Sie ermöglichen es Ihnen, die Entwicklungszeit zu verkürzen und erleichtern die Verwaltung der Infrastruktur, da alle für das Projekt benötigten Ressourcen von einem zentralen System gesteuert werden.

Wir erstellen eine Kubernetes-Plattform bei Pinterest

Abbildung 1: Infrastrukturprioritäten (Zuverlässigkeit, Entwicklergeschwindigkeit und Effizienz).

Das Cloud Management Platform-Team von Pinterest kam 2017 mit K8s in Kontakt. Bis zur ersten Hälfte von 2017 hatten wir den Großteil unserer Produktionsumgebungen dokumentiert, einschließlich der API und aller unserer Webserver. Danach führten wir eine gründliche Bewertung verschiedener Container-Orchestrierungssysteme, Clusteraufbau und deren Betrieb durch. Ende 2017 entschieden wir uns für Kubernetes, da es ausreichend flexibel war und breit in der Entwicklergemeinde unterstützt wurde.

Bis heute haben wir unsere eigenen Tools für die primäre Cluster-Bereitstellung auf Basis von Kops entwickelt und bestehende Infrastrukturkomponenten wie Netzwerke, Sicherheit, Monitoring, Logging, Identitätsmanagement und Traffic in Kubernetes überführt. Zudem haben wir ein System zur Modellierung von Arbeitslasten für unsere Ressourcen implementiert, dessen Komplexität für die Entwickler verborgen bleibt. Aktuell konzentrieren wir uns auf die Stabilität des Clusters, dessen Skalierung und die Anbindung neuer Kunden.

Kubernetes: der Weg von Pinterest

Die Einführung von Kubernetes in der Skalierung von Pinterest als Plattform, die bei unseren Ingenieuren beliebt sein soll, brachte zahlreiche Herausforderungen mit sich.

Als großes Unternehmen haben wir erhebliche Mittel in infrastrukturelle Werkzeuge investiert. Beispielsweise verfügen wir über Sicherheitsinstrumente, die Zertifikate verarbeiten und Schlüssel verteilen, Komponenten für die Verkehrsüberwachung, Systeme zur Erkennung von Diensten sowie Elemente zur Sichtbarkeit und zum Senden von Protokollen und Metriken. All dies wurde nicht ohne Grund zusammengestellt: Wir haben einen normalen Prozess von Versuch und Irrtum durchlaufen und wollten daher all diese Ressourcen in eine neue Infrastruktur auf Kubernetes integrieren, anstatt das alte Rad auf einer neuen Plattform neu zu erfinden. Dieser Ansatz hat die Migration insgesamt vereinfacht, da die gesamte Anwendungsunterstützung bereits vorhanden ist und nicht von Grund auf neu geschaffen werden muss.

Andererseits sind die Prognosemodelle für Lasten im Kubernetes (zum Beispiel Bereitstellungen, Jobs und Daemon-Sets) für unser Projekt unzureichend. Diese Usability-Probleme stellen ein enormes Hindernis für den Wechsel zu Kubernetes dar. Wir haben beispielsweise gehört, wie Entwickler von Diensten sich über fehlende oder falsche Einstellungen des Zugangs beschweren. Außerdem haben wir uns mit einer fehlerhaften Nutzung von Templates konfrontiert gesehen, bei der Hunderte von Kopien mit identischer Spezifikation und Aufgabe erstellt wurden, was zu schrecklichen Debugging-Problemen führte.

Es war auch sehr schwierig, verschiedene Versionen im selben Cluster zu unterstützen. Stellen Sie sich die Komplexität des Kundensupports vor, wenn Sie gleichzeitig mit mehreren Versionen derselben Laufzeitumgebung arbeiten müssen, einschließlich aller ihrer Probleme, Bugs und Updates.

Benutzerdefinierte Ressourcen und Controller von Pinterest

Um unseren Ingenieuren den Einstieg in Kubernetes zu erleichtern und die Infrastruktur zu vereinfachen und deren Leistung zu steigern, haben wir unsere eigenen Definitionen für benutzerdefinierte Ressourcen (CRD) entwickelt.

CRD bieten folgende Funktionalitäten an:

  1. Integration verschiedener nativer Kubernetes-Ressourcen, damit sie als eine einzige Last funktionieren. Beispielsweise umfasst die Ressource PinterestService das Deployment, den Login-Dienst und die Config-Map. Dadurch brauchen sich Entwickler keine Gedanken über die DNS-Konfiguration zu machen.
  2. Implementierung der nötigen Anwendungsunterstützung. Der Benutzer sollte sich ausschließlich auf die Container-Spezifikation gemäß seiner Geschäftslogik konzentrieren, während der CRD-Controller alle notwendigen Init-Container, Umgebungsvariablen und Pod-Spezifikationen implementiert. Dies bietet Entwicklern ein völlig neues Maß an Komfort.
  3. CRD-Controller verwalten auch den Lebenszyklus eigener Ressourcen und verbessern die Verfügbarkeit von Debugging. Dazu gehört die Abstimmung zwischen gewünschten und tatsächlichen Spezifikationen, die Aktualisierung des CRD-Status und das Führen von Ereignisprotokollen und mehr. Ohne CRD wären Entwickler gezwungen, eine Vielzahl von Ressourcen zu verwalten, was die Fehleranfälligkeit erhöhen würde.

Hier ist ein Beispiel für PinterestService und eine interne Ressource, die von unserem Controller verwaltet wird:

Wir erstellen eine Kubernetes-Plattform bei Pinterest

Wie oben erwähnt, müssen wir für die Unterstützung eines benutzerdefinierten Containers diesen mit einem Initialisierungscontainer und mehreren Erweiterungen integrieren, um Sicherheit, Sichtbarkeit und Interaktion mit dem Netzwerkverkehr zu gewährleisten. Zudem haben wir Konfigurationskartenvorlagen erstellt und die Unterstützung für PVC-Vorlagen für Batch-Jobs implementiert sowie die Verfolgung mehrerer Umgebungsvariablen zur Identifikation, Ressourcennutzung und Aufzeichnung von „Müll“ realisiert.

Es ist schwer vorstellbar, dass Entwickler diese Konfigurationsdateien manuell ohne Unterstützung durch CRD schreiben möchten, ganz zu schweigen von der weiteren Unterstützung und Fehlersuche bei den Konfigurationen.

Workflow für die Bereitstellung von Anwendungen

Wir erstellen eine Kubernetes-Plattform bei Pinterest

Die obige Abbildung zeigt, wie man einen benutzerdefinierten Pinterest-Ressource in einem Kubernetes-Cluster bereitstellt:

  1. Entwickler interagieren mit unserem Kubernetes-Cluster über die CLI und die Benutzeroberfläche.
  2. Die CLI-/UI-Tools extrahieren YAML-Konfigurationsdateien des Workflows und andere Build-Eigenschaften (dasselbe Versionskennzeichen) aus Artifactory und senden sie dann an den Job Submission Service. Dieser Schritt stellt sicher, dass nur funktionierende Versionen in den Cluster geliefert werden.
  3. JSS dient als Gateway für verschiedene Plattformen, einschließlich Kubernetes. Hier erfolgt die Benutzeranmeldung, die Zuteilung von Quoten und eine partielle Überprüfung der Konfiguration unseres CRD.
  4. Nach der Prüfung des CRD auf Seiten von JSS wird die Information an die API der k8s-Plattform gesendet.
  5. Unser CRD-Controller überwacht Ereignisse aller Benutzerressourcen. Er wandelt die CR in native k8s-Ressourcen um, fügt notwendige Module hinzu, setzt entsprechende Umgebungsvariablen und führt andere unterstützende Aufgaben durch, wodurch er den Containeranwendungen der Benutzer eine ausreichende infrastrukturelle Unterstützung garantiert.
  6. Anschließend überträgt der CRD-Controller die erhaltenen Daten an die Kubernetes-API, damit diese vom Scheduler verarbeitet und in Betrieb genommen werden.

Hinweis: Dieses Pre-Release-Workflow für das Deployment wurde für die ersten Nutzer der neuen k8s-Plattform erstellt. Wir befinden uns derzeit in der Überarbeitung dieses Prozesses, um ihn vollständig mit unserem neuen CI/CD zu integrieren. Das bedeutet, dass wir noch nicht alles über Kubernetes mitteilen können. Wir freuen uns darauf, unsere Erfahrungen und den Fortschritt des Teams in dieser Hinsicht in unserem nächsten Blogbeitrag „Building a CI/CD platform for Pinterest“ zu teilen.

Arten von speziellen Ressourcen

Basierend auf den spezifischen Anforderungen von Pinterest haben wir die folgenden CRDs entwickelt, die für verschiedene Arbeitsabläufe geeignet sind:

  • PinterestService — das sind seit langem bestehende stateless-Services. Viele unserer Kernsysteme basieren auf einer Reihe solcher Services.
  • PinterestJobSet modelliert Batch-Jobs im vollständigen Zyklus. In Pinterest gibt es ein verbreitetes Szenario, bei dem mehrere Jobs dieselben Container parallel starten, unabhängig von anderen ähnlichen Prozessen.
  • PinterestCronJob wird häufig in Kombination mit kleinen, regelmäßigen Lasten eingesetzt. Es handelt sich um eine Shell für die native Cron-Integration mit Mechanismen zur Unterstützung von Pinterest, die für Sicherheit, Traffic, Protokolle und Metriken verantwortlich sind.
  • PinterestDaemon umfasst die Daemons der Infrastruktur. Diese Familie wächst weiter, da wir zunehmend Unterstützung für unsere Cluster hinzufügen.
  • PinterestTrainingJob bezieht sich auf Tensorflow- und Pytorch-Prozesse und bietet während des Betriebs das gleiche Unterstützungsniveau wie alle anderen CRDs. Da Tensorflow und andere Maschinenlernsysteme aktiv bei Pinterest eingesetzt werden, hatten wir guten Grund, um sie herum ein separates CRD zu entwickeln.

Außerdem arbeiten wir an PinterestStatefulSet, das bald für Datenspeicher und andere zustandsbehaftete Systeme angepasst werden wird.

Unterstützung der Laufzeitumgebung

Wenn ein Anwendungsmodul in Kubernetes gestartet wird, erhält es automatisch ein Zertifikat zur Identifikation. Dieses Zertifikat wird verwendet, um auf den geheimen Speicher zuzugreifen oder um über mTLS mit anderen Diensten zu kommunizieren. In der Zwischenzeit laden der Container-Initializer und der Daemon alle erforderlichen Abhängigkeiten vor dem Start der Containeranwendung. Sobald alles bereit ist, registrieren der Sidecar-Traffic und der Daemon die IP-Adresse des Moduls in unserem Zookeeper, damit die Kunden es finden können. All dies funktioniert, da das Netzwerkmodul bereits vor dem Start der Anwendung konfiguriert wurde.

Die obigen Beispiele zeigen typische Unterstützungsarten für Workloads zur Laufzeit. Für andere Arten von Workloads könnte etwas andere Unterstützung erforderlich sein, aber alle werden in Form von Pod-Level-Sidecars, Node-Level- oder Machine-Level-Daemons bereitgestellt. Wir stellen sicher, dass dies alles innerhalb der Verwaltungsinfrastruktur implementiert wird und zwischen den Anwendungen abgestimmt ist, was letztendlich die technische Arbeitsbelastung und den Support erheblich reduziert.

Testing und QA

Wir haben eine End-to-End-Testpipeline über die bereits vorhandene Testinfrastruktur von Kubernetes aufgebaut. Diese Tests gelten für alle unsere Cluster. Unsere Pipeline hat viele Anpassungen durchlaufen, bevor sie Teil des Produktclusters wurde.

Neben den Testsystemen verfügen wir über Überwachungs- und Benachrichtigungssysteme, die kontinuierlich den Zustand der Systemkomponenten, den Ressourcenverbrauch und andere wichtige Kennzahlen überwachen und uns nur dann benachrichtigen, wenn menschliches Eingreifen erforderlich ist.

Alternativen

Wir haben einige Alternativen zu benutzerdefinierten Ressourcen in Betracht gezogen, wie z. B. Mutations-Policy-Controller und Template-Systeme. Alle waren jedoch mit erheblichen Herausforderungen verbunden, sodass wir uns für den Weg der benutzerdefinierten Ressourcen-Definition (CRD) entschieden haben.

Der Mutations-Policy-Controller wurde verwendet, um Sidecars, Umgebungsvariablen und andere Unterstützungen während der Ausführung einzuführen. Er hatte jedoch mit verschiedenen Problemen zu kämpfen, beispielsweise mit der Bindung von Ressourcen und der Verwaltung ihres Lebenszyklus, während solche Probleme bei CRD nicht auftreten.

Hinweis: Vorlagensysteme wie Helm-Diagramme werden häufig verwendet, um Anwendungen mit ähnlichen Konfigurationen zu starten. Allerdings sind unsere Arbeitsanwendungen zu vielfältig, um sie mit Vorlagen zu verwalten. Zudem treten beim kontinuierlichen Deployment mit Vorlagen zu viele Fehler auf.

Zukünftige Arbeiten

Derzeit haben wir es mit einer gemischten Last auf all unseren Clustern zu tun. Um solche Prozesse unterschiedlicher Art und Größe zu unterstützen, arbeiten wir in folgenden Bereichen:

  • Ein Clusterverbund verteilt große Anwendungen auf verschiedene Cluster, um Skalierbarkeit und Stabilität zu gewährleisten.
  • Sicherstellung der Stabilität, Skalierbarkeit und Sichtbarkeit des Clusters zur Verbindung von Anwendung und SLA.
  • Ressourcen- und Quotenmanagement, damit sich die Anwendungen nicht gegenseitig behindern und die Skalierung des Clusters von unserer Seite kontrolliert wird.
  • Neue CI/CD-Plattform zur Unterstützung und Bereitstellung von Anwendungen in Kubernetes.

Quelle: habr.com

Kaufen Sie zuverlässiges Hosting für Websites mit DDoS-Schutz, VPS VDS-Server 🔥 Kaufen Sie zuverlässiges Hosting für Websites mit DDoS-Schutz, VPS VDS-Server | ProHoster