Various improvements for kubeadm. Removed the user command, as it's too little time for implementing that. Now it's possible to use multiple arches.

This commit is contained in:
Lucas Käldström 2016-09-15 17:40:42 +03:00 committed by Ilya Dmitrichenko
parent 6a20487b38
commit cab23e202e
No known key found for this signature in database
GPG Key ID: E7889175A6C0CEB9
11 changed files with 82 additions and 101 deletions

View File

@ -19,7 +19,6 @@ package app
import ( import (
"fmt" "fmt"
"os" "os"
"path"
"strings" "strings"
"github.com/spf13/pflag" "github.com/spf13/pflag"
@ -34,14 +33,12 @@ var CommandLine *pflag.FlagSet
// TODO(phase2) use componentconfig // TODO(phase2) use componentconfig
// we need some params for testing etc, let's keep these hidden for now // we need some params for testing etc, let's keep these hidden for now
func getEnvParams() map[string]string { func getEnvParams() map[string]string {
globalPrefix := os.Getenv("KUBE_PREFIX_ALL")
if globalPrefix == "" {
globalPrefix = "/etc/kubernetes"
}
envParams := map[string]string{ envParams := map[string]string{
"prefix": globalPrefix, // TODO(phase1): Mode prefix and host_pki_path to another place as constants, and use them everywhere
"host_pki_path": path.Join(globalPrefix, "pki"), // 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", "host_etcd_path": "/var/lib/etcd",
"hyperkube_image": "", "hyperkube_image": "",
"discovery_image": "dgoodwin/kubediscovery:latest", // TODO(phase1): fmt.Sprintf("gcr.io/google_containers/kube-discovery-%s:%s", runtime.GOARCH, "1.0"), "discovery_image": "dgoodwin/kubediscovery:latest", // TODO(phase1): fmt.Sprintf("gcr.io/google_containers/kube-discovery-%s:%s", runtime.GOARCH, "1.0"),

View File

@ -90,7 +90,6 @@ func NewKubeadmCommand(f *cmdutil.Factory, in io.Reader, out, err io.Writer, env
cmds.AddCommand(NewCmdInit(out, s)) cmds.AddCommand(NewCmdInit(out, s))
cmds.AddCommand(NewCmdJoin(out, s)) cmds.AddCommand(NewCmdJoin(out, s))
cmds.AddCommand(NewCmdUser(out, s))
cmds.AddCommand(NewCmdManual(out, s)) cmds.AddCommand(NewCmdManual(out, s))
return cmds return cmds

View File

@ -120,9 +120,8 @@ func NewCmdManualBootstrapInitMaster(out io.Writer, s *kubeadmapi.KubeadmConfig)
&s.InitFlags.API.ExternalDNSName, "api-external-dns-name", []string{}, &s.InitFlags.API.ExternalDNSName, "api-external-dns-name", []string{},
`(optional) DNS name to advertise, in case you have configured one yourself.`, `(optional) DNS name to advertise, in case you have configured one yourself.`,
) )
_, defaultServicesCIDR, _ := net.ParseCIDR("100.64.0.0/12")
cmd.PersistentFlags().IPNetVar( cmd.PersistentFlags().IPNetVar(
&s.InitFlags.Services.CIDR, "service-cidr", *defaultServicesCIDR, &s.InitFlags.Services.CIDR, "service-cidr", *kubeadmapi.DefaultServicesCIDR,
`(optional) use alterantive range of IP address for service VIPs, e.g. "10.16.0.0/12"`, `(optional) use alterantive range of IP address for service VIPs, e.g. "10.16.0.0/12"`,
) )
cmd.PersistentFlags().StringVar( cmd.PersistentFlags().StringVar(

View File

@ -1,34 +0,0 @@
/*
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 cmd
import (
"io"
"github.com/spf13/cobra"
kubeadmapi "k8s.io/kubernetes/pkg/kubeadm/api"
)
func NewCmdUser(out io.Writer, s *kubeadmapi.KubeadmConfig) *cobra.Command {
cmd := &cobra.Command{
Use: "user",
Short: "Get initial admin credentials for a cluster.", // using TLS bootstrap
Run: func(cmd *cobra.Command, args []string) {
},
}
return cmd
}

View File

@ -35,13 +35,15 @@ const (
gcrPrefix = "gcr.io/google_containers" gcrPrefix = "gcr.io/google_containers"
etcdVersion = "2.2.5" etcdVersion = "2.2.5"
kubeVersion = "v1.4.0-beta.6"
kubeDnsVersion = "1.7" kubeDnsVersion = "1.7"
dnsmasqVersion = "1.3" dnsmasqVersion = "1.3"
exechealthzVersion = "1.1" exechealthzVersion = "1.1"
) )
// TODO(phase1): Make this configurable + default to a v1.4 value fetched from: https://storage.googleapis.com/kubernetes-release/release/stable.txt
var DefaultKubeVersion = "v1.4.0-beta.6"
func GetCoreImage(image string, overrideImage string) string { func GetCoreImage(image string, overrideImage string) string {
if overrideImage != "" { if overrideImage != "" {
return overrideImage return overrideImage
@ -49,10 +51,10 @@ func GetCoreImage(image string, overrideImage string) string {
return map[string]string{ return map[string]string{
KubeEtcdImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "etcd", runtime.GOARCH, etcdVersion), KubeEtcdImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "etcd", runtime.GOARCH, etcdVersion),
KubeApiServerImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-apiserver", runtime.GOARCH, kubeVersion), KubeApiServerImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-apiserver", runtime.GOARCH, DefaultKubeVersion),
KubeControllerManagerImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-controller-manager", runtime.GOARCH, kubeVersion), KubeControllerManagerImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-controller-manager", runtime.GOARCH, DefaultKubeVersion),
KubeSchedulerImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-scheduler", runtime.GOARCH, kubeVersion), KubeSchedulerImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-scheduler", runtime.GOARCH, DefaultKubeVersion),
KubeProxyImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-proxy", runtime.GOARCH, kubeVersion), KubeProxyImage: fmt.Sprintf("%s/%s-%s:%s", gcrPrefix, "kube-proxy", runtime.GOARCH, DefaultKubeVersion),
}[image] }[image]
} }

View File

@ -19,6 +19,7 @@ package master
import ( import (
"fmt" "fmt"
"path" "path"
"runtime"
"k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/resource" "k8s.io/kubernetes/pkg/api/resource"
@ -28,11 +29,14 @@ import (
ipallocator "k8s.io/kubernetes/pkg/registry/service/ipallocator" ipallocator "k8s.io/kubernetes/pkg/registry/service/ipallocator"
"k8s.io/kubernetes/pkg/util/intstr" "k8s.io/kubernetes/pkg/util/intstr"
) )
// TODO(phase1+): kube-proxy should be a daemonset, three different daemonsets should not be here
func createKubeProxyPodSpec(s *kubeadmapi.KubeadmConfig) api.PodSpec { func createKubeProxyPodSpec(s *kubeadmapi.KubeadmConfig, architecture string) api.PodSpec {
privilegedTrue := true privilegedTrue := true
return api.PodSpec{ return api.PodSpec{
SecurityContext: &api.PodSecurityContext{HostNetwork: true}, SecurityContext: &api.PodSecurityContext{HostNetwork: true},
NodeSelector: map[string]string{
"beta.kubernetes.io/arch": architecture,
},
Containers: []api.Container{{ Containers: []api.Container{{
Name: kubeProxy, Name: kubeProxy,
Image: images.GetCoreImage(images.KubeProxyImage, s.EnvParams["hyperkube_image"]), Image: images.GetCoreImage(images.KubeProxyImage, s.EnvParams["hyperkube_image"]),
@ -65,7 +69,7 @@ func createKubeProxyPodSpec(s *kubeadmapi.KubeadmConfig) api.PodSpec {
{ {
Name: "kubeconfig", Name: "kubeconfig",
VolumeSource: api.VolumeSource{ VolumeSource: api.VolumeSource{
HostPath: &api.HostPathVolumeSource{Path: path.Join(s.EnvParams["prefix"], "kubelet.conf")}, HostPath: &api.HostPathVolumeSource{Path: path.Join(s.EnvParams["kubernetes_dir"], "kubelet.conf")},
}, },
}, },
{ {
@ -101,6 +105,9 @@ func createKubeDNSPodSpec(s *kubeadmapi.KubeadmConfig) api.PodSpec {
) )
return api.PodSpec{ return api.PodSpec{
NodeSelector: map[string]string{
"beta.kubernetes.io/arch": runtime.GOARCH,
},
Containers: []api.Container{ Containers: []api.Container{
// DNS server // DNS server
{ {
@ -223,11 +230,15 @@ func createKubeDNSServiceSpec(s *kubeadmapi.KubeadmConfig) (*api.ServiceSpec, er
} }
func CreateEssentialAddons(s *kubeadmapi.KubeadmConfig, client *clientset.Clientset) error { func CreateEssentialAddons(s *kubeadmapi.KubeadmConfig, client *clientset.Clientset) error {
kubeProxyDaemonSet := NewDaemonSet(kubeProxy, createKubeProxyPodSpec(s)) arches := [3]string{"amd64", "arm", "arm64"}
SetMasterTaintTolerations(&kubeProxyDaemonSet.Spec.Template.ObjectMeta)
if _, err := client.Extensions().DaemonSets(api.NamespaceSystem).Create(kubeProxyDaemonSet); err != nil { for _, arch := range arches {
return fmt.Errorf("<master/addons> failed creating essential kube-proxy addon [%s]", err) kubeProxyDaemonSet := NewDaemonSet(kubeProxy + "-" + arch, createKubeProxyPodSpec(s, arch))
SetMasterTaintTolerations(&kubeProxyDaemonSet.Spec.Template.ObjectMeta)
if _, err := client.Extensions().DaemonSets(api.NamespaceSystem).Create(kubeProxyDaemonSet); err != nil {
return fmt.Errorf("<master/addons> failed creating essential kube-proxy addon [%s]", err)
}
} }
fmt.Println("<master/addons> created essential addon: kube-proxy") fmt.Println("<master/addons> created essential addon: kube-proxy")

View File

@ -36,7 +36,8 @@ import (
// init master` and `kubeadm manual bootstrap master` can get going. // init master` and `kubeadm manual bootstrap master` can get going.
const ( const (
DefaultClusterName = "--cluster-name=kubernetes" DefaultClusterName = "kubernetes"
DefaultCloudConfigPath = "/etc/kubernetes/cloud-config.json"
etcd = "etcd" etcd = "etcd"
apiServer = "apiserver" apiServer = "apiserver"
@ -57,12 +58,7 @@ func WriteStaticPodManifests(s *kubeadmapi.KubeadmConfig) error {
staticPodSpecs := map[string]api.Pod{ staticPodSpecs := map[string]api.Pod{
// TODO this needs a volume // TODO this needs a volume
etcd: componentPod(api.Container{ etcd: componentPod(api.Container{
Command: []string{ Command: getComponentCommand(etcd, s),
"/usr/local/bin/etcd",
"--listen-client-urls=http://127.0.0.1:2379",
"--advertise-client-urls=http://127.0.0.1:2379",
"--data-dir=/var/etcd/data",
},
VolumeMounts: []api.VolumeMount{etcdVolumeMount()}, VolumeMounts: []api.VolumeMount{etcdVolumeMount()},
Image: images.GetCoreImage(images.KubeEtcdImage, s.EnvParams["etcd_image"]), Image: images.GetCoreImage(images.KubeEtcdImage, s.EnvParams["etcd_image"]),
LivenessProbe: componentProbe(2379, "/health"), LivenessProbe: componentProbe(2379, "/health"),
@ -74,18 +70,18 @@ func WriteStaticPodManifests(s *kubeadmapi.KubeadmConfig) error {
Name: kubeAPIServer, Name: kubeAPIServer,
Image: images.GetCoreImage(images.KubeApiServerImage, s.EnvParams["hyperkube_image"]), Image: images.GetCoreImage(images.KubeApiServerImage, s.EnvParams["hyperkube_image"]),
Command: getComponentCommand(apiServer, s), Command: getComponentCommand(apiServer, s),
VolumeMounts: []api.VolumeMount{pkiVolumeMount()}, VolumeMounts: []api.VolumeMount{k8sVolumeMount()},
LivenessProbe: componentProbe(8080, "/healthz"), LivenessProbe: componentProbe(8080, "/healthz"),
Resources: componentResources("250m"), Resources: componentResources("250m"),
}, pkiVolume(s)), }, k8sVolume(s)),
kubeControllerManager: componentPod(api.Container{ kubeControllerManager: componentPod(api.Container{
Name: kubeControllerManager, Name: kubeControllerManager,
Image: images.GetCoreImage(images.KubeControllerManagerImage, s.EnvParams["hyperkube_image"]), Image: images.GetCoreImage(images.KubeControllerManagerImage, s.EnvParams["hyperkube_image"]),
Command: getComponentCommand(controllerManager, s), Command: getComponentCommand(controllerManager, s),
VolumeMounts: []api.VolumeMount{pkiVolumeMount()}, VolumeMounts: []api.VolumeMount{k8sVolumeMount()},
LivenessProbe: componentProbe(10252, "/healthz"), LivenessProbe: componentProbe(10252, "/healthz"),
Resources: componentResources("200m"), Resources: componentResources("200m"),
}, pkiVolume(s)), }, k8sVolume(s)),
kubeScheduler: componentPod(api.Container{ kubeScheduler: componentPod(api.Container{
Name: kubeScheduler, Name: kubeScheduler,
Image: images.GetCoreImage(images.KubeSchedulerImage, s.EnvParams["hyperkube_image"]), Image: images.GetCoreImage(images.KubeSchedulerImage, s.EnvParams["hyperkube_image"]),
@ -95,7 +91,7 @@ func WriteStaticPodManifests(s *kubeadmapi.KubeadmConfig) error {
}), }),
} }
manifestsPath := path.Join(s.EnvParams["prefix"], "manifests") manifestsPath := path.Join(s.EnvParams["kubernetes_dir"], "manifests")
if err := os.MkdirAll(manifestsPath, 0700); err != nil { if err := os.MkdirAll(manifestsPath, 0700); err != nil {
return fmt.Errorf("<master/manifests> failed to create directory %q [%s]", manifestsPath, err) return fmt.Errorf("<master/manifests> failed to create directory %q [%s]", manifestsPath, err)
} }
@ -128,19 +124,19 @@ func etcdVolumeMount() api.VolumeMount {
} }
} }
func pkiVolume(s *kubeadmapi.KubeadmConfig) api.Volume { func k8sVolume(s *kubeadmapi.KubeadmConfig) api.Volume {
return api.Volume{ return api.Volume{
Name: "pki", Name: "pki",
VolumeSource: api.VolumeSource{ VolumeSource: api.VolumeSource{
HostPath: &api.HostPathVolumeSource{Path: s.EnvParams["host_pki_path"]}, HostPath: &api.HostPathVolumeSource{Path: s.EnvParams["kubernetes_dir"]},
}, },
} }
} }
func pkiVolumeMount() api.VolumeMount { func k8sVolumeMount() api.VolumeMount {
return api.VolumeMount{ return api.VolumeMount{
Name: "pki", Name: "pki",
MountPath: "/etc/kubernetes/pki", MountPath: "/etc/kubernetes/",
ReadOnly: true, ReadOnly: true,
} }
} }
@ -187,32 +183,43 @@ 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.KubeadmConfig) (command []string) {
baseFalgs := map[string][]string{ // TODO: make a global constant of this
pki_dir := "/etc/kubernetes/pki"
baseFlags := map[string][]string{
etcd: []string{
"/usr/local/bin/etcd",
"--listen-client-urls=http://127.0.0.1:2379",
"--advertise-client-urls=http://127.0.0.1:2379",
"--data-dir=/var/etcd/data",
},
apiServer: []string{ apiServer: []string{
"--address=127.0.0.1", "--address=127.0.0.1",
"--etcd-servers=http://127.0.0.1:2379", "--etcd-servers=http://127.0.0.1:2379",
"--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota", "--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota",
"--service-cluster-ip-range=" + s.InitFlags.Services.CIDR.String(), "--service-cluster-ip-range=" + s.InitFlags.Services.CIDR.String(),
"--service-account-key-file=/etc/kubernetes/pki/apiserver-key.pem", "--service-account-key-file=" + pki_dir + "/apiserver-key.pem",
"--client-ca-file=/etc/kubernetes/pki/ca.pem", "--client-ca-file=" + pki_dir + "/ca.pem",
"--tls-cert-file=/etc/kubernetes/pki/apiserver.pem", "--tls-cert-file=" + pki_dir + "/apiserver.pem",
"--tls-private-key-file=/etc/kubernetes/pki/apiserver-key.pem", "--tls-private-key-file=" + pki_dir + "/apiserver-key.pem",
"--token-auth-file=" + pki_dir + "/tokens.csv",
"--secure-port=443", "--secure-port=443",
"--allow-privileged", "--allow-privileged",
"--token-auth-file=/etc/kubernetes/pki/tokens.csv",
}, },
controllerManager: []string{ controllerManager: []string{
// TODO: consider adding --address=127.0.0.1 in order to not expose the cm port to the rest of the world
"--leader-elect", "--leader-elect",
"--master=127.0.0.1:8080", "--master=127.0.0.1:8080",
DefaultClusterName, "--cluster-name=" + DefaultClusterName,
"--root-ca-file=/etc/kubernetes/pki/ca.pem", "--root-ca-file=" + pki_dir + "/ca.pem",
"--service-account-private-key-file=/etc/kubernetes/pki/apiserver-key.pem", "--service-account-private-key-file=" + pki_dir + "/apiserver-key.pem",
"--cluster-signing-cert-file=/etc/kubernetes/pki/ca.pem", "--cluster-signing-cert-file=" + pki_dir + "/ca.pem",
"--cluster-signing-key-file=/etc/kubernetes/pki/ca-key.pem", "--cluster-signing-key-file=" + pki_dir + "/ca-key.pem",
"--insecure-experimental-approve-all-kubelet-csrs-for-group=system:kubelet-bootstrap", "--insecure-experimental-approve-all-kubelet-csrs-for-group=system:kubelet-bootstrap",
"--cluster-cidr=" + s.InitFlags.Services.CIDR.String(), "--cluster-cidr=" + s.InitFlags.Services.CIDR.String(),
}, },
scheduler: []string{ scheduler: []string{
// TODO: consider adding --address=127.0.0.1 in order to not expose the scheduler port to the rest of the world
"--leader-elect", "--leader-elect",
"--master=127.0.0.1:8080", "--master=127.0.0.1:8080",
}, },
@ -226,10 +233,15 @@ func getComponentCommand(component string, s *kubeadmapi.KubeadmConfig) (command
} }
command = append(command, s.EnvParams["component_loglevel"]) command = append(command, s.EnvParams["component_loglevel"])
command = append(command, baseFalgs[component]...) command = append(command, baseFlags[component]...)
if component == controllerManager && s.InitFlags.CloudProvider != "" { if component == controllerManager && s.InitFlags.CloudProvider != "" {
command = append(command, "--cloud-provider="+s.InitFlags.CloudProvider) command = append(command, "--cloud-provider="+s.InitFlags.CloudProvider)
// Only append the --cloud-config option if there's a such file
if _, err := os.Stat(DefaultCloudConfigPath); err == nil {
command = append(command, "--cloud-config=" + DefaultCloudConfigPath)
}
} }
return return

View File

@ -27,12 +27,6 @@ import (
certutil "k8s.io/kubernetes/pkg/util/cert" certutil "k8s.io/kubernetes/pkg/util/cert"
) )
/*
func errorf(f string, err error, vargs ...string) error {
return fmt.Errorf("<master/pki> %s [%s]", fmt.Sprintf(f, v...), err)
}
*/
func newCertificateAuthority() (*rsa.PrivateKey, *x509.Certificate, error) { func newCertificateAuthority() (*rsa.PrivateKey, *x509.Certificate, error) {
key, err := certutil.NewPrivateKey() key, err := certutil.NewPrivateKey()
if err != nil { if err != nil {

View File

@ -20,6 +20,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"strings" "strings"
"os"
"k8s.io/kubernetes/pkg/apis/certificates" "k8s.io/kubernetes/pkg/apis/certificates"
unversionedcertificates "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/unversioned" unversionedcertificates "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/certificates/unversioned"
@ -33,10 +34,6 @@ import (
certutil "k8s.io/kubernetes/pkg/util/cert" certutil "k8s.io/kubernetes/pkg/util/cert"
) )
func getNodeName() string {
return "TODO"
}
func PerformTLSBootstrapFromConfig(s *kubeadmapi.KubeadmConfig) (*clientcmdapi.Config, error) { func PerformTLSBootstrapFromConfig(s *kubeadmapi.KubeadmConfig) (*clientcmdapi.Config, error) {
caCert, err := ioutil.ReadFile(s.ManualFlags.CaCertFile) caCert, err := ioutil.ReadFile(s.ManualFlags.CaCertFile)
if err != nil { if err != nil {
@ -51,7 +48,11 @@ func PerformTLSBootstrap(s *kubeadmapi.KubeadmConfig, apiEndpoint string, caCert
// TODO try all the api servers until we find one that works // TODO try all the api servers until we find one that works
bareClientConfig := kubeadmutil.CreateBasicClientConfig("kubernetes", apiEndpoint, caCert) bareClientConfig := kubeadmutil.CreateBasicClientConfig("kubernetes", apiEndpoint, caCert)
nodeName := getNodeName() // Try to fetch the hostname of the node
nodeName, err := os.Hostname()
if err != nil {
return nil, fmt.Errorf("<node/csr> failed to get node hostname [%v]", err)
}
bootstrapClientConfig, err := clientcmd.NewDefaultClientConfig( bootstrapClientConfig, err := clientcmd.NewDefaultClientConfig(
*kubeadmutil.MakeClientConfigWithToken( *kubeadmutil.MakeClientConfigWithToken(

View File

@ -82,11 +82,11 @@ func MakeClientConfigWithToken(config *clientcmdapi.Config, clusterName string,
// start it again in that case). // start it again in that case).
func WriteKubeconfigIfNotExists(s *kubeadmapi.KubeadmConfig, name string, kubeconfig *clientcmdapi.Config) error { func WriteKubeconfigIfNotExists(s *kubeadmapi.KubeadmConfig, name string, kubeconfig *clientcmdapi.Config) error {
if err := os.MkdirAll(s.EnvParams["prefix"], 0700); err != nil { if err := os.MkdirAll(s.EnvParams["kubernetes_dir"], 0700); err != nil {
return fmt.Errorf("<util/kubeconfig> failed to create directory %q [%s]", s.EnvParams["prefix"], err) return fmt.Errorf("<util/kubeconfig> failed to create directory %q [%s]", s.EnvParams["kubernetes_dir"], err)
} }
filename := path.Join(s.EnvParams["prefix"], fmt.Sprintf("%s.conf", name)) filename := path.Join(s.EnvParams["kubernetes_dir"], fmt.Sprintf("%s.conf", name))
// Create and open the file, only if it does not already exist. // Create and open the file, only if it does not already exist.
f, err := os.OpenFile( f, err := os.OpenFile(
filename, filename,

View File

@ -30,7 +30,7 @@ const (
TokenBytes = 8 TokenBytes = 8
) )
func randBytes(length int) ([]byte, string, error) { func RandBytes(length int) ([]byte, string, error) {
b := make([]byte, length) b := make([]byte, length)
_, err := rand.Read(b) _, err := rand.Read(b)
if err != nil { if err != nil {
@ -43,12 +43,12 @@ func randBytes(length int) ([]byte, string, error) {
} }
func GenerateToken(s *kubeadmapi.KubeadmConfig) error { func GenerateToken(s *kubeadmapi.KubeadmConfig) error {
_, tokenID, err := randBytes(TokenIDLen / 2) _, tokenID, err := RandBytes(TokenIDLen / 2)
if err != nil { if err != nil {
return err return err
} }
tokenBytes, token, err := randBytes(TokenBytes) tokenBytes, token, err := RandBytes(TokenBytes)
if err != nil { if err != nil {
return err return err
} }