-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Split cluster package into multiple files (#6484)
* Split cluster package into multiple files * Name restart/ressurect functions fix * Minor refactor fixes
- Loading branch information
1 parent
a50ebb8
commit d35c825
Showing
11 changed files
with
952 additions
and
707 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
/* | ||
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 cluster | ||
|
||
import ( | ||
"os/exec" | ||
|
||
"github.com/docker/machine/libmachine" | ||
"github.com/docker/machine/libmachine/mcnerror" | ||
"github.com/docker/machine/libmachine/state" | ||
"github.com/golang/glog" | ||
"github.com/pkg/errors" | ||
"k8s.io/minikube/pkg/drivers/kic/oci" | ||
"k8s.io/minikube/pkg/minikube/driver" | ||
"k8s.io/minikube/pkg/minikube/out" | ||
) | ||
|
||
// deleteOrphanedKIC attempts to delete an orphaned docker instance | ||
func deleteOrphanedKIC(name string) { | ||
cmd := exec.Command(oci.Docker, "rm", "-f", "-v", name) | ||
err := cmd.Run() | ||
if err == nil { | ||
glog.Infof("Found stale kic container and successfully cleaned it up!") | ||
} | ||
} | ||
|
||
// DeleteHost deletes the host VM. | ||
func DeleteHost(api libmachine.API, machineName string) error { | ||
host, err := api.Load(machineName) | ||
if err != nil && host == nil { | ||
deleteOrphanedKIC(machineName) | ||
// keep going even if minikube does not know about the host | ||
} | ||
|
||
// Get the status of the host. Ensure that it exists before proceeding ahead. | ||
status, err := GetHostStatus(api, machineName) | ||
if err != nil { | ||
// Warn, but proceed | ||
out.WarningT("Unable to get the status of the {{.name}} cluster.", out.V{"name": machineName}) | ||
} | ||
|
||
if status == state.None.String() { | ||
return mcnerror.ErrHostDoesNotExist{Name: machineName} | ||
} | ||
|
||
// This is slow if SSH is not responding, but HyperV hangs otherwise, See issue #2914 | ||
if host.Driver.DriverName() == driver.HyperV { | ||
if err := trySSHPowerOff(host); err != nil { | ||
glog.Infof("Unable to power off minikube because the host was not found.") | ||
} | ||
out.T(out.DeletingHost, "Successfully powered off Hyper-V. minikube driver -- {{.driver}}", out.V{"driver": host.Driver.DriverName()}) | ||
} | ||
|
||
out.T(out.DeletingHost, `Deleting "{{.profile_name}}" in {{.driver_name}} ...`, out.V{"profile_name": machineName, "driver_name": host.DriverName}) | ||
if err := host.Driver.Remove(); err != nil { | ||
return errors.Wrap(err, "host remove") | ||
} | ||
if err := api.Remove(machineName); err != nil { | ||
return errors.Wrap(err, "api remove") | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/* | ||
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 cluster | ||
|
||
import ( | ||
"fmt" | ||
"net" | ||
|
||
"github.com/docker/machine/libmachine" | ||
"github.com/pkg/errors" | ||
"github.com/spf13/viper" | ||
"k8s.io/minikube/pkg/drivers/kic" | ||
"k8s.io/minikube/pkg/drivers/kic/oci" | ||
"k8s.io/minikube/pkg/minikube/config" | ||
"k8s.io/minikube/pkg/minikube/constants" | ||
"k8s.io/minikube/pkg/minikube/driver" | ||
"k8s.io/minikube/pkg/minikube/localpath" | ||
) | ||
|
||
// GetHostDockerEnv gets the necessary docker env variables to allow the use of docker through minikube's vm | ||
func GetHostDockerEnv(api libmachine.API) (map[string]string, error) { | ||
pName := viper.GetString(config.MachineProfile) | ||
host, err := CheckIfHostExistsAndLoad(api, pName) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "Error checking that api exists and loading it") | ||
} | ||
|
||
ip := kic.DefaultBindIPV4 | ||
if !driver.IsKIC(host.Driver.DriverName()) { // kic externally accessible ip is different that node ip | ||
ip, err = host.Driver.GetIP() | ||
if err != nil { | ||
return nil, errors.Wrap(err, "Error getting ip from host") | ||
} | ||
|
||
} | ||
|
||
tcpPrefix := "tcp://" | ||
port := constants.DockerDaemonPort | ||
if driver.IsKIC(host.Driver.DriverName()) { // for kic we need to find out what port docker allocated during creation | ||
port, err = oci.HostPortBinding(host.Driver.DriverName(), pName, constants.DockerDaemonPort) | ||
if err != nil { | ||
return nil, errors.Wrapf(err, "get hostbind port for %d", constants.DockerDaemonPort) | ||
} | ||
} | ||
|
||
envMap := map[string]string{ | ||
"DOCKER_TLS_VERIFY": "1", | ||
"DOCKER_HOST": tcpPrefix + net.JoinHostPort(ip, fmt.Sprint(port)), | ||
"DOCKER_CERT_PATH": localpath.MakeMiniPath("certs"), | ||
} | ||
return envMap, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
/* | ||
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 cluster | ||
|
||
import ( | ||
"fmt" | ||
"math" | ||
"strconv" | ||
"strings" | ||
"time" | ||
|
||
"github.com/docker/machine/libmachine" | ||
"github.com/docker/machine/libmachine/host" | ||
"github.com/docker/machine/libmachine/provision" | ||
"github.com/docker/machine/libmachine/state" | ||
"github.com/golang/glog" | ||
"github.com/pkg/errors" | ||
"k8s.io/minikube/pkg/minikube/config" | ||
"k8s.io/minikube/pkg/minikube/out" | ||
"k8s.io/minikube/pkg/util/retry" | ||
) | ||
|
||
// hostRunner is a minimal host.Host based interface for running commands | ||
type hostRunner interface { | ||
RunSSHCommand(string) (string, error) | ||
} | ||
|
||
const ( | ||
// The maximum the guest VM clock is allowed to be ahead and behind. This value is intentionally | ||
// large to allow for inaccurate methodology, but still small enough so that certificates are likely valid. | ||
maxClockDesyncSeconds = 2.1 | ||
) | ||
|
||
// fixHost fixes up a previously configured VM so that it is ready to run Kubernetes | ||
func fixHost(api libmachine.API, mc config.MachineConfig) (*host.Host, error) { | ||
out.T(out.Waiting, "Reconfiguring existing host ...") | ||
|
||
start := time.Now() | ||
glog.Infof("fixHost starting: %s", mc.Name) | ||
defer func() { | ||
glog.Infof("fixHost completed within %s", time.Since(start)) | ||
}() | ||
|
||
h, err := api.Load(mc.Name) | ||
if err != nil { | ||
return h, errors.Wrap(err, "Error loading existing host. Please try running [minikube delete], then run [minikube start] again.") | ||
} | ||
|
||
s, err := h.Driver.GetState() | ||
if err != nil { | ||
return h, errors.Wrap(err, "Error getting state for host") | ||
} | ||
|
||
if s == state.Running { | ||
out.T(out.Running, `Using the running {{.driver_name}} "{{.profile_name}}" VM ...`, out.V{"driver_name": mc.VMDriver, "profile_name": mc.Name}) | ||
} else { | ||
out.T(out.Restarting, `Starting existing {{.driver_name}} VM for "{{.profile_name}}" ...`, out.V{"driver_name": mc.VMDriver, "profile_name": mc.Name}) | ||
if err := h.Driver.Start(); err != nil { | ||
return h, errors.Wrap(err, "driver start") | ||
} | ||
if err := api.Save(h); err != nil { | ||
return h, errors.Wrap(err, "save") | ||
} | ||
} | ||
|
||
e := engineOptions(mc) | ||
if len(e.Env) > 0 { | ||
h.HostOptions.EngineOptions.Env = e.Env | ||
glog.Infof("Detecting provisioner ...") | ||
provisioner, err := provision.DetectProvisioner(h.Driver) | ||
if err != nil { | ||
return h, errors.Wrap(err, "detecting provisioner") | ||
} | ||
if err := provisioner.Provision(*h.HostOptions.SwarmOptions, *h.HostOptions.AuthOptions, *h.HostOptions.EngineOptions); err != nil { | ||
return h, errors.Wrap(err, "provision") | ||
} | ||
} | ||
|
||
if err := postStartSetup(h, mc); err != nil { | ||
return h, errors.Wrap(err, "post-start") | ||
} | ||
|
||
glog.Infof("Configuring auth for driver %s ...", h.Driver.DriverName()) | ||
if err := h.ConfigureAuth(); err != nil { | ||
return h, &retry.RetriableError{Err: errors.Wrap(err, "Error configuring auth on host")} | ||
} | ||
return h, ensureSyncedGuestClock(h) | ||
} | ||
|
||
// ensureGuestClockSync ensures that the guest system clock is relatively in-sync | ||
func ensureSyncedGuestClock(h hostRunner) error { | ||
d, err := guestClockDelta(h, time.Now()) | ||
if err != nil { | ||
glog.Warningf("Unable to measure system clock delta: %v", err) | ||
return nil | ||
} | ||
if math.Abs(d.Seconds()) < maxClockDesyncSeconds { | ||
glog.Infof("guest clock delta is within tolerance: %s", d) | ||
return nil | ||
} | ||
if err := adjustGuestClock(h, time.Now()); err != nil { | ||
return errors.Wrap(err, "adjusting system clock") | ||
} | ||
return nil | ||
} | ||
|
||
// guestClockDelta returns the approximate difference between the host and guest system clock | ||
// NOTE: This does not currently take into account ssh latency. | ||
func guestClockDelta(h hostRunner, local time.Time) (time.Duration, error) { | ||
out, err := h.RunSSHCommand("date +%s.%N") | ||
if err != nil { | ||
return 0, errors.Wrap(err, "get clock") | ||
} | ||
glog.Infof("guest clock: %s", out) | ||
ns := strings.Split(strings.TrimSpace(out), ".") | ||
secs, err := strconv.ParseInt(strings.TrimSpace(ns[0]), 10, 64) | ||
if err != nil { | ||
return 0, errors.Wrap(err, "atoi") | ||
} | ||
nsecs, err := strconv.ParseInt(strings.TrimSpace(ns[1]), 10, 64) | ||
if err != nil { | ||
return 0, errors.Wrap(err, "atoi") | ||
} | ||
// NOTE: In a synced state, remote is a few hundred ms ahead of local | ||
remote := time.Unix(secs, nsecs) | ||
d := remote.Sub(local) | ||
glog.Infof("Guest: %s Remote: %s (delta=%s)", remote, local, d) | ||
return d, nil | ||
} | ||
|
||
// adjustSystemClock adjusts the guest system clock to be nearer to the host system clock | ||
func adjustGuestClock(h hostRunner, t time.Time) error { | ||
out, err := h.RunSSHCommand(fmt.Sprintf("sudo date -s @%d", t.Unix())) | ||
glog.Infof("clock set: %s (err=%v)", out, err) | ||
return err | ||
} |
Oops, something went wrong.