// RunJoin executes worked node provisioning and tries to join an existing cluster. func RunJoin(out io.Writer, cmd *cobra.Command, args []string, s *kubeadmapi.KubeadmConfig) error { // TODO(phase1+) this we are missing args from the help text, there should be a way to tell cobra about it if len(args) == 0 { return fmt.Errorf("<cmd/join> must specify master IP address (see --help)") } for _, i := range args { addr := net.ParseIP(i) // TODO(phase1+) should allow resolvable names too if addr == nil { return fmt.Errorf("<cmd/join> failed to parse argument (%q) as an IP address", i) } s.JoinFlags.MasterAddrs = append(s.JoinFlags.MasterAddrs, addr) } ok, err := kubeadmutil.UseGivenTokenIfValid(s) if !ok { if err != nil { return fmt.Errorf("<cmd/join> %v (see --help)\n", err) } return fmt.Errorf("Must specify --token (see --help)\n") } kubeconfig, err := kubenode.RetrieveTrustedClusterInfo(s) if err != nil { return err } err = kubeadmutil.WriteKubeconfigIfNotExists(s, "kubelet", kubeconfig) if err != nil { return err } fmt.Fprintf(out, joinDoneMsgf) return nil }
// RunJoin executes worked node provisioning and tries to join an existing cluster. func RunJoin(out io.Writer, cmd *cobra.Command, args []string, s *kubeadmapi.NodeConfiguration) error { // TODO(phase1+) this we are missing args from the help text, there should be a way to tell cobra about it if len(args) == 0 { return fmt.Errorf("<cmd/join> must specify master IP address (see --help)") } s.MasterAddresses = append(s.MasterAddresses, args...) ok, err := kubeadmutil.UseGivenTokenIfValid(&s.Secrets) if !ok { if err != nil { return fmt.Errorf("<cmd/join> %v (see --help)\n", err) } return fmt.Errorf("Must specify --token (see --help)\n") } kubeconfig, err := kubenode.RetrieveTrustedClusterInfo(s) if err != nil { return err } err = kubeadmutil.WriteKubeconfigIfNotExists("kubelet", kubeconfig) if err != nil { return err } fmt.Fprintf(out, joinDoneMsgf) return nil }
// Run executes master node provisioning, including certificates, needed static pod manifests, etc. func (i *Init) Run(out io.Writer) error { if err := kubemaster.CreateTokenAuthFile(&i.cfg.Secrets); 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 agains 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 } schedulePodsOnMaster := false if err := kubemaster.UpdateMasterRoleLabelsAndTaints(client, schedulePodsOnMaster); err != nil { return err } if err := kubemaster.CreateDiscoveryDeploymentAndSecret(i.cfg, client, caCert); err != nil { return err } if err := kubemaster.CreateEssentialAddons(i.cfg, client); err != nil { return err } data := joinArgsData{i.cfg, kubeadmapiext.DefaultAPIBindPort, kubeadmapiext.DefaultDiscoveryBindPort} if joinArgs, err := generateJoinArgs(data); err != nil { return err } else { fmt.Fprintf(out, initDoneMsgf, joinArgs) } return nil }
// Run executes worked node provisioning and tries to join an existing cluster. func (j *Join) Run(out io.Writer) error { clusterInfo, err := kubenode.RetrieveTrustedClusterInfo(j.cfg) if err != nil { return err } connectionDetails, err := kubenode.EstablishMasterConnection(j.cfg, clusterInfo) if err != nil { return err } err = kubenode.CheckForNodeNameDuplicates(connectionDetails) if err != nil { return err } kubeconfig, err := kubenode.PerformTLSBootstrap(connectionDetails) if err != nil { return err } err = kubeadmutil.WriteKubeconfigIfNotExists("kubelet", kubeconfig) if err != nil { return err } fmt.Fprintf(out, joinDoneMsgf) return nil }
// RunJoin executes worked node provisioning and tries to join an existing cluster. func RunJoin(out io.Writer, cmd *cobra.Command, args []string, s *kubeadmapi.NodeConfiguration, skipPreFlight bool) error { // TODO(phase1+) this we are missing args from the help text, there should be a way to tell cobra about it if !skipPreFlight { fmt.Println("Running pre-flight checks") err := preflight.RunJoinNodeChecks() if err != nil { return err } } else { fmt.Println("Skipping pre-flight checks") } if len(args) == 0 { return fmt.Errorf("<cmd/join> must specify master IP address (see --help)") } s.MasterAddresses = append(s.MasterAddresses, args...) ok, err := kubeadmutil.UseGivenTokenIfValid(&s.Secrets) if !ok { if err != nil { return fmt.Errorf("<cmd/join> %v (see --help)\n", err) } return fmt.Errorf("Must specify --token (see --help)\n") } clusterInfo, err := kubenode.RetrieveTrustedClusterInfo(s) if err != nil { return err } connectionDetails, err := kubenode.EstablishMasterConnection(s, clusterInfo) if err != nil { return err } kubeconfig, err := kubenode.PerformTLSBootstrap(connectionDetails) if err != nil { return err } err = kubeadmutil.WriteKubeconfigIfNotExists("kubelet", kubeconfig) if err != nil { return err } fmt.Fprintf(out, joinDoneMsgf) return nil }
// Run executes worked node provisioning and tries to join an existing cluster. func (j *Join) Run(out io.Writer) error { clusterInfo, err := kubenode.RetrieveTrustedClusterInfo(j.cfg.Discovery.Token) if err != nil { return err } var cfg *clientcmdapi.Config // TODO: delete this first block when we move Token to the discovery interface if j.cfg.Discovery.Token != nil { connectionDetails, err := kubenode.EstablishMasterConnection(j.cfg.Discovery.Token, clusterInfo) if err != nil { return err } err = kubenode.CheckForNodeNameDuplicates(connectionDetails) if err != nil { return err } cfg, err = kubenode.PerformTLSBootstrapDeprecated(connectionDetails) if err != nil { return err } } else { cfg, err = discovery.For(j.cfg.Discovery) if err != nil { return err } if err := kubenode.PerformTLSBootstrap(cfg); err != nil { return err } } err = kubeadmutil.WriteKubeconfigIfNotExists("kubelet", cfg) if err != nil { return err } fmt.Fprintf(out, joinDoneMsgf) return nil }
// RunInit executes master node provisioning, including certificates, needed static pod manifests, etc. func RunInit(out io.Writer, cmd *cobra.Command, args []string, cfg *kubeadmapi.MasterConfiguration) error { // Auto-detect the IP if len(cfg.API.AdvertiseAddresses) == 0 { // TODO(phase1+) perhaps we could actually grab eth0 and eth1 ip, err := netutil.ChooseHostInterface() if err != nil { return err } cfg.API.AdvertiseAddresses = []string{ip.String()} } // TODO(phase1+) create a custom flag if cfg.CloudProvider != "" { if cloudprovider.IsCloudProvider(cfg.CloudProvider) { fmt.Printf("<cmd/init> cloud provider %q initialized for the control plane. Remember to set the same cloud provider flag on the kubelet.\n", cfg.CloudProvider) } else { return fmt.Errorf("<cmd/init> cloud provider %q is not supported, you can use any of %v, or leave it unset.\n", cfg.CloudProvider, cloudprovider.CloudProviders()) } } if err := kubemaster.CreateTokenAuthFile(&cfg.Secrets); err != nil { return err } if err := kubemaster.WriteStaticPodManifests(cfg); err != nil { return err } caKey, caCert, err := kubemaster.CreatePKIAssets(cfg) if err != nil { return err } kubeconfigs, err := kubemaster.CreateCertsAndConfigForClients(cfg.API.AdvertiseAddresses, []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 agains 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 } schedulePodsOnMaster := false if err := kubemaster.UpdateMasterRoleLabelsAndTaints(client, schedulePodsOnMaster); err != nil { return err } if err := kubemaster.CreateDiscoveryDeploymentAndSecret(cfg, client, caCert); err != nil { return err } if err := kubemaster.CreateEssentialAddons(cfg, client); err != nil { return err } // TODO(phase1+) use templates to reference struct fields directly as order of args is fragile fmt.Fprintf(out, initDoneMsgf, cfg.Secrets.GivenToken, cfg.API.AdvertiseAddresses[0], ) return nil }
// Run executes master node provisioning, including certificates, needed static pod manifests, etc. func (i *Init) Run(out io.Writer) error { if err := kubemaster.CreateTokenAuthFile(&i.cfg.Secrets); 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 agains 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 } schedulePodsOnMaster := false if err := kubemaster.UpdateMasterRoleLabelsAndTaints(client, schedulePodsOnMaster); err != nil { return err } if err := kubemaster.CreateDiscoveryDeploymentAndSecret(i.cfg, client, caCert); err != nil { return err } if err := kubemaster.CreateEssentialAddons(i.cfg, client); err != nil { return err } // TODO(phase1+) we could probably use templates for this logic, and reference struct fields directly etc joinArgs := []string{fmt.Sprintf("--token=%s", i.cfg.Secrets.GivenToken)} if i.cfg.API.BindPort != kubeadmapi.DefaultAPIBindPort { joinArgs = append(joinArgs, fmt.Sprintf("--api-port=%d", i.cfg.API.BindPort)) } if i.cfg.Discovery.BindPort != kubeadmapi.DefaultDiscoveryBindPort { joinArgs = append(joinArgs, fmt.Sprintf("--discovery-port=%d", i.cfg.Discovery.BindPort)) } joinArgs = append(joinArgs, i.cfg.API.AdvertiseAddresses[0]) fmt.Fprintf(out, initDoneMsgf, strings.Join(joinArgs, " ")) return nil }