KubernetesLXXIV · kubeadmkubeadm
kubeadm-config ConfigMap — ClusterConfiguration, KubeletConfiguration
What you'll learn
- Identify the kubeadm-config ConfigMap contents
- Read ClusterConfiguration, KubeletConfiguration
- Edit the ConfigMap safely for cluster-level changes
- Plan upgrades while preserving the ConfigMap
Prerequisites
Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16
kubeadm init writes a ConfigMap to
kube-system/kubeadm-config. This ConfigMap holds the
cluster’s ClusterConfiguration and KubeletConfiguration
and is the source of truth for upgrade and config-edit
operations. This lesson walks its contents, the runtime
behaviour, and the production discipline of editing it.
The ConfigMap
kubectl -n kube-system get configmap kubeadm-config -o yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: kubeadm-config
namespace: kube-system
data:
ClusterConfiguration: |
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
kubernetesVersion: v1.34.0
networking:
serviceSubnet: 10.96.0.0/12
podSubnet: 10.244.0.0/16
controlPlaneEndpoint: loadbalancer.example:6443
etcd:
local:
dataDir: /var/lib/etcd
scheduler: {}
apiServer:
extraArgs:
authorization-mode: Node,RBAC
...
...
KubeletConfiguration: |
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
...
Two main sections:
- ClusterConfiguration. The cluster-level config: networking, etcd, API server args, scheduler args.
- KubeletConfiguration. The kubelet config: resource handling, eviction, etc.
What’s in ClusterConfiguration
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
networking:
serviceSubnet: 10.96.0.0/12
podSubnet: 10.244.0.0/16
dnsDomain: cluster.local
kubernetesVersion: v1.34.0
controlPlaneEndpoint: loadbalancer.example:6443
etcd:
local:
dataDir: /var/lib/etcd
apiServer:
extraArgs:
authorization-mode: Node,RBAC
enable-admission-plugins: NodeRestriction
...
extraVolumes:
- hostPath: /etc/kubernetes/encryption-config.yaml
mountPath: /etc/kubernetes/encryption-config.yaml
name: encryption-config
readOnly: true
controllerManager:
extraArgs:
...
scheduler:
extraArgs:
...
dns: {}
Each control-plane component’s extraArgs is here.
What’s in KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
authentication:
anonymous:
enabled: false
webhook:
enabled: true
x509:
clientCAFile: /etc/kubernetes/pki/ca.crt
authorization:
mode: Webhook
clusterDNS:
- 10.96.0.10
clusterDomain: cluster.local
evictionHard:
memory.available: 100Mi
nodefs.available: 10%
evictionPressureTransitionPeriod: 5m0s
imageGCHighThresholdPercent: 85
imageGCLowThresholdPercent: 80
maxPods: 110
The KubeletConfiguration is applied to every kubelet in the cluster (via the kubelet’s static pod manifest).
$ kubectl -n kube-system get configmap kubeadm-config -o yaml | head -100...Where the ConfigMap is read
The ConfigMap is read by:
- kubeadm upgrade (during a Kubernetes upgrade).
- The kubelet reconciler. The kubelet on each host reads the ConfigMap, applies KubeletConfiguration.
- Manual config edits via
kubeadm init phase.
flowchart LR
CM[kubeadm-config] -->|upgrade| KU[kubeadm upgrade apply]
CM -->|kubelet config| KR[kubelet reconciler]
CM -->|config commands| KO[kubeadm phase commands]
Editing the ConfigMap
To apply a cluster-level config change:
# Edit the ConfigMap
kubectl -n kube-system edit configmap kubeadm-config
# Then apply the change with kubeadm
sudo kubeadm init phase kubelet-finally
# or
sudo kubeadm upgrade node
Two things together: edit the ConfigMap and run the phase command. The phase command reads the ConfigMap and applies the change.
Common ConfigMap edits
Change the API server args
kubectl -n kube-system edit configmap kubeadm-config
# data.ClusterConfiguration.apiServer.extraArgs:
# add: --enable-profiling=true
Then on each control-plane host:
sudo kubeadm upgrade apply v1.34.1
Or via kubeadm init phase (more targeted):
sudo kubeadm init phase control-plane apiserver
Change the kubelet config
kubectl -n kube-system edit configmap kubeadm-config
# data.KubeletConfiguration.evictionHard.memory.available:
# change from "100Mi" to "200Mi"
Then on each host (control plane + workers):
sudo kubeadm upgrade node
# Or, kubeadm init phase kubelet-final
# Or, simply restart kubelet
The upgrade preserves the ConfigMap
kubeadm upgrade apply reads the ConfigMap and preserves
customisations not in the upgrade’s defaults:
sequenceDiagram
participant Op as Operator
participant KU as kubeadm upgrade
participant CM as kubeadm-config
participant ES as Static pod manifests
Op->>KU: kubeadm upgrade apply v1.34.1
KU->>CM: read ClusterConfiguration
KU->>KU: merge new defaults + customisations
KU->>CM: update ClusterConfiguration
KU->>ES: update static pod manifests
KU->>ES: restart static pods
Customisations like --enable-admission-plugins are
preserved; the upgrade does not overwrite them.
What is NOT in the ConfigMap
- Application-level configs (CNI, ingress, etc.).
- Custom manifests (operator-installed resources).
- RBAC bindings.
- Pods (their manifests are not in the ConfigMap).
The ConfigMap is the kubeadm-managed config; everything else is application-managed.
The kubeadm init phase subcommands
The phase commands that read the ConfigMap:
sudo kubeadm init phase apiserver # write API server static pod
sudo kubeadm init phase controller-manager
sudo kubeadm init phase scheduler
sudo kubeadm init phase etcd
sudo kubeadm init phase kubelet-finally # kubelet config
sudo kubeadm init phase certs
sudo kubeadm init phase kubeconfig
sudo kubeadm init phase bootstrap-token
Each phase is idempotent and reads the ConfigMap.
The control plane vs worker ConfigMaps
- Control plane hosts read
ClusterConfigurationfor static pod manifests. - All hosts (control + worker) read
KubeletConfigurationfor kubelet behavior.
A worker host’s kubelet reads the kubelet config in
kubeadm-config. The reconciler on every host applies it.
The reset of the ConfigMap
To reset:
sudo kubeadm reset
# Removes the kubeadm-managed state
# including /etc/kubernetes/pki/ca.crt is not removed (PKI preserved)
# The kubeadm-config ConfigMap is preserved (it's in the cluster)
After reset, the host is clean for a re-init / re-join.
$ kubectl -n kube-system get cm kubeadm-config -o jsonpath='{.data.ClusterConfiguration}' | head...The kubeadm upgrade apply outputs the merged config
Components that must be started manually after upgrade: None
Upgrade context:
- Config from "kubeadm-config" ConfigMap:
ClusterConfiguration:
apiServer:
extraArgs:
authorization-mode: Node,RBAC
...
etcd:
local:
dataDir: /var/lib/etcd
networking:
podSubnet: 10.244.0.0/16
serviceSubnet: 10.96.0.0/12
- Kubernetes version: v1.34.0 -> v1.34.1
The upgrade uses the existing ClusterConfiguration; the
new defaults are merged.
The output shows the merged config; the operator can inspect it before proceeding.
The discipline
- Treat the ConfigMap as configuration source-of-truth. Edit it for changes; apply via kubeadm.
- Pair ConfigMap edits with phase commands. Edit-only is a no-op; phase-only is missing the change.
- Validate after edits.
kubectl get ...confirms the change took effect. - Test changes on staging. A ConfigMap edit that applies to all nodes is a wide-blast-radius change.
- Document the ConfigMap’s purpose. A runbook entry on ConfigMap edits is essential.
Quiz
Knowledge check · 4 questions
Q1. What does the `kubeadm-config` ConfigMap contain?
Q2. Editing the kubeadm-config ConfigMap applies the changes automatically.
Q3. The team wants to add `--enable-profiling=true` to the API server. Walk the procedure.
Cluster: 3-host stacked. The API server currently has no profiling flag.
Q4. Why does kubeadm upgrade preserve the ConfigMap's customisations?
Passing score: 75%. Answers are checked in this browser.
Production discipline
- The ConfigMap is the cluster’s config. Treat edits with the discipline of any config-as-data system.
- Pair edits with phase commands. The pair is the procedure.
- Test on staging. ConfigMap edits apply to all hosts at once.
- Document every change. The ConfigMap’s history tells the cluster’s story.
- Validate post-edit. kubectl / crictl confirm the change took effect.
The ConfigMap is the cluster’s introspection surface; operating it well is keeping the cluster’s configuration intentional and documented.