Skip to content

Runbook — Patch di risorse Kubernetes / OpenShift

Runbook — Patch di risorse Kubernetes / OpenShift


1. Concetti base

In Kubernetes/OpenShift puoi modificare una risorsa in vari modi:

Terminal window
oc edit <kind> <name> -n <namespace>

oppure con patch diretta:

Terminal window
oc patch <kind> <name> -n <namespace> --type <tipo_patch> -p '<payload>'

I tipi patch più usati sono:

TipoQuando usarlo
mergeIl più comodo per modificare campi semplici dentro oggetti YAML/JSON
jsonUtile per aggiungere/rimuovere/sostituire campi in modo preciso
strategicUtile su alcune risorse Kubernetes native, ma non sempre supportato sulle CRD

Su OpenShift puoi usare sia oc sia kubectl. Negli esempi uso oc, ma quasi tutti i comandi valgono anche con kubectl.


2. Prima regola: fai sempre backup della risorsa

Prima di patchare:

Terminal window
oc get <kind> <name> -n <namespace> -o yaml > backup-<kind>-<name>.yaml

Esempio:

Terminal window
oc get argocd openshift-gitops -n openshift-gitops -o yaml > backup-argocd-openshift-gitops.yaml

Se hai kubectl-neat:

Terminal window
oc get argocd openshift-gitops -n openshift-gitops -o yaml | kubectl-neat > backup-argocd-openshift-gitops-neat.yaml

3. Verificare il valore attuale di un campo

Con jsonpath:

Terminal window
oc get <kind> <name> -n <namespace> -o jsonpath='{.spec.campo}{"\n"}'

Esempio per OpenShift GitOps notifications:

Terminal window
oc get argocd openshift-gitops -n openshift-gitops \
-o jsonpath='{.spec.notifications.enabled}{"\n"}'

Con jq:

Terminal window
oc get <kind> <name> -n <namespace> -o json | jq '.spec'

Esempio:

Terminal window
oc get argocd openshift-gitops -n openshift-gitops -o json | jq '.spec.notifications'

4. Patch semplice con --type merge

4.1 Impostare un campo booleano a true

Terminal window
oc patch <kind> <name> -n <namespace> \
--type merge \
-p '{"spec":{"campo":{"enabled":true}}}'

Esempio reale: abilitare notifications su OpenShift GitOps:

Terminal window
oc patch argocd openshift-gitops \
-n openshift-gitops \
--type merge \
-p '{"spec":{"notifications":{"enabled":true}}}'

Verifica:

Terminal window
oc get argocd openshift-gitops -n openshift-gitops \
-o jsonpath='{.spec.notifications.enabled}{"\n"}'

4.2 Impostare un campo booleano a false

Terminal window
oc patch argocd openshift-gitops \
-n openshift-gitops \
--type merge \
-p '{"spec":{"notifications":{"enabled":false}}}'

4.3 Cambiare una stringa

Terminal window
oc patch <kind> <name> -n <namespace> \
--type merge \
-p '{"spec":{"campo":"nuovo-valore"}}'

Esempio:

Terminal window
oc patch route my-route -n my-namespace \
--type merge \
-p '{"spec":{"host":"app.example.com"}}'

4.4 Cambiare un numero

Terminal window
oc patch <kind> <name> -n <namespace> \
--type merge \
-p '{"spec":{"replicas":3}}'

Esempio Deployment:

Terminal window
oc patch deployment my-app -n my-namespace \
--type merge \
-p '{"spec":{"replicas":3}}'

Nota: per i replica è spesso più leggibile usare:

Terminal window
oc scale deployment my-app -n my-namespace --replicas=3

5. Patch annidata

Se il campo è dentro più livelli YAML:

spec:
server:
route:
enabled: false

Patch:

Terminal window
oc patch <kind> <name> -n <namespace> \
--type merge \
-p '{"spec":{"server":{"route":{"enabled":true}}}}'

Esempio ArgoCD route:

Terminal window
oc patch argocd openshift-gitops \
-n openshift-gitops \
--type merge \
-p '{"spec":{"server":{"route":{"enabled":true}}}}'

6. Patch di risorse gestite da operator/controller

Se la console mostra:

Managed resource
This resource is managed by ...

la patch può essere sovrascritta.

Prima controlla owner, label e annotation:

Terminal window
oc get <kind> <name> -n <namespace> -o json | jq '.metadata.ownerReferences'
Terminal window
oc get <kind> <name> -n <namespace> -o json | jq '.metadata.labels'
Terminal window
oc get <kind> <name> -n <namespace> -o json | jq '.metadata.annotations'

Esempio:

Terminal window
oc get argocd openshift-gitops -n openshift-gitops -o json | jq '.metadata.ownerReferences'
Terminal window
oc get argocd openshift-gitops -n openshift-gitops -o json | jq '.metadata.labels, .metadata.annotations'

Se la risorsa è gestita da ArgoCD/GitOps, modifica il manifest nel repository Git o nella Application che la riconcilia.

Cerca eventuali Application ArgoCD:

Terminal window
oc get applications.argoproj.io -A

Cerca riferimenti alla risorsa:

Terminal window
oc get applications.argoproj.io -A -o yaml | grep -B20 -A20 "openshift-gitops"

7. Patch con file JSON/YAML

Se il payload è lungo, evita il one-liner e usa un file.

Crea file:

Terminal window
cat > patch.json <<'EOF'
{
"spec": {
"notifications": {
"enabled": true
}
}
}
EOF

Applica:

Terminal window
oc patch argocd openshift-gitops \
-n openshift-gitops \
--type merge \
--patch-file patch.json

8. Patch label

8.1 Aggiungere o aggiornare una label

Modo consigliato:

Terminal window
oc label <kind> <name> -n <namespace> chiave=valore --overwrite

Esempio:

Terminal window
oc label namespace my-namespace environment=prod --overwrite

Con patch:

Terminal window
oc patch <kind> <name> -n <namespace> \
--type merge \
-p '{"metadata":{"labels":{"environment":"prod"}}}'

8.2 Rimuovere una label

Terminal window
oc label <kind> <name> -n <namespace> chiave-

Esempio:

Terminal window
oc label namespace my-namespace environment-

Con JSON patch:

Terminal window
oc patch <kind> <name> -n <namespace> \
--type json \
-p='[{"op":"remove","path":"/metadata/labels/environment"}]'

9. Patch annotation

9.1 Aggiungere o aggiornare una annotation

Modo consigliato:

Terminal window
oc annotate <kind> <name> -n <namespace> chiave=valore --overwrite

Esempio:

Terminal window
oc annotate deployment my-app -n my-namespace backup.velero.io/backup-volumes=data --overwrite

Con patch:

Terminal window
oc patch <kind> <name> -n <namespace> \
--type merge \
-p '{"metadata":{"annotations":{"mia.annotation/chiave":"valore"}}}'

9.2 Rimuovere una annotation

Terminal window
oc annotate <kind> <name> -n <namespace> chiave-

Esempio:

Terminal window
oc annotate deployment my-app -n my-namespace backup.velero.io/backup-volumes-

Con JSON patch, attenzione agli slash / nella chiave: vanno scritti come ~1.

Esempio annotation:

backup.velero.io/backup-volumes

Path JSON patch:

/metadata/annotations/backup.velero.io~1backup-volumes

Comando:

Terminal window
oc patch deployment my-app -n my-namespace \
--type json \
-p='[{"op":"remove","path":"/metadata/annotations/backup.velero.io~1backup-volumes"}]'

10. JSON Patch: add, replace, remove

Il tipo json usa operazioni precise.

10.1 Replace

Terminal window
oc patch <kind> <name> -n <namespace> \
--type json \
-p='[{"op":"replace","path":"/spec/replicas","value":3}]'

Esempio:

Terminal window
oc patch deployment my-app -n my-namespace \
--type json \
-p='[{"op":"replace","path":"/spec/replicas","value":3}]'

10.2 Add

Terminal window
oc patch <kind> <name> -n <namespace> \
--type json \
-p='[{"op":"add","path":"/spec/nuovoCampo","value":"valore"}]'

10.3 Remove

Terminal window
oc patch <kind> <name> -n <namespace> \
--type json \
-p='[{"op":"remove","path":"/spec/campoDaRimuovere"}]'

Esempio:

Terminal window
oc patch route my-route -n my-namespace \
--type json \
-p='[{"op":"remove","path":"/spec/host"}]'

11. Patch di liste/array

11.1 Aggiungere un elemento in fondo a una lista

Usa /- per append.

Esempio: aggiungere una tolleration a un Deployment:

Terminal window
oc patch deployment my-app -n my-namespace \
--type json \
-p='[
{
"op": "add",
"path": "/spec/template/spec/tolerations/-",
"value": {
"key": "node-role.kubernetes.io/infra",
"operator": "Exists",
"effect": "NoSchedule"
}
}
]'

Se la lista tolerations non esiste, prima devi crearla:

Terminal window
oc patch deployment my-app -n my-namespace \
--type json \
-p='[
{
"op": "add",
"path": "/spec/template/spec/tolerations",
"value": []
}
]'

Poi aggiungi l’elemento.

11.2 Sostituire il primo elemento di una lista

Terminal window
oc patch <kind> <name> -n <namespace> \
--type json \
-p='[{"op":"replace","path":"/spec/lista/0","value":"nuovo-valore"}]'

11.3 Rimuovere il primo elemento di una lista

Terminal window
oc patch <kind> <name> -n <namespace> \
--type json \
-p='[{"op":"remove","path":"/spec/lista/0"}]'

12. Patch nodeSelector e tolerations su Deployment

12.1 Aggiungere nodeSelector

Terminal window
oc patch deployment my-app -n my-namespace \
--type merge \
-p '{"spec":{"template":{"spec":{"nodeSelector":{"node-role.kubernetes.io/infra":""}}}}}'

12.2 Aggiungere toleration infra

Se tolerations non esiste:

Terminal window
oc patch deployment my-app -n my-namespace \
--type merge \
-p '{"spec":{"template":{"spec":{"tolerations":[{"key":"node-role.kubernetes.io/infra","operator":"Exists","effect":"NoSchedule"}]}}}}'

Attenzione: con merge, una lista viene sostituita interamente. Se esistono già altre toleration, meglio usare JSON patch append.

Terminal window
oc patch deployment my-app -n my-namespace \
--type json \
-p='[
{
"op": "add",
"path": "/spec/template/spec/tolerations/-",
"value": {
"key": "node-role.kubernetes.io/infra",
"operator": "Exists",
"effect": "NoSchedule"
}
}
]'

13. Patch risorse CPU/Memoria su Deployment

13.1 Cambiare requests/limits del primo container

Terminal window
oc patch deployment my-app -n my-namespace \
--type merge \
-p '{
"spec": {
"template": {
"spec": {
"containers": [
{
"name": "my-container",
"resources": {
"requests": {
"cpu": "100m",
"memory": "256Mi"
},
"limits": {
"cpu": "500m",
"memory": "512Mi"
}
}
}
]
}
}
}
}'

Per i Deployment, lo strategic merge può funzionare meglio sulle liste di container perché usa name come chiave di merge:

Terminal window
oc patch deployment my-app -n my-namespace \
--type strategic \
-p '{
"spec": {
"template": {
"spec": {
"containers": [
{
"name": "my-container",
"resources": {
"requests": {
"cpu": "100m",
"memory": "256Mi"
},
"limits": {
"cpu": "500m",
"memory": "512Mi"
}
}
}
]
}
}
}
}'

Nota: sulle CRD lo strategic merge spesso non è supportato. Usa merge o json.


14. Patch Service

14.1 Cambiare type da ClusterIP a NodePort

Terminal window
oc patch svc my-service -n my-namespace \
--type merge \
-p '{"spec":{"type":"NodePort"}}'

14.2 Cambiare type da NodePort a ClusterIP

Prima potresti dover rimuovere i nodePort assegnati.

Terminal window
oc patch svc my-service -n my-namespace \
--type merge \
-p '{"spec":{"type":"ClusterIP"}}'

14.3 Impostare un nodePort specifico

Attenzione: il nodePort deve essere libero e nel range ammesso dal cluster.

Terminal window
oc patch svc my-service -n my-namespace \
--type json \
-p='[
{
"op": "replace",
"path": "/spec/ports/0/nodePort",
"value": 30080
}
]'

15. Patch Route OpenShift

15.1 Cambiare host

Terminal window
oc patch route my-route -n my-namespace \
--type merge \
-p '{"spec":{"host":"my-app.apps.example.com"}}'

15.2 Cambiare termination TLS

Terminal window
oc patch route my-route -n my-namespace \
--type merge \
-p '{"spec":{"tls":{"termination":"edge","insecureEdgeTerminationPolicy":"Redirect"}}}'

15.3 Rimuovere TLS da una Route

Terminal window
oc patch route my-route -n my-namespace \
--type json \
-p='[{"op":"remove","path":"/spec/tls"}]'

16. Patch IngressController OpenShift

16.1 Cambiare numero repliche router

Terminal window
oc patch ingresscontroller default -n openshift-ingress-operator \
--type merge \
-p '{"spec":{"replicas":3}}'

16.2 Aggiungere nodePlacement su infra

Terminal window
oc patch ingresscontroller default -n openshift-ingress-operator \
--type merge \
-p '{
"spec": {
"nodePlacement": {
"nodeSelector": {
"matchLabels": {
"node-role.kubernetes.io/infra": ""
}
},
"tolerations": [
{
"key": "node-role.kubernetes.io/infra",
"operator": "Exists",
"effect": "NoSchedule"
}
]
}
}
}'

17. Patch MachineConfigPool

17.1 Pausare un MachineConfigPool

Terminal window
oc patch mcp worker \
--type merge \
-p '{"spec":{"paused":true}}'

17.2 Riattivare un MachineConfigPool

Terminal window
oc patch mcp worker \
--type merge \
-p '{"spec":{"paused":false}}'

Verifica:

Terminal window
oc get mcp

18. Patch Operator Subscription

18.1 Cambiare installPlanApproval a Manual

Terminal window
oc patch subscription <subscription-name> -n <namespace> \
--type merge \
-p '{"spec":{"installPlanApproval":"Manual"}}'

Esempio:

Terminal window
oc patch subscription openshift-gitops-operator -n openshift-operators \
--type merge \
-p '{"spec":{"installPlanApproval":"Manual"}}'

18.2 Cambiare channel

Terminal window
oc patch subscription <subscription-name> -n <namespace> \
--type merge \
-p '{"spec":{"channel":"stable"}}'

Esempio:

Terminal window
oc patch subscription openshift-gitops-operator -n openshift-operators \
--type merge \
-p '{"spec":{"channel":"latest"}}'

19. Patch ConfigMap

19.1 Cambiare un valore semplice

Terminal window
oc patch configmap my-config -n my-namespace \
--type merge \
-p '{"data":{"CHIAVE":"valore"}}'

19.2 Aggiungere più chiavi

Terminal window
oc patch configmap my-config -n my-namespace \
--type merge \
-p '{"data":{"KEY1":"value1","KEY2":"value2"}}'

19.3 Rimuovere una chiave

Con JSON patch:

Terminal window
oc patch configmap my-config -n my-namespace \
--type json \
-p='[{"op":"remove","path":"/data/CHIAVE"}]'

Se la chiave contiene /, sostituire / con ~1.


20. Patch Secret

20.1 Aggiornare una chiave in un Secret

I valori nei Secret devono essere base64.

Terminal window
echo -n 'nuova-password' | base64 -w0

Su macOS:

Terminal window
echo -n 'nuova-password' | base64

Patch:

Terminal window
oc patch secret my-secret -n my-namespace \
--type merge \
-p '{"data":{"password":"bnVvdmEtcGFzc3dvcmQ="}}'

Metodo più sicuro per generare il payload:

Terminal window
PASSWORD_B64="$(echo -n 'nuova-password' | base64 -w0)"
oc patch secret my-secret -n my-namespace \
--type merge \
-p "{\"data\":{\"password\":\"${PASSWORD_B64}\"}}"

21. Patch SecurityContextConstraints

21.1 Aggiungere un ServiceAccount a una SCC

Modo consigliato:

Terminal window
oc adm policy add-scc-to-user <scc-name> -z <serviceaccount> -n <namespace>

Esempio:

Terminal window
oc adm policy add-scc-to-user privileged -z my-sa -n my-namespace

Patch manuale, da usare con cautela:

Terminal window
oc patch scc privileged \
--type json \
-p='[
{
"op": "add",
"path": "/users/-",
"value": "system:serviceaccount:my-namespace:my-sa"
}
]'

22. Patch ClusterLogForwarder esempio

Esempio generico per abilitare un campo booleano dentro una CRD:

Terminal window
oc patch clusterlogforwarder collector -n openshift-logging \
--type merge \
-p '{"spec":{"collector":{"someField":true}}}'

Per CRD complesse, meglio prima esportare:

Terminal window
oc get clusterlogforwarder collector -n openshift-logging -o yaml > clf-before.yaml

Modificare un file locale e poi applicare:

Terminal window
oc apply -f clf-before.yaml

Oppure usare oc edit:

Terminal window
oc edit clusterlogforwarder collector -n openshift-logging

23. Patch ArgoCD/OpenShift GitOps

23.1 Abilitare notifications

Terminal window
oc patch argocd openshift-gitops \
-n openshift-gitops \
--type merge \
-p '{"spec":{"notifications":{"enabled":true}}}'

Verifica:

Terminal window
oc get argocd openshift-gitops -n openshift-gitops \
-o jsonpath='{.spec.notifications.enabled}{"\n"}'

Controlla pod/deployment:

Terminal window
oc get deploy,pod -n openshift-gitops | egrep -i 'notification|argocd'

23.2 Disabilitare notifications

Terminal window
oc patch argocd openshift-gitops \
-n openshift-gitops \
--type merge \
-p '{"spec":{"notifications":{"enabled":false}}}'

23.3 Abilitare Grafana

Terminal window
oc patch argocd openshift-gitops \
-n openshift-gitops \
--type merge \
-p '{"spec":{"grafana":{"enabled":true}}}'

23.4 Abilitare route server

Terminal window
oc patch argocd openshift-gitops \
-n openshift-gitops \
--type merge \
-p '{"spec":{"server":{"route":{"enabled":true}}}}'

24. Patch su tutte le risorse di un namespace

24.1 Aggiungere una label a tutti i Deployment del namespace

Terminal window
for d in $(oc get deploy -n my-namespace -o name); do
oc label "$d" -n my-namespace managed-by=ops --overwrite
done

24.2 Patchare tutte le Deployment con una label

Terminal window
oc get deploy -n my-namespace -l app=my-app -o name | while read d; do
oc patch "$d" -n my-namespace \
--type merge \
-p '{"spec":{"replicas":2}}'
done

24.3 Patchare tutti i namespace non di sistema

Esempio: aggiungere una label a namespace applicativi.

Terminal window
oc get ns -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' \
| grep -vE '^(openshift-|kube-)' \
| while read ns; do
oc label ns "$ns" checked-by=ops --overwrite
done

25. Dry-run e validazione

25.1 Dry-run server-side

Non sempre disponibile per tutte le operazioni patch, ma utile quando supportato.

Terminal window
oc patch <kind> <name> -n <namespace> \
--type merge \
-p '{"spec":{"campo":"valore"}}' \
--dry-run=server -o yaml

25.2 Controllare differenze prima/dopo

Prima:

Terminal window
oc get <kind> <name> -n <namespace> -o yaml > before.yaml

Patch:

Terminal window
oc patch <kind> <name> -n <namespace> \
--type merge \
-p '{"spec":{"campo":"valore"}}'

Dopo:

Terminal window
oc get <kind> <name> -n <namespace> -o yaml > after.yaml

Diff:

Terminal window
diff -u before.yaml after.yaml

Con kubectl-neat:

Terminal window
oc get <kind> <name> -n <namespace> -o yaml | kubectl-neat > after-neat.yaml

26. Rollback veloce

Se hai salvato il backup YAML:

Terminal window
oc apply -f backup-<kind>-<name>.yaml

Esempio:

Terminal window
oc apply -f backup-argocd-openshift-gitops.yaml

Attenzione: se la risorsa è gestita da un operator, il rollback manuale può essere a sua volta riconciliato dal controller.


27. Errori comuni

27.1 Invalid JSON

Errore tipico:

invalid character ...

Controlla virgolette e apici.

Buona pratica:

Terminal window
cat <<'EOF' > patch.json
{
"spec": {
"notifications": {
"enabled": true
}
}
}
EOF
jq . patch.json

Poi:

Terminal window
oc patch argocd openshift-gitops -n openshift-gitops \
--type merge \
--patch-file patch.json

27.2 Campo inesistente con JSON patch replace

replace richiede che il campo esista. Se non esiste, usa add.

Terminal window
oc patch <kind> <name> -n <namespace> \
--type json \
-p='[{"op":"add","path":"/spec/nuovoCampo","value":"valore"}]'

27.3 Liste sovrascritte con merge patch

Con --type merge, le liste vengono normalmente sostituite.

Esempio rischioso:

Terminal window
oc patch deployment my-app -n my-namespace \
--type merge \
-p '{"spec":{"template":{"spec":{"tolerations":[...]}}}}'

Se vuoi aggiungere un solo elemento senza perdere gli altri, usa --type json con path /-.

27.4 La patch funziona ma poi torna indietro

Probabile risorsa gestita da:

  • Operator
  • ArgoCD / OpenShift GitOps
  • ACM
  • Helm
  • Kustomize
  • altro controller

Controlla:

Terminal window
oc get <kind> <name> -n <namespace> -o json | jq '.metadata.ownerReferences'
Terminal window
oc get <kind> <name> -n <namespace> -o json | jq '.metadata.labels, .metadata.annotations'

28. Mini cheat sheet finale

Merge patch

Terminal window
oc patch <kind> <name> -n <namespace> \
--type merge \
-p '{"spec":{"campo":"valore"}}'

JSON patch replace

Terminal window
oc patch <kind> <name> -n <namespace> \
--type json \
-p='[{"op":"replace","path":"/spec/campo","value":"valore"}]'

JSON patch add

Terminal window
oc patch <kind> <name> -n <namespace> \
--type json \
-p='[{"op":"add","path":"/spec/campo","value":"valore"}]'

JSON patch remove

Terminal window
oc patch <kind> <name> -n <namespace> \
--type json \
-p='[{"op":"remove","path":"/spec/campo"}]'

Verifica campo

Terminal window
oc get <kind> <name> -n <namespace> \
-o jsonpath='{.spec.campo}{"\n"}'

Backup

Terminal window
oc get <kind> <name> -n <namespace> -o yaml > backup.yaml

Rollback

Terminal window
oc apply -f backup.yaml

29. Template rapido da riusare

Terminal window
KIND="argocd"
NAME="openshift-gitops"
NS="openshift-gitops"
oc get "$KIND" "$NAME" -n "$NS" -o yaml > "backup-${KIND}-${NAME}.yaml"
oc patch "$KIND" "$NAME" -n "$NS" \
--type merge \
-p '{"spec":{"notifications":{"enabled":true}}}'
oc get "$KIND" "$NAME" -n "$NS" \
-o jsonpath='{.spec.notifications.enabled}{"\n"}'

30. Template con variabili e patch-file

Terminal window
KIND="argocd"
NAME="openshift-gitops"
NS="openshift-gitops"
cat > patch.json <<'EOF'
{
"spec": {
"notifications": {
"enabled": true
}
}
}
EOF
jq . patch.json
oc get "$KIND" "$NAME" -n "$NS" -o yaml > "backup-${KIND}-${NAME}.yaml"
oc patch "$KIND" "$NAME" -n "$NS" \
--type merge \
--patch-file patch.json
oc get "$KIND" "$NAME" -n "$NS" -o yaml | kubectl-neat