Commit 12409789 authored by xiangpengzhao's avatar xiangpengzhao

Re-engineer the kubeadm join logic.

parent d52d1602
...@@ -20,6 +20,7 @@ import ( ...@@ -20,6 +20,7 @@ import (
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"os"
"path/filepath" "path/filepath"
"strings" "strings"
...@@ -28,6 +29,8 @@ import ( ...@@ -28,6 +29,8 @@ import (
flag "github.com/spf13/pflag" flag "github.com/spf13/pflag"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/wait"
clientset "k8s.io/client-go/kubernetes"
certutil "k8s.io/client-go/util/cert" certutil "k8s.io/client-go/util/cert"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
...@@ -237,9 +240,23 @@ func (j *Join) Run(out io.Writer) error { ...@@ -237,9 +240,23 @@ func (j *Join) Run(out io.Writer) error {
return err 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 // 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) { if features.Enabled(j.cfg.FeatureGates, features.DynamicKubeletConfig) {
client, err := kubeconfigutil.ClientSetFromFile(kubeadmconstants.GetAdminKubeConfigPath()) client, err := getTLSBootstrappedClient()
if err != nil { if err != nil {
return err return err
} }
...@@ -250,20 +267,25 @@ func (j *Join) Run(out io.Writer) error { ...@@ -250,20 +267,25 @@ func (j *Join) Run(out io.Writer) error {
} }
} }
kubeconfigFile := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.KubeletBootstrapKubeConfigFileName) fmt.Fprintf(out, joinDoneMsgf)
return nil
}
// Write the bootstrap kubelet config file or the TLS-Boostrapped kubelet config file down to disk // getTLSBootstrappedClient waits for the kubelet to perform the TLS bootstrap
if err := kubeconfigutil.WriteToDisk(kubeconfigFile, cfg); err != nil { // and then creates a client from config file /etc/kubernetes/kubelet.conf
return err func getTLSBootstrappedClient() (clientset.Interface, error) {
} fmt.Println("[tlsbootstrap] Waiting for the kubelet to perform the TLS Bootstrap...")
// Write the ca certificate to disk so kubelet can use it for authentication kubeletKubeConfig := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.KubeletKubeConfigFileName)
cluster := cfg.Contexts[cfg.CurrentContext].Cluster
err = certutil.WriteCert(j.cfg.CACertPath, cfg.Clusters[cluster].CertificateAuthorityData) // 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 { if err != nil {
return fmt.Errorf("couldn't save the CA certificate to disk: %v", err) return nil, err
} }
fmt.Fprintf(out, joinDoneMsgf) return kubeconfigutil.ClientSetFromFile(kubeletKubeConfig)
return nil
} }
...@@ -39,6 +39,9 @@ import ( ...@@ -39,6 +39,9 @@ import (
// CreateBaseKubeletConfiguration creates base kubelet configuration for dynamic kubelet configuration feature. // CreateBaseKubeletConfiguration creates base kubelet configuration for dynamic kubelet configuration feature.
func CreateBaseKubeletConfiguration(cfg *kubeadmapi.MasterConfiguration, client clientset.Interface) error { 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() _, kubeletCodecs, err := kubeletconfigscheme.NewSchemeAndCodecs()
if err != nil { if err != nil {
return err return err
...@@ -69,6 +72,9 @@ func CreateBaseKubeletConfiguration(cfg *kubeadmapi.MasterConfiguration, client ...@@ -69,6 +72,9 @@ func CreateBaseKubeletConfiguration(cfg *kubeadmapi.MasterConfiguration, client
// UpdateNodeWithConfigMap updates node ConfigSource with KubeletBaseConfigurationConfigMap // UpdateNodeWithConfigMap updates node ConfigSource with KubeletBaseConfigurationConfigMap
func UpdateNodeWithConfigMap(client clientset.Interface, nodeName string) error { 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. // 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) { return wait.Poll(kubeadmconstants.APICallRetryInterval, kubeadmconstants.UpdateNodeTimeout, func() (bool, error) {
node, err := client.CoreV1().Nodes().Get(nodeName, metav1.GetOptions{}) node, err := client.CoreV1().Nodes().Get(nodeName, metav1.GetOptions{})
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment