docs/content/en/guides/infrastructure-management/managing-existing-infrastructure.md
Most clusters do not arrive empty. They carry months or years of accumulated Deployments, CRDs, operators, and Secrets, deployed by pipelines that predate Meshery and that will keep running after it. This guide is for the platform engineer bringing that kind of estate - a brownfield - under Meshery's management: what connecting a live cluster actually does, what it deliberately does not do, and what to evaluate before you connect.
The short version: greenfield versus brownfield is a non-event for Meshery's discovery model. [MeshSync]({{< ref "concepts/architecture/meshsync.md" >}}) performs read-only discovery of whatever the cluster already contains. Meshery does not require that resources be created through it, does not modify what it finds, and continues to discover resources created outside of it for as long as the cluster is connected. That last part is not an edge case - it is the operating model.
For the underlying concepts, see the canonical references:
{{% alert color="info" title="What 'management' means at each stage" %}} Discovery populates Meshery's inventory: a continuously refreshed, read-only snapshot of the cluster. Management actions - deploying or undeploying a [Design]({{< ref "concepts/logical/designs.md" >}}), transitioning a Connection's state - are separate, explicit, and user-initiated. Connecting a cluster never mutates the workloads already running on it. {{% /alert %}}
When MeshSync starts against a cluster, its informers first list every resource type in scope - delivering each pre-existing object to Meshery as a discovered resource - and then watch for subsequent changes. The initial listing is the brownfield snapshot; the watch keeps it current. There is no requirement that a resource carry any particular label or annotation to be discovered.
Meshery does not brand what it deploys, either: resources created by deploying a Meshery [Design]({{< ref "concepts/logical/designs.md" >}}) reach the cluster carrying exactly the metadata the design declares - Meshery Server does not inject identifying labels or annotations at deploy time - and discovery treats them identically to resources that predate Meshery. Your inventory is one uniform, continuously refreshed view of the cluster, whatever created its contents.
Connecting an existing cluster is the same flow as connecting any cluster - the [Connection Wizard]({{< ref "guides/infrastructure-management/registering-a-connection.md" >}}) or mesheryctl. Mechanically, this is what takes place:
/livez endpoint and registers the cluster's component models) to [Connected]({{< ref "concepts/logical/connections/index.md#state-connected" >}}) in the same import. Unreachable contexts remain Discovered until you act on them.meshsync_deployment_mode metadata on the Connection):
meshery namespace). The operator in turn deploys [Meshery Broker]({{< ref "concepts/architecture/broker/index.md" >}}) (NATS) and MeshSync, and injects the Broker address into MeshSync as BROKER_URL. Administrators can also disable operator deployment server-wide with the DISABLE_OPERATOR environment variable on Meshery Server.GET /api/system/meshsync/resources.Meshery models a Connection's lifecycle with explicit states - Discovered, Registered, Connected, Ignored, Maintenance, Disconnected, Deleted, and Not Found - documented in [States and the Lifecycle of Connections]({{< ref "concepts/logical/connections/index.md#states-and-the-lifecycle-of-connections" >}}). For an estate you already operate, the practical readings are:
Two honest footnotes, verified against Meshery Server's Kubernetes state machine: the Maintenance state, while defined for Connections generally, is not currently part of the implemented Kubernetes transition set; and Not Found is where a Connection lands when registration cannot verify the cluster (you can delete it or re-register once the cluster is reachable).
MeshSync's code performs no writes against your cluster - it lists and watches. Its effective reach, and the enforcement of that read-only posture, depend on the deployment mode:
Embedded mode runs discovery under the identity in the kubeconfig you upload. Its RBAC is that identity's RBAC - no more, no less. For a locked-down cluster, this is the least-privilege path: create a dedicated read-only user or ServiceAccount context scoped to exactly the namespaces and resource types you want discovered, and upload that. If the identity cannot read a resource type, that type is simply not discovered.
Operator mode installs the meshery-operator Helm chart, whose ClusterRole is deliberately narrow - no wildcards. It grants create/delete/get/list/patch/update/watch on core configmaps, secrets, and services, and on deployments and statefulsets (apps) - the resources the operator manages to run Broker and MeshSync - plus full control of its own brokers.meshery.io and meshsyncs.meshery.io custom resources and create on tokenreviews and subjectaccessreviews.
Two consequences follow. First, MeshSync's Deployment runs under the same meshery-operator ServiceAccount - there is no separate, read-only MeshSync role - so MeshSync's read-only behavior is a property of its code, not of a dedicated RBAC boundary. If you require RBAC-enforced read-only discovery, use embedded mode with a read-only identity. Second, discovery in operator mode is bounded by that same role: resource types it does not authorize (Pods, Nodes, Namespaces, CRDs, and much of MeshSync's default watch list) are not readable, and therefore not discovered, until a cluster administrator explicitly grants additional get/list/watch permissions to the meshery-operator ServiceAccount. Nothing self-escalates; widening discovery is a deliberate act.
In-cluster Meshery Server (the meshery Helm chart) is the opposite end of the spectrum: its ServiceAccount is bound to a ClusterRole granting * on *. If Meshery Server itself runs in a cluster, discovery of that local cluster is effectively unrestricted, and the server holds write access it uses for deploying designs. Factor this into which cluster hosts your Meshery Server.
/livez probe); if the API endpoint in your kubeconfig is private, the Connection will not progress past Discovered.ClusterIP - reachable only from inside the cluster. That works when Meshery Server runs in the same cluster; an out-of-cluster server (your laptop, another cluster, a SaaS deployment) needs the Broker exposed via the Broker custom resource's spec.service.type (NodePort or LoadBalancer) or an explicit spec.service.externalEndpointOverride for ingress and NAT topologies. The operator publishes the resolved address in the Broker's status.endpoint.For the specific service-networking and endpoint knobs, see [Configuring Meshery Operator, MeshSync, and Broker]({{< ref "guides/infrastructure-management/configuring-operator-meshsync-broker.md#broker-service-networking" >}}).
The first sync lists every object of every watched resource type. On a large brownfield cluster, this causes a burst of load on the API server, a burst of traffic to the Broker (operator mode), and a burst of writes into Meshery's database. There are no rate or depth tuning knobs in MeshSync today; scoping is the lever:
MeshSync custom resource's watch-list (see the [MeshSync FAQs]({{< ref "concepts/architecture/meshsync.md#meshsync-faqs" >}}) for exact syntax).--outputNamespaces and --outputResources filters.The full set of scoping and deployment knobs, and where each is configured, is covered in [Configuring Meshery Operator, MeshSync, and Broker]({{< ref "guides/infrastructure-management/configuring-operator-meshsync-broker.md#configuring-meshsync" >}}).
MeshSync's default watch list includes secrets.v1., and Secret values are published to Meshery unredacted by default. On a brownfield cluster this means credentials that predate Meshery flow into its inventory the moment discovery starts. Decide your posture before connecting, not after:
MESHSYNC_REDACT_SECRETS=true on the MeshSync process to replace every value in a discovered Secret's data with [REDACTED] while preserving the keys - the inventory still shows that Secrets exist and how they are shaped, without their contents.secrets.v1. in the watch-list so Secrets are not discovered at all.get/list/watch on Secrets; in operator mode, do not grant Secret read access beyond what the chart requires. What cannot be read cannot be published.(Optional) Rehearse discovery offline. MeshSync's file output mode captures a point-in-time snapshot of a cluster to local YAML with nothing installed and no Broker involved - a zero-commitment preview of exactly what discovery would collect. The [kubectl meshsync snapshot]({{< ref "extensions/extensions/kubectl-meshsync-snapshot/index.md" >}}) plugin packages this.
Connect the cluster. In the Meshery UI (Lifecycle → Connections → Create Connection → Kubernetes), upload your kubeconfig, select the contexts to import, and choose each context's MeshSync deployment mode - embedded if you are not ready to install anything into a production cluster, operator for in-cluster, event-streamed discovery. Full steps: [Registering a Connection]({{< ref "guides/infrastructure-management/registering-a-connection.md" >}}). For managed clouds, mesheryctl system config aks|eks|gke|minikube uploads the context for you.
Verify component health. Confirm the Connection shows Connected in the Connections table. In operator mode, verify the in-cluster components:
mesheryctl system check --operator
This checks the Meshery Operator, Broker, and MeshSync deployments and the Broker's advertised endpoint. For deeper, kubectl-level checks (MeshSync's /healthz and /readyz probes, BROKER_URL wiring), see [MeshSync's common tasks]({{< ref "concepts/architecture/meshsync.md#common-tasks" >}}) and the [troubleshooting guide]({{< ref "guides/troubleshooting/meshery-operator-meshsync.md" >}}).
Watch the inventory populate. Your estate appears in Meshery's dashboard and resource views as the initial listing completes - existing resources first, then live updates as your clusters change. On a large estate, give the first sync time to finish before judging completeness. From the CLI:
mesheryctl connection list --kind kubernetes
Scope discovery to what you care about. If the inventory is noisier than useful - or the initial sync is heavier than you want - narrow the watch list and output filters (see the checklist above) and restart MeshSync to apply.
Organize and share. Assign the Connection to an [Environment]({{< ref "concepts/logical/environments.md" >}}), and the Environment to a [Workspace]({{< ref "concepts/logical/workspaces.md" >}}), to make the cluster available to your team with scoped access.
Operate deliberately. Discovery has populated the inventory; management actions remain yours to initiate:
?asDesign=true) for visualization and evaluation. There is no import source that persists a design from live cluster state today - designs are imported from Kubernetes manifests, Helm charts, Docker Compose files, or existing design files. If your estate's manifests live in Git, import those directly: mesheryctl design import -f ./manifests.yaml -s "Kubernetes Manifest" (see [design import]({{< ref "reference/references/mesheryctl/design/import.md" >}})).exec sessions and log streaming, available in operator mode via the Broker) are active operations inside your workloads - user-initiated, on demand, and only possible if MeshSync's ServiceAccount is granted create on pods/exec and get on pods/log, which the current chart RBAC does not include by default.{{< discuss >}}