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.
| Was | Wozu | |
|---|---|---|
| Erforderlich | Die Rolle Owner oder Admin im Dashboard | Für die Registrierungsschlüssel und Ihre Mitgliedsseite |
| Erforderlich | Zugriff per kubectl auf den Cluster, so wie Sie ihn heute erreichen, mit dem Recht, einen Namespace anzulegen, mit einem Label zu versehen und darin bereitzustellen | Die 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 |
| Erforderlich | Das Image unter Add device › Docker | Es startet den Agenten und registriert ihn |
| Erforderlich | Ein ReadWriteOnce-Volume mit 1 GiB | Es bewahrt die Identität des Geräts über Neustarts hinweg |
| Erforderlich | Die Zeile server: Ihrer kubeconfig | Der API-Server wird unter diesem Host und Port veröffentlicht |
| Erforderlich | Ein angemeldetes Notebook mit der SXAccess-App oder der CLI und mit kubectl | Für den Test |
| Optional | CI-Jobs, die als root oder mit sudo laufen, auf VMs oder in Containern mit NET_ADMIN und NET_RAW | Schritte 5 und 6 |
Bevor Sie beginnen
Ein Pod spricht für den Cluster.
Warum ein Deployment statt eines DaemonSets und Services statt des Pod-CIDR, steht unter Erweiterte Konfiguration.
Einrichtung
- 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-routersein 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
kubectlden 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. SobaldEnrollment 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.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} - Name -
- 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 Siekubectl apply -f sxaccess-router.yamlaus. Setzt der Befehl dort weitere Variablen mit-e, übernehmen Sie sie unterenv.Das Image startet den Agenten und führt
sxaccess startaus, mit dem Schlüssel ausSX_ENROLLMENT_KEYund dem Namen ausSX_HOSTNAME.BPFist optional.strategy: Recreatebeendet 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 infomitConnected, undk8s-router-prodsteht unter Devices ink8s-routers.Runningallein beweist nicht, dass sich der Pod registriert hat.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
Sich selbst in die Gruppe platform aufnehmen
Die Regel aus Schritt 4 lässt die Gruppe
platformden API-Server erreichen. Legen Sie die Gruppe gleich mit Ihrem Notebook an: Öffnen Sie People › Members › Ihren Eintrag › Access, tippen Sieplatformunter 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:
platformneben Ihrem Notebook unter Devices. - 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 undsxaccess reach listdie Ressource an. Address: der Host aus der Zeileserver:Ihrer kubeconfig, ohnehttps://und Port. Destination Groups: Tippen Siek8s-prod-apiein und drücken Sie Enter. Wählen Sie dann Add Resource. - Create access rule - das Ziel ist bereits
Kubernetes API. Wählen Sieplatformals Quelle, dann TCP. Klicken Sie in das Port-Feld, tippen Sie den Port aus der Zeileserver: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-prodzeigt1 resource,1 deviceundplatform. Wie Sie zusätzlich einen Service veröffentlichen, steht unter Erweiterte Konfiguration. - Add Resource - Name
- 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-runnersein 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 aufk8s-prodund wählen Sie in der ZeileKubernetes APIAdd Access rule. Wählen Sieci-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 APIzeigt die Spalte Access rules2, und in der Netzwerkliste steht in der Zeilek8s-prodjetztci-runnersnebenplatform. - Name -
- 6
Jeden Job verbinden und am Ende trennen
Auf einem VM-Runner, auf dem der Job root oder
sudohat, nehmen Sie den Block unten. Die Startzeilen kommen an den Anfang des Jobs,sxaccess stopin den Schritt, den Ihr CI-System nach jedem Job ausführt, ob erfolgreich oder nicht.CI_JOB_IDsteht 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_ADMINundNET_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.# 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
# 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
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.
kubectl get nodesFehlersuche
Die ersten drei Zeilen betreffen speziell den Betrieb in einem Cluster.
| Symptom | Wahrscheinliche Ursache | Abhilfe |
|---|---|---|
| Es entsteht nie ein Pod | Pod 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 offline | Zur 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ät | Es 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 wird | Die 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öst | Das 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 agent | Der Job läuft in einem Container ohne Dienstverwaltung. | Nehmen Sie den Container-Block nach Schritt 6 |
| Runner sammeln sich unter Devices an | Dem 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.

