Merge branch 'master' into driver-fallback
commit
aee3c1d4b8
|
|
@ -19,6 +19,8 @@ jobs:
|
|||
run : |
|
||||
make minikube-linux-amd64
|
||||
make e2e-linux-amd64
|
||||
make minikube-windows-amd64.exe
|
||||
make e2e-windows-amd64.exe
|
||||
cp -r test/integration/testdata ./out
|
||||
whoami
|
||||
echo github ref $GITHUB_REF
|
||||
|
|
@ -117,7 +119,7 @@ jobs:
|
|||
with:
|
||||
name: minikube_binaries
|
||||
- name: Run Integration Test
|
||||
continue-on-error: true
|
||||
continue-on-error: false
|
||||
# bash {0} to allow test to continue to next step. in case of
|
||||
shell: bash {0}
|
||||
run: |
|
||||
|
|
@ -251,6 +253,70 @@ jobs:
|
|||
numPass=$(echo $STAT | jq '.NumberOfPass')
|
||||
echo "*** $numPass Passed ***"
|
||||
if [ "$numFail" -gt 0 ];then echo "*** $numFail Failed ***";exit 2;fi
|
||||
docker_on_windows:
|
||||
needs: [build_minikube]
|
||||
env:
|
||||
TIME_ELAPSED: time
|
||||
JOB_NAME: "Docker_on_windows"
|
||||
COMMIT_STATUS: ""
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Docker Info
|
||||
shell: bash
|
||||
run: |
|
||||
docker info || true
|
||||
docker version || true
|
||||
docker ps || true
|
||||
- name: Download gopogh
|
||||
run: |
|
||||
curl -LO https://github.com/medyagh/gopogh/releases/download/v0.1.16/gopogh.exe
|
||||
shell: bash
|
||||
- name: Download binaries
|
||||
uses: actions/download-artifact@v1
|
||||
with:
|
||||
name: minikube_binaries
|
||||
- name: run integration test
|
||||
continue-on-error: true
|
||||
run: |
|
||||
set +euo pipefail
|
||||
mkdir -p report
|
||||
mkdir -p testhome
|
||||
START_TIME=$(date -u +%s)
|
||||
KUBECONFIG=$(pwd)/testhome/kubeconfig MINIKUBE_HOME=$(pwd)/testhome minikube_binaries/e2e-windows-amd64.exe -minikube-start-args=--vm-driver=docker -binary=minikube_binaries/minikube-windows-amd64.exe -test.v -test.timeout=65m 2>&1 | tee ./report/testout.txt
|
||||
END_TIME=$(date -u +%s)
|
||||
TIME_ELAPSED=$(($END_TIME-$START_TIME))
|
||||
min=$((${TIME_ELAPSED}/60))
|
||||
sec=$((${TIME_ELAPSED}%60))
|
||||
TIME_ELAPSED="${min} min $sec seconds"
|
||||
echo ::set-env name=TIME_ELAPSED::${TIME_ELAPSED}
|
||||
shell: bash
|
||||
- name: Generate html report
|
||||
run: |
|
||||
go tool test2json -t < ./report/testout.txt > ./report/testout.json || true
|
||||
STAT=$(${GITHUB_WORKSPACE}/gopogh.exe -in ./report/testout.json -out ./report/testout.html -name " $GITHUB_REF" -repo "${JOB_NAME} ${GITHUB_REF} ${GITHUB_REPOSITORY}" -details "${GITHUB_SHA}") || true
|
||||
echo status: ${STAT}
|
||||
FailNum=$(echo $STAT | jq '.NumberOfFail')
|
||||
TestsNum=$(echo $STAT | jq '.NumberOfTests')
|
||||
GOPOGH_RESULT="${JOB_NAME} : completed with ${FailNum} / ${TestsNum} failures in ${TIME_ELAPSED}"
|
||||
echo ::set-env name=GOPOGH_RESULT::${GOPOGH_RESULT}
|
||||
echo ::set-env name=STAT::${STAT}
|
||||
shell: bash
|
||||
- uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: docker_on_windows
|
||||
path: report
|
||||
- name: The End Result
|
||||
run: |
|
||||
echo ${GOPOGH_RESULT}
|
||||
numFail=$(echo $STAT | jq '.NumberOfFail')
|
||||
echo "----------------${numFail} Failures----------------------------"
|
||||
echo $STAT | jq '.FailedTests' || true
|
||||
echo "--------------------------------------------"
|
||||
numPass=$(echo $STAT | jq '.NumberOfPass')
|
||||
echo "*** $numPass Passed ***"
|
||||
if [ "$numFail" -gt 0 ];then echo "*** $numFail Failed ***";exit 2;fi
|
||||
shell: bash
|
||||
none_ubuntu16_04:
|
||||
needs: [build_minikube]
|
||||
env:
|
||||
|
|
@ -521,6 +587,15 @@ jobs:
|
|||
run: |
|
||||
mkdir -p all_reports
|
||||
cp -r docker_ubuntu_18_04 ./all_reports/
|
||||
- name: download results docker_on_windows
|
||||
uses: actions/download-artifact@v1
|
||||
with:
|
||||
name: docker_on_windows
|
||||
- name: cp to all_report
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p all_reports
|
||||
cp -r docker_on_windows ./all_reports/
|
||||
- name: Download Results none_ubuntu16_04
|
||||
uses: actions/download-artifact@v1
|
||||
with:
|
||||
|
|
|
|||
|
|
@ -62,6 +62,6 @@ minikube is a Kubernetes [#sig-cluster-lifecycle](https://github.com/kubernetes/
|
|||
* [minikube-dev mailing list](https://groups.google.com/forum/#!forum/minikube-dev)
|
||||
* [Bi-weekly office hours, Mondays @ 11am PST](https://tinyurl.com/minikube-oh)
|
||||
|
||||
* [Contributing](https://minikube.sigs.k8s.io/docs/contributing/)
|
||||
* [Development Roadmap](https://minikube.sigs.k8s.io/docs/contributing/roadmap/)
|
||||
* [Contributing](https://minikube.sigs.k8s.io/docs/contrib/)
|
||||
* [Development Roadmap](https://minikube.sigs.k8s.io/docs/contrib/roadmap/)
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ import (
|
|||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
|
|
@ -38,6 +37,7 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/mustload"
|
||||
"k8s.io/minikube/pkg/minikube/out"
|
||||
"k8s.io/minikube/pkg/minikube/shell"
|
||||
"k8s.io/minikube/pkg/minikube/sysinit"
|
||||
)
|
||||
|
||||
var dockerEnvTmpl = fmt.Sprintf("{{ .Prefix }}%s{{ .Delimiter }}{{ .DockerTLSVerify }}{{ .Suffix }}{{ .Prefix }}%s{{ .Delimiter }}{{ .DockerHost }}{{ .Suffix }}{{ .Prefix }}%s{{ .Delimiter }}{{ .DockerCertPath }}{{ .Suffix }}{{ .Prefix }}%s{{ .Delimiter }}{{ .MinikubeDockerdProfile }}{{ .Suffix }}{{ if .NoProxyVar }}{{ .Prefix }}{{ .NoProxyVar }}{{ .Delimiter }}{{ .NoProxyValue }}{{ .Suffix }}{{end}}{{ .UsageHint }}", constants.DockerTLSVerifyEnv, constants.DockerHostEnv, constants.DockerCertPathEnv, constants.MinikubeActiveDockerdEnv)
|
||||
|
|
@ -116,9 +116,7 @@ func (EnvNoProxyGetter) GetNoProxyVar() (string, string) {
|
|||
|
||||
// isDockerActive checks if Docker is active
|
||||
func isDockerActive(r command.Runner) bool {
|
||||
c := exec.Command("sudo", "systemctl", "is-active", "--quiet", "service", "docker")
|
||||
_, err := r.RunCmd(c)
|
||||
return err == nil
|
||||
return sysinit.New(r).Active("docker")
|
||||
}
|
||||
|
||||
// dockerEnvCmd represents the docker-env command
|
||||
|
|
|
|||
|
|
@ -668,7 +668,7 @@ func validateUser(drvName string) {
|
|||
useForce := viper.GetBool(force)
|
||||
|
||||
if driver.NeedsRoot(drvName) && u.Uid != "0" && !useForce {
|
||||
exit.WithCodeT(exit.Permissions, `The "{{.driver_name}}" driver requires root privileges. Please run minikube using 'sudo minikube --driver={{.driver_name}}'.`, out.V{"driver_name": drvName})
|
||||
exit.WithCodeT(exit.Permissions, `The "{{.driver_name}}" driver requires root privileges. Please run minikube using 'sudo minikube start --driver={{.driver_name}}'.`, out.V{"driver_name": drvName})
|
||||
}
|
||||
|
||||
if driver.NeedsRoot(drvName) || u.Uid != "0" {
|
||||
|
|
|
|||
|
|
@ -208,15 +208,9 @@ func status(api libmachine.API, cc config.ClusterConfig, n config.Node) (*Status
|
|||
return st, err
|
||||
}
|
||||
|
||||
stk, err := kverify.KubeletStatus(cr)
|
||||
glog.Infof("%s kubelet status = %s (err=%v)", name, stk, err)
|
||||
|
||||
if err != nil {
|
||||
glog.Warningf("kubelet err: %v", err)
|
||||
st.Kubelet = state.Error.String()
|
||||
} else {
|
||||
st.Kubelet = stk.String()
|
||||
}
|
||||
stk := kverify.KubeletStatus(cr)
|
||||
glog.Infof("%s kubelet status = %s", name, stk)
|
||||
st.Kubelet = stk.String()
|
||||
|
||||
// Early exit for regular nodes
|
||||
if !controlPlane {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/driver"
|
||||
"k8s.io/minikube/pkg/minikube/localpath"
|
||||
"k8s.io/minikube/pkg/minikube/sysinit"
|
||||
)
|
||||
|
||||
func generateTarball(kubernetesVersion, containerRuntime, tarballFilename string) error {
|
||||
|
|
@ -86,7 +87,9 @@ func generateTarball(kubernetesVersion, containerRuntime, tarballFilename string
|
|||
KubernetesVersion: kubernetesVersion,
|
||||
}
|
||||
runner := command.NewKICRunner(profile, driver.OCIBinary)
|
||||
if err := bsutil.TransferBinaries(kcfg, runner); err != nil {
|
||||
sm := sysinit.New(runner)
|
||||
|
||||
if err := bsutil.TransferBinaries(kcfg, runner, sm); err != nil {
|
||||
return errors.Wrap(err, "transferring k8s binaries")
|
||||
}
|
||||
// Create image tarball
|
||||
|
|
|
|||
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
Copyright 2020 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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 hyperkit
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestExtractFile(t *testing.T) {
|
||||
testDir, err := ioutil.TempDir(os.TempDir(), "")
|
||||
if nil != err {
|
||||
return
|
||||
}
|
||||
defer os.Remove(testDir)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
isoPath string
|
||||
srcPath string
|
||||
destPath string
|
||||
expectedError bool
|
||||
}{
|
||||
{
|
||||
name: "all is right",
|
||||
isoPath: "iso_test.iso",
|
||||
srcPath: "/test1.txt",
|
||||
destPath: testDir + "/test1.txt",
|
||||
expectedError: false,
|
||||
},
|
||||
{
|
||||
name: "isoPath is error",
|
||||
isoPath: "tests.iso",
|
||||
srcPath: "/test1.txt",
|
||||
destPath: testDir + "/test1.txt",
|
||||
expectedError: true,
|
||||
},
|
||||
{
|
||||
name: "srcPath is empty",
|
||||
isoPath: "iso_tests.iso",
|
||||
srcPath: "",
|
||||
destPath: testDir + "/test1.txt",
|
||||
expectedError: true,
|
||||
},
|
||||
{
|
||||
name: "srcPath is error",
|
||||
isoPath: "iso_tests.iso",
|
||||
srcPath: "/t1.txt",
|
||||
destPath: testDir + "/test1.txt",
|
||||
expectedError: true,
|
||||
},
|
||||
{
|
||||
name: "destPath is empty",
|
||||
isoPath: "iso_test.iso",
|
||||
srcPath: "/test1.txt",
|
||||
destPath: "",
|
||||
expectedError: true,
|
||||
},
|
||||
{
|
||||
name: "find files in a folder",
|
||||
isoPath: "./iso_test.iso",
|
||||
srcPath: "/test2/test2.txt",
|
||||
destPath: testDir + "/test2.txt",
|
||||
expectedError: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := ExtractFile(tt.isoPath, tt.srcPath, tt.destPath)
|
||||
if (nil != err) != tt.expectedError {
|
||||
t.Errorf("expectedError = %v, get = %v", tt.expectedError, err)
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
|
@ -22,6 +22,7 @@ import (
|
|||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
|
|
@ -37,7 +38,7 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/cruntime"
|
||||
"k8s.io/minikube/pkg/minikube/download"
|
||||
"k8s.io/minikube/pkg/minikube/kubelet"
|
||||
"k8s.io/minikube/pkg/minikube/sysinit"
|
||||
)
|
||||
|
||||
// Driver represents a kic driver https://minikube.sigs.k8s.io/docs/reference/drivers/docker
|
||||
|
|
@ -112,6 +113,28 @@ func (d *Driver) Create() error {
|
|||
}
|
||||
}
|
||||
|
||||
if err := oci.PrepareContainerNode(params); err != nil {
|
||||
return errors.Wrap(err, "setting up container node")
|
||||
}
|
||||
|
||||
var waitForPreload sync.WaitGroup
|
||||
waitForPreload.Add(1)
|
||||
go func() {
|
||||
defer waitForPreload.Done()
|
||||
// If preload doesn't exist, don't bother extracting tarball to volume
|
||||
if !download.PreloadExists(d.NodeConfig.KubernetesVersion, d.NodeConfig.ContainerRuntime) {
|
||||
return
|
||||
}
|
||||
t := time.Now()
|
||||
glog.Infof("Starting extracting preloaded images to volume")
|
||||
// Extract preloaded images to container
|
||||
if err := oci.ExtractTarballToVolume(download.TarballPath(d.NodeConfig.KubernetesVersion, d.NodeConfig.ContainerRuntime), params.Name, BaseImage); err != nil {
|
||||
glog.Infof("Unable to extract preloaded tarball to volume: %v", err)
|
||||
} else {
|
||||
glog.Infof("duration metric: took %f seconds to extract preloaded images to volume", time.Since(t).Seconds())
|
||||
}
|
||||
}()
|
||||
|
||||
if err := oci.CreateContainerNode(params); err != nil {
|
||||
return errors.Wrap(err, "create kic node")
|
||||
}
|
||||
|
|
@ -120,19 +143,7 @@ func (d *Driver) Create() error {
|
|||
return errors.Wrap(err, "prepare kic ssh")
|
||||
}
|
||||
|
||||
// If preload doesn't exist, don't bother extracting tarball to volume
|
||||
if !download.PreloadExists(d.NodeConfig.KubernetesVersion, d.NodeConfig.ContainerRuntime) {
|
||||
return nil
|
||||
}
|
||||
t := time.Now()
|
||||
glog.Infof("Starting extracting preloaded images to volume")
|
||||
// Extract preloaded images to container
|
||||
if err := oci.ExtractTarballToVolume(download.TarballPath(d.NodeConfig.KubernetesVersion, d.NodeConfig.ContainerRuntime), params.Name, BaseImage); err != nil {
|
||||
glog.Infof("Unable to extract preloaded tarball to volume: %v", err)
|
||||
} else {
|
||||
glog.Infof("Took %f seconds to extract preloaded images to volume", time.Since(t).Seconds())
|
||||
}
|
||||
|
||||
waitForPreload.Wait()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -245,7 +256,7 @@ func (d *Driver) GetState() (state.State, error) {
|
|||
func (d *Driver) Kill() error {
|
||||
// on init this doesn't get filled when called from cmd
|
||||
d.exec = command.NewKICRunner(d.MachineName, d.OCIBinary)
|
||||
if err := kubelet.ForceStop(d.exec); err != nil {
|
||||
if err := sysinit.New(d.exec).ForceStop("kubelet"); err != nil {
|
||||
glog.Warningf("couldn't force stop kubelet. will continue with kill anyways: %v", err)
|
||||
}
|
||||
cmd := exec.Command(d.NodeConfig.OCIBinary, "kill", d.MachineName)
|
||||
|
|
@ -318,9 +329,9 @@ func (d *Driver) Stop() error {
|
|||
d.exec = command.NewKICRunner(d.MachineName, d.OCIBinary)
|
||||
// docker does not send right SIG for systemd to know to stop the systemd.
|
||||
// to avoid bind address be taken on an upgrade. more info https://github.com/kubernetes/minikube/issues/7171
|
||||
if err := kubelet.Stop(d.exec); err != nil {
|
||||
if err := sysinit.New(d.exec).Stop("kubelet"); err != nil {
|
||||
glog.Warningf("couldn't stop kubelet. will continue with stop anyways: %v", err)
|
||||
if err := kubelet.ForceStop(d.exec); err != nil {
|
||||
if err := sysinit.New(d.exec).ForceStop("kubelet"); err != nil {
|
||||
glog.Warningf("couldn't force stop kubelet. will continue with stop anyways: %v", err)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,6 +84,19 @@ func DeleteContainer(ociBin string, name string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// PrepareContainerNode sets up the container node befpre CreateContainerNode is caleld
|
||||
// for the docker runtime, it creates a docker volume which will be mounted into kic
|
||||
func PrepareContainerNode(p CreateParams) error {
|
||||
if p.OCIBinary != Docker {
|
||||
return nil
|
||||
}
|
||||
if err := createDockerVolume(p.Name, p.Name); err != nil {
|
||||
return errors.Wrapf(err, "creating volume for %s container", p.Name)
|
||||
}
|
||||
glog.Infof("Successfully created a docker volume %s", p.Name)
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateContainerNode creates a new container node
|
||||
func CreateContainerNode(p CreateParams) error {
|
||||
runArgs := []string{
|
||||
|
|
@ -122,10 +135,6 @@ func CreateContainerNode(p CreateParams) error {
|
|||
runArgs = append(runArgs, "--volume", fmt.Sprintf("%s:/var:exec", hostVarVolPath))
|
||||
}
|
||||
if p.OCIBinary == Docker {
|
||||
if err := createDockerVolume(p.Name, p.Name); err != nil {
|
||||
return errors.Wrapf(err, "creating volume for %s container", p.Name)
|
||||
}
|
||||
glog.Infof("Successfully created a docker volume %s", p.Name)
|
||||
runArgs = append(runArgs, "--volume", fmt.Sprintf("%s:/var", p.Name))
|
||||
// setting resource limit in privileged mode is only supported by docker
|
||||
// podman error: "Error: invalid configuration, cannot set resources with rootless containers not using cgroups v2 unified mode"
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/cruntime"
|
||||
"k8s.io/minikube/pkg/minikube/kubeconfig"
|
||||
"k8s.io/minikube/pkg/minikube/kubelet"
|
||||
"k8s.io/minikube/pkg/minikube/sysinit"
|
||||
"k8s.io/minikube/pkg/minikube/vmpath"
|
||||
)
|
||||
|
||||
|
|
@ -142,12 +142,12 @@ func (d *Driver) GetState() (state.State, error) {
|
|||
return state.Running, nil
|
||||
}
|
||||
|
||||
return kverify.KubeletStatus(d.exec)
|
||||
return kverify.KubeletStatus(d.exec), nil
|
||||
}
|
||||
|
||||
// Kill stops a host forcefully, including any containers that we are managing.
|
||||
func (d *Driver) Kill() error {
|
||||
if err := kubelet.ForceStop(d.exec); err != nil {
|
||||
if err := sysinit.New(d.exec).ForceStop("kubelet"); err != nil {
|
||||
glog.Warningf("couldn't force stop kubelet. will continue with kill anyways: %v", err)
|
||||
}
|
||||
|
||||
|
|
@ -211,9 +211,9 @@ func (d *Driver) Start() error {
|
|||
|
||||
// Stop a host gracefully, including any containers that we are managing.
|
||||
func (d *Driver) Stop() error {
|
||||
if err := kubelet.Stop(d.exec); err != nil {
|
||||
if err := sysinit.New(d.exec).Stop("kubelet"); err != nil {
|
||||
glog.Warningf("couldn't stop kubelet. will continue with stop anyways: %v", err)
|
||||
if err := kubelet.ForceStop(d.exec); err != nil {
|
||||
if err := sysinit.New(d.exec).ForceStop("kubelet"); err != nil {
|
||||
glog.Warningf("couldn't force stop kubelet. will continue with stop anyways: %v", err)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ type Bootstrapper interface {
|
|||
// LogCommands returns a map of log type to a command which will display that log.
|
||||
LogCommands(config.ClusterConfig, LogOptions) map[string]string
|
||||
SetupCerts(config.KubernetesConfig, config.Node) error
|
||||
GetKubeletStatus() (string, error)
|
||||
GetAPIServerStatus(string, int) (string, error)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,11 +32,12 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/download"
|
||||
"k8s.io/minikube/pkg/minikube/machine"
|
||||
"k8s.io/minikube/pkg/minikube/sysinit"
|
||||
"k8s.io/minikube/pkg/minikube/vmpath"
|
||||
)
|
||||
|
||||
// TransferBinaries transfers all required Kubernetes binaries
|
||||
func TransferBinaries(cfg config.KubernetesConfig, c command.Runner) error {
|
||||
func TransferBinaries(cfg config.KubernetesConfig, c command.Runner, sm sysinit.Manager) error {
|
||||
ok, err := binariesExist(cfg, c)
|
||||
if err == nil && ok {
|
||||
glog.Info("Found k8s binaries, skipping transfer")
|
||||
|
|
@ -50,11 +51,6 @@ func TransferBinaries(cfg config.KubernetesConfig, c command.Runner) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// stop kubelet to avoid "Text File Busy" error
|
||||
if _, err := c.RunCmd(exec.Command("/bin/bash", "-c", "pgrep kubelet && sudo systemctl stop kubelet")); err != nil {
|
||||
glog.Warningf("unable to stop kubelet: %s", err)
|
||||
}
|
||||
|
||||
var g errgroup.Group
|
||||
for _, name := range constants.KubernetesReleaseBinaries {
|
||||
name := name
|
||||
|
|
@ -64,6 +60,12 @@ func TransferBinaries(cfg config.KubernetesConfig, c command.Runner) error {
|
|||
return errors.Wrapf(err, "downloading %s", name)
|
||||
}
|
||||
|
||||
if name == "kubelet" {
|
||||
if err := sm.ForceStop("kubelet"); err != nil {
|
||||
glog.Errorf("unable to stop kubelet: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
dst := path.Join(dir, name)
|
||||
if err := machine.CopyBinary(c, src, dst); err != nil {
|
||||
return errors.Wrapf(err, "copybinary %s -> %s", src, dst)
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@ package bsutil
|
|||
import (
|
||||
"path"
|
||||
|
||||
"k8s.io/minikube/pkg/minikube/assets"
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/vmpath"
|
||||
)
|
||||
|
||||
|
|
@ -35,20 +33,8 @@ const (
|
|||
KubeletServiceFile = "/lib/systemd/system/kubelet.service"
|
||||
// KubeletSystemdConfFile is config for the systemd kubelet.service
|
||||
KubeletSystemdConfFile = "/etc/systemd/system/kubelet.service.d/10-kubeadm.conf"
|
||||
// InitRestartWrapper is ...
|
||||
InitRestartWrapper = "/etc/init.d/.restart_wrapper.sh"
|
||||
// KubeletInitPath is where Sys-V style init script is installed
|
||||
KubeletInitPath = "/etc/init.d/kubelet"
|
||||
)
|
||||
|
||||
// ConfigFileAssets returns configuration file assets
|
||||
func ConfigFileAssets(cfg config.KubernetesConfig, kubeadm []byte, kubelet []byte, kubeletSvc []byte, defaultCNIConfig []byte) []assets.CopyableFile {
|
||||
fs := []assets.CopyableFile{
|
||||
assets.NewMemoryAssetTarget(kubeadm, KubeadmYamlPath+".new", "0640"),
|
||||
assets.NewMemoryAssetTarget(kubelet, KubeletSystemdConfFile+".new", "0644"),
|
||||
assets.NewMemoryAssetTarget(kubeletSvc, KubeletServiceFile+".new", "0644"),
|
||||
}
|
||||
// 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 defaultCNIConfig != nil {
|
||||
fs = append(fs, assets.NewMemoryAssetTarget(defaultCNIConfig, DefaultCNIConfigPath, "0644"))
|
||||
}
|
||||
return fs
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ package kverify
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
|
@ -36,6 +35,7 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/cruntime"
|
||||
"k8s.io/minikube/pkg/minikube/logs"
|
||||
"k8s.io/minikube/pkg/minikube/sysinit"
|
||||
)
|
||||
|
||||
// WaitForSystemPods verifies essential pods for running kurnetes is running
|
||||
|
|
@ -156,22 +156,11 @@ func announceProblems(r cruntime.Manager, bs bootstrapper.Bootstrapper, cfg conf
|
|||
}
|
||||
|
||||
// KubeletStatus checks the kubelet status
|
||||
func KubeletStatus(cr command.Runner) (state.State, error) {
|
||||
func KubeletStatus(cr command.Runner) state.State {
|
||||
glog.Infof("Checking kubelet status ...")
|
||||
rr, err := cr.RunCmd(exec.Command("sudo", "systemctl", "is-active", "kubelet"))
|
||||
if err != nil {
|
||||
// Do not return now, as we still have parsing to do!
|
||||
glog.Warningf("%s returned error: %v", rr.Command(), err)
|
||||
active := sysinit.New(cr).Active("kubelet")
|
||||
if active {
|
||||
return state.Running
|
||||
}
|
||||
s := strings.TrimSpace(rr.Stdout.String())
|
||||
glog.Infof("kubelet is-active: %s", s)
|
||||
switch s {
|
||||
case "active":
|
||||
return state.Running, nil
|
||||
case "inactive":
|
||||
return state.Stopped, nil
|
||||
case "activating":
|
||||
return state.Starting, nil
|
||||
}
|
||||
return state.Error, nil
|
||||
return state.Stopped
|
||||
}
|
||||
|
|
|
|||
|
|
@ -323,20 +323,33 @@ func collectCACerts() (map[string]string, error) {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if info == nil {
|
||||
return nil
|
||||
}
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if info != nil && !info.IsDir() {
|
||||
ext := strings.ToLower(filepath.Ext(hostpath))
|
||||
if ext == ".crt" || ext == ".pem" {
|
||||
glog.Infof("found cert: %s (%d bytes)", info.Name(), info.Size())
|
||||
validPem, err := isValidPEMCertificate(hostpath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if validPem {
|
||||
filename := filepath.Base(hostpath)
|
||||
dst := fmt.Sprintf("%s.%s", strings.TrimSuffix(filename, ext), "pem")
|
||||
certFiles[hostpath] = path.Join(vmpath.GuestCertAuthDir, dst)
|
||||
}
|
||||
fullPath := filepath.Join(certsDir, hostpath)
|
||||
ext := strings.ToLower(filepath.Ext(hostpath))
|
||||
|
||||
if ext == ".crt" || ext == ".pem" {
|
||||
if info.Size() < 32 {
|
||||
glog.Warningf("ignoring %s, impossibly tiny %d bytes", fullPath, info.Size())
|
||||
return nil
|
||||
}
|
||||
|
||||
glog.Infof("found cert: %s (%d bytes)", fullPath, info.Size())
|
||||
|
||||
validPem, err := isValidPEMCertificate(hostpath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if validPem {
|
||||
filename := filepath.Base(hostpath)
|
||||
dst := fmt.Sprintf("%s.%s", strings.TrimSuffix(filename, ext), "pem")
|
||||
certFiles[hostpath] = path.Join(vmpath.GuestCertAuthDir, dst)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
@ -394,23 +407,26 @@ func installCertSymlinks(cr command.Runner, caCerts map[string]string) error {
|
|||
for _, caCertFile := range caCerts {
|
||||
dstFilename := path.Base(caCertFile)
|
||||
certStorePath := path.Join(vmpath.GuestCertStoreDir, dstFilename)
|
||||
// If the cert really exists, add a named symlink
|
||||
cmd := fmt.Sprintf("test -f %s && ln -fs %s %s", caCertFile, caCertFile, certStorePath)
|
||||
|
||||
cmd := fmt.Sprintf("test -s %s && ln -fs %s %s", caCertFile, caCertFile, certStorePath)
|
||||
if _, err := cr.RunCmd(exec.Command("sudo", "/bin/bash", "-c", cmd)); err != nil {
|
||||
return errors.Wrapf(err, "create symlink for %s", caCertFile)
|
||||
}
|
||||
if hasSSLBinary {
|
||||
subjectHash, err := getSubjectHash(cr, caCertFile)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "calculate hash for cacert %s", caCertFile)
|
||||
}
|
||||
subjectHashLink := path.Join(vmpath.GuestCertStoreDir, fmt.Sprintf("%s.0", subjectHash))
|
||||
|
||||
// NOTE: This symlink may exist, but point to a missing file
|
||||
cmd := fmt.Sprintf("test -L %s || ln -fs %s %s", subjectHashLink, certStorePath, subjectHashLink)
|
||||
if _, err := cr.RunCmd(exec.Command("sudo", "/bin/bash", "-c", cmd)); err != nil {
|
||||
return errors.Wrapf(err, "create symlink for %s", caCertFile)
|
||||
}
|
||||
if !hasSSLBinary {
|
||||
continue
|
||||
}
|
||||
|
||||
subjectHash, err := getSubjectHash(cr, caCertFile)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "calculate hash for cacert %s", caCertFile)
|
||||
}
|
||||
subjectHashLink := path.Join(vmpath.GuestCertStoreDir, fmt.Sprintf("%s.0", subjectHash))
|
||||
|
||||
// NOTE: This symlink may exist, but point to a missing file
|
||||
cmd = fmt.Sprintf("test -L %s || ln -fs %s %s", subjectHashLink, certStorePath, subjectHashLink)
|
||||
if _, err := cr.RunCmd(exec.Command("sudo", "/bin/bash", "-c", cmd)); err != nil {
|
||||
return errors.Wrapf(err, "create symlink for %s", caCertFile)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -51,8 +51,8 @@ func TestSetupCerts(t *testing.T) {
|
|||
}
|
||||
|
||||
expected := map[string]string{
|
||||
`sudo /bin/bash -c "test -f /usr/share/ca-certificates/mycert.pem && ln -fs /usr/share/ca-certificates/mycert.pem /etc/ssl/certs/mycert.pem"`: "-",
|
||||
`sudo /bin/bash -c "test -f /usr/share/ca-certificates/minikubeCA.pem && ln -fs /usr/share/ca-certificates/minikubeCA.pem /etc/ssl/certs/minikubeCA.pem"`: "-",
|
||||
`sudo /bin/bash -c "test -s /usr/share/ca-certificates/mycert.pem && ln -fs /usr/share/ca-certificates/mycert.pem /etc/ssl/certs/mycert.pem"`: "-",
|
||||
`sudo /bin/bash -c "test -s /usr/share/ca-certificates/minikubeCA.pem && ln -fs /usr/share/ca-certificates/minikubeCA.pem /etc/ssl/certs/minikubeCA.pem"`: "-",
|
||||
}
|
||||
f := command.NewFakeCommandRunner()
|
||||
f.SetCommandToOutput(expected)
|
||||
|
|
|
|||
|
|
@ -51,9 +51,9 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/constants"
|
||||
"k8s.io/minikube/pkg/minikube/cruntime"
|
||||
"k8s.io/minikube/pkg/minikube/driver"
|
||||
"k8s.io/minikube/pkg/minikube/kubelet"
|
||||
"k8s.io/minikube/pkg/minikube/machine"
|
||||
"k8s.io/minikube/pkg/minikube/out"
|
||||
"k8s.io/minikube/pkg/minikube/sysinit"
|
||||
"k8s.io/minikube/pkg/minikube/vmpath"
|
||||
"k8s.io/minikube/pkg/util"
|
||||
"k8s.io/minikube/pkg/util/retry"
|
||||
|
|
@ -82,26 +82,6 @@ func NewBootstrapper(api libmachine.API, cc config.ClusterConfig, n config.Node)
|
|||
return &Bootstrapper{c: runner, contextName: cc.Name, k8sClient: nil}, nil
|
||||
}
|
||||
|
||||
// GetKubeletStatus returns the kubelet status
|
||||
func (k *Bootstrapper) GetKubeletStatus() (string, error) {
|
||||
rr, err := k.c.RunCmd(exec.Command("sudo", "systemctl", "is-active", "kubelet"))
|
||||
if err != nil {
|
||||
// Do not return now, as we still have parsing to do!
|
||||
glog.Warningf("%s returned error: %v", rr.Command(), err)
|
||||
}
|
||||
s := strings.TrimSpace(rr.Stdout.String())
|
||||
glog.Infof("kubelet is-active: %s", s)
|
||||
switch s {
|
||||
case "active":
|
||||
return state.Running.String(), nil
|
||||
case "inactive":
|
||||
return state.Stopped.String(), nil
|
||||
case "activating":
|
||||
return state.Starting.String(), nil
|
||||
}
|
||||
return state.Error.String(), nil
|
||||
}
|
||||
|
||||
// GetAPIServerStatus returns the api-server status
|
||||
func (k *Bootstrapper) GetAPIServerStatus(hostname string, port int) (string, error) {
|
||||
s, err := kverify.APIServerStatus(k.c, hostname, port)
|
||||
|
|
@ -190,7 +170,7 @@ func (k *Bootstrapper) init(cfg config.ClusterConfig) error {
|
|||
}
|
||||
|
||||
extraFlags := bsutil.CreateFlagsFromExtraArgs(cfg.KubernetesConfig.ExtraOptions)
|
||||
r, err := cruntime.New(cruntime.Config{Type: cfg.KubernetesConfig.ContainerRuntime})
|
||||
r, err := cruntime.New(cruntime.Config{Type: cfg.KubernetesConfig.ContainerRuntime, Runner: k.c})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -615,7 +595,7 @@ func (k *Bootstrapper) DeleteCluster(k8s config.KubernetesConfig) error {
|
|||
glog.Warningf("%s: %v", rr.Command(), err)
|
||||
}
|
||||
|
||||
if err := kubelet.ForceStop(k.c); err != nil {
|
||||
if err := sysinit.New(k.c).ForceStop("kubelet"); err != nil {
|
||||
glog.Warningf("stop kubelet: %v", err)
|
||||
}
|
||||
|
||||
|
|
@ -679,6 +659,11 @@ func (k *Bootstrapper) UpdateCluster(cfg config.ClusterConfig) error {
|
|||
|
||||
// UpdateNode updates a node.
|
||||
func (k *Bootstrapper) UpdateNode(cfg config.ClusterConfig, n config.Node, r cruntime.Manager) error {
|
||||
now := time.Now()
|
||||
defer func() {
|
||||
glog.Infof("reloadKubelet took %s", time.Since(now))
|
||||
}()
|
||||
|
||||
kubeadmCfg, err := bsutil.GenerateKubeadmYAML(cfg, n, r)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "generating kubeadm cfg")
|
||||
|
|
@ -696,24 +681,40 @@ func (k *Bootstrapper) UpdateNode(cfg config.ClusterConfig, n config.Node, r cru
|
|||
|
||||
glog.Infof("kubelet %s config:\n%+v", kubeletCfg, cfg.KubernetesConfig)
|
||||
|
||||
if err := bsutil.TransferBinaries(cfg.KubernetesConfig, k.c); err != nil {
|
||||
sm := sysinit.New(k.c)
|
||||
|
||||
if err := bsutil.TransferBinaries(cfg.KubernetesConfig, k.c, sm); err != nil {
|
||||
return errors.Wrap(err, "downloading binaries")
|
||||
}
|
||||
|
||||
var cniFile []byte
|
||||
files := []assets.CopyableFile{
|
||||
assets.NewMemoryAssetTarget(kubeadmCfg, bsutil.KubeadmYamlPath+".new", "0640"),
|
||||
assets.NewMemoryAssetTarget(kubeletCfg, bsutil.KubeletSystemdConfFile+".new", "0644"),
|
||||
assets.NewMemoryAssetTarget(kubeletService, bsutil.KubeletServiceFile+".new", "0644"),
|
||||
}
|
||||
// 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.KubernetesConfig.EnableDefaultCNI {
|
||||
cniFile = []byte(defaultCNIConfig)
|
||||
files = append(files, assets.NewMemoryAssetTarget([]byte(defaultCNIConfig), bsutil.DefaultCNIConfigPath, "0644"))
|
||||
}
|
||||
|
||||
// Install assets into temporary files
|
||||
files := bsutil.ConfigFileAssets(cfg.KubernetesConfig, kubeadmCfg, kubeletCfg, kubeletService, cniFile)
|
||||
// Installs compatibility shims for non-systemd environments
|
||||
kubeletPath := path.Join(vmpath.GuestPersistentDir, "binaries", cfg.KubernetesConfig.KubernetesVersion, "kubectl")
|
||||
shims, err := sm.GenerateInitShim("kubelet", kubeletPath, bsutil.KubeletSystemdConfFile)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "shim")
|
||||
}
|
||||
files = append(files, shims...)
|
||||
|
||||
if err := copyFiles(k.c, files); err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "copy")
|
||||
}
|
||||
|
||||
if err := reloadKubelet(k.c); err != nil {
|
||||
return err
|
||||
if err := startKubeletIfRequired(k.c, sm); err != nil {
|
||||
return errors.Wrap(err, "reload")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -736,7 +737,12 @@ func copyFiles(runner command.Runner, files []assets.CopyableFile) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func reloadKubelet(runner command.Runner) error {
|
||||
func startKubeletIfRequired(runner command.Runner, sm sysinit.Manager) error {
|
||||
now := time.Now()
|
||||
defer func() {
|
||||
glog.Infof("reloadKubelet took %s", time.Since(now))
|
||||
}()
|
||||
|
||||
svc := bsutil.KubeletServiceFile
|
||||
conf := bsutil.KubeletSystemdConfFile
|
||||
|
||||
|
|
@ -746,11 +752,12 @@ func reloadKubelet(runner command.Runner) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
startCmd := exec.Command("/bin/bash", "-c", fmt.Sprintf("sudo cp %s.new %s && sudo cp %s.new %s && sudo systemctl daemon-reload && sudo systemctl restart kubelet", svc, svc, conf, conf))
|
||||
startCmd := exec.Command("/bin/bash", "-c", fmt.Sprintf("sudo cp %s.new %s && sudo cp %s.new %s", svc, svc, conf, conf))
|
||||
if _, err := runner.RunCmd(startCmd); err != nil {
|
||||
return errors.Wrap(err, "starting kubelet")
|
||||
}
|
||||
return nil
|
||||
|
||||
return sm.Start("kubelet")
|
||||
}
|
||||
|
||||
// applyKicOverlay applies the CNI plugin needed to make kic work
|
||||
|
|
|
|||
|
|
@ -21,27 +21,33 @@ import (
|
|||
"github.com/pkg/errors"
|
||||
"k8s.io/minikube/pkg/minikube/command"
|
||||
"k8s.io/minikube/pkg/minikube/cruntime"
|
||||
"k8s.io/minikube/pkg/minikube/kubelet"
|
||||
"k8s.io/minikube/pkg/minikube/sysinit"
|
||||
)
|
||||
|
||||
// Pause pauses a Kubernetes cluster
|
||||
func Pause(cr cruntime.Manager, r command.Runner, namespaces []string) ([]string, error) {
|
||||
ids := []string{}
|
||||
|
||||
// Disable the kubelet so it does not attempt to restart paused pods
|
||||
if err := kubelet.Disable(r); err != nil {
|
||||
sm := sysinit.New(r)
|
||||
if err := sm.Disable("kubelet"); err != nil {
|
||||
return ids, errors.Wrap(err, "kubelet disable")
|
||||
}
|
||||
if err := kubelet.Stop(r); err != nil {
|
||||
|
||||
if err := sm.Stop("kubelet"); err != nil {
|
||||
return ids, errors.Wrap(err, "kubelet stop")
|
||||
}
|
||||
|
||||
ids, err := cr.ListContainers(cruntime.ListOptions{State: cruntime.Running, Namespaces: namespaces})
|
||||
if err != nil {
|
||||
return ids, errors.Wrap(err, "list running")
|
||||
}
|
||||
|
||||
if len(ids) == 0 {
|
||||
glog.Warningf("no running containers to pause")
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
return ids, cr.PauseContainers(ids)
|
||||
|
||||
}
|
||||
|
|
@ -59,11 +65,14 @@ func Unpause(cr cruntime.Manager, r command.Runner, namespaces []string) ([]stri
|
|||
return ids, errors.Wrap(err, "unpause")
|
||||
}
|
||||
|
||||
if err := kubelet.Enable(r); err != nil {
|
||||
sm := sysinit.New(r)
|
||||
if err := sm.Enable("kubelet"); err != nil {
|
||||
return ids, errors.Wrap(err, "kubelet enable")
|
||||
}
|
||||
if err := kubelet.Start(r); err != nil {
|
||||
|
||||
if err := sm.Start("kubelet"); err != nil {
|
||||
return ids, errors.Wrap(err, "kubelet start")
|
||||
}
|
||||
|
||||
return ids, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/download"
|
||||
"k8s.io/minikube/pkg/minikube/out"
|
||||
"k8s.io/minikube/pkg/minikube/sysinit"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -116,6 +117,7 @@ type Containerd struct {
|
|||
Runner CommandRunner
|
||||
ImageRepository string
|
||||
KubernetesVersion semver.Version
|
||||
Init sysinit.Manager
|
||||
}
|
||||
|
||||
// Name is a human readable name for containerd
|
||||
|
|
@ -158,9 +160,7 @@ func (r *Containerd) DefaultCNI() bool {
|
|||
|
||||
// Active returns if containerd is active on the host
|
||||
func (r *Containerd) Active() bool {
|
||||
c := exec.Command("sudo", "systemctl", "is-active", "--quiet", "service", "containerd")
|
||||
_, err := r.Runner.RunCmd(c)
|
||||
return err == nil
|
||||
return r.Init.Active("containerd")
|
||||
}
|
||||
|
||||
// Available returns an error if it is not possible to use this runtime on a host
|
||||
|
|
@ -208,21 +208,14 @@ func (r *Containerd) Enable(disOthers bool) error {
|
|||
if err := enableIPForwarding(r.Runner); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Otherwise, containerd will fail API requests with 'Unimplemented'
|
||||
c := exec.Command("sudo", "systemctl", "restart", "containerd")
|
||||
if _, err := r.Runner.RunCmd(c); err != nil {
|
||||
return errors.Wrap(err, "restart containerd")
|
||||
}
|
||||
return nil
|
||||
return r.Init.Restart("containerd")
|
||||
}
|
||||
|
||||
// Disable idempotently disables containerd on a host
|
||||
func (r *Containerd) Disable() error {
|
||||
c := exec.Command("sudo", "systemctl", "stop", "-f", "containerd")
|
||||
if _, err := r.Runner.RunCmd(c); err != nil {
|
||||
return errors.Wrapf(err, "stop containerd")
|
||||
}
|
||||
return nil
|
||||
return r.Init.ForceStop("containerd")
|
||||
}
|
||||
|
||||
// ImageExists checks if an image exists, expected input format
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/download"
|
||||
"k8s.io/minikube/pkg/minikube/out"
|
||||
"k8s.io/minikube/pkg/minikube/sysinit"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -41,6 +42,7 @@ type CRIO struct {
|
|||
Runner CommandRunner
|
||||
ImageRepository string
|
||||
KubernetesVersion semver.Version
|
||||
Init sysinit.Manager
|
||||
}
|
||||
|
||||
// generateCRIOConfig sets up /etc/crio/crio.conf
|
||||
|
|
@ -104,9 +106,7 @@ func (r *CRIO) Available() error {
|
|||
|
||||
// Active returns if CRIO is active on the host
|
||||
func (r *CRIO) Active() bool {
|
||||
c := exec.Command("sudo", "systemctl", "is-active", "--quiet", "service", "crio")
|
||||
_, err := r.Runner.RunCmd(c)
|
||||
return err == nil
|
||||
return r.Init.Active("crio")
|
||||
}
|
||||
|
||||
// Enable idempotently enables CRIO on a host
|
||||
|
|
@ -125,19 +125,12 @@ func (r *CRIO) Enable(disOthers bool) error {
|
|||
if err := enableIPForwarding(r.Runner); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := r.Runner.RunCmd(exec.Command("sudo", "systemctl", "restart", "crio")); err != nil {
|
||||
return errors.Wrapf(err, "enable crio.")
|
||||
}
|
||||
return nil
|
||||
return r.Init.Start("crio")
|
||||
}
|
||||
|
||||
// Disable idempotently disables CRIO on a host
|
||||
func (r *CRIO) Disable() error {
|
||||
if _, err := r.Runner.RunCmd(exec.Command("sudo", "systemctl", "stop", "-f", "crio")); err != nil {
|
||||
return errors.Wrapf(err, "disable crio.")
|
||||
}
|
||||
return nil
|
||||
return r.Init.ForceStop("crio")
|
||||
}
|
||||
|
||||
// ImageExists checks if an image exists
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/command"
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
"k8s.io/minikube/pkg/minikube/out"
|
||||
"k8s.io/minikube/pkg/minikube/sysinit"
|
||||
)
|
||||
|
||||
// ContainerState is the run state of a container
|
||||
|
|
@ -131,13 +132,27 @@ type ListOptions struct {
|
|||
|
||||
// New returns an appropriately configured runtime
|
||||
func New(c Config) (Manager, error) {
|
||||
sm := sysinit.New(c.Runner)
|
||||
|
||||
switch c.Type {
|
||||
case "", "docker":
|
||||
return &Docker{Socket: c.Socket, Runner: c.Runner}, nil
|
||||
return &Docker{Socket: c.Socket, Runner: c.Runner, Init: sm}, nil
|
||||
case "crio", "cri-o":
|
||||
return &CRIO{Socket: c.Socket, Runner: c.Runner, ImageRepository: c.ImageRepository, KubernetesVersion: c.KubernetesVersion}, nil
|
||||
return &CRIO{
|
||||
Socket: c.Socket,
|
||||
Runner: c.Runner,
|
||||
ImageRepository: c.ImageRepository,
|
||||
KubernetesVersion: c.KubernetesVersion,
|
||||
Init: sm,
|
||||
}, nil
|
||||
case "containerd":
|
||||
return &Containerd{Socket: c.Socket, Runner: c.Runner, ImageRepository: c.ImageRepository, KubernetesVersion: c.KubernetesVersion}, nil
|
||||
return &Containerd{
|
||||
Socket: c.Socket,
|
||||
Runner: c.Runner,
|
||||
ImageRepository: c.ImageRepository,
|
||||
KubernetesVersion: c.KubernetesVersion,
|
||||
Init: sm,
|
||||
}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown runtime type: %q", c.Type)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/pkg/errors"
|
||||
|
|
@ -406,12 +407,27 @@ func (f *FakeRunner) crictl(args []string, _ bool) (string, error) {
|
|||
|
||||
// systemctl is a fake implementation of systemctl
|
||||
func (f *FakeRunner) systemctl(args []string, root bool) (string, error) { // nolint result 0 (string) is always ""
|
||||
glog.Infof("fake systemctl: %v", args)
|
||||
action := args[0]
|
||||
svcs := args[1:]
|
||||
|
||||
if action == "--version" {
|
||||
return "systemd 123 (321.2-1)", nil
|
||||
}
|
||||
|
||||
if action == "daemon-reload" {
|
||||
return "ok", nil
|
||||
}
|
||||
|
||||
var svcs []string
|
||||
if len(args) > 0 {
|
||||
svcs = args[1:]
|
||||
}
|
||||
|
||||
// force
|
||||
if svcs[0] == "-f" {
|
||||
svcs = svcs[1:]
|
||||
}
|
||||
|
||||
out := ""
|
||||
|
||||
for i, arg := range args {
|
||||
|
|
@ -496,7 +512,6 @@ func TestVersion(t *testing.T) {
|
|||
// defaultServices reflects the default boot state for the minikube VM
|
||||
var defaultServices = map[string]serviceState{
|
||||
"docker": SvcRunning,
|
||||
"docker.socket": SvcRunning,
|
||||
"crio": SvcExited,
|
||||
"crio-shutdown": SvcExited,
|
||||
"containerd": SvcExited,
|
||||
|
|
@ -507,7 +522,7 @@ func TestDisable(t *testing.T) {
|
|||
runtime string
|
||||
want []string
|
||||
}{
|
||||
{"docker", []string{"sudo", "systemctl", "stop", "-f", "docker", "docker.socket"}},
|
||||
{"docker", []string{"sudo", "systemctl", "stop", "-f", "docker"}},
|
||||
{"crio", []string{"sudo", "systemctl", "stop", "-f", "crio"}},
|
||||
{"containerd", []string{"sudo", "systemctl", "stop", "-f", "containerd"}},
|
||||
}
|
||||
|
|
@ -539,23 +554,20 @@ func TestEnable(t *testing.T) {
|
|||
}{
|
||||
{"docker", map[string]serviceState{
|
||||
"docker": SvcRunning,
|
||||
"docker.socket": SvcRunning,
|
||||
"containerd": SvcExited,
|
||||
"crio": SvcExited,
|
||||
"crio-shutdown": SvcExited,
|
||||
}},
|
||||
{"containerd", map[string]serviceState{
|
||||
"docker": SvcExited,
|
||||
"docker.socket": SvcExited,
|
||||
"containerd": SvcRestarted,
|
||||
"crio": SvcExited,
|
||||
"crio-shutdown": SvcExited,
|
||||
}},
|
||||
{"crio", map[string]serviceState{
|
||||
"docker": SvcExited,
|
||||
"docker.socket": SvcExited,
|
||||
"containerd": SvcExited,
|
||||
"crio": SvcRestarted,
|
||||
"crio": SvcRunning,
|
||||
"crio-shutdown": SvcExited,
|
||||
}},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/docker"
|
||||
"k8s.io/minikube/pkg/minikube/download"
|
||||
"k8s.io/minikube/pkg/minikube/out"
|
||||
"k8s.io/minikube/pkg/minikube/sysinit"
|
||||
)
|
||||
|
||||
// KubernetesContainerPrefix is the prefix of each kubernetes container
|
||||
|
|
@ -56,6 +57,7 @@ func (e *ErrISOFeature) Error() string {
|
|||
type Docker struct {
|
||||
Socket string
|
||||
Runner CommandRunner
|
||||
Init sysinit.Manager
|
||||
}
|
||||
|
||||
// Name is a human readable name for Docker
|
||||
|
|
@ -97,9 +99,7 @@ func (r *Docker) Available() error {
|
|||
|
||||
// Active returns if docker is active on the host
|
||||
func (r *Docker) Active() bool {
|
||||
c := exec.Command("sudo", "systemctl", "is-active", "--quiet", "service", "docker")
|
||||
_, err := r.Runner.RunCmd(c)
|
||||
return err == nil
|
||||
return r.Init.Active("docker")
|
||||
}
|
||||
|
||||
// Enable idempotently enables Docker on a host
|
||||
|
|
@ -109,29 +109,18 @@ func (r *Docker) Enable(disOthers bool) error {
|
|||
glog.Warningf("disableOthers: %v", err)
|
||||
}
|
||||
}
|
||||
c := exec.Command("sudo", "systemctl", "start", "docker")
|
||||
if _, err := r.Runner.RunCmd(c); err != nil {
|
||||
return errors.Wrap(err, "enable docker.")
|
||||
}
|
||||
return nil
|
||||
|
||||
return r.Init.Start("docker")
|
||||
}
|
||||
|
||||
// Restart restarts Docker on a host
|
||||
func (r *Docker) Restart() error {
|
||||
c := exec.Command("sudo", "systemctl", "restart", "docker")
|
||||
if _, err := r.Runner.RunCmd(c); err != nil {
|
||||
return errors.Wrap(err, "restarting docker.")
|
||||
}
|
||||
return nil
|
||||
return r.Init.Restart("docker")
|
||||
}
|
||||
|
||||
// Disable idempotently disables Docker on a host
|
||||
func (r *Docker) Disable() error {
|
||||
c := exec.Command("sudo", "systemctl", "stop", "-f", "docker", "docker.socket")
|
||||
if _, err := r.Runner.RunCmd(c); err != nil {
|
||||
return errors.Wrap(err, "disable docker")
|
||||
}
|
||||
return nil
|
||||
return r.Init.ForceStop("docker")
|
||||
}
|
||||
|
||||
// ImageExists checks if an image exists
|
||||
|
|
|
|||
|
|
@ -1,117 +0,0 @@
|
|||
/*
|
||||
Copyright 2019 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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 kubelet
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/minikube/pkg/minikube/command"
|
||||
"k8s.io/minikube/pkg/util/retry"
|
||||
)
|
||||
|
||||
// Stop idempotently stops the kubelet
|
||||
func Stop(cr command.Runner) error {
|
||||
return stop(cr, false)
|
||||
}
|
||||
|
||||
// ForceStop idempotently force stops the kubelet
|
||||
func ForceStop(cr command.Runner) error {
|
||||
return stop(cr, true)
|
||||
}
|
||||
|
||||
// stop dempotently stops the kubelet
|
||||
func stop(cr command.Runner, force bool) error {
|
||||
glog.Infof("stopping kubelet ...")
|
||||
stp := func() error {
|
||||
cmd := exec.Command("sudo", "systemctl", "stop", "kubelet.service")
|
||||
if force {
|
||||
cmd = exec.Command("sudo", "systemctl", "stop", "-f", "kubelet.service")
|
||||
}
|
||||
if rr, err := cr.RunCmd(cmd); err != nil {
|
||||
return fmt.Errorf("temporary error for %q : %v", rr.Command(), err)
|
||||
}
|
||||
cmd = exec.Command("sudo", "systemctl", "show", "-p", "SubState", "kubelet")
|
||||
rr, err := cr.RunCmd(cmd)
|
||||
if err != nil {
|
||||
return fmt.Errorf("temporary error: for %q : %v", rr.Command(), err)
|
||||
}
|
||||
if !strings.Contains(rr.Stdout.String(), "dead") && !strings.Contains(rr.Stdout.String(), "failed") {
|
||||
return fmt.Errorf("unexpected kubelet state: %q", rr.Stdout.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := retry.Expo(stp, 1*time.Second, time.Minute, 2); err != nil {
|
||||
return errors.Wrapf(err, "error stopping kubelet")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Start starts the kubelet
|
||||
func Start(cr command.Runner) error {
|
||||
glog.Infof("restarting kubelet.service ...")
|
||||
c := exec.Command("sudo", "systemctl", "start", "kubelet")
|
||||
if _, err := cr.RunCmd(c); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Restart restarts the kubelet
|
||||
func Restart(cr command.Runner) error {
|
||||
glog.Infof("restarting kubelet.service ...")
|
||||
c := exec.Command("sudo", "systemctl", "restart", "kubelet.service")
|
||||
if _, err := cr.RunCmd(c); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check checks on the status of the kubelet
|
||||
func Check(cr command.Runner) error {
|
||||
glog.Infof("checking for running kubelet ...")
|
||||
c := exec.Command("sudo", "systemctl", "is-active", "--quiet", "service", "kubelet")
|
||||
if _, err := cr.RunCmd(c); err != nil {
|
||||
return errors.Wrap(err, "check kubelet")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Disable disables the Kubelet
|
||||
func Disable(cr command.Runner) error {
|
||||
glog.Infof("disabling kubelet ...")
|
||||
c := exec.Command("sudo", "systemctl", "disable", "kubelet")
|
||||
if _, err := cr.RunCmd(c); err != nil {
|
||||
return errors.Wrap(err, "disable")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Enable enables the Kubelet
|
||||
func Enable(cr command.Runner) error {
|
||||
glog.Infof("enabling kubelet ...")
|
||||
c := exec.Command("sudo", "systemctl", "enable", "kubelet")
|
||||
if _, err := cr.RunCmd(c); err != nil {
|
||||
return errors.Wrap(err, "enable")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -113,7 +113,8 @@ func Start(starter Starter, apiServer bool) (*kubeconfig.Settings, error) {
|
|||
// setup kubeadm (must come after setupKubeconfig)
|
||||
bs = setupKubeAdm(starter.MachineAPI, *starter.Cfg, *starter.Node)
|
||||
err = bs.StartCluster(*starter.Cfg)
|
||||
if err != nil {
|
||||
|
||||
if err != nil {
|
||||
out.LogEntries("Error starting cluster", err, logs.FindProblems(cr, bs, *starter.Cfg, starter.Runner))
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,9 +21,11 @@ import (
|
|||
"fmt"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/machine/libmachine/drivers"
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/minikube/pkg/drivers/kic"
|
||||
"k8s.io/minikube/pkg/drivers/kic/oci"
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
|
|
@ -70,7 +72,7 @@ func configure(cc config.ClusterConfig, n config.Node) (interface{}, error) {
|
|||
func status() registry.State {
|
||||
_, err := exec.LookPath(oci.Docker)
|
||||
if err != nil {
|
||||
return registry.State{Error: err, Installed: false, Healthy: false, Fix: "Docker is required.", Doc: "https://minikube.sigs.k8s.io/docs/reference/drivers/docker/"}
|
||||
return registry.State{Error: err, Installed: false, Healthy: false, Fix: "Install Docker.", Doc: "https://minikube.sigs.k8s.io/docs/drivers/docker/#install-docker"}
|
||||
}
|
||||
|
||||
// Allow no more than 3 seconds for docker info
|
||||
|
|
@ -78,8 +80,19 @@ func status() registry.State {
|
|||
defer cancel()
|
||||
|
||||
err = exec.CommandContext(ctx, oci.Docker, "info").Run()
|
||||
|
||||
if ctx.Err() == context.DeadlineExceeded {
|
||||
return registry.State{Error: err, Installed: true, Healthy: false, Fix: "Docker responds too slow. Restart the Docker Service.", Doc: "https://minikube.sigs.k8s.io/docs/drivers/docker"}
|
||||
}
|
||||
if err != nil {
|
||||
return registry.State{Error: err, Installed: true, Healthy: false, Fix: "Docker is not running or is responding too slow. Try: restarting docker desktop."}
|
||||
glog.Infof("docker info returned error: %v", err)
|
||||
if strings.Contains(err.Error(), "Cannot connect to the Docker daemon") {
|
||||
return registry.State{Error: err, Installed: true, Healthy: false, Fix: "Start the Docker Service.", Doc: "https://minikube.sigs.k8s.io/docs/drivers/docker"}
|
||||
}
|
||||
// if we get here, something is really wrong on their docker.
|
||||
// our best suggestion would be re-install latest docker.
|
||||
return registry.State{Error: err, Installed: true, Healthy: false, Fix: "Re-install the latest version of Docker.", Doc: "https://minikube.sigs.k8s.io/docs/drivers/docker"}
|
||||
|
||||
}
|
||||
|
||||
return registry.State{Installed: true, Healthy: true}
|
||||
|
|
|
|||
|
|
@ -52,8 +52,9 @@ func configure(cc config.ClusterConfig, n config.Node) (interface{}, error) {
|
|||
}
|
||||
|
||||
func status() registry.State {
|
||||
if _, err := exec.LookPath("systemctl"); err != nil {
|
||||
return registry.State{Error: err, Fix: "Use a systemd based Linux distribution", Doc: "https://minikube.sigs.k8s.io/docs/reference/drivers/none/"}
|
||||
_, err := exec.LookPath("iptables")
|
||||
if err != nil {
|
||||
return registry.State{Error: err, Fix: "iptables must be installed", Doc: "https://minikube.sigs.k8s.io/docs/reference/drivers/none/"}
|
||||
}
|
||||
|
||||
if _, err := exec.LookPath("docker"); err != nil {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
Copyright 2019 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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 sysinit provides an abstraction over init systems like systemctl
|
||||
package sysinit
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"html/template"
|
||||
"os/exec"
|
||||
"path"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/minikube/pkg/minikube/assets"
|
||||
"k8s.io/minikube/pkg/minikube/vmpath"
|
||||
)
|
||||
|
||||
var restartWrapper = `#!/bin/bash
|
||||
# Wrapper script to emulate systemd restart on non-systemd systems
|
||||
readonly UNIT_PATH=$1
|
||||
|
||||
while true; do
|
||||
if [[ -f "${UNIT_PATH}" ]]; then
|
||||
eval $(egrep "^ExecStart=" "${UNIT_PATH}" | cut -d"=" -f2-)
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
`
|
||||
|
||||
var initScriptTmpl = template.Must(template.New("initScript").Parse(`#!/bin/bash
|
||||
# OpenRC init script shim for systemd units
|
||||
readonly NAME="{{.Name}}"
|
||||
readonly RESTART_WRAPPER="{{.Wrapper}}"
|
||||
readonly UNIT_PATH="{{.Unit}}"
|
||||
readonly PID_PATH="/var/run/${NAME}.pid"
|
||||
|
||||
function start() {
|
||||
start-stop-daemon --oknodo --pidfile "${PID_PATH}" --background --start --make-pid --exec "${RESTART_WRAPPER}" "${UNIT_PATH}"
|
||||
}
|
||||
|
||||
function stop() {
|
||||
if [[ -f "${PID_PATH}" ]]; then
|
||||
pkill -P "$(cat ${PID_PATH})"
|
||||
fi
|
||||
start-stop-daemon --oknodo --pidfile "${PID_PATH}" --stop
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
restart)
|
||||
stop
|
||||
start
|
||||
;;
|
||||
status)
|
||||
start-stop-daemon --pidfile "${PID_PATH}" --status
|
||||
;;
|
||||
*)
|
||||
echo "Usage: {{.Name}} {start|stop|restart|status}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
`))
|
||||
|
||||
// OpenRC is a service manager for OpenRC-like init systems
|
||||
type OpenRC struct {
|
||||
r Runner
|
||||
}
|
||||
|
||||
// Name returns the name of the init system
|
||||
func (s *OpenRC) Name() string {
|
||||
return "OpenRC"
|
||||
}
|
||||
|
||||
// Active checks if a service is running
|
||||
func (s *OpenRC) Active(svc string) bool {
|
||||
_, err := s.r.RunCmd(exec.Command("sudo", "service", svc, "status"))
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// Start starts a service idempotently
|
||||
func (s *OpenRC) Start(svc string) error {
|
||||
if s.Active(svc) {
|
||||
return nil
|
||||
}
|
||||
ctx, cb := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cb()
|
||||
|
||||
rr, err := s.r.RunCmd(exec.CommandContext(ctx, "sudo", "service", svc, "start"))
|
||||
glog.Infof("start output: %s", rr.Output())
|
||||
return err
|
||||
}
|
||||
|
||||
// Disable does nothing
|
||||
func (s *OpenRC) Disable(svc string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Enable does nothing
|
||||
func (s *OpenRC) Enable(svc string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Restart restarts a service
|
||||
func (s *OpenRC) Restart(svc string) error {
|
||||
rr, err := s.r.RunCmd(exec.Command("sudo", "service", svc, "restart"))
|
||||
glog.Infof("restart output: %s", rr.Output())
|
||||
return err
|
||||
}
|
||||
|
||||
// Stop stops a service
|
||||
func (s *OpenRC) Stop(svc string) error {
|
||||
rr, err := s.r.RunCmd(exec.Command("sudo", "service", svc, "stop"))
|
||||
glog.Infof("stop output: %s", rr.Output())
|
||||
return err
|
||||
}
|
||||
|
||||
// ForceStop stops a service with prejuidice
|
||||
func (s *OpenRC) ForceStop(svc string) error {
|
||||
return s.Stop(svc)
|
||||
}
|
||||
|
||||
// GenerateInitShim generates any additional init files required for this service
|
||||
func (s *OpenRC) GenerateInitShim(svc string, binary string, unit string) ([]assets.CopyableFile, error) {
|
||||
restartWrapperPath := path.Join(vmpath.GuestPersistentDir, "openrc-restart-wrapper.sh")
|
||||
|
||||
opts := struct {
|
||||
Binary string
|
||||
Wrapper string
|
||||
Name string
|
||||
Unit string
|
||||
}{
|
||||
Name: svc,
|
||||
Binary: binary,
|
||||
Wrapper: restartWrapperPath,
|
||||
Unit: unit,
|
||||
}
|
||||
|
||||
var b bytes.Buffer
|
||||
if err := initScriptTmpl.Execute(&b, opts); err != nil {
|
||||
return nil, errors.Wrap(err, "template execute")
|
||||
}
|
||||
|
||||
files := []assets.CopyableFile{
|
||||
assets.NewMemoryAssetTarget([]byte(restartWrapper), restartWrapperPath, "0755"),
|
||||
assets.NewMemoryAssetTarget(b.Bytes(), path.Join("/etc/init.d/", svc), "0755"),
|
||||
}
|
||||
|
||||
return files, nil
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
Copyright 2020 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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 sysinit
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
|
||||
"k8s.io/minikube/pkg/minikube/assets"
|
||||
"k8s.io/minikube/pkg/minikube/command"
|
||||
)
|
||||
|
||||
var cachedSystemdCheck *bool
|
||||
|
||||
// Runner is the subset of command.Runner this package consumes
|
||||
type Runner interface {
|
||||
RunCmd(cmd *exec.Cmd) (*command.RunResult, error)
|
||||
}
|
||||
|
||||
// Manager is a common interface for init systems
|
||||
type Manager interface {
|
||||
// Name returns the name of the init manager
|
||||
Name() string
|
||||
|
||||
// Active returns if a service is active
|
||||
Active(string) bool
|
||||
|
||||
// Disable disables a service
|
||||
Disable(string) error
|
||||
|
||||
// Enable enables a service
|
||||
Enable(string) error
|
||||
|
||||
// Start starts a service idempotently
|
||||
Start(string) error
|
||||
|
||||
// Restart restarts a service
|
||||
Restart(string) error
|
||||
|
||||
// Stop stops a service
|
||||
Stop(string) error
|
||||
|
||||
// ForceStop stops a service with prejudice
|
||||
ForceStop(string) error
|
||||
|
||||
// GenerateInitShim generates any additional init files required for this service
|
||||
GenerateInitShim(svc string, binary string, unit string) ([]assets.CopyableFile, error)
|
||||
}
|
||||
|
||||
// New returns an appropriately configured service manager
|
||||
func New(r Runner) Manager {
|
||||
// If we are not provided a runner, we can't do anything anyways
|
||||
if r == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var systemd bool
|
||||
|
||||
// Caching the result is important, as this manager may be created in many places,
|
||||
// and ssh calls are expensive on some drivers, such as Docker.
|
||||
if cachedSystemdCheck != nil {
|
||||
systemd = *cachedSystemdCheck
|
||||
} else {
|
||||
systemd = usesSystemd(r)
|
||||
cachedSystemdCheck = &systemd
|
||||
}
|
||||
|
||||
if systemd {
|
||||
return &Systemd{r: r}
|
||||
}
|
||||
return &OpenRC{r: r}
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
Copyright 2019 The Kubernetes Authors All rights reserved.
|
||||
|
||||
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 sysinit provides an abstraction over init systems like systemctl
|
||||
package sysinit
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
|
||||
"k8s.io/minikube/pkg/minikube/assets"
|
||||
)
|
||||
|
||||
// Systemd is a service manager for systemd distributions
|
||||
type Systemd struct {
|
||||
r Runner
|
||||
}
|
||||
|
||||
// Name returns the name of the init system
|
||||
func (s *Systemd) Name() string {
|
||||
return "systemd"
|
||||
}
|
||||
|
||||
// reload reloads systemd configuration
|
||||
func (s *Systemd) reload() error {
|
||||
_, err := s.r.RunCmd(exec.Command("sudo", "systemctl", "daemon-reload"))
|
||||
return err
|
||||
}
|
||||
|
||||
// Active checks if a service is running
|
||||
func (s *Systemd) Active(svc string) bool {
|
||||
_, err := s.r.RunCmd(exec.Command("sudo", "systemctl", "is-active", "--quiet", "service", svc))
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// Disable disables a service
|
||||
func (s *Systemd) Disable(svc string) error {
|
||||
_, err := s.r.RunCmd(exec.Command("sudo", "systemctl", "disable", svc))
|
||||
return err
|
||||
}
|
||||
|
||||
// Enable enables a service
|
||||
func (s *Systemd) Enable(svc string) error {
|
||||
_, err := s.r.RunCmd(exec.Command("sudo", "systemctl", "enable", svc))
|
||||
return err
|
||||
}
|
||||
|
||||
// Start starts a service
|
||||
func (s *Systemd) Start(svc string) error {
|
||||
if err := s.reload(); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := s.r.RunCmd(exec.Command("sudo", "systemctl", "start", svc))
|
||||
return err
|
||||
}
|
||||
|
||||
// Restart restarts a service
|
||||
func (s *Systemd) Restart(svc string) error {
|
||||
if err := s.reload(); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := s.r.RunCmd(exec.Command("sudo", "systemctl", "restart", svc))
|
||||
return err
|
||||
}
|
||||
|
||||
// Stop stops a service
|
||||
func (s *Systemd) Stop(svc string) error {
|
||||
_, err := s.r.RunCmd(exec.Command("sudo", "systemctl", "stop", svc))
|
||||
return err
|
||||
}
|
||||
|
||||
// ForceStop terminates a service with prejudice
|
||||
func (s *Systemd) ForceStop(svc string) error {
|
||||
_, err := s.r.RunCmd(exec.Command("sudo", "systemctl", "stop", "-f", svc))
|
||||
return err
|
||||
}
|
||||
|
||||
// GenerateInitShim does nothing for systemd
|
||||
func (s *Systemd) GenerateInitShim(svc string, binary string, unit string) ([]assets.CopyableFile, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func usesSystemd(r Runner) bool {
|
||||
_, err := r.RunCmd(exec.Command("systemctl", "--version"))
|
||||
return err == nil
|
||||
}
|
||||
|
|
@ -163,3 +163,9 @@ div.td-content {
|
|||
font-size: 1.3rem !important;
|
||||
}
|
||||
}
|
||||
|
||||
// make search bar wider https://www.docsy.dev/docs/adding-content/navigation/#configure-local-search-with-lunr
|
||||
.popover.offline-search-result {
|
||||
background-color: $gray-200 !important;
|
||||
max-width: 460px;
|
||||
}
|
||||
|
|
@ -79,11 +79,12 @@ All translations are stored in the top-level `translations` directory.
|
|||
|
||||
* You now have a fresh minikube binary in the `out` directory. If your system locale is that of the language you added translations for, a simple `out/minikube start` will work as a test, assuming you translated phrases from `minikube start`. You can use whatever command you'd like in that way.
|
||||
|
||||
* If you have a different system locale, you can override the printed language using the LANG environment variable:
|
||||
* If you have a different system locale, you can override the printed language using the LC_ALL environment variable:
|
||||
```
|
||||
~/minikube$ LANG=fr out/minikube start
|
||||
😄 minikube v1.9.0-beta.2 sur Darwin 10.14.6
|
||||
✨ Choix automatique du driver hyperkit
|
||||
~/minikube$ LC_ALL=fr out/minikube start
|
||||
😄 minikube v1.9.2 sur Darwin 10.14.5
|
||||
✨ Choix automatique du driver hyperkit. Autres choix: <no value>
|
||||
👍 Starting control plane node minikube in cluster minikube
|
||||
🔥 Création de VM hyperkit (CPUs=2, Mémoire=4000MB, Disque=20000MB)...
|
||||
🐳 Préparation de Kubernetes v1.18.0 sur Docker 19.03.8...
|
||||
🌟 Installation des addons: default-storageclass, storage-provisioner
|
||||
|
|
|
|||
|
|
@ -21,12 +21,16 @@ The Docker driver allows you to install Kubernetes into an existing Docker insta
|
|||
|
||||
- On macOS, containers might get hung and require a restart of Docker for Desktop. See [docker/for-mac#1835](https://github.com/docker/for-mac/issues/1835)
|
||||
|
||||
- The `ingress` and `ingress-dns` addons are currently only supported on Linux. See [#7332](https://github.com/kubernetes/minikube/issues/7332)
|
||||
- The `ingress`, `ingress-dns` and `registry` addons are currently only supported on Linux. See [#7332](https://github.com/kubernetes/minikube/issues/7332) and [#7535](https://github.com/kubernetes/minikube/issues/7535)
|
||||
|
||||
- On WSL2 (experimental - see [#5392](https://github.com/kubernetes/minikube/issues/5392)), you may need to run:
|
||||
|
||||
`sudo mkdir /sys/fs/cgroup/systemd && sudo mount -t cgroup -o none,name=systemd cgroup /sys/fs/cgroup/systemd`.
|
||||
|
||||
- Addon 'registry' for mac and windows is not supported yet and it is [a work in progress](https://github.com/kubernetes/minikube/issues/7535).
|
||||
|
||||
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- On macOS or Windows, you may need to restart Docker for Desktop if a command gets hung
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
title: "Pushing images"
|
||||
weight: 5
|
||||
description: >
|
||||
There are many ways to push images into minikube.
|
||||
comparing 5 ways to push your image into a minikiube cluster.
|
||||
aliases:
|
||||
- /docs/tasks/building
|
||||
- /docs/tasks/caching
|
||||
|
|
@ -10,15 +10,81 @@ aliases:
|
|||
- /docs/tasks/docker_daemon
|
||||
---
|
||||
|
||||
# Cached Images
|
||||
## Comparison table for different methods
|
||||
The best method to push your image to minikube depends on the container-runtime you built your cluster with (default docker).
|
||||
Here is a comparison table to help you choose:
|
||||
|
||||
From the host, you can push a Docker image directly to minikube. It will also be cached for future cluster starts.
|
||||
|
||||
| Method | Supported Runtimes | Issues | Performance |
|
||||
|--- |--- |--- |--- |--- |
|
||||
| [docker-env command](/docs/handbook/pushing/#1pushing-directly-to-the-in-cluster-docker-daemon-docker-env) | only docker | | good |
|
||||
| [podman-env command](/docs/handbook/pushing/#3-pushing-directly-to-in-cluster-crio-podman-env) | only cri-o | | good |
|
||||
| [cache add command](/pushing/#push-images-using-cache-command) | all | | ok |
|
||||
| [registry addon](/docs/handbook/pushing/#4-pushing-to-an-in-cluster-using-registry-addon) | all | work in progress for [docker on mac](https://github.com/kubernetes/minikube/issues/7535) | ok |
|
||||
| [minikube ssh](/docs/handbook/pushing/#5-building-images-inside-of-minikube-using-ssh) | all | | best |
|
||||
|
||||
|
||||
* note1 : the default container-runtime on minikube is 'docker'.
|
||||
* note2 : 'none' driver (bare metal) does not need pushing image to the cluster, as any image on your system is already available to the kuberentes.
|
||||
|
||||
---
|
||||
|
||||
## 1.Pushing directly to the in-cluster Docker daemon (docker-env)
|
||||
When using a container or VM driver (all drivers except none), you can reuse the Docker daemon inside minikube cluster.
|
||||
this means you don't have to build on your host machine and push the image into a docker registry. You can just build inside the same docker daemon as minikube which speeds up local experiments.
|
||||
|
||||
To point your terminal to use the docker daemon inside minikube run this:
|
||||
|
||||
```shell
|
||||
minikube cache add ubuntu:16.04
|
||||
eval $(minikube docker-env)
|
||||
```
|
||||
|
||||
The add command will store the requested image to `$MINIKUBE_HOME/cache/images`, and load it into the VM's container runtime environment next time `minikube start` is called.
|
||||
now any 'docker' command you run in this current terminal will run against the docker inside minikube VM or Container.
|
||||
Try it:
|
||||
|
||||
```shell
|
||||
docker ps
|
||||
```
|
||||
|
||||
now you 'build' against the docker inside minikube. which is instantly accessible to kubernetes cluster.
|
||||
|
||||
'''
|
||||
docker build -t myimage .
|
||||
'''
|
||||
|
||||
Remember to turn off the `imagePullPolicy:Always` (use `imagePullPolicy:IfNotPresent` or `imagePullPolicy:Never`), as otherwise Kubernetes won't use images you built locally.
|
||||
|
||||
{{% pageinfo %}}
|
||||
Evaluating the docker-env is only valid for the current terminal.
|
||||
and by closing the terminal, you will go back to using your own system's docker daemon.
|
||||
|
||||
in some drivers such as Docker or Podman, you will need to re-do docker-env each time you restart your minikube.
|
||||
{{% /pageinfo %}}
|
||||
|
||||
To verify your terminal is using minikuber's docker-env you can check the value of the environment variable MINIKUBE_ACTIVE_DOCKERD to reflect the profile name.
|
||||
|
||||
more information on [docker-env](https://minikube.sigs.k8s.io/docs/commands/docker-env/)
|
||||
|
||||
---
|
||||
|
||||
## 2.Push images using 'cache' command.
|
||||
|
||||
From your host, you can push a Docker image directly to minikube. This image will be cached and automatically pulled into all future minikube clusters created on the machine
|
||||
|
||||
```shell
|
||||
minikube cache add alpine:latest
|
||||
```
|
||||
|
||||
The add command will store the requested image to `$MINIKUBE_HOME/cache/images`, and load it into the minikube cluster's container runtime environment automatically.
|
||||
|
||||
{{% pageinfo %}}
|
||||
if your image changes after your cached it, you could do `cache reload` to ensure minikube gets the last updates.
|
||||
|
||||
```
|
||||
shell
|
||||
minikube cache reload
|
||||
```
|
||||
{{% /pageinfo %}}
|
||||
|
||||
To display images you have added to the cache:
|
||||
|
||||
|
|
@ -26,7 +92,8 @@ To display images you have added to the cache:
|
|||
minikube cache list
|
||||
```
|
||||
|
||||
This listing will not include the images which are built-in to minikube.
|
||||
This listing will not include the images minikube's built-in system images.
|
||||
|
||||
|
||||
|
||||
```shell
|
||||
|
|
@ -37,36 +104,9 @@ For more information, see:
|
|||
|
||||
* [Reference: cache command]({{< ref "/docs/commands/cache.md" >}})
|
||||
|
||||
You must be using minikube with the container runtime set to Docker. This is the default setting.
|
||||
---
|
||||
|
||||
# Pushing directly to the in-cluster Docker daemon
|
||||
When user a container or VM driver, it's really handy to reuse the Docker daemon inside minikube; as this means you don't have to build on your host machine and push the image into a docker registry - you can just build inside the same docker daemon as minikube which speeds up local experiments.
|
||||
|
||||
To point your terminal to use the docker daemon inside minikube run this:
|
||||
|
||||
```shell
|
||||
eval $(minikube docker-env)
|
||||
```
|
||||
|
||||
now any command you run in this current terminal will run against the docker inside minikube VM or Container.
|
||||
Try it:
|
||||
|
||||
```shell
|
||||
docker ps
|
||||
```
|
||||
|
||||
now you can use same docker build command against the docker inside minikube. which is instantly accessible to kubernetes cluster.
|
||||
|
||||
'''
|
||||
docker build -t myimage .
|
||||
'''
|
||||
|
||||
|
||||
Remember to turn off the `imagePullPolicy:Always` (use `imagePullPolicy:IfNotPresent` or `imagePullPolicy:Never`), as otherwise Kubernetes won't use images you built locally.
|
||||
|
||||
more information on [docker-env](https://minikube.sigs.k8s.io/docs/commands/docker-env/)
|
||||
|
||||
# Pushing directly to in-cluster CRIO
|
||||
## 3. Pushing directly to in-cluster CRIO. (podman-env)
|
||||
|
||||
To push directly to CRIO, configure podman client on your mac/linux host using the podman-env command in your shell:
|
||||
|
||||
|
|
@ -82,7 +122,9 @@ podman-remote help
|
|||
|
||||
Remember to turn off the `imagePullPolicy:Always` (use `imagePullPolicy:IfNotPresent` or `imagePullPolicy:Never`), as otherwise Kubernetes won't use images you built locally.
|
||||
|
||||
# Pushing to an in-cluster Registry
|
||||
---
|
||||
|
||||
## 4. Pushing to an in-cluster using Registry addon
|
||||
|
||||
For illustration purpose, we will assume that minikube VM has one of the ip from `192.168.39.0/24` subnet. If you have not overridden these subnets as per [networking guide](https://minikube.sigs.k8s.io/reference/networking/), you can find out default subnet being used by minikube for a specific OS and driver combination [here](https://github.com/kubernetes/minikube/blob/dfd9b6b83d0ca2eeab55588a16032688bc26c348/pkg/minikube/cluster/cluster.go#L408) which is subject to change. Replace `192.168.39.0/24` with appropriate values for your environment wherever applicable.
|
||||
|
||||
|
|
@ -108,9 +150,12 @@ Push docker image to minikube registry:
|
|||
docker push $(minikube ip):5000/test-img
|
||||
```
|
||||
|
||||
# Building images inside of minikube
|
||||
---
|
||||
|
||||
Use `minikube ssh` to connect to the virtual machine, and run the `docker build` there:
|
||||
## 5. Building images inside of minikube using SSH
|
||||
|
||||
Use `minikube ssh` to run commands inside the minikube node, and run the `docker build` directly there.
|
||||
Any command you run there will run against the same daemon that kubernetes cluster is using.
|
||||
|
||||
```shell
|
||||
docker build
|
||||
|
|
@ -126,3 +171,7 @@ sudo -E podman build
|
|||
|
||||
For more information on the `podman build` command, read the [Podman documentation](https://github.com/containers/libpod/blob/master/docs/source/markdown/podman-build.1.md) (podman.io).
|
||||
|
||||
to exit minikube ssh and come back to your terminal type:
|
||||
```shell
|
||||
exit
|
||||
```
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit e13afeb5c0ffa5a2dff237fffa77bea80319f578
|
||||
Subproject commit dd303fd19cc13ffc01bcbe86ff54f21e423d04de
|
||||
|
|
@ -73,6 +73,11 @@ func TestFunctional(t *testing.T) {
|
|||
if err := os.Remove(p); err != nil {
|
||||
t.Logf("unable to remove %q: %v", p, err)
|
||||
}
|
||||
p = localEmptyCertPath()
|
||||
if err := os.Remove(p); err != nil {
|
||||
t.Logf("unable to remove %q: %v", p, err)
|
||||
}
|
||||
|
||||
CleanupWithLogs(t, profile, cancel)
|
||||
}()
|
||||
|
||||
|
|
@ -793,18 +798,44 @@ func localTestCertPath() string {
|
|||
return filepath.Join(localpath.MiniPath(), "/certs", testCert())
|
||||
}
|
||||
|
||||
// localEmptyCertPath is where the test file will be synced into the VM
|
||||
func localEmptyCertPath() string {
|
||||
return filepath.Join(localpath.MiniPath(), "/certs", fmt.Sprintf("%d_empty.pem", os.Getpid()))
|
||||
}
|
||||
|
||||
// Copy extra file into minikube home folder for file sync test
|
||||
func setupFileSync(ctx context.Context, t *testing.T, profile string) {
|
||||
p := localSyncTestPath()
|
||||
t.Logf("local sync path: %s", p)
|
||||
err := copy.Copy("./testdata/sync.test", p)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to copy ./testdata/sync.test : %v", err)
|
||||
t.Fatalf("failed to copy ./testdata/sync.test: %v", err)
|
||||
}
|
||||
|
||||
err = copy.Copy("./testdata/minikube_test.pem", localTestCertPath())
|
||||
testPem := "./testdata/minikube_test.pem"
|
||||
|
||||
err = copy.Copy(testPem, localTestCertPath())
|
||||
if err != nil {
|
||||
t.Fatalf("failed to copy ./testdata/minikube_test.pem : %v", err)
|
||||
t.Fatalf("failed to copy %s: %v", testPem, err)
|
||||
}
|
||||
|
||||
want, err := os.Stat(testPem)
|
||||
if err != nil {
|
||||
t.Fatalf("stat failed: %v", err)
|
||||
}
|
||||
|
||||
got, err := os.Stat(localTestCertPath())
|
||||
if err != nil {
|
||||
t.Fatalf("stat failed: %v", err)
|
||||
}
|
||||
|
||||
if want.Size() != got.Size() {
|
||||
t.Errorf("%s size=%d, want %d", localTestCertPath(), got.Size(), want.Size())
|
||||
}
|
||||
|
||||
// Create an empty file just to mess with people
|
||||
if _, err := os.Create(localEmptyCertPath()); err != nil {
|
||||
t.Fatalf("create failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -203,7 +203,8 @@ func clusterLogs(t *testing.T, profile string) {
|
|||
|
||||
t.Logf("-----------------------post-mortem--------------------------------")
|
||||
t.Logf("<<< %s FAILED: start of post-mortem logs <<<", t.Name())
|
||||
t.Logf("-------------------post-mortem minikube logs----------------------")
|
||||
t.Logf("======> post-mortem[%s]: minikube logs <======", t.Name())
|
||||
|
||||
rr, err := Run(t, exec.Command(Target(), "-p", profile, "logs", "--problems"))
|
||||
if err != nil {
|
||||
t.Logf("failed logs error: %v", err)
|
||||
|
|
@ -211,27 +212,43 @@ func clusterLogs(t *testing.T, profile string) {
|
|||
}
|
||||
t.Logf("%s logs: %s", t.Name(), rr.Output())
|
||||
|
||||
t.Logf("------------------post-mortem api server status-------------------")
|
||||
t.Logf("======> post-mortem[%s]: disk usage <======", t.Name())
|
||||
rr, err = Run(t, exec.Command(Target(), "-p", profile, "ssh", "df -h /var/lib/docker/overlay2 /var /; du -hs /var/lib/docker/overlay2"))
|
||||
if err != nil {
|
||||
t.Logf("failed df error: %v", err)
|
||||
}
|
||||
t.Logf("%s df: %s", t.Name(), rr.Stdout)
|
||||
|
||||
st = Status(context.Background(), t, Target(), profile, "APIServer")
|
||||
if st != state.Running.String() {
|
||||
t.Logf("%q apiserver is not running, skipping kubectl commands (state=%q)", profile, st)
|
||||
return
|
||||
}
|
||||
t.Logf("--------------------post-mortem get pods--------------------------")
|
||||
|
||||
t.Logf("======> post-mortem[%s]: get pods <======", t.Name())
|
||||
rr, rerr := Run(t, exec.Command("kubectl", "--context", profile, "get", "po", "-A", "--show-labels"))
|
||||
if rerr != nil {
|
||||
t.Logf("%s: %v", rr.Command(), rerr)
|
||||
return
|
||||
}
|
||||
t.Logf("(dbg) %s:\n%s", rr.Command(), rr.Output())
|
||||
t.Logf("-------------------post-mortem describe node----------------------")
|
||||
|
||||
t.Logf("======> post-mortem[%s]: describe node <======", t.Name())
|
||||
rr, err = Run(t, exec.Command("kubectl", "--context", profile, "describe", "node"))
|
||||
if err != nil {
|
||||
t.Logf("%s: %v", rr.Command(), err)
|
||||
} else {
|
||||
t.Logf("(dbg) %s:\n%s", rr.Command(), rr.Output())
|
||||
}
|
||||
t.Logf("------------------------------------------------------------------")
|
||||
|
||||
t.Logf("======> post-mortem[%s]: describe pods <======", t.Name())
|
||||
rr, err = Run(t, exec.Command("kubectl", "--context", profile, "describe", "po", "-A"))
|
||||
if err != nil {
|
||||
t.Logf("%s: %v", rr.Command(), err)
|
||||
} else {
|
||||
t.Logf("(dbg) %s:\n%s", rr.Command(), rr.Stdout)
|
||||
}
|
||||
|
||||
t.Logf("<<< %s FAILED: end of post-mortem logs <<<", t.Name())
|
||||
t.Logf("---------------------/post-mortem---------------------------------")
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue