Skip to content

kubeadm: CoreDNS version is hardcoded to a single constant instead of resolved per Kubernetes version #3322

Description

@yashsingh74

Issue

kubeadm pins the CoreDNS version to be deployed to a single flat constant (constants.CoreDNSVersion, currently v1.14.4), used regardless of which Kubernetes version is being installed or upgraded to. Users can already override the deployed CoreDNS tag via ClusterConfiguration.dns.imageTag, but several code paths reference the raw constant directly instead of the resolved/overridden value, so the override doesn't fully propagate everywhere it should:

  • Corefile migration logic (phases/addons/dns/dns.go) migrates toward the hardcoded constant rather than the actually-deployed/overridden tag.
  • The CoreDNS upgrade preflight checks (phases/upgrade/preflight.go) validate migration compatibility against the hardcoded constant.
  • The suggested DNSVersion shown by kubeadm upgrade plan (phases/upgrade/compute.go) is a flat constant instead of being computed per target Kubernetes version, unlike the sibling EtcdVersion on the same lines.

There's also a maintenance-side problem: the upstream CoreDNS version does not get updated once a Kubernetes release branch is cut, which forces kubeadm to keep carrying the same pinned CoreDNS dependency for the lifetime of that branch. Combined with the hardcoded constant, this means there is no supported way to move off an older CoreDNS build on an existing release branch even when upstream ships a newer one.

This matters beyond consistency: newer CoreDNS releases are rebuilt against newer Go toolchain versions, which routinely carry Go CVE fixes. Because the override doesn't propagate everywhere today, a user who explicitly sets dns.imageTag to a newer CoreDNS build to pick up those fixes doesn't get consistent behavior across kubeadm. The migration/preflight/upgrade-plan logic still reasons about the old hardcoded version instead of the version the user actually asked to run. Users should be able to opt into a newer, more secure CoreDNS build without kubeadm second-guessing that choice in some code paths but not others.

What did you expect to happen?

CoreDNS should follow the same override model that etcd already has:

  • A SupportedCoreDNSVersion map (keyed by Kubernetes minor version) with a resolver function
  • GetDNSImage a new GetDNSImageTag helper should resolve the default from that map (falling back to the nearest version with a warning if the target Kubernetes version isn't covered yet), then apply cfg.DNS.ImageTag on top if set.
  • Corefile migration, the CoreDNS upgrade preflight checks, and the kubeadm upgrade plan suggested DNSVersion should all consult the resolved/overridden version instead of the raw constant, so a user's override — including overriding to a newer CoreDNS build for CVE/security reasons — is honored consistently everywhere, not just in the deployed manifest.

This does not require any new API field — ClusterConfiguration.dns.imageTag dns.imageRepository already exist and already provide the override surface.

Created a PR addressing the changes -

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/corednskind/bugCategorizes issue or PR as related to a bug.kind/featureCategorizes issue or PR as related to a new feature.priority/backlogHigher priority than priority/awaiting-more-evidence.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions