Skip to content

Set up remote deployment

Use this how-to to deploy Platform Mesh across multiple clusters, where the operator runs on one cluster but manages resources on separate runtime and infra clusters.

When to use this

Remote deployment fits scenarios where Platform Mesh's control-plane workloads cannot live on the same cluster as the operator. Common cases:

  • Separation of concerns — keep kcp, OCM, and the PlatformMesh resource on a dedicated runtime cluster, while the operator and GitOps tooling run elsewhere.
  • Shared GitOps cluster — a central cluster runs FluxCD or ArgoCD and rolls out releases to one or more runtime clusters.
  • Compliance or isolation — runtime workloads must run in a network or tenant boundary that the operator cluster cannot host.

If everything runs on the same cluster, you do not need this guide.

Alpha feature

Remote deployment is functional but limited to a single remote deployment per operator instance. APIs and Helm values may change.

Prerequisites

  • A running Kubernetes cluster for the operator (the operator cluster)
  • A separate Kubernetes cluster for the runtime workloads (the runtime cluster) — this is where kcp, OCM, and the PlatformMesh resource live
  • Optionally, a third cluster for FluxCD or ArgoCD (the infra cluster) — if not provided, the operator cluster serves this role
  • kubectl configured to access all clusters
  • Helm 3.x installed

Architecture overview

Remote deployment is considered when the Runtime and Infra clusters are different. FluxCD HelmReleases receive a kubeConfig.secretRef that tells FluxCD to deploy workloads to the runtime cluster. ArgoCD Applications receive a destination.server pointing to the runtime cluster API.

Step 1: Create a kubeconfig secret for the runtime cluster

Generate a kubeconfig that gives the operator access to the runtime cluster. Create a Secret on the operator cluster:

bash
kubectl create secret generic platform-mesh-kubeconfig \
  --namespace platform-mesh-system \
  --from-file=kubeconfig=<path-to-runtime-kubeconfig>

Step 2: Create a kubeconfig secret for FluxCD to reach the runtime cluster

FluxCD (running on the infra cluster) needs credentials to deploy workloads to the runtime cluster. Create a Secret on the infra cluster:

bash
kubectl create secret generic platform-mesh-runtime-secret \
  --namespace platform-mesh-system \
  --from-file=kubeconfig=<path-to-runtime-kubeconfig-for-fluxcd>

This secret is referenced by every HelmRelease via spec.kubeConfig.secretRef.

Step 3: (Optional) Create a kubeconfig secret for the infra cluster

If the operator does not run on the infra cluster (that is, Operator != Infra), create a Secret on the operator cluster with credentials to reach the infra cluster:

bash
kubectl create secret generic platform-mesh-infra-kubeconfig \
  --namespace platform-mesh-system \
  --from-file=kubeconfig=<path-to-infra-kubeconfig>

Skip this step if the operator runs on the same cluster as FluxCD or ArgoCD.

Step 4: Install the operator with remote deployment enabled

Install the platform-mesh-operator Helm chart with remote deployment values:

bash
helm install platform-mesh-operator \
  oci://ghcr.io/platform-mesh/helm-charts/platform-mesh-operator \
  --namespace platform-mesh-system --create-namespace \
  --set remoteRuntime.enabled=true \
  --set remoteRuntime.secretName=platform-mesh-kubeconfig \
  --set remoteRuntime.secretKey=kubeconfig \
  --set remoteRuntime.infra.secretName=platform-mesh-runtime-secret \
  --set remoteRuntime.infra.secretKey=kubeconfig

If Operator != Infra, also add:

bash
  --set remoteInfra.enabled=true \
  --set remoteInfra.secretName=platform-mesh-infra-kubeconfig \
  --set remoteInfra.secretKey=kubeconfig

Helm values reference

ValueDefaultDescription
remoteRuntime.enabledfalseEnable remote runtime cluster reconciliation
remoteRuntime.secretNameplatform-mesh-secretSecret with kubeconfig to reach the runtime cluster
remoteRuntime.secretKeykubeconfigKey within the secret
remoteRuntime.infra.secretNameplatform-mesh-secretSecret for FluxCD to deploy to the runtime cluster
remoteRuntime.infra.secretKeykubeconfigKey within the infra secret
remoteInfra.enabledfalseEnable remote infra cluster (only if Operator != Infra)
remoteInfra.secretNameplatform-mesh-kubeconfigSecret with kubeconfig to reach the infra cluster
remoteInfra.secretKeykubeconfigKey within the secret

Step 5: Create the PlatformMesh resource on the runtime cluster

The PlatformMesh CR and its profile ConfigMap must live on the runtime cluster. Switch your kubectl context to the runtime cluster and apply them:

bash
kubectl config use-context <runtime-cluster-context>

Create the profile ConfigMap:

yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: platform-mesh-sample-profile
  namespace: platform-mesh-system
data:
  profile.yaml: |
    infra:
      deploymentTechnology: fluxcd
      certManager:
        enabled: true
        name: cert-manager
        interval: 5m
        targetNamespace: cert-manager
        ocmResourceName: charts
        values:
          crds:
            enabled: true
    components:
      deploymentTechnology: fluxcd
      ocm:
        repo:
          name: platform-mesh
        component:
          name: platform-mesh
        referencePath:
        - name: core
      services:
        account-operator:
          enabled: true
          values:
            ingress:
              host: "account-operator.{{ .baseDomain }}"

Create the PlatformMesh resource:

yaml
apiVersion: core.platform-mesh.io/v1alpha1
kind: PlatformMesh
metadata:
  name: platform-mesh-sample
  namespace: platform-mesh-system
spec:
  exposure:
    baseDomain: example.com
    port: 443
    protocol: https
  ocm:
    repo:
      name: platform-mesh
    component:
      name: platform-mesh
    referencePath:
    - name: core
  kcp:
    providerConnections:
    - endpointSliceName: core.platform-mesh.io
      path: root:platform-mesh-system
      secret: platform-mesh-operator-kubeconfig
      adminAuth: true

The operator links the two resources by naming convention: a PlatformMesh instance named platform-mesh-sample expects a ConfigMap named platform-mesh-sample-profile in the same namespace. Override this with spec.profileConfigMap if needed.

Step 6: Verify the deployment

Check the operator logs on the operator cluster:

bash
kubectl logs -n platform-mesh-system -l app=platform-mesh-operator --tail=50

Verify the PlatformMesh resource status on the runtime cluster:

bash
kubectl get platformmesh -n platform-mesh-system -o yaml

Look for status conditions showing all subroutines succeeded:

yaml
status:
  conditions:
  - type: DeploymentSubroutine
    status: "True"
  - type: Ready
    status: "True"

Check that HelmReleases on the infra cluster include the kubeConfig reference:

bash
kubectl get helmreleases -n platform-mesh-system -o yaml | grep -A3 kubeConfig

Troubleshooting

SymptomLikely cause
Operator fails to startThe kubeconfig secret does not exist or has the wrong key
PlatformMesh not reconciledThe CR was created on the wrong cluster — it must be on the runtime cluster
HelmRelease stuckThe FluxCD kubeConfig.secretRef secret is missing on the infra cluster
cert-manager not readyOCIRepository not created yet — check ResourceSubroutine logs
EU and German government funding logos

Funded by the European Union – NextGenerationEU.

The views and opinions expressed are solely those of the author(s) and do not necessarily reflect the views of the European Union or the European Commission. Neither the European Union nor the European Commission can be held responsible for them.