MeshSync is a standalone Go binary, one instance per managed Kubernetes cluster. It has no HTTP API and no persistent store of its own: it watches the API server via dynamic informers, converts each object into a canonical model, deduplicates, and publishes the result over NATS (default) or to a snapshot file.
main.go --parses CLI flags--> pkg/lib/meshsync.Run(...)
|
v
meshsync.Handler (meshsync/meshsync.go)
| dynamic informer factory (client-go)
v
internal/pipeline.New(...) <-- rebuilt every run/resync
|
+-----------------+------------------+
| Global-resource | Local-resource | StartInformers
| discovery stage | discovery stage | stage
+-----------------+------------------+
|
v
internal/output.Writer (broker | file | composite)
| with internal/output dedup
v
NATS broker (Meshery Server consumes it) or snapshot file
main.goparses flags (-output,-outputFile,-outputNamespaces,-outputResources,-stopAfter) and callspkg/lib/meshsync.Run(...).meshsync.Handler(meshsync/meshsync.go) holds the config, logger, broker handle, dynamic informer factory, kube client, channel pool, output writer, and output-filtration config.meshsync.New(...)wires them together and derives the cluster ID viapkg/utils.GetClusterID.GetDynamicInformerbuilds adynamicinformer.DynamicSharedInformerFactory. Resource filtering happens in the watch-list config (internal/config/crd_config.godecides which informers get registered); the factory's list-options hook (GetListOptionsFunc) is a deliberate no-op.
- Built on
github.com/myntra/pipeline.pipeline.New(...)constructs fresh stages on every call - it runs once at startup and again on every resync, so stages/steps must never be cached in package-level state (a shared stage would retain a shut-down informer factory and a closed stop channel from a prior run). - Three stages, run in order: global-resource discovery, local-resource discovery (both register one informer step per configured resource kind, skipping any kind excluded by
outputFiltration.ResourceSet), then StartInformers (starts every registered informer against the given stop channel). internal/pipeline/step.godefines the per-resource-kind informer registration step;internal/pipeline/handlers.goare the Add/Update/Delete event callbacks that convert an informer event into amodel.KubernetesResourceand hand it to the output writer.
config.go/default_config.go/crd_config.godefine the discoverable resource set (global vs. local/namespaced), whitelist/blacklist, and pluralization (pluralise.go) needed to map a Kind to its API resource.OutputFiltrationContainer/OutputResourceSet(referenced frommeshsync.Handler) carry the-outputNamespaces/-outputResourcesCLI restrictions through to the pipeline and output writer.
output.Writeris the single interface consumed by the pipeline:Write(obj model.KubernetesResource, evtype broker.EventType, config config.PipelineConfig) error.- Implementations:
broker.go(publishes to the MeshKitbroker.Handler, i.e. NATS),file.go(writes a cluster snapshot viainternal/file),composite.go(fans out to multiple writers - used when both broker and file output are needed). inmemory_deduplicator*.gosuppresses redundant republishes of unchanged resources;processor.gois the shared write-path plumbing.
model.KubernetesResource(plusKubernetesResourceObjectMeta,KubernetesResourceSpec,KubernetesResourceStatus,KubernetesKeyValue) is MeshSync's canonical wire/DB shape - a local Go/GORM struct, not generated fromgithub.com/meshery/schemas. See naming conventions for the casing implications.model_converter.go/preprocessor.goconvert a rawunstructured.Unstructuredinformer object into this model;exec.go/log.go/process.gohandle exec-stream and log-stream requests routed in over the broker (seemeshsync/exec.go,meshsync/logstream.go).
channel.go/generic.go/system.go/broker.godefine small typed channels (e.g.StructChannel) used for coordination (stop signals, broker request/response) between the handler and the pipeline - not a general pub/sub system.
- Meshery Server routes interactive
kubectl execand pod-log requests to MeshSync over the broker;meshsync/exec.go(processExecRequest) andmeshsync/logstream.go(processLogRequest) start one long-lived goroutine per request, keyed by a request id. - These per-session channels live in a
sync.Mutex-guardedsessionsmap on the Handler (meshsync/sessions.go), deliberately separate fromchannelPool, which holds only the fixed system channels (Stop/OS/ReSync) and is read-only after construction. Keeping them apart avoids the concurrent map read/write panic that occurred when session goroutines mutated the same map other goroutines ranged. - An exec session subscribes to its own
input.<id>subject (client keystrokes) viaSubscribeWithChannel. On teardown - stream EOF/error, an explicit stop request, or the globalStop-terminate()runs once (guarded by async.Once) and callsbroker.Handler.Unsubscribe("input.<id>"), which releases the subscription and the broker's delivery goroutine. Before MeshKit exposedUnsubscribe(v1.0.22), the subscription could not be torn down and each session parked a drain goroutine that never exited, leaking a goroutine and a subscription per session.
- Meshery Operator's
MeshSynccontroller (meshery/meshery-operator,pkg/meshsync/meshsync.go) renders this binary as aDeploymentand injectsBROKER_URLpointing at the Broker's derived NATS endpoint. See that repo's architecture doc for the reconcile side. - Meshery Server subscribes to the NATS subjects MeshSync publishes on and persists/serves the resulting resource state; the
pkg/model.KubernetesResourceshape is the de facto contract between the two. - Coordinate CLI flag, config-schema, or model changes with both
meshery-operatorandmeshery(server) - this repo does not own the full contract in isolation.
- design-spec: MeshSync infrastructure synchronization - discovery concepts, tiered discovery, composite prints, user stories
- design-spec: embedded MeshSync - proposal for running MeshSync in-process inside Meshery Server