Exemple #1
0
// RunCreateToken generates a new bootstrap token and stores it as a secret on the server.
func RunCreateToken(out io.Writer, cmd *cobra.Command, tokenDuration time.Duration, token string) error {
	client, err := kubemaster.CreateClientFromFile(path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "admin.conf"))
	if err != nil {
		return err
	}

	d := &kubeadmapi.TokenDiscovery{}
	if token != "" {
		parsedID, parsedSecret, err := kubeadmutil.ParseToken(token)
		if err != nil {
			return err
		}
		d.ID = parsedID
		d.Secret = parsedSecret
	}
	err = kubeadmutil.GenerateTokenIfNeeded(d)
	if err != nil {
		return err
	}

	err = kubeadmutil.UpdateOrCreateToken(client, d, tokenDuration)
	if err != nil {
		return err
	}
	fmt.Fprintln(out, kubeadmutil.BearerToken(d))

	return nil
}
Exemple #2
0
func setInitDynamicDefaults(cfg *kubeadmapi.MasterConfiguration) error {
	// Auto-detect the IP
	if len(cfg.API.AdvertiseAddresses) == 0 {
		ip, err := netutil.ChooseHostInterface()
		if err != nil {
			return err
		}
		cfg.API.AdvertiseAddresses = []string{ip.String()}
	}

	// Validate version argument
	ver, err := kubeadmutil.KubernetesReleaseVersion(cfg.KubernetesVersion)
	if err != nil {
		if cfg.KubernetesVersion != kubeadmapiext.DefaultKubernetesVersion {
			return err
		} else {
			ver = kubeadmapiext.DefaultKubernetesFallbackVersion
		}
	}
	cfg.KubernetesVersion = ver
	fmt.Println("[init] Using Kubernetes version:", ver)

	// Omit the "v" in the beginning, otherwise semver will fail
	// If the version is newer than the specified version, RBAC v1beta1 support is enabled in the apiserver so we can default to RBAC
	k8sVersion, err := semver.Parse(cfg.KubernetesVersion[1:])
	if k8sVersion.GT(allowAllMaxVersion) {
		cfg.AuthorizationMode = "RBAC"
	}

	fmt.Println("[init] Using Authorization mode:", cfg.AuthorizationMode)

	// Warn about the limitations with the current cloudprovider solution.
	if cfg.CloudProvider != "" {
		fmt.Println("[init] WARNING: For cloudprovider integrations to work --cloud-provider must be set for all kubelets in the cluster.")
		fmt.Println("\t(/etc/systemd/system/kubelet.service.d/10-kubeadm.conf should be edited for this purpose)")
	}

	// Validate token if any, otherwise generate
	if cfg.Discovery.Token != nil {
		if cfg.Discovery.Token.ID != "" && cfg.Discovery.Token.Secret != "" {
			fmt.Printf("[init] A token has been provided, validating [%s]\n", kubeadmutil.BearerToken(cfg.Discovery.Token))
			if valid, err := kubeadmutil.ValidateToken(cfg.Discovery.Token); valid == false {
				return err
			}
		} else {
			fmt.Println("[init] A token has not been provided, generating one")
			if err := kubeadmutil.GenerateToken(cfg.Discovery.Token); err != nil {
				return err
			}
		}

		// If there aren't any addresses specified, default to the first advertised address which can be user-provided or the default network interface's IP address
		if len(cfg.Discovery.Token.Addresses) == 0 {
			cfg.Discovery.Token.Addresses = []string{cfg.API.AdvertiseAddresses[0] + ":" + strconv.Itoa(kubeadmapiext.DefaultDiscoveryBindPort)}
		}
	}

	return nil
}
Exemple #3
0
// EstablishMasterConnection establishes a connection with exactly one of the provided API endpoints.
// The function builds a client for every endpoint and concurrently keeps trying to connect to any one
// of the provided endpoints. Blocks until at least one connection is established, then it stops the
// connection attempts for other endpoints.
func EstablishMasterConnection(c *kubeadmapi.TokenDiscovery, clusterInfo *kubeadmapi.ClusterInfo) (*ConnectionDetails, error) {
	hostName, err := os.Hostname()
	if err != nil {
		return nil, fmt.Errorf("failed to get node hostname [%v]", err)
	}
	// TODO(phase1+) https://github.com/kubernetes/kubernetes/issues/33641
	nodeName := types.NodeName(hostName)

	endpoints := clusterInfo.Endpoints
	caCert := []byte(clusterInfo.CertificateAuthorities[0])

	stopChan := make(chan struct{})
	result := make(chan *ConnectionDetails)
	var wg sync.WaitGroup
	for _, endpoint := range endpoints {
		clientSet, err := createClients(caCert, endpoint, kubeadmutil.BearerToken(c), nodeName)
		if err != nil {
			fmt.Printf("[bootstrap] Warning: %s. Skipping endpoint %s\n", err, endpoint)
			continue
		}
		wg.Add(1)
		go func(apiEndpoint string) {
			defer wg.Done()
			wait.Until(func() {
				fmt.Printf("[bootstrap] Trying to connect to endpoint %s\n", apiEndpoint)
				err := checkAPIEndpoint(clientSet, apiEndpoint)
				if err != nil {
					fmt.Printf("[bootstrap] Endpoint check failed [%v]\n", err)
					return
				}
				fmt.Printf("[bootstrap] Successfully established connection with endpoint %q\n", apiEndpoint)
				// connection established, stop all wait threads
				close(stopChan)
				result <- &ConnectionDetails{
					ClientSet:  clientSet,
					CertClient: clientSet.CertificatesV1alpha1Client,
					Endpoint:   apiEndpoint,
					CACert:     caCert,
					NodeName:   nodeName,
				}
			}, retryTimeout*time.Second, stopChan)
		}(endpoint)
	}

	go func() {
		wg.Wait()
		// all wait.Until() calls have finished now
		close(result)
	}()

	establishedConnection, ok := <-result
	if !ok {
		return nil, fmt.Errorf("failed to create bootstrap clients for any of the provided API endpoints")
	}
	return establishedConnection, nil
}
Exemple #4
0
func RunGenerateToken(out io.Writer) error {
	td := &kubeadmapi.TokenDiscovery{}
	err := kubeadmutil.GenerateToken(td)
	if err != nil {
		return err
	}

	fmt.Fprintln(out, kubeadmutil.BearerToken(td))
	return nil
}
Exemple #5
0
func generateTokenIfNeeded(d *kubeadmapi.TokenDiscovery) error {
	ok, err := kubeadmutil.IsTokenValid(d)
	if err != nil {
		return err
	}
	if ok {
		fmt.Println("[tokens] Accepted provided token")
		return nil
	}
	if err := kubeadmutil.GenerateToken(d); err != nil {
		return err
	}
	fmt.Printf("[tokens] Generated token: %q\n", kubeadmutil.BearerToken(d))
	return nil
}
Exemple #6
0
// EstablishMasterConnection establishes a connection with exactly one of the provided API endpoints.
// The function builds a client for every endpoint and concurrently keeps trying to connect to any one
// of the provided endpoints. Blocks until at least one connection is established, then it stops the
// connection attempts for other endpoints and returns the valid client configuration, if any.
func EstablishMasterConnection(c *kubeadmapi.TokenDiscovery, clusterInfo *kubeadmapi.ClusterInfo) (*clientcmdapi.Config, error) {
	hostName, err := os.Hostname()
	if err != nil {
		return nil, fmt.Errorf("failed to get node hostname [%v]", err)
	}
	// TODO(phase1+) https://github.com/kubernetes/kubernetes/issues/33641
	nodeName := types.NodeName(hostName)

	endpoints := clusterInfo.Endpoints
	caCert := []byte(clusterInfo.CertificateAuthorities[0])

	stopChan := make(chan struct{})
	var clientConfig *clientcmdapi.Config
	var once sync.Once
	var wg sync.WaitGroup
	for _, endpoint := range endpoints {
		ac, err := createClients(caCert, endpoint, kubeadmutil.BearerToken(c), nodeName)
		if err != nil {
			fmt.Printf("[bootstrap] Warning: %s. Skipping endpoint %s\n", err, endpoint)
			continue
		}
		wg.Add(1)
		go func(apiEndpoint string) {
			defer wg.Done()
			wait.Until(func() {
				fmt.Printf("[bootstrap] Trying to connect to endpoint %s\n", apiEndpoint)
				err := checkAPIEndpoint(ac.clientSet, apiEndpoint)
				if err != nil {
					fmt.Printf("[bootstrap] Endpoint check failed [%v]\n", err)
					return
				}
				fmt.Printf("[bootstrap] Successfully established connection with endpoint %q\n", apiEndpoint)
				// connection established, stop all wait threads
				close(stopChan)
				once.Do(func() {
					clientConfig = ac.clientConfig
				})
			}, retryTimeout*time.Second, stopChan)
		}(endpoint)
	}
	wg.Wait()

	if clientConfig == nil {
		return nil, fmt.Errorf("failed to create bootstrap clients for any of the provided API endpoints")
	}

	return clientConfig, nil
}
Exemple #7
0
// RunCreateToken generates a new bootstrap token and stores it as a secret on the server.
func RunCreateToken(out io.Writer, cmd *cobra.Command, tokenDuration time.Duration, token string) error {
	client, err := kubemaster.CreateClientFromFile(path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, kubeconfig.AdminKubeConfigFileName))
	if err != nil {
		return err
	}

	parsedID, parsedSecret, err := kubeadmutil.ParseToken(token)
	if err != nil {
		return err
	}
	td := &kubeadmapi.TokenDiscovery{ID: parsedID, Secret: parsedSecret}

	err = kubeadmutil.UpdateOrCreateToken(client, td, tokenDuration)
	if err != nil {
		return err
	}
	fmt.Fprintln(out, kubeadmutil.BearerToken(td))

	return nil
}
Exemple #8
0
// Run executes master node provisioning, including certificates, needed static pod manifests, etc.
func (i *Init) Run(out io.Writer) error {

	if i.cfg.Discovery.Token != nil {
		if err := kubemaster.PrepareTokenDiscovery(i.cfg.Discovery.Token); err != nil {
			return err
		}
		if err := kubemaster.CreateTokenAuthFile(kubeadmutil.BearerToken(i.cfg.Discovery.Token)); err != nil {
			return err
		}
	}

	if err := kubemaster.WriteStaticPodManifests(i.cfg); err != nil {
		return err
	}

	caKey, caCert, err := kubemaster.CreatePKIAssets(i.cfg)
	if err != nil {
		return err
	}

	kubeconfigs, err := kubemaster.CreateCertsAndConfigForClients(i.cfg.API, []string{"kubelet", "admin"}, caKey, caCert)
	if err != nil {
		return err
	}

	// kubeadm is responsible for writing the following kubeconfig file, which
	// kubelet should be waiting for. Help user avoid foot-shooting by refusing to
	// write a file that has already been written (the kubelet will be up and
	// running in that case - they'd need to stop the kubelet, remove the file, and
	// start it again in that case).
	// TODO(phase1+) this is no longer the right place to guard against foo-shooting,
	// we need to decide how to handle existing files (it may be handy to support
	// importing existing files, may be we could even make our command idempotant,
	// or at least allow for external PKI and stuff)
	for name, kubeconfig := range kubeconfigs {
		if err := kubeadmutil.WriteKubeconfigIfNotExists(name, kubeconfig); err != nil {
			return err
		}
	}

	client, err := kubemaster.CreateClientAndWaitForAPI(kubeconfigs["admin"])
	if err != nil {
		return err
	}

	if err := kubemaster.UpdateMasterRoleLabelsAndTaints(client, false); err != nil {
		return err
	}

	if i.cfg.Discovery.Token != nil {
		if err := kubemaster.CreateDiscoveryDeploymentAndSecret(i.cfg, client, caCert); err != nil {
			return err
		}
	}

	if err := kubemaster.CreateEssentialAddons(i.cfg, client); err != nil {
		return err
	}

	fmt.Fprintf(out, initDoneMsgf, generateJoinArgs(i.cfg))
	return nil
}
Exemple #9
0
// Run executes master node provisioning, including certificates, needed static pod manifests, etc.
func (i *Init) Run(out io.Writer) error {

	// PHASE 1: Generate certificates
	caCert, err := certphase.CreatePKIAssets(i.cfg, kubeadmapi.GlobalEnvParams.HostPKIPath)
	if err != nil {
		return err
	}

	// PHASE 2: Generate kubeconfig files for the admin and the kubelet

	// TODO this is not great, but there is only one address we can use here
	// so we'll pick the first one, there is much of chance to have an empty
	// slice by the time this gets called
	masterEndpoint := fmt.Sprintf("https://%s:%d", i.cfg.API.AdvertiseAddresses[0], i.cfg.API.Port)
	err = kubeconfigphase.CreateAdminAndKubeletKubeConfig(masterEndpoint, kubeadmapi.GlobalEnvParams.HostPKIPath, kubeadmapi.GlobalEnvParams.KubernetesDir)
	if err != nil {
		return err
	}

	// TODO: It's not great to have an exception for token here, but necessary because the apiserver doesn't handle this properly in the API yet
	// but relies on files on disk for now, which is daunting.
	if i.cfg.Discovery.Token != nil {
		if err := kubemaster.CreateTokenAuthFile(kubeadmutil.BearerToken(i.cfg.Discovery.Token)); err != nil {
			return err
		}
	}

	// Phase 3: Bootstrap the control plane
	if err := kubemaster.WriteStaticPodManifests(i.cfg); err != nil {
		return err
	}

	client, err := kubemaster.CreateClientAndWaitForAPI(path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, kubeconfigphase.AdminKubeConfigFileName))
	if err != nil {
		return err
	}

	if i.cfg.AuthorizationMode == "RBAC" {
		err = apiconfig.CreateBootstrapRBACClusterRole(client)
		if err != nil {
			return err
		}

		err = apiconfig.CreateKubeDNSRBACClusterRole(client)
		if err != nil {
			return err
		}

		// TODO: remove this when https://github.com/kubernetes/kubeadm/issues/114 is fixed
		err = apiconfig.CreateKubeProxyClusterRoleBinding(client)
		if err != nil {
			return err
		}
	}

	if err := kubemaster.UpdateMasterRoleLabelsAndTaints(client, false); err != nil {
		return err
	}

	if i.cfg.Discovery.Token != nil {
		fmt.Printf("[token-discovery] Using token: %s\n", kubeadmutil.BearerToken(i.cfg.Discovery.Token))
		if err := kubemaster.CreateDiscoveryDeploymentAndSecret(i.cfg, client, caCert); err != nil {
			return err
		}
		if err := kubeadmutil.UpdateOrCreateToken(client, i.cfg.Discovery.Token, kubeadmutil.DefaultTokenDuration); err != nil {
			return err
		}
	}

	if err := kubemaster.CreateEssentialAddons(i.cfg, client); err != nil {
		return err
	}

	fmt.Fprintf(out, initDoneMsgf, generateJoinArgs(i.cfg))
	return nil
}