Zum Inhalt

Sandboxes und Abfragen

Eine Sandbox ist eine private Wegwerf-Datenbank, wiederhergestellt aus einem Backup oder aus jeder Sekunde des Fensters. Sie ist das Standardziel einer Wiederherstellung, denn Nachsehen gefährdet nie die Produktion.

tenax restore team-a/app --at 2026-10-07T09:41:27Z --ttl 6h --wait
tenax sandbox list
tenax sandbox show <sandbox>

Was eine Sandbox ist

  • Ein Datenbank-Pod mit Engine und Version des Ziels (spec.sandbox.image am Ziel), im Sandbox-Namespace von Tenax, mit generierten Zugangsdaten und einer NetworkPolicy, die standardmäßig alles verweigert.
  • Eine TTL (sandbox.defaultTTL, höchstens sandbox.maxTTL, beides pro Policy und im ganzen Chart). Läuft sie ab, löscht Tenax die Sandbox und ihren Speicher. tenax sandbox extend <sandbox> --by 24h verschafft mehr Zeit; tenax sandbox delete <sandbox> beendet sie vorzeitig.
  • Sie gehört der Person, die sie angefordert hat; jede Aktion darauf wird protokolliert.

Abfragen

Die Seite Abfrage der Konsole und tenax query führen SQL über den Abfrage-Proxy von Tenax aus, standardmäßig nur lesend:

tenax query <sandbox> -e "select count(*) from orders where created_at > now() - interval '1 day'"
tenax query <sandbox> -e "select * from coupons" -o csv > coupons.csv

Jede Abfrage hat ein Limit von 30 Sekunden und liefert höchstens 1.000 Zeilen; --write erlaubt Schreibzugriffe (nur in Sandboxes).

Im Editor führt Ctrl+Enter (Cmd+Enter auf dem Mac) die Abfrage aus, bei einer Auswahl nur den markierten Text. Die Vervollständigung bietet Schlüsselwörter, Funktionen, Tabellen und Spalten an: Beim Tippen öffnet sie sich nach zwei Zeichen, nach alias. listet sie die Spalten dieser Tabelle, nach schema. deren Tabellen, und Ctrl+Space öffnet sie überall. Tab oder Enter übernimmt einen Vorschlag, Esc schließt sie, und sonst rückt Tab ein.

Die Konsole spricht das SQL jeder Engine (heute PostgreSQL und MySQL); Ergebnisse zeigen Werte so, wie die Datenbank sie ausgibt.

Dimensionierung

Jede Sandbox ist ein Datenbank-Pod in einem eigenen Namespace. Was sie bekommt, stammt von der ersten Stelle, die es festlegt:

  1. die Wiederherstellung: die Felder CPU, Speicher, Festplatte und Storage-Klasse auf der Seite Restore (die ausgegrauten Werte gelten, wenn Sie sie leer lassen), tenax restore … --cpu 2 --memory 8Gi --size 50Gi --storage-class local-path oder spec.destination.sandbox eines Restore;
  2. das Ziel: spec.sandbox.cpu, memory, sizeLimit, storageClass des BackupTarget;
  3. die Installation: sandbox.resources des Charts;
  4. eingebaut: 100m CPU, 256Mi angeforderter Speicher mit einem Limit von 1Gi und eine Disk von doppelter Datengröße des Backups plus 512Mi (mindestens 1Gi) auf dem Node (emptyDir, wird mit der Sandbox entfernt).
Einstellung Bedeutung
CPU CPU-Request; kein CPU-Limit, damit eine Wiederherstellung freie Kerne nutzen kann
Memory Speicher-Request und -Limit
Disk Größe des Datenvolumes; auf der Disk des Nodes, sofern keine Storage Class gesetzt ist
Storage class die Daten landen stattdessen auf einem PVC dieser Klasse, für Wiederherstellungen, die größer sind, als Node-Disks erlauben

sandbox.limits im Chart setzt Obergrenzen für CPU, Speicher und Disk. Konsole und API lehnen eine Anfrage darüber ab, und eine Wiederherstellung, deren Größe darüber liegt (durch eine Einstellung des Ziels oder die automatische Größe eines großen Backups), schlägt mit Begründung fehl, statt mittendrin eine Disk zu füllen. Eine laufende Sandbox behält ihre Größe: Stellen Sie erneut wieder her, um sie zu ändern.

Verbinden aus dem Cluster

Host, Port und Zugangsdaten der Sandbox stehen auf ihrer Seite (Zugangsdaten anzeigen, protokolliert) und in tenax sandbox show. Pods in anderen Namespaces brauchen das Label tenax.run/sandbox-client: <sandbox>; die Network Policy der Sandbox weist alles andere ab.

Verbinden von außerhalb des Clusters

Wie Sandboxes vom Laptop aus erreicht werden, entscheidet die Installation (expose.provider, siehe unten). In jedem Fall gilt:

  • Öffnen Sie den externen Zugriff mit Externen Zugriff öffnen auf der Seite der Sandbox, tenax sandbox expose <sandbox> oder open external access beim Wiederherstellen (tenax restore … --expose); das braucht die Rolle operator.
  • Verbinden Sie sich mit tenax sandbox connect <sandbox>, das einen Connection-String für jeden Datenbank-Client ausgibt, oder kopieren Sie ihn von der Seite der Sandbox.
  • Schließen Sie ihn mit Externen Zugriff schließen oder tenax sandbox unexpose <sandbox>. Er schließt sich auch, wenn die Sandbox abläuft oder gelöscht wird.
expose.provider Was tenax sandbox connect tut Der Client braucht
none (Standard) Leitet einen lokalen Port über Ihre Kubeconfig an die Sandbox weiter, bis Strg+C Eine Kubeconfig, die Port-Forwarding in tenax-sbx-<sandbox> erlaubt
service Gibt die eigene Adresse der Sandbox aus (postgres://…@sbx-7f3a.db.example.com:5432/app?sslmode=require) Nichts: jeden Datenbank-Client, über TLS
cloudflare Öffnet nach einem Access-Login cloudflared access tcp auf einem lokalen Port, bis Strg+C cloudflared und eine zugelassene E-Mail-Adresse

Postgres-Sandboxes bieten TLS mit einem eigenen Zertifikat an (selbstsigniert: Clients verwenden sslmode=require, das verschlüsselt, ohne den Aussteller zu prüfen); MySQL-Sandboxes verwenden das Zertifikat, das MySQL erzeugt.

Sandboxes von außerhalb des Clusters erreichen (Administratoren)

Tenax öffnet von sich aus nichts: Jede Option nutzt etwas, das Ihr Cluster bereits hat.

Option service: ein Kubernetes-Service pro Sandbox

Jede freigegebene Sandbox erhält einen Service, gebaut aus expose.service; was auch immer Ihr Cluster für Services betreibt, gibt ihm eine Adresse, und Tenax zeigt diese Adresse an. Für Entwickler ist das am einfachsten (jeder Datenbank-Client) und funktioniert mit jedem Kubernetes:

Ihr Cluster hat Setzen Sie Entwickler verbinden sich mit
Einen Cloud-Load-Balancer (AKS, EKS, GKE) type: LoadBalancer, sourceRanges: [<office or VPN CIDRs>] Der IP des Load Balancers
Dasselbe, plus external-dns zusätzlich annotations: {external-dns.alpha.kubernetes.io/hostname: "sbx-{id}.db.example.com"} und hostnamePattern: "sbx-{id}.db.example.com" sbx-<id>.db.example.com
MetalLB (On-Premises) type: LoadBalancer Einer Adresse in Ihrem Netzwerk
Den Tailscale-Operator loadBalancerClass: tailscale Dem Tailnet-Namen der Sandbox; nichts ist öffentlich
Nichts davon type: NodePort, hostnamePattern: "nodes.example.com" mit einem passenden Namen für Ihre Nodes nodes.example.com:<node port>
expose:
  provider: service
  service:
    type: LoadBalancer
    sourceRanges: ["203.0.113.0/24"]   # who may connect; leave empty only on a private network

Sandboxes enthalten Kopien von Produktionsdaten

Ein öffentlicher Load Balancer schützt eine Sandbox nur mit ihrem Zufallspasswort, TLS und ihrem Zeitlimit. Setzen Sie sourceRanges auf die Adressen, von denen Ihre Entwickler kommen, oder verwenden Sie eine private Option (Tailscale, einen internen Load Balancer über die Annotation Ihrer Cloud, MetalLB in einem privaten Netzwerk).

Solange eine Sandbox freigegeben ist, lässt eine zusätzliche NetworkPolicy expose.service.allowFrom (Standard: alles; die Filterung übernimmt sourceRanges des Load Balancers, da dessen Traffic oft von Node-Adressen kommt) auf den Datenbank-Port zu. Mit dem eingebauten Load Balancer von k3s belegt jede freigegebene Sandbox den Datenbank-Port auf den Nodes, dort kann also jeweils nur eine Postgres- und eine MySQL-Sandbox freigegeben sein.

Option cloudflare: ein Tunnel hinter einem Access-Login

Tunnel brauchen ein Cloudflare-API-Token, das zur Installation gehört, nicht zu einem Benutzer. Es ist ein Kubernetes-Secret im Namespace von Tenax, einmal eingerichtet wie alle anderen Zugangsdaten (mit Ihrem GitOps-Secret-Werkzeug, zum Beispiel SOPS). Die Konsole fragt nie danach, speichert es nie und zeigt es nie an: Es kann DNS und Access-Anwendungen in der Zone ändern.

  1. In Cloudflare unter My Profile → API Tokens → Create Token → Custom token mit diesen Berechtigungen, für die Zone, in der die Hostnamen liegen:
    • Account: Cloudflare Tunnel: Edit
    • Account: Access: Apps and Policies: Edit
    • Zone: DNS: Edit
    • Zone: Zone: Read
  2. Speichern Sie es:

    kubectl -n tenax-system create secret generic tenax-cloudflare-api --from-file=token=api-token.txt
    
  3. Konfigurieren Sie das Chart:

    expose:
      provider: cloudflare
      cloudflare:
        zone: example.com
        apiTokenSecret: tenax-cloudflare-api
        hostnamePattern: "sbx-{id}.example.com"
        allowEmails: ["*@example.com"]      # who may connect to an open tunnel
      cloudflared:
        enabled: true
    

Halten Sie die Hostnamen eine Ebene unter der Zone (sbx-{id}.example.com, nicht sbx-{id}.db.example.com): Das kostenlose Zertifikat von Cloudflare deckt nur *.example.com ab, und der Client erreicht den Hostnamen über HTTPS. Ein Datenbank-Port lässt sich nicht durch einen Browser-Login schützen, daher führen Entwickler cloudflared aus, was tenax sandbox connect für sie übernimmt.

Mit dem Token ermittelt Tenax das Konto aus der Zone, legt einen Tunnel namens tenax an (expose.cloudflare.tunnelName) oder verwendet ihn wieder und schreibt das Connector-Token des Tunnels in das Secret <release>-tunnel-token, aus dem die cloudflared-Pods starten. Es prüft dieses Secret alle 15 Minuten, sodass ein in Cloudflare rotiertes Token von selbst im Secret ankommt (starten Sie die cloudflared-Pods neu, damit sie es übernehmen). allowEmails nimmt Adressen und ganze Domains (*@example.com); allowGroups nimmt Access-Gruppen-IDs.

Ein Tunnel, den Sie bereits verwalten

Setzen Sie expose.cloudflare.tunnelID, um statt tenax einen bestehenden, remote verwalteten Tunnel zu verwenden, und expose.cloudflared.tunnelTokenSecret auf ein Secret (Schlüssel token) mit seinem Connector-Token, wenn Sie es lieber selbst bereitstellen; Tenax lässt dieses Secret dann in Ruhe. Tenax fügt nur seine eigenen sbx-…-Regeln hinzu und entfernt nur diese, die übrigen Routen des Tunnels bleiben also, wie sie sind. accountID und zoneID lassen sich setzen, um die Nachschlagevorgänge zu überspringen.

Derselbe Tunnel kann auch die Konsole selbst bereitstellen: Fügen Sie dem Tunnel einen öffentlichen Hostnamen für tenax-api hinzu (Zero Trust → Networks → Tunnels → tenax → Public hostnames), hinter einer Access-Anwendung, und setzen Sie expose.cloudflared.consoleHostname mit auth.provider: cloudflare-access: siehe Konsole, CLI und Zugriff.