Postgres-Dienstag Nr. 5: „PostgreSQL und Kubernetes. CI/CD. Automatisierung von Tests“

Postgres-Dienstag Nr. 5: „PostgreSQL und Kubernetes. CI/CD. Automatisierung von Tests“

Am Ende des vergangenen Jahres fand eine weitere Live-Sendung der russischen PostgreSQL-Community statt #RuPostgres, in deren Rahmen sein Mitgründer Nikolai Samokhvalov mit dem technischen Direktor von «Flant» Dmitriy Stolyarov über diese Datenbank in Bezug auf Kubernetes sprach.

Wir veröffentlichen das Protokoll des Hauptteils dieser Diskussion, und auf dem YouTube-Kanal der Community wurde die vollständige Videoaufzeichnung veröffentlicht:

Video abspielen

Datenbanken und Kubernetes

NS: Heute werden wir nicht über VACUUM und CHECKPOINTS sprechen. Wir möchten über Kubernetes reden. Ich weiß, dass du schon viele Jahre Erfahrung hast. Ich habe deine Videos angesehen und einige sogar in Ausschnitten erneut angeschaut… Lass uns gleich zur Sache kommen: Warum überhaupt Postgres oder MySQL in K8s?

DS: Auf diese Frage gibt es keine eindeutige Antwort und kann es nicht geben. Aber im Allgemeinen, das ist einfach und bequem… potenziell. Jeder möchte schließlich Managed-Services.

NS: Um wie ausgenutzt, und es gibt bereits einen Exploit-Prototypen. Wie genau diese Informationen sind, ist bisher unklar; möglicherweise sind im Bericht lediglich die Annahmen der NVD künstlerisch aufbereitet. Nach, nur bei sich selbst?

DS: Ja: um wie RDS, nur überall.

NS: „Überall“ — das ist eine gute Anmerkung. In großen Unternehmen ist alles an verschiedenen Orten angesiedelt. Warum sollte man dann, wenn es sich um ein großes Unternehmen handelt, nicht eine fertige Lösung verwenden? Zum Beispiel hat Nutanix eigene Entwicklungen, andere Unternehmen (VMware…) haben das gleiche „RDS, nur bei sich“.

DS: Aber hier sprechen wir über eine spezifische Umsetzung, die nur unter bestimmten Bedingungen funktioniert. Wenn es um Kubernetes geht, gibt es hier eine riesige Vielfalt an Infrastruktur (die in K8s sein kann). Es ist im Grunde ein Standard für die API zur Cloud…

NS: Und das sogar kostenlos!

DS: Das ist nicht so wichtig. Kostenlosheit ist für einen nicht sehr großen Teil des Marktes nicht von großer Bedeutung. Wichtiger ist etwas anderes… Du erinnerst dich wahrscheinlich an den Vortrag „Datenbanken und Kubernetes»?

NS: Ja.

DS: Ich habe verstanden, dass er sehr unterschiedlich aufgenommen wurde. Teil der Leute dachten, dass ich sage: „Leute, lass uns alle Datenbanken in Kubernetes bringen!“, während andere dachten, dass das alles schreckliche Fahrräder sind. Ich wollte jedoch etwas ganz anderes sagen: „Schaut, was passiert, welche Probleme es gibt und wie man sie lösen kann. Sollte man jetzt Datenbanken in Kubernetes betreiben? In der Produktion? Nun, nur wenn ihr es liebt… euch mit bestimmten Dingen zu beschäftigen. Aber für die Entwicklung — ich kann sagen, dass ich empfehle. Für die Entwicklung ist die Dynamik der Erstellung/Entfernung von Umgebungen sehr wichtig.“

NS: Mit Entwicklung meinst du alle Umgebungen, die nicht prod sind? Staging, QA…

DS: Wenn wir von perf-Ständen sprechen, dann wahrscheinlich nicht, weil die Anforderungen dort spezifisch sind. Wenn wir von speziellen Fällen sprechen, in denen auf Staging eine sehr große DB benötigt wird, dann wahrscheinlich auch nicht... Wenn es sich um eine statische, langlebige Umgebung handelt, wo ist der Vorteil, wenn die Datenbank in K8s liegt?

NS: Keiner. Aber wo sehen wir statische Umgebungen? Statische Umgebungen sind morgen schon veraltet.

DS: Staging kann statisch sein. Wir haben Kunden…

NS: Ja, ich habe auch welche. Es ist ein großes Problem, wenn du eine Datenbank mit 10 TB hast und das Staging nur 200 GB beträgt…

DS: Ich habe einen sehr coolen Anwendungsfall! Auf Staging befindet sich die Produktionsdatenbank, in die Änderungen eingepflegt werden. Und es gibt einen Button: „In Produktion bringen“. Diese Änderungen – Deltas – werden (ich glaube, einfach über die API synchronisiert) in die Produktion übernommen. Das ist eine sehr exotische Variante.

NS: Ich habe Startups im Silicon Valley gesehen, die noch in RDS oder sogar in Heroku sind – das sind Geschichten von vor 2-3 Jahren – und sie laden sich das Dump auf ihren Laptop. Weil die Datenbank gerade einmal 80 GB groß ist und auf dem Laptop Platz ist. Dann kaufen sie jedem zusätzliche Festplatten, um 3 Datenbanken zu haben, um verschiedene Entwicklungen voranzutreiben. So kann es auch laufen. Ich habe auch gesehen, dass sie keine Scheu haben, Prod nach Staging zu kopieren – das hängt sehr stark vom Unternehmen ab. Aber ich habe auch gesehen, dass viele Angst haben und häufig Zeit und manpower fehlen. Aber bevor wir zu diesem Thema übergehen, möchte ich etwas über Kubernetes hören. Verstehe ich richtig, dass es in der Produktion momentan niemand hat?

DS: Wir haben kleine Datenbanken in der Produktion. Es geht um Volumen im Bereich von mehreren Dutzend Gigabyte und nicht kritischen Diensten, für die es zu mühsam war, Replikate zu erstellen (und es einfach auch keine Notwendigkeit dafür gab). Und vorausgesetzt, es gibt unter Kubernetes ein ordentliches Speichersystem. Diese Datenbank lief in einer virtuellen Maschine – bedingt in VMware, über einem SAN. Wir haben sie in PV verschoben und können sie jetzt von Maschine zu Maschine transferieren.

NS: Datenbanken dieser Größe, bis zu 100 GB, können auf guten Festplatten und bei gutem Netzwerk innerhalb von Minuten bereitgestellt werden, richtig? Eine Geschwindigkeit von 1 GB pro Sekunde ist schon keine Seltenheit mehr.

DS: Ja, für eine lineare Operation ist das kein Problem.

NS: Okay, an Prod müssen wir nur denken. Und wenn wir Kubernetes für nicht-prod-Umgebungen in Betracht ziehen – wie machen wir das? Ich sehe, dass Zalando einen Operatormacht, bei Crunchy entwickeln sie, es gibt noch andere Optionen. Und da istOnGres – das ist unser guter Freund Alvaro aus Spanien: sie machen im Grunde nicht nur einen Operator , sondern ein ganzes Distributionspaket (StackGresStackGres), in das neben Postgres auch ein Backup integriert werden soll, Proxy Envoy…

DS: Wozu ist Envoy gut? Genau für die Lastverteilung des Postgres-Traffics?

NS: Ja. Sie sehen es so: Wenn man eine Linux-Distribution und den Kernel betrachtet, dann ist der normale PostgreSQL der Kernel, und sie wollen eine Distribution erstellen, die cloudfreundlich ist und in Kubernetes läuft. Sie kombinieren Komponenten (Backups usw.) und optimieren sie, damit sie gut funktionieren.

DS: Sehr cool! Im Grunde ist das Software, um ein verwaltetes Postgres anzubieten.

NS: Linux-Distributionen haben ständig Probleme damit, wie man Treiber erstellt, damit die gesamte Hardware unterstützt wird. Ihr Ansatz ist, dass sie in Kubernetes arbeiten werden. Ich weiß, dass wir bei Zalando kürzlich eine Verbindung zu AWS gesehen haben, was nicht ideal ist. Es sollte nicht von einer bestimmten Infrastruktur abhängen — was wäre dann der Sinn?

DS: Ich weiß nicht, in welchem konkreten Fall Zalando sich zusammengeschlossen hat, aber in Kubernetes ist der Speicher derzeit so gestaltet, dass man keinen generischen Weg nutzen kann, um ein Disk-Backup zu erstellen. Vor kurzem wurde im Standard — in der neuesten Version, der CSI-Spezifikation, die Möglichkeit von Snapshots integriert, aber wo ist das implementiert? Ehrlich gesagt, alles ist noch so unausgereift… Wir versuchen CSI über AWS, GCE, Azure, vSphere, aber sobald man es zu benutzen beginnt, wird deutlich, dass es noch nicht bereit ist.

NS: Deshalb muss man manchmal auf die Infrastruktur angewiesen sein. Ich denke, wir befinden uns noch in einer frühen Phase — das ist ein Wachstumsproblem. Frage: Was würdest du Neulingen empfehlen, die PgSQL in K8s ausprobieren möchten? Welcher Operator vielleicht?

DS: Das Problem ist, dass Postgres für uns nur 3 % ausmacht. Wir haben eine sehr lange Liste an anderer Software in Kubernetes, ich will nicht alles auflisten. Zum Beispiel Elasticsearch. Es gibt viele Operatoren: Einige entwickeln sich aktiv, andere nicht. Wir haben unsere Anforderungen an den Operator festgelegt, die erfüllt sein müssen, damit wir ihn ernst nehmen. Ein Operator speziell für Kubernetes — nicht für „einen Operator, um etwas unter Amazon-Bedingungen zu tun“… Tatsächlich verwenden wir ziemlich massenhaft (= fast alle Kunden) einen einzigen Operator — für Redis (bald werden wir auch einen Artikel darüber veröffentlichen).

NS: Und für MySQL gibt es auch keinen? Ich weiß, dass Percona… da sie sich jetzt sowohl um MySQL als auch um MongoDB und Postgres kümmern, müssen sie irgendwie einen universellen Ansatz entwickeln: für alle Datenbanken und alle Cloud-Anbieter.

DS: Wir haben es nicht geschafft, die Operatoren für MySQL zu betrachten. Das ist im Moment nicht unser Hauptfokus. MySQL funktioniert einwandfrei im Standalone-Modus. Warum einen Operator, wenn man die DB einfach starten kann… Man kann einen Docker-Container mit PostgreSQL starten, oder man kann es einfach machen.

NS: Darüber gab es auch eine Frage. Ganz ohne Operator?

DS: Ja, in 100 % der Fälle läuft bei uns PostgreSQL ohne Operator. Bis jetzt so. Wir nutzen den Operator aktiv für Prometheus und für Redis. Wir haben geplant, einen Operator für Elasticsearch zu finden - der brennt am meisten, weil wir ihn in 100 % der Fälle in Kubernetes einsetzen möchten. Genauso wie wir auch möchten, dass MongoDB immer in Kubernetes installiert wird. Hier gibt es bestimmte Wünsche - es gibt das Gefühl, dass man in diesen Fällen etwas tun kann. Und bei Postgres haben wir uns noch nicht einmal umgesehen. Natürlich wissen wir von verschiedenen Möglichkeiten, aber faktisch haben wir Standalone.

DB für Tests in Kubernetes

NS: Lass uns zum Thema Testing übergehen. Wie man Änderungen in der Datenbank ausrollt - aus der Sicht von DevOps. Es gibt Mikrodienste, viele Datenbanken, ständig ändert sich irgendwo etwas. Wie stellt man ein ordentliches CI/CD sicher, damit aus Sicht der DB alles in Ordnung ist. Was ist dein Ansatz?

DS: Es kann nicht die eine Antwort geben. Es gibt mehrere Parameter. Erstens ist die Größe der Datenbank, die wir ausrollen möchten. Du hast selbst erwähnt, dass Unternehmen unterschiedlich damit umgehen, eine Kopie der Prod-Datenbank in dev und stage zu haben.

NS: Und unter den Bedingungen der GDPR, denke ich, gehen sie immer sorgfältiger damit um... Ich kann sagen, dass in Europa bereits mit Geldstrafen begonnen wurde.

DS: Aber oft kann man Software schreiben, die ein Dump von der Produktion erstellt und diesen obfuskiert. Es entstehen Produktionsdaten (Snapshot, Dump, binäre Kopie...), aber sie sind anonymisiert. Stattdessen kann es auch Generierungsskripte geben: das können Fixtures sein oder einfach ein Skript, das eine große Datenbank generiert. Das Problem besteht darin: Wie lange dauert es, das Basisimage zu erstellen? Und wie lange dauert es, es in der benötigten Umgebung bereitzustellen?

Wir sind zu dem Schema gekommen: Wenn der Kunde ein Fixture-Datensatz hat (minimale Version der Datenbank), verwenden wir diese standardmäßig. Wenn es um Review-Umgebungen geht, wenn wir einen Branch erstellt haben und eine Instanz der Anwendung ausgeführt wird - bringen wir eine kleine Datenbank dort ein. Aber das hat sich gut ergeben und Variante, wenn wir einmal täglich (nachts) ein Dump von der Produktion machen und darauf basierend einen Docker-Container mit PostgreSQL und MySQL mit diesen geladenen Daten erstellen. Wenn man diese Datenbank 50 Mal aus diesem Image bereitstellen muss, ist das relativ einfach und schnell.

NS: Einfaches Kopieren?

DS: Die Daten werden direkt im Docker-Image gespeichert. Das heißt, wir haben ein fertiges Image, sagen wir 100 GB groß. Dank der Schichten in Docker können wir dieses Image schnell die benötigte Anzahl von Malen bereitstellen. Die Methode ist einfach, funktioniert aber ganz gut.

NS: Und dann, wenn Sie testen, ändert es sich direkt innerhalb von Docker, oder? Copy-on-write innerhalb von Docker — wir verwerfen alles und fangen neu an, alles gut. Klasse! Und verwenden Sie das bereits umfassend?

DS: Schon lange.

NS: Wir beschäftigen uns mit sehr ähnlichen Dingen. Nur benutzen wir nicht das Docker-typische Copy-on-write, sondern etwas anderes.

DS: Es ist nicht allgemein. Das Docker-System funktioniert universell.

NS: Theoretisch, ja. Aber wir haben da auch Module, man kann verschiedene Module machen und mit verschiedenen Dateisystemen arbeiten. Hier ist der Punkt. Wir sehen das aus der Perspektive von Postgres bereits anders. Jetzt habe ich es aus der Perspektive von Docker gesehen und festgestellt, dass bei Ihnen alles funktioniert. Aber wenn die Datenbank riesig ist, beispielsweise 1 TB, dann wird das schon alles lange: sowohl die Operationen nachts als auch alles in Docker zu packen… Und wenn man 5 TB in Docker packen will… Oder ist das alles in Ordnung?

DS: Was macht das für einen Unterschied: das sind doch Blobs, einfach Bits und Bytes.

NS: Der Unterschied ist: machen Sie das über Dump und Restore?

DS: Ganz und gar nicht notwendig. Die Methoden zur Erstellung dieses Images können unterschiedlich sein.

NS: Für einige Kunden haben wir es so gemacht, dass wir den Basis-Image nicht regelmäßig erstellen, sondern ständig aktuell halten. Es ist im Grunde eine Replik, aber die Daten kommen nicht direkt vom Master, sondern über ein Archiv. Ein binäres Archiv, in das täglich die WALs geschrieben werden, dort werden auch Backups erstellt… Diese WALs kommen dann mit geringer Verzögerung (nur 1-2 Sekunden) zum Basis-Image. Von dort klonen wir auf jede erdenkliche Weise — derzeit verwenden wir standardmäßig ZFS.

DS: Aber mit ZFS sind Sie auf einen Knoten beschränkt.

NS: Ja. Aber ZFS hat noch etwas Zauberhaftes send: damit kann man einen Snapshot schicken und sogar (ich habe das noch nicht besonders getestet, aber…) man kann die Delta zwischen zwei nachsenden. PGDATA. Tatsächlich haben wir noch ein anderes Werkzeug, das wir für solche Aufgaben noch nicht großartig in Betracht gezogen haben. In PostgreSQL gibt es pg_rewind, der als „intelligenter“ rsync fungiert und vieles überspringt, was man sich nicht ansehen muss, weil sich daran definitiv nichts verändert hat. Wir können eine schnelle Synchronisierung zwischen zwei Servern durchführen und genau so zurückspulen.

Nun, wir versuchen, von dieser, etwas DBA-lastigen Seite, ein Tool zu schaffen, das genau das ermöglicht, worüber du gesprochen hast: Wir haben eine Datenbank, aber wir möchten 50 Mal etwas testen, fast gleichzeitig.

DS: 50 Mal bedeutet, dass ihr 50 Spot-Instanzen bestellen müsst.

NS: Nein, wir machen alles auf einer Maschine.

DS: Aber wie implementiert ihr das 50 Mal, wenn diese eine Datenbank, sagen wir, terabyte-groß ist? Wahrscheinlich benötigt sie bedingt 256 GB RAM?

NS: Ja, manchmal braucht man viel Speicher – das ist normal. Aber ein Beispiel aus dem Leben. Auf der Produktionsmaschine sind 96 Kerne und 600 GB. Dabei werden für die Datenbank 32 Kerne (manchmal sogar 16 Kerne heutzutage) und 100-120 GB Speicher verwendet.

DS: Passt da 50 Kopien hinein?

NS: Es ist ja eine Kopie, danach arbeitet das copy-on-write (ZFS)… Ich erzähle dir mehr darüber.

Wir haben beispielsweise eine Datenbank mit 10 TB. Die Festplatte dafür ist gemacht, ZFS hat ihre Größe um 30-40% komprimiert. Da wir keine Lasttests durchführen, ist uns die genaue Reaktionszeit nicht wichtig: es kann bis zu 2 Mal langsamer sein – das ist okay.

Wir geben Programmierern, QA, DBA usw. die Möglichkeit, Tests in 1-2 Threads durchzuführen. Zum Beispiel können sie eine Art Migration starten. Diese benötigt nicht sofort 10 Kerne – sie braucht 1 Backend von Postgres, 1 Kern. Die Migration startet – vielleicht, autovacuum wird sie noch eine starten, dann wird der zweite Kern aktiviert. Uns stehen 16-32 Kerne zur Verfügung, sodass 10 Personen gleichzeitig arbeiten können, es gibt keine Probleme.

Da physisch PGDATA identisch ist, ergibt sich, dass wir Postgres tatsächlich überlisten. Der Trick ist der: Zum Beispiel werden 10 Postgres-Funktionen gleichzeitig gestartet. Was ist normalerweise das Problem? Sie setzen shared_buffers, sagen wir, auf 25%. Das sind entsprechend 200 GB. Mehr als drei solcher Instanzen kann man nicht starten, da der Speicher ausgeht.

Aber irgendwann haben wir realisiert, dass das nicht nötig ist: Wir setzen shared_buffers auf 2 GB. PostgreSQL hat effective_cache_size, und in der Realität beeinflusst nur er die Pläne. Den setzen wir auf 0,5 TB. Und es ist nicht einmal wichtig, dass es sie tatsächlich nicht gibt: Er erstellt Pläne, als ob es sie gibt.

Dementsprechend können wir, wenn wir eine Migration testen, alle Pläne zusammenfassen – wir werden sehen, wie es in der Produktion ablaufen wird. Die Zeitangaben werden anders sein (langsamer), aber die Daten, die wir tatsächlich ablesen, und die Pläne selbst (welche JOINs und so weiter) werden genau so sein wie in der Produktion. Gleichzeitig können wir viele solcher Überprüfungen auf einem einzigen Rechner durchführen.

DS: Denkst du nicht, dass es hier mehrere Probleme gibt? Erstens – das ist eine Lösung, die nur mit PostgreSQL funktioniert. Ein solcher Ansatz ist sehr speziell, nicht allgemein. Zweitens – Kubernetes (und alles, wohin die Cloud-Technologien jetzt gehen) bedeutet viele Knoten, und diese Knoten sind flüchtig. In deinem Fall ist das jedoch ein stateful, persistenter Knoten. Diese Dinge werfen bei mir Widersprüche auf.

NS: Zunächst – ich stimme zu, das ist rein Postgres-spezifisch. Ich denke, wenn wir irgendeinen direktem IO und einen Pufferpool hätten, der fast den gesamten Speicher nutzt, wäre dieser Ansatz nicht geeignet – die Pläne wären anders. Aber derzeit arbeiten wir nur mit Postgres und denken nicht über andere nach.

Über Kubernetes. Du erzählst doch überall, dass unsere Datenbank persistent ist. Wenn eine Instanz ausfällt, ist das Wichtigste, die Festplatte zu sichern. Auch unsere gesamte Plattform läuft in Kubernetes, und die Komponente mit Postgres ist separat (obwohl sie dort eines Tages sein wird). Daher ist es so: Die Instanz ist ausgefallen, aber wir haben ihr PV gesichert und einfach an eine andere (neue) Instanz angeschlossen, als wäre nichts passiert.

DS: Aus meiner Sicht erstellen wir Pods in Kubernetes. K8s ist elastisch: Knoten werden nach Bedarf bestellt. Die Aufgabe ist einfach, einen Pod zu erstellen und anzugeben, dass er X Ressourcen benötigt, und dann kümmert sich K8s selbst darum. Aber die Unterstützung von Speicher in Kubernetes ist nach wie vor instabil: in 1.16, in 1.17 (dieses Release wurde vor Wochen veröffentlicht) sind diese Funktionen nur Beta.

In sechs Monaten bis zu einem Jahr wird es mehr oder weniger stabil sein oder zumindest als solches erklärt werden. Dann löst die Möglichkeit von Snapshots und Resizing eure Aufgabe vollständig. Denn ihr habt eine Datenbank. Ja, sie ist möglicherweise nicht sehr schnell, aber die Geschwindigkeit hängt davon ab, was „unter der Haube“ ist, denn einige Implementierungen unterstützen das Kopieren und Copy-on-Write auf Ebene des Speichersystems.

NS: Hier ist es auch wichtig, dass alle Engines (Amazon, Google…) diese Version unterstützen - das dauert auch eine gewisse Zeit.

DS: Momentan verwenden wir sie nicht. Wir verwenden unser eigenes.

Lokale Entwicklung unter Kubernetes

NS: Hast du schon einmal mit der Situation zu tun gehabt, in der du auf einem einzigen Rechner alle Pods hochfahren und ein kleines Testverfahren durchführen musstest? Um schnell einen Proof of Concept zu erhalten und zu sehen, ob die Anwendung in Kubernetes funktioniert, ohne dafür eine Menge Maschinen bereitzustellen. Es gibt Minikube, oder?

DS: Ich denke, dieser Fall – auf einem Knoten zu deployen – bezieht sich ausschließlich auf lokale Entwicklung. Oder auf einige Manifestationen dieses Musters. Es gibt Minikube, es gibt k3s, KIND. Wir gehen dahin, dass wir Kubernetes IN Docker verwenden werden. Wir haben jetzt angefangen, damit für Tests zu arbeiten.

NS: Früher dachte ich, dass es der Versuch sei, alle Pods in ein Docker-Image zu packen. Aber es stellte sich heraus, dass es um etwas ganz anderes geht. Dort sind immer noch separate Container, separate Pods – einfach in Docker.

DS: Ja. Und dort gibt es eine ziemlich amüsante Simulation, aber der Sinn ist folgender… Wir haben ein Tool für das Deployment – werf. Wir wollen darin einen Modus einrichten – bedingt werf up: „Erstelle mir ein lokales Kubernetes“. Und anschließend soll dort ein bedingtes werf follow. Dann kann der Entwickler in der IDE arbeiten, während im System ein Prozess läuft, der die Änderungen sieht, die Images neu baut und sie in das lokale K8s deployt. So wollen wir versuchen, das Problem der lokalen Entwicklung zu lösen.

Snapshots und Klonen von Datenbanken in K8s

NS: Wenn wir zu Copy-on-Write zurückkehren. Ich habe bemerkt, dass auch die Cloud Anbieter Snapshots haben. Die funktionieren unterschiedlich. Zum Beispiel, im GCP: Du hast an der Ostküste der USA eine Multi-Terabyte-Instanz. Du machst regelmäßig Snapshots. Du hebst aus einem Snapshot eine Kopie des Datenträgers an der Westküste hoch – nach wenigen Minuten ist alles bereit, es funktioniert sehr schnell, nur der Cache muss im Speicher gefüllt werden. Aber diese Klone (Snapshots) sind dazu da, um ein neues Volume bereitzustellen. Das ist großartig, wenn du viele Instanzen erstellen musst.

Aber für Tests, denke ich, ermöglichen die Snapshots, von denen du sprichst, in Docker oder die, über die ich in ZFS, btrfs und sogar LVM spreche… – sie ermöglichen es genau, auf einem Computer keine echten neuen Daten zu erstellen. In der Cloud wirst du auch jedes Mal dafür bezahlen müssen und wirst nicht Sekunden, sondern Minuten warten (und im Fall des Lazy Loads, möglicherweise sogar Stunden).

Anstattdessen kannst du diese Daten in ein paar Sekunden erhalten, den Test durchführen und sie verwerfen. Diese Snapshots lösen unterschiedliche Probleme. Im ersten Fall – um zu skalieren und neue Replikate zu erhalten, und im zweiten – für Tests.

DS: Ich stimme nicht zu. Eine ordnungsgemäße Klonung von Volumes ist eine Aufgabe der Cloud. Ich habe ihre Implementierung nicht gesehen, weiß aber, wie wir das auf Hardware machen. Wir haben Ceph, dort kann man jedem physischen Volume (RBD) sagen clone und innerhalb von wenigen Dutzend Millisekunden das zweite Volume mit denselben Eigenschaften, IOPSusw. erhalten. Man muss verstehen, dass dort innen ein cleveres Copy-on-Write ist. Warum sollte die Cloud das nicht auch so machen? Ich bin mir sicher, dass sie sich bemühen, es zu realisieren.

NS: Aber sie benötigen trotzdem Sekunden, sogar Dutzende von Sekunden, um eine Instanz hochzufahren, Docker zu installieren usw.

DS: Warum muss man unbedingt eine ganze Instanz hochfahren? Wir haben doch eine Instanz mit 32 Kernen, mit 16... und in diese passen ein paar hinein – beispielsweise vier. Wenn wir die fünfte anfordern, wird bereits eine Instanz hochgefahren, und danach wird sie wieder gelöscht.

NS: Ja, interessant, in Kubernetes sieht das anders aus. Bei uns ist die DB nicht in K8s, und es gibt nur eine Instanz. Aber die Klonung einer Multi-Terabyte-Datenbank dauert nicht länger als zwei Sekunden.

DS: Das ist cool. Aber mein ursprünglicher Punkt ist, dass das keine generische Lösung ist. Ja, sie ist klasse, aber funktioniert nur mit Postgres und nur auf einem Knoten.

NS: Sie ist nicht nur für Postgres geeignet: Diese Pläne, wie ich beschrieben habe, werden nur dort so funktionieren. Aber wenn man sich nicht um die Pläne kümmert und einfach alle Daten für Funktionstests benötigt, dann ist das für jede DBMS geeignet.

DS: Vor vielen Jahren haben wir etwas Ähnliches mit LVM-Snapshots gemacht. Das ist klassisch. Dieser Ansatz wurde sehr aktiv verwendet. Stateful-Knoten sind jedoch ein Schmerz. Denn man darf sie nicht fallen lassen und muss immer an sie denken...

NS: Siehst du hier nicht eine Möglichkeit für einen Hybrid? Angenommen, stateful ist ein Pod, der von mehreren Personen (viele Tester) genutzt wird. Wir haben nur ein Volume, aber dank des Dateisystems sind die Klone lokal. Wenn der Pod ausfällt, bleibt die Disk erhalten – der Pod wird wieder hochgefahren, liest die Informationen über alle Klone und stellt alles wieder her und sagt: „Hier sind eure Klone auf diesen Ports, arbeitet weiter mit ihnen.“

DS: Technisch bedeutet das, dass es in Kubernetes ein Pod ist, in dem wir viele Postgres-Instanzen starten.

NS: Ja. Er hat ein Limit: Angenommen, gleichzeitig arbeiten nicht mehr als 10 Personen damit. Wenn 20 benötigt werden – starten wir einen zweiten solchen Pod. Es ist vollkommen möglich, ihn zu klonen und ein zweites vollständiges Volume zu erhalten, auf dem dieselben 10 „dünnen“ Klone sein werden. Siehst du da nicht eine Möglichkeit?

DS: Hier müssen Sicherheitsfragen hinzugefügt werden. Diese Art der Organisation impliziert, dass dieses Pod hohe Privilegien (Capabilities) hat, da es nicht-standardisierte Operationen im Dateisystem ausführen kann... Aber ich wiederhole: Ich bin der Meinung, dass Kubernetes in der mittelfristigen Perspektive den Storage reparieren wird, in Cloud-Umgebungen wird die gesamte Geschichte mit Volumes behoben — alles wird „einfach funktionieren“. Es wird Resize, Klonen geben... Es gibt ein Volume — wir sagen: „Erstelle ein neues basierend auf diesem“, und nach anderthalb Sekunden haben wir, was wir brauchen.

NS: Ich glaube nicht an anderthalb Sekunden für mehrere Terabyte. Mit Ceph machst du es selbst, während du von Clouds sprichst. Geh in die Cloud, mache auf EC2 ein Klon eines EBS-Volumes mit vielen Terabyte und schau dir die Leistung an. Das wird nicht einige Sekunden dauern. Ich bin wirklich gespannt, wann sie zu solch einem Wert kommen. Ich verstehe, wovon du sprichst, aber ich erlaube mir, nicht zuzustimmen.

DS: Okay, aber ich habe gesagt, dass ich von einer mittelfristigen Perspektive spreche, nicht von einer kurzfristigen. In ein paar Jahren.

Über den PostgreSQL-Operator von Zalando

Mitte dieses Treffens kam auch Alexey Kлюкин, ein ehemaliger Entwickler von Zalando, dazu, der über die Geschichte des PostgreSQL-Operators sprach:

Es ist großartig, dass dieses Thema überhaupt angesprochen wird: sowohl Postgres als auch Kubernetes. Als wir 2017 bei Zalando anfingen, daran zu arbeiten, war das ein Thema, mit dem alle sich beschäftigen wollten, aber niemand machte es. Jeder hatte bereits Kubernetes, aber als gefragt wurde, wie man mit Datenbanken umgeht, sagten sogar solche Leute wie Kelsey Hightower, die K8s propagierten, etwa Folgendes:

„Geht zu Managed-Services und nutzt sie, startet keine Datenbanken in Kubernetes. Sonst kann euer K8s zum Beispiel beschließen, ein Upgrade durchzuführen, alle Knoten herunterfahren und eure Daten sind weit weg.“

Wir beschlossen, einen Operator zu erstellen, der entgegen diesem Rat PostgreSQL-Datenbanken in Kubernetes starten würde. Und wir hatten eine gute Grundlage — Patroni. Das ist ein automatischer Failover für PostgreSQL, der richtig umgesetzt ist, d.h. er nutzt etcd, Consul oder ZooKeeper als Speicher für Informationen über das Cluster. Ein solches Speicher, das allen, die fragen, dieselbe Information gibt, z.B. wer gerade der Leader ist — obwohl wir alles verteilt haben — um ein Split Brain zu verhindern. Außerdem hatten wir Docker-Image nachdenken.

Das Bedürfnis nach Auto-Failover entstand im Unternehmen nach der Migration vom internen Rechenzentrum in die Cloud. Die Cloud basierte auf einer eigenen PaaS-Lösung (Platform-as-a-Service). Sie ist Open Source, aber um sie aufzubauen, musste man viel Arbeit investieren. Es wurde genannt STUPS.

Ursprünglich gab es kein Kubernetes. Genauer gesagt, als die eigene Lösung bereitgestellt wurde, war K8s bereits vorhanden, aber so unvollständig, dass es nicht für die Produktion geeignet war. Das war, glaube ich, im Jahr 2015 oder 2016. Bis 2017 hatte Kubernetes einen gewissen Reifegrad erreicht — es gab den Bedarf, dorthin zu migrieren.

Und wir hatten bereits einen Docker-Container. Es gab eine PaaS, die Docker verwendete. Warum also nicht K8s ausprobieren? Warum nicht einen eigenen Operator schreiben? Murat Kabilov, der von Avito zu uns kam, begann dies als Projekt aus eigener Initiative — „ein bisschen zu experimentieren“ — und das Projekt „startete durch“.

Aber eigentlich wollte ich über AWS sprechen. Warum gab es historisch gesehen Code, der mit AWS verbunden war…

Wenn Sie etwas in Kubernetes starten, müssen Sie verstehen, dass K8s ein Work in Progress ist. Es entwickelt sich ständig weiter, verbessert sich und fällt manchmal sogar auseinander. Man muss die Veränderungen in Kubernetes genau im Auge behalten und bereit sein, im Falle eines Problems tiefer einzutauchen und zu verstehen, wie es im Detail funktioniert — möglicherweise mehr, als einem lieb ist. Das gilt grundsätzlich für jede Plattform, auf der Sie Ihre Datenbanken starten…

Also, als wir den Operator entwickelten, hatten wir Postgres, das mit einem externen Volume (in diesem Fall EBS, da wir in AWS arbeiteten) arbeitete. Die Datenbank wuchs, und irgendwann war es notwendig, eine Größenänderung vorzunehmen: Zum Beispiel betrug die ursprüngliche Größe von EBS 100 TB, die Datenbank war gewachsen, nun wollten wir EBS auf 200 TB erhöhen. Wie? Angenommen, man könnte einen Dump/Restore auf eine neue Instanz machen, aber das ist zeitaufwändig und mit Ausfallzeiten verbunden.

Deshalb wollten wir eine Größenänderung, die die Partition von EBS vergrößert und dann dem Dateisystem sagt, dass es den neuen Speicherplatz verwenden soll. Und das haben wir gemacht, aber zu dieser Zeit hatte Kubernetes keine API für die Größenänderung. Da wir bei AWS arbeiteten, schrieben wir Code für dessen API.

Niemand hindert Sie daran, dasselbe für andere Plattformen zu tun. Der Operator hat keine Bindung, die besagt, dass er nur auf AWS gestartet werden kann, und auf allem anderen nicht funktionieren wird. Insgesamt ist das ein Open Source-Projekt: Wenn jemand die Verwendung der neuen API beschleunigen möchte — herzlich willkommen. Es gibt GitHub, Pull-Requests – das Zalando-Team reagiert darauf ziemlich schnell und fördert den Operator. Soweit ich weiß, hat das Projekt teilgenommen an Google Summer of Code und anderen ähnlichen Initiativen. Zalando arbeitet sehr aktiv daran.

P.S. Bonus!

Wenn Sie sich für das Thema PostgreSQL und Kubernetes interessieren, beachten Sie bitte auch, dass letzte Woche der nächste Postgres-Dienstag stattfand, bei dem Nikolai mit Alexander Kukushkin von Zalando sprach.Das Video davon ist verfügbar hier.

P.P.S.

Lesen Sie auch in unserem Blog:

Quelle: habr.com

Zuverlässiges Hosting für Websites mit DDoS-Schutz kaufen, VPS VDS Server 🔥 Zuverlässiges Hosting für Websites mit DDoS-Schutz kaufen, VPS VDS Server - ProHoster