kubeadm: refactor config

1) break object into substructures
2) seperate a config object for master and node
pull/6/head
Mike Danese 2016-09-28 23:36:18 -07:00
parent 3933ddbc9a
commit 56ea178e7c
20 changed files with 317 additions and 269 deletions

View File

@ -0,0 +1,23 @@
/*
Copyright 2016 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 api
const (
DefaultServiceDNSDomain = "cluster.local"
DefaultServicesSubnet = "10.12.0.0/12"
DefaultKubernetesVersion = "v1.4.0"
)

View File

@ -0,0 +1,49 @@
/*
Copyright 2016 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 api
import (
"fmt"
"os"
"runtime"
"strings"
)
// TODO(phase2) use componentconfig
// we need some params for testing etc, let's keep these hidden for now
func GetEnvParams() map[string]string {
envParams := map[string]string{
// TODO(phase1+): Mode prefix and host_pki_path to another place as constants, and use them everywhere
// Right now they're used here and there, but not consequently
"kubernetes_dir": "/etc/kubernetes",
"host_pki_path": "/etc/kubernetes/pki",
"host_etcd_path": "/var/lib/etcd",
"hyperkube_image": "",
"discovery_image": fmt.Sprintf("gcr.io/google_containers/kube-discovery-%s:%s", runtime.GOARCH, "1.0"),
"etcd_image": "",
"component_loglevel": "--v=4",
}
for k := range envParams {
if v := os.Getenv(fmt.Sprintf("KUBE_%s", strings.ToUpper(k))); v != "" {
envParams[k] = v
}
}
return envParams
}

View File

@ -16,89 +16,54 @@ limitations under the License.
package api
import (
"net"
)
import "k8s.io/kubernetes/pkg/api/unversioned"
// KubeadmConfig TODO add description
// TODO(phase1+) @krousey: Please don't embed structs. It obfuscates the source of the fields and doesn't really buy you anything.
type KubeadmConfig struct {
InitFlags
JoinFlags
Secrets struct {
GivenToken string // dot-separated `<TokenID>.<Token>` set by the user
TokenID string // optional on master side, will be generated if not specified
Token []byte // optional on master side, will be generated if not specified
BearerToken string // set based on Token
}
EnvParams map[string]string // TODO(phase2) this is likely to be come componentconfig
type MasterConfiguration struct {
unversioned.TypeMeta
Secrets Secrets
API API
Etcd Etcd
Networking Networking
KubernetesVersion string
CloudProvider string
}
// TODO(phase2) should we add validation functions for these structs?
// TODO(phase1+) refactor token handling
// - https://github.com/kubernetes/kubernetes/pull/33262/files#r80333662
// - https://github.com/kubernetes/kubernetes/pull/33262/files#r80336374
// - https://github.com/kubernetes/kubernetes/pull/33262/files#r80333982
// InitFlags holds values for "kubeadm init" command flags.
type InitFlags struct {
API struct {
AdvertiseAddrs []net.IP
ExternalDNSNames []string
Etcd struct {
ExternalEndpoints []string
ExternalCAFile string
ExternalCertFile string
ExternalKeyFile string
}
}
Services struct {
CIDR net.IPNet
DNSDomain string
}
PodNetwork struct {
CIDR net.IPNet
}
Versions struct {
Kubernetes string
}
CloudProvider string
type API struct {
AdvertiseAddresses []string
ExternalDNSNames []string
}
const (
DefaultServiceDNSDomain = "cluster.local"
DefaultServicesCIDRString = "10.12.0.0/12"
DefaultKubernetesVersion = "v1.4.0"
)
var (
DefaultServicesCIDR *net.IPNet
ListOfCloudProviders = []string{
"aws",
"azure",
"cloudstack",
"gce",
"mesos",
"openstack",
"ovirt",
"rackspace",
"vsphere",
}
)
func init() {
_, DefaultServicesCIDR, _ = net.ParseCIDR(DefaultServicesCIDRString)
type Networking struct {
ServiceSubnet string
PodSubnet string
DNSDomain string
}
// JoinFlags holds values for "kubeadm join" command flags.
type JoinFlags struct {
MasterAddrs []net.IP
// TODO(phase1+) add manual mode flags here, e.g. RootCACertPath
type Etcd struct {
Endpoints []string
CAFile string
CertFile string
KeyFile string
}
type Secrets struct {
GivenToken string // dot-separated `<TokenID>.<Token>` set by the user
TokenID string // optional on master side, will be generated if not specified
Token []byte // optional on master side, will be generated if not specified
BearerToken string // set based on Token
}
type NodeConfiguration struct {
unversioned.TypeMeta
MasterAddresses []string
Secrets Secrets
}
// ClusterInfo TODO add description
type ClusterInfo struct {
unversioned.TypeMeta
// TODO(phase1+) this may become simply `api.Config`
CertificateAuthorities []string `json:"certificateAuthorities"`
Endpoints []string `json:"endpoints"`

View File

@ -0,0 +1,25 @@
/*
Copyright 2016 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 api
func ValidateMasterConfiguration(o *MasterConfiguration) error {
return nil
}
func ValidateNodeConfiguration(o *MasterConfiguration) error {
return nil
}

View File

@ -22,12 +22,11 @@ import (
"github.com/renstrom/dedent"
"github.com/spf13/cobra"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/api"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/util/flag"
)
func NewKubeadmCommand(f *cmdutil.Factory, in io.Reader, out, err io.Writer, envParams map[string]string) *cobra.Command {
func NewKubeadmCommand(f *cmdutil.Factory, in io.Reader, out, err io.Writer) *cobra.Command {
cmds := &cobra.Command{
Use: "kubeadm",
Short: "kubeadm: easily bootstrap a secure Kubernetes cluster.",
@ -76,14 +75,11 @@ func NewKubeadmCommand(f *cmdutil.Factory, in io.Reader, out, err io.Writer, env
// would then be able to look at files users has given an diff or validate if those are sane, we could also warn
// if any of the files had been deprecated
s := new(kubeadmapi.KubeadmConfig)
s.EnvParams = envParams
cmds.ResetFlags()
cmds.SetGlobalNormalizationFunc(flag.WarnWordSepNormalizeFunc)
cmds.AddCommand(NewCmdInit(out, s))
cmds.AddCommand(NewCmdJoin(out, s))
cmds.AddCommand(NewCmdInit(out))
cmds.AddCommand(NewCmdJoin(out))
cmds.AddCommand(NewCmdVersion(out))
return cmds

View File

@ -19,8 +19,6 @@ package cmd
import (
"fmt"
"io"
"net"
"strings"
"github.com/renstrom/dedent"
"github.com/spf13/cobra"
@ -28,6 +26,7 @@ import (
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/api"
kubemaster "k8s.io/kubernetes/cmd/kubeadm/app/master"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
"k8s.io/kubernetes/pkg/cloudprovider"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
netutil "k8s.io/kubernetes/pkg/util/net"
)
@ -43,66 +42,66 @@ var (
)
// NewCmdInit returns "kubeadm init" command.
func NewCmdInit(out io.Writer, s *kubeadmapi.KubeadmConfig) *cobra.Command {
advertiseAddrs := &[]string{} // TODO(pahse1+) make it work somehow else, custom flag or whatever
func NewCmdInit(out io.Writer) *cobra.Command {
cfg := &kubeadmapi.MasterConfiguration{}
cmd := &cobra.Command{
Use: "init",
Short: "Run this in order to set up the Kubernetes master.",
Run: func(cmd *cobra.Command, args []string) {
err := RunInit(out, cmd, args, s, advertiseAddrs)
err := RunInit(out, cmd, args, cfg)
cmdutil.CheckErr(err)
},
}
cmd.PersistentFlags().StringVar(
&s.Secrets.GivenToken, "token", "",
&cfg.Secrets.GivenToken, "token", "",
"Shared secret used to secure cluster bootstrap; if none is provided, one will be generated for you",
)
cmd.PersistentFlags().StringSliceVar(
advertiseAddrs, "api-advertise-addresses", []string{},
&cfg.API.AdvertiseAddresses, "api-advertise-addresses", []string{},
"The IP addresses to advertise, in case autodetection fails",
)
cmd.PersistentFlags().StringSliceVar(
&s.InitFlags.API.ExternalDNSNames, "api-external-dns-names", []string{},
&cfg.API.ExternalDNSNames, "api-external-dns-names", []string{},
"The DNS names to advertise, in case you have configured them yourself",
)
cmd.PersistentFlags().IPNetVar(
&s.InitFlags.Services.CIDR, "service-cidr", *kubeadmapi.DefaultServicesCIDR,
`Use alterantive range of IP address for service VIPs, defaults to `+
kubeadmapi.DefaultServicesCIDRString,
cmd.PersistentFlags().StringVar(
&cfg.Networking.ServiceSubnet, "service-cidr", kubeadmapi.DefaultServicesSubnet,
"Use alterantive range of IP address for service VIPs",
)
cmd.PersistentFlags().IPNetVar(
&s.InitFlags.PodNetwork.CIDR, "pod-network-cidr", net.IPNet{},
cmd.PersistentFlags().StringVar(
&cfg.Networking.PodSubnet, "pod-network-cidr", "",
"Specify range of IP addresses for the pod network; if set, the control plane will automatically allocate CIDRs for every node",
)
cmd.PersistentFlags().StringVar(
&s.InitFlags.Services.DNSDomain, "service-dns-domain", kubeadmapi.DefaultServiceDNSDomain,
&cfg.Networking.DNSDomain, "service-dns-domain", kubeadmapi.DefaultServiceDNSDomain,
`Use alternative domain for services, e.g. "myorg.internal"`,
)
cmd.PersistentFlags().StringVar(
&s.InitFlags.CloudProvider, "cloud-provider", "",
&cfg.CloudProvider, "cloud-provider", "",
`Enable cloud provider features (external load-balancers, storage, etc), e.g. "gce"`,
)
cmd.PersistentFlags().StringVar(
&s.InitFlags.Versions.Kubernetes, "use-kubernetes-version", kubeadmapi.DefaultKubernetesVersion,
&cfg.KubernetesVersion, "use-kubernetes-version", kubeadmapi.DefaultKubernetesVersion,
`Choose a specific Kubernetes version for the control plane`,
)
// TODO (phase1+) @errordeveloper make the flags below not show up in --help but rather on --advanced-help
cmd.PersistentFlags().StringSliceVar(
&s.InitFlags.API.Etcd.ExternalEndpoints, "external-etcd-endpoints", []string{},
&cfg.Etcd.Endpoints, "external-etcd-endpoints", []string{},
"etcd endpoints to use, in case you have an external cluster",
)
cmd.PersistentFlags().StringVar(
&s.InitFlags.API.Etcd.ExternalCAFile, "external-etcd-cafile", "",
&cfg.Etcd.CAFile, "external-etcd-cafile", "",
"etcd certificate authority certificate file. Note: The path must be in /etc/ssl/certs",
)
cmd.PersistentFlags().StringVar(
&s.InitFlags.API.Etcd.ExternalCertFile, "external-etcd-certfile", "",
&cfg.Etcd.CertFile, "external-etcd-certfile", "",
"etcd client certificate file. Note: The path must be in /etc/ssl/certs",
)
cmd.PersistentFlags().StringVar(
&s.InitFlags.API.Etcd.ExternalKeyFile, "external-etcd-keyfile", "",
&cfg.Etcd.KeyFile, "external-etcd-keyfile", "",
"etcd client key file. Note: The path must be in /etc/ssl/certs",
)
@ -110,57 +109,40 @@ func NewCmdInit(out io.Writer, s *kubeadmapi.KubeadmConfig) *cobra.Command {
}
// RunInit executes master node provisioning, including certificates, needed static pod manifests, etc.
func RunInit(out io.Writer, cmd *cobra.Command, args []string, s *kubeadmapi.KubeadmConfig, advertiseAddrs *[]string) error {
func RunInit(out io.Writer, cmd *cobra.Command, args []string, cfg *kubeadmapi.MasterConfiguration) error {
// Auto-detect the IP
if len(*advertiseAddrs) == 0 {
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
}
s.InitFlags.API.AdvertiseAddrs = []net.IP{ip}
} else {
for _, i := range *advertiseAddrs {
addr := net.ParseIP(i)
if addr == nil {
// TODO(phase1+) custom flag will help to get this error message into a better place
return fmt.Errorf("<cmd/init> failed to parse %q (in %q) as an IP address", i, "--api-advertise-addresses="+strings.Join(*advertiseAddrs, ","))
}
s.InitFlags.API.AdvertiseAddrs = append(s.InitFlags.API.AdvertiseAddrs, addr)
}
cfg.API.AdvertiseAddresses = []string{ip.String()}
}
// TODO(phase1+) create a custom flag
if s.InitFlags.CloudProvider != "" {
found := false
for _, provider := range kubeadmapi.ListOfCloudProviders {
if provider == s.InitFlags.CloudProvider {
found = true
break
}
}
if found {
fmt.Printf("<cmd/init> cloud provider %q initialized for the control plane. Remember to set the same cloud provider flag on the kubelet.\n", s.InitFlags.CloudProvider)
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", s.InitFlags.CloudProvider, kubeadmapi.ListOfCloudProviders)
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(s); err != nil {
if err := kubemaster.CreateTokenAuthFile(&cfg.Secrets); err != nil {
return err
}
if err := kubemaster.WriteStaticPodManifests(s); err != nil {
if err := kubemaster.WriteStaticPodManifests(cfg); err != nil {
return err
}
caKey, caCert, err := kubemaster.CreatePKIAssets(s)
caKey, caCert, err := kubemaster.CreatePKIAssets(cfg)
if err != nil {
return err
}
kubeconfigs, err := kubemaster.CreateCertsAndConfigForClients(s, []string{"kubelet", "admin"}, caKey, caCert)
kubeconfigs, err := kubemaster.CreateCertsAndConfigForClients(cfg.API.AdvertiseAddresses, []string{"kubelet", "admin"}, caKey, caCert)
if err != nil {
return err
}
@ -175,7 +157,7 @@ func RunInit(out io.Writer, cmd *cobra.Command, args []string, s *kubeadmapi.Kub
// 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(s, name, kubeconfig); err != nil {
if err := kubeadmutil.WriteKubeconfigIfNotExists(name, kubeconfig); err != nil {
return err
}
}
@ -190,18 +172,18 @@ func RunInit(out io.Writer, cmd *cobra.Command, args []string, s *kubeadmapi.Kub
return err
}
if err := kubemaster.CreateDiscoveryDeploymentAndSecret(s, client, caCert); err != nil {
if err := kubemaster.CreateDiscoveryDeploymentAndSecret(cfg, client, caCert); err != nil {
return err
}
if err := kubemaster.CreateEssentialAddons(s, client); err != nil {
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,
s.Secrets.GivenToken,
s.InitFlags.API.AdvertiseAddrs[0].String(),
cfg.Secrets.GivenToken,
cfg.API.AdvertiseAddresses[0],
)
return nil

View File

@ -19,7 +19,6 @@ package cmd
import (
"fmt"
"io"
"net"
"github.com/renstrom/dedent"
"github.com/spf13/cobra"
@ -42,18 +41,19 @@ var (
)
// NewCmdJoin returns "kubeadm join" command.
func NewCmdJoin(out io.Writer, s *kubeadmapi.KubeadmConfig) *cobra.Command {
func NewCmdJoin(out io.Writer) *cobra.Command {
cfg := &kubeadmapi.NodeConfiguration{}
cmd := &cobra.Command{
Use: "join",
Short: "Run this on any machine you wish to join an existing cluster.",
Run: func(cmd *cobra.Command, args []string) {
err := RunJoin(out, cmd, args, s)
err := RunJoin(out, cmd, args, cfg)
cmdutil.CheckErr(err)
},
}
cmd.PersistentFlags().StringVar(
&s.Secrets.GivenToken, "token", "",
&cfg.Secrets.GivenToken, "token", "",
"(required) Shared secret used to secure bootstrap. Must match the output of 'kubeadm init'",
)
@ -61,20 +61,14 @@ func NewCmdJoin(out io.Writer, s *kubeadmapi.KubeadmConfig) *cobra.Command {
}
// 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 {
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)")
}
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)
}
s.MasterAddresses = append(s.MasterAddresses, args...)
ok, err := kubeadmutil.UseGivenTokenIfValid(s)
ok, err := kubeadmutil.UseGivenTokenIfValid(&s.Secrets)
if !ok {
if err != nil {
return fmt.Errorf("<cmd/join> %v (see --help)\n", err)
@ -87,7 +81,7 @@ func RunJoin(out io.Writer, cmd *cobra.Command, args []string, s *kubeadmapi.Kub
return err
}
err = kubeadmutil.WriteKubeconfigIfNotExists(s, "kubelet", kubeconfig)
err = kubeadmutil.WriteKubeconfigIfNotExists("kubelet", kubeconfig)
if err != nil {
return err
}

View File

@ -43,17 +43,17 @@ const (
exechealthzVersion = "1.1"
)
func GetCoreImage(image string, cfg *kubeadmapi.KubeadmConfig, overrideImage string) string {
func GetCoreImage(image string, cfg *kubeadmapi.MasterConfiguration, overrideImage string) string {
if overrideImage != "" {
return overrideImage
}
return map[string]string{
KubeEtcdImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "etcd", runtime.GOARCH, etcdVersion),
KubeAPIServerImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-apiserver", runtime.GOARCH, cfg.Versions.Kubernetes),
KubeControllerManagerImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-controller-manager", runtime.GOARCH, cfg.Versions.Kubernetes),
KubeSchedulerImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-scheduler", runtime.GOARCH, cfg.Versions.Kubernetes),
KubeProxyImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-proxy", runtime.GOARCH, cfg.Versions.Kubernetes),
KubeAPIServerImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-apiserver", runtime.GOARCH, cfg.KubernetesVersion),
KubeControllerManagerImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-controller-manager", runtime.GOARCH, cfg.KubernetesVersion),
KubeSchedulerImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-scheduler", runtime.GOARCH, cfg.KubernetesVersion),
KubeProxyImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-proxy", runtime.GOARCH, cfg.KubernetesVersion),
}[image]
}

View File

@ -17,10 +17,7 @@ limitations under the License.
package app
import (
"fmt"
"os"
"runtime"
"strings"
"github.com/renstrom/dedent"
"github.com/spf13/pflag"
@ -36,31 +33,6 @@ var AlphaWarningOnExit = dedent.Dedent(`
kubeadm: and make sure to mention @kubernetes/sig-cluster-lifecycle. Thank you!
`)
// TODO(phase2) use componentconfig
// we need some params for testing etc, let's keep these hidden for now
func getEnvParams() map[string]string {
envParams := map[string]string{
// TODO(phase1+): Mode prefix and host_pki_path to another place as constants, and use them everywhere
// Right now they're used here and there, but not consequently
"kubernetes_dir": "/etc/kubernetes",
"host_pki_path": "/etc/kubernetes/pki",
"host_etcd_path": "/var/lib/etcd",
"hyperkube_image": "",
"discovery_image": fmt.Sprintf("gcr.io/google_containers/kube-discovery-%s:%s", runtime.GOARCH, "1.0"),
"etcd_image": "",
"component_loglevel": "--v=4",
}
for k := range envParams {
if v := os.Getenv(fmt.Sprintf("KUBE_%s", strings.ToUpper(k))); v != "" {
envParams[k] = v
}
}
return envParams
}
func Run() error {
logs.InitLogs()
defer logs.FlushLogs()
@ -69,6 +41,6 @@ func Run() error {
pflag.CommandLine.MarkHidden("google-json-key")
pflag.CommandLine.MarkHidden("log-flush-frequency")
cmd := cmd.NewKubeadmCommand(cmdutil.NewFactory(nil), os.Stdin, os.Stdout, os.Stderr, getEnvParams())
cmd := cmd.NewKubeadmCommand(cmdutil.NewFactory(nil), os.Stdin, os.Stdout, os.Stderr)
return cmd.Execute()
}

View File

@ -18,6 +18,7 @@ package master
import (
"fmt"
"net"
"path"
"runtime"
@ -31,7 +32,8 @@ import (
)
// TODO(phase1+): kube-proxy should be a daemonset, three different daemonsets should not be here
func createKubeProxyPodSpec(s *kubeadmapi.KubeadmConfig, architecture string) api.PodSpec {
func createKubeProxyPodSpec(s *kubeadmapi.MasterConfiguration, architecture string) api.PodSpec {
envParams := kubeadmapi.GetEnvParams()
privilegedTrue := true
return api.PodSpec{
SecurityContext: &api.PodSecurityContext{HostNetwork: true},
@ -40,7 +42,7 @@ func createKubeProxyPodSpec(s *kubeadmapi.KubeadmConfig, architecture string) ap
},
Containers: []api.Container{{
Name: kubeProxy,
Image: images.GetCoreImage(images.KubeProxyImage, s, s.EnvParams["hyperkube_image"]),
Image: images.GetCoreImage(images.KubeProxyImage, s, envParams["hyperkube_image"]),
Command: append(getComponentCommand("proxy", s), "--kubeconfig=/run/kubeconfig"),
SecurityContext: &api.SecurityContext{Privileged: &privilegedTrue},
VolumeMounts: []api.VolumeMount{
@ -70,7 +72,7 @@ func createKubeProxyPodSpec(s *kubeadmapi.KubeadmConfig, architecture string) ap
{
Name: "kubeconfig",
VolumeSource: api.VolumeSource{
HostPath: &api.HostPathVolumeSource{Path: path.Join(s.EnvParams["kubernetes_dir"], "kubelet.conf")},
HostPath: &api.HostPathVolumeSource{Path: path.Join(envParams["kubernetes_dir"], "kubelet.conf")},
},
},
{
@ -83,7 +85,7 @@ func createKubeProxyPodSpec(s *kubeadmapi.KubeadmConfig, architecture string) ap
}
}
func createKubeDNSPodSpec(s *kubeadmapi.KubeadmConfig) api.PodSpec {
func createKubeDNSPodSpec(s *kubeadmapi.MasterConfiguration) api.PodSpec {
dnsPodResources := api.ResourceList{
api.ResourceName(api.ResourceCPU): resource.MustParse("100m"),
@ -98,7 +100,7 @@ func createKubeDNSPodSpec(s *kubeadmapi.KubeadmConfig) api.PodSpec {
kubeDNSPort := int32(10053)
dnsmasqPort := int32(53)
nslookup := fmt.Sprintf("nslookup kubernetes.default.svc.%s 127.0.0.1", s.InitFlags.Services.DNSDomain)
nslookup := fmt.Sprintf("nslookup kubernetes.default.svc.%s 127.0.0.1", s.Networking.DNSDomain)
nslookup = fmt.Sprintf("-cmd=%s:%d >/dev/null && %s:%d >/dev/null",
nslookup, dnsmasqPort,
@ -119,7 +121,7 @@ func createKubeDNSPodSpec(s *kubeadmapi.KubeadmConfig) api.PodSpec {
Requests: dnsPodResources,
},
Args: []string{
fmt.Sprintf("--domain=%s", s.InitFlags.Services.DNSDomain),
fmt.Sprintf("--domain=%s", s.Networking.DNSDomain),
fmt.Sprintf("--dns-port=%d", kubeDNSPort),
// TODO __PILLAR__FEDERATIONS__DOMAIN__MAP__
},
@ -212,10 +214,14 @@ func createKubeDNSPodSpec(s *kubeadmapi.KubeadmConfig) api.PodSpec {
}
func createKubeDNSServiceSpec(s *kubeadmapi.KubeadmConfig) (*api.ServiceSpec, error) {
ip, err := ipallocator.GetIndexedIP(&s.InitFlags.Services.CIDR, 10)
func createKubeDNSServiceSpec(s *kubeadmapi.MasterConfiguration) (*api.ServiceSpec, error) {
_, n, err := net.ParseCIDR(s.Networking.ServiceSubnet)
if err != nil {
return nil, fmt.Errorf("unable to allocate IP address for kube-dns addon from the given CIDR (%q) [%v]", s.InitFlags.Services.CIDR, err)
return nil, fmt.Errorf("could not parse %q: %v", s.Networking.ServiceSubnet, err)
}
ip, err := ipallocator.GetIndexedIP(n, 10)
if err != nil {
return nil, fmt.Errorf("unable to allocate IP address for kube-dns addon from the given CIDR (%q) [%v]", s.Networking.ServiceSubnet, err)
}
svc := &api.ServiceSpec{
@ -230,7 +236,7 @@ func createKubeDNSServiceSpec(s *kubeadmapi.KubeadmConfig) (*api.ServiceSpec, er
return svc, nil
}
func CreateEssentialAddons(s *kubeadmapi.KubeadmConfig, client *clientset.Clientset) error {
func CreateEssentialAddons(s *kubeadmapi.MasterConfiguration, client *clientset.Clientset) error {
arches := [3]string{"amd64", "arm", "arm64"}
for _, arch := range arches {

View File

@ -40,15 +40,15 @@ const (
kubeDiscoverySecretName = "clusterinfo"
)
func encodeKubeDiscoverySecretData(s *kubeadmapi.KubeadmConfig, caCert *x509.Certificate) map[string][]byte {
func encodeKubeDiscoverySecretData(s *kubeadmapi.MasterConfiguration, caCert *x509.Certificate) map[string][]byte {
var (
data = map[string][]byte{}
endpointList = []string{}
tokenMap = map[string]string{}
)
for _, addr := range s.InitFlags.API.AdvertiseAddrs {
endpointList = append(endpointList, fmt.Sprintf("https://%s:443", addr.String()))
for _, addr := range s.API.AdvertiseAddresses {
endpointList = append(endpointList, fmt.Sprintf("https://%s:443", addr))
}
tokenMap[s.Secrets.TokenID] = s.Secrets.BearerToken
@ -60,7 +60,8 @@ func encodeKubeDiscoverySecretData(s *kubeadmapi.KubeadmConfig, caCert *x509.Cer
return data
}
func newKubeDiscoveryPodSpec(s *kubeadmapi.KubeadmConfig) api.PodSpec {
func newKubeDiscoveryPodSpec() api.PodSpec {
envParams := kubeadmapi.GetEnvParams()
return api.PodSpec{
// We have to use host network namespace, as `HostPort`/`HostIP` are Docker's
// buisness and CNI support isn't quite there yet (except for kubenet)
@ -69,7 +70,7 @@ func newKubeDiscoveryPodSpec(s *kubeadmapi.KubeadmConfig) api.PodSpec {
SecurityContext: &api.PodSecurityContext{HostNetwork: true},
Containers: []api.Container{{
Name: kubeDiscoveryName,
Image: s.EnvParams["discovery_image"],
Image: envParams["discovery_image"],
Command: []string{"/usr/local/bin/kube-discovery"},
VolumeMounts: []api.VolumeMount{{
Name: kubeDiscoverySecretName,
@ -100,9 +101,9 @@ func newKubeDiscoveryPodSpec(s *kubeadmapi.KubeadmConfig) api.PodSpec {
}
}
func newKubeDiscovery(s *kubeadmapi.KubeadmConfig, caCert *x509.Certificate) kubeDiscovery {
func newKubeDiscovery(s *kubeadmapi.MasterConfiguration, caCert *x509.Certificate) kubeDiscovery {
kd := kubeDiscovery{
Deployment: NewDeployment(kubeDiscoveryName, 1, newKubeDiscoveryPodSpec(s)),
Deployment: NewDeployment(kubeDiscoveryName, 1, newKubeDiscoveryPodSpec()),
Secret: &api.Secret{
ObjectMeta: api.ObjectMeta{Name: kubeDiscoverySecretName},
Type: api.SecretTypeOpaque,
@ -116,7 +117,7 @@ func newKubeDiscovery(s *kubeadmapi.KubeadmConfig, caCert *x509.Certificate) kub
return kd
}
func CreateDiscoveryDeploymentAndSecret(s *kubeadmapi.KubeadmConfig, client *clientset.Clientset, caCert *x509.Certificate) error {
func CreateDiscoveryDeploymentAndSecret(s *kubeadmapi.MasterConfiguration, client *clientset.Clientset, caCert *x509.Certificate) error {
kd := newKubeDiscovery(s, caCert)
if _, err := client.Extensions().Deployments(api.NamespaceSystem).Create(kd.Deployment); err != nil {

View File

@ -22,20 +22,19 @@ import (
"fmt"
// TODO: "k8s.io/client-go/client/tools/clientcmd/api"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/api"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
certutil "k8s.io/kubernetes/pkg/util/cert"
)
func CreateCertsAndConfigForClients(s *kubeadmapi.KubeadmConfig, clientNames []string, caKey *rsa.PrivateKey, caCert *x509.Certificate) (map[string]*clientcmdapi.Config, error) {
func CreateCertsAndConfigForClients(advertiseAddresses, clientNames []string, caKey *rsa.PrivateKey, caCert *x509.Certificate) (map[string]*clientcmdapi.Config, error) {
basicClientConfig := kubeadmutil.CreateBasicClientConfig(
"kubernetes",
// 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
fmt.Sprintf("https://%s:443", s.InitFlags.API.AdvertiseAddrs[0]),
fmt.Sprintf("https://%s:443", advertiseAddresses[0]),
certutil.EncodeCertPEM(caCert),
)

View File

@ -53,12 +53,13 @@ const (
// WriteStaticPodManifests builds manifest objects based on user provided configuration and then dumps it to disk
// where kubelet will pick and schedule them.
func WriteStaticPodManifests(s *kubeadmapi.KubeadmConfig) error {
func WriteStaticPodManifests(s *kubeadmapi.MasterConfiguration) error {
envParams := kubeadmapi.GetEnvParams()
// Prepare static pod specs
staticPodSpecs := map[string]api.Pod{
kubeAPIServer: componentPod(api.Container{
Name: kubeAPIServer,
Image: images.GetCoreImage(images.KubeAPIServerImage, s, s.EnvParams["hyperkube_image"]),
Image: images.GetCoreImage(images.KubeAPIServerImage, s, envParams["hyperkube_image"]),
Command: getComponentCommand(apiServer, s),
VolumeMounts: []api.VolumeMount{certsVolumeMount(), k8sVolumeMount()},
LivenessProbe: componentProbe(8080, "/healthz"),
@ -66,7 +67,7 @@ func WriteStaticPodManifests(s *kubeadmapi.KubeadmConfig) error {
}, certsVolume(s), k8sVolume(s)),
kubeControllerManager: componentPod(api.Container{
Name: kubeControllerManager,
Image: images.GetCoreImage(images.KubeControllerManagerImage, s, s.EnvParams["hyperkube_image"]),
Image: images.GetCoreImage(images.KubeControllerManagerImage, s, envParams["hyperkube_image"]),
Command: getComponentCommand(controllerManager, s),
VolumeMounts: []api.VolumeMount{certsVolumeMount(), k8sVolumeMount()},
LivenessProbe: componentProbe(10252, "/healthz"),
@ -74,7 +75,7 @@ func WriteStaticPodManifests(s *kubeadmapi.KubeadmConfig) error {
}, certsVolume(s), k8sVolume(s)),
kubeScheduler: componentPod(api.Container{
Name: kubeScheduler,
Image: images.GetCoreImage(images.KubeSchedulerImage, s, s.EnvParams["hyperkube_image"]),
Image: images.GetCoreImage(images.KubeSchedulerImage, s, envParams["hyperkube_image"]),
Command: getComponentCommand(scheduler, s),
LivenessProbe: componentProbe(10251, "/healthz"),
Resources: componentResources("100m"),
@ -82,7 +83,7 @@ func WriteStaticPodManifests(s *kubeadmapi.KubeadmConfig) error {
}
// Add etcd static pod spec only if external etcd is not configured
if len(s.InitFlags.API.Etcd.ExternalEndpoints) == 0 {
if len(s.Etcd.Endpoints) == 0 {
staticPodSpecs[etcd] = componentPod(api.Container{
Name: etcd,
Command: []string{
@ -92,7 +93,7 @@ func WriteStaticPodManifests(s *kubeadmapi.KubeadmConfig) error {
"--data-dir=/var/etcd/data",
},
VolumeMounts: []api.VolumeMount{certsVolumeMount(), etcdVolumeMount(), k8sVolumeMount()},
Image: images.GetCoreImage(images.KubeEtcdImage, s, s.EnvParams["etcd_image"]),
Image: images.GetCoreImage(images.KubeEtcdImage, s, envParams["etcd_image"]),
LivenessProbe: componentProbe(2379, "/health"),
Resources: componentResources("200m"),
SecurityContext: &api.SecurityContext{
@ -107,7 +108,7 @@ func WriteStaticPodManifests(s *kubeadmapi.KubeadmConfig) error {
}, certsVolume(s), etcdVolume(s), k8sVolume(s))
}
manifestsPath := path.Join(s.EnvParams["kubernetes_dir"], "manifests")
manifestsPath := path.Join(envParams["kubernetes_dir"], "manifests")
if err := os.MkdirAll(manifestsPath, 0700); err != nil {
return fmt.Errorf("<master/manifests> failed to create directory %q [%v]", manifestsPath, err)
}
@ -125,11 +126,12 @@ func WriteStaticPodManifests(s *kubeadmapi.KubeadmConfig) error {
}
// etcdVolume exposes a path on the host in order to guarantee data survival during reboot.
func etcdVolume(s *kubeadmapi.KubeadmConfig) api.Volume {
func etcdVolume(s *kubeadmapi.MasterConfiguration) api.Volume {
envParams := kubeadmapi.GetEnvParams()
return api.Volume{
Name: "etcd",
VolumeSource: api.VolumeSource{
HostPath: &api.HostPathVolumeSource{Path: s.EnvParams["host_etcd_path"]},
HostPath: &api.HostPathVolumeSource{Path: envParams["host_etcd_path"]},
},
}
}
@ -142,7 +144,7 @@ func etcdVolumeMount() api.VolumeMount {
}
// certsVolume exposes host SSL certificates to pod containers.
func certsVolume(s *kubeadmapi.KubeadmConfig) api.Volume {
func certsVolume(s *kubeadmapi.MasterConfiguration) api.Volume {
return api.Volume{
Name: "certs",
VolumeSource: api.VolumeSource{
@ -159,11 +161,12 @@ func certsVolumeMount() api.VolumeMount {
}
}
func k8sVolume(s *kubeadmapi.KubeadmConfig) api.Volume {
func k8sVolume(s *kubeadmapi.MasterConfiguration) api.Volume {
envParams := kubeadmapi.GetEnvParams()
return api.Volume{
Name: "pki",
VolumeSource: api.VolumeSource{
HostPath: &api.HostPathVolumeSource{Path: s.EnvParams["kubernetes_dir"]},
HostPath: &api.HostPathVolumeSource{Path: envParams["kubernetes_dir"]},
},
}
}
@ -218,13 +221,13 @@ func componentPod(container api.Container, volumes ...api.Volume) api.Pod {
}
}
func getComponentCommand(component string, s *kubeadmapi.KubeadmConfig) (command []string) {
func getComponentCommand(component string, s *kubeadmapi.MasterConfiguration) (command []string) {
baseFlags := map[string][]string{
apiServer: {
"--insecure-bind-address=127.0.0.1",
"--etcd-servers=http://127.0.0.1:2379",
"--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota",
"--service-cluster-ip-range=" + s.InitFlags.Services.CIDR.String(),
"--service-cluster-ip-range=" + s.Networking.ServiceSubnet,
"--service-account-key-file=" + pkiDir + "/apiserver-key.pem",
"--client-ca-file=" + pkiDir + "/ca.pem",
"--tls-cert-file=" + pkiDir + "/apiserver.pem",
@ -252,37 +255,38 @@ func getComponentCommand(component string, s *kubeadmapi.KubeadmConfig) (command
proxy: {},
}
if s.EnvParams["hyperkube_image"] != "" {
envParams := kubeadmapi.GetEnvParams()
if envParams["hyperkube_image"] != "" {
command = []string{"/hyperkube", component}
} else {
command = []string{"/usr/local/bin/kube-" + component}
}
command = append(command, s.EnvParams["component_loglevel"])
command = append(command, envParams["component_loglevel"])
command = append(command, baseFlags[component]...)
if component == apiServer {
// Check if the user decided to use an external etcd cluster
if len(s.InitFlags.API.Etcd.ExternalEndpoints) > 0 {
command = append(command, fmt.Sprintf("--etcd-servers=%s", strings.Join(s.InitFlags.API.Etcd.ExternalEndpoints, ",")))
if len(s.Etcd.Endpoints) > 0 {
command = append(command, fmt.Sprintf("--etcd-servers=%s", strings.Join(s.Etcd.Endpoints, ",")))
} else {
command = append(command, "--etcd-servers=http://127.0.0.1:2379")
}
// Is etcd secured?
if s.InitFlags.API.Etcd.ExternalCAFile != "" {
command = append(command, fmt.Sprintf("--etcd-cafile=%s", s.InitFlags.API.Etcd.ExternalCAFile))
if s.Etcd.CAFile != "" {
command = append(command, fmt.Sprintf("--etcd-cafile=%s", s.Etcd.CAFile))
}
if s.InitFlags.API.Etcd.ExternalCertFile != "" && s.InitFlags.API.Etcd.ExternalKeyFile != "" {
etcdClientFileArg := fmt.Sprintf("--etcd-certfile=%s", s.InitFlags.API.Etcd.ExternalCertFile)
etcdKeyFileArg := fmt.Sprintf("--etcd-keyfile=%s", s.InitFlags.API.Etcd.ExternalKeyFile)
if s.Etcd.CertFile != "" && s.Etcd.KeyFile != "" {
etcdClientFileArg := fmt.Sprintf("--etcd-certfile=%s", s.Etcd.CertFile)
etcdKeyFileArg := fmt.Sprintf("--etcd-keyfile=%s", s.Etcd.KeyFile)
command = append(command, etcdClientFileArg, etcdKeyFileArg)
}
}
if component == controllerManager {
if s.InitFlags.CloudProvider != "" {
command = append(command, "--cloud-provider="+s.InitFlags.CloudProvider)
if s.CloudProvider != "" {
command = append(command, "--cloud-provider="+s.CloudProvider)
// Only append the --cloud-config option if there's a such file
// TODO(phase1+) this won't work unless it's in one of the few directories we bind-mount
@ -290,12 +294,9 @@ func getComponentCommand(component string, s *kubeadmapi.KubeadmConfig) (command
command = append(command, "--cloud-config="+DefaultCloudConfigPath)
}
}
if s.InitFlags.PodNetwork.CIDR.IP != nil {
// Let the controller-manager allocate Node CIDRs for the Pod network.
// Each node will get a subspace of the address CIDR provided with --pod-network-cidr.
command = append(command, "--allocate-node-cidrs=true", "--cluster-cidr="+s.InitFlags.PodNetwork.CIDR.String())
}
// Let the controller-manager allocate Node CIDRs for the Pod network.
// Each node will get a subspace of the address CIDR provided with --pod-network-cidr.
command = append(command, "--allocate-node-cidrs=true", "--cluster-cidr="+s.Networking.PodSubnet)
}
return

View File

@ -20,6 +20,7 @@ import (
"crypto/rsa"
"crypto/x509"
"fmt"
"net"
"path"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/api"
@ -45,7 +46,7 @@ func newCertificateAuthority() (*rsa.PrivateKey, *x509.Certificate, error) {
return key, cert, nil
}
func newServerKeyAndCert(s *kubeadmapi.KubeadmConfig, caCert *x509.Certificate, caKey *rsa.PrivateKey, altNames certutil.AltNames) (*rsa.PrivateKey, *x509.Certificate, error) {
func newServerKeyAndCert(s *kubeadmapi.MasterConfiguration, caCert *x509.Certificate, caKey *rsa.PrivateKey, altNames certutil.AltNames) (*rsa.PrivateKey, *x509.Certificate, error) {
key, err := certutil.NewPrivateKey()
if err != nil {
return nil, nil, fmt.Errorf("unabel to create private key [%v]", err)
@ -55,12 +56,16 @@ func newServerKeyAndCert(s *kubeadmapi.KubeadmConfig, caCert *x509.Certificate,
"kubernetes",
"kubernetes.default",
"kubernetes.default.svc",
fmt.Sprintf("kubernetes.default.svc.%s", s.InitFlags.Services.DNSDomain),
fmt.Sprintf("kubernetes.default.svc.%s", s.Networking.DNSDomain),
}
internalAPIServerVirtualIP, err := ipallocator.GetIndexedIP(&s.InitFlags.Services.CIDR, 1)
_, n, err := net.ParseCIDR(s.Networking.ServiceSubnet)
if err != nil {
return nil, nil, fmt.Errorf("unable to allocate IP address for the API server from the given CIDR (%q) [%v]", &s.InitFlags.Services.CIDR, err)
return nil, nil, fmt.Errorf("error parsing CIDR %q: %v", s.Networking.ServiceSubnet, err)
}
internalAPIServerVirtualIP, err := ipallocator.GetIndexedIP(n, 1)
if err != nil {
return nil, nil, fmt.Errorf("unable to allocate IP address for the API server from the given CIDR (%q) [%v]", &s.Networking.ServiceSubnet, err)
}
altNames.IPs = append(altNames.IPs, internalAPIServerVirtualIP)
@ -138,16 +143,22 @@ func newServiceAccountKey() (*rsa.PrivateKey, error) {
// It first generates a self-signed CA certificate, a server certificate (signed by the CA) and a key for
// signing service account tokens. It returns CA key and certificate, which is convenient for use with
// client config funcs.
func CreatePKIAssets(s *kubeadmapi.KubeadmConfig) (*rsa.PrivateKey, *x509.Certificate, error) {
func CreatePKIAssets(s *kubeadmapi.MasterConfiguration) (*rsa.PrivateKey, *x509.Certificate, error) {
var (
err error
altNames certutil.AltNames
)
altNames.IPs = append(altNames.IPs, s.InitFlags.API.AdvertiseAddrs...)
altNames.DNSNames = append(altNames.DNSNames, s.InitFlags.API.ExternalDNSNames...)
for _, a := range s.API.AdvertiseAddresses {
if ip := net.ParseIP(a); ip != nil {
altNames.IPs = append(altNames.IPs, ip)
} else {
return nil, nil, fmt.Errorf("could not parse ip %q", a)
}
}
altNames.DNSNames = append(altNames.DNSNames, s.API.ExternalDNSNames...)
pkiPath := path.Join(s.EnvParams["host_pki_path"])
pkiPath := path.Join(kubeadmapi.GetEnvParams()["host_pki_path"])
caKey, caCert, err := newCertificateAuthority()
if err != nil {

View File

@ -28,7 +28,7 @@ import (
"k8s.io/kubernetes/pkg/util/uuid"
)
func generateTokenIfNeeded(s *kubeadmapi.KubeadmConfig) error {
func generateTokenIfNeeded(s *kubeadmapi.Secrets) error {
ok, err := kubeadmutil.UseGivenTokenIfValid(s)
// TODO(phase1+) @krousey: I know it won't happen with the way it is currently implemented, but this doesn't handle case where ok is true and err is non-nil.
if !ok {
@ -39,7 +39,7 @@ func generateTokenIfNeeded(s *kubeadmapi.KubeadmConfig) error {
if err != nil {
return err
}
fmt.Printf("<master/tokens> generated token: %q\n", s.Secrets.GivenToken)
fmt.Printf("<master/tokens> generated token: %q\n", s.GivenToken)
} else {
fmt.Println("<master/tokens> accepted provided token")
}
@ -47,15 +47,15 @@ func generateTokenIfNeeded(s *kubeadmapi.KubeadmConfig) error {
return nil
}
func CreateTokenAuthFile(s *kubeadmapi.KubeadmConfig) error {
tokenAuthFilePath := path.Join(s.EnvParams["host_pki_path"], "tokens.csv")
func CreateTokenAuthFile(s *kubeadmapi.Secrets) error {
tokenAuthFilePath := path.Join(kubeadmapi.GetEnvParams()["host_pki_path"], "tokens.csv")
if err := generateTokenIfNeeded(s); err != nil {
return fmt.Errorf("<master/tokens> failed to generate token(s) [%v]", err)
}
if err := os.MkdirAll(s.EnvParams["host_pki_path"], 0700); err != nil {
return fmt.Errorf("<master/tokens> failed to create directory %q [%v]", s.EnvParams["host_pki_path"], err)
if err := os.MkdirAll(kubeadmapi.GetEnvParams()["host_pki_path"], 0700); err != nil {
return fmt.Errorf("<master/tokens> failed to create directory %q [%v]", kubeadmapi.GetEnvParams()["host_pki_path"], err)
}
serialized := []byte(fmt.Sprintf("%s,kubeadm-node-csr,%s,system:kubelet-bootstrap\n", s.Secrets.BearerToken, uuid.NewUUID()))
serialized := []byte(fmt.Sprintf("%s,kubeadm-node-csr,%s,system:kubelet-bootstrap\n", s.BearerToken, uuid.NewUUID()))
// DumpReaderToFile create a file with mode 0600
if err := cmdutil.DumpReaderToFile(bytes.NewReader(serialized), tokenAuthFilePath); err != nil {
return fmt.Errorf("<master/tokens> failed to save token auth file (%q) [%v]", tokenAuthFilePath, err)

View File

@ -34,8 +34,8 @@ import (
)
// PerformTLSBootstrap creates a RESTful client in order to execute certificate signing request.
func PerformTLSBootstrap(s *kubeadmapi.KubeadmConfig, apiEndpoint string, caCert []byte) (*clientcmdapi.Config, error) {
// TODO(phase2) try all the api servers until we find one that works
func PerformTLSBootstrap(s *kubeadmapi.NodeConfiguration, apiEndpoint string, caCert []byte) (*clientcmdapi.Config, error) {
// TODO(phase1+) try all the api servers until we find one that works
bareClientConfig := kubeadmutil.CreateBasicClientConfig("kubernetes", apiEndpoint, caCert)
hostName, err := os.Hostname()

View File

@ -28,8 +28,8 @@ import (
clientcmdapi "k8s.io/kubernetes/pkg/client/unversioned/clientcmd/api"
)
func RetrieveTrustedClusterInfo(s *kubeadmapi.KubeadmConfig) (*clientcmdapi.Config, error) {
host, port := s.JoinFlags.MasterAddrs[0].String(), 9898
func RetrieveTrustedClusterInfo(s *kubeadmapi.NodeConfiguration) (*clientcmdapi.Config, error) {
host, port := s.MasterAddresses[0], 9898
requestURL := fmt.Sprintf("http://%s:%d/cluster-info/v1/?token-id=%s", host, port, s.Secrets.TokenID)
req, err := http.NewRequest("GET", requestURL, nil)
if err != nil {

View File

@ -75,12 +75,13 @@ func MakeClientConfigWithToken(config *clientcmdapi.Config, clusterName string,
return newConfig
}
func WriteKubeconfigIfNotExists(s *kubeadmapi.KubeadmConfig, name string, kubeconfig *clientcmdapi.Config) error {
if err := os.MkdirAll(s.EnvParams["kubernetes_dir"], 0700); err != nil {
return fmt.Errorf("<util/kubeconfig> failed to create directory %q [%v]", s.EnvParams["kubernetes_dir"], err)
func WriteKubeconfigIfNotExists(name string, kubeconfig *clientcmdapi.Config) error {
envParams := kubeadmapi.GetEnvParams()
if err := os.MkdirAll(envParams["kubernetes_dir"], 0700); err != nil {
return fmt.Errorf("<util/kubeconfig> failed to create directory %q [%v]", envParams["kubernetes_dir"], err)
}
filename := path.Join(s.EnvParams["kubernetes_dir"], fmt.Sprintf("%s.conf", name))
filename := path.Join(envParams["kubernetes_dir"], fmt.Sprintf("%s.conf", name))
// Create and open the file, only if it does not already exist.
f, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_EXCL, 0600)
if err != nil {

View File

@ -42,7 +42,7 @@ func RandBytes(length int) ([]byte, string, error) {
return b, hex.EncodeToString(b), nil
}
func GenerateToken(s *kubeadmapi.KubeadmConfig) error {
func GenerateToken(s *kubeadmapi.Secrets) error {
_, tokenID, err := RandBytes(TokenIDLen / 2)
if err != nil {
return err
@ -53,19 +53,19 @@ func GenerateToken(s *kubeadmapi.KubeadmConfig) error {
return err
}
s.Secrets.TokenID = tokenID
s.Secrets.BearerToken = token
s.Secrets.Token = tokenBytes
s.Secrets.GivenToken = fmt.Sprintf("%s.%s", tokenID, token)
s.TokenID = tokenID
s.BearerToken = token
s.Token = tokenBytes
s.GivenToken = fmt.Sprintf("%s.%s", tokenID, token)
return nil
}
func UseGivenTokenIfValid(s *kubeadmapi.KubeadmConfig) (bool, error) {
if s.Secrets.GivenToken == "" {
func UseGivenTokenIfValid(s *kubeadmapi.Secrets) (bool, error) {
if s.GivenToken == "" {
return false, nil // not given
}
fmt.Println("<util/tokens> validating provided token")
givenToken := strings.Split(strings.ToLower(s.Secrets.GivenToken), ".")
givenToken := strings.Split(strings.ToLower(s.GivenToken), ".")
// TODO(phase1+) print desired format
// TODO(phase1+) could also print more specific messages in each case
invalidErr := "<util/tokens> provided token is invalid - %s"
@ -78,8 +78,8 @@ func UseGivenTokenIfValid(s *kubeadmapi.KubeadmConfig) (bool, error) {
len(givenToken[0]), TokenIDLen))
}
tokenBytes := []byte(givenToken[1])
s.Secrets.TokenID = givenToken[0]
s.Secrets.BearerToken = givenToken[1]
s.Secrets.Token = tokenBytes
s.TokenID = givenToken[0]
s.BearerToken = givenToken[1]
s.Token = tokenBytes
return true, nil // given and valid
}

View File

@ -32,8 +32,10 @@ import (
type Factory func(config io.Reader) (Interface, error)
// All registered cloud providers.
var providersMutex sync.Mutex
var providers = make(map[string]Factory)
var (
providersMutex sync.Mutex
providers = make(map[string]Factory)
)
// RegisterCloudProvider registers a cloudprovider.Factory by name. This
// is expected to happen during app startup.
@ -47,6 +49,27 @@ func RegisterCloudProvider(name string, cloud Factory) {
providers[name] = cloud
}
// IsCloudProvider returns true if name corresponds to an already registered
// cloud provider.
func IsCloudProvider(name string) bool {
providersMutex.Lock()
defer providersMutex.Unlock()
_, found := providers[name]
return found
}
// CloudProviders returns the name of all registered cloud providers in a
// string slice
func CloudProviders() []string {
names := []string{}
providersMutex.Lock()
defer providersMutex.Unlock()
for name := range providers {
names = append(names, name)
}
return names
}
// GetCloudProvider creates an instance of the named cloud provider, or nil if
// the name is not known. The error return is only used if the named provider
// was known but failed to initialize. The config parameter specifies the