Skip to content

Commit c8125c4

Browse files
authored
Merge pull request kubernetes#121305 from neolit123/1.29-super-admin-conf
kubeadm: add support for separate super-admin.conf kubeconfig file
2 parents 0360916 + 8370901 commit c8125c4

File tree

15 files changed

+671
-44
lines changed

15 files changed

+671
-44
lines changed

cmd/kubeadm/app/cmd/certs_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ func TestRunRenewCommands(t *testing.T) {
134134
// Generate all the kubeconfig files with embedded certs
135135
for _, kubeConfig := range []string{
136136
kubeadmconstants.AdminKubeConfigFileName,
137+
kubeadmconstants.SuperAdminKubeConfigFileName,
137138
kubeadmconstants.SchedulerKubeConfigFileName,
138139
kubeadmconstants.ControllerManagerKubeConfigFileName,
139140
} {
@@ -162,6 +163,7 @@ func TestRunRenewCommands(t *testing.T) {
162163
},
163164
KubeconfigFiles: []string{
164165
kubeadmconstants.AdminKubeConfigFileName,
166+
kubeadmconstants.SuperAdminKubeConfigFileName,
165167
kubeadmconstants.SchedulerKubeConfigFileName,
166168
kubeadmconstants.ControllerManagerKubeConfigFileName,
167169
},
@@ -214,6 +216,12 @@ func TestRunRenewCommands(t *testing.T) {
214216
kubeadmconstants.AdminKubeConfigFileName,
215217
},
216218
},
219+
{
220+
command: "super-admin.conf",
221+
KubeconfigFiles: []string{
222+
kubeadmconstants.SuperAdminKubeConfigFileName,
223+
},
224+
},
217225
{
218226
command: "scheduler.conf",
219227
KubeconfigFiles: []string{

cmd/kubeadm/app/cmd/init.go

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -72,20 +72,21 @@ var _ phases.InitData = &initData{}
7272
// initData defines all the runtime information used when running the kubeadm init workflow;
7373
// this data is shared across all the phases that are included in the workflow.
7474
type initData struct {
75-
cfg *kubeadmapi.InitConfiguration
76-
skipTokenPrint bool
77-
dryRun bool
78-
kubeconfigDir string
79-
kubeconfigPath string
80-
ignorePreflightErrors sets.Set[string]
81-
certificatesDir string
82-
dryRunDir string
83-
externalCA bool
84-
client clientset.Interface
85-
outputWriter io.Writer
86-
uploadCerts bool
87-
skipCertificateKeyPrint bool
88-
patchesDir string
75+
cfg *kubeadmapi.InitConfiguration
76+
skipTokenPrint bool
77+
dryRun bool
78+
kubeconfigDir string
79+
kubeconfigPath string
80+
ignorePreflightErrors sets.Set[string]
81+
certificatesDir string
82+
dryRunDir string
83+
externalCA bool
84+
client clientset.Interface
85+
outputWriter io.Writer
86+
uploadCerts bool
87+
skipCertificateKeyPrint bool
88+
patchesDir string
89+
adminKubeConfigBootstrapped bool
8990
}
9091

9192
// newCmdInit returns "kubeadm init" command.
@@ -495,12 +496,22 @@ func (d *initData) Client() (clientset.Interface, error) {
495496
// If we're dry-running, we should create a faked client that answers some GETs in order to be able to do the full init flow and just logs the rest of requests
496497
dryRunGetter := apiclient.NewInitDryRunGetter(d.cfg.NodeRegistration.Name, svcSubnetCIDR.String())
497498
d.client = apiclient.NewDryRunClient(dryRunGetter, os.Stdout)
498-
} else {
499-
// If we're acting for real, we should create a connection to the API server and wait for it to come up
499+
} else { // Use a real client
500500
var err error
501-
d.client, err = kubeconfigutil.ClientSetFromFile(d.KubeConfigPath())
502-
if err != nil {
503-
return nil, err
501+
if !d.adminKubeConfigBootstrapped {
502+
// Call EnsureAdminClusterRoleBinding() to obtain a working client from admin.conf.
503+
d.client, err = kubeconfigphase.EnsureAdminClusterRoleBinding(kubeadmconstants.KubernetesDir, nil)
504+
if err != nil {
505+
return nil, errors.Wrapf(err, "could not bootstrap the admin user in file %s", kubeadmconstants.AdminKubeConfigFileName)
506+
}
507+
d.adminKubeConfigBootstrapped = true
508+
} else {
509+
// In case adminKubeConfigBootstrapped is already set just return a client from the default
510+
// kubeconfig location.
511+
d.client, err = kubeconfigutil.ClientSetFromFile(d.KubeConfigPath())
512+
if err != nil {
513+
return nil, err
514+
}
504515
}
505516
}
506517
}

cmd/kubeadm/app/cmd/phases/init/kubeconfig.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ var (
4141
short: "Generate a kubeconfig file for the admin to use and for kubeadm itself",
4242
long: "Generate the kubeconfig file for the admin and for kubeadm itself, and save it to %s file.",
4343
},
44+
kubeadmconstants.SuperAdminKubeConfigFileName: {
45+
name: "super-admin",
46+
short: "Generate a kubeconfig file for the super-admin",
47+
long: "Generate a kubeconfig file for the super-admin, and save it to %s file.",
48+
},
4449
kubeadmconstants.KubeletKubeConfigFileName: {
4550
name: "kubelet",
4651
short: "Generate a kubeconfig file for the kubelet to use *only* for cluster bootstrapping purposes",
@@ -77,6 +82,7 @@ func NewKubeConfigPhase() workflow.Phase {
7782
RunAllSiblings: true,
7883
},
7984
NewKubeConfigFilePhase(kubeadmconstants.AdminKubeConfigFileName),
85+
NewKubeConfigFilePhase(kubeadmconstants.SuperAdminKubeConfigFileName),
8086
NewKubeConfigFilePhase(kubeadmconstants.KubeletKubeConfigFileName),
8187
NewKubeConfigFilePhase(kubeadmconstants.ControllerManagerKubeConfigFileName),
8288
NewKubeConfigFilePhase(kubeadmconstants.SchedulerKubeConfigFileName),

cmd/kubeadm/app/cmd/phases/reset/cleanupnode.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ func resetConfigDir(configPathDir string, dirsToClean []string, isDryRun bool) {
169169

170170
filesToClean := []string{
171171
filepath.Join(configPathDir, kubeadmconstants.AdminKubeConfigFileName),
172+
filepath.Join(configPathDir, kubeadmconstants.SuperAdminKubeConfigFileName),
172173
filepath.Join(configPathDir, kubeadmconstants.KubeletKubeConfigFileName),
173174
filepath.Join(configPathDir, kubeadmconstants.KubeletBootstrapKubeConfigFileName),
174175
filepath.Join(configPathDir, kubeadmconstants.ControllerManagerKubeConfigFileName),

cmd/kubeadm/app/cmd/phases/reset/cleanupnode_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ func TestConfigDirCleaner(t *testing.T) {
6868
"manifests/kube-apiserver.yaml",
6969
"pki/ca.pem",
7070
kubeadmconstants.AdminKubeConfigFileName,
71+
kubeadmconstants.SuperAdminKubeConfigFileName,
7172
kubeadmconstants.KubeletKubeConfigFileName,
7273
},
7374
verifyExists: []string{

cmd/kubeadm/app/constants/constants.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,11 @@ const (
146146
// FrontProxyClientCertCommonName defines front proxy certificate common name
147147
FrontProxyClientCertCommonName = "front-proxy-client" //used as subject.commonname attribute (CN)
148148

149-
// AdminKubeConfigFileName defines name for the kubeconfig aimed to be used by the superuser/admin of the cluster
149+
// AdminKubeConfigFileName defines name for the kubeconfig aimed to be used by the admin of the cluster
150150
AdminKubeConfigFileName = "admin.conf"
151+
// SuperAdminKubeConfigFileName defines name for the kubeconfig aimed to be used by the super-admin of the cluster
152+
SuperAdminKubeConfigFileName = "super-admin.conf"
153+
151154
// KubeletBootstrapKubeConfigFileName defines the file name for the kubeconfig that the kubelet will use to do
152155
// the TLS bootstrap to get itself an unique credential
153156
KubeletBootstrapKubeConfigFileName = "bootstrap-kubelet.conf"
@@ -201,6 +204,10 @@ const (
201204
NodeAutoApproveBootstrapClusterRoleBinding = "kubeadm:node-autoapprove-bootstrap"
202205
// NodeAutoApproveCertificateRotationClusterRoleBinding defines name of the ClusterRoleBinding that makes the csrapprover approve node auto rotated CSRs
203206
NodeAutoApproveCertificateRotationClusterRoleBinding = "kubeadm:node-autoapprove-certificate-rotation"
207+
// ClusterAdminsGroupAndClusterRoleBinding is the name of the Group used for kubeadm generated cluster
208+
// admin credentials and the name of the ClusterRoleBinding that binds the same Group to the "cluster-admin"
209+
// built-in ClusterRole.
210+
ClusterAdminsGroupAndClusterRoleBinding = "kubeadm:cluster-admins"
204211

205212
// APICallRetryInterval defines how long kubeadm should wait before retrying a failed API operation
206213
APICallRetryInterval = 500 * time.Millisecond
@@ -567,6 +574,11 @@ func GetAdminKubeConfigPath() string {
567574
return filepath.Join(KubernetesDir, AdminKubeConfigFileName)
568575
}
569576

577+
// GetSuperAdminKubeConfigPath returns the location on the disk where admin kubeconfig is located by default
578+
func GetSuperAdminKubeConfigPath() string {
579+
return filepath.Join(KubernetesDir, SuperAdminKubeConfigFileName)
580+
}
581+
570582
// GetBootstrapKubeletKubeConfigPath returns the location on the disk where bootstrap kubelet kubeconfig is located by default
571583
func GetBootstrapKubeletKubeConfigPath() string {
572584
return filepath.Join(KubernetesDir, KubeletBootstrapKubeConfigFileName)

cmd/kubeadm/app/constants/constants_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,19 @@ func TestGetAdminKubeConfigPath(t *testing.T) {
5050
}
5151
}
5252

53+
func TestGetSuperAdminKubeConfigPath(t *testing.T) {
54+
expected := filepath.Join(KubernetesDir, SuperAdminKubeConfigFileName)
55+
actual := GetSuperAdminKubeConfigPath()
56+
57+
if actual != expected {
58+
t.Errorf(
59+
"failed GetSuperAdminKubeConfigPath:\n\texpected: %s\n\t actual: %s",
60+
expected,
61+
actual,
62+
)
63+
}
64+
}
65+
5366
func TestGetBootstrapKubeletKubeConfigPath(t *testing.T) {
5467
expected := filepath.FromSlash("/etc/kubernetes/bootstrap-kubelet.conf")
5568
actual := GetBootstrapKubeletKubeConfigPath()

cmd/kubeadm/app/phases/certs/renewal/manager.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,10 @@ func NewManager(cfg *kubeadmapi.ClusterConfiguration, kubernetesDir string) (*Ma
141141
longName: "certificate embedded in the kubeconfig file for the admin to use and for kubeadm itself",
142142
fileName: kubeadmconstants.AdminKubeConfigFileName,
143143
},
144+
{
145+
longName: "certificate embedded in the kubeconfig file for the super-admin",
146+
fileName: kubeadmconstants.SuperAdminKubeConfigFileName,
147+
},
144148
{
145149
longName: "certificate embedded in the kubeconfig file for the controller manager to use",
146150
fileName: kubeadmconstants.ControllerManagerKubeConfigFileName,

cmd/kubeadm/app/phases/certs/renewal/manager_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func TestNewManager(t *testing.T) {
6464
{
6565
name: "cluster with local etcd",
6666
cfg: &kubeadmapi.ClusterConfiguration{},
67-
expectedCertificates: 10, //[admin apiserver apiserver-etcd-client apiserver-kubelet-client controller-manager etcd/healthcheck-client etcd/peer etcd/server front-proxy-client scheduler]
67+
expectedCertificates: 11, // [admin super-admin apiserver apiserver-etcd-client apiserver-kubelet-client controller-manager etcd/healthcheck-client etcd/peer etcd/server front-proxy-client scheduler]
6868
},
6969
{
7070
name: "cluster with external etcd",
@@ -73,7 +73,7 @@ func TestNewManager(t *testing.T) {
7373
External: &kubeadmapi.ExternalEtcd{},
7474
},
7575
},
76-
expectedCertificates: 6, // [admin apiserver apiserver-kubelet-client controller-manager front-proxy-client scheduler]
76+
expectedCertificates: 7, // [admin super-admin apiserver apiserver-kubelet-client controller-manager front-proxy-client scheduler]
7777
},
7878
}
7979

0 commit comments

Comments
 (0)