pbx-agent
pbx-agent ist das Programm auf jedem Server von PaaSbox Clusters, das den Cluster in dem Zustand hält, den das Portal für ihn vorsieht. Diese Seite listet seine Befehle, Dateien, sein Protokoll, seine Operationen und sein Verhalten bei Fehlern, für den Fall, dass du selbst auf einen Node schaust oder genau wissen willst, was das Portal von ihm verlangen kann.
pbx-agent ist ein statisches Go-Programm, das systemd auf jedem k3s-Server eines Clusters von PaaSbox Clusters ausführt. Es ist kein KI-Agent. Es läuft als root, weil eine Wiederherstellung k3s anhalten und wieder starten muss, während die Kubernetes-API nicht erreichbar ist. Es lauscht auf keinem Port: Es ruft das Portal an, bringt den Node auf den Sollzustand, den es bekommt, und führt eine Operation nach der anderen aus einer festen Liste aus.
Befehle
Abschnitt betitelt „Befehle“| Befehl | Was er tut |
|---|---|
pbx-agent run | Der Dienst: sich einmal registrieren, k3s starten, sich mit dem Portal abgleichen, den Sollzustand anwenden, Operationen ausführen. Das führt die systemd-Unit aus. |
pbx-agent status | Gibt den Zustand von pbx-agent als JSON aus, ohne jedes Geheimnis. |
pbx-agent uninstall | Zeigt, was er entfernen würde, und ändert nichts. Mit --yes entfernt er den Agenten (unten). |
pbx-agent version | Gibt die Version und die IDs der eingebauten Release-Schlüssel aus. |
pbx-agent simulate | Simulierte Agenten, um das Portal zu testen, bis zu einem Lasttest mit 1.000; ändert nichts an der Maschine, auf der er läuft. Wird auf einem Node nicht benutzt. |
Dateien auf dem Node
Abschnitt betitelt „Dateien auf dem Node“| Pfad | Modus | Was es ist |
|---|---|---|
/etc/pbx-agent/config.yaml | 0600 | Die Adresse des Portals, die ID des Clusters, der Name des Nodes und das Registrierungs-Token, bis es benutzt ist. Von cloud-init geschrieben. |
/etc/systemd/system/pbx-agent.service | Die Unit. Von cloud-init geschrieben. | |
/var/lib/pbx-agent/ | 0700 | Das Zustandsverzeichnis von pbx-agent. |
/var/lib/pbx-agent/bin/pbx-agent | Das Programm, daneben pbx-agent.prev (die vorige Version) und pbx-agent.new (während eines Updates). | |
/var/lib/pbx-agent/identity.json | 0600 | Die ID von pbx-agent und seine privaten Schlüssel: ein Ed25519-Schlüssel zum Signieren, ein X25519-Schlüssel, um versiegelte Geheimnisse zu empfangen; während eines Wechsels auch die vorigen Schlüssel. |
/var/lib/pbx-agent/state.json | 0600 | Der zuletzt angewandte Sollzustand, die laufende Operation und ihr Schritt, und die IDs abgeschlossener Operationen (30 Tage aufbewahrt). |
/var/lib/pbx-agent/bootstrap.json | 0600 | Die Antwort auf die Registrierung. Geheimnisse darin bleiben auf der Platte versiegelt. |
/var/lib/pbx-agent/ops/<id>.log | Ein Log pro Operation. Die letzten 200 Zeilen gehen in einen Fehlerbericht. | |
/etc/rancher/k3s/config.yaml | 0600 | Die Konfiguration von k3s, einmal bei der Registrierung geschrieben. |
/etc/rancher/k3s/config.yaml.d/50-pbx-*.yaml | Die Drop-ins von pbx-agent: der Snapshot-Zeitplan und der Ingress-Modus. | |
/var/lib/rancher/k3s/server/manifests/pbx-*.yaml | Die Manifeste, die k3s bei seinem ersten Start anwendet, etwa das des Cloud Controllers. Sobald pbx-agent dieses Add-on über die API verwaltet, schreibt er pbx-<name>.yaml.skip daneben, damit k3s die erste Fassung nicht mehr anwendet. |
Das Programm liegt unter /var, weil /usr auf dem Node-Image nur lesbar ist; /var und das Overlay auf /etc überstehen Image-Updates.
Die Unit:
[Unit]Description=pbx-agentWants=network-online.targetAfter=network-online.target[Service]Type=execExecStart=/var/lib/pbx-agent/bin/pbx-agent runRestart=alwaysRestartSec=5ProtectHome=yesPrivateTmp=yes[Install]WantedBy=multi-user.targetDie Logs: journalctl -u pbx-agent.
Das Protokoll
Abschnitt betitelt „Das Protokoll“pbx-agent öffnet jede Verbindung, zu https://agents.<Domain des Portals>/agent/v1. JSON über HTTPS, Bodies von höchstens 256 KiB.
| Endpunkt | Zweck | Authentisiert durch |
|---|---|---|
POST /enroll | Das Registrierungs-Token gegen eine Identität und die Konfiguration des Nodes tauschen | Das Registrierungs-Token |
POST /sync | Den Zustand des Nodes melden; den Sollzustand und höchstens eine Operation bekommen | Die Signatur von pbx-agent |
POST /operations/{id}/events | Fortschritt und Ergebnis einer Operation melden | Die Signatur von pbx-agent |
GET /releases/{version}/manifest | Ein signiertes Release-Manifest holen | Die Signatur von pbx-agent |
POST /rotate-key | Neue öffentliche Schlüssel eintragen, signiert mit dem alten Schlüssel | Die Signatur von pbx-agent |
Signieren. Jede Anfrage nach der Registrierung trägt die ID von pbx-agent, einen Zeitstempel und eine Ed25519-Signatur über Methode, Pfad, Zeitstempel und einen SHA-256 des Bodys. Das Portal lehnt eine Zeitabweichung von mehr als 60 Sekunden ab und eine Signatur, die es in den letzten 120 Sekunden schon gesehen hat.
Versiegeln. Jedes Geheimnis, das das Portal schickt (k3s-Tokens, S3-Schlüssel, Hetzner-Tokens, Geheimnisse von Add-ons), ist mit einer libsodium Sealed Box an den X25519-Schlüssel von pbx-agent verschlüsselt. Kommt ein Geheimnis im Klartext an, lehnt pbx-agent das ganze Dokument ab (unsealed_secret).
Wie pbx-agent auf die Statuscodes des Portals reagiert
Abschnitt betitelt „Wie pbx-agent auf die Statuscodes des Portals reagiert“| Antwort | pbx-agent |
|---|---|
| 200 | wendet sie an |
| 400 | protokolliert sie und wartet; schickt dieselbe Anfrage nie öfter als dreimal. Eine Antwort replayed (ein neu gestarteter pbx-agent hat dieselbe Anfrage in derselben Sekunde signiert) signiert er einmal neu mit der nächsten Sekunde. |
| 401 | behandelt seine Identität als widerrufen: hört auf, sich abzugleichen, lässt den Cluster in Ruhe, läuft untätig weiter |
409 clock_skew | korrigiert seine Zeitabweichung anhand der Zeit des Portals und versucht es erneut |
426 protocol_too_old | aktualisiert sich auf den pbx-agent des Releases, das das Portal nennt, egal, was der Sollzustand sagt |
| 429 | wartet so lange, wie das Portal sagt |
| 5xx, kein Netz | wartet exponentiell länger, von 5 Sekunden bis 5 Minuten, mit Zufallsanteil |
Registrierung
Abschnitt betitelt „Registrierung“- Beim ersten Start erzeugt
pbx-agentseine Schlüssel und speichert sie, bevor er sie benutzt. - Er liest die ID des Servers aus dem Metadatendienst von Hetzner.
- Er schickt das Registrierungs-Token, seine öffentlichen Schlüssel und den Hash des Boot-Images, das der Node tatsächlich gestartet hat. Das Portal prüft das Token (unbenutzt, nicht abgelaufen, an diesen Cluster und diesen Node-Namen gebunden), prüft über die Hetzner-API, dass der Server das Label des Clusters und den Namen des Nodes trägt, und vergleicht den Hash des Boot-Images mit dem Release.
- Er speichert die Antwort und löscht das Token aus seiner Konfiguration.
- Er schreibt die Konfiguration von k3s, startet k3s als Server, wartet auf die API und schreibt die Secrets
kube-system/hcloudundkube-system/pbx-etcd-s3.
| Das Portal antwortet | Bedeutung | pbx-agent |
|---|---|---|
| 200 | Identität und Konfiguration | macht weiter |
401 invalid_token, token_used, token_expired, server_mismatch | das Token wird abgelehnt | versucht es höchstens dreimal, dann wartet er untätig; ein neues Token heißt ein neuer Server |
409 image_mismatch | der Node hat ein anderes Image gestartet als das seines Releases | wartet untätig; der Node braucht einen neuen Server aus dem richtigen Image |
409 conflict | die Konfiguration kann noch nicht gebaut werden | versucht es mit wachsender Wartezeit erneut |
503 internal | das Portal erreicht die Hetzner-API nicht | versucht es mit wachsender Wartezeit erneut |
| 429 | zu viele Anfragen | wartet so lange, wie das Portal sagt |
Dasselbe Token mit denselben Schlüsseln vom selben Server bekommt wieder dieselbe Antwort; eine Antwort, die unterwegs verloren geht, kann pbx-agent also gefahrlos erneut anfragen.
Der Abgleich
Abschnitt betitelt „Der Abgleich“Etwa alle 30 Sekunden (± 5) schickt pbx-agent seinen Bericht und bekommt den Sollzustand. In jedem Durchgang gleicht er in dieser Reihenfolge an: sein eigenes Update, die Konfiguration des Hosts (Drop-ins für k3s), die Konfiguration des Clusters (Secrets, Add-ons), dann die Operation. Die Konfiguration des Clusters wendet er alle 10 Minuten neu an, auch ohne Änderung; eine Änderung von Hand an einem verwalteten Objekt wird also überschrieben.
Ein Sollzustand wird als Ganzes angewandt. Sein Release-Manifest wird zuerst geholt und geprüft; ein Manifest, das kein eingebauter Schlüssel bestätigt, ändert nichts (manifest_rejected).
Ein Drop-in, das einen Neustart von k3s braucht, wird sofort geschrieben; der Neustart folgt im nächsten Moment innerhalb des Wartungsfensters, nie während einer Operation. In Arbeit Das ist auf einem echten Node noch nicht gelaufen.
In einem Cluster mit mehr als einem Server führt ein pbx-agent: der Inhaber des Lease pbx-system/pbx-agent-leader. Auf einem einzelnen Node führt sein pbx-agent, solange die Kubernetes-API läuft.
Add-ons
Abschnitt betitelt „Add-ons“pbx-agent wendet jedes Add-on aus der Vorlage im signierten Release an, mit den Optionen aus dem Sollzustand.
| Was | Wie |
|---|---|
| Objekte, die er anlegen darf | HelmChart- und HelmChartConfig-Objekte, Secrets namens pbx-addon-* in kube-system und für die PaaSbox Platform eine clusterweite Platform, benannt nach dem Cluster |
| Labels | pbx.io/managed=true an jedem verwalteten Objekt, pbx.io/addon=<name> an den Objekten eines Add-ons |
| Geheime Optionen | Nur in einem Secret pbx-addon-<name>, das das Chart liest, nie in einem HelmChart: k3s verschlüsselt Secrets im Ruhezustand, Custom Resources nicht |
| Abgeschaltet | Seine Objekte werden gelöscht; Daten, Volumes und CRDs bleiben. Die Secrets hcloud und pbx-etcd-s3 werden nie gelöscht. |
| Eine Vorlage oder ein Anwenden, das fehlschlägt | Das Add-on meldet failed und behält die Objekte, die es hat: Eine fehlgeschlagene Vorlage deinstalliert nie ein laufendes Chart |
Jedes Add-on meldet einen Zustand: applied, pending, failed oder removed.
| Fall | Zustand |
|---|---|
| Ein Add-on, das es braucht, ist aus | failed: braucht das Add-on <r>, das aus ist |
| Ein Add-on, mit dem es sich nicht verträgt, ist an und installiert | failed: verträgt sich nicht mit dem Add-on <c>; schalte das zuerst ab |
| Ein solches Add-on ist aus, seine Objekte gibt es noch | pending, bis sie weg sind |
Ein Add-on, das es braucht, ist noch nicht applied | pending |
| Angewandt, seine Gesundheitsprüfung besteht noch nicht | pending; pbx-agent wendet die Konfiguration des Clusters in jedem Durchgang an, bis sie besteht |
| Angewandt, seine Gesundheitsprüfung besteht, oder es hat keine | applied |
| Abgeschaltet, während ein Add-on an ist, das es braucht | failed: wird noch gebraucht |
Gebaut im Labor: Das Add-on PaaSbox Platform wird in zwei Schritten abgeschaltet. Solange es eine SaaSApplication gibt, ändert Abschalten nichts: Das Add-on meldet failed mit den Namen der Anwendungen. Lösche sie zuerst. Dann wendet pbx-agent eine Platform an, die nichts installiert, und wartet, bis Flux entfernt hat, was die Plattform installiert hat. Eine Platform, die das Entfernen ablehnt (eine Datenbank, oder eine Anwendung, die noch einen Teil von ihr braucht), behält alles und meldet das Add-on mit ihrer Nachricht als failed.
Operationen
Abschnitt betitelt „Operationen“Pro Cluster läuft eine Operation zur Zeit. Jede ist eine Liste benannter Schritte, die sich gefahrlos wiederholen lassen; pbx-agent hält den Schritt fest, bevor er ihn beginnt, und setzt nach einem Absturz oder Neustart dort fort. Ein fehlgeschlagener Schritt meldet seinen Namen und die letzten 200 Zeilen seines Logs. Zerstörende Schritte wiederholt pbx-agent nie von sich aus.
| Operation | Schritte | Was sie tut |
|---|---|---|
snapshot.save | save, confirm_s3, report | Macht einen etcd-Snapshot und bestätigt, dass er im Bucket angekommen ist |
cluster.restore | stop_k3s, reset_restore, start_k3s, wait_api, forget_stale_nodes | Setzt den Zustand des Clusters auf einen Snapshot zurück; siehe Snapshots machen und wiederherstellen |
cluster.upgrade | preflight, pre_snapshot, fetch_image, stage_slot, reboot, health_gate, commit | Aktualisiert das Node-Image an Ort und Stelle; siehe Einen Cluster upgraden |
access.issue | ensure_sa, token, seal | Stellt eine Kubeconfig aus, versiegelt an den Schlüssel dessen, der gefragt hat: deinen Browser oder den eigenen Schlüssel eines Agenten |
access.revoke | delete_sa | Löscht die ServiceAccounts einer Person oder die aller |
agent.rotate_key | generate, register, confirm | Ersetzt die eigenen Schlüssel von pbx-agent; das Portal verlangt das, wenn sie 90 Tage alt sind |
s3.verify | list_bucket | Listet den Bucket mit neuen Schlüsseln, bevor sie benutzt werden |
diag.collect | collect | Versionen, Zustände der Units und die letzten Zeilen der Logs von k3s und pbx-agent, nur mit deiner Zustimmung für genau diese Anfrage; nie Secrets, Tokens oder Umgebungsdateien |
server.rejoin, node.drain, node.forget | Für Cluster mit mehr als einem Server; auf einem einzelnen Node nicht benutzt |
Wie die Schritte entscheiden, wo es darauf ankommt:
reset_restorelegt den Snapshot selbst auf den Node, aus der lokalen Kopie von k3s oder mit dem eigenen S3-Client vonpbx-agentaus dem Bucket geholt, entpackt ihn und startetk3s server --cluster-resetmit--etcd-s3=false. Die S3-Schlüssel landen nie auf einer Kommandozeile oder in der Umgebung von k3s.forget_stale_nodeslöscht einen anderen Node als den eigenen, dessen Kubelet sich nicht gemeldet hat, seit die wiederhergestellte API läuft, nach einer Frist von 2 Minuten.cluster.upgrademacht den Snapshotpbx-pre-upgrade-<release>, legt das neue Image als Boot-Eintragpbx-<release>-<arch>.efian und behält zwei Einträge, den neuen und den, von dem es kam. Die Gesundheitsprüfung wartet auf die API, den NodeReadymit dem neuen k3s, den neuen Boot-Eintrag und jedes Deployment inkube-systemverfügbar. Ein Node, der 20 Minuten nach dem Neustart nicht gesund ist, wird in den alten Eintrag neu gestartet. In Arbeit Diese Rückkehr hat auf einem echten Node noch nicht ausgelöst.reset_restoreundrebootsind die zerstörenden Schritte. Nach einem Absturz in einem davon prüftpbx-agent, was der Node zeigt: nicht begonnen, dann läuft er; abgeschlossen, dann geht es weiter; alles andere istfailedund läuft nie von sich aus erneut.
Eine unbekannte Operation wird als nicht unterstützt beantwortet. Es gibt keine Operation, die einen Befehl ausführt, den du oder jemand anderes eintippt.
Ist die Kubernetes-API nicht erreichbar, nimmt pbx-agent nur cluster.restore und diag.collect an.
Wenn etwas schiefgeht
Abschnitt betitelt „Wenn etwas schiefgeht“| Lage | pbx-agent |
|---|---|
| Das Portal ist nicht erreichbar | behält den letzten Sollzustand und versucht es mit wachsender Wartezeit erneut; k3s macht weiter die geplanten Snapshots |
| Die Kubernetes-API ist nicht erreichbar | meldet das und nimmt nur Operationen auf Host-Ebene an: Wiederherstellung und Diagnose |
| Ein Schritt einer Operation schlägt fehl | hält an, meldet den Schritt und die letzten 200 Log-Zeilen; wiederholt einen zerstörenden Schritt nie von sich aus |
| Die Signatur eines Release-Manifests ist ungültig | lehnt es ab, meldet manifest_rejected, ändert nichts |
| Ein Geheimnis kommt im Klartext an | lehnt das ganze Dokument ab, meldet unsealed_secret, ändert nichts |
pbx-agent ist widerrufen | hört auf, sich abzugleichen, und lässt den Cluster, wie er ist |
Seine eigenen Updates
Abschnitt betitelt „Seine eigenen Updates“Nennt der Sollzustand eine andere Version von pbx-agent, holt er das Release-Manifest, nimmt das Programm für seine Architektur, prüft dessen SHA-256, behält das laufende Programm als pbx-agent.prev, stellt einen Rückkehr-Timer auf 10 Minuten, tauscht die Programme und startet neu. Der erste erfolgreiche Abgleich mit dem Portal entschärft den Timer. Löst er aus, wird das vorige Programm zurückgelegt. Ein pbx-agent, der sich zurückgerollt findet, meldet das und versucht diese Version sechs Stunden lang nicht wieder.
pbx-agent vertraut nur Release-Manifesten, die mit einem der beiden eingebauten Release-Schlüssel signiert sind. Nichts zur Laufzeit kann diese Schlüssel ändern. Ein pbx-agent, der ohne sie gebaut wurde, lehnt jedes Manifest ab: Er aktualisiert sich nie und upgradet den Node nie. Releases und Kanäle beschreibt das Signieren.
Ihn entfernen
Abschnitt betitelt „Ihn entfernen“pbx-agent uninstall --yesSchaltet die Unit und den Rückkehr-Timer ab und entfernt sie, entfernt /var/lib/pbx-agent und /etc/pbx-agent. k3s, seine Konfiguration und jedes Kubernetes-Objekt bleiben. Ohne --yes zeigt er, was er tun würde, und ändert nichts. In Arbeit Auf einem echten Node noch nicht gelaufen. Einen Cluster abkoppeln oder löschen sagt, wann du ihn benutzt.