kubeadm: allow kubeadm init to read config from file

This commit is contained in:
Mike Danese 2016-10-10 15:29:49 -07:00
parent c2027108cd
commit 58d25e378c

View File

@ -19,6 +19,7 @@ package cmd
import ( import (
"fmt" "fmt"
"io" "io"
"io/ioutil"
"github.com/renstrom/dedent" "github.com/renstrom/dedent"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -26,8 +27,10 @@ import (
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
kubemaster "k8s.io/kubernetes/cmd/kubeadm/app/master" kubemaster "k8s.io/kubernetes/cmd/kubeadm/app/master"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util" kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/cloudprovider" "k8s.io/kubernetes/pkg/cloudprovider"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/runtime"
netutil "k8s.io/kubernetes/pkg/util/net" netutil "k8s.io/kubernetes/pkg/util/net"
) )
@ -44,12 +47,19 @@ var (
// NewCmdInit returns "kubeadm init" command. // NewCmdInit returns "kubeadm init" command.
func NewCmdInit(out io.Writer) *cobra.Command { func NewCmdInit(out io.Writer) *cobra.Command {
cfg := &kubeadmapi.MasterConfiguration{} cfg := &kubeadmapi.MasterConfiguration{}
var cfgPath string
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "init", Use: "init",
Short: "Run this in order to set up the Kubernetes master.", Short: "Run this in order to set up the Kubernetes master.",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
err := RunInit(out, cmd, args, cfg) check := func(err error) {
cmdutil.CheckErr(err) if err != nil {
cmdutil.CheckErr(fmt.Errorf("<cmd/init> %v", err))
}
}
i, err := NewInit(cfgPath, cfg)
check(err)
check(i.Run(out))
}, },
} }
@ -87,6 +97,8 @@ func NewCmdInit(out io.Writer) *cobra.Command {
`Choose a specific Kubernetes version for the control plane`, `Choose a specific Kubernetes version for the control plane`,
) )
cmd.PersistentFlags().StringVar(&cfgPath, "config", "", "Path to kubeadm config file")
// TODO (phase1+) @errordeveloper make the flags below not show up in --help but rather on --advanced-help // TODO (phase1+) @errordeveloper make the flags below not show up in --help but rather on --advanced-help
cmd.PersistentFlags().StringSliceVar( cmd.PersistentFlags().StringSliceVar(
&cfg.Etcd.Endpoints, "external-etcd-endpoints", []string{}, &cfg.Etcd.Endpoints, "external-etcd-endpoints", []string{},
@ -115,14 +127,26 @@ func NewCmdInit(out io.Writer) *cobra.Command {
return cmd return cmd
} }
// RunInit executes master node provisioning, including certificates, needed static pod manifests, etc. type Init struct {
func RunInit(out io.Writer, cmd *cobra.Command, args []string, cfg *kubeadmapi.MasterConfiguration) error { cfg *kubeadmapi.MasterConfiguration
}
func NewInit(cfgPath string, cfg *kubeadmapi.MasterConfiguration) (*Init, error) {
if cfgPath != "" {
b, err := ioutil.ReadFile(cfgPath)
if err != nil {
return nil, fmt.Errorf("unable to read config from %q [%v]", cfgPath, err)
}
if err := runtime.DecodeInto(api.Codecs.UniversalDecoder(), b, cfg); err != nil {
return nil, fmt.Errorf("unable to decode config from %q [%v]", cfgPath, err)
}
}
// Auto-detect the IP // Auto-detect the IP
if len(cfg.API.AdvertiseAddresses) == 0 { if len(cfg.API.AdvertiseAddresses) == 0 {
// TODO(phase1+) perhaps we could actually grab eth0 and eth1 // TODO(phase1+) perhaps we could actually grab eth0 and eth1
ip, err := netutil.ChooseHostInterface() ip, err := netutil.ChooseHostInterface()
if err != nil { if err != nil {
return err return nil, err
} }
cfg.API.AdvertiseAddresses = []string{ip.String()} cfg.API.AdvertiseAddresses = []string{ip.String()}
} }
@ -130,26 +154,31 @@ func RunInit(out io.Writer, cmd *cobra.Command, args []string, cfg *kubeadmapi.M
// TODO(phase1+) create a custom flag // TODO(phase1+) create a custom flag
if cfg.CloudProvider != "" { if cfg.CloudProvider != "" {
if cloudprovider.IsCloudProvider(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) fmt.Printf("cloud provider %q initialized for the control plane. Remember to set the same cloud provider flag on the kubelet.\n", cfg.CloudProvider)
} else { } 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()) return nil, fmt.Errorf("cloud provider %q is not supported, you can use any of %v, or leave it unset.\n", cfg.CloudProvider, cloudprovider.CloudProviders())
} }
} }
return &Init{cfg: cfg}, nil
}
if err := kubemaster.CreateTokenAuthFile(&cfg.Secrets); err != nil { // RunInit 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 return err
} }
if err := kubemaster.WriteStaticPodManifests(cfg); err != nil { if err := kubemaster.WriteStaticPodManifests(i.cfg); err != nil {
return err return err
} }
caKey, caCert, err := kubemaster.CreatePKIAssets(cfg) caKey, caCert, err := kubemaster.CreatePKIAssets(i.cfg)
if err != nil { if err != nil {
return err return err
} }
kubeconfigs, err := kubemaster.CreateCertsAndConfigForClients(cfg.API.AdvertiseAddresses, []string{"kubelet", "admin"}, caKey, caCert) kubeconfigs, err := kubemaster.CreateCertsAndConfigForClients(i.cfg.API.AdvertiseAddresses, []string{"kubelet", "admin"}, caKey, caCert)
if err != nil { if err != nil {
return err return err
} }
@ -179,18 +208,18 @@ func RunInit(out io.Writer, cmd *cobra.Command, args []string, cfg *kubeadmapi.M
return err return err
} }
if err := kubemaster.CreateDiscoveryDeploymentAndSecret(cfg, client, caCert); err != nil { if err := kubemaster.CreateDiscoveryDeploymentAndSecret(i.cfg, client, caCert); err != nil {
return err return err
} }
if err := kubemaster.CreateEssentialAddons(cfg, client); err != nil { if err := kubemaster.CreateEssentialAddons(i.cfg, client); err != nil {
return err return err
} }
// TODO(phase1+) use templates to reference struct fields directly as order of args is fragile // TODO(phase1+) use templates to reference struct fields directly as order of args is fragile
fmt.Fprintf(out, initDoneMsgf, fmt.Fprintf(out, initDoneMsgf,
cfg.Secrets.GivenToken, i.cfg.Secrets.GivenToken,
cfg.API.AdvertiseAddresses[0], i.cfg.API.AdvertiseAddresses[0],
) )
return nil return nil