k8s-bootstrap: add kubeadm:bootstrap-signer-clusterinfo RBAC for AKS#61
Merged
Merged
Conversation
The cluster-info ConfigMap in kube-public is read by kubeadm during the discovery phase of `kubeadm join`. Stock kubeadm provisions a Role+RoleBinding for it as part of `kubeadm init` and binds the RoleBinding to `Group=system:anonymous` (so kubeadm clients can read the ConfigMap before they have a bootstrap identity). That binding is dead on AKS: AKS sets `--anonymous-auth=false` cluster-wide, so the discovery client falls back to its bootstrap-token identity (`system:bootstrappers:kubeadm:default-node-token` and `system:bootstrappers`) and the API server returns 403 — surfaced by kubeadm as the misleading [discovery] Error reading the cluster-info ConfigMap, will try again: Unauthorized Without this RBAC, every `kubeadm join` against an AKS cluster loops on discovery until the parent timeout fires. Adding the Role+RoleBinding bound to the bootstrap-token groups makes node join work on a fresh cluster with no manual kubectl patching. Verified end-to-end on voice-agent-flex (westeurope) joining `Standard_ND96isr_H200_v5` nodes from eastus2 via aks-flex-node v0.0.18.
Contributor
There was a problem hiding this comment.
Pull request overview
Adds the missing kubeadm discovery RBAC to the config k8s-bootstrap manifest so bootstrap-token identities (used on AKS where anonymous auth is disabled) can read kube-public/cluster-info during kubeadm join.
Changes:
- Add a
Roleinkube-publicgrantinggeton thecluster-infoConfigMap. - Add a matching
RoleBindingbinding that Role tosystem:bootstrappersandsystem:bootstrappers:kubeadm:default-node-token(instead ofsystem:anonymous).
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
anson627
approved these changes
Apr 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The
config k8s-bootstraptemplate provisions thekube-public/cluster-infoConfigMap (which kubeadm reads during the discovery phase of
kubeadm join)but does not provision the Role+RoleBinding that authorizes reading it.
Stock kubeadm normally creates this RBAC during
kubeadm initand binds theRoleBinding to
Group=system:anonymous, which works on self-managed clusterswhere anonymous auth is enabled. On AKS,
--anonymous-auth=falseis setcluster-wide, so:
identities
system:bootstrappersandsystem:bootstrappers:kubeadm:default-node-token.getonkube-public/cluster-info.[discovery] Error reading the cluster-info ConfigMap, will try again: Unauthorized.kubeadm joinloops on discovery until the parent timeout fires.Without manual kubectl patching, every fresh AKS cluster fails the very first
remote-node join attempt.
Fix
Add the Role+RoleBinding to the embedded
config.yamltemplate, scoped tokube-public, grantinggeton thecluster-infoConfigMap to thebootstrap-token groups.
Verification
Reproduced on
voice-agent-flex(westeurope): without the patch, joiningStandard_ND96isr_H200_v5nodes from eastus2 via aks-flex-node v0.0.18 hangson discovery 403; with the patch,
kubeadm joincompletes in seconds and thenode goes Ready.
Rendered output verified with
KUBECONFIG=/dev/null go run ./cli config k8s-bootstrap.go test ./...incli/passes.