提交 2f1a11d8 编写于 作者: T Thomas Stromberg

Move reusable files (images, binaries, certs) to /data

上级 35e473ad
......@@ -38,8 +38,8 @@ const driverName = constants.DriverNone
// cleanupPaths are paths to be removed by cleanup, and are used by both kubeadm and minikube.
var cleanupPaths = []string{
"/data/minikube",
"/etc/kubernetes/manifests",
constants.GuestEphemeralDir,
constants.GuestManifestsDir,
"/var/lib/minikube",
}
......
......@@ -70,7 +70,7 @@ var Addons = map[string]*Addon{
"addon-manager": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/addon-manager.yaml.tmpl",
"/etc/kubernetes/manifests/",
constants.GuestManifestsDir,
"addon-manager.yaml.tmpl",
"0640",
true),
......@@ -78,13 +78,13 @@ var Addons = map[string]*Addon{
"dashboard": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/dashboard/dashboard-dp.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"dashboard-dp.yaml",
"0640",
true),
MustBinAsset(
"deploy/addons/dashboard/dashboard-svc.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"dashboard-svc.yaml",
"0640",
false),
......@@ -92,7 +92,7 @@ var Addons = map[string]*Addon{
"default-storageclass": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/storageclass/storageclass.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"storageclass.yaml",
"0640",
false),
......@@ -100,7 +100,7 @@ var Addons = map[string]*Addon{
"storage-provisioner": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/storage-provisioner/storage-provisioner.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"storage-provisioner.yaml",
"0640",
true),
......@@ -108,25 +108,25 @@ var Addons = map[string]*Addon{
"storage-provisioner-gluster": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/storage-provisioner-gluster/storage-gluster-ns.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"storage-gluster-ns.yaml",
"0640",
false),
MustBinAsset(
"deploy/addons/storage-provisioner-gluster/glusterfs-daemonset.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"glusterfs-daemonset.yaml",
"0640",
false),
MustBinAsset(
"deploy/addons/storage-provisioner-gluster/heketi-deployment.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"heketi-deployment.yaml",
"0640",
false),
MustBinAsset(
"deploy/addons/storage-provisioner-gluster/storage-provisioner-glusterfile.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"storage-privisioner-glusterfile.yaml",
"0640",
false),
......@@ -134,31 +134,31 @@ var Addons = map[string]*Addon{
"heapster": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/heapster/influx-grafana-rc.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"influxGrafana-rc.yaml",
"0640",
true),
MustBinAsset(
"deploy/addons/heapster/grafana-svc.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"grafana-svc.yaml",
"0640",
false),
MustBinAsset(
"deploy/addons/heapster/influxdb-svc.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"influxdb-svc.yaml",
"0640",
false),
MustBinAsset(
"deploy/addons/heapster/heapster-rc.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"heapster-rc.yaml",
"0640",
true),
MustBinAsset(
"deploy/addons/heapster/heapster-svc.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"heapster-svc.yaml",
"0640",
false),
......@@ -166,37 +166,37 @@ var Addons = map[string]*Addon{
"efk": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/efk/elasticsearch-rc.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"elasticsearch-rc.yaml",
"0640",
true),
MustBinAsset(
"deploy/addons/efk/elasticsearch-svc.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"elasticsearch-svc.yaml",
"0640",
false),
MustBinAsset(
"deploy/addons/efk/fluentd-es-rc.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"fluentd-es-rc.yaml",
"0640",
true),
MustBinAsset(
"deploy/addons/efk/fluentd-es-configmap.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"fluentd-es-configmap.yaml",
"0640",
false),
MustBinAsset(
"deploy/addons/efk/kibana-rc.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"kibana-rc.yaml",
"0640",
false),
MustBinAsset(
"deploy/addons/efk/kibana-svc.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"kibana-svc.yaml",
"0640",
false),
......@@ -204,19 +204,19 @@ var Addons = map[string]*Addon{
"ingress": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/ingress/ingress-configmap.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"ingress-configmap.yaml",
"0640",
false),
MustBinAsset(
"deploy/addons/ingress/ingress-rbac.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"ingress-rbac.yaml",
"0640",
false),
MustBinAsset(
"deploy/addons/ingress/ingress-dp.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"ingress-dp.yaml",
"0640",
true),
......@@ -224,19 +224,19 @@ var Addons = map[string]*Addon{
"metrics-server": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/metrics-server/metrics-apiservice.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"metrics-apiservice.yaml",
"0640",
false),
MustBinAsset(
"deploy/addons/metrics-server/metrics-server-deployment.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"metrics-server-deployment.yaml",
"0640",
true),
MustBinAsset(
"deploy/addons/metrics-server/metrics-server-service.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"metrics-server-service.yaml",
"0640",
false),
......@@ -244,19 +244,19 @@ var Addons = map[string]*Addon{
"registry": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/registry/registry-rc.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"registry-rc.yaml",
"0640",
false),
MustBinAsset(
"deploy/addons/registry/registry-svc.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"registry-svc.yaml",
"0640",
false),
MustBinAsset(
"deploy/addons/registry/registry-proxy.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"registry-proxy.yaml",
"0640",
false),
......@@ -264,7 +264,7 @@ var Addons = map[string]*Addon{
"registry-creds": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/registry-creds/registry-creds-rc.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"registry-creds-rc.yaml",
"0640",
false),
......@@ -272,7 +272,7 @@ var Addons = map[string]*Addon{
"freshpod": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/freshpod/freshpod-rc.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"freshpod-rc.yaml",
"0640",
true),
......@@ -280,7 +280,7 @@ var Addons = map[string]*Addon{
"nvidia-driver-installer": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/gpu/nvidia-driver-installer.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"nvidia-driver-installer.yaml",
"0640",
true),
......@@ -288,7 +288,7 @@ var Addons = map[string]*Addon{
"nvidia-gpu-device-plugin": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/gpu/nvidia-gpu-device-plugin.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"nvidia-gpu-device-plugin.yaml",
"0640",
true),
......@@ -296,13 +296,13 @@ var Addons = map[string]*Addon{
"logviewer": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/logviewer/logviewer-dp-and-svc.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"logviewer-dp-and-svc.yaml",
"0640",
false),
MustBinAsset(
"deploy/addons/logviewer/logviewer-rbac.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"logviewer-rbac.yaml",
"0640",
false),
......@@ -310,7 +310,7 @@ var Addons = map[string]*Addon{
"gvisor": NewAddon([]*BinAsset{
MustBinAsset(
"deploy/addons/gvisor/gvisor-pod.yaml.tmpl",
constants.AddonsPath,
constants.GuestAddonsDir,
"gvisor-pod.yaml",
"0640",
true),
......@@ -332,7 +332,7 @@ var Addons = map[string]*Addon{
// AddMinikubeDirAssets adds all addons and files to the list
// of files to be copied to the vm.
func AddMinikubeDirAssets(assets *[]CopyableFile) error {
if err := addMinikubeDirToAssets(constants.MakeMiniPath("addons"), constants.AddonsPath, assets); err != nil {
if err := addMinikubeDirToAssets(constants.MakeMiniPath("addons"), constants.GuestAddonsDir, assets); err != nil {
return errors.Wrap(err, "adding addons folder to assets")
}
if err := addMinikubeDirToAssets(constants.MakeMiniPath("files"), "", assets); err != nil {
......
......@@ -56,18 +56,18 @@ func TestAddMinikubeDirAssets(t *testing.T) {
}{
{
relativePath: "/dir1/file1.txt",
expectedPath: constants.AddonsPath,
expectedPath: constants.GuestAddonsDir,
},
{
relativePath: "/dir1/file2.txt",
expectedPath: constants.AddonsPath,
expectedPath: constants.GuestAddonsDir,
},
{
relativePath: "/dir2/file1.txt",
expectedPath: constants.AddonsPath,
expectedPath: constants.GuestAddonsDir,
},
},
vmPath: constants.AddonsPath,
vmPath: constants.GuestAddonsDir,
},
{
description: "absolute path assets",
......
......@@ -23,6 +23,7 @@ import (
"io"
"os"
"path"
"path/filepath"
"github.com/golang/glog"
"github.com/pkg/errors"
......@@ -78,14 +79,15 @@ func NewMemoryAssetTarget(d []byte, targetPath, permissions string) *MemoryAsset
}
// NewFileAsset creates a new FileAsset
func NewFileAsset(path, targetDir, targetName, permissions string) (*FileAsset, error) {
f, err := os.Open(path)
func NewFileAsset(src, targetDir, targetName, permissions string) (*FileAsset, error) {
glog.Infof("NewFileAsset: %s -> %s", src, filepath.Join(targetDir, targetName))
f, err := os.Open(src)
if err != nil {
return nil, errors.Wrapf(err, "Error opening file asset: %s", path)
return nil, errors.Wrapf(err, "Error opening file asset: %s", src)
}
return &FileAsset{
BaseAsset: BaseAsset{
AssetName: path,
AssetName: src,
TargetDir: targetDir,
TargetName: targetName,
Permissions: permissions,
......
......@@ -56,7 +56,7 @@ const (
func GetCachedBinaryList(bootstrapper string) []string {
switch bootstrapper {
case BootstrapperTypeKubeadm:
return constants.GetKubeadmCachedBinaries()
return constants.KubeadmBinaries
default:
return []string{}
}
......
......@@ -50,7 +50,9 @@ func SetupCerts(cmd command.Runner, k8s config.KubernetesConfig) error {
if err := generateCerts(k8s); err != nil {
return errors.Wrap(err, "Error generating certs")
}
if err := cmd.Run(fmt.Sprintf("sudo mkdir -p %s", constants.GuestCertsDir)); err != nil {
return errors.Wrap(err, "mkdir")
}
copyableFiles := []assets.CopyableFile{}
for _, cert := range certs {
......@@ -59,7 +61,7 @@ func SetupCerts(cmd command.Runner, k8s config.KubernetesConfig) error {
if strings.HasSuffix(cert, ".key") {
perms = "0600"
}
certFile, err := assets.NewFileAsset(p, util.DefaultCertPath, cert, perms)
certFile, err := assets.NewFileAsset(p, constants.GuestCertsDir, cert, perms)
if err != nil {
return err
}
......@@ -69,9 +71,9 @@ func SetupCerts(cmd command.Runner, k8s config.KubernetesConfig) error {
kubeCfgSetup := &util.KubeConfigSetup{
ClusterName: k8s.NodeName,
ClusterServerAddress: fmt.Sprintf("https://localhost:%d", k8s.NodePort),
ClientCertificate: path.Join(util.DefaultCertPath, "apiserver.crt"),
ClientKey: path.Join(util.DefaultCertPath, "apiserver.key"),
CertificateAuthority: path.Join(util.DefaultCertPath, "ca.crt"),
ClientCertificate: path.Join(constants.GuestCertsDir, "apiserver.crt"),
ClientKey: path.Join(constants.GuestCertsDir, "apiserver.key"),
CertificateAuthority: path.Join(constants.GuestCertsDir, "ca.crt"),
KeepContext: false,
}
......@@ -85,13 +87,12 @@ func SetupCerts(cmd command.Runner, k8s config.KubernetesConfig) error {
return errors.Wrap(err, "encoding kubeconfig")
}
kubeCfgFile := assets.NewMemoryAsset(data,
util.DefaultMinikubeDirectory, "kubeconfig", "0644")
kubeCfgFile := assets.NewMemoryAsset(data, constants.GuestEphemeralDir, "kubeconfig", "0644")
copyableFiles = append(copyableFiles, kubeCfgFile)
for _, f := range copyableFiles {
if err := cmd.Copy(f); err != nil {
return err
return errors.Wrapf(err, "Copy %s", f.GetAssetName())
}
}
return nil
......
......@@ -22,6 +22,7 @@ import (
"fmt"
"net"
"net/http"
"path/filepath"
"runtime"
"strings"
"time"
......@@ -90,6 +91,9 @@ var PodsByLayer = []pod{
{"dns", "k8s-app", "kube-dns"},
}
// yamlConfigPath is the path to the kubeadm configuration
var yamlConfigPath = filepath.Join(constants.GuestEphemeralDir, "kubeadm.yaml")
// SkipAdditionalPreflights are additional preflights we skip depending on the runtime in use.
var SkipAdditionalPreflights = map[string][]string{}
......@@ -206,8 +210,8 @@ func (k *Bootstrapper) StartCluster(k8s config.KubernetesConfig) error {
}
ignore := []string{
"DirAvailable--etc-kubernetes-manifests", // Addons are stored in /etc/kubernetes/manifests
"DirAvailable--data-minikube",
fmt.Sprintf("DirAvailable-%s", strings.Replace(constants.GuestManifestsDir, "/", "-", -1)),
fmt.Sprintf("DirAvailable-%s", strings.Replace(constants.GuestPersistentDir, "/", "-", -1)),
"FileAvailable--etc-kubernetes-manifests-kube-scheduler.yaml",
"FileAvailable--etc-kubernetes-manifests-kube-apiserver.yaml",
"FileAvailable--etc-kubernetes-manifests-kube-controller-manager.yaml",
......@@ -223,8 +227,8 @@ func (k *Bootstrapper) StartCluster(k8s config.KubernetesConfig) error {
ignore = append(ignore, "SystemVerification")
}
cmd := fmt.Sprintf("sudo /usr/bin/kubeadm init --config %s %s --ignore-preflight-errors=%s",
constants.KubeadmConfigFile, extraFlags, strings.Join(ignore, ","))
cmd := fmt.Sprintf("%s init --config %s %s --ignore-preflight-errors=%s",
invokeKubeadm(k8s.KubernetesVersion), yamlConfigPath, extraFlags, strings.Join(ignore, ","))
out, err := k.c.CombinedOutput(cmd)
if err != nil {
return errors.Wrapf(err, "cmd failed: %s\n%s\n", cmd, out)
......@@ -347,13 +351,12 @@ func (k *Bootstrapper) RestartCluster(k8s config.KubernetesConfig) error {
controlPlane = "control-plane"
}
configPath := constants.KubeadmConfigFile
baseCmd := fmt.Sprintf("sudo kubeadm %s", phase)
baseCmd := fmt.Sprintf("%s %s", invokeKubeadm(k8s.KubernetesVersion), phase)
cmds := []string{
fmt.Sprintf("%s phase certs all --config %s", baseCmd, configPath),
fmt.Sprintf("%s phase kubeconfig all --config %s", baseCmd, configPath),
fmt.Sprintf("%s phase %s all --config %s", baseCmd, controlPlane, configPath),
fmt.Sprintf("%s phase etcd local --config %s", baseCmd, configPath),
fmt.Sprintf("%s phase certs all --config %s", baseCmd, yamlConfigPath),
fmt.Sprintf("%s phase kubeconfig all --config %s", baseCmd, yamlConfigPath),
fmt.Sprintf("%s phase %s all --config %s", baseCmd, controlPlane, yamlConfigPath),
fmt.Sprintf("%s phase etcd local --config %s", baseCmd, yamlConfigPath),
}
// Run commands one at a time so that it is easier to root cause failures.
......@@ -367,7 +370,7 @@ func (k *Bootstrapper) RestartCluster(k8s config.KubernetesConfig) error {
return errors.Wrap(err, "waiting for apiserver")
}
// restart the proxy and coredns
if err := k.c.Run(fmt.Sprintf("%s phase addon all --config %s", baseCmd, configPath)); err != nil {
if err := k.c.Run(fmt.Sprintf("%s phase addon all --config %s", baseCmd, yamlConfigPath)); err != nil {
return errors.Wrapf(err, "addon phase")
}
......@@ -379,8 +382,21 @@ func (k *Bootstrapper) RestartCluster(k8s config.KubernetesConfig) error {
// waitForAPIServer waits for the apiserver to start up
func (k *Bootstrapper) waitForAPIServer(k8s config.KubernetesConfig) error {
glog.Infof("Waiting for apiserver ...")
return wait.PollImmediate(time.Millisecond*300, time.Minute*3, func() (bool, error) {
glog.Infof("Waiting for apiserver process ...")
// To give a better error message, first check for process existence via ssh
err := wait.PollImmediate(time.Millisecond*300, time.Minute*2, func() (bool, error) {
ierr := k.c.Run(`pgrep apiserver`)
if ierr != nil {
return false, ierr
}
return true, nil
})
if err != nil {
return fmt.Errorf("apiserver process never appeared")
}
glog.Infof("Waiting for apiserver status ...")
return wait.PollImmediate(time.Millisecond*300, time.Minute*1, func() (bool, error) {
status, err := k.GetAPIServerStatus(net.ParseIP(k8s.NodeIP), k8s.NodePort)
glog.Infof("apiserver status: %s, err: %v", status, err)
if err != nil {
......@@ -395,7 +411,7 @@ func (k *Bootstrapper) waitForAPIServer(k8s config.KubernetesConfig) error {
// DeleteCluster removes the components that were started earlier
func (k *Bootstrapper) DeleteCluster(k8s config.KubernetesConfig) error {
cmd := fmt.Sprintf("sudo kubeadm reset --force")
cmd := fmt.Sprintf("%s reset --force", invokeKubeadm(k8s.KubernetesVersion))
out, err := k.c.CombinedOutput(cmd)
if err != nil {
return errors.Wrapf(err, "kubeadm reset: %s\n%s\n", cmd, out)
......@@ -414,7 +430,7 @@ func (k *Bootstrapper) PullImages(k8s config.KubernetesConfig) error {
return fmt.Errorf("pull command is not supported by kubeadm v%s", version)
}
cmd := fmt.Sprintf("sudo kubeadm config images pull --config %s", constants.KubeadmConfigFile)
cmd := fmt.Sprintf("%s config images pull --config %s", invokeKubeadm(k8s.KubernetesVersion), yamlConfigPath)
if err := k.c.Run(cmd); err != nil {
return errors.Wrapf(err, "running cmd: %s", cmd)
}
......@@ -428,15 +444,15 @@ func (k *Bootstrapper) SetupCerts(k8s config.KubernetesConfig) error {
// NewKubeletConfig generates a new systemd unit containing a configured kubelet
// based on the options present in the KubernetesConfig.
func NewKubeletConfig(k8s config.KubernetesConfig, r cruntime.Manager) (string, error) {
func NewKubeletConfig(k8s config.KubernetesConfig, r cruntime.Manager) ([]byte, error) {
version, err := ParseKubernetesVersion(k8s.KubernetesVersion)
if err != nil {
return "", errors.Wrap(err, "parsing kubernetes version")
return nil, errors.Wrap(err, "parsing kubernetes version")
}
extraOpts, err := ExtraConfigForComponent(Kubelet, k8s.ExtraOptions, version)
if err != nil {
return "", errors.Wrap(err, "generating extra configuration for kubelet")
return nil, errors.Wrap(err, "generating extra configuration for kubelet")
}
for k, v := range r.KubeletOptions() {
......@@ -454,28 +470,28 @@ func NewKubeletConfig(k8s config.KubernetesConfig, r cruntime.Manager) (string,
// parses a map of the feature gates for kubelet
_, kubeletFeatureArgs, err := ParseFeatureArgs(k8s.FeatureGates)
if err != nil {
return "", errors.Wrap(err, "parses feature gate config for kubelet")
return nil, errors.Wrap(err, "parses feature gate config for kubelet")
}
if kubeletFeatureArgs != "" {
extraOpts["feature-gates"] = kubeletFeatureArgs
}
extraFlags := convertToFlags(extraOpts)
b := bytes.Buffer{}
opts := struct {
ExtraOptions string
ContainerRuntime string
KubeletPath string
}{
ExtraOptions: extraFlags,
ExtraOptions: convertToFlags(extraOpts),
ContainerRuntime: k8s.ContainerRuntime,
KubeletPath: filepath.Join(binRoot(k8s.KubernetesVersion), "kubelet"),
}
if err := kubeletSystemdTemplate.Execute(&b, opts); err != nil {
return "", err
return nil, err
}
return b.String(), nil
return b.Bytes(), nil
}
// UpdateCluster updates the cluster
......@@ -499,32 +515,35 @@ func (k *Bootstrapper) UpdateCluster(cfg config.KubernetesConfig) error {
if err != nil {
return errors.Wrap(err, "generating kubelet config")
}
glog.Infof("kubelet %s config:\n%s", cfg.KubernetesVersion, kubeletCfg)
var files []assets.CopyableFile
files = copyConfig(cfg, files, kubeadmCfg, kubeletCfg)
kubeletService, err := NewKubeletService(cfg)
if err != nil {
return errors.Wrap(err, "generating kubelet service")
}
if err := downloadBinaries(cfg, k.c); err != nil {
glog.Infof("kubelet %s config:\n%s", cfg.KubernetesVersion, kubeletCfg)
// stop kubelet to avoid "Text File Busy" error
err = k.c.Run(`pgrep kubelet && sudo systemctl stop kubelet`)
if err != nil {
glog.Warningf("unable to stop kubelet: %s", err)
}
if err := transferBinaries(cfg, k.c); err != nil {
return errors.Wrap(err, "downloading binaries")
}
files := configFiles(cfg, kubeadmCfg, kubeletCfg, kubeletService)
if err := addAddons(&files, assets.GenerateTemplateData(cfg)); err != nil {
return errors.Wrap(err, "adding addons")
}
for _, f := range files {
if err := k.c.Copy(f); err != nil {
return errors.Wrapf(err, "copy")
}
}
err = k.c.Run(`
sudo systemctl daemon-reload &&
sudo systemctl start kubelet
`)
if err != nil {
if err := k.c.Run(`sudo systemctl daemon-reload && sudo systemctl start kubelet`); err != nil {
return errors.Wrap(err, "starting kubelet")
}
return nil
}
......@@ -547,21 +566,22 @@ func createExtraComponentConfig(extraOptions util.ExtraOptionSlice, version semv
return extraArgsSlice, nil
}
func generateConfig(k8s config.KubernetesConfig, r cruntime.Manager) (string, error) {
// generateConfig generates the kubeadm.yaml file
func generateConfig(k8s config.KubernetesConfig, r cruntime.Manager) ([]byte, error) {
version, err := ParseKubernetesVersion(k8s.KubernetesVersion)
if err != nil {
return "", errors.Wrap(err, "parsing kubernetes version")
return nil, errors.Wrap(err, "parsing kubernetes version")
}
// parses a map of the feature gates for kubeadm and component
kubeadmFeatureArgs, componentFeatureArgs, err := ParseFeatureArgs(k8s.FeatureGates)
if err != nil {
return "", errors.Wrap(err, "parses feature gate config for kubeadm and component")
return nil, errors.Wrap(err, "parses feature gate config for kubeadm and component")
}
extraComponentConfig, err := createExtraComponentConfig(k8s.ExtraOptions, version, componentFeatureArgs)
if err != nil {
return "", errors.Wrap(err, "generating extra component config for kubeadm")
return nil, errors.Wrap(err, "generating extra component config for kubeadm")
}
// In case of no port assigned, use util.APIServerPort
......@@ -585,13 +605,13 @@ func generateConfig(k8s config.KubernetesConfig, r cruntime.Manager) (string, er
FeatureArgs map[string]bool
NoTaintMaster bool
}{
CertDir: util.DefaultCertPath,
CertDir: constants.GuestCertsDir,
ServiceCIDR: util.DefaultServiceCIDR,
PodSubnet: k8s.ExtraOptions.Get("pod-network-cidr", Kubeadm),
AdvertiseAddress: k8s.NodeIP,
APIServerPort: nodePort,
KubernetesVersion: k8s.KubernetesVersion,
EtcdDataDir: "/data/minikube", //TODO(r2d4): change to something else persisted
EtcdDataDir: filepath.Join(constants.GuestPersistentDir, "etcd"),
NodeName: k8s.NodeName,
CRISocket: r.SocketPath(),
ImageRepository: k8s.ImageRepository,
......@@ -618,41 +638,62 @@ func generateConfig(k8s config.KubernetesConfig, r cruntime.Manager) (string, er
configTmpl = configTmplV1Beta1
}
if err := configTmpl.Execute(&b, opts); err != nil {
return "", err
return nil, err
}
return b.String(), nil
return b.Bytes(), nil
}
func copyConfig(cfg config.KubernetesConfig, files []assets.CopyableFile, kubeadmCfg string, kubeletCfg string) []assets.CopyableFile {
files = append(files,
assets.NewMemoryAssetTarget([]byte(kubeletService), constants.KubeletServiceFile, "0640"),
assets.NewMemoryAssetTarget([]byte(kubeletCfg), constants.KubeletSystemdConfFile, "0640"),
assets.NewMemoryAssetTarget([]byte(kubeadmCfg), constants.KubeadmConfigFile, "0640"))
// NewKubeletService returns a generated systemd unit file for the kubelet
func NewKubeletService(cfg config.KubernetesConfig) ([]byte, error) {
var b bytes.Buffer
opts := struct{ KubeletPath string }{KubeletPath: filepath.Join(binRoot(cfg.KubernetesVersion), "kubelet")}
if err := kubeletServiceTemplate.Execute(&b, opts); err != nil {
return nil, errors.Wrap(err, "template execute")
}
return b.Bytes(), nil
}
// configFiles returns configuration file assets
func configFiles(cfg config.KubernetesConfig, kubeadm []byte, kubelet []byte, kubeletSvc []byte) []assets.CopyableFile {
fs := []assets.CopyableFile{
assets.NewMemoryAssetTarget(kubeadm, yamlConfigPath, "0640"),
assets.NewMemoryAssetTarget(kubelet, constants.KubeletSystemdConfFile, "0640"),
assets.NewMemoryAssetTarget(kubeletSvc, constants.KubeletServiceFile, "0640"),
}
// Copy the default CNI config (k8s.conf), so that kubelet can successfully
// start a Pod in the case a user hasn't manually installed any CNI plugin
// and minikube was started with "--extra-config=kubelet.network-plugin=cni".
if cfg.EnableDefaultCNI {
files = append(files,
assets.NewMemoryAssetTarget([]byte(defaultCNIConfig), constants.DefaultCNIConfigPath, "0644"))
fs = append(fs, assets.NewMemoryAssetTarget([]byte(defaultCNIConfig), constants.DefaultCNIConfigPath, "0644"))
}
return fs
}
return files
// binDir returns the persistant path binaries are stored in
func binRoot(version string) string {
return filepath.Join(constants.GuestPersistentDir, "binaries", version)
}
func downloadBinaries(cfg config.KubernetesConfig, c command.Runner) error {
// invokeKubeadm returns the invocation command for Kubeadm
func invokeKubeadm(version string) string {
return fmt.Sprintf("sudo env PATH=%s:$PATH kubeadm", binRoot(version))
}
// transferBinaries transfers all required Kubernetes binaries
func transferBinaries(cfg config.KubernetesConfig, c command.Runner) error {
var g errgroup.Group
for _, bin := range constants.GetKubeadmCachedBinaries() {
bin := bin
for _, name := range constants.KubeadmBinaries {
name := name
g.Go(func() error {
path, err := machine.CacheBinary(bin, cfg.KubernetesVersion, "linux", runtime.GOARCH)
src, err := machine.CacheBinary(name, cfg.KubernetesVersion, "linux", runtime.GOARCH)
if err != nil {
return errors.Wrapf(err, "downloading %s", bin)
return errors.Wrapf(err, "downloading %s", name)
}
err = machine.CopyBinary(c, bin, path)
if err != nil {
return errors.Wrapf(err, "copying %s", bin)
dst := filepath.Join(binRoot(cfg.KubernetesVersion), name)
if err := machine.CopyBinary(c, src, dst); err != nil {
return errors.Wrapf(err, "copybinary %s -> %s", src, dst)
}
return nil
})
......
......@@ -151,24 +151,24 @@ evictionHard:
imagefs.available: "0%"
`))
var kubeletSystemdTemplate = template.Must(template.New("kubeletSystemdTemplate").Parse(`
[Unit]
// kubeletSystemdTemplate hosts the override kubelet flags, written to constants.KubeletSystemdConfFile
var kubeletSystemdTemplate = template.Must(template.New("kubeletSystemdTemplate").Parse(`[Unit]
{{if or (eq .ContainerRuntime "cri-o") (eq .ContainerRuntime "cri")}}Wants=crio.service{{else if eq .ContainerRuntime "containerd"}}Wants=containerd.service{{else}}Wants=docker.socket{{end}}
[Service]
ExecStart=
ExecStart=/usr/bin/kubelet{{if .ExtraOptions}} {{.ExtraOptions}}{{end}}
ExecStart={{.KubeletPath}}{{if .ExtraOptions}} {{.ExtraOptions}}{{end}}
[Install]
`))
const kubeletService = `
[Unit]
// kubeletServiceTemplate is the base kubelet systemd template, written to constanst.KubeletServiceFile
var kubeletServiceTemplate = template.Must(template.New("kubeletServiceTemplate").Parse(`[Unit]
Description=kubelet: The Kubernetes Node Agent
Documentation=http://kubernetes.io/docs/
[Service]
ExecStart=/usr/bin/kubelet
ExecStart={{.KubeletPath}}
Restart=always
StartLimitInterval=0
# Tuned for local dev: faster than upstream default (10s), but slower than systemd default (100ms)
......@@ -176,7 +176,7 @@ RestartSec=600ms
[Install]
WantedBy=multi-user.target
`
`))
// printMapInOrder sorts the keys and prints the map in order, combining key
// value pairs with the separator character
......
......@@ -241,7 +241,7 @@ var versionSpecificOpts = []VersionedExtraOption{
NewUnversionedOption(Kubelet, "hostname-override", constants.DefaultNodeName),
// System pods args
NewUnversionedOption(Kubelet, "pod-manifest-path", "/etc/kubernetes/manifests"),
NewUnversionedOption(Kubelet, "pod-manifest-path", constants.GuestManifestsDir),
{
Option: util.ExtraOption{
Component: Kubelet,
......@@ -257,7 +257,7 @@ var versionSpecificOpts = []VersionedExtraOption{
// Auth args
NewUnversionedOption(Kubelet, "authorization-mode", "Webhook"),
NewUnversionedOption(Kubelet, "client-ca-file", path.Join(util.DefaultCertPath, "ca.crt")),
NewUnversionedOption(Kubelet, "client-ca-file", path.Join(constants.GuestCertsDir, "ca.crt")),
// Cgroup args
NewUnversionedOption(Kubelet, "cgroup-driver", "cgroupfs"),
......
......@@ -21,11 +21,13 @@ import (
"fmt"
"io"
"path"
"path/filepath"
"sync"
"github.com/golang/glog"
"github.com/pkg/errors"
"golang.org/x/crypto/ssh"
"golang.org/x/sync/errgroup"
"k8s.io/minikube/pkg/minikube/assets"
"k8s.io/minikube/pkg/util"
)
......@@ -152,14 +154,6 @@ func (s *SSHRunner) CombinedOutput(cmd string) (string, error) {
// Copy copies a file to the remote over SSH.
func (s *SSHRunner) Copy(f assets.CopyableFile) error {
deleteCmd := fmt.Sprintf("sudo rm -f %s", path.Join(f.GetTargetDir(), f.GetTargetName()))
mkdirCmd := fmt.Sprintf("sudo mkdir -p %s", f.GetTargetDir())
for _, cmd := range []string{deleteCmd, mkdirCmd} {
if err := s.Run(cmd); err != nil {
return errors.Wrapf(err, "pre-copy")
}
}
sess, err := s.c.NewSession()
if err != nil {
return errors.Wrap(err, "NewSession")
......@@ -170,40 +164,38 @@ func (s *SSHRunner) Copy(f assets.CopyableFile) error {
return errors.Wrap(err, "StdinPipe")
}
// The scpcmd below *should not* return until all data is copied and the
// StdinPipe is closed. But let's use a WaitGroup to make it expicit.
var wg sync.WaitGroup
wg.Add(1)
var ierr error
// StdinPipe is closed. But let's use errgroup to make it expicit.
var g errgroup.Group
var copied int64
dst := filepath.Join(path.Join(f.GetTargetDir(), f.GetTargetName()))
glog.Infof("Transferring %d bytes to %s", f.GetLength(), dst)
go func() {
defer wg.Done()
g.Go(func() error {
defer w.Close()
glog.Infof("Transferring %d bytes to %s", f.GetLength(), f.GetTargetName())
header := fmt.Sprintf("C%s %d %s\n", f.GetPermissions(), f.GetLength(), f.GetTargetName())
fmt.Fprint(w, header)
if f.GetLength() == 0 {
glog.Warningf("%s is a 0 byte asset!", f.GetTargetName())
fmt.Fprint(w, "\x00")
return
return nil
}
copied, ierr = io.Copy(w, f)
if copied != int64(f.GetLength()) {
glog.Warningf("%s: expected to copy %d bytes, but copied %d instead", f.GetTargetName(), f.GetLength(), copied)
} else {
glog.Infof("%s: copied %d bytes", f.GetTargetName(), copied)
copied, err = io.Copy(w, f)
if err != nil {
return errors.Wrap(err, "io.Copy")
}
if ierr != nil {
glog.Errorf("io.Copy failed: %v", ierr)
if copied != int64(f.GetLength()) {
return fmt.Errorf("%s: expected to copy %d bytes, but copied %d instead", f.GetTargetName(), f.GetLength(), copied)
}
glog.Infof("%s: copied %d bytes", f.GetTargetName(), copied)
fmt.Fprint(w, "\x00")
}()
return nil
})
_, err = sess.CombinedOutput(fmt.Sprintf("sudo scp -t %s", f.GetTargetDir()))
scp := fmt.Sprintf("sudo mkdir -p %s && sudo scp -t %s", f.GetTargetDir(), f.GetTargetDir())
out, err := sess.CombinedOutput(scp)
if err != nil {
return err
return fmt.Errorf("%s: %s\noutput: %s", scp, err, out)
}
wg.Wait()
return ierr
return g.Wait()
}
......@@ -208,12 +208,6 @@ func GetProfilePath(profile string, miniHome ...string) string {
return filepath.Join(miniPath, "profiles", profile)
}
// AddonsPath is the default path of the addons configuration
const AddonsPath = "/etc/kubernetes/addons"
// FilesPath is the default path of files
const FilesPath = "/files"
const (
// KubeletServiceFile is the path to the kubelet systemd service
KubeletServiceFile = "/lib/systemd/system/kubelet.service"
......@@ -223,9 +217,17 @@ const (
KubeadmConfigFile = "/var/lib/kubeadm.yaml"
// DefaultCNIConfigPath is the path to the CNI configuration
DefaultCNIConfigPath = "/etc/cni/net.d/k8s.conf"
)
// GuestAddonsDir is the default path of the addons configuration
GuestAddonsDir = "/etc/kubernetes/addons"
// GuestManifestsDir is where the kubelet should look for static Pod manifests
GuestManifestsDir = "/etc/kubernetes/manifests"
// PersistentDir is the path where persistant data should be stored within the VM (not tmpfs)
GuestPersistentDir = "/data/minikube"
// GuestEphemeralDir is the path where ephemeral data should be stored within the VM
GuestEphemeralDir = "/var/tmp/minikube"
// GuestCertsDir are where Kubernetes certificates are kept on the guest
GuestCertsDir = "/data/minikube/certs"
const (
// DefaultUfsPort is the default port of UFS
DefaultUfsPort = "5640"
// DefaultUfsDebugLvl is the default debug level of UFS
......@@ -236,6 +238,12 @@ const (
DefaultMsize = 262144
// DefaultMountVersion is the default 9p version to use for mount
DefaultMountVersion = "9p2000.L"
// IsMinikubeChildProcess is the name of "is minikube child process" variable
IsMinikubeChildProcess = "IS_MINIKUBE_CHILD_PROCESS"
// FileScheme is the file scheme
FileScheme = "file"
)
// ImageRepositories contains all known image repositories
......@@ -254,16 +262,8 @@ func GetKubernetesReleaseURLSHA1(binaryName, version, osName, archName string) s
return fmt.Sprintf("%s.sha1", GetKubernetesReleaseURL(binaryName, version, osName, archName))
}
// IsMinikubeChildProcess is the name of "is minikube child process" variable
const IsMinikubeChildProcess = "IS_MINIKUBE_CHILD_PROCESS"
// FileScheme is the file scheme
const FileScheme = "file"
// GetKubeadmCachedBinaries gets the binaries to cache for kubeadm
func GetKubeadmCachedBinaries() []string {
return []string{"kubelet", "kubeadm"}
}
// KubeadmBinaries are Kubernetes release binaries required for kubeadm
var KubeadmBinaries = []string{"kubelet", "kubeadm"}
// GetKubeadmCachedImages gets the images to cache for kubeadm for a version
func GetKubeadmCachedImages(imageRepository string, kubernetesVersionStr string) (string, []string) {
......
......@@ -34,7 +34,7 @@ import (
)
// rootCauseRe is a regular expression that matches known failure root causes
var rootCauseRe = regexp.MustCompile(`^error: |eviction manager: pods.* evicted|unknown flag: --|forbidden.*no providers available|eviction manager:.*evicted|tls: bad certificate`)
var rootCauseRe = regexp.MustCompile(`^error: |eviction manager: pods.* evicted|unknown flag: --|forbidden.*no providers available|eviction manager:.*evicted|tls: bad certificate|kubelet.*no API client|kubelet.*No api server`)
// ignoreRe is a regular expression that matches spurious errors to not surface
var ignoreCauseRe = regexp.MustCompile("error: no objects passed to apply")
......
......@@ -20,6 +20,7 @@ import (
"crypto"
"os"
"path"
"path/filepath"
"runtime"
"github.com/golang/glog"
......@@ -90,9 +91,9 @@ func CacheBinary(binary, version, osName, archName string) (string, error) {
return targetFilepath, nil
}
// CopyBinary copies previously cached binaries into the path
func CopyBinary(cr command.Runner, binary, path string) error {
f, err := assets.NewFileAsset(path, "/usr/bin", binary, "0755")
// CopyBinary copies a locally cached binary to the guest VM
func CopyBinary(cr command.Runner, src string, dest string) error {
f, err := assets.NewFileAsset(src, filepath.Dir(dest), filepath.Base(dest), "0755")
if err != nil {
return errors.Wrap(err, "new file asset")
}
......
......@@ -41,7 +41,8 @@ import (
"k8s.io/minikube/pkg/minikube/cruntime"
)
const tempLoadDir = "/tmp"
// loadRoot is where images should be loaded from within the guest VM
var loadRoot = filepath.Join(constants.GuestPersistentDir, "images")
var getWindowsVolumeName = getWindowsVolumeNameCmd
......@@ -86,6 +87,9 @@ func CacheImages(images []string, cacheDir string) error {
// LoadImages loads previously cached images into the container runtime
func LoadImages(cmd command.Runner, images []string, cacheDir string) error {
glog.Infof("LoadImages start: %s", images)
defer glog.Infof("LoadImages end")
var g errgroup.Group
// Load profile cluster config from file
cc, err := config.Load()
......@@ -97,7 +101,7 @@ func LoadImages(cmd command.Runner, images []string, cacheDir string) error {
g.Go(func() error {
src := filepath.Join(cacheDir, image)
src = sanitizeCacheDir(src)
if err := loadImageFromCache(cmd, cc.KubernetesConfig, src); err != nil {
if err := transferAndLoadImage(cmd, cc.KubernetesConfig, src); err != nil {
glog.Warningf("Failed to load %s: %v", src, err)
return errors.Wrapf(err, "loading image %s", src)
}
......@@ -194,15 +198,15 @@ func getWindowsVolumeNameCmd(d string) (string, error) {
return vname, nil
}
// loadImageFromCache loads a single image from the cache
func loadImageFromCache(cr command.Runner, k8s config.KubernetesConfig, src string) error {
// transferAndLoadImage transfers and loads a single image from the cache
func transferAndLoadImage(cr command.Runner, k8s config.KubernetesConfig, src string) error {
glog.Infof("Loading image from cache: %s", src)
filename := filepath.Base(src)
if _, err := os.Stat(src); err != nil {
return err
}
dst := path.Join(tempLoadDir, filename)
f, err := assets.NewFileAsset(src, tempLoadDir, filename, "0777")
dst := path.Join(loadRoot, filename)
f, err := assets.NewFileAsset(src, loadRoot, filename, "0644")
if err != nil {
return errors.Wrapf(err, "creating copyable file asset: %s", filename)
}
......@@ -222,9 +226,6 @@ func loadImageFromCache(cr command.Runner, k8s config.KubernetesConfig, src stri
return errors.Wrapf(err, "%s load %s", r.Name(), dst)
}
if err := cr.Run("sudo rm -rf " + dst); err != nil {
return errors.Wrap(err, "deleting temp docker image location")
}
glog.Infof("Successfully loaded image %s from cache", src)
return nil
}
......
......@@ -26,7 +26,6 @@ import (
const (
APIServerPort = 8443
DefaultMinikubeDirectory = "/var/lib/minikube"
DefaultCertPath = DefaultMinikubeDirectory + "/certs/"
DefaultKubeConfigPath = DefaultMinikubeDirectory + "/kubeconfig"
DefaultDNSDomain = "cluster.local"
DefaultServiceCIDR = "10.96.0.0/12"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册