Skip to content

Upgrade Runbook — OCP 4.14 → 4.18 (Control Plane Only)

Upgrade Runbook — OCP 4.14 → 4.18 (Control Plane Only)

Procedura operativa per il salto OpenShift 4.14 → 4.16 → 4.18 con strategia Control Plane Only (EUS-to-EUS via versioni intermedie con MCP worker/infra/storage in pause).

Riferimento per cluster con ODF/OpenShift Data Foundation, Loki, Quay Operator, Service Mesh v2, ACM. Ogni sezione ha comandi puntuali e link ai KCS Red Hat rilevanti.

Contesto: strategia EUS-to-EUS. Il salto 4.14 → 4.18 non è diretto: si passa da 4.15 CP-only (worker restano su 4.14) → 4.16.z full → 4.17 CP-only → 4.18.z full. È l’unico path supportato per saltare release non-EUS.


Path di upgrade

OPENSHIFT · UPGRADE PATH EUS-to-EUS 4.14 → 4.18 Control Plane Only, worker/infra/storage in pause fino al 4.18.z finale 4.14.z EUS di partenza channel stable-4.14 full cluster 4.15.z step intermedio channel eus-4.16 CP-only · pause MCP 4.16.z EUS intermedio unpause MCP · ODF 4.16 full cluster 4.17.z step intermedio channel eus-4.18 CP-only · pause MCP 4.18.z EUS target unpause · ODF 4.18 full cluster NOTE OPERATIVE • Worker/infra/storage MCP restano su 4.14 → 4.16 tutta la fase 4.15, poi passano da 4.16 direttamente. Idem 4.17 → 4.18. • Il salto worker "diretto" 4.16 → 4.18 è supportato in pause-MCP durante la fase 4.17 CP-only. • MAI mettere in pause il MCP storage (rompe PDB dei pod OSD → Ceph fuori quorum).

1. Documentazione Red Hat di riferimento

1.1 Updating clusters (guida ufficiale)

1.2 Pre-check requirement

1.3 Tool interattivi (utilizzi in fase pianificazione)

1.4 Deprecated API

Prima del salto 4.15 → 4.16 il cluster deve essere “libero” da API deprecate in Kubernetes 1.29.

Ack obbligatorio prima di procedere:

Terminal window
oc -n openshift-config patch cm admin-acks \
--patch '{"data":{"ack-4.15-kube-1.29-api-removals-in-4.16":"true"}}' \
--type=merge

2. Client oc — versione allineata

Prima di partire, aggiorna il client oc sul bastion alla stessa minor version del target (o superiore).

Su RHEL 8.x, se il repo standard non ha ancora la nuova versione:

Terminal window
# Se il bastion è dietro proxy
export http_proxy=proxy.example.com:8080
export https_proxy=proxy.example.com:8080
# Client 4.18 per RHEL 8 (build specifica)
wget https://mirror.openshift.com/pub/openshift-v4/x86_64/clients/ocp/stable/openshift-client-linux-amd64-rhel8.tar.gz
sudo tar -xzf openshift-client-linux-amd64-rhel8.tar.gz -C /usr/local/bin/ oc kubectl
sudo chmod +x /usr/local/bin/oc /usr/local/bin/kubectl
oc version --client

Riferimento: oc 4.16+ su RHEL 8.x.


3. Pre-upgrade checklist

Da eseguire prima di ogni salto minor.

3.1 Check ClusterVersion e ClusterOperator

Terminal window
oc get clusterversion
oc get co

Nessun CO deve essere AVAILABLE=False, PROGRESSING=True o DEGRADED=True. Se qualcuno è Degraded, indaga con:

Terminal window
oc get co --no-headers | awk '$3!="True" || $4!="False" || $5!="False"'
oc describe co <nome>

3.2 Check etcd health

Terminal window
# Endpoint status di ogni member
oc -n openshift-etcd rsh etcd-<master-hostname> \
etcdctl endpoint status --cluster -w table
# Alarm list (dovrebbe essere vuoto)
oc -n openshift-etcd rsh etcd-<master-hostname> \
etcdctl alarm list
# DB size vs quota
oc -n openshift-etcd rsh etcd-<master-hostname> \
etcdctl endpoint status --cluster -w json | jq '.[] | {endpoint: .Endpoint, dbSize: .Status.dbSize, dbSizeInUse: .Status.dbSizeInUse}'

Se dbSize > 70% della quota (default 8 GiB su OCP), fai defrag prima dell’upgrade:

Terminal window
oc -n openshift-etcd rsh etcd-<master-hostname> \
etcdctl defrag --cluster

Il defrag può bloccare i write per qualche secondo per member: farlo fuori orario.

3.3 Check ODF/Ceph

Terminal window
# Ceph status (dovrebbe essere HEALTH_OK)
oc exec -it $(oc get pod -n openshift-storage -l app=rook-ceph-operator -o name) \
-n openshift-storage -- \
ceph status -c /var/lib/rook/openshift-storage/openshift-storage.config
# OSD tree (tutti "up")
oc exec -it $(oc get pod -n openshift-storage -l app=rook-ceph-operator -o name) \
-n openshift-storage -- \
ceph osd tree -c /var/lib/rook/openshift-storage/openshift-storage.config

Se ci sono crash “recenti” ma archiviabili (KCS 5989901):

Terminal window
oc exec -it $(oc get pod -n openshift-storage -l app=rook-ceph-operator -o name) \
-n openshift-storage -- \
ceph crash archive-all -c /var/lib/rook/openshift-storage/openshift-storage.config

Verifica finale che HEALTH_OK sia effettivo (non solo HEALTH_WARN mascherato).

3.4 Upgrade operator all’ultima z-stream del channel corrente

Prima di alzare OCP, allinea gli operator alla loro ultima z del channel dove sono. Da console: Operators → Installed Operators → aggiorna a “Latest available” per ogni operator che ha update pending.

Verifica CSV attuali:

Terminal window
oc get csv -A

Lista operator tipici da controllare:

OperatorVersion tipica pre-upgradeNote
cluster-logging6.2.xVedi §7 LokiStack schema
cluster-observability-operator1.3.xAttenzione al channel
devworkspace-operator0.35.xNon platform-aligned
web-terminal1.11.xNon platform-aligned
elasticsearch-operator5.8.22End-of-life, considera migrazione a Loki
local-storage-operator4.16.xPlatform-aligned
odf-operator4.16.xPlatform-aligned, segue OCP
loki-operator6.2.xPlatform-agnostic
servicemeshoperator2.6.8 → 2.6.14Deve essere ≥ 2.6.14 prima di 4.18
jaeger-operator1.65.xPlatform-agnostic
kiali-operator2.4.x → 2.22.xCon Service Mesh
group-sync-operator0.0.xCommunity operator

Comandi utili per Service Mesh:

Terminal window
oc get csv -A | egrep 'service-mesh|servicemesh'
oc get smcp -A
oc get smcp -A -o custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,SPEC_VERSION:.spec.version,READY:.status.conditions[-1].status'

3.5 MachineHealthCheck — pause

Necessario per evitare che MHC forzi ricreazione dei nodi mentre stanno rebootando per la nuova MachineConfig:

Terminal window
# Vedi MHC esistenti
oc get machinehealthcheck -n openshift-machine-api
# Pause
oc -n openshift-machine-api annotate mhc machine-api-termination-handler \
cluster.x-k8s.io/paused=""

Post-upgrade completo, unpause (nota il - finale):

Terminal window
oc -n openshift-machine-api annotate mhc machine-api-termination-handler \
cluster.x-k8s.io/paused-

3.6 Backup — NooBaa (ODF)

Riferimento: Backup NooBaa.

Backup dei secrets (in una cartella locale, poi copia off-cluster):

Terminal window
mkdir -p ~/backup/noobaa && cd ~/backup/noobaa
for s in noobaa-root-master-key noobaa-admin noobaa-db noobaa-operator noobaa-server noobaa-endpoints; do
oc get secret $s -n openshift-storage -o yaml > $s.yaml
done
ls -la

Backup del database PostgreSQL:

Terminal window
oc exec -n openshift-storage -it noobaa-db-pg-0 -- \
pg_dump nbcore -f /tmp/mcg.db -F custom
oc cp openshift-storage/noobaa-db-pg-0:/tmp/mcg.db ~/backup/noobaa/mcg.bck

Verifica che il file esista e sia > 0 byte.

3.7 Backup — Quay

Riferimento: Backing up and restoring — Quay 3.11+.

⚠ Durante l’upgrade Quay è previsto disservizio di qualche minuto. Il push/pull immagini fallirà nel periodo. Coordinare col team applicativo.

3.8 Backup — etcd snapshot

Anche se non listato esplicitamente nel runbook, è la rete di sicurezza per rollback:

Terminal window
# Snapshot su un master
oc -n openshift-etcd rsh etcd-<master-hostname> \
bash -c 'etcdctl snapshot save /var/lib/etcd/pre-upgrade-$(date +%F).db'
# Copia off-cluster
oc cp openshift-etcd/etcd-<master-hostname>:/var/lib/etcd/pre-upgrade-<date>.db \
~/backup/etcd/pre-upgrade-<date>.db

4. Procedura CP-only step-by-step

4.1 Fase A — Salto 4.14 → 4.16 (via 4.15 CP-only)

  1. Applica pre-check §3 (etcd, ODF, operator z-stream, MHC pause, backup)
  2. Ack Deprecated API (KCS 7031404)
  3. Set channel a eus-4.16:
    Terminal window
    oc adm upgrade channel eus-4.16
  4. Pause MCP worker, infra (NON storage):
    Terminal window
    oc patch mcp worker --type merge -p '{"spec":{"paused":true}}'
    oc patch mcp infra --type merge -p '{"spec":{"paused":true}}'
  5. Upgrade a 4.15.z tramite oc adm upgrade:
    Terminal window
    oc adm upgrade --to=<4.15.z-target>
    watch -n5 'oc adm upgrade status --details=health'
  6. Attendi che i master siano sulla 4.15
  7. Upgrade a 4.16.z:
    Terminal window
    oc adm upgrade --to=<4.16.z-target>
  8. Unpause MCP da console (o CLI):
    Terminal window
    oc patch mcp worker --type merge -p '{"spec":{"paused":false}}'
    oc patch mcp infra --type merge -p '{"spec":{"paused":false}}'
  9. Attendi che tutti i node siano Ready con nuova RHCOS 4.16
  10. Upgrade operator z-stream al nuovo channel (in particolare ODF a stable-4.16)

4.2 Fase B — Salto 4.16 → 4.18 (via 4.17 CP-only)

Prima di partire, Service Mesh deve essere ≥ 2.6.14:

Terminal window
# Verifica
oc get csv -A | egrep 'servicemesh|service-mesh'
# Se serve upgrade, dalla console o
oc patch subscription servicemeshoperator -n openshift-operators \
--type merge -p '{"spec":{"channel":"stable"}}'
  1. Set channel a eus-4.18:
    Terminal window
    oc adm upgrade channel eus-4.18
  2. Pause tutti i MCP (worker, infra — NON storage):
    Terminal window
    oc patch mcp worker --type merge -p '{"spec":{"paused":true}}'
    oc patch mcp infra --type merge -p '{"spec":{"paused":true}}'
  3. Upgrade a 4.17.z:
    Terminal window
    oc adm upgrade --to=<4.17.z-target>
  4. Fix monitoring “grafana deprecated” — vedi §7.1
  5. Upgrade operator ODF/Local Storage all’ultima z del canale stable-4.17 (change channel su ODF):
    Terminal window
    # da console o
    oc patch subscription odf-operator -n openshift-storage \
    --type merge -p '{"spec":{"channel":"stable-4.17"}}'
  6. Upgrade Quay a 3.12.z (change channel a stable-3.12)
  7. Upgrade a 4.18.z:
    Terminal window
    oc adm upgrade --to=<4.18.z-target>
  8. Unpause di tutti i MCP:
    Terminal window
    oc patch mcp worker --type merge -p '{"spec":{"paused":false}}'
    oc patch mcp infra --type merge -p '{"spec":{"paused":false}}'
  9. Attendi che tutti i node siano Ready con RHCOS 4.18
  10. Upgrade operator z-stream all’ultimo canale:
    • ODF → stable-4.18
    • Local Storage → platform-aligned
    • Loki, Cluster Logging → ultima z del channel

5. Post-upgrade checklist

5.1 Verifiche di sanità

Terminal window
oc get clusterversion
oc get co
oc get nodes -o wide
oc get mcp
oc get csv -A | grep -v Succeeded

Tutti i CO devono essere AVAILABLE=True, PROGRESSING=False, DEGRADED=False. Tutti i node Ready. Tutti gli MCP UPDATED=True.

5.2 Applicare KubeletConfig dynamic-sizing (se non già fatto)

Su cluster grandi, evita l’alert SystemMemoryExceedsReservation. Riferimento: Working with nodes — resource allocation CR.

apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
metadata:
name: dynamic-node-master
spec:
autoSizingReserved: true
machineConfigPoolSelector:
matchLabels:
pools.operator.machineconfiguration.openshift.io/master: ""
---
apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
metadata:
name: dynamic-node-worker
spec:
autoSizingReserved: true
machineConfigPoolSelector:
matchLabels:
pools.operator.machineconfiguration.openshift.io/worker: ""

Applica:

Terminal window
oc apply -f dynamic-node.yaml

Attenzione: al primo apply gli MCP fanno un rolling restart dei node (uno alla volta).

5.3 Unpause MachineHealthCheck

Terminal window
oc -n openshift-machine-api annotate mhc machine-api-termination-handler \
cluster.x-k8s.io/paused-

5.4 Verifica ODF post-upgrade

Terminal window
oc get csv -n openshift-storage | grep odf
oc exec -it $(oc get pod -n openshift-storage -l app=rook-ceph-operator -o name) \
-n openshift-storage -- \
ceph status -c /var/lib/rook/openshift-storage/openshift-storage.config

HEALTH_OK obbligatorio prima di considerare il cluster in produzione.


6. Comandi utili durante l’upgrade

6.1 Watch di sanità (aprire in 3 terminali)

Terminal window
# Terminal 1: pod non stabili
watch -n1 -d "oc get po -A | grep -v -E 'Running|Completed'"
# Terminal 2: node state (con age e version)
watch -n1 -d "oc get no -o wide"
# Terminal 3: eventi cluster
oc get events -A --sort-by=.lastTimestamp | tail -30

6.2 Upgrade status ricco (richiede oc 4.16+)

Terminal window
export OC_ENABLE_CMD_UPGRADE_STATUS=true
oc adm upgrade status
oc adm upgrade status --details=health
oc adm upgrade status --details=nodes
oc adm upgrade status --details=operators

--details=health è quella più utile per vedere quali CO sono bloccati e perché.

6.3 ClusterVersion

Terminal window
oc get clusterversions.config.openshift.io version
oc describe clusterversion

6.4 Machine Config Operator log

Se un MCP non completa (bloccato in Progressing), controlla:

Terminal window
# Namespace
oc get pods -n openshift-machine-config-operator
# Controller
oc logs -n openshift-machine-config-operator machine-config-controller-<hash>
# Operator
oc logs -n openshift-machine-config-operator machine-config-operator-<hash>

6.5 OLM error check

Terminal window
oc -n openshift-operator-lifecycle-manager logs \
$(oc get pods -l app=catalog-operator -o NAME -n openshift-operator-lifecycle-manager) \
| grep "'ResolutionFailed' constraints not satisfiable"

Se trovi ResolutionFailed, c’è un problema di dipendenze operator. Vedi §7.7.


7. Troubleshooting — “gotcha” dal campo

7.1 Fix monitoring: unknown field "grafana" (post-4.17)

Il campo grafana: in cluster-monitoring-config è deprecato da 4.17. Riferimento: KCS 7106258.

Terminal window
# Vedi contenuto
oc get cm cluster-monitoring-config -o yaml -n openshift-monitoring
# Rimuovi il campo grafana
oc edit cm cluster-monitoring-config -n openshift-monitoring
# ...cancella la sezione grafana: ...

Se il cm è gestito da ACM policy (es. policy-monitoring-ocpapp-collaudo), rimuovi il campo dalla policy per non farla riscrivere.

7.2 LokiStack Schema Upgrades Required

Riferimenti:

L’alert appare quando LokiStack ha uno schema TSDB che va migrato. Va gestito prima di considerare il cluster stabile post-upgrade.

7.3 SystemMemoryExceedsReservation

L’alert dice che il node sta usando più memoria di quanto system-reserved prevedeva. Fix definitivo: applicare la KubeletConfig con autoSizingReserved: true (vedi §5.2). Riferimento: Working with nodes.

Formula: system = capacity − allocatable.

7.4 Patch NooBaa HPA (autoscaling endpoints)

Terminal window
oc patch -n openshift-storage storagecluster ocs-storagecluster \
--type merge \
--patch '{"spec": {"multiCloudGateway": {"endpoints": {"minCount": 2, "maxCount": 3}}}}'

Imposta min 2 / max 3 endpoint MCG (default è 1). Migliora resilienza durante upgrade.

7.5 Ceph Daemons “Recently Crashed” (CephClusterWarningState)

Riferimento: KCS 5989901. Sintomo: post-upgrade Ceph riporta HEALTH_WARN con crash storico che è già stato risolto.

Terminal window
# Archivia tutti i crash noti (li marca "letti")
oc exec -it $(oc get pod -n openshift-storage -l app=rook-ceph-operator -o name) \
-n openshift-storage -- \
ceph crash archive-all -c /var/lib/rook/openshift-storage/openshift-storage.config
# Conferma HEALTH_OK
oc exec -it $(oc get pod -n openshift-storage -l app=rook-ceph-operator -o name) \
-n openshift-storage -- \
ceph status -c /var/lib/rook/openshift-storage/openshift-storage.config

7.6 Fix ODF: ocs-client-operator-console-serving-cert

Riferimento: KCS 7105144.

Terminal window
oc create secret generic ocs-client-operator-console-serving-cert -n openshift-storage
oc scale deployment ocs-client-operator-console ocs-client-operator-controller-manager \
--replicas=0 -n openshift-storage
oc get events -n openshift-storage | grep ocs-client-operator-console

7.7 Operator “Unknown Failure” durante l’upgrade

Restart OLM + catalog operator:

Terminal window
oc delete pods -l 'app in (catalog-operator, olm-operator)' \
-n openshift-operator-lifecycle-manager
oc rollout restart deployment.apps/catalog-operator deployment.apps/olm-operator \
-n openshift-operator-lifecycle-manager

Se anche dopo persiste, rimuovi l’annotazione olm.generated-by da subscription orfane:

Terminal window
for sub in $(oc get subs -n openshift-storage -o json | \
jq '.items[] | select((.metadata.annotations."olm.generated-by" | .!= null) and (.status.installplan==null)) | .metadata.name' -r); do
oc patch subs -n openshift-storage $sub \
--type json -p '[{"op":"remove", "path":"/metadata/annotations/olm.generated-by"}]'
done

Se ResolutionFailed persiste, cerca e cancella i job falliti in openshift-marketplace e le relative ConfigMap con lo stesso nome del job.

7.8 Rook-Ceph Toolbox (abilitare per debug)

Riferimento: KCS 4628891.

Terminal window
oc patch storagecluster ocs-storagecluster -n openshift-storage \
--type json --patch '[{ "op": "replace", "path": "/spec/enableCephTools", "value": true }]'

Poi il pod rook-ceph-tools-* appare nel namespace e permette di eseguire comandi ceph “puri” senza rsh nell’operator.

7.9 Fix RPC Hidden Services (security hardening)

Riferimento: KCS 7025827.

Il socket rpcbind è aperto per default su RHCOS ma non usato. MachineConfig per fermarlo su tutti i node:

apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfig
metadata:
labels:
machineconfiguration.openshift.io/role: worker
name: stop-rpc-bind-socket-worker
spec:
config:
ignition:
version: 3.2.0
systemd:
units:
- name: stop-rpc-bind-socket.service
enabled: true
contents: |
[Unit]
Description=Stop rpcbind socket
[Service]
Type=oneshot
ExecStart=/usr/bin/systemctl stop rpcbind.socket
[Install]
WantedBy=multi-user.target
---
apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfig
metadata:
labels:
machineconfiguration.openshift.io/role: master
name: stop-rpc-bind-socket-master
spec:
config:
ignition:
version: 3.2.0
systemd:
units:
- name: stop-rpc-bind-socket.service
enabled: true
contents: |
[Unit]
Description=Stop rpcbind socket
[Service]
Type=oneshot
ExecStart=/usr/bin/systemctl stop rpcbind.socket
[Install]
WantedBy=multi-user.target

Verifica dopo l’applicazione (su un node, via oc debug node):

Terminal window
ss -lntup | grep ':111' # non deve restituire nulla
systemctl is-active rpcbind.socket # inactive
systemctl is-enabled rpcbind.socket # disabled

7.10 ACM upgrade (Advanced Cluster Management)

Se il cluster è gestito da ACM, aggiorna anche l’operator ACM.

Terminal window
# Verifica versione attuale
oc get csv -A | grep advanced-cluster-management
# Update channel (release-2.11 per ACM su OCP 4.16-4.18)
oc patch subscription advanced-cluster-management \
-n open-cluster-management \
--type merge -p '{"spec":{"channel":"release-2.11"}}'

7.11 ⚠ MAI eliminare pod PDB su nodi ODF/Storage

Se durante l’upgrade un pod noobaa-*, rook-ceph-* o csi-* è “stuck”, non fare oc delete pod. Il PodDisruptionBudget impedisce che il Ceph resti sotto quorum: uccidere manualmente rompe la replicazione. Aspetta che il pod si ricrei da solo o interviene l’operator.

7.12 Altri KCS di riferimento

SintomoKCS
Operator cannot be upgraded, “CatalogSource was removed”6603001
Reinstalling Operator fails due to Catalog Cache6777761
ODF: Remove and reinstall Subscription/CSV6972585
CSV not referenced by subscription6991414

8. Note operative finali

  • Ordine sacro operator vs. OCP: prima si allineano gli operator alla loro ultima z del channel corrente, poi si alza OCP. Dopo il salto OCP, si cambia channel dell’operator e si riallinea. Farlo al contrario significa quasi sempre bloccarsi in Progressing.
  • Il MCP storage non si mette mai in pause: Ceph ha bisogno di rolling restart controllato dei pod OSD, che passa dal MCP. Se pausi, il PDB blocca l’operator e Ceph resta con OSD vecchi che vanno degradando.
  • oc adm upgrade status è la stella polare: --details=health mostra il primo CO che blocca la catena. Se dice tutto verde ma il cluster non progredisce, guarda i log MCO.
  • Rollback è possibile solo con etcd snapshot pre-upgrade e reinstall dei master (procedura complessa). Meglio prevenire con tutti i pre-check di §3 fatti bene.
  • EUS-to-EUS non è opzionale su ambiente produttivo: skippare uno step (es. andare direttamente 4.16→4.18 su tutto il cluster) non è supportato. Il pattern CP-only con pause MCP è l’unica via.

Vedi anche