Dieses Kapitel beschreibt den vollständigen Ablauf einer CRUD-Operation in Kubernetes - von der Client-Anfrage bis zur Container-Ausführung. Am Beispiel einer Pod-Erstellung wird der Weg durch alle beteiligten Komponenten verfolgt.
Das
Sequenzdiagramm zeigt die chronologische Interaktion aller Komponenten
während eines Pod-Creation-Requests. Gut zu erkennen ist hier das alle
Komponenten via API Server miteinander kommunizieren.
| Phase | Komponente | Aktion |
|---|---|---|
| 1. Authentication | API Server | Client-Identität validieren |
| 2. Authorization | API Server | RBAC-Permissions prüfen |
| 3. Admission | API Server | Admission Controllers ausführen |
| 4. Validation | API Server | Resource-Spec validieren |
| 5. Persistence | API Server → etcd | Objekt in etcd speichern |
| 6. Watch/Reconciliation | Controller Manager | Gewünschten Zustand durchsetzen |
| 7. Scheduling | Scheduler | Pod einem Node zuweisen |
| 8. Node Assignment | API Server → etcd | Node-Assignment persistieren |
| 9. Kubelet Pull | Kubelet → API Server | Assigned Pods abrufen |
| 10. Runtime Execution | Kubelet → Container Runtime | Container starten |
| 11. Status Reporting | Kubelet → API Server | Container/Pod-Status melden |
Diagramm
der Kommunikationsflüsse zwischen allen beteiligten
Komponenten.
kubectl create -f pod.yaml
# oder
helm install myapp ./chartRequest-Struktur:
Der API Server führt die Authentifizierung durch und routet Requests über die API Aggregation Layer:
API Aggregation Layer:
/apis/apiextensions.k8s.io/v1/apis/metrics.k8s.io/v1beta1| Authentifizierungstyp | Verfahren | Verwendung |
|---|---|---|
| Client Certificates | X.509 Certificate im TLS-Handshake | kubectl mit kubeconfig |
| Bearer Tokens | HTTP Header Authorization: Bearer <token> |
Service Accounts, OIDC |
| Basic Auth | HTTP Header Authorization: Basic <base64> |
Legacy (nicht empfohlen) |
| Bootstrap Tokens | Spezielle Tokens für Node-Registrierung | kubeadm |
| TLS Bootstrapping | CSR-basierte Zertifikatserneuerung | Kubelet Auto-Renewal |
TLS Bootstrapping Ablauf:
Nach erfolgreicher Authentifizierung prüft der API Server die Berechtigung des Clients für die angeforderte Operation.
RBAC-Evaluation:
RBAC-Objekte:
# Beispiel: ClusterRole für Pod-Erstellung
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: pod-creator
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["create", "get", "list"]RBAC-Fehlerbeispiel:
# HTTP 403 Response bei unzureichenden Permissions
status:
code: 403
message: "pods is forbidden: User 'dev' cannot create resource 'pods' in API group '' in the namespace 'default'"
reason: "Forbidden"
details:
group: ""
kind: "pods"
name: "mypod"Mit den validierten Berechtigungen durchläuft die Anfrage nun die Admission Controller Pipeline zur finalen Modifikation und Validierung.
Admission Controller Pipeline:
Diagramm der Admission Controller Pipeline mit Mutating und
Validating Webhooks.
1. Mutating Admission Controllers: Modifizieren die Request
NamespaceLifecycle: Verhindert Erstellung in
terminating NamespacesLimitRanger: Setzt Resource-LimitsDefaultStorageClass: Weist Standard-StorageClass
zu2. Dynamic Admission (Webhooks):
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingAdmissionWebhook
metadata:
name: pod-policy-webhook
webhooks:
- name: mutate.example.com
admissionReviewVersions: ["v1", "v1beta1"]
clientConfig:
service:
name: webhook-service
namespace: webhook-system
path: "/mutate"
rules:
- operations: ["CREATE"]
apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods"]3. Validating Admission Controllers:
ResourceQuota: Prüft Namespace-QuotasPodSecurityPolicy: Durchsetzt Security-PoliciesNetworkPolicy: Validiert Netzwerk-RegelnWebhook-Ablauf:
AdmissionReview an externes
SystemAdmissionResponseNach erfolgreicher Admission Control validiert der API Server die finale Resource-Specification und persistiert das Objekt in etcd.
Schema-Validierung:
Detaillierter Ablauf der API Server Validierung und
etcd-Persistierung.
Optimistic Concurrency Control (OCC):
apiVersion: v1
kind: Pod
metadata:
name: mypod
resourceVersion: "12345" # etcd revision number
spec:
containers: [...]OCC-Ablauf:
resourceVersionresourceVersionresourceVersionetcd-Persistierung:
Key Structure:
/registry/{group}/{version}/{kind}/{namespace}/{name}
/registry/pods/default/mypod
/registry/deployments/kube-system/corednsAtomic Operations: Compare-And-Swap für Konsistenz
Watch-Events: Änderungen an alle Watch-Clients propagieren
{
"type": "ADDED",
"object": {...},
"resourceVersion": "12346"
}Nach erfolgreicher Persistierung in etcd reagieren nun die Controller über ihre Watch-Mechanismen - eine eventbasierte Reaktion auf Watch-Streams vom API Server.
Watch-Mechanismus:
// Controller abonniert Watch-Events für spezifische Ressourcen
watchInterface, err := clientset.CoreV1().Pods(namespace).Watch(context.TODO(), metav1.ListOptions{})
for event := range watchInterface.ResultChan() {
switch event.Type {
case watch.Added:
controller.handlePodAdded(event.Object.(*v1.Pod))
case watch.Modified:
controller.handlePodModified(event.Object.(*v1.Pod))
case watch.Deleted:
controller.handlePodDeleted(event.Object.(*v1.Pod))
}
}Controller Loop:
for {
desired := getDesiredState()
current := getCurrentState()
if desired != current {
reconcile(desired, current)
}
sleep(reconciliationInterval)
}
Diagramm der Controller Watch-Streams und Reconciliation
Loops.
ReplicaSet Controller Beispiel:
Parallel zu den Controller-Aktionen reagiert der Scheduler
eventbasiert auf Watch-Streams für ungeschedulte Pods
(Phase Pending ohne nodeName).
Scheduler Watch-Pattern:
// Scheduler überwacht Pods ohne Node-Assignment
watchInterface := clientset.CoreV1().Pods("").Watch(context.TODO(), metav1.ListOptions{
FieldSelector: "spec.nodeName=", // Pods ohne nodeName
})Scheduling-Algorithmus:
Detaillierter Ablauf des Scheduling-Algorithmus mit Filtering und
Scoring.
Filtering Phase - Ungeeignete Nodes ausschließen:
Scoring Phase - Verbleibende Nodes bewerten:
Binding - Besten Node auswählen und Pod zuweisen:
# Pod-Update mit Node-Assignment
spec:
nodeName: worker-node-1
schedulerName: default-scheduler
status:
phase: PendingMit der Scheduler-Entscheidung wird das Node-Assignment über den API Server in etcd persistiert, wodurch der zugewiesene Kubelet über seine Watch-Streams aktiviert wird.
Node-Assignment-Persistierung:
spec:
nodeName: worker-node-1 # Scheduler-Entscheidung
status:
phase: Pending
conditions:
- type: PodScheduled
status: "True"
reason: "Scheduled"Der Kubelet auf dem zugewiesenen Node erkennt über seinen kontinuierlichen Pull-Mechanismus die neue Pod-Zuweisung und startet die Container-Orchestrierung.
Pull-Modell vs. Push-Modell:
Kubelet Control Loop:
Sync Loop (jede Sekunde):
assignedPods := apiserver.GetPodsAssignedToNode(nodeName)
runningPods := kubelet.GetRunningPods()
kubelet.SyncPods(assignedPods, runningPods)Pod Lifecycle Event Generator (PLEG):
Der Pod Lifecycle Event Generator (PLEG) erkennt Zustandsänderungen durch Container-Events und stellt sicher, dass der Kubelet umgehend auf Container-State-Transitions reagiert.
// PLEG überwacht Container-Runtime für State-Änderungen
for event := range runtime.GetContainerEvents() {
switch event.Type {
case ContainerStarted:
kubelet.HandleContainerStarted(event.PodUID, event.ContainerID)
case ContainerDied:
kubelet.HandleContainerDied(event.PodUID, event.ContainerID)
}
}cAdvisor Integration:
// Sammelt Container-Metriken und Resource-Usage
containerStats := cAdvisor.GetContainerStats(containerID)
kubelet.UpdatePodStatus(podUID, containerStats)Pod Sync Ablauf:
/var/lib/kubelet/pods/{pod-uid})Nach der Kubelet-Vorbereitung übernimmt die Container Runtime die eigentliche Container-Orchestrierung mit dem Pod Sandbox Lifecycle.
Container Runtime Implementierungen:
Zustandsdiagramm: PodPending → PodRunning → PodSucceeded/Failed →
Terminated
Pod Sandbox Lifecycle:
1. Pod Sandbox Creation (Pause Container):
# Pause Container wird zuerst gestartet
crictl runp pod-sandbox-config.json
# Output: sandbox-id (z.B. abc123...)Pause Container Zweck:
2. Container Runtime Interface (CRI):
Image Pull:
crictl pull docker.io/nginx:latestContainer Creation im Pod Sandbox:
{
"pod_sandbox_id": "abc123...",
"config": {
"image": {
"image": "docker.io/nginx:latest"
},
"command": ["/docker-entrypoint.sh"],
"args": ["nginx", "-g", "daemon off;"],
"envs": [{"key": "PATH", "value": "/usr/local/sbin:/usr/local/bin"}],
"mounts": [{"container_path": "/var/log", "host_path": "/var/log/pods/..."}],
"linux": {
"resources": {
"cpu_quota": 100000,
"memory_limit_in_bytes": 268435456
},
"security_context": {
"run_as_user": {"value": 1000}
}
}
}
}3. Container Start Sequence:
Mit laufenden Containern beginnt das kontinuierliche Status-Reporting des Kubelet an den API Server, wodurch der Request-Lifecycle in einen dauerhaften Monitoring-Zyklus übergeht.
Kubelet → API Server Status Updates:
status:
phase: Running
conditions:
- type: Ready
status: "True"
- type: ContainersReady
status: "True"
containerStatuses:
- name: nginx
state:
running:
startedAt: "2024-01-01T10:00:00Z"
ready: true
restartCount: 0
image: "docker.io/nginx:latest" Kompletter
Pod-Status-Lifecycle von Pending bis Running/Succeeded/Failed.
| Operation | Typische Latenz | Limiting Factor |
|---|---|---|
| API Request → etcd Write | 10-50ms | etcd Write Latency |
| Controller Reconciliation | 100ms-5s | Controller Sync Interval |
| Scheduler Decision | 50-200ms | Node Count, Constraints |
| Kubelet Pod Sync | 1-10s | Image Pull Time |
| Container Startup | 100ms-30s | Application Init Time |
Retry-Mechanismen:
Pending, erneute
Scheduling-VersucheSpezifische Fehlerszenarien:
| Status | Grund | Ursache | Maßnahme |
|---|---|---|---|
| OOMKilled | Memory-Limit überschritten | Container verbraucht mehr RAM als erlaubt | Memory-Limits erhöhen, Application optimieren |
| CrashLoopBackOff | Wiederholte Container-Exits | Application-Fehler, Config-Probleme | Logs prüfen, Dependencies validieren |
| ImagePullBackOff | Image nicht verfügbar | Registry-Auth, Netzwerk, falscher Tag | Credentials prüfen, Image-Tag validieren |
| Pending | Unschedulable | Keine passenden Nodes | Ressourcen hinzufügen, Constraints lockern |
| FailedMount | Volume-Probleme | PV nicht verfügbar, Permission-Fehler | Storage-Klasse prüfen, Node-Permissions |
status:
containerStatuses:
- name: app
state:
terminated:
reason: "OOMKilled"
exitCode: 137
restartCount: 3Ablauf:
Always,
OnFailure, Never)status:
containerStatuses:
- name: app
state:
waiting:
reason: "CrashLoopBackOff"
message: "back-off 5m0s restarting failed container"
restartCount: 10Backoff-Strategie:
Restart Delays: 10s, 20s, 40s, 80s, 160s, 300s (max)
Ursachen:
status:
containerStatuses:
- name: app
state:
waiting:
reason: "ImagePullBackOff"
message: "Back-off pulling image 'invalid-registry/app:latest'"Retry-Logic:
status:
conditions:
- type: PodScheduled
status: "False"
reason: "Unschedulable"
message: "0/3 nodes are available: insufficient cpu"Häufige Scheduling-Failures:
Monitoring-Points:
/var/log/audit.log)scheduler_pending_pods)kubectl describe pod)crictl stats)kubelet_pleg_relist_duration_seconds