mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-10-31 18:28:13 +00:00 
			
		
		
		
	Merge pull request #40316 from luxas/kubeadm_fix_apiserver_certs
Automatic merge from submit-queue (batch tested with PRs 40303, 40316) kubeadm: Fix up the apiserver kubelet client cert **What this PR does / why we need it**: I didn't notice that the apiserver serving cert was _only_ a server cert, not both a server and client cert in https://github.com/kubernetes/kubernetes/pull/40292. This PR fixes that misconception and generates a dedicated client cert for apiserver -> kubelet communication and harmonizes the `ca.crt` path to `/etc/kubernetes/pki/ca.crt` on both master and node. **Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes # **Special notes for your reviewer**: ```console $ systemctl cat kubelet # /lib/systemd/system/kubelet.service [Unit] Description=kubelet: The Kubernetes Node Agent Documentation=http://kubernetes.io/docs/ [Service] ExecStart=/usr/bin/kubelet Restart=always StartLimitInterval=0 RestartSec=10 [Install] WantedBy=multi-user.target # /etc/systemd/system/kubelet.service.d/10-kubeadm.conf [Service] Environment="KUBELET_KUBECONFIG_ARGS=--kubeconfig=/etc/kubernetes/kubelet.conf **--authorization-mode=Webhook --client-ca-file=/etc/kubernetes/pki/ca.crt** --require-kubeconfig=true" Environment="KUBELET_SYSTEM_PODS_ARGS=--pod-manifest-path=/etc/kubernetes/manifests --allow-privileged=true" Environment="KUBELET_NETWORK_ARGS=--network-plugin=cni --cni-conf-dir=/etc/cni/net.d --cni-bin-dir=/opt/cni/bin" Environment="KUBELET_DNS_ARGS=--cluster-dns=10.96.0.10 --cluster-domain=cluster.local" ExecStart= ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_SYSTEM_PODS_ARGS $KUBELET_NETWORK_ARGS $KUBELET_DNS_ARGS $KUBELET_EXTRA_ARGS $ curl -k https://localhost:10250/containerLogs/kube-system/weave-net-arm64-4t2xv/weave Forbidden (user=system:anonymous, verb=get, resource=nodes, subresource=proxy) $ curl --cert /etc/kubernetes/pki/apiserver-kubelet-client.crt --key /etc/kubernetes/pki/apiserver-kubelet-client.key -k https://localhost:10250/containerLogs/kube-system/weave-net-arm64-4t2xv/weave [Works!!] ``` **Release note**: ```release-note NONE ``` @liggitt @deads2k
This commit is contained in:
		| @@ -146,7 +146,7 @@ func (j *Join) Run(out io.Writer) error { | ||||
|  | ||||
| 	// Write the ca certificate to disk so kubelet can use it for authentication | ||||
| 	cluster := cfg.Contexts[cfg.CurrentContext].Cluster | ||||
| 	caCertFile := filepath.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, kubeadmconstants.CACertName) | ||||
| 	caCertFile := filepath.Join(kubeadmapi.GlobalEnvParams.HostPKIPath, kubeadmconstants.CACertName) | ||||
| 	err = certutil.WriteCert(caCertFile, cfg.Clusters[cluster].CertificateAuthorityData) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("couldn't save the CA certificate to disk: %v", err) | ||||
|   | ||||
| @@ -24,4 +24,8 @@ const ( | ||||
| 	APIServerCertAndKeyBaseName = "apiserver" | ||||
| 	APIServerCertName           = "apiserver.crt" | ||||
| 	APIServerKeyName            = "apiserver.key" | ||||
|  | ||||
| 	APIServerKubeletClientCertAndKeyBaseName = "apiserver-kubelet-client" | ||||
| 	APIServerKubeletClientCertName           = "apiserver-kubelet-client.crt" | ||||
| 	APIServerKubeletClientKeyName            = "apiserver-kubelet-client.key" | ||||
| ) | ||||
|   | ||||
| @@ -322,8 +322,8 @@ func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration, selfHosted bool) [ | ||||
| 		"--client-ca-file="+getCertFilePath(kubeadmconstants.CACertName), | ||||
| 		"--tls-cert-file="+getCertFilePath(kubeadmconstants.APIServerCertName), | ||||
| 		"--tls-private-key-file="+getCertFilePath(kubeadmconstants.APIServerKeyName), | ||||
| 		"--kubelet-client-certificate="+getCertFilePath(kubeadmconstants.APIServerCertName), | ||||
| 		"--kubelet-client-key="+getCertFilePath(kubeadmconstants.APIServerKeyName), | ||||
| 		"--kubelet-client-certificate="+getCertFilePath(kubeadmconstants.APIServerKubeletClientCertName), | ||||
| 		"--kubelet-client-key="+getCertFilePath(kubeadmconstants.APIServerKubeletClientKeyName), | ||||
| 		"--token-auth-file="+kubeadmapi.GlobalEnvParams.HostPKIPath+"/tokens.csv", | ||||
| 		fmt.Sprintf("--secure-port=%d", cfg.API.Port), | ||||
| 		"--allow-privileged", | ||||
|   | ||||
| @@ -376,8 +376,8 @@ func TestGetAPIServerCommand(t *testing.T) { | ||||
| 				"--client-ca-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.crt", | ||||
| 				"--tls-cert-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.crt", | ||||
| 				"--tls-private-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.key", | ||||
| 				"--kubelet-client-certificate=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.crt", | ||||
| 				"--kubelet-client-key=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.key", | ||||
| 				"--kubelet-client-certificate=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-kubelet-client.crt", | ||||
| 				"--kubelet-client-key=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-kubelet-client.key", | ||||
| 				"--token-auth-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/tokens.csv", | ||||
| 				fmt.Sprintf("--secure-port=%d", 123), | ||||
| 				"--allow-privileged", | ||||
| @@ -399,8 +399,8 @@ func TestGetAPIServerCommand(t *testing.T) { | ||||
| 				"--client-ca-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.crt", | ||||
| 				"--tls-cert-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.crt", | ||||
| 				"--tls-private-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.key", | ||||
| 				"--kubelet-client-certificate=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.crt", | ||||
| 				"--kubelet-client-key=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.key", | ||||
| 				"--kubelet-client-certificate=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-kubelet-client.crt", | ||||
| 				"--kubelet-client-key=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-kubelet-client.key", | ||||
| 				"--token-auth-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/tokens.csv", | ||||
| 				fmt.Sprintf("--secure-port=%d", 123), | ||||
| 				"--allow-privileged", | ||||
| @@ -424,8 +424,8 @@ func TestGetAPIServerCommand(t *testing.T) { | ||||
| 				"--client-ca-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.crt", | ||||
| 				"--tls-cert-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.crt", | ||||
| 				"--tls-private-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.key", | ||||
| 				"--kubelet-client-certificate=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.crt", | ||||
| 				"--kubelet-client-key=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.key", | ||||
| 				"--kubelet-client-certificate=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-kubelet-client.crt", | ||||
| 				"--kubelet-client-key=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-kubelet-client.key", | ||||
| 				"--token-auth-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/tokens.csv", | ||||
| 				fmt.Sprintf("--secure-port=%d", 123), | ||||
| 				"--allow-privileged", | ||||
| @@ -451,8 +451,8 @@ func TestGetAPIServerCommand(t *testing.T) { | ||||
| 				"--client-ca-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.crt", | ||||
| 				"--tls-cert-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.crt", | ||||
| 				"--tls-private-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.key", | ||||
| 				"--kubelet-client-certificate=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.crt", | ||||
| 				"--kubelet-client-key=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.key", | ||||
| 				"--kubelet-client-certificate=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-kubelet-client.crt", | ||||
| 				"--kubelet-client-key=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-kubelet-client.key", | ||||
| 				"--token-auth-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/tokens.csv", | ||||
| 				fmt.Sprintf("--secure-port=%d", 123), | ||||
| 				"--allow-privileged", | ||||
|   | ||||
| @@ -110,7 +110,7 @@ func CreatePKIAssets(cfg *kubeadmapi.MasterConfiguration, pkiDir string) error { | ||||
| 	// If at least one of them exists, we should try to load them | ||||
| 	// In the case that only one exists, there will most likely be an error anyway | ||||
| 	if pkiutil.CertOrKeyExist(pkiDir, kubeadmconstants.APIServerCertAndKeyBaseName) { | ||||
| 		// Try to load ca.crt and ca.key from the PKI directory | ||||
| 		// Try to load apiserver.crt and apiserver.key from the PKI directory | ||||
| 		apiCert, apiKey, err := pkiutil.TryLoadCertAndKeyFromDisk(pkiDir, kubeadmconstants.APIServerCertAndKeyBaseName) | ||||
| 		if err != nil || apiCert == nil || apiKey == nil { | ||||
| 			return fmt.Errorf("certificate and/or key existed but they could not be loaded properly") | ||||
| @@ -123,9 +123,7 @@ func CreatePKIAssets(cfg *kubeadmapi.MasterConfiguration, pkiDir string) error { | ||||
| 		config := certutil.Config{ | ||||
| 			CommonName: "kube-apiserver", | ||||
| 			AltNames:   altNames, | ||||
| 			// This makes the apiserver allowed to talk to the kubelets in the cluster | ||||
| 			Organization: []string{"system:masters"}, | ||||
| 			Usages:       []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, | ||||
| 			Usages:     []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, | ||||
| 		} | ||||
| 		apiCert, apiKey, err := pkiutil.NewCertAndKey(caCert, caKey, config) | ||||
| 		if err != nil { | ||||
| @@ -138,6 +136,35 @@ func CreatePKIAssets(cfg *kubeadmapi.MasterConfiguration, pkiDir string) error { | ||||
| 		fmt.Println("[certificates] Generated API server certificate and key.") | ||||
| 	} | ||||
|  | ||||
| 	// If at least one of them exists, we should try to load them | ||||
| 	// In the case that only one exists, there will most likely be an error anyway | ||||
| 	if pkiutil.CertOrKeyExist(pkiDir, kubeadmconstants.APIServerKubeletClientCertAndKeyBaseName) { | ||||
| 		// Try to load apiserver-kubelet-client.crt and apiserver-kubelet-client.key from the PKI directory | ||||
| 		apiCert, apiKey, err := pkiutil.TryLoadCertAndKeyFromDisk(pkiDir, kubeadmconstants.APIServerKubeletClientCertAndKeyBaseName) | ||||
| 		if err != nil || apiCert == nil || apiKey == nil { | ||||
| 			return fmt.Errorf("certificate and/or key existed but they could not be loaded properly") | ||||
| 		} | ||||
|  | ||||
| 		fmt.Println("[certificates] Using the existing API Server kubelet client certificate and key.") | ||||
| 	} else { | ||||
| 		// The certificate and the key did NOT exist, let's generate them now | ||||
| 		// TODO: Add a test case to verify that this cert has the x509.ExtKeyUsageClientAuth flag | ||||
| 		config := certutil.Config{ | ||||
| 			CommonName:   "kube-apiserver-kubelet-client", | ||||
| 			Organization: []string{"system:masters"}, | ||||
| 			Usages:       []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, | ||||
| 		} | ||||
| 		apiClientCert, apiClientKey, err := pkiutil.NewCertAndKey(caCert, caKey, config) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("failure while creating API server kubelet client key and certificate [%v]", err) | ||||
| 		} | ||||
|  | ||||
| 		if err = pkiutil.WriteCertAndKey(pkiDir, kubeadmconstants.APIServerKubeletClientCertAndKeyBaseName, apiClientCert, apiClientKey); err != nil { | ||||
| 			return fmt.Errorf("failure while saving API server kubelet client certificate and key [%v]", err) | ||||
| 		} | ||||
| 		fmt.Println("[certificates] Generated API server kubelet client certificate and key.") | ||||
| 	} | ||||
|  | ||||
| 	fmt.Printf("[certificates] Valid certificates and keys now exist in %q\n", pkiDir) | ||||
|  | ||||
| 	return nil | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Kubernetes Submit Queue
					Kubernetes Submit Queue