# Config Syncer: keeping ConfigMaps and Secrets in step across clusters

> Config Syncer, the project formerly known as Kubed, is a Go controller that keeps ConfigMaps and Secrets synchronized across namespaces and across clusters. The code is still organised around the old kubed identity, the docs live on a vendor site, and the release tags stopped in 2022 while commits continued.

**config-syncer/config-syncer** — 🛡️ Kubernetes Config Syncer (previously kubed)

- Repository: https://github.com/config-syncer/config-syncer
- Website: https://config-syncer.com
- Stars: 1,015 · Forks: 103
- Language: Go
- License: Apache-2.0
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/config-syncer-config-syncer

## One source of truth for ConfigMaps and Secrets

Config Syncer is described in one line: it keeps ConfigMaps and Secrets synchronized across namespaces and/or clusters. The or in that sentence is the design decision, because the two cases are solved differently. Synchronising within one cluster means a controller watching for changes and copying a resource into one or more target namespaces. Synchronising across clusters means the resource has to travel over the network, which implies credentials, a transport and a conflict story.

The project is by AppsCode, and it was previously called Kubed. The rename is not complete in the code, which matters more than it sounds, and the repository reflects that in several places. The Go module path is kubeops.dev/config-syncer, the README badges still point at the kubeops organisation on GitHub, the Makefile defaults the API group to kubed:v1alpha1, and the documentation links all live under a products/kubed path on the vendor site. A reader arriving from the current name will find old names in every direction.

For a controller, the fact that it handles both Secrets and ConfigMaps is the interesting part, because Secrets need encryption at rest and tighter access control, and a syncer that copies them moves the sensitive data across a trust boundary.

## The kubed API group is still what the code registers

The Makefile is where the operational identity of the controller is written down, and it is worth reading even if you never build from source. The binary name is set with BIN := config-syncer, the API group default is API_GROUPS ?= kubed:v1alpha1, and the custom resource definition generation is controlled by CRD_OPTIONS, which defaults to allowDangerousTypes=true.

That last default deserves a second look. Allowing dangerous types in a CRD is a setting that lets a custom resource carry a field the API server would normally reject, and turning it on is often necessary for the data shapes a syncer needs to hold, such as embedded binary content. The tradeoff is a wider API surface on your cluster, and it is set on by default rather than being something you opt into.

The rest of the Makefile is a version strategy. The version string comes from git describe, and the strategy is a tag when the checkout is exactly on a tag, a branch name on a release- branch, and the commit hash otherwise. The container image registry defaults to appscode, and the code generator image is pinned to a release-1.25 tag of the gengo image from the same ghcr.io organisation, which tells you which Kubernetes release the code generation targets.

## A Go 1.18 codebase built against Kubernetes 1.25 libraries

The go.mod file gives the dependency picture, and it is a dated but coherent one. The module is declared for go 1.18, and the Kubernetes libraries are the 0.25 series: k8s.io/api, apiextensions-apiserver, apimachinery, apiserver and client-go at v0.25.1, with apimachinery at v0.25.3.

That pins the project to a Kubernetes 1.25 generation client. For a controller, that matters more than for an application, because the version skew policy means a client-go built against 1.25 is officially supported against a limited range of newer control planes, and the range has a defined end. The repository also vendors its dependencies, with a vendor/ directory at the root, which is what makes an air-gapped build possible and what makes the dependency set auditable without a network fetch.

The other dependencies are ordinary for this kind of project. cobra and pflag provide the command line, klog the logging, ginkgo and gomega the test framework, and a set of gomodules.xyz and kmodules.xyz packages from the same AppsCode ecosystem handle runtime helpers, certificate handling, blob storage and logging. A DCO file at the root tells you contributions require a Developer Certificate of Origin sign-off.

## The README points elsewhere for everything that matters

This repository has one of the thinnest READMEs in the projects you will read this year. It names the project, states what it does with a link to the product documentation, and then gives four links: installation, usage, contribution guidelines and support.

Every one of those leads to the vendor's documentation site, under the kubed product path. The install guide is at the setup/install page, the usage guide at the product root, and the contribution guide at the welcome/contributing page. Support is a contact form on the vendor's site, plus a Twitter account for announcements, and bugs or feature requests go to the GitHub issue tracker.

There is a real consequence here. A project whose entire onboarding path lives on a commercial vendor's site is a project whose documentation can change, move or be discontinued independently of the source code, and a self-hosted operator with an air-gapped cluster may not be able to reach it. The docs/ directory in the repository exists, so some material is vendored, but the README makes no claim about what the directory contains. Anyone planning a long-lived deployment should assume the vendor site is the reference and archive what it needs.

## Where a syncer is the wrong tool

The first wrong-tool case is a single cluster. If your ConfigMap needs to exist in three namespaces of one cluster, a controller that watches and copies is a lot of machinery, and a small Job that runs kubectl and copies the resource on a schedule, or a CI step that applies the same manifest to each namespace, does the same job with parts you already have. The syncer earns its place when the set of targets changes often enough that a manifest listing every target is a burden.

The second is a team whose source of truth is already a repository. When the desired state of a ConfigMap already lives in Git and is applied by a declarative controller, a second controller that copies it at runtime introduces two writers for the same object. The outcome depends on which one runs last, and the README does not describe a conflict resolution policy for a target namespace where a user has edited the resource by hand. The usual answer, a copy with a defined overwrite behaviour, is exactly the kind of detail that has to be tested rather than assumed.

The third is a security review that dislikes Secret replication. A syncer that copies Secrets between clusters needs credentials in both directions and widens the blast radius of a credential leak, and the Apache-2.0 licence and the source code tell you nothing about the deployment's threat model. If the only thing crossing the boundary is a non-sensitive ConfigMap, the exposure is smaller and the decision is easier.

## Apache-2.0, a 2022 tag, and commits that kept going

The project is licensed Apache-2.0, with the LICENSE file at the root, and the Makefile carries the standard Apache 2.0 header with the copyright lines for AppsCode Inc and the Kubernetes Authors, which reflects the project's origins in the Kubernetes community.

The release history needs reading carefully. The listed versions are v0.12.0 dated 2020-05-18, v0.13.0 dated 2022-01-03 and v0.13.2 dated 2022-02-24. So the newest tag is more than four years old, and the version number itself is still below 1.0, which says the authors treated it as a beta for its whole published life.

The repository is not archived, and the last push was on 2026-10-10, so work is still landing on the master branch without new tags. That combination is workable for a controller, because the container image is built from the branch rather than from a release, but it means there is no stable version to pin and no release notes to read. The Makefile's git-describe version strategy handles it, since a container built from a commit gets a hash-based version, but an operator who wants a version to write in a ticket has nothing to write down.

Given that, the reasonable posture is to pin a commit hash, read the diff between the commit you run and the one before it, and treat the vendor documentation as part of the deployment.

## Conclusion

Adopt Config Syncer if you run several Kubernetes clusters or many namespaces and need one ConfigMap or Secret source to propagate, and read the current installation guide on the vendor site rather than the repository README before you deploy. Do not adopt it for a single cluster with a handful of namespaces, where a small Job or a CI step that copies the resource will do the same work with fewer moving parts, and do not adopt it if you need an active open source community around the tool, because the release tags stopped at v0.13.2 in 2022 even though commits have continued into 2026. Before you install, confirm the CRD API group you will use, since the code still registers kubed:v1alpha1, and check the Apache-2.0 licence file at the root.

## FAQ

### What does Config Syncer do?

It keeps ConfigMaps and Secrets synchronized across namespaces and/or clusters. The project is by AppsCode and was previously called Kubed, which is still visible in the API group the code registers.

### How do I install Config Syncer?

The README points to an installation guide hosted on the vendor documentation site rather than giving commands in the repository. The docs live under the kubed product path, and the project has also been renamed from Kubed to Config Syncer.

### Which Kubernetes version does Config Syncer target?

The go.mod file depends on the Kubernetes 0.25 libraries, including client-go, api, apimachinery and apiserver, and the Makefile pins the code generator image to a release-1.25 tag. The module itself declares go 1.18.

### Is Config Syncer still being released?

The repository is not archived and the last push was on 2026-10-10, but the newest release tag is v0.13.2 from 2022-02-24. The project has stayed below version 1.0, so there is no stable release to pin and a commit hash is the practical pin.

### What licence is Config Syncer under?

Apache-2.0, with the LICENSE file at the repository root. The Makefile also carries the standard Apache 2.0 header with copyright lines for AppsCode Inc and the Kubernetes Authors.

## Sources

- [config-syncer/config-syncer on GitHub](https://github.com/config-syncer/config-syncer)
- [License: Apache-2.0](https://github.com/config-syncer/config-syncer/blob/master/LICENSE)
- [Project website](https://config-syncer.com)
- [README](https://github.com/config-syncer/config-syncer/blob/master/README.md)
- [Releases](https://github.com/config-syncer/config-syncer/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/config-syncer-config-syncer
