Guide: Setting Up a Restricted-Access OpenShift Cluster for SAP Edge Lifecycle Management (ELM) with Service Mesh 3.x

Updated -

Part of: SAP Edge Integration Cell on Red Hat OpenShift

Table of Contents

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 oc CLI 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
  • kubectl on your PATH — required by the bundled apply-restricted-resources.sh script used to apply downloaded resources. The script invokes kubectl by name, so an oc-only installation does not satisfy it.
  • The same administrator kubeconfig and target context for kubectl and oc — the script uses the active kubectl context; 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:

  1. Install Operators: Install the Red Hat OpenShift Service Mesh 3.x Operators.
  2. Configure Service Mesh 3.x: Deploy and customize the Red Hat OpenShift Service Mesh 3.x to manage network traffic.
  3. 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:

  1. Log in to the OpenShift web console.
  2. Navigate to Operators → OperatorHub.
  3. Search for Red Hat OpenShift Service Mesh.
  4. Select the Service Mesh 3.x version.
  5. 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 ECONNRESET errors or 404 route_not_found responses.

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 edgelm namespace 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 under addresses. 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 as i/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 addresses list 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:

  1. Initialize Edge Node — Apply the ELM resources, generate the Kubeconfig, and upload it to complete registration.
  2. 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 apply merges 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

  1. In the ELM UI, start the Add an Edge Node process.
  2. On the first stage, Provide Edge Node Details, enter a name for your Edge Node.
  3. 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
  4. When you reach the Initialize Edge Node stage, click Download Kubernetes Resources to download the resource files.
  5. Extract the archive into its own directory and use its bundled apply-restricted-resources.sh script. 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.

  1. Apply the OpenShift SCC annotation and Service Mesh labels to the edgelm namespace. Configure these explicitly even when the downloaded namespace manifest already includes some of the labels:

Note: At this stage, only the edgelm namespace 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 for edgelm instead.

# 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
  1. Generate the Kubeconfig file. The downloaded resources created the edgelm namespace 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 edgelm service account in the edgelm namespace.

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 --minify copies 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-kubeconfig

Re-run the auth can-i test 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
  1. Back in the ELM UI:

    1. Check the "I confirm that I have downloaded and applied resources" checkbox
    2. Upload the edgelm-kubeconfig file you generated in the previous step
    3. Enter a Context Password and click Download Bootstrapping File
    4. Proceed with the rest of the configuration as guided by the UI
  2. 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 edgelm namespace exists.
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
  1. Navigate to All Deployments in the ELM UI
  2. Locate the component (e.g., IstioGateways, Edge Integration Cell)
  3. Click the "..." (actions menu) for the component
  4. Select "Download Kubernetes Resources"
  5. 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
  1. 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-injection on the affected workload namespaces.

Resource update procedure — after you initiate an upgrade and its status changes to Prepared:

  1. 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.
  2. 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
    
  3. After the script succeeds, re-apply and verify SCC annotations and Service Mesh labels for all affected namespaces. Use the edgelm commands 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.

  4. 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-gateways namespace (not istio-system), since that is where the istio-ingressgateway service 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-discovery changes value, from enabled to sap-edge-mesh, so the namespaces are discovered by the dedicated control plane (whose discoverySelectors match istio-discovery: sap-edge-mesh, as defined in the Istio resource 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 by istio.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/product is 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=enabled targets the default Istio control plane/webhook.
  • istio.io/rev=sap-mesh-istio targets 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 declares istio-injection: enabled can restore that label when applied. After every resource application, verify the dedicated discovery/revision labels and remove istio-injection again 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