Zum Inhalt springen

Blog ·

Den VMID-Bereich für ein Hostinggeschäft wählen

Eine VMID ist eine Identität, kein Zähler. Was der Bereich entscheidet: was Ihre Plattform anlegen darf, was sie lesen darf und was beim Volllaufen passiert.

Von Provibr

Jede Proxmox-Installation beginnt bei 100 und zählt aufwärts. Das funktioniert gut, bis die Maschine aufhört, allein Ihnen zu gehören: bis ein Panel darauf Gäste anlegt, eine Kollegin darauf von Hand Gäste anlegt, eine Vorlagenbibliothek dazukommt und ein Backup-Auftrag um drei Uhr nachts etwas zurückspielt.

An diesem Punkt hört die VMID auf, ein Zähler zu sein, und wird zu einer Identität, und der Bereich, den Sie Ihrer Automatisierung übergeben, hört auf, eine Bequemlichkeit zu sein, und wird zu einer Grenze. Es lohnt sich, ihn bewusst zu wählen, denn zwei der drei Dinge, die ein Bereich entscheidet, sind unsichtbar, bis sie schiefgehen.

Was Proxmox tatsächlich erlaubt

Der volle Raum ist weiter, als die meisten annehmen:

Wert
Niedrigste VMID, die Proxmox akzeptiert100
Höchste VMID, die Proxmox akzeptiert999999999
Übliche manuelle Nutzung100 bis ein paar hundert

Neun Stellen. Das ist keine Einladung, sie alle zu benutzen, aber es heißt, dass die übliche Sorge, „gehen mir die Nummern aus“, die falsche Sorge ist. Ein schlecht gewählter Bereich ist lange vor den Nummern erschöpft.

Diese zwei Schranken sind die einzigen, die der Hypervisor durchsetzt. Alles andere, also der Teil, auf den es ankommt, ist Ihre Entscheidung.

Ein Bereich ist eine Rechtegrenze, bevor er ein Zuteiler ist

Hier ist der Teil, den man leicht übersieht. Wenn einer Plattform gesagt wird „zugeteilt wird von 5000 bis 8999“, sind ihr zwei Dinge auf einmal gesagt worden:

  1. Was sie anlegen darf. Neue Gäste bekommen eine Nummer aus diesem Fenster und aus keinem anderen.
  2. Was nicht ihr gehört. Alles außerhalb dieses Fensters hat jemand anders gemacht, und die Plattform hat dort nichts anzufassen.

Der zweite Punkt gehört an die Wand geschrieben. Als wir die Proxmox-Integration bauten, haben wir den VMID-Bereich in den Integrationseinstellungen im Code genau so beschrieben: Die Plattform teilt nur innerhalb von [vmidRangeStart, vmidRangeEnd] zu, eine Integration kann also von Bauart her keine VM außerhalb erreichen. Wer seine Produktions-VMs außerhalb des Bereichs hält, hält sie außer Reichweite.

Diese Sichtweise ändert, wie Sie die Zahlen wählen. Sie wählen nicht, wo Ihre Automatisierung zu zählen beginnt. Sie ziehen eine Linie um die Maschinen, bei denen Sie es hinnehmen, dass ein Programm sie löscht.

Die Leseseite ist eine eigene Frage, und sie beißt später

Anlegen ist die offensichtliche Hälfte. Lesen ist die Hälfte, die uns überrascht hat.

Unser Agent fragt den Cluster einmal pro Runde mit einem einzigen GET /cluster/resources?type=vm ab, was keinen einzigen Gast berührt. Aber für jeden laufenden Gast in dieser Antwort machte er danach zwei weitere Aufrufe in den QEMU-Gastagenten, network-get-interfaces und get-fsinfo, um Adressen und Plattenbelegung zu erfahren. Diese Liste kam ungefiltert direkt aus der Clusterabfrage.

Auf einem Testhypervisor, der auch Produktionslasten fährt, enthielt diese Liste die Produktionsmaschinen. Die Lesevorgänge sind harmlos in dem Sinne, dass nichts geschrieben wird. Sie sind nicht harmlos in dem Sinne, auf den es ankommt, denn „nur lesend“ ist keine Antwort auf die Frage, warum Ihr Agent mit dem Gastagenten einer Maschine spricht, die nicht Ihnen gehört.

Die Behebung ist, dass derselbe Bereich nun auch die Lesevorgänge begrenzt. Wer das selbst baut: Die Lehre lässt sich verallgemeinern. Eine Grenze, die nur Schreibvorgänge abdeckt, ist eine halbe Grenze, und die Lesehälfte ist die, deren Fehlen niemandem auffällt.

Wo der Bereich wohnen sollte

Wir mussten das einmal beantworten, und die Begründung gehört ausgesprochen, denn die naheliegende Antwort ist falsch.

Die naheliegende Antwort ist, den Bereich neben die Zugangsdaten zu legen, in welches Bündel auch immer die Plattform beim Anlegen der Integration an den Agenten schiebt. Eine Nachricht, sie kommt mit allem anderen an, fertig.

Das scheitert an einem Neustart. Zugangsdaten werden einmal geschoben; nach einem Neustart baut der Agent seine Integrationen aus seinem lokalen Tresor wieder auf, ohne Schub. Eine Grenze, die auf diesem Weg geliefert wird, verschwindet beim ersten Neustart des Prozesses still, und eine Grenze, die still aufhört zu gelten, ist schlimmer als gar keine, denn niemand sucht nach ihr.

Der Bereich reist also in einer eigenen Nachricht, die bei jedem Sitzungs-Handshake gesendet wird und den vollständigen Stand trägt. Zwei Lieferwege, eine Quelle der Wahrheit. Es gibt zusätzlich eine Umgebungsvariable auf dem Host als Rückfallebene, und die Reihenfolge zwischen beiden ist Absicht:

QuelleWann sie gewinnt
Die Einstellung der PlattformImmer, wenn sie eine gesendet hat
Umgebungsvariable des HostsNur, wenn die Plattform nichts gesagt hat
Gar keine GrenzeWenn keiner von beiden etwas gesagt hat

Verlockend ist die umgekehrte Reihenfolge, in der Annahme, ein auf dem Host geschnallter Gürtel sei fester. Sie erzeugt einen Zustand, den niemand sehen kann: Ein Administrator, der einmal eine Variable gesetzt hat, behält still eine Grenze, die nicht mehr zu dem passt, was das Panel zeigt, und ein Kunde, der den Bereich in der Oberfläche erweitert, kann sich nicht erklären, warum sich nichts geändert hat.

Ein kleines Detail mit großer Wirkung im Fehlerfall: Ein unlesbarer Wert gilt als „niemand“, nicht als „alle“. Wer eine Grenze verlangt und sich vertippt, bekommt gar keine Lesevorgänge, dazu eine Logzeile mit dem Grund. Der Preis ist kosmetisch: eine Adresse und eine Plattenzahl fehlen im Panel. Die Alternative, auf „alles ist erlaubt“ zurückzufallen, ist der klassische Allowlist-Fehler. Sie fällt offen aus, still, und zwar genau in dem Fall, in dem jemand vorsichtig sein wollte.

Vorlagen liegen außerhalb des Bereichs. Immer.

Das ist eine Regel und keine Vorliebe, und es ist der Fehler, der sich selbst auffrisst.

Ein Zuteiler vergibt Nummern aus dem Bereich. Legen Sie eine Vorlage in den Bereich, erreicht der Zuteiler sie eines Tages, auf dieser Nummer wird eine neue Bestellung angelegt, und die Vorlage wird zur Kunden-VM. Die Bestellung danach klont von einer Maschine, die keine Vorlage mehr ist. Der Validator weist deshalb eine Proxmox-Vorlagen-VMID ab, die in den Bereich der Integration fällt, und der Zuteiler behandelt zusätzlich jede verknüpfte Vorlage als belegt, falls jemand den Bereich nach dem Verknüpfen erweitert hat.

Außerhalb des Bereichs darf eine Vorlage überall liegen. Der Bereich begrenzt, was die Plattform anlegt, nicht, wo Ausgangsmaterial liegen darf.

Eine Nummer nie wiederverwenden, auch wenn die Maschine weg ist

Der Zuteiler vergibt die niedrigste freie VMID im Bereich, und „frei“ ist strenger, als Sie erwarten würden: Jede VMID, die die Integration jemals vergeben hat, gilt als belegt, auch die von gelöschten Servern.

Das sieht ungefähr fünf Sekunden lang verschwenderisch aus, bis Sie überlegen, was Wiederverwendung bedeuten würde. Ein spätes Zustandsereignis der alten VM landet auf der neuen Zeile. Die Prüfhistorie zweier verschiedener Server läuft in einem Zeitstrahl zusammen. Jemand spielt das Backup von gestern auf eine Nummer zurück, die nun einem anderen Kunden gehört.

Interessanterweise treffen wir im selben Produkt für IP-Adressen die entgegengesetzte Wahl, und das aus gutem Grund: Eine Adresse ist eine Adresse, und sie nie wiederzuverwenden würde ein /24 nach 254 Maschinen dauerhaft erschöpfen. Eine VMID ist ein Name für die Geschichte einer Maschine. Bereiche sind billig; Verwechslung ist es nicht.

Es gibt eine dritte Kategorie von „belegt“, die erst auftaucht, wenn mehr als eine Stelle Maschinen anlegt. Eine noch laufende Wiederherstellung hat ihre Ziel-VMID beansprucht, hat aber noch keine Serverzeile, eine zweite Wiederherstellung in derselben Minute bekäme also dieselbe „freie“ Nummer. Alles, was eine VMID vor der Zeile reserviert, muss mitgezählt werden.

Was passiert, wenn der Bereich voll ist

Zwei Antworten, und es sollte beide geben.

Die freundliche ist Arithmetik: Der Zuteiler durchsucht den Bereich, findet nichts Freies und gibt einen bestimmten Fehler zurück, der Anfang und Ende des Bereichs nennt. Der Kunde liest „dieser Bereich ist voll, von 5000 bis 8999“ statt eines Hypervisorfehlers vier Schichten tiefer.

Die echte ist die Datenbank. Die Eindeutigkeitsbedingung auf (Integration, externe ID) ist der Schiedsrichter: Zwei im selben Augenblick aufgegebene Bestellungen können beide dieselbe niedrigste freie Nummer sehen, und genau ein Insert überlebt. Der Verlierer versucht es erneut, bis zu einer kleinen festen Anzahl von Versuchen. Erst prüfen und dann einfügen öffnet genau das Rennen, das die Bedingung schließt; die Bedingung ist also der Mechanismus, und die freundliche Meldung ist eine Höflichkeit darüber.

Beachten Sie, was wir nicht verwenden: Proxmox hat einen Endpunkt für die nächste freie ID, und der ist hier das falsche Werkzeug. Er beantwortet „welche Nummer ist auf diesem Cluster frei“, und das ist eine andere Frage als „welche Nummer ist frei und liegt in dem Fenster, das mir gehört“. Fragen Sie den Hypervisor, und Sie bekommen irgendwann eine Nummer außerhalb Ihrer eigenen Grenze.

Also, praktisch

  • Fangen Sie hoch an und lassen Sie die niedrigen Nummern in Ruhe. 100 bis ein paar hundert ist auf jeder Proxmox-Installation der Ort für handgemachte Maschinen, auch auf Ihrer in drei Jahren, wenn Sie diese Entscheidung vergessen haben.
  • Wählen Sie einen Bereich mit erkennbarer Form. 5000 bis 8999 liest sich in der Weboberfläche auf einen Blick als „unser“. Ein Bereich von 4000 Nummern bedeutet viertausend Maschinen an einer Integration.
  • Legen Sie Vorlagen außerhalb ab, in einen eigenen Block, weit weg.
  • Schreiben Sie den Bereich dorthin, wo die Plattform ihn sieht, nicht nur in eine Konfigurationsdatei auf dem Host, und sorgen Sie dafür, dass er immer wieder gesendet wird statt nur einmal.
  • Prüfen Sie, dass auch Lesevorgänge begrenzt sind, nicht nur Anlegen und Löschen.

Auf die Zahl selbst kommt es wenig an. Worauf es ankommt: dass die Grenze eine Sache ist, an einer Stelle sichtbar, auf Lesen und Schreiben gleichermaßen angewandt, und dass sie fail-closed ausfällt, wenn sie nicht gelesen werden kann.

Das entstand beim Bau der Proxmox-Integration für Provibr, wo der Agent im eigenen Netz des Kunden läuft und sich ausschließlich nach außen verbindet.

Fangen Sie mit einem Host und einem Agenten an

Konto erstellen, den Agenten mit einem einzigen Befehl installieren und Ihren ersten Proxmox-Host verbinden. Die Testphase läuft 14 Tage und fragt nicht nach Zahlungsdaten.