ConfigMaps that hold more than 50 keys
What does ZopNight detect here?
ZopNight flags any ConfigMap on EKS, GKE or AKS that holds more than 50 keys; ConfigMaps in kube-system and the other system namespaces are never collected, so never flagged. Such a map has usually become a shared dumping ground, which makes changes hard to review, pushes it toward the 1 MiB cap, and can force unrelated pods to restart together.
Signal and threshold
| Field | Value |
|---|---|
| Rule IDs | RC-1752 · RC-1852 · RC-1952 |
| Category | governance |
| Severity | low |
| Metric | key count |
| Threshold | more than 50 keys |
| Source | ZopNight |
| Permissions used | list configmaps |
Where it applies
A single oversized ConfigMap couples unrelated changes
A ConfigMap is meant to hold a small amount of configuration for one consumer. The ConfigMap documentation says plainly that it is not designed for large chunks of data and that its contents cannot exceed 1 MiB. Long before a map reaches that cap, a high key count causes a quieter problem: several teams or components start editing the same object.
Every edit then has a wide blast radius. Keys consumed as environment variables are not updated automatically; the pods reading them need a restart to see new values. So a one-line change for service A leads someone to restart service B as well, because both read the same map. Reviewing the diff is harder too, since a pull request touching one key sits beside dozens of keys nobody on the review owns.
Counting keys across every namespace
The DATA column of kubectl get configmaps -A shows the key count per map. ZopNight counts
keys in both data and binaryData, so to list only the maps above the rule’s line:
kubectl get configmaps -A -o json | jq -r ' .items[] | (((.data // {}) | length) + ((.binaryData // {}) | length)) as $n | select($n > 50) | "\(.metadata.namespace)/\(.metadata.name) \($n) keys"'To see which workloads mount or read a given map before you split it:
kubectl get pods -n <namespace> -o json | jq -r ' .items[] | select(tostring | contains("<configmap-name>")) | .metadata.name'The 50-key line and what ZopNight reads
The rule reads the key count ZopNight collected for each ConfigMap and fires when it is greater than 50. Exactly 50 keys does not fire. There is no time window: the count is read fresh each time the cluster is evaluated, and the finding clears on its own once the map drops to 50 keys or fewer.
Maps the check does not judge
A ConfigMap whose key count was not reported is skipped rather than guessed at. The rule does
not look at total byte size, so a map with a handful of very large values is not flagged here.
It also does not know who owns the keys: a generated map maintained by one tool, such as a
bundle of dashboards, can carry many keys for good reason. ConfigMaps in kube-system,
kube-public and kube-node-lease (and GKE’s own system namespaces) are not collected, so they are
never flagged.
Governance finding, no dollar amount
ConfigMaps are API objects and carry no cloud charge of their own, so this finding has no savings figure. Its value is operational: smaller maps mean smaller reviews, fewer surprise restarts and less risk of hitting the 1 MiB cap during a release.
Breaking the map apart
- Group the keys by the component or team that reads them. Prefixes in key names usually give the grouping away.
- Create one ConfigMap per group and point each workload at only the maps it needs.
- Roll the workloads so pods pick up the new references, then delete the old keys.
- For values that should never change after release, consider an immutable ConfigMap, stable since Kubernetes v1.21.
For the equivalent check on credentials, see Secret has excessive keys.