Guide: Setting Up a Restricted-Access OpenShift Cluster for SAP Edge Lifecycle Management (ELM) with Service Mesh 3.x
Table of Contents
- Overview
- Prerequisites
- Process Overview
- Step 1: Install Service Mesh 3.x Operators
- Step 2: Configure OpenShift Service Mesh 3.x
- Step 3: Register the Cluster in ELM
- Optional: Exposing the Istio Ingress Gateway via OpenShift Routes
- Advanced: Multiple Service Mesh Instances
Overview
This guide provides step-by-step instructions for onboarding a shared Red Hat OpenShift cluster into SAP Edge Lifecycle Management (ELM) using a restricted-privilege model. Instead of requiring full cluster-admin rights, ELM will use a dedicated Service Account with a precise, limited set of permissions. The official source of truth for this process is SAP Note 3618713, and this guide serves as an extension of the information provided therein.
Intended Audience: This document is for anyone responsible for preparing the cluster environment — typically a Red Hat OpenShift Cluster Administrator, or any user with sufficient privileges to install operators and create the required namespaces, RBAC, and service accounts. Administrator involvement is required for initial setup and whenever ELM requires updated restricted resources during an upgrade; routine ELM operations use the restricted service account.
Prerequisites
Before beginning this setup, ensure you have completed the following requirements:
Required Access and Credentials
- Cluster-admin privileges, or delegated permissions covering every resource in the downloaded bundle and the namespace configuration commands, on the target OpenShift cluster. These are needed for initial setup and for resource updates requested by ELM during upgrades.
- Access to SAP Note 3618713 (requires SAP S-user credentials)
- Authenticated
ocCLI session to your OpenShift cluster
Software Requirements
- Red Hat OpenShift Container Platform 4.14+ (tested versions for Service Mesh 3.x)
- OpenShift CLI (
oc) version matching your cluster - Bash 3.2+ to run the bundled apply script
kubectlon yourPATH— required by the bundledapply-restricted-resources.shscript used to apply downloaded resources. The script invokeskubectlby name, so anoc-only installation does not satisfy it.- The same administrator kubeconfig and target context for
kubectlandoc— the script uses the activekubectlcontext; the cluster name printed by the script does not select or verify that context. - Red Hat OpenShift Service Mesh 3.x Operators installed:
- Red Hat OpenShift Service Mesh 3.x (required)
- Kiali Operator (optional - for service mesh visualization)
- Red Hat OpenShift distributed tracing platform (optional - for distributed tracing)
Downloaded Resources
Download the Kubernetes resources from the ELM UI for the current Edge Node and deployment or upgrade operation. Use the instructions and apply script supplied with that download; the bundle contents can change between operations and releases. See Resource Bundle Scope and Apply Script.
Process Overview
The setup process consists of three main stages:
- Install Operators: Install the Red Hat OpenShift Service Mesh 3.x Operators.
- Configure Service Mesh 3.x: Deploy and customize the Red Hat OpenShift Service Mesh 3.x to manage network traffic.
- Register the Cluster in ELM: Download resources from the ELM UI to create namespaces and RBAC permissions, generate the Kubeconfig, and register the cluster as an Edge Node.
Step 1: Install Service Mesh 3.x Operators
Before configuring any components, you must install the necessary operators.
Installation Method:
- Log in to the OpenShift web console.
- Navigate to Operators → OperatorHub.
- Search for Red Hat OpenShift Service Mesh.
- Select the Service Mesh 3.x version.
- Click Install and follow the prompts to complete the installation.
Verify Installation:
Run the following command to confirm the operators are installed:
# Verify the required Service Mesh 3.x operator is installed
# Adjust the grep pattern if your operator name differs
oc get csv -n openshift-operators | grep -E "servicemeshoperator3|Service Mesh 3"
Step 2: Configure OpenShift Service Mesh 3.x
The SAP Note requires a service mesh to be present. This guide provides a specific, tested configuration for Red Hat OpenShift Service Mesh version 3.x. The architecture and configuration approach has changed significantly from Service Mesh 2.x.
Deployment Options:
This step shows the standard shared service mesh approach. For environments requiring enhanced security isolation or multi-tenancy, see Advanced: Multiple Service Mesh Instances for deploying a dedicated service mesh specifically for SAP workloads.
Note: The configurations provided below are general guidance for a standard Service Mesh 3.x deployment. If you need to make customized changes to the service mesh configuration, please refer to the official Red Hat OpenShift Service Mesh 3.x documentation for detailed customization options.
# --- Command 1: Create the Service Mesh control plane namespace ---
oc new-project istio-system
# --- Command 2: Create the CNI namespace ---
oc new-project istio-cni
# --- Command 3: Create the IstioCNI resource ---
oc apply -f - <<EOF
apiVersion: sailoperator.io/v1
kind: IstioCNI
metadata:
name: default
namespace: istio-cni
spec:
namespace: istio-cni
EOF
Command 4: Create the Istio Control Plane
Choose the appropriate configuration based on your environment:
Standard Configuration (Direct Internet Access):
Use this configuration if your cluster has direct internet access without requiring a corporate proxy.
# --- Command 4a: Create the Istio control plane (standard) ---
oc apply -f - <<EOF
apiVersion: sailoperator.io/v1
kind: Istio
metadata:
name: default
namespace: istio-system
spec:
namespace: istio-system
values:
meshConfig:
discoverySelectors:
- matchLabels:
istio-discovery: enabled
EOF
Corporate Proxy Configuration (HTTP Proxy Required):
Use this configuration if your environment requires a corporate proxy for external connectivity (e.g., to reach SAP BTP, XSUAA, or other external services). This configuration enables DNS capture, which is required for proper proxy traffic routing through the Istio sidecar.
# --- Command 4b: Create the Istio control plane (with corporate proxy support) ---
oc apply -f - <<EOF
apiVersion: sailoperator.io/v1
kind: Istio
metadata:
name: default
namespace: istio-system
spec:
namespace: istio-system
values:
meshConfig:
discoverySelectors:
- matchLabels:
istio-discovery: enabled
defaultConfig:
proxyMetadata:
ISTIO_META_DNS_CAPTURE: "true"
ISTIO_META_DNS_AUTO_ALLOCATE: "true"
EOF
Why is DNS capture needed for corporate proxy? When SAP EIC applications connect to external services through a corporate proxy using HTTP CONNECT tunneling, the Istio sidecar (Envoy) must properly intercept DNS queries to route traffic correctly. Without DNS capture enabled, you may encounter
ECONNRESETerrors or404 route_not_foundresponses.
Corporate Proxy ServiceEntry:
When using a corporate proxy, you must also create a ServiceEntry so that the Istio sidecar permits outbound TCP connections to the proxy. Replace the placeholders with your proxy's hostname, IP address(es), and port.
Note: Apply this ServiceEntry after the
edgelmnamespace is created in Step 3. You can return to this command after completing step 6 of the Initialize Edge Node procedure.
oc apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: allow-http-proxy
namespace: edgelm
spec:
hosts:
- <proxy-hostname>
addresses:
- <proxy-IP>
ports:
- number: <proxy-port>
name: tcp-proxy-tunnel
protocol: TCP
location: MESH_EXTERNAL
resolution: NONE
EOF
CRITICAL: List every IP the proxy hostname resolves to. With
resolution: NONE, the Istio sidecar (Envoy) only permits outbound connections to the IP addresses explicitly declared underaddresses. It does not re-resolve the hostname at connection time. If the proxy hostname is backed by more than one IP (common for load-balanced or highly-available proxies), any IP missing from this list has no route and the connection is silently dropped, surfacing asi/o timeout.Because DNS returns the backing IPs in round-robin order, a missing IP causes intermittent failures — connections succeed whenever DNS hands back a listed IP and time out whenever it returns an unlisted one. The corporate proxy logs will show only the successful attempts, because the failing ones time out before ever reaching the proxy.
Discover all proxy IPs. From a cluster node or any host on the same network, resolve the hostname and add all returned IPs to the addresses list above:
# List every IP the proxy hostname resolves to
dig +short <proxy-hostname>
Validate a suspect IP before adding it. If a specific IP times out, confirm it is a live proxy backend (and not a stale DNS record) by sending the same request through it directly — first bypassing the sidecar from a node, then from inside a sidecar-injected pod:
# From an OpenShift node (bypasses the Istio sidecar)
curl -x http://<proxy-IP>:<proxy-port> -I https://<sap-btp-endpoint>
# From a sidecar-injected pod in edgelm
oc exec -n edgelm <pod> -c <app-container> -- \
curl -x http://<proxy-IP>:<proxy-port> -I https://<sap-btp-endpoint>
- Works from the node but not from the pod → the IP is a valid backend; add it to the ServiceEntry
addresseslist and re-apply.- Fails from both → the IP is a dead or misconfigured proxy backend. Ask your proxy/networking team to fix routing to it or remove it from the proxy hostname's DNS pool. Do not add an unreachable IP to the ServiceEntry.
Complete the Service Mesh Setup
# --- Command 5: Label the control plane namespace for discovery ---
oc label namespace istio-system istio-discovery=enabled
Wait for Service Mesh Control Plane to Be Ready
The Service Mesh 3.x control plane takes 5-10 minutes to deploy and become ready. You must wait for it to be ready before proceeding to Step 3.
# Wait for Istio control plane to be ready (may take 5-10 minutes)
oc wait --for=condition=Ready istio/default -n istio-system --timeout=600s
# Verify all components are running
oc get pods -n istio-system
oc get pods -n istio-cni
Expected output: All pods should show Running or Completed status.
Step 3: Register the Cluster in ELM
This step uses the ELM UI to download Kubernetes resources (namespaces, CRDs, RBAC), apply them to the cluster, generate a Kubeconfig, and complete the Edge Node registration.
The resource handling is split into two phases:
- Initialize Edge Node — Apply the ELM resources, generate the Kubeconfig, and upload it to complete registration.
- Component Deployment — Apply the resources requested by ELM, which may also cover dependent components. See Component Resource Downloads below.
Resource Bundle Scope and Apply Script
The archive generated by ELM determines which resources must be applied. It may include cluster-scoped resources and resources for dependent components. Inspect the actual download to identify the affected namespaces and the permissions needed to apply it.
Extract each download into a separate directory and keep its script and all manifests together. Use the bundle generated for the current Edge Node and operation; do not mix files from different downloads. Run the apply script with administrator credentials or sufficient delegated permissions, rather than the restricted runtime edgelm kubeconfig.
What the Script Checks and Applies
Use apply-restricted-resources.sh when supplied, and check its --help output for the options supported by that download. The commands in this guide use:
| Invocation | Behavior |
|---|---|
./apply-restricted-resources.sh --check |
Runs the script's preflight checks without applying resources; it is not a complete manifest or permissions validation. |
./apply-restricted-resources.sh |
Runs the checks, prompts for confirmation, and applies the bundle. |
./apply-restricted-resources.sh --yes |
Skips confirmation prompts, including any legacy namespace adoption prompt. Use only after reviewing the target and ownership. |
If the script fails, resolve the error before continuing in ELM; resources applied before the failure may remain. Do not replace the supplied script with a directory-wide oc apply that bypasses its checks. If the download has no apply script, follow the accompanying SAP instructions.
Review Ownership Across the Full Bundle
Before applying, verify the target cluster, Edge Node, operation, and ownership of all affected namespaces, including dependencies. The script's ownership checks can cover fewer namespaces than its manifests; a successful --check does not establish ownership of namespaces outside those checks. Resolve conflicts or uncertain ownership with SAP before proceeding. Do not pre-create empty application namespaces or change ownership labels to bypass validation. Confirm legacy adoption only for namespaces belonging to the registration being upgraded.
Critical: Verify OpenShift Settings After Each Resource Apply
IMPORTANT
After the bundle succeeds, apply and verify the SCC annotations and Service Mesh labels required by this guide for every affected namespace, including dependent components. Preserve SAP ownership metadata. Complete this OpenShift configuration before continuing deployment in ELM.
After you initiate an upgrade in ELM, the operation changes to Prepared if updated Kubernetes resources are required. The upgrade then pauses while you download and apply those resources. After applying them, repeat the SCC annotation and Service Mesh label configuration above before resuming the upgrade in ELM.
kubectl applymerges metadata, so existing custom settings may be preserved, while values declared in the bundle can be restored. See Kubernetes apply merge behavior.In particular, applying a bundle can restore
istio-injection=enabled. For a dedicated mesh, follow Assign SAP Namespaces to the Dedicated Mesh after each apply. See Upgrade Requirements for the upgrade sequence.
Initialize Edge Node
- In the ELM UI, start the Add an Edge Node process.
- On the first stage, Provide Edge Node Details, enter a name for your Edge Node.
- CRITICAL: Check "Restricted Access to Kubernetes cluster" checkbox
- You MUST select this checkbox
- Without this, ELM will attempt to use cluster-admin privileges and the deployment will fail
- When you reach the Initialize Edge Node stage, click Download Kubernetes Resources to download the resource files.
- Extract the archive into its own directory and use its bundled
apply-restricted-resources.shscript. Select the administrator kubeconfig for both CLIs and verify the target before applying:
# Replace this path with the administrator kubeconfig for the target cluster
export KUBECONFIG="/path/to/cluster-admin-kubeconfig"
kubectl config current-context
kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}{"\n"}'
cd <path-to-downloaded-resources>/
chmod +x apply-restricted-resources.sh
# Validate namespace ownership without applying resources
./apply-restricted-resources.sh --check
# Apply the bundle (prompts for confirmation before applying)
./apply-restricted-resources.sh
Continue only after both commands succeed. See What the Script Checks and Applies for ownership conflicts, legacy adoption, and non-interactive use. Keep using the administrator kubeconfig for the remaining cluster preparation commands; the runtime kubeconfig generated below is for ELM.
- Apply the OpenShift SCC annotation and Service Mesh labels to the
edgelmnamespace. Configure these explicitly even when the downloaded namespace manifest already includes some of the labels:
Note: At this stage, only the
edgelmnamespace resources are included. Additional namespaces are handled during component deployment — see Component Resource Downloads. The commands below use the shared mesh; for a dedicated mesh, apply the SCC annotation and use the dedicated mesh labels foredgelminstead.
# Apply SCC annotation to edgelm namespace
oc annotate namespace edgelm openshift.io/sa.scc.supplemental-groups="67000/1000" --overwrite
# Configure Service Mesh discovery and injection for the shared mesh
oc label namespace edgelm istio-discovery=enabled istio-injection=enabled --overwrite
- Generate the Kubeconfig file. The downloaded resources created the
edgelmnamespace and its RBAC bindings. Now create the service account and kubeconfig that ELM will use to authenticate to your cluster:
CRITICAL: You must use the
edgelmservice account in theedgelmnamespace.The RBAC resources you just applied are specifically bound to this service account. Do not substitute your own service account or one from a different namespace.
# --- 1. Create the 'edgelm' service account in the 'edgelm' namespace ---
oc create sa edgelm -n edgelm
# --- 2. Create a secret to hold the long-lived service account token ---
oc apply -n edgelm -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
name: edgelm-kubeconfig-token
annotations:
kubernetes.io/service-account.name: edgelm
type: kubernetes.io/service-account-token
EOF
# --- 3. Extract the token and generate the Kubeconfig file ---
export SECRET_NAME_SA=edgelm-kubeconfig-token
export TOKEN_SA=$(oc get secret ${SECRET_NAME_SA} -n edgelm -ojsonpath='{.data.token}' | base64 -d)
oc config view --raw --minify > edgelm-kubeconfig
oc config unset users --kubeconfig=edgelm-kubeconfig
oc config set-credentials edgelm --kubeconfig=edgelm-kubeconfig --token=${TOKEN_SA}
oc config set-context --current --kubeconfig=edgelm-kubeconfig --user=edgelm
echo "Kubeconfig file 'edgelm-kubeconfig' has been generated successfully."
# Test the kubeconfig file to ensure it works
oc --kubeconfig=edgelm-kubeconfig auth can-i list pods -n edgelm
# Expected output: "yes" - this confirms the kubeconfig works correctly
If ELM rejects the kubeconfig with a TLS error: On some clusters, ELM reports:
Cluster '<api-host>:6443' must have exactly one of 'certificate-authority-data' or 'insecure-skip-tls-verify: true' defined, but not both or neither.This happens when the admin's current login relies on the operating system's trust store (for example, a cluster whose API server presents a publicly or corporately trusted certificate). In that case
oc config view --raw --minifycopies a cluster entry that contains neither field, which ELM does not accept. Embed the cluster's CA into the generated kubeconfig:# Derive the API server host:port and cluster name from the generated kubeconfig API_URL=$(oc --kubeconfig=edgelm-kubeconfig config view -o jsonpath='{.clusters[0].cluster.server}') CLUSTER_NAME=$(oc --kubeconfig=edgelm-kubeconfig config view -o jsonpath='{.clusters[0].name}') # Fetch the API server CA chain and embed it into the kubeconfig echo | openssl s_client -connect "${API_URL#https://}" -showcerts 2>/dev/null \ | openssl x509 -outform PEM > cluster-ca.crt oc config set-cluster "${CLUSTER_NAME}" \ --certificate-authority=cluster-ca.crt --embed-certs=true \ --kubeconfig=edgelm-kubeconfigRe-run the
auth can-itest above to confirm the kubeconfig still works, then upload it to ELM.Not recommended: As a last-resort fallback for testing only, you can instead disable certificate verification. This weakens transport security and should never be used for a production registration:
oc config set-cluster "${CLUSTER_NAME}" --insecure-skip-tls-verify=true --kubeconfig=edgelm-kubeconfig
-
Back in the ELM UI:
- Check the "I confirm that I have downloaded and applied resources" checkbox
- Upload the
edgelm-kubeconfigfile you generated in the previous step - Enter a Context Password and click Download Bootstrapping File
- Proceed with the rest of the configuration as guided by the UI
-
If your environment requires a corporate proxy, select "Enable HTTP Proxy" and configure the proxy settings.
- Note: Ensure you used the Corporate Proxy Configuration option in Step 2 when deploying the Istio control plane, and apply the ServiceEntry for your proxy now that the
edgelmnamespace exists.
- Note: Ensure you used the Corporate Proxy Configuration option in Step 2 when deploying the Istio control plane, and apply the ServiceEntry for your proxy now that the
Verification
After applying annotations, verify they were applied correctly:
# Verify SCC annotations on edgelm namespace
oc get namespace edgelm -o yaml | grep -A 2 "openshift.io/sa.scc"
# Expected output should show:
# openshift.io/sa.scc.supplemental-groups: 67000/1000
Component Resource Downloads (Deployment and Upgrades)
Each deployed component has its own Kubernetes resources that must be downloaded and applied to the cluster. These resources are available from the All Deployments view in the ELM UI.
Components Requiring Resource Downloads
| Component | Archive | Namespaces Created |
|---|---|---|
| IstioGateways | restricted-resources-IstioGateways-<version>.zip |
istio-gateways |
| Edge Integration Cell Services | restricted-resources-Edge_Integration_Cell_Services-<version>.zip |
edge-icell-services |
| Edge Integration Cell | restricted-resources-Edge_Integration_Cell-<version>.zip |
edge-icell, edge-icell-secrets, edge-icell-ela, edge-icell-services, istio-gateways |
Note: The Edge Integration Cell archive is a superset — it includes all namespace definitions and resources from the IstioGateways and Edge Integration Cell Services archives. You can apply just the Edge Integration Cell archive to cover all three components. If you do, you must still apply the SCC annotations and Service Mesh labels for all namespaces listed below.
How to Download Component Resources
- Navigate to All Deployments in the ELM UI
- Locate the component (e.g., IstioGateways, Edge Integration Cell)
- Click the "..." (actions menu) for the component
- Select "Download Kubernetes Resources"
- Extract the archive into a separate directory and review ownership for all affected namespaces. Apply it using the script supplied with that download and the administrator kubeconfig from the initialization step, following Resource Bundle Scope and Apply Script:
cd <path-to-component-resources>/
chmod +x apply-restricted-resources.sh
./apply-restricted-resources.sh --check # runs the supplied script's preflight checks
./apply-restricted-resources.sh
- After the script succeeds, apply and verify the SCC annotations and Service Mesh labels for all namespaces included in the archive, including dependent components' namespaces (see below), then continue deployment in ELM.
SCC Annotations and Service Mesh Labels per Component
After the bundle succeeds, run the command groups below for every namespace it affects, including dependencies, before continuing deployment or upgrade. These commands configure the shared mesh from Step 2. For a dedicated mesh, apply the SCC annotations below and use the dedicated mesh labels instead. Preserve SAP ownership metadata.
After applying IstioGateways resources:
# Apply Service Mesh labels to istio-gateways namespace
oc label namespace istio-gateways istio-discovery=enabled istio-injection=enabled --overwrite
After applying Edge Integration Cell Services resources:
# Apply SCC annotations to edge-icell-services namespace
oc annotate namespace edge-icell-services openshift.io/sa.scc.uid-range="1000000/1000" --overwrite
oc annotate namespace edge-icell-services openshift.io/sa.scc.supplemental-groups="1000002/1000" --overwrite
# Apply Service Mesh labels
oc label namespace edge-icell-services istio-discovery=enabled istio-injection=enabled --overwrite
For the EIC workload namespaces after applying Edge Integration Cell resources:
# Apply SCC annotations to edge-icell namespace
oc annotate namespace edge-icell openshift.io/sa.scc.uid-range="10000/100" --overwrite
oc annotate namespace edge-icell openshift.io/sa.scc.supplemental-groups="1000/100" --overwrite
# Apply SCC annotations to edge-icell-ela namespace
oc annotate namespace edge-icell-ela openshift.io/sa.scc.uid-range="100000/1000" --overwrite
oc annotate namespace edge-icell-ela openshift.io/sa.scc.supplemental-groups="100002/1000" --overwrite
# Apply Service Mesh labels
oc label namespace edge-icell edge-icell-ela istio-discovery=enabled istio-injection=enabled --overwrite
oc label namespace edge-icell-secrets istio-discovery=enabled --overwrite
Verify Istio Injection Labels
After applying all component resources and their labels, verify that the correct namespaces have Istio injection enabled. The following expected values apply to the shared mesh; for a dedicated mesh, verify istio.io/rev and istio-discovery as described in the advanced section.
# Verify Istio injection labels across all namespaces
oc get ns -L istio-injection
# Expected output: edgelm, edge-icell, edge-icell-ela, edge-icell-services,
# and istio-gateways should show "enabled" in the ISTIO-INJECTION column.
# edge-icell-secrets should NOT have istio-injection enabled.
Upgrade Requirements
IMPORTANT: Resource Updates for Upgrades
When you initiate an upgrade in ELM, ELM checks whether Kubernetes resource changes are required. If no changes are required, the upgrade proceeds without manual resource application. If changes are required, the operation status changes to Prepared and the upgrade pauses, waiting for you to download and apply the updated resources. Complete the resource application and OpenShift configuration below, then resume the upgrade in ELM. See SAP ELM Key Concepts.
OpenShift configuration: Verify and re-apply the required SCC annotations and mesh labels after the resource update and before resuming. Existing custom metadata may be preserved, but bundle-defined injection labels can be restored. For a dedicated mesh, repeat the revision-based labeling and removal of
istio-injectionon the affected workload namespaces.
Resource update procedure — after you initiate an upgrade and its status changes to Prepared:
- In the ELM UI, navigate to All Deployments and download the Kubernetes resources for the target version and current upgrade operation (see How to Download Component Resources). This also applies when ELM itself requires updated restricted resources.
-
Extract the updated archive into a separate directory. Verify the target context and ownership of all affected namespaces, then run the supplied script with the administrator kubeconfig:
cd <path-to-updated-resources>/ chmod +x apply-restricted-resources.sh ./apply-restricted-resources.sh --check ./apply-restricted-resources.sh -
After the script succeeds, re-apply and verify SCC annotations and Service Mesh labels for all affected namespaces. Use the
edgelmcommands in Initialize Edge Node and the relevant groups in SCC Annotations and Service Mesh Labels per Component. Apply the dedicated mesh labels instead when using that configuration. - Resume the upgrade in the ELM UI only after both the SAP resource apply and OpenShift configuration steps succeed.
Note: Download resources for each operation that ELM marks as requiring an update. A single EIC archive can also update dependency resources, so review the actual manifests and configure every affected namespace. If ELM requests additional component downloads, repeat the procedure with those bundles; do not assume an earlier combined download satisfies a different operation or target version.
Optional: Exposing the Istio Ingress Gateway via OpenShift Routes
If your environment does not have a LoadBalancer provider (e.g., MetalLB), you can expose the Istio Ingress Gateway using OpenShift Routes instead.
Important: For restricted-access deployments, the Route must be created in the
istio-gatewaysnamespace (notistio-system), since that is where theistio-ingressgatewayservice resides.
For full instructions — including Route YAML examples, the manual service patch workaround, support scope, traffic flow with external load balancers, and operational restrictions — see Exposing the SAP EIC Istio Ingress Gateway in the Installation Guide.
Advanced: Multiple Service Mesh Instances
OpenShift Service Mesh 3.x supports deploying multiple service mesh instances on a single cluster. This advanced pattern allows the entire SAP ELM / EIC stack to run in its own isolated service mesh, separate from other applications on the same cluster. This offers a higher degree of security and autonomy.
The Istio CNI configuration created earlier (in Step 2 of the main flow) is cluster-wide and is reused by both the shared and dedicated control planes. You do not need to create an additional CNI namespace or IstioCNI resource for the dedicated mesh.
For detailed information about this feature, refer to the official Red Hat documentation: Deploying multiple service meshes on a single cluster.
When to Use This Configuration:
- Multi-tenancy: When multiple teams or applications share the same cluster
- Security isolation: When SAP workloads require complete network isolation
- Independent lifecycle management: When different mesh versions or configurations are needed
Discover Existing Service Mesh Instances
Before adding a dedicated mesh — or when a cluster already hosts more than one EIC / Istio instance — inventory what is already present so you don't collide with an existing control plane, revision, or namespace assignment.
1. List all Istio control planes and revisions:
# All Istio control planes (CRs) across the cluster, with their namespace and status
oc get istios.sailoperator.io -A
# All control plane revisions and their readiness (one per Istio, more during upgrades)
oc get istiorevisions.sailoperator.io -A
# The cluster-wide Istio CNI (shared by every mesh — there should be only one)
oc get istiocni.sailoperator.io -A
2. See which namespaces each control plane claims (its discovery selector):
# Print each Istio's name, control plane namespace, and discoverySelectors
oc get istios.sailoperator.io -A \
-o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.namespace}{"\t"}{.spec.values.meshConfig.discoverySelectors}{"\n"}{end}'
Each discoverySelectors entry (for example istio-discovery: enabled for the shared mesh, or istio-discovery: sap-edge-mesh for a dedicated SAP mesh) tells you the label a namespace needs to join that mesh. Pick a unique istio-discovery value for every new dedicated mesh so meshes do not overlap.
3. See which mesh each namespace currently belongs to:
# Show the mesh-related labels on every namespace at a glance
oc get namespaces -L istio-injection,istio-discovery,istio.io/rev
# List only the namespaces bound to a specific control plane revision
oc get namespaces -l istio.io/rev=sap-mesh-istio
# List all EIC namespaces on the cluster (across every EIC instance)
oc get namespaces -l edgelm.sap.com/product=edgelm
4. Confirm which revision actually injects sidecars (the injection webhooks):
# Each revision/named control plane registers its own injection webhook
oc get mutatingwebhookconfigurations -l istio.io/rev
# Inspect the running proxies per control plane namespace
oc get pods -n istio-system # shared mesh (default)
oc get pods -n istio-system-sap-edge # dedicated SAP mesh (if present)
Edge Node ownership: A dedicated service mesh does not resolve namespace ownership conflicts. Review ownership across the full bundle before applying resources. This section configures mesh isolation for one SAP deployment; confirm a supported namespace arrangement with SAP before attempting another Edge Node registration on the same cluster.
Alternative Deployment: Dedicated SAP Service Mesh
In the standard flow, Step 2: Configure OpenShift Service Mesh 3.x creates a shared service mesh used by SAP workloads and potentially other applications.
If you require stronger isolation or separate lifecycle management, you can replace Step 2 with the following dedicated mesh configuration.
All other steps (Step 1, Step 3) remain the same.
Prerequisites for this alternative path:
- You have completed Step 1: Install Service Mesh 3.x Operators
- The Istio CNI namespace and IstioCNI resource from Step 2 have already been created
If these prerequisites are not yet fulfilled, go back to the main flow and complete the CNI setup in Step 2 before proceeding.
Step 2 (Alternative): Deploy an Independent Control Plane for SAP
# Create dedicated namespace for SAP mesh
oc new-project istio-system-sap-edge
Choose the appropriate Istio configuration based on your environment:
Standard Configuration (Direct Internet Access):
# Create dedicated Istio resource with unique selector (standard)
oc apply -f - <<EOF
apiVersion: sailoperator.io/v1
kind: Istio
metadata:
name: sap-mesh-istio
namespace: istio-system-sap-edge
spec:
namespace: istio-system-sap-edge
values:
meshConfig:
discoverySelectors:
- matchLabels:
istio-discovery: sap-edge-mesh
EOF
Corporate Proxy Configuration (HTTP Proxy Required):
# Create dedicated Istio resource with unique selector (with corporate proxy support)
oc apply -f - <<EOF
apiVersion: sailoperator.io/v1
kind: Istio
metadata:
name: sap-mesh-istio
namespace: istio-system-sap-edge
spec:
namespace: istio-system-sap-edge
values:
meshConfig:
discoverySelectors:
- matchLabels:
istio-discovery: sap-edge-mesh
defaultConfig:
proxyMetadata:
ISTIO_META_DNS_CAPTURE: "true"
ISTIO_META_DNS_AUTO_ALLOCATE: "true"
EOF
Assign SAP Namespaces to the Dedicated Mesh
Understanding the labels
Moving the SAP namespaces from the shared mesh to the dedicated mesh changes two of the labels you applied in the main flow. The table below summarizes every Service Mesh label used, what it does, and the value it must have in each configuration:
| Label | Purpose | Shared mesh (main flow Step 2) | Dedicated SAP mesh (this section) |
|---|---|---|---|
istio-discovery |
Selects which namespaces a control plane watches. The value must match the control plane's discoverySelectors. |
enabled |
sap-edge-mesh |
istio.io/rev |
Binds a namespace to a specific control plane revision for sidecar injection. | (not used) | sap-mesh-istio |
istio-injection |
Enables sidecar injection via the default control plane webhook. | enabled |
(must be removed — conflicts with istio.io/rev) |
edgelm.sap.com/product |
SAP product identification; applied to all EIC namespaces. | edgelm |
edgelm (unchanged) |
The injection labels in this table apply to workload namespaces. Keep edge-icell-secrets without an injection-enabling label. Preserve SAP ownership metadata when changing mesh labels.
Key points:
istio-discoverychanges value, fromenabledtosap-edge-mesh, so the namespaces are discovered by the dedicated control plane (whosediscoverySelectorsmatchistio-discovery: sap-edge-mesh, as defined in theIstioresource above) instead of the shared one.- Injection switches mechanism. In the shared mesh, injection is driven by
istio-injection=enabled(the default webhook). In the dedicated mesh it is driven byistio.io/rev=sap-mesh-istio(the named revision). Having both labels on the same namespace causes conflicting injection — see the warning below. edgelm.sap.com/productis unaffected and stays on every EIC namespace.
After the application namespaces are created by the script (during Step 3), label them to join the dedicated mesh before continuing deployment in ELM. The commands below show the complete namespace set; after an individual bundle apply, include only the affected namespaces that already exist.
# Label the control plane namespace for discovery
oc label namespace istio-system-sap-edge istio-discovery=sap-edge-mesh --overwrite
# Assign all SAP-related namespaces to the dedicated mesh
oc label namespace edgelm edge-icell edge-icell-services edge-icell-secrets edge-icell-ela istio-gateways \
istio-discovery=sap-edge-mesh --overwrite
# Enable revision-based injection only for workload namespaces
oc label namespace edgelm edge-icell edge-icell-services edge-icell-ela istio-gateways \
istio.io/rev=sap-mesh-istio --overwrite
Important – Avoid Label Conflicts for Sidecar Injection
When using revision-based control planes, sidecar injection must be driven only by the istio.io/rev label.
Having both istio.io/rev=sap-mesh-istio and istio-injection=enabled on the same namespace can cause conflicts:
istio-injection=enabledtargets the default Istio control plane/webhook.istio.io/rev=sap-mesh-istiotargets the dedicated SAP mesh revision.
If both are present, injection behavior becomes unpredictable and may fail entirely if the default webhook is not configured for this mesh.
To clean up existing labels and rely solely on the revision label, run:
# Remove the legacy istio-injection label from all SAP namespaces (if present)
oc label namespace edgelm edge-icell edge-icell-services edge-icell-secrets edge-icell-ela istio-gateways istio-injection-
# Keep the secrets namespace without revision-based injection (if previously set)
oc label namespace edge-icell-secrets istio.io/rev-
# Optional: Verify the mesh labels and preserved SAP ownership labels
oc get namespace edgelm --show-labels
Important — Resource application re-adds
istio-injection=enabled:
Any namespace manifest that declaresistio-injection: enabledcan restore that label when applied. After every resource application, verify the dedicated discovery/revision labels and removeistio-injectionagain on all affected namespaces, including dependencies, before continuing deployment or upgrade. For the complete deployment:oc label namespace edgelm edge-icell edge-icell-services edge-icell-secrets edge-icell-ela istio-gateways istio-injection-
The istio.io/rev=sap-mesh-istio label on the namespaces ensures that sidecar injection for pods in these namespaces is handled by the dedicated SAP mesh control plane (sap-mesh-istio) instead of the shared mesh.
Optional: You can verify the available mesh revisions and confirm the sap-mesh-istio revision name by running:
oc get istiorevisions -n istio-system-sap-edge
Verify the Dedicated Mesh Deployment
# Wait for the dedicated control plane to be ready
oc wait --for=condition=Ready istio/sap-mesh-istio -n istio-system-sap-edge --timeout=600s
# Verify the dedicated control plane pods
oc get pods -n istio-system-sap-edge
# After the ELM bundle has created edgelm, verify its namespace labels
oc get namespace edgelm -o yaml | grep -A 10 labels
Wait for the dedicated control plane to be ready before starting Step 3: Register the Cluster in ELM. During Step 3, apply the dedicated mesh labels to each bundle's namespaces after its script succeeds and before continuing deployment in ELM.
Important Notes:
- This configuration creates isolation between SAP workloads and any other service mesh instances on the same cluster
- Use this approach when you need independent service mesh management or enhanced security isolation
- Both the shared and dedicated mesh approaches are supported — choose based on your cluster's multi-tenancy and isolation requirements
Comments