kubeadm: Upload CRISocket information and hence make kubeadm join blocking
This commit is contained in:
		@@ -52,6 +52,7 @@ import (
 | 
				
			|||||||
	kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
 | 
						kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
 | 
				
			||||||
	kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet"
 | 
						kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet"
 | 
				
			||||||
	markmasterphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/markmaster"
 | 
						markmasterphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/markmaster"
 | 
				
			||||||
 | 
						patchnodephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode"
 | 
				
			||||||
	selfhostingphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/selfhosting"
 | 
						selfhostingphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/selfhosting"
 | 
				
			||||||
	uploadconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig"
 | 
						uploadconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig"
 | 
				
			||||||
	"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
 | 
						"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
 | 
				
			||||||
@@ -379,7 +380,10 @@ func (i *Init) Run(out io.Writer) error {
 | 
				
			|||||||
	glog.V(1).Infof("[init] waiting for the API server to be healthy")
 | 
						glog.V(1).Infof("[init] waiting for the API server to be healthy")
 | 
				
			||||||
	waiter := getWaiter(i, client)
 | 
						waiter := getWaiter(i, client)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := waitForAPIAndKubelet(waiter); err != nil {
 | 
						fmt.Printf("[init] waiting for the kubelet to boot up the control plane as Static Pods from directory %q \n", kubeadmconstants.GetStaticPodDirectory())
 | 
				
			||||||
 | 
						fmt.Println("[init] this might take a minute or longer if the control plane images have to be pulled")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := waitForKubeletAndFunc(waiter, waiter.WaitForAPI); err != nil {
 | 
				
			||||||
		ctx := map[string]string{
 | 
							ctx := map[string]string{
 | 
				
			||||||
			"Error":                  fmt.Sprintf("%v", err),
 | 
								"Error":                  fmt.Sprintf("%v", err),
 | 
				
			||||||
			"APIServerImage":         images.GetCoreImage(kubeadmconstants.KubeAPIServer, i.cfg.GetControlPlaneImageRepository(), i.cfg.KubernetesVersion, i.cfg.UnifiedControlPlaneImage),
 | 
								"APIServerImage":         images.GetCoreImage(kubeadmconstants.KubeAPIServer, i.cfg.GetControlPlaneImageRepository(), i.cfg.KubernetesVersion, i.cfg.UnifiedControlPlaneImage),
 | 
				
			||||||
@@ -417,6 +421,11 @@ func (i *Init) Run(out io.Writer) error {
 | 
				
			|||||||
		return fmt.Errorf("error marking master: %v", err)
 | 
							return fmt.Errorf("error marking master: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						glog.V(1).Infof("[init] preserving the crisocket information for the master")
 | 
				
			||||||
 | 
						if err := patchnodephase.AnnotateCRISocket(client, i.cfg.NodeRegistration.Name, i.cfg.NodeRegistration.CRISocket); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("error uploading crisocket: %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
 | 
				
			||||||
	// This feature is disabled by default, as it is alpha still
 | 
						// This feature is disabled by default, as it is alpha still
 | 
				
			||||||
	if features.Enabled(i.cfg.FeatureGates, features.DynamicKubeletConfig) {
 | 
						if features.Enabled(i.cfg.FeatureGates, features.DynamicKubeletConfig) {
 | 
				
			||||||
@@ -581,15 +590,11 @@ func getWaiter(i *Init, client clientset.Interface) apiclient.Waiter {
 | 
				
			|||||||
	return apiclient.NewKubeWaiter(client, timeout, os.Stdout)
 | 
						return apiclient.NewKubeWaiter(client, timeout, os.Stdout)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// waitForAPIAndKubelet waits primarily for the API server to come up. If that takes a long time, and the kubelet
 | 
					// waitForKubeletAndFunc waits primarily for the function f to execute, even though it might take some time. If that takes a long time, and the kubelet
 | 
				
			||||||
// /healthz and /healthz/syncloop endpoints continuously are unhealthy, kubeadm will error out after a period of
 | 
					// /healthz continuously are unhealthy, kubeadm will error out after a period of exponential backoff
 | 
				
			||||||
// backoffing exponentially
 | 
					func waitForKubeletAndFunc(waiter apiclient.Waiter, f func() error) error {
 | 
				
			||||||
func waitForAPIAndKubelet(waiter apiclient.Waiter) error {
 | 
					 | 
				
			||||||
	errorChan := make(chan error)
 | 
						errorChan := make(chan error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fmt.Printf("[init] waiting for the kubelet to boot up the control plane as Static Pods from directory %q \n", kubeadmconstants.GetStaticPodDirectory())
 | 
					 | 
				
			||||||
	fmt.Println("[init] this might take a minute or longer if the control plane images have to be pulled")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	go func(errC chan error, waiter apiclient.Waiter) {
 | 
						go func(errC chan error, waiter apiclient.Waiter) {
 | 
				
			||||||
		// This goroutine can only make kubeadm init fail. If this check succeeds, it won't do anything special
 | 
							// This goroutine can only make kubeadm init fail. If this check succeeds, it won't do anything special
 | 
				
			||||||
		if err := waiter.WaitForHealthyKubelet(40*time.Second, "http://localhost:10248/healthz"); err != nil {
 | 
							if err := waiter.WaitForHealthyKubelet(40*time.Second, "http://localhost:10248/healthz"); err != nil {
 | 
				
			||||||
@@ -598,9 +603,9 @@ func waitForAPIAndKubelet(waiter apiclient.Waiter) error {
 | 
				
			|||||||
	}(errorChan, waiter)
 | 
						}(errorChan, waiter)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	go func(errC chan error, waiter apiclient.Waiter) {
 | 
						go func(errC chan error, waiter apiclient.Waiter) {
 | 
				
			||||||
		// This main goroutine sends whatever WaitForAPI returns (error or not) to the channel
 | 
							// This main goroutine sends whatever the f function returns (error or not) to the channel
 | 
				
			||||||
		// This in order to continue on success (nil error), or just fail if
 | 
							// This in order to continue on success (nil error), or just fail if the function returns an error
 | 
				
			||||||
		errC <- waiter.WaitForAPI()
 | 
							errC <- f()
 | 
				
			||||||
	}(errorChan, waiter)
 | 
						}(errorChan, waiter)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// This call is blocking until one of the goroutines sends to errorChan
 | 
						// This call is blocking until one of the goroutines sends to errorChan
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,6 +19,7 @@ package cmd
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
	"path/filepath"
 | 
						"path/filepath"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -28,6 +29,7 @@ import (
 | 
				
			|||||||
	flag "github.com/spf13/pflag"
 | 
						flag "github.com/spf13/pflag"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/sets"
 | 
						"k8s.io/apimachinery/pkg/util/sets"
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/util/wait"
 | 
				
			||||||
	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"
 | 
				
			||||||
	kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
 | 
						kubeadmscheme "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
 | 
				
			||||||
@@ -37,8 +39,10 @@ import (
 | 
				
			|||||||
	"k8s.io/kubernetes/cmd/kubeadm/app/discovery"
 | 
						"k8s.io/kubernetes/cmd/kubeadm/app/discovery"
 | 
				
			||||||
	"k8s.io/kubernetes/cmd/kubeadm/app/features"
 | 
						"k8s.io/kubernetes/cmd/kubeadm/app/features"
 | 
				
			||||||
	kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet"
 | 
						kubeletphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubelet"
 | 
				
			||||||
 | 
						patchnodephase "k8s.io/kubernetes/cmd/kubeadm/app/phases/patchnode"
 | 
				
			||||||
	"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
 | 
						"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
 | 
				
			||||||
	kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
 | 
						kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
 | 
				
			||||||
	configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
 | 
						configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
 | 
				
			||||||
	kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
 | 
						kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
 | 
				
			||||||
	utilsexec "k8s.io/utils/exec"
 | 
						utilsexec "k8s.io/utils/exec"
 | 
				
			||||||
@@ -96,6 +100,19 @@ var (
 | 
				
			|||||||
		Often times the same token is used for both parts. In this case, the
 | 
							Often times the same token is used for both parts. In this case, the
 | 
				
			||||||
		--token flag can be used instead of specifying each token individually.
 | 
							--token flag can be used instead of specifying each token individually.
 | 
				
			||||||
		`)
 | 
							`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						kubeadmJoinFailMsgf = dedent.Dedent(`
 | 
				
			||||||
 | 
							Unfortunately, an error has occurred:
 | 
				
			||||||
 | 
								%v
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							This error is likely caused by:
 | 
				
			||||||
 | 
								- The kubelet is not running
 | 
				
			||||||
 | 
								- The kubelet is unhealthy due to a misconfiguration of the node in some way (required cgroups disabled)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							If you are on a systemd-powered system, you can try to troubleshoot the error with the following commands:
 | 
				
			||||||
 | 
								- 'systemctl status kubelet'
 | 
				
			||||||
 | 
								- 'journalctl -xeu kubelet'
 | 
				
			||||||
 | 
							`)
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewCmdJoin returns "kubeadm join" command.
 | 
					// NewCmdJoin returns "kubeadm join" command.
 | 
				
			||||||
@@ -269,16 +286,30 @@ func (j *Join) Run(out io.Writer) error {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Now the kubelet will perform the TLS Bootstrap, transforming bootstrap-kubeconfig.conf to kubeconfig.conf in /etc/kubernetes
 | 
						// Now the kubelet will perform the TLS Bootstrap, transforming bootstrap-kubeconfig.conf to kubeconfig.conf in /etc/kubernetes
 | 
				
			||||||
 | 
						// Wait for the kubelet to create the /etc/kubernetes/kubelet.conf KubeConfig file. If this process
 | 
				
			||||||
 | 
						// times out, display a somewhat user-friendly message.
 | 
				
			||||||
 | 
						waiter := apiclient.NewKubeWaiter(nil, kubeadmconstants.TLSBootstrapTimeout, os.Stdout)
 | 
				
			||||||
 | 
						if err := waitForKubeletAndFunc(waiter, waitForTLSBootstrappedClient); err != nil {
 | 
				
			||||||
 | 
							fmt.Printf(kubeadmJoinFailMsgf, err)
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// When we know the /etc/kubernetes/kubelet.conf file is available, get the client
 | 
				
			||||||
 | 
						kubeletKubeConfig := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.KubeletKubeConfigFileName)
 | 
				
			||||||
 | 
						client, err := kubeconfigutil.ClientSetFromFile(kubeletKubeConfig)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						glog.V(1).Infof("[join] preserving the crisocket information for the node")
 | 
				
			||||||
 | 
						if err := patchnodephase.AnnotateCRISocket(client, j.cfg.NodeRegistration.Name, j.cfg.NodeRegistration.CRISocket); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("error uploading crisocket: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// NOTE: the "--dynamic-config-dir" flag should be specified in /etc/systemd/system/kubelet.service.d/10-kubeadm.conf for this to work
 | 
						// NOTE: the "--dynamic-config-dir" flag should be specified in /etc/systemd/system/kubelet.service.d/10-kubeadm.conf for this to work
 | 
				
			||||||
	// This feature is disabled by default, as it is alpha still
 | 
						// This feature is disabled by default, as it is alpha still
 | 
				
			||||||
	glog.V(1).Infoln("[join] enabling dynamic kubelet configuration")
 | 
						glog.V(1).Infoln("[join] enabling dynamic kubelet configuration")
 | 
				
			||||||
	if features.Enabled(j.cfg.FeatureGates, features.DynamicKubeletConfig) {
 | 
						if features.Enabled(j.cfg.FeatureGates, features.DynamicKubeletConfig) {
 | 
				
			||||||
		client, err := kubeletphase.GetLocalNodeTLSBootstrappedClient()
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if err := kubeletphase.EnableDynamicConfigForNode(client, j.cfg.NodeRegistration.Name, kubeletVersion); err != nil {
 | 
							if err := kubeletphase.EnableDynamicConfigForNode(client, j.cfg.NodeRegistration.Name, kubeletVersion); err != nil {
 | 
				
			||||||
			return fmt.Errorf("error consuming base kubelet configuration: %v", err)
 | 
								return fmt.Errorf("error consuming base kubelet configuration: %v", err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -287,3 +318,15 @@ func (j *Join) Run(out io.Writer) error {
 | 
				
			|||||||
	fmt.Fprintf(out, joinDoneMsgf)
 | 
						fmt.Fprintf(out, joinDoneMsgf)
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// waitForTLSBootstrappedClient waits for the /etc/kubernetes/kubelet.conf file to be available
 | 
				
			||||||
 | 
					func waitForTLSBootstrappedClient() 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.
 | 
				
			||||||
 | 
						return wait.PollImmediate(kubeadmconstants.APICallRetryInterval, kubeadmconstants.TLSBootstrapTimeout, func() (bool, error) {
 | 
				
			||||||
 | 
							_, err := os.Stat(kubeletKubeConfig)
 | 
				
			||||||
 | 
							return (err == nil), nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -171,6 +171,8 @@ const (
 | 
				
			|||||||
	PatchNodeTimeout = 2 * time.Minute
 | 
						PatchNodeTimeout = 2 * time.Minute
 | 
				
			||||||
	// UpdateNodeTimeout specifies how long kubeadm should wait for updating node with the initial remote configuration of kubelet before timing out
 | 
						// UpdateNodeTimeout specifies how long kubeadm should wait for updating node with the initial remote configuration of kubelet before timing out
 | 
				
			||||||
	UpdateNodeTimeout = 2 * time.Minute
 | 
						UpdateNodeTimeout = 2 * time.Minute
 | 
				
			||||||
 | 
						// TLSBootstrapTimeout specifies how long kubeadm should wait for the kubelet to perform the TLS Bootstrap
 | 
				
			||||||
 | 
						TLSBootstrapTimeout = 2 * time.Minute
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// MinimumAddressesInServiceSubnet defines minimum amount of nodes the Service subnet should allow.
 | 
						// MinimumAddressesInServiceSubnet defines minimum amount of nodes the Service subnet should allow.
 | 
				
			||||||
	// We need at least ten, because the DNS service is always at the tenth cluster clusterIP
 | 
						// We need at least ten, because the DNS service is always at the tenth cluster clusterIP
 | 
				
			||||||
@@ -184,6 +186,10 @@ const (
 | 
				
			|||||||
	// This is a duplicate definition of the constant in pkg/controller/service/service_controller.go
 | 
						// This is a duplicate definition of the constant in pkg/controller/service/service_controller.go
 | 
				
			||||||
	LabelNodeRoleMaster = "node-role.kubernetes.io/master"
 | 
						LabelNodeRoleMaster = "node-role.kubernetes.io/master"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// AnnotationKubeadmCRISocket specifies the annotation kubeadm uses to preserve the crisocket information given to kubeadm at
 | 
				
			||||||
 | 
						// init/join time for use later. kubeadm annotates the node object with this information
 | 
				
			||||||
 | 
						AnnotationKubeadmCRISocket = "kubeadm.alpha.kubernetes.io/cri-socket"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// MasterConfigurationConfigMap specifies in what ConfigMap in the kube-system namespace the `kubeadm init` configuration should be stored
 | 
						// MasterConfigurationConfigMap specifies in what ConfigMap in the kube-system namespace the `kubeadm init` configuration should be stored
 | 
				
			||||||
	MasterConfigurationConfigMap = "kubeadm-config"
 | 
						MasterConfigurationConfigMap = "kubeadm-config"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,17 +18,13 @@ package kubelet
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"path/filepath"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"k8s.io/api/core/v1"
 | 
						"k8s.io/api/core/v1"
 | 
				
			||||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/types"
 | 
						"k8s.io/apimachinery/pkg/types"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/wait"
 | 
					 | 
				
			||||||
	clientset "k8s.io/client-go/kubernetes"
 | 
						clientset "k8s.io/client-go/kubernetes"
 | 
				
			||||||
	kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
 | 
						kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
 | 
				
			||||||
	"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
 | 
						"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
 | 
				
			||||||
	kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
 | 
					 | 
				
			||||||
	"k8s.io/kubernetes/pkg/util/version"
 | 
						"k8s.io/kubernetes/pkg/util/version"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -63,22 +59,3 @@ func patchNodeForDynamicConfig(n *v1.Node, configMapName string, configMapUID ty
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
// GetLocalNodeTLSBootstrappedClient waits for the kubelet to perform the TLS bootstrap
 | 
					 | 
				
			||||||
// and then creates a client from config file /etc/kubernetes/kubelet.conf
 | 
					 | 
				
			||||||
func GetLocalNodeTLSBootstrappedClient() (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)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										40
									
								
								cmd/kubeadm/app/phases/patchnode/patchnode.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								cmd/kubeadm/app/phases/patchnode/patchnode.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2018 The Kubernetes Authors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					limitations under the License.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package patchnode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"k8s.io/api/core/v1"
 | 
				
			||||||
 | 
						clientset "k8s.io/client-go/kubernetes"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/cmd/kubeadm/app/constants"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/cmd/kubeadm/app/util/apiclient"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AnnotateCRISocket annotates the node with the given crisocket
 | 
				
			||||||
 | 
					func AnnotateCRISocket(client clientset.Interface, nodeName string, criSocket string) error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fmt.Printf("[patchnode] Uploading the CRI Socket information %q to the Node API object %q as an annotation\n", criSocket, nodeName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return apiclient.PatchNode(client, nodeName, func(n *v1.Node) {
 | 
				
			||||||
 | 
							annotateNodeWithCRISocket(n, criSocket)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func annotateNodeWithCRISocket(n *v1.Node, criSocket string) {
 | 
				
			||||||
 | 
						n.ObjectMeta.Annotations[constants.AnnotationKubeadmCRISocket] = criSocket
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user