@@ -739,6 +739,24 @@ func run(s *options.KubeletServer, kubeDeps *kubelet.Dependencies, stopCh <-chan
739
739
// bootstrapping is enabled or client certificate rotation is enabled.
740
740
func buildKubeletClientConfig (s * options.KubeletServer , nodeName types.NodeName ) (* restclient.Config , func (), error ) {
741
741
if s .RotateCertificates && utilfeature .DefaultFeatureGate .Enabled (features .RotateKubeletClientCertificate ) {
742
+ // Rules for client rotation and the handling of kube config files:
743
+ //
744
+ // 1. If the client provides only a kubeconfig file, we must use that as the initial client
745
+ // kubeadm needs the initial data in the kubeconfig to be placed into the cert store
746
+ // 2. If the client provides only an initial bootstrap kubeconfig file, we must create a
747
+ // kubeconfig file at the target location that points to the cert store, but until
748
+ // the file is present the client config will have no certs
749
+ // 3. If the client provides both and the kubeconfig is valid, we must ignore the bootstrap
750
+ // kubeconfig.
751
+ // 4. If the client provides both and the kubeconfig is expired or otherwise invalid, we must
752
+ // replace the kubeconfig with a new file that points to the cert dir
753
+ //
754
+ // The desired configuration for bootstrapping is to use a bootstrap kubeconfig and to have
755
+ // the kubeconfig file be managed by this process. For backwards compatibility with kubeadm,
756
+ // which provides a high powered kubeconfig on the master with cert/key data, we must
757
+ // bootstrap the cert manager with the contents of the initial client config.
758
+
759
+ klog .Infof ("Client rotation is on, will bootstrap in background" )
742
760
certConfig , clientConfig , err := bootstrap .LoadClientConfig (s .KubeConfig , s .BootstrapKubeconfig , s .CertDirectory )
743
761
if err != nil {
744
762
return nil , nil , err
@@ -750,9 +768,8 @@ func buildKubeletClientConfig(s *options.KubeletServer, nodeName types.NodeName)
750
768
}
751
769
752
770
// the rotating transport will use the cert from the cert manager instead of these files
753
- transportConfig := restclient .CopyConfig (clientConfig )
754
- transportConfig .CertFile = ""
755
- transportConfig .KeyFile = ""
771
+ transportConfig := restclient .AnonymousClientConfig (clientConfig )
772
+ kubeClientConfigOverrides (s , transportConfig )
756
773
757
774
// we set exitAfter to five minutes because we use this client configuration to request new certs - if we are unable
758
775
// to request new certs, we will be unable to continue normal operation. Exiting the process allows a wrapper
@@ -774,10 +791,16 @@ func buildKubeletClientConfig(s *options.KubeletServer, nodeName types.NodeName)
774
791
}
775
792
}
776
793
777
- clientConfig , err := createAPIServerClientConfig (s )
794
+ clientConfig , err := clientcmd .NewNonInteractiveDeferredLoadingClientConfig (
795
+ & clientcmd.ClientConfigLoadingRules {ExplicitPath : s .KubeConfig },
796
+ & clientcmd.ConfigOverrides {},
797
+ ).ClientConfig ()
778
798
if err != nil {
779
799
return nil , nil , fmt .Errorf ("invalid kubeconfig: %v" , err )
780
800
}
801
+
802
+ kubeClientConfigOverrides (s , clientConfig )
803
+
781
804
return clientConfig , nil , nil
782
805
}
783
806
@@ -804,12 +827,26 @@ func buildClientCertificateManager(certConfig, clientConfig *restclient.Config,
804
827
return kubeletcertificate .NewKubeletClientCertificateManager (
805
828
certDir ,
806
829
nodeName ,
830
+
831
+ // this preserves backwards compatibility with kubeadm which passes
832
+ // a high powered certificate to the kubelet as --kubeconfig and expects
833
+ // it to be rotated out immediately
834
+ clientConfig .CertData ,
835
+ clientConfig .KeyData ,
836
+
807
837
clientConfig .CertFile ,
808
838
clientConfig .KeyFile ,
809
839
newClientFn ,
810
840
)
811
841
}
812
842
843
+ func kubeClientConfigOverrides (s * options.KubeletServer , clientConfig * restclient.Config ) {
844
+ clientConfig .ContentType = s .ContentType
845
+ // Override kubeconfig qps/burst settings from flags
846
+ clientConfig .QPS = float32 (s .KubeAPIQPS )
847
+ clientConfig .Burst = int (s .KubeAPIBurst )
848
+ }
849
+
813
850
// getNodeName returns the node name according to the cloud provider
814
851
// if cloud provider is specified. Otherwise, returns the hostname of the node.
815
852
func getNodeName (cloud cloudprovider.Interface , hostname string ) (types.NodeName , error ) {
@@ -898,38 +935,6 @@ func InitializeTLS(kf *options.KubeletFlags, kc *kubeletconfiginternal.KubeletCo
898
935
return tlsOptions , nil
899
936
}
900
937
901
- func kubeconfigClientConfig (s * options.KubeletServer ) (* restclient.Config , error ) {
902
- return clientcmd .NewNonInteractiveDeferredLoadingClientConfig (
903
- & clientcmd.ClientConfigLoadingRules {ExplicitPath : s .KubeConfig },
904
- & clientcmd.ConfigOverrides {},
905
- ).ClientConfig ()
906
- }
907
-
908
- // createClientConfig creates a client configuration from the command line arguments.
909
- // If --kubeconfig is explicitly set, it will be used.
910
- func createClientConfig (s * options.KubeletServer ) (* restclient.Config , error ) {
911
- if len (s .BootstrapKubeconfig ) > 0 || len (s .KubeConfig ) > 0 {
912
- return kubeconfigClientConfig (s )
913
- }
914
- return nil , fmt .Errorf ("createClientConfig called in standalone mode" )
915
- }
916
-
917
- // createAPIServerClientConfig generates a client.Config from command line flags
918
- // via createClientConfig and then injects chaos into the configuration via addChaosToClientConfig.
919
- func createAPIServerClientConfig (s * options.KubeletServer ) (* restclient.Config , error ) {
920
- clientConfig , err := createClientConfig (s )
921
- if err != nil {
922
- return nil , err
923
- }
924
-
925
- clientConfig .ContentType = s .ContentType
926
- // Override kubeconfig qps/burst settings from flags
927
- clientConfig .QPS = float32 (s .KubeAPIQPS )
928
- clientConfig .Burst = int (s .KubeAPIBurst )
929
-
930
- return clientConfig , nil
931
- }
932
-
933
938
// RunKubelet is responsible for setting up and running a kubelet. It is used in three different applications:
934
939
// 1 Integration tests
935
940
// 2 Kubelet binary
0 commit comments