Voraussetzung: ein Cluster mit oc login
als Admin, Namespace library. Das User-Workload-Monitoring muss eingeschaltet
sein (Schritt 3 zeigt wie).
1 oc get co lesen
Jede Kern-Fähigkeit – auth, ingress, dns, image-registry, monitoring,
network, etcd, kube-apiserver… – ist ein ClusterOperator-Objekt,
rund 30 Stück, verwaltet vom Cluster Version Operator.
Jede Kern-Fähigkeit des Clusters – Auth, Ingress, DNS, Registry, Monitoring, Netzwerk, etcd, kube-apiserver – ist ein ClusterOperator-Objekt, verwaltet von seinem Operator. Jedes meldet drei Zustände: Available (nutzbar?), Degraded (läuft, aber ungesund?), Progressing (mitten in einer Änderung?). oc get co ist die Gesundheits-Ampel des Clusters.
ClusterOperator-Objekt mit drei Conditions: Available (nutzbar? False = Ausfall), Degraded (läuft, aber nicht im Soll? True = untersuchen), Progressing (mitten in einer Änderung? normal beim Upgrade). oc get co zeigt sie alle – alles True/False/False = gesund. Ein Degraded-Operator blockiert Upgrades. Man liest ihn über die message → den Operand-Namespace → die Pod-Logs.- jede Kern-Fähigkeit (auth, ingress, dns, image-registry, monitoring, network, etcd, kube-apiserver…) ist ein
ClusterOperator-Objekt – rund 30 Stück, verwaltet vom CVO - die volle Liste mit Operand-Namespace und typischen Pods steht in der Tabelle oben – das sind zugleich die Default-Pods, die
oc get pods -Aauf jedem frischen Cluster zeigt, bevor auch nur eine eigene App läuft - auf einer Bare-Metal-SNO wie dieser sind
machine-api,machine-approver,cloud-controller-manager,cloud-credential,control-plane-machine-setundbaremetalzwarAvailable, tun aber praktisch nichts – sie sind für Cloud- oder IPI-Installer gedacht, die hier nicht laufen Available: ist die Funktion nutzbar?False= Ausfall (z. B.ingressFalse→ keine Route erreichbar)Degraded: die Funktion geht noch, ist aber nicht im Sollzustand –True= untersuchen, wird oft zuAvailable: FalseProgressing: der Operator rollt gerade etwas aus – normal beim Upgrade, aber stundenlangTrue= es hängt- gesund im Ruhezustand:
Available=True,Degraded=False,Progressing=False.Upgradeable=False= erst etwas tun, dann upgraden - der CVO (G5) blockiert Upgrades, solange irgendein CO
Degradedist - einen kaputten CO lesen:
oc get co→ wer ist nichtTrue/False/False? →oc describe co <name>für diemessage - dann in den
Related Objects-Namespace:oc get pods -n <operand-ns>,oc logsdes Operator-Pods,oc get events - hier fängt jede „der Cluster fühlt sich komisch an“-Untersuchung an
- OLM-Operatoren (Block D) sind eine separate Ebene – sie erscheinen nicht in
oc get co - Alarme dazu:
ClusterOperatorDown/ClusterOperatorDegradedan Alertmanager (G1) - nach einem
sno.ps1 upstehtimage-registryoft aufProgressingoderDegraded– der Operator hängt an einer Leader-Lease von vor dem Snapshot.sno-wsl.sh remediate(imupeingebaut) räumt das - Bibliothek: schlägt ein
helm upgrademit wirren Fehlern fehl, ist der erste Blickoc get co– istingressoderauthenticationDegraded, weil der Cluster nach dem Restore noch nicht durch ist? - OCP-Unterschied: identisch – ClusterOperators sind Kern-OpenShift, die Menge ist in OKD und OCP fast gleich
oc get co
oc get co -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.conditions[?(@.type=="Available")].status}{"\t"}{.status.conditions[?(@.type=="Degraded")].status}{"\n"}{end}'
| Bedingung | bedeutet |
|---|---|
| Available | ist die Funktion nutzbar? False = Ausfall (z. B. ingress False → keine Route erreichbar) |
| Degraded | die Funktion geht noch, ist aber nicht im Sollzustand – True heißt untersuchen, wird oft zu Available: False |
| Progressing | der Operator rollt gerade etwas aus – normal beim Upgrade, stundenlang True heißt es hängt |
| Upgradeable | False = erst etwas tun, dann upgraden |
gesund im RuhezustandAvailable=True,
Degraded=False, Progressing=False. Der CVO blockiert Upgrades
(Schritt 7), solange irgendein CO Degraded ist. OLM-Operatoren (Block D)
sind eine separate Ebene – sie erscheinen nicht in oc get co.
2 Einen kaputten ClusterOperator debuggen
Hier fängt jede „der Cluster fühlt sich komisch an“-Untersuchung an.
# wer ist nicht True/False/False? oc get co | grep -v "True.*False.*False" # die message lesen: oc describe co image-registry # dann in den Related-Objects-Namespace: oc get pods -n openshift-image-registry oc logs deployment/cluster-image-registry-operator -n openshift-image-registry --tail=50 oc get events -n openshift-image-registry --sort-by=.lastTimestamp | tail -20
nach sno.ps1 upsteht
image-registry oft auf Progressing oder Degraded –
der Operator hängt an einer Leader-Lease von vor dem Snapshot.
sno-wsl.sh remediate (in sno.ps1 up eingebaut) räumt das
automatisch auf.
Alarme zum selben Zustand landen im Alertmanager: ClusterOperatorDown /
ClusterOperatorDegraded (Schritt 3).
3 Der Monitoring-Stack
Zwei getrennte Stacks: Plattform-Monitoring (immer an) und User-Workload-Monitoring (opt-in).
OpenShift bringt zwei getrennte Monitoring-Stacks mit. Der Plattform-Stack läuft immer und überwacht die Control Plane, die Nodes und die Operatoren. Der User-Workload-Stack ist opt-in und überwacht deine Apps – du meldest sie mit einem ServiceMonitor an. Beide zeigen im Observe-Tab und alarmieren über Alertmanager.
openshift-monitoring) läuft immer und scrapt Control Plane, Nodes und Operatoren; Thanos vereinheitlicht die Abfrage, Alertmanager leitet die Alarme. Das User-Workload-Monitoring ist opt-in (enableUserWorkload: true) und gibt dir einen eigenen Prometheus – du meldest deine App mit einem ServiceMonitor an und schreibst eigene PrometheusRule-Alarme. Beides erscheint im Observe-Tab.- OpenShift hat zwei getrennte Stacks: Plattform-Monitoring (immer an) und User-Workload-Monitoring (opt-in)
- Plattform (
openshift-monitoring): Prometheus-Paar scrapt Control Plane,node-exporter-DaemonSet,kube-state-metricsund jeden Operator – nicht abschaltbar, nur tunen - Thanos-Querier fächert eine Abfrage über alle Prometheus-Instanzen, Thanos-Ruler wertet die Regeln aus
- Alertmanager entprellt, gruppiert und leitet Alarme an
receivers: PagerDuty, Slack, Webhook, E-Mail - User-Workload aktivieren: die ConfigMap
cluster-monitoring-configmitenableUserWorkload: true - du meldest deine App an mit einem
ServiceMonitor(oderPodMonitor): Label-Selektor, Pfad, Port, Intervall - eigene Alarme: ein
PrometheusRule-CR im Namespacelibrary– etwaup{job="catalog-service"} == 0für 5 min, über denselben Alertmanager wie die Plattform - Rechte: die Rolle
monitoring-editim Namespace erlaubt eigene Monitore und Regeln - der Observe-Tab der Konsole: Metrics (PromQL), Alerts (+ Silences), Dashboards, Targets (up/down)
- auf der SNO: der User-Workload-Prometheus bekommt per Default keine PVC – nach einem
sno.ps1 upsind die App-Metriken von vor dem Snapshot weg, einevolumeClaimTemplateimuser-workload-monitoring-confighält dagegen - was schiefgeht:
TargetDownbei falschem Selektor oder Port, hohe Kardinalität frisst RAM, ein unkonfigurierterreceiverschluckt Alarme - Bibliothek: ein
ServiceMonitorje Spring-Dienst auf/actuator/prometheus(Micrometer) – die Bitnami-Charts von Postgres, Kafka und Redis bringen je einenmetrics-Exporter mit, den ein eigenerServiceMonitorabholt - Merksatz:
ServiceMonitor= „scrap diese Pods“,PrometheusRule= „alarmiere bei diesem Ausdruck“ - auf SNO ohne HA: der ganze Stack läuft (ServiceMonitor, Observe-Tab, Alertmanager) – nur das Prometheus-Paar und echte Ausfallsicherheit fehlen
- OCP-Unterschied: identisch – der Stack ist Kern-OpenShift. Reines Kubernetes braucht den kube-prometheus-Stack von Hand
openshift-monitoring: Prometheus-Paar scrapt die Control Plane, jeden Operator, node-exporter – nicht abschaltbar, nur tunencluster-monitoring-config – erst danach zählen eigene ServiceMonitorecat <<'YAML' | oc apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: cluster-monitoring-config
namespace: openshift-monitoring
data:
config.yaml: |
enableUserWorkload: true
YAML
oc get pods -n openshift-user-workload-monitoring -w
4 Einen ServiceMonitor live anlegen
Anmelden bei Prometheus, dann eine eigene Alarmregel.
oc create deployment demo-metrics -n library --image=registry.access.redhat.com/ubi9/httpd-24
oc expose deployment demo-metrics -n library --port=8080
cat <<'YAML' | oc apply -f -
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: demo-metrics
namespace: library
spec:
selector:
matchLabels: { app: demo-metrics }
endpoints:
- port: 8080-tcp
path: /metrics
interval: 30s
YAML
cat <<'YAML' | oc apply -f -
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: demo-metrics-alerts
namespace: library
spec:
groups:
- name: demo.rules
rules:
- alert: DemoTargetDown
expr: up{job="demo-metrics"} == 0
for: 5m
labels: { severity: warning }
annotations: { summary: "demo-metrics antwortet nicht" }
YAML
oc get servicemonitor,prometheusrule -n library
Im Konsolen-Tab Observe: Metrics (PromQL),
Alerts (+ Silences), Dashboards,
Targets (up/down – genau hier sieht man, ob der ServiceMonitor
wirklich scrapt). Rechte dafür: die Rolle monitoring-edit im Namespace.
Merksatz: ServiceMonitor = „scrap diese Pods“,
PrometheusRule = „alarmiere bei diesem Ausdruck“.
5 Storage: PVC, StorageClass, RWO/RWX
Ein PersistentVolumeClaim ist der Antrag, eine
StorageClass die clusterweite Vorlage.
Ein Pod will einen Datenträger – er stellt einen PersistentVolumeClaim (den Antrag). Eine StorageClass ist die Vorlage, nach der ein PersistentVolume dynamisch entsteht und an den PVC gebunden wird. Der Zugriffsmodus entscheidet, ob mehrere Pods gleichzeitig schreiben dürfen – und die meiste Blockspeicherung kann das nicht.
PVC verlangt Größe und Zugriffsmodus. Die StorageClass sagt, welcher CSI-Treiber mit welchen Parametern ein PV dynamisch erzeugt und daran bindet. volumeBindingMode: WaitForFirstConsumer wartet, bis der Pod geschedult ist, damit das PV in dessen Zone landet. Der Zugriffsmodus entscheidet: RWO = ein Node, RWX = viele – und RWX braucht ein Netzwerk-Dateisystem, das die meiste Blockspeicherung nicht bietet.- ein
PersistentVolumeClaimist der Antrag (Größe,accessModes, optionalstorageClassName) – namespaced - eine
StorageClassist die clusterweite Vorlage:provisioner(der CSI-Treiber, kommt als Operator),reclaimPolicy,volumeBindingMode,allowVolumeExpansion - dynamisches Provisioning erzeugt ein
PersistentVolumeund bindet es an den PVC (Bound) – oder es bindet an ein passendes statisches PV volumeBindingMode: WaitForFirstConsumerwartet, bis der Pod geschedult ist – sonst landet das PV in der falschen Zone und der Pod scheduled nie (B6)reclaimPolicy: Deletelöscht das PV mit dem PVC,Retainbehält es (Released) für manuelle RettungRWO(ein Node zur Zeit) – die meiste Blockspeicherung.RWOP= genau ein PodRWX(viele Nodes schreibend) braucht ein Netzwerk-Dateisystem (NFS, CephFS, ODF) – AWS EBS, Hetzner Volume, iSCSI können es nicht- ein
Deploymentmit >1 Replica an einem RWO-PVC → nur ein Pod läuft, der Rest bleibtPending VolumeSnapshot+VolumeSnapshotClassfür Point-in-Time-Kopien (Basis für Velero-Backups, E4)- PVC vergrößern geht nur größer, nie kleiner, und nur bei
allowVolumeExpansion - auf der SNO: ein
local-path-Provisioner statt echtem CSI (Daten am Node, keine HA). Sein SA braucht die SCChostmount-anyuid(A7), und das Basis-Verzeichnis musschcon -t container_file_tbekommen – SCOS-SELinux lässt sonst auchrootdort nicht schreiben - Bibliothek: Postgres, Kafka und Redis wollen je ein RWO-Block-PVC über ihre StatefulSets (B1)
- Stolperstein: der image-registry-Operator will eine
RWX-PVC,local-pathkann nurRWO– dieimage-registry-storage-PVC von Hand alsRWOvorab anlegen, sonst startet die Registry nicht - ein geteiltes Verzeichnis (etwa Buchcover für alle
catalog-service-Replicas) bräuchteRWX– mitlocal-pathunmöglich, also Objekt-Storage (MinIO, S3) oder ein NFS-Volume - OCP-Unterschied: identisch – CSI ist Kubernetes. OpenShift Data Foundation (Ceph) ist ein Zusatzprodukt für RWX und Objektspeicher im Cluster
| Begriff | ist |
|---|---|
PVC | Antrag: Grösse, accessModes, optional storageClassName – namespaced |
StorageClass | provisioner (der CSI-Treiber), reclaimPolicy, volumeBindingMode, allowVolumeExpansion |
RWO | ein Node zur Zeit – die meiste Blockspeicherung. RWOP = genau ein Pod |
RWX | viele Nodes schreibend – braucht ein Netzwerk-Dateisystem (NFS, CephFS, ODF). Cloud-Blockspeicher (EBS, Hetzner Volume) kann das nicht |
volumeBindingMode: WaitForFirstConsumer wartet, bis der Pod geschedult ist
– sonst landet das PV in der falschen Zone und der Pod scheduled nie (B6).
reclaimPolicy: Delete löscht das PV mit dem PVC, Retain
behält es (Released) für manuelle Rettung.
6 Ein PVC anlegen und binden sehen
Ein Deployment mit zwei Replicas an einem RWO-PVC – und live sehen, warum nur ein Pod läuft.
cat <<'YAML' | oc apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: demo-data
namespace: library
spec:
accessModes: [ReadWriteOnce]
resources: { requests: { storage: 1Gi } }
YAML
oc get pvc demo-data -n library -w
# Pending -> Bound (mit WaitForFirstConsumer erst, sobald ein Pod ihn nutzt)
oc get pv $(oc get pvc demo-data -n library -o jsonpath='{.spec.volumeName}')
Falleein Deployment mit
replicas: 2, das denselben RWO-PVC mountet, lässt nur den ersten Pod
laufen – der zweite bleibt dauerhaft Pending
(oc describe pod zeigt multi-attach error oder
„volume is already used“).
PVC vergrössern geht nur grösser, nie kleiner, und nur bei
allowVolumeExpansion: true an der StorageClass.
VolumeSnapshot/VolumeSnapshotClass sind die Basis für
Point-in-Time-Kopien (Velero-Backups, E4).
7 Cluster-Upgrades
Ein Upgrade ist ein Release-Image – der Cluster Version Operator (CVO) gleicht den Cluster darauf ab: erst die ClusterOperatoren in Abhängigkeitsreihenfolge, dann die Nodes (G4).
Ein OpenShift-Upgrade ist ein Ziel: ein Release-Image, das die Manifeste aller Komponenten enthält. Der Cluster Version Operator (CVO) gleicht den ganzen Cluster darauf ab – er geht die ClusterOperatoren der Reihe nach durch, dann rollt der MCO die Nodes. Du wählst nur den Channel und das Ziel, den Rest macht der CVO. Ein Rollback gibt es nicht.
CVO gleicht den ganzen Cluster auf ein Release-Image ab – er hebt die ClusterOperatoren in Reihenfolge, dann rollt der MCO die Nodes (G4). Du wählst den Channel (stable-4.16, eus-4.x…) und das Ziel mit oc adm upgrade --to=. Vorbedingung: kein Degraded-ClusterOperator (G6), admin-acks bestätigt. Ein Rollback wird nicht unterstützt – man testet in einer niedrigeren Umgebung.- ein Upgrade ist ein Release-Image – ein Digest mit den Manifesten jeder Komponente und den Operator-Images
- der
Cluster Version Operator(CVO) gleicht den Cluster darauf ab: erst die ClusterOperatoren in Abhängigkeitsreihenfolge, dann rollt der MCO die Nodes (G4) - Channels:
stable-4.16(empfohlen),fast,candidate, dazueus-4.x– jeder Channel ist ein Graph erlaubter Pfade, immer nur ein Minor auf einmal oc adm upgradezeigt aktuelle Version und verfügbare Ziele,oc adm upgrade --to=4.16.7startet- Vorbedingung: kein ClusterOperator
Degraded(G6) – sonst blockiert der CVO admin-acksbestätigen für bekannte Breaking Changes zwischen Minors, deprecated APIs prüfen (APIRemovedInNextReleaseInUse-Alarm)- PodDisruptionBudgets müssen erfüllbar sein und genug Kapazität für
drainvorhanden - kein Rollback – nur vorwärts, in einer niedrigeren Umgebung testen
- nach dem Start nicht abbrechen – ein halb-upgradeter Cluster ist der schlechteste Zustand
- Fortschritt:
oc get clusterversion -w,oc get co(was ist nochProgressing), oder die Console unter Cluster Settings - etcd-Backup vor dem Upgrade (G7) · der Node-Teil ist G4 · die Health-Ampel ist G6
- real auf der SNO: OKD-SCOS-Update-Graphen sind community-gepflegt und dünn – oft ist der Weg nicht
oc adm upgrade, sondernsno.ps1 destroyund dannsno.ps1 installmit der neueren Version (der Rebuild aus dem Plan) - wenn doch ein Upgrade: erst
sno.ps1 downals Sicherung, dannoc adm upgrade --to, rund 40 min – der eine Node rebootet, die API ist während des Control-Plane-Reboots kurz weg - auf SNO ohne HA: ein
oc adm upgradeläuft und der CVO geht die COs durch – nur der EUS-Worker-Pool-Tanz braucht Worker - OCP-Unterschied: OCP hat Subscription-Channels und OpenShift Update Service (disconnected). OKD nutzt community-gepflegte Update-Graphen
oc get clusterversion oc adm upgrade # zeigt aktuelle Version und verfuegbare Ziele oc adm upgrade --to=4.16.7 oc get clusterversion -w
Vorbedingung: kein ClusterOperator Degraded (Schritt 1), sonst
blockiert der CVO. admin-acks bestätigen für bekannte Breaking Changes
zwischen Minors, deprecated APIs vorher prüfen. Kein Rollback –
nur vorwärts. Nach dem Start nicht abbrechen, ein halb-upgradeter Cluster ist der
schlechteste Zustand.
real auf der SNOOKD-SCOS-Update-Graphen
sind community-gepflegt und dünn – oft ist der Weg nicht oc adm upgrade,
sondern sno.ps1 destroy und dann install mit der neueren Version
(der Rebuild aus dem Plan). Wenn doch: erst sno.ps1 down als Sicherung, dann
oc adm upgrade --to, rund 40 Min – der eine Node rebootet, die API ist
während des Control-Plane-Reboots kurz weg.
OCP-Unterschied: OCP hat Subscription-Channels und den OpenShift Update Service (disconnected). OKD nutzt community-gepflegte Update-Graphen. etcd-Backup vorher (G7).
8 Typische Fallen
| Symptom | meist |
|---|---|
| Upgrade startet nicht | ein ClusterOperator ist Degraded – erst Schritt 2 |
| Targets zeigen „down“ | falscher Port/Selektor im ServiceMonitor, oder eine NetworkPolicy sperrt den Scrape (F2) |
| zweiter Replica bleibt Pending | RWO-PVC von zwei Pods gleichzeitig verlangt – braucht RWX oder nur 1 Replica |
| PV in falscher Zone | volumeBindingMode: Immediate statt WaitForFirstConsumer |
| hohe RAM-Last durch Prometheus | zu hohe Kardinalität in eigenen Metrik-Labels |
9 Wie die Bibliothek es macht
| Baustein | real |
|---|---|
| Monitoring | ein ServiceMonitor je Spring-Dienst auf /actuator/prometheus (Micrometer) – die Bitnami-Charts von Postgres, Kafka und Redis bringen je einen metrics-Exporter mit, den ein eigener ServiceMonitor abholt |
| Storage | Postgres, Kafka und Redis wollen je ein RWO-Block-PVC über ihre StatefulSets – auf der SNO ein local-path-Provisioner statt echtem CSI (Daten am Node, keine HA) |
| Storage-Stolperstein | der image-registry-Operator will eine RWX-PVC, local-path kann nur RWO – die image-registry-storage-PVC von Hand als RWO vorab anlegen, sonst startet die Registry nicht |
| SNO ohne HA | bei G1/G3/G6 läuft der ganze Stack normal – nur das Prometheus-Paar und echte Ausfallsicherheit fehlen. Bei G5 fehlt vor allem der EUS-Worker-Pool-Tanz, den es ohne Worker-Nodes nicht gibt |
Fehlschlag-Reflex: schlägt ein helm upgrade mit wirren Fehlern fehl, ist
der erste Blick oc get co – ist ingress oder
authentication Degraded, weil der Cluster nach einem sno.ps1 up
noch nicht ganz durch ist?
+ Die Kurzfassung
WaitForFirstConsumer vor Zonen-Fallenoc adm upgrade