Skip to main content
RunBook Academy

KubernetesLXXIV · kubeadmkubeadm

kubeadm-config ConfigMap — ClusterConfiguration, KubeletConfiguration

Advanced⏱ ~17 minkubectlkubeadm

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

Not yet marked complete on this device.

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).

Read-only / Safe
$ 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 ClusterConfiguration for static pod manifests.
  • All hosts (control + worker) read KubeletConfiguration for 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.

Read-only / Safe
$ 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

  1. Q1. What does the `kubeadm-config` ConfigMap contain?

  2. Q2. Editing the kubeadm-config ConfigMap applies the changes automatically.

  3. 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.

  4. 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.