SXAccessSXAccessDoku
Dashboard öffnen

Kubernetes und CI

Entwicklern per kubectl Zugriff auf einen privaten Cluster geben und CI-Jobs eng begrenzten, kurzlebigen Zugriff, ohne den API-Server freizugeben.

Was Sie erreichen werden

Entwickler arbeiten von ihren Notebooks aus mit kubectl auf einem privaten Cluster, und CI-Jobs erreichen nur das, wohin sie deployen.

Der API-Server bleibt vom öffentlichen Internet aus unerreichbar. Runner kommen und gehen, ohne die Geräteliste zu füllen.

Wann Sie das brauchen

Diese Seite behandelt zwei Aufgaben, in dieser Reihenfolge:

  • Den Cluster erreichen - Entwickler brauchen den API-Server und vielleicht einige Services. Schritte 1 bis 4.
  • CI-Zugriff gewähren - Runner brauchen den API-Server für ein paar Minuten und verschwinden dann. Schritte 5 und 6.

Halten Sie beides getrennt. Geben Sie CI nie den Schlüssel des Clusters: Jeder Runner käme sonst in die Gruppe des Routing-Geräts und würde selbst Verkehr für den Cluster weiterleiten.

Was Sie brauchen

Die als Erforderlich markierten Zeilen genügen, um den Cluster zu erreichen. Für CI kommt die optionale Zeile hinzu.

WasWozu
ErforderlichDie Rolle Owner oder Admin im DashboardFür die Registrierungsschlüssel und Ihre Mitgliedsseite
ErforderlichZugriff per kubectl auf den Cluster, so wie Sie ihn heute erreichen, mit dem Recht, einen Namespace anzulegen, mit einem Label zu versehen und darin bereitzustellenDie Schritte 1 und 2 brauchen diesen Zugriff, bevor SXAccess den API-Server erreicht. Der Agent braucht für NET_ADMIN und NET_RAW die Stufe privileged von Pod Security Admission
ErforderlichDas Image unter Add device › DockerEs startet den Agenten und registriert ihn
ErforderlichEin ReadWriteOnce-Volume mit 1 GiBEs bewahrt die Identität des Geräts über Neustarts hinweg
ErforderlichDie Zeile server: Ihrer kubeconfigDer API-Server wird unter diesem Host und Port veröffentlicht
ErforderlichEin angemeldetes Notebook mit der SXAccess-App oder der CLI und mit kubectlFür den Test
OptionalCI-Jobs, die als root oder mit sudo laufen, auf VMs oder in Containern mit NET_ADMIN und NET_RAWSchritte 5 und 6

Bevor Sie beginnen

Ein Pod spricht für den Cluster.

Wie ein privater Cluster erreicht wirdNotebooks in der Gruppe platform und temporäre CI-Runner verbinden sich über verschlüsselte Tunnel mit einem einzelnen Agent-Pod im Cluster. Dieser erreicht den API-Server und alle Services, die Sie einzeln veröffentlichen. Der Pod-CIDR wird nie veröffentlicht, weil sich Pod-Adressen ständig ändern.KUBERNETES-CLUSTEREinzeln veröffentlichtAPI-ServerServicesPod-CIDRNotebookSXAccess-AppCI-Runnertemporäres GerätAgent-Podein Deployment,ein Replikatverschlüsselter TunnelCluster-Verkehrnie veröffentlichtEin Routing-Gerät je Cluster, nicht je KnotenWie ein privater Cluster erreicht wirdNotebooks in der Gruppe platform und temporäre CI-Runner verbinden sich über verschlüsselte Tunnel mit einem einzelnen Agent-Pod im Cluster. Dieser erreicht den API-Server und alle Services, die Sie einzeln veröffentlichen. Der Pod-CIDR wird nie veröffentlicht, weil sich Pod-Adressen ständig ändern.KUBERNETES-CLUSTEREinzeln veröffentlichtAPI-ServerServicesPod-CIDRNotebookSXAccess-AppCI-RunnertemporäresGerätAgent-Podein Deployment,ein Replikatverschlüsselter TunnelCluster-Verkehrnie veröffentlichtEin Routing-Gerät je Cluster, nicht je Knoten

Warum ein Deployment statt eines DaemonSets und Services statt des Pod-CIDR, steht unter Erweiterte Konfiguration.

Einrichtung

  1. 1

    Den Schlüssel des Clusters anlegen und als Secret ablegen

    Access › Enrollment keys › Create enrollment key:

    • Name - k8s-prod-router.
    • Make this key reusable - an, damit sich ein Pod, der sein Volume verloren hat, neu registrieren kann.
    • Expires in - leer, dann läuft der Schlüssel nie ab.
    • Usage limit - 5. Nur ein neues Gerät verbraucht eine Nutzung, ein Neustart nicht.
    • Temporary devices, Allow Extra DNS Labels - aus. Ein Routing-Gerät muss während des Reschedulings seines Pods in der Liste bleiben.
    • Auto-assigned groups - tippen Sie k8s-routers ein und drücken Sie Enter.

    Wählen Sie Create enrollment key und kopieren Sie den Schlüssel: Er wird nur einmal angezeigt.

    Führen Sie den Block unten, wie auch Schritt 2, dort aus, wo kubectl den Cluster heute schon erreicht. Er legt den Schlüssel als Secret in einem Namespace ab, der die Capabilities des Agenten erlaubt, und hält ihn aus Ihrer Shell-Historie und Ihren Manifesten heraus. Führen Sie den Block in bash oder zsh aus (macOS, Linux, WSL). Fügen Sie den ganzen Block ein und drücken Sie einmal Enter. Sobald Enrollment key: erscheint, fügen Sie den Schlüssel ein, und nur ihn, und drücken Sie Enter. Der Schlüssel wird nicht angezeigt, und bei einer leeren Zeile fragt der Block erneut.

    Sie sehen: secret/sxaccess-key created.

    shell
    kubectl create namespace sxaccesskubectl label namespace sxaccess pod-security.kubernetes.io/enforce=privileged{  KEY=''  until [ -n "$KEY" ]; do printf 'Enrollment key: '; read -rs KEY || break; echo; done  [ -n "$KEY" ] && kubectl -n sxaccess create secret generic sxaccess-key --from-literal=enrollment-key="$KEY"  unset KEY}
  2. 2

    Den Agenten als einzelnes Deployment betreiben

    Speichern Sie das Manifest unten als sxaccess-router.yaml, ersetzen Sie den Platzhalter durch das Image aus Add device › Docker und führen Sie kubectl apply -f sxaccess-router.yaml aus. Setzt der Befehl dort weitere Variablen mit -e, übernehmen Sie sie unter env.

    Das Image startet den Agenten und führt sxaccess start aus, mit dem Schlüssel aus SX_ENROLLMENT_KEY und dem Namen aus SX_HOSTNAME. BPF ist optional. strategy: Recreate beendet den alten Pod, bevor der neue startet; so teilen sich nie zwei Pods die Identität auf dem Volume.

    Sie sehen: Nach etwa einer Minute beginnt die Ausgabe von kubectl -n sxaccess exec deploy/sxaccess-router -- sxaccess info mit Connected, und k8s-router-prod steht unter Devices in k8s-routers. Running allein beweist nicht, dass sich der Pod registriert hat.

    shell
    apiVersion: v1kind: PersistentVolumeClaimmetadata:  name: sxaccess-state  namespace: sxaccessspec:  accessModes: ["ReadWriteOnce"]  resources:    requests:      storage: 1Gi---apiVersion: apps/v1kind: Deploymentmetadata:  name: sxaccess-router  namespace: sxaccessspec:  replicas: 1  strategy:    type: Recreate  selector:    matchLabels: { app: sxaccess-router }  template:    metadata:      labels: { app: sxaccess-router }    spec:      containers:        - name: sxaccess          image: IMAGE-FROM-ADD-DEVICE-DOCKER   # aus Add device > Docker kopieren          securityContext:            capabilities:              add: ["NET_ADMIN", "NET_RAW"]     # "BPF" ist optional          env:            - name: SX_ENROLLMENT_KEY              valueFrom:                secretKeyRef:                  name: sxaccess-key                  key: enrollment-key            - name: SX_HOSTNAME              value: k8s-router-prod          volumeMounts:            - name: state              mountPath: /var/lib/sxaccess      volumes:        - name: state          persistentVolumeClaim:            claimName: sxaccess-state
  3. 3

    Sich selbst in die Gruppe platform aufnehmen

    Die Regel aus Schritt 4 lässt die Gruppe platform den API-Server erreichen. Legen Sie die Gruppe gleich mit Ihrem Notebook an: Öffnen Sie People › Members › Ihren Eintrag › Access, tippen Sie platform unter Auto-assigned groups ein, drücken Sie Enter und wählen Sie Save Changes. Wiederholen Sie das für jeden Entwickler. Ihr Notebook kommt sofort hinein, weil die Gruppenweitergabe standardmäßig eingeschaltet ist.

    Sie sehen: platform neben Ihrem Notebook unter Devices.

  4. 4

    Den API-Server veröffentlichen

    Networks › Internal networks › Add internal network: Network Name k8s-prod, dann Add Network. Drei Formulare folgen:

    • Add Resource - Name Kubernetes API; so zeigen die Apps und sxaccess reach list die Ressource an. Address: der Host aus der Zeile server: Ihrer kubeconfig, ohne https:// und Port. Destination Groups: Tippen Sie k8s-prod-api ein und drücken Sie Enter. Wählen Sie dann Add Resource.
    • Create access rule - das Ziel ist bereits Kubernetes API. Wählen Sie platform als Quelle, dann TCP. Klicken Sie in das Port-Feld, tippen Sie den Port aus der Zeile server: ein (443, wenn sie keinen nennt) und drücken Sie Enter: Das Feld zeigt ihn statt All. Wählen Sie dann Create access rule.
    • Add Routing Device - wählen Sie unter Device group k8s-routers, dann Continue. Lassen Sie Masquerade eingeschaltet und wählen Sie Add Routing Device. Die Gruppe deckt auch einen Pod ab, der sich neu registriert.

    Sie sehen: Die Zeile k8s-prod zeigt 1 resource, 1 device und platform. Wie Sie zusätzlich einen Service veröffentlichen, steht unter Erweiterte Konfiguration.

  5. 5

    CI einen eigenen Schlüssel und eine eigene Zugriffsregel geben

    Legen Sie für die Runner einen zweiten Schlüssel an, unter Access › Enrollment keys › Create enrollment key:

    • Name - ci-runners. Make this key reusable - an.
    • Expires in - 90. Ersetzen Sie den Schlüssel vorher: neuer Schlüssel, neues CI-Secret, alter Schlüssel widerrufen.
    • Usage limit - leer. Jeder Job verbraucht eine Nutzung, ein Limit würde CI also irgendwann anhalten.
    • Temporary devices - an: Ein fertiger Runner wird etwa 10 Minuten, nachdem er offline gegangen ist, entfernt. Später lässt sich das nicht mehr einschalten. Allow Extra DNS Labels - aus.
    • Auto-assigned groups - tippen Sie ci-runners ein und drücken Sie Enter.

    Wählen Sie Create enrollment key und hinterlegen Sie den Schlüssel, der nur einmal angezeigt wird, als maskierte geheime CI-Variable namens CI_SXACCESS_KEY. Klicken Sie dann in der Netzwerkliste auf k8s-prod und wählen Sie in der Zeile Kubernetes API Add Access rule. Wählen Sie ci-runners, TCP und denselben Port, dann Create access rule. Mehr bekommen Runner nicht: Ein Build führt Code aus Pull Requests aus.

    Sie sehen: In der Zeile Kubernetes API zeigt die Spalte Access rules 2, und in der Netzwerkliste steht in der Zeile k8s-prod jetzt ci-runners neben platform.

  6. 6

    Jeden Job verbinden und am Ende trennen

    Auf einem VM-Runner, auf dem der Job root oder sudo hat, nehmen Sie den Block unten. Die Startzeilen kommen an den Anfang des Jobs, sxaccess stop in den Schritt, den Ihr CI-System nach jedem Job ausführt, ob erfolgreich oder nicht. CI_JOB_ID steht für die Jobnummer Ihres CI-Systems, damit jeder Runner einen eigenen Namen bekommt.

    Ein Job in einem Container hat keine Dienstverwaltung; nehmen Sie dort den Block nach diesen Schritten, der den Agenten selbst startet und wartet, bis der Agent antwortet. Der Job braucht root, NET_ADMIN und NET_RAW. Wo Ihr CI das nicht gewähren kann, wie bei den meisten geteilten Container-Runnern, nehmen Sie einen VM-Runner.

    Sie sehen: Während der Job läuft, steht der Runner unter Devices als ci- mit der Jobnummer. Etwa 10 Minuten nach Jobende ist er verschwunden.

    shell
    # Zu Beginn des Jobs, auf einem VM-Runner.curl -fsSL https://pkgs.sxaccess.com/install.sh | shSX_ENROLLMENT_KEY="$CI_SXACCESS_KEY" sxaccess start --hostname "ci-$CI_JOB_ID"# Am Ende des Jobs, ob erfolgreich oder nicht: im Nach-Job-Schritt Ihres CI-Systems.sxaccess stop
shell - ein CI-Job in einem Container, statt des Blocks aus Schritt 6
# Zu Beginn eines Jobs in einem Container: als root, mit NET_ADMIN und NET_RAW.# Das Skript kann nach der Installation von sxaccess beim Dienst scheitern.curl -fsSL https://pkgs.sxaccess.com/install.sh | sh || command -v sxaccess# Den Agenten starten, falls noch keiner antwortet, dann bis zu einer Minute auf ihn warten.sxaccess info > /dev/null 2>&1 || { sxaccess agent serve & }n=0; until sxaccess info > /dev/null 2>&1 || [ "$n" -ge 15 ]; do n=$((n + 1)); sleep 1; doneSX_ENROLLMENT_KEY="$CI_SXACCESS_KEY" sxaccess start --hostname "ci-$CI_JOB_ID"# Am Ende des Jobs, ob erfolgreich oder nicht.sxaccess stop
Der Reiter „Enrollment keys“ auf der Seite „Access“ mit Schlüsseln, ihrem Status, den Nutzungen im Verhältnis zu ihrem Limit, der zugeordneten Gruppe und dem Ablaufdatum.
Status, Nutzungen im Verhältnis zum Limit, zugeordnete Gruppe und Ablauf jedes Schlüssels. Ein abgelaufener oder aufgebrauchter Schlüssel registriert nichts; sehen Sie also hier zuerst nach, wenn ein Pod oder Runner nicht beitreten kann.

Prüfen

Prüfen Sie von Ihrem Notebook in platform aus, dann von einem Gerät außerhalb davon, dann aus einem CI-Job.

Erwartetes Ergebnis

kubectl get nodes funktioniert vom Notebook aus, ohne Bastion und ohne öffentlichen Endpunkt. Die SXAccess-App zeigt Kubernetes API unter Resources; mit dem CLI-Agenten zeigt sxaccess reach list die Ressource mit state: Selected.

Dann prüfen, was fehlschlagen sollte

Auf einem Gerät, das weder in platform noch in ci-runners ist, schlägt kubectl get nodes fehl: Der Befehl läuft in ein Timeout, oder der Name wird nicht aufgelöst. Kein zweites Gerät zur Hand? Nehmen Sie platform auf Ihrer Mitgliedsseite heraus, versuchen Sie es und fügen Sie die Gruppe dann wieder hinzu.

Dann CI prüfen

Ein Job, der kubectl ausführt, erreicht den API-Server, und sein Runner verschwindet etwa zehn Minuten nach Jobende aus Devices.

shell - auf Ihrem Notebook, in platform
kubectl get nodes

Fehlersuche

Die ersten drei Zeilen betreffen speziell den Betrieb in einem Cluster.

SymptomWahrscheinliche UrsacheAbhilfe
Es entsteht nie ein PodPod Security Admission weist die Capabilities zurück; die Ereignisse des ReplicaSet melden das.Versehen Sie den Namespace mit der Stufe privileged (Schritt 1). kubectl -n sxaccess describe replicaset
Der Pod startet in einer Schleife neu (CrashLoopBackOff), sein Gerät steht in der Liste, bleibt aber offlineZur Laufzeit fehlt eine Capability, typischerweise NET_RAW: Der Agent registriert sich, kann dann aber seine Schnittstelle nicht hochfahren.Ergänzen Sie NET_ADMIN und NET_RAW. kubectl -n sxaccess logs deploy/sxaccess-router
Bei jedem Neustart erscheint ein neues GerätEs gibt kein persistentes Volume; der Pod registriert sich bei jedem Neustart neu und verbraucht den Schlüssel.Hängen Sie einen PersistentVolumeClaim unter /var/lib/sxaccess ein
kubectl läuft in ein Timeout, obwohl Kubernetes API angezeigt wirdDie Zeile server: nennt einen anderen Host oder Port als die Ressource und ihre Regel.Gleichen Sie beides an. Schritt 4
Ein Cluster-DNS-Name wird nicht aufgelöstDas Routing-Gerät löst Domain-Ressourcen über das DNS des Clusters auf.kubectl -n sxaccess exec deploy/sxaccess-router -- nslookup <name>
Ein CI-Job bricht bei der Installation ab oder meldet cannot reach the SXAccess agentDer Job läuft in einem Container ohne Dienstverwaltung.Nehmen Sie den Container-Block nach Schritt 6
Runner sammeln sich unter Devices anDem CI-Schlüssel fehlt Temporary devices, oder die Jobs endeten vor weniger als 10 Minuten.Legen Sie einen neuen Schlüssel mit dieser Option an, aktualisieren Sie das CI-Secret und widerrufen Sie den alten
Kommen Sie immer noch nicht weiter?Zerlegen Sie die Verbindung Stufe für Stufe.Nachvollziehen, warum eine Verbindung blockiert wird

Erweiterte Konfiguration

Ein Deployment, und Services statt Pods

Ein DaemonSet würde für jeden Knoten, auf den es skaliert, ein Gerät registrieren; der Cluster braucht ein einziges Routing-Gerät. Pod-Adressen werden ständig neu vergeben, ein veröffentlichter Pod-CIDR zeigt also bald auf die falschen Pods: Veröffentlichen Sie Services oder den ganzen Service-CIDR, und setzen Sie vor jeden Pod, den Sie brauchen, einen Service.

Um einen Service zu veröffentlichen, klicken Sie in der Netzwerkliste auf k8s-prod und wählen Add Resource. Geben Sie unter Name einen Namen ein und unter Address die Cluster-IP des Services oder seinen Namen <service>.<namespace>.svc.cluster.local, den das Routing-Gerät auflöst. Wählen Sie dann in der Spalte Access rules der neuen Ressource Add Access rule.

Einen Knotenausfall überstehen

Bei einem Replikat kehrt der Zugriff zurück, sobald das Rescheduling abgeschlossen und das Volume dem Pod gefolgt ist. Ein ReadWriteOnce-Volume auf zonalem Speicher lässt sich nur in seiner eigenen Zone einhängen; der Pod kann also nur dort zurückkommen. Für schnelleres Failover betreiben Sie ein zweites Deployment mit eigenem Volume und Hostnamen in einer anderen Zone: Mit demselben Schlüssel landet es in k8s-routers.

Cluster-Zugriff an das Notebook knüpfen

Hängen Sie an die Regel für platform eine Geräteanforderung: Bei der Cluster-Administration zählt ein konformes Notebook am meisten.

Weitere Cluster und die umgebende VPC

Geben Sie jedem Cluster ein eigenes Netzwerk, einen eigenen Schlüssel, eine eigene Gruppe und einen eigenen Hostnamen. Eine VPC, die ebenfalls erreichbar sein soll, ist ein eigenes Netzwerk mit eigenem Routing-Gerät: siehe AWS EC2 und Cloud-VPCs.

Verwandte Themen