From 12409789a161c81d49bb97e0f18dc725be2ccf1c Mon Sep 17 00:00:00 2001 From: xiangpengzhao Date: Sun, 19 Nov 2017 18:21:42 +0800 Subject: [PATCH 1/2] Re-engineer the kubeadm join logic. --- cmd/kubeadm/app/cmd/join.go | 52 ++++++++++++++++------- cmd/kubeadm/app/phases/kubelet/kubelet.go | 6 +++ 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/cmd/kubeadm/app/cmd/join.go b/cmd/kubeadm/app/cmd/join.go index 5ec77b15e2..266f268b06 100644 --- a/cmd/kubeadm/app/cmd/join.go +++ b/cmd/kubeadm/app/cmd/join.go @@ -20,6 +20,7 @@ import ( "fmt" "io" "io/ioutil" + "os" "path/filepath" "strings" @@ -28,6 +29,8 @@ import ( flag "github.com/spf13/pflag" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/wait" + clientset "k8s.io/client-go/kubernetes" certutil "k8s.io/client-go/util/cert" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" @@ -237,9 +240,23 @@ func (j *Join) Run(out io.Writer) error { return err } + kubeconfigFile := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.KubeletBootstrapKubeConfigFileName) + + // Write the bootstrap kubelet config file or the TLS-Boostrapped kubelet config file down to disk + if err := kubeconfigutil.WriteToDisk(kubeconfigFile, cfg); err != nil { + return fmt.Errorf("couldn't save bootstrap-kubelet.conf to disk: %v", err) + } + + // Write the ca certificate to disk so kubelet can use it for authentication + cluster := cfg.Contexts[cfg.CurrentContext].Cluster + err = certutil.WriteCert(j.cfg.CACertPath, cfg.Clusters[cluster].CertificateAuthorityData) + if err != nil { + return fmt.Errorf("couldn't save the CA certificate to disk: %v", err) + } + // NOTE: flag "--dynamic-config-dir" should be specified in /etc/systemd/system/kubelet.service.d/10-kubeadm.conf if features.Enabled(j.cfg.FeatureGates, features.DynamicKubeletConfig) { - client, err := kubeconfigutil.ClientSetFromFile(kubeadmconstants.GetAdminKubeConfigPath()) + client, err := getTLSBootstrappedClient() if err != nil { return err } @@ -250,20 +267,25 @@ func (j *Join) Run(out io.Writer) error { } } - kubeconfigFile := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.KubeletBootstrapKubeConfigFileName) - - // Write the bootstrap kubelet config file or the TLS-Boostrapped kubelet config file down to disk - if err := kubeconfigutil.WriteToDisk(kubeconfigFile, cfg); err != nil { - return err - } - - // Write the ca certificate to disk so kubelet can use it for authentication - cluster := cfg.Contexts[cfg.CurrentContext].Cluster - err = certutil.WriteCert(j.cfg.CACertPath, cfg.Clusters[cluster].CertificateAuthorityData) - if err != nil { - return fmt.Errorf("couldn't save the CA certificate to disk: %v", err) - } - fmt.Fprintf(out, joinDoneMsgf) return nil } + +// getTLSBootstrappedClient waits for the kubelet to perform the TLS bootstrap +// and then creates a client from config file /etc/kubernetes/kubelet.conf +func getTLSBootstrappedClient() (clientset.Interface, error) { + fmt.Println("[tlsbootstrap] Waiting for the kubelet to perform the TLS Bootstrap...") + + kubeletKubeConfig := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.KubeletKubeConfigFileName) + + // Loop on every falsy return. Return with an error if raised. Exit successfully if true is returned. + err := wait.PollImmediateInfinite(kubeadmconstants.APICallRetryInterval, func() (bool, error) { + _, err := os.Stat(kubeletKubeConfig) + return (err == nil), nil + }) + if err != nil { + return nil, err + } + + return kubeconfigutil.ClientSetFromFile(kubeletKubeConfig) +} diff --git a/cmd/kubeadm/app/phases/kubelet/kubelet.go b/cmd/kubeadm/app/phases/kubelet/kubelet.go index af0d5dc769..23d5362a8c 100644 --- a/cmd/kubeadm/app/phases/kubelet/kubelet.go +++ b/cmd/kubeadm/app/phases/kubelet/kubelet.go @@ -39,6 +39,9 @@ import ( // CreateBaseKubeletConfiguration creates base kubelet configuration for dynamic kubelet configuration feature. func CreateBaseKubeletConfiguration(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface) error { + fmt.Printf("[kubelet] Uploading a ConfigMap %q in namespace %s with base configuration for the kubelets in the cluster", + kubeadmconstants.KubeletBaseConfigurationConfigMap, metav1.NamespaceSystem) + _, kubeletCodecs, err := kubeletconfigscheme.NewSchemeAndCodecs() if err != nil { return err @@ -69,6 +72,9 @@ func CreateBaseKubeletConfiguration(cfg *kubeadmapi.MasterConfiguration, client // UpdateNodeWithConfigMap updates node ConfigSource with KubeletBaseConfigurationConfigMap func UpdateNodeWithConfigMap(client clientset.Interface, nodeName string) error { + fmt.Printf("[kubelet] Using Dynamic Kubelet Config for node %q; config sourced from ConfigMap %q in namespace %s", + nodeName, kubeadmconstants.KubeletBaseConfigurationConfigMap, metav1.NamespaceSystem) + // Loop on every falsy return. Return with an error if raised. Exit successfully if true is returned. return wait.Poll(kubeadmconstants.APICallRetryInterval, kubeadmconstants.UpdateNodeTimeout, func() (bool, error) { node, err := client.CoreV1().Nodes().Get(nodeName, metav1.GetOptions{}) From 045937aaadcc4563c22ec9e4522ec99cb096e6bb Mon Sep 17 00:00:00 2001 From: xiangpengzhao Date: Sun, 19 Nov 2017 18:22:39 +0800 Subject: [PATCH 2/2] Auto generated BUILD files. --- cmd/kubeadm/app/cmd/BUILD | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/kubeadm/app/cmd/BUILD b/cmd/kubeadm/app/cmd/BUILD index fb3f2d7a92..195f639a33 100644 --- a/cmd/kubeadm/app/cmd/BUILD +++ b/cmd/kubeadm/app/cmd/BUILD @@ -70,6 +70,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/fields:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/apimachinery/pkg/version:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/flag:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library",