Skip to content

Strategia Migrazione OSSM 2/3 — caso reale

Caso reale di migrazione Red Hat OpenShift Service Mesh 2.6 → 3.0 sul cluster OCP COLL (OCP 4.18.5, OVN-Kubernetes). Ogni scelta è verificata sull’ambiente: control plane, ingress dietro F5, ~1500 risorse Istio (296 Gateway, VirtualService, AuthorizationPolicy, DestinationRule, PeerAuthentication).

As-is (dati certi)

ElementoValore rilevatoImpatto
PiattaformaOCP 4.18.5, OVN-KubernetesSupportata da OSSM 3.
Operatorservicemeshoperator.v2.6.17 — SucceededPrereq operator coperto (≥2.6.14).
Control planeSMCP basic @ istio-system, spec.version v2.4 / chart 2.4.15Da portare a v2.6 (Fase 0).
ModeClusterWideGuida cluster-wide, revision-label canary.
CAsecret cacerts (4 chiavi: ca-cert/ca-key/cert-chain/root-cert) = plugged CARoot custom, no cert-manager. Verifica root su cacerts, non istio-ca-secret.
mTLSdataPlane.mtls: true + PeerAuthentication/default STRICTSTRICT esplicito (API Istio) → invariato.
PA addondisable-mtls-jaeger-collector (DISABLE), grafana-ports-mtls-disabled (PERMISSIVE)Orfane dopo rimozione addon.
Ingress2 NodePort condivisi, su infra nodeistio-ingressgateway 80→30001/443→30002/15021→32072 (pod-label istio: ingressgateway); backend-ingressgateway 80→30011/443→30012/15021→32082 (istio: backend-ingressgateway).
Egress0 riferimenti (nessun Gateway/VS lo instrada)Da NON ricreare in OSSM 3.
Esposizione apphost VS = VIP F5 → uno dei 2 NodePortnodePort fissi da preservare.
IOR~300 Route auto-generate in istio-system (IOR on, chart 2.4.x)Vestigiali: le app entrano solo via F5→NodePort. Le uniche route “vive” sono quelle infra OCP (console/quay), estranee a OSSM. → disable IOR + delete.
Namespace312 con istio-injection=enabled (~157 prod / ~146 dev), pattern be/fe/mgwCanary per namespace, a ondate. memberSelectors SMMR = istio-injection=enabled.
Gateway296: 229 istio: ingressgateway + 64 istio: backend-ingressgateway + 4 senza selettore (demo/hello)Le CR selezionano il pod → invariate.
Secret TLStutti i gwc-* in istio-system, credentialName senza prefisso nsI gateway injected devono restare in istio-system (SDS). Nessun <ns>/<name> da riscrivere.
VirtualServicegateway-bound (*.cariprpccoll.it, match URI/rewrite) + [mesh] interni + mgw SNI passthroughInvariati (API Istio).
AuthorizationPolicyallow-nothing/allow-from-ns/allow-istio-ingressgateway/allow-gateway-sa per nsReferenziano il SA dell’ingress → SA da preservare.
DestinationRule78Invariate.
EnvoyFiltersolo stats-filter/tcp-stats-filter 1.13–1.16 di sistemaGenerati dal CP 2.x, spariscono con esso. Zero custom.
WasmPlugin / SidecarnessunoNessuna remediation Envoy per Istio 1.24.
ServiceEntry1: d0-npf-be/auth-collaudo (res=DNS, MESH_EXTERNAL)DNS capture da riabilitare in OSSM 3 (vedi Fase 3).

Strategia in una riga

Cluster-wide, revision-label (canary), plugged CA condivisa via cacerts, gateway-injection dei soli 2 ingress con adozione dei Service NodePort → i due CP coesistono in istio-system, i namespace migrano a ondate senza disservizio, F5 non viene mai toccato.

Decisioni derivate dai dati reali:

  • No cert-manager: CA = plugged cacerts → percorso “istio revision label”.
  • IOR vestigiale: disable + delete route generate, niente migrazione a route esplicite (traffico solo F5→NodePort).
  • Egress escluso: 0 utilizzi → non ricreato.
  • mTLS invariato: STRICT già PeerAuthentication esplicita.
  • DNS capture: 1 ServiceEntry res=DNSproxyMetadata obbligatorio nella CR Istio.
  • Nessun rischio Envoy 1.24: zero EnvoyFilter/WasmPlugin/Sidecar custom.

Fase 0 — Control plane a v2.6

Operator già 2.6.17. Il control plane è ancora v2.4 (chart 2.4.15) → va portato a v2.6 (che diventa 2.6.17 ≥ 2.6.14). Congela prima gli update.

Terminal window
oc patch subscription servicemeshoperator -n openshift-operators \
--type merge -p '{"spec":{"installPlanApproval":"Manual"}}'
# upgrade incrementale, una minor alla volta (matrice RH)
oc patch smcp basic -n istio-system --type merge -p '{"spec":{"version":"v2.5"}}'
oc rollout status deploy/istiod-basic -n istio-system
oc patch smcp basic -n istio-system --type merge -p '{"spec":{"version":"v2.6"}}'
oc rollout status deploy/istiod-basic -n istio-system
oc get smcp basic -n istio-system -o jsonpath='spec={.spec.version} chart={.status.chartVersion}{"\n"}' # atteso 2.6.17

Fase 1 — Premigration checklist

1.1 Dismetti IOR (route vestigiali)

Le app entrano via F5→NodePort: le route IOR in istio-system non servono e OSSM 3 non le gestisce. Disabilita IOR sul CP 2.6 ed eliminale.

Terminal window
# stop reconciliation IOR
oc patch smcp basic -n istio-system --type merge -p '{"spec":{"gateways":{"openshiftRoute":{"enabled":false}}}}'
# censisci le route generate (naming <ns>-<gateway>-<hash>, target *ingressgateway)
oc get route -n istio-system -o json \
| jq -r '.items[] | select(.spec.to.name|test("ingressgateway")) | .metadata.name'
# elimina dopo verifica (F5 non le usa). Esempio mirato:
# oc delete route -n istio-system <name> ...

1.2 ServiceEntry pre-check

Istio 1.24 rifiuta ServiceEntry >256 host o senza porte.

Terminal window
oc get serviceentry -A -o json | jq -r '.items[] | select(.spec.hosts|length>256) | "\(.metadata.namespace)/\(.metadata.name)"'
oc get serviceentry -A -o json | jq -r '.items[] | select(.spec.ports==null or (.spec.ports|length==0)) | "\(.metadata.namespace)/\(.metadata.name)"'

L’unico ServiceEntry (d0-npf-be/auth-collaudo) è res=DNS → richiede DNS capture (Fase 3), non un fix qui.

1.3 Disabilita addon e configura i sostituti

Addon tutti attivi (grafana, jaeger Memory, kiali, prometheus). In OSSM 3 non esistono più nell’SMCP.

Terminal window
oc patch smcp basic -n istio-system --type merge -p '{
"spec":{
"addons":{"grafana":{"enabled":false},"kiali":{"enabled":false},"prometheus":{"enabled":false}},
"tracing":{"type":"None"},
"security":{"manageNetworkPolicy":false}
}}'

Sostituti (validi anche in 3.0): metriche → User Workload Monitoring (extensionProvider prometheus); tracing → Tempo + OTel Collector (il Jaeger Memory a sampling 100% non è portabile); Kiali → CR Kiali standalone (Grafana off).

apiVersion: telemetry.istio.io/v1
kind: Telemetry
metadata:
name: mesh-default
namespace: istio-system
spec:
metrics: [{ providers: [{ name: prometheus }] }]
tracing: [{ providers: [{ name: otel }] }]
apiVersion: kiali.io/v1alpha1
kind: Kiali
metadata:
name: kiali
namespace: istio-system
spec:
version: default
external_services:
prometheus:
auth: { type: bearer, use_kiali_token: true }
thanos_proxy: { enabled: true }
url: https://thanos-querier.openshift-monitoring.svc.cluster.local:9091
tracing:
enabled: true
provider: tempo
use_grpc: false
internal_url: http://tempo-<stack>-query-frontend.tempo:3200
external_url: https://<tempo-route>
grafana: { enabled: false }

1.4 NetworkPolicy

manageNetworkPolicy messo a false sopra. In banking ricrea le NP a mano (Fase 4), con accesso a entrambi i CP, prima di migrare i workload.


Fase 2 — Gateway injection dei 2 ingress (F5-safe)

I VIP F5 bilanciano su node:nodePort fissi. Adotta i Service esistenti come standalone prima di sganciarli dall’SMCP → i nodePort non cambiano mai. Solo 2 ingress (l’egress è escluso: 0 utilizzi).

2.1 SA (verificati)

Gatewaypod-label (istio:)ServiceAccount
istio-ingressgatewayingressgatewayistio-ingressgateway-service-account
backend-ingressgatewaybackend-ingressgatewaybackend-ingressgateway-service-account

2.2 Adotta i Service NodePort (rimuovi ownerReferences SMCP)

Terminal window
for svc in istio-ingressgateway backend-ingressgateway; do
oc get svc $svc -n istio-system -o yaml \
| yq 'del(.metadata.ownerReferences,.metadata.resourceVersion,.metadata.uid,.metadata.creationTimestamp,.status)' \
| oc apply -f -
done

2.3 Deploy gateway injected (revision 2.6) dietro lo stesso Service

Attenzione alla pod-label: default ingress = istio: ingressgateway (229 Gateway lo selezionano), backend = istio: backend-ingressgateway (64). Sbagliarla = host F5 a vuoto.

# DEFAULT ingress — pod-label istio: ingressgateway
apiVersion: apps/v1
kind: Deployment
metadata:
name: istio-ingressgateway-inj
namespace: istio-system
spec:
selector:
matchLabels: { istio: ingressgateway }
template:
metadata:
annotations: { inject.istio.io/templates: gateway }
labels:
istio: ingressgateway # match del Service NodePort adottato (229 Gateway)
sidecar.istio.io/inject: "true"
istio.io/rev: basic # revision 2.6 corrente
spec:
serviceAccountName: istio-ingressgateway-service-account
nodeSelector: { node-role.kubernetes.io/infra: "" }
tolerations:
- { key: node-role.kubernetes.io/infra, effect: NoSchedule }
- { key: node-role.kubernetes.io/infra, effect: NoExecute }
- { key: node.ocs.openshift.io/storage, effect: NoSchedule }
containers:
- { name: istio-proxy, image: auto }
---
# BACKEND ingress — pod-label istio: backend-ingressgateway
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-ingressgateway-inj
namespace: istio-system
spec:
selector:
matchLabels: { istio: backend-ingressgateway }
template:
metadata:
annotations: { inject.istio.io/templates: gateway }
labels:
istio: backend-ingressgateway # 64 Gateway
sidecar.istio.io/inject: "true"
istio.io/rev: basic
spec:
serviceAccountName: backend-ingressgateway-service-account
nodeSelector: { node-role.kubernetes.io/infra: "" }
tolerations:
- { key: node-role.kubernetes.io/infra, effect: NoSchedule }
- { key: node-role.kubernetes.io/infra, effect: NoExecute }
- { key: node.ocs.openshift.io/storage, effect: NoSchedule }
containers:
- { name: istio-proxy, image: auto }

2.4 Sgancia i gateway dall’SMCP

Con i pod injected Ready dietro i Service adottati, svuota spec.gateways dell’SMCP (default ingress + additionalIngress.backend-ingressgateway + egress). L’SMCP elimina solo i propri Deployment; Service standalone e pod injected restano.

Terminal window
istioctl ps -n istio-system | grep -E 'ingressgateway'
oc edit smcp basic -n istio-system # svuota spec.gateways.*
# conferma che i VIP F5 rispondono ancora (SIMPLE + mgw SNI)

Fase 3 — Installa OSSM 3, IstioCNI e control plane 3.0

Operator OSSM 3 (Sail) → IstioCNI → risorsa Istio nello stesso istio-system per condividere la plugged CA (cacerts).

apiVersion: sailoperator.io/v1
kind: IstioCNI
metadata: { name: default }
spec:
namespace: istio-cni
version: v1.24-latest
apiVersion: sailoperator.io/v1
kind: Istio
metadata:
name: ossm-3
spec:
namespace: istio-system # stesso ns del 2.6 → cacerts condiviso
updateStrategy: { type: RevisionBased }
version: v1.24-latest
values:
meshConfig:
# cluster-wide: nessun discoverySelector → guarda tutti i namespace (come l'as-is)
defaultConfig:
proxyMetadata: # DNS capture per il ServiceEntry res=DNS (d0-npf-be/auth-collaudo)
ISTIO_META_DNS_CAPTURE: "true"
ISTIO_META_DNS_AUTO_ALLOCATE: "true"
extensionProviders:
- { name: prometheus, prometheus: {} }
- name: otel
opentelemetry: { port: 4317, service: otel-collector.<otel-ns>.svc.cluster.local }
pilot:
traceSampling: 100 # SMCP tracing.sampling:10000 = 100%
nodeSelector: { node-role.kubernetes.io/infra: "" }
tolerations:
- { key: node-role.kubernetes.io/infra, effect: NoSchedule }
- { key: node-role.kubernetes.io/infra, effect: NoExecute }
- { key: node.ocs.openshift.io/storage, effect: NoSchedule }
global:
defaultNodeSelector: { node-role.kubernetes.io/infra: "" }
defaultTolerations:
- { key: node-role.kubernetes.io/infra, effect: NoSchedule }
- { key: node-role.kubernetes.io/infra, effect: NoExecute }
- { key: node.ocs.openshift.io/storage, effect: NoSchedule }
Terminal window
oc apply -f istiocni.yaml -f istio-ossm3.yaml
# Verifica CHIAVE: il nuovo istiod carica la plugged CA ESISTENTE (cacerts), non genera una root nuova
oc logs deploy/istiod-ossm-3-v1-24-<patch> -n istio-system | grep -i 'existing secret'
oc get istios ossm-3 # ACTIVE REVISION es. ossm-3-v1-24-<patch>

Fase 4 — NetworkPolicy durante la migrazione

Entrambi i CP devono raggiungere tutti i workload e viceversa.

Terminal window
for ns in $(oc get smmr default -n istio-system -o jsonpath='{.status.members[*]}'); do
oc label ns "$ns" service-mesh=enabled --overwrite
done
# istiod NP rev 3.0: podSelector app=istiod, istio.io/rev=<ACTIVE REVISION 3.0>

Fase 5 — Migrazione workload (canary, per namespace)

Terminal window
REV=$(oc get istios ossm-3 -o jsonpath='{.status.activeRevisionName}') # es. ossm-3-v1-24-x
oc label ns <ns> istio.io/rev=$REV maistra.io/ignore-namespace=true istio-injection- --overwrite=true
oc rollout restart deploy -n <ns>
oc rollout status deploy -n <ns>
istioctl ps -n <ns> # atteso: ISTIOD istiod-ossm-3-... VERSION 1.24.x
  • rimuove istio-injection (ha precedenza su istio.io/rev), aggiunge istio.io/rev=$REV (proxy 3.0) e maistra.io/ignore-namespace=true (ferma l’injector 2.6 → evita il doppio-CNI che blocca il sidecar).

Fase 6 — Migrazione gateway (canary)

I 2 ingress sono già injected (Fase 2). Ruota i pod da rev basic a rev 3.0 sullo stesso Service NodePort → F5 intatto.

Terminal window
REV=$(oc get istios ossm-3 -o jsonpath='{.status.activeRevisionName}')
# clone del deployment injected con istio.io/rev=$REV, STESSA pod-label (ingressgateway / backend-ingressgateway)
oc scale deploy/istio-ingressgateway-3 -n istio-system --replicas=<n+1>
oc scale deploy/istio-ingressgateway-inj -n istio-system --replicas=<n-1>
istioctl ps -n istio-system | grep ingressgateway # verifica rev 1.24.x

Ripeti per backend-ingressgateway. Per gateway a bassa criticità: in-place (relabel ns + rollout restart).


Fase 7 — mTLS / PeerAuthentication

PeerAuthentication/default STRICT è API Istio → resta valida in 3.0. Nessuna traduzione di dataPlane.mtls.

  • Mantieni PeerAuthentication/default STRICT.
  • Rimuovi disable-mtls-jaeger-collector e grafana-ports-mtls-disabled dopo la dismissione addon.
  • 78 DestinationRule e le AuthorizationPolicy restano invariate (dipendono dai SA preservati in Fase 2).

Fase 8 — Completamento

8.1 (Opzionale) default revision tag

Dopo aver migrato tutti ns e gateway, torna a istio-injection=enabled col tag di default → i futuri update 3.x non richiedono re-label dei ~300 ns.

apiVersion: sailoperator.io/v1
kind: IstioRevisionTag
metadata: { name: default }
spec:
targetRef: { kind: IstioRevision, name: <ACTIVE REVISION 3.0> }
Terminal window
oc apply -f rev-tag.yaml
oc get istiorevisiontags # default → Healthy / IN USE True dopo relabel
# per ns: oc label ns <ns> istio-injection=enabled istio.io/rev- ; oc rollout restart deploy -n <ns>

8.2 Rimozione OSSM 2.6

Terminal window
oc get smcp,smm,smmr -A
oc delete smcp --all -A ; oc delete smmr --all -A ; oc delete smm --all -A
csv=$(oc get subscription servicemeshoperator -n openshift-operators -o jsonpath='{.status.currentCSV}')
oc delete subscription servicemeshoperator -n openshift-operators
oc delete clusterserviceversion "$csv" -n openshift-operators
oc get crds -o name | grep '\.maistra\.io$' | xargs -r -n1 oc delete
# label residue SOLO dopo la disinstallazione del CP 2.6
oc get ns -l maistra.io/ignore-namespace=true -o name | xargs -r -n1 -I{} oc label {} maistra.io/ignore-namespace-

Reference — mapping SMCP → Istio (campi in uso)

SMCP 2.6 (basic)Istio 3.0 (ossm-3)Nota
mode: ClusterWide(default) — no discoverySelectors3.0 cluster-wide di default.
policy.type: Istiod(default)Mixer rimosso.
tracing.sampling: 10000values.pilot.traceSampling: 10010000 = 100%.
tracing.type: JaegerTelemetry + extensionProvider otel → TempoJaeger Memory non portabile.
addons.*Operator separati (UWM, Kiali, Tempo)Grafana non supportata.
security.dataPlane.mtls: truePeerAuthentication/default STRICTGià presente → invariata.
security.certificateAuthority.istiod + cacertssecret cacerts in istio-systemPlugged CA condivisa, no cert-manager.
gateways.openshiftRoute (IOR)Disabilitato + route eliminate (F5→NodePort).
gateways.{ingress,additionalIngress}Gateway injection (Deployment + Service self-managed)Solo 2 ingress; egress escluso.
runtime…nodeSelector/tolerations (infra)values.pilot.* + values.global.default*Placement infra preservato.
ServiceEntry res=DNSmeshConfig.defaultConfig.proxyMetadata DNS_CAPTURE+AUTO_ALLOCATEEvita Name or service not known.

Non supportati in 3.0 e presenti in questo SMCP: addons.*, policy.*, telemetry.*, gateways.openshiftRoute, security.certificateAuthority.istiod.privateKey.rootCADir (root via cacerts).


Check residui (non bloccanti)

  • I 4 Gateway senza selettore (istio-system-hello-*, ossm-bookinfo-*, 4296-demo-*): demo/test → verifica e rimuovi, o escludi dalla migrazione.
  • Conferma il mode dei Gateway mgw (PASSTHROUGH, porta 443, selettore su uno dei 2 ingress): SNI-routing gestito dai VS mgw, TLS terminato a valle.
  • 4b-corporatebanking: presenti Gateway con nomi non allineati al namespace (corporatebanking-gateway) → verifica il binding VS↔Gateway prima di migrare quel gruppo.