Add podman driver (#6515)

pull/6616/head
Medya Ghazizadeh 2020-02-12 19:11:44 -07:00 committed by GitHub
parent 434176ffad
commit 398c7ef00b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 397 additions and 135 deletions

View File

@ -142,3 +142,37 @@ jobs:
with:
name: none_on_ubuntu_latest_report
path: report
podman_ubuntu_18_04:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- name: install podman
run: |
. /etc/os-release
sudo sh -c "echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${VERSION_ID}/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list"
wget -q https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/xUbuntu_${VERSION_ID}/Release.key -O- | sudo apt-key add -
sudo apt-key add - < Release.key || true
sudo apt-get update -qq
sudo apt-get -qq -y install podman
- name: build binaries
run : |
make minikube-linux-amd64
make e2e-linux-amd64
- name: install gopogh
run: |
cd /tmp
GO111MODULE="on" go get github.com/medyagh/gopogh@v0.0.17 || true
cd -
- name: run integration test
run: |
mkdir -p /tmp/testhome
MINIKUBE_HOME=/tmp/testhome sudo -E ./out/e2e-linux-amd64 -minikube-start-args=--vm-driver=podman -expected-default-driver= -test.timeout=70m -test.v -binary=out/minikube-linux-amd64 2>&1 | tee ./report/testout.txt
- name: generate gopogh report
run: |
export PATH=${PATH}:`go env GOPATH`/bin
go tool test2json -t < ./report/testout.txt > ./report/testout.json || true
gopogh -in ./report/testout.json -out ./report/testout.html -name "docker ubuntu" -repo github.com/kubernetes/minikube/ || true
- uses: actions/upload-artifact@v1
with:
name: podman_on_ubuntu_latest_report
path: report

View File

@ -32,7 +32,6 @@ import (
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"k8s.io/minikube/pkg/drivers/kic"
"k8s.io/minikube/pkg/drivers/kic/oci"
"k8s.io/minikube/pkg/minikube/cluster"
"k8s.io/minikube/pkg/minikube/config"
@ -269,7 +268,7 @@ func dockerEnvVars(ec DockerEnvConfig) (map[string]string, error) {
if err != nil {
return nil, errors.Wrapf(err, "get hostbind port for %d", constants.DockerDaemonPort)
}
env[constants.DockerCertPathEnv] = dockerURL(kic.DefaultBindIPV4, port)
env[constants.DockerCertPathEnv] = dockerURL(oci.DefaultBindIPV4, port)
}
return env, nil
}

View File

@ -747,11 +747,11 @@ func validateUser(drvName string) {
useForce := viper.GetBool(force)
if driver.BareMetal(drvName) && u.Uid != "0" && !useForce {
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 --vm-driver={{.driver_name}}'.`, out.V{"driver_name": drvName})
}
if driver.BareMetal(drvName) || u.Uid != "0" {
if driver.NeedsRoot(drvName) || u.Uid != "0" {
return
}
@ -815,16 +815,18 @@ func validateFlags(cmd *cobra.Command, drvName string) {
validateDiskSize()
validateMemorySize()
if driver.BareMetal(drvName) {
if viper.GetString(config.MachineProfile) != constants.DefaultMachineName {
exit.WithCodeT(exit.Config, "The 'none' driver does not support multiple profiles: https://minikube.sigs.k8s.io/docs/reference/drivers/none/")
}
if !driver.HasResourceLimits(drvName) { // both podman and none need root and they both cant specify resources
if cmd.Flags().Changed(cpus) {
out.WarningT("The 'none' driver does not respect the --cpus flag")
out.WarningT("The '{{.name}}' driver does not respect the --cpus flag", out.V{"name": drvName})
}
if cmd.Flags().Changed(memory) {
out.WarningT("The 'none' driver does not respect the --memory flag")
out.WarningT("The '{{.name}}' driver does not respect the --memory flag", out.V{"name": drvName})
}
}
if driver.BareMetal(drvName) {
if viper.GetString(config.MachineProfile) != constants.DefaultMachineName {
exit.WithCodeT(exit.Config, "The '{{.name}} driver does not support multiple profiles: https://minikube.sigs.k8s.io/docs/reference/drivers/none/", out.V{"name": drvName})
}
runtime := viper.GetString(containerRuntime)

View File

@ -27,8 +27,13 @@
readonly TEST_ROOT="${HOME}/minikube-integration"
readonly TEST_HOME="${TEST_ROOT}/${OS_ARCH}-${VM_DRIVER}-${MINIKUBE_LOCATION}-$$-${COMMIT}"
export GOPATH="$HOME/go"
export KUBECONFIG="${TEST_HOME}/kubeconfig"
export PATH=$PATH:"/usr/local/bin/:/usr/local/go/bin/:$GOPATH/bin"
# installing golang so we could do go get for gopogh
sudo ./installers/check_install_golang.sh "1.13.4" "/usr/local" || true
echo ">> Starting at $(date)"
echo ""
echo "arch: ${OS_ARCH}"
@ -42,6 +47,7 @@ echo "uptime: $(uptime)"
# Setting KUBECONFIG prevents the version ceck from erroring out due to permission issues
echo "kubectl: $(env KUBECONFIG=${TEST_HOME} kubectl version --client --short=true)"
echo "docker: $(docker version --format '{{ .Client.Version }}')"
echo "podman: $(sudo podman version --format '{{.Version}}' || true)"
echo "go: $(go version || true)"
@ -235,7 +241,6 @@ cleanup_stale_routes || true
mkdir -p "${TEST_HOME}"
export MINIKUBE_HOME="${TEST_HOME}/.minikube"
export KUBECONFIG="${TEST_HOME}/kubeconfig"
# Build the gvisor image so that we can integration test changes to pkg/gvisor
@ -319,7 +324,7 @@ touch "${JSON_OUT}"
echo ">> Running go test2json"
go tool test2json -t < "${TEST_OUT}" > "${JSON_OUT}" || true
echo ">> Installing gopogh"
cd /tmp
cd $(mktemp -d)
GO111MODULE="on" go get -u github.com/medyagh/gopogh@v0.0.17 || true
cd -
echo ">> Running gopogh"
@ -347,7 +352,7 @@ fi
echo ">> Cleaning up after ourselves ..."
${SUDO_PREFIX}${MINIKUBE_BIN} tunnel --cleanup || true
${SUDO_PREFIX}${MINIKUBE_BIN} delete --all >/dev/null 2>/dev/null || true
${SUDO_PREFIX}${MINIKUBE_BIN} delete --all --purge >/dev/null 2>/dev/null || true
cleanup_stale_routes || true
${SUDO_PREFIX} rm -Rf "${MINIKUBE_HOME}" || true

View File

@ -32,4 +32,7 @@ JOB_NAME="Docker_Linux"
mkdir -p cron && gsutil -qm rsync "gs://minikube-builds/${MINIKUBE_LOCATION}/cron" cron || echo "FAILED TO GET CRON FILES"
sudo install cron/cleanup_and_reboot_Linux.sh /etc/cron.hourly/cleanup_and_reboot || echo "FAILED TO INSTALL CLEANUP"
# removing possible left over docker containers from previous runs
docker rm -f -v $(docker ps -aq) >/dev/null 2>&1 || true
source ./common.sh

View File

@ -44,8 +44,8 @@ docker rm -f $(docker ps -aq) >/dev/null 2>&1 || true
sudo rm -rf /data/*
# Cleanup old Kubernetes configs
sudo rm -rf /etc/kubernetes/*
# Cleanup old minikube files
sudo rm -rf /var/lib/minikube/*
sudo rm -rf /var/lib/minikube/*
# Stop any leftover kubelets
systemctl is-active --quiet kubelet \
&& echo "stopping kubelet" \

View File

@ -0,0 +1,41 @@
#!/bin/bash
# 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.
# This script runs the integration tests on a Linux machine for the KVM Driver
# The script expects the following env variables:
# MINIKUBE_LOCATION: GIT_COMMIT from upstream build.
# COMMIT: Actual commit ID from upstream build
# EXTRA_BUILD_ARGS (optional): Extra args to be passed into the minikube integrations tests
# access_token: The Github API access token. Injected by the Jenkins credential provider.
set -e
OS_ARCH="linux-amd64"
VM_DRIVER="podman"
JOB_NAME="Podman_Linux"
mkdir -p cron && gsutil -qm rsync "gs://minikube-builds/${MINIKUBE_LOCATION}/cron" cron || echo "FAILED TO GET CRON FILES"
sudo install cron/cleanup_and_reboot_Linux.sh /etc/cron.hourly/cleanup_and_reboot || echo "FAILED TO INSTALL CLEANUP"
SUDO_PREFIX="sudo -E "
EXTRA_ARGS="--container-runtime=containerd"
# remove possible left over podman containers
sudo podman rm -f -v $(sudo podman ps -aq) || true
source ./common.sh

View File

@ -41,6 +41,7 @@ jobs=(
'KVM_Linux'
'none_Linux'
'Docker_Linux'
'Podman_Linux'
)
# retry_github_status provides reliable github status updates

View File

@ -17,11 +17,13 @@ limitations under the License.
package addons
import (
"fmt"
"os/exec"
"path"
"k8s.io/minikube/pkg/minikube/config"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/vmpath"
)
var (
@ -41,7 +43,7 @@ func kubectlCommand(profile string, files []string, enable bool) (*exec.Cmd, err
kubectlAction = "delete"
}
args := []string{"KUBECONFIG=/var/lib/minikube/kubeconfig", kubectlBinary, kubectlAction}
args := []string{fmt.Sprintf("KUBECONFIG=%s", path.Join(vmpath.GuestPersistentDir, "kubeconfig")), kubectlBinary, kubectlAction}
for _, f := range files {
args = append(args, []string{"-f", f}...)
}
@ -63,5 +65,5 @@ func kubernetesVersion(profile string) (string, error) {
}
func kubectlBinaryPath(version string) string {
return path.Join("/var/lib/minikube/binaries", version, "kubectl")
return path.Join(vmpath.GuestPersistentDir, "binaries", version, "kubectl")
}

View File

@ -36,7 +36,7 @@ import (
"k8s.io/minikube/pkg/minikube/constants"
)
// Driver represents a kic driver https://minikube.sigs.k8s.io/docs/reference/drivers/kic/
// Driver represents a kic driver https://minikube.sigs.k8s.io/docs/reference/drivers/docker
type Driver struct {
*drivers.BaseDriver
*pkgdrivers.CommonDriver
@ -76,15 +76,15 @@ func (d *Driver) Create() error {
// control plane specific options
params.PortMappings = append(params.PortMappings, oci.PortMapping{
ListenAddress: DefaultBindIPV4,
ListenAddress: oci.DefaultBindIPV4,
ContainerPort: constants.APIServerPort,
},
oci.PortMapping{
ListenAddress: DefaultBindIPV4,
ListenAddress: oci.DefaultBindIPV4,
ContainerPort: constants.SSHPort,
},
oci.PortMapping{
ListenAddress: DefaultBindIPV4,
ListenAddress: oci.DefaultBindIPV4,
ContainerPort: constants.DockerDaemonPort,
},
)
@ -138,12 +138,12 @@ func (d *Driver) GetIP() (string, error) {
// GetExternalIP returns an IP which is accissble from outside
func (d *Driver) GetExternalIP() (string, error) {
return DefaultBindIPV4, nil
return oci.DefaultBindIPV4, nil
}
// GetSSHHostname returns hostname for use with ssh
func (d *Driver) GetSSHHostname() (string, error) {
return DefaultBindIPV4, nil
return oci.DefaultBindIPV4, nil
}
// GetSSHPort returns port for use with ssh
@ -186,7 +186,7 @@ func (d *Driver) GetState() (state.State, error) {
cmd := exec.Command(d.NodeConfig.OCIBinary, "inspect", "-f", "{{.State.Status}}", d.MachineName)
out, err := cmd.CombinedOutput()
o := strings.Trim(string(out), "\n")
o := strings.TrimSpace(string(out))
if err != nil {
return state.Error, errors.Wrapf(err, "get container %s status", d.MachineName)
}
@ -222,7 +222,7 @@ func (d *Driver) Remove() error {
}
cmd := exec.Command(d.NodeConfig.OCIBinary, "rm", "-f", "-v", d.MachineName)
o, err := cmd.CombinedOutput()
out := strings.Trim(string(o), "\n")
out := strings.TrimSpace(string(o))
if err != nil {
if strings.Contains(out, "is already in progress") {
log.Warnf("Docker engine is stuck. please restart docker daemon on your computer.", d.MachineName)

View File

@ -18,6 +18,7 @@ package oci
import (
"os"
"path/filepath"
"strconv"
"bufio"
@ -26,6 +27,7 @@ import (
"github.com/golang/glog"
"github.com/pkg/errors"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/localpath"
"fmt"
"os/exec"
@ -39,8 +41,6 @@ func CreateContainerNode(p CreateParams) error {
}
runArgs := []string{
fmt.Sprintf("--cpus=%s", p.CPUs),
fmt.Sprintf("--memory=%s", p.Memory),
"-d", // run the container detached
"-t", // allocate a tty for entrypoint logs
// running containers in a container requires privileged
@ -53,7 +53,6 @@ func CreateContainerNode(p CreateParams) error {
"--tmpfs", "/tmp", // various things depend on working /tmp
"--tmpfs", "/run", // systemd wants a writable /run
// logs,pods be stroed on filesystem vs inside container,
"--volume", "/var",
// some k8s things want /lib/modules
"-v", "/lib/modules:/lib/modules:ro",
"--hostname", p.Name, // make hostname match container name
@ -64,6 +63,23 @@ func CreateContainerNode(p CreateParams) error {
"--label", fmt.Sprintf("%s=%s", nodeRoleKey, p.Role),
}
// volume path in minikube home folder to mount to /var
hostVarVolPath := filepath.Join(localpath.MiniPath(), "machines", p.Name, "var")
if err := os.MkdirAll(hostVarVolPath, 0711); err != nil {
return errors.Wrapf(err, "create var dir %s", hostVarVolPath)
}
if p.OCIBinary == Podman { // enable execing in /var
// podman mounts var/lib with no-exec by default https://github.com/containers/libpod/issues/5103
runArgs = append(runArgs, "--volume", fmt.Sprintf("%s:/var:exec", hostVarVolPath))
}
if p.OCIBinary == Docker {
runArgs = append(runArgs, "--volume", fmt.Sprintf("%s:/var", hostVarVolPath))
// 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"
runArgs = append(runArgs, fmt.Sprintf("--cpus=%s", p.CPUs), fmt.Sprintf("--memory=%s", p.Memory))
}
for key, val := range p.Envs {
runArgs = append(runArgs, "-e", fmt.Sprintf("%s=%s", key, val))
}
@ -113,6 +129,10 @@ func createContainer(ociBinary string, image string, opts ...createOpt) ([]strin
}
// construct the actual docker run argv
args := []string{"run"}
// to run nested container from privileged container in podman https://bugzilla.redhat.com/show_bug.cgi?id=1687713
if ociBinary == Podman {
args = append(args, "--cgroup-manager", "cgroupfs")
}
args = append(args, runArgs...)
args = append(args, image)
args = append(args, o.ContainerArgs...)
@ -159,12 +179,24 @@ func HostPortBinding(ociBinary string, ociID string, contPort int) (int, error)
if err := PointToHostDockerDaemon(); err != nil {
return 0, errors.Wrap(err, "point host docker-daemon")
}
cmd := exec.Command(ociBinary, "inspect", "-f", fmt.Sprintf("'{{(index (index .NetworkSettings.Ports \"%d/tcp\") 0).HostPort}}'", contPort), ociID)
out, err := cmd.CombinedOutput()
if err != nil {
return 0, errors.Wrapf(err, "getting host-bind port %d for container ID %q, output %s", contPort, ociID, out)
var out []byte
var err error
if ociBinary == Podman {
//podman inspect -f "{{range .NetworkSettings.Ports}}{{if eq .ContainerPort "80"}}{{.HostPort}}{{end}}{{end}}"
cmd := exec.Command(ociBinary, "inspect", "-f", fmt.Sprintf("{{range .NetworkSettings.Ports}}{{if eq .ContainerPort %s}}{{.HostPort}}{{end}}{{end}}", fmt.Sprint(contPort)), ociID)
out, err = cmd.CombinedOutput()
if err != nil {
return 0, errors.Wrapf(err, "get host-bind port %d for %q, output %s", contPort, ociID, out)
}
} else {
cmd := exec.Command(ociBinary, "inspect", "-f", fmt.Sprintf("'{{(index (index .NetworkSettings.Ports \"%d/tcp\") 0).HostPort}}'", contPort), ociID)
out, err = cmd.CombinedOutput()
if err != nil {
return 0, errors.Wrapf(err, "get host-bind port %d for %q, output %s", contPort, ociID, out)
}
}
o := strings.Trim(string(out), "\n")
o := strings.TrimSpace(string(out))
o = strings.Trim(o, "'")
p, err := strconv.Atoi(o)
if err != nil {
@ -175,11 +207,35 @@ func HostPortBinding(ociBinary string, ociID string, contPort int) (int, error)
// ContainerIPs returns ipv4,ipv6, error of a container by their name
func ContainerIPs(ociBinary string, name string) (string, string, error) {
if ociBinary == Podman {
return podmanConttainerIP(name)
}
return dockerContainerIP(name)
}
// podmanConttainerIP returns ipv4, ipv6 of container or error
func podmanConttainerIP(name string) (string, string, error) {
cmd := exec.Command(Podman, "inspect",
"-f", "{{.NetworkSettings.IPAddress}}",
name)
out, err := cmd.CombinedOutput()
if err != nil {
return "", "", errors.Wrapf(err, "podman inspect ip %s", name)
}
output := strings.TrimSpace(string(out))
if err == nil && output == "" { // podman returns empty for 127.0.0.1
return DefaultBindIPV4, "", nil
}
return output, "", nil
}
// dockerContainerIP returns ipv4, ipv6 of container or error
func dockerContainerIP(name string) (string, string, error) {
if err := PointToHostDockerDaemon(); err != nil {
return "", "", errors.Wrap(err, "point host docker-daemon")
}
// retrieve the IP address of the node using docker inspect
lines, err := inspect(ociBinary, name, "{{range .NetworkSettings.Networks}}{{.IPAddress}},{{.GlobalIPv6Address}}{{end}}")
lines, err := inspect(Docker, name, "{{range .NetworkSettings.Networks}}{{.IPAddress}},{{.GlobalIPv6Address}}{{end}}")
if err != nil {
return "", "", errors.Wrap(err, "inspecting NetworkSettings.Networks")
}
@ -191,7 +247,6 @@ func ContainerIPs(ociBinary string, name string) (string, string, error) {
return "", "", errors.Errorf("container addresses should have 2 values, got %d values: %+v", len(ips), ips)
}
return ips[0], ips[1], nil
}
// ContainerID returns id of a container name

View File

@ -17,8 +17,10 @@ limitations under the License.
package oci
const (
Docker = "docker"
Podman = "podman"
// DefaultBindIPV4 is The default IP the container will listen on.
DefaultBindIPV4 = "127.0.0.1"
Docker = "docker"
Podman = "podman"
// ClusterLabelKey is applied to each node docker container for identification
ClusterLabelKey = "io.x-k8s.kic.cluster"
// NodeRoleKey is used to identify if it is control plane or worker

View File

@ -23,8 +23,7 @@ const (
DefaultNetwork = "bridge"
// DefaultPodCIDR is The CIDR to be used for pods inside the node.
DefaultPodCIDR = "10.244.0.0/16"
// DefaultBindIPV4 is The default IP the container will bind to.
DefaultBindIPV4 = "127.0.0.1"
// BaseImage is the base image is used to spin up kic containers. it uses same base-image as kind.
BaseImage = "gcr.io/k8s-minikube/kicbase:v0.0.5@sha256:3ddd8461dfb5c3e452ccc44d87750b87a574ec23fc425da67dccc1f0c57d428a"
// OverlayImage is the cni plugin used for overlay image, created by kind.

View File

@ -32,7 +32,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/tools/clientcmd/api"
"k8s.io/client-go/tools/clientcmd/api/latest"
"k8s.io/minikube/pkg/drivers/kic"
"k8s.io/minikube/pkg/drivers/kic/oci"
"k8s.io/minikube/pkg/minikube/assets"
"k8s.io/minikube/pkg/minikube/command"
"k8s.io/minikube/pkg/minikube/config"
@ -169,7 +169,7 @@ func generateCerts(k8s config.KubernetesConfig, n config.Node) error {
apiServerIPs := append(
k8s.APIServerIPs,
[]net.IP{net.ParseIP(n.IP), serviceIP, net.ParseIP(kic.DefaultBindIPV4), net.ParseIP("10.0.0.1")}...)
[]net.IP{net.ParseIP(n.IP), serviceIP, net.ParseIP(oci.DefaultBindIPV4), net.ParseIP("10.0.0.1")}...)
apiServerNames := append(k8s.APIServerNames, k8s.APIServerName)
apiServerAlternateNames := append(
apiServerNames,

View File

@ -210,9 +210,9 @@ func (k *Bootstrapper) StartCluster(cfg config.MachineConfig) error {
return errors.Wrapf(err, "init failed. output: %q", rr.Output())
}
if driver.IsKIC(cfg.VMDriver) {
if cfg.VMDriver == driver.Docker {
if err := k.applyKicOverlay(cfg); err != nil {
return errors.Wrap(err, "applying kic overlay network")
return errors.Wrap(err, "apply kic overlay")
}
}
@ -276,7 +276,7 @@ func (k *Bootstrapper) WaitForCluster(cfg config.MachineConfig, timeout time.Dur
ip := cp.IP
port := cp.Port
if driver.IsKIC(cfg.VMDriver) {
ip = kic.DefaultBindIPV4
ip = oci.DefaultBindIPV4
port, err = oci.HostPortBinding(cfg.VMDriver, cfg.Name, port)
if err != nil {
return errors.Wrapf(err, "get host-bind port %d for container %s", port, cfg.Name)
@ -344,7 +344,7 @@ func (k *Bootstrapper) restartCluster(cfg config.MachineConfig) error {
ip := n.IP
port := n.Port
if driver.IsKIC(cfg.VMDriver) {
ip = kic.DefaultBindIPV4
ip = oci.DefaultBindIPV4
port, err = oci.HostPortBinding(cfg.VMDriver, cfg.Name, port)
if err != nil {
return errors.Wrapf(err, "get host-bind port %d for container %s", port, cfg.Name)
@ -471,7 +471,7 @@ func (k *Bootstrapper) UpdateCluster(cfg config.MachineConfig) error {
// applyKicOverlay applies the CNI plugin needed to make kic work
func (k *Bootstrapper) applyKicOverlay(cfg config.MachineConfig) error {
cmd := exec.Command("sudo",
path.Join("/var/lib/minikube/binaries", cfg.KubernetesConfig.KubernetesVersion, "kubectl"), "create", "--kubeconfig=/var/lib/minikube/kubeconfig",
path.Join(vmpath.GuestPersistentDir, "binaries", cfg.KubernetesConfig.KubernetesVersion, "kubectl"), "create", fmt.Sprintf("--kubeconfig=%s", path.Join(vmpath.GuestPersistentDir, "kubeconfig")),
"-f", "-")
b := bytes.Buffer{}
if err := kicCNIConfig.Execute(&b, struct{ ImageName string }{ImageName: kic.OverlayImage}); err != nil {

View File

@ -25,7 +25,7 @@ import (
"github.com/docker/machine/libmachine"
"github.com/docker/machine/libmachine/host"
"github.com/pkg/errors"
"k8s.io/minikube/pkg/drivers/kic"
"k8s.io/minikube/pkg/drivers/kic/oci"
"k8s.io/minikube/pkg/minikube/driver"
)
@ -84,7 +84,7 @@ func GetHostDriverIP(api libmachine.API, machineName string) (net.IP, error) {
return nil, errors.Wrap(err, "getting IP")
}
if driver.IsKIC(host.DriverName) {
ipStr = kic.DefaultBindIPV4
ipStr = oci.DefaultBindIPV4
}
ip := net.ParseIP(ipStr)
if ip == nil {

View File

@ -198,7 +198,7 @@ func commandRunner(h *host.Host) (command.Runner, error) {
}
if driver.IsKIC(d) {
glog.Infof("Returning KICRunner for %q driver", d)
return command.NewKICRunner(h.Name, "docker"), nil
return command.NewKICRunner(h.Name, d), nil
}
glog.Infof("Creating SSH client and returning SSHRunner for %q driver", d)

View File

@ -30,6 +30,7 @@ import (
"github.com/golang/glog"
"github.com/pkg/errors"
"golang.org/x/crypto/ssh/terminal"
"k8s.io/minikube/pkg/drivers/kic/oci"
"k8s.io/minikube/pkg/minikube/assets"
)
@ -126,7 +127,7 @@ func (k *kicRunner) RunCmd(cmd *exec.Cmd) (*RunResult, error) {
// Copy copies a file and its permissions
func (k *kicRunner) Copy(f assets.CopyableFile) error {
assetName := f.GetAssetName()
src := f.GetAssetName()
if _, err := os.Stat(f.GetAssetName()); os.IsNotExist(err) {
fc := make([]byte, f.GetLength()) // Read asset file into a []byte
if _, err := f.Read(fc); err != nil {
@ -147,25 +148,37 @@ func (k *kicRunner) Copy(f assets.CopyableFile) error {
if err := tmpFile.Close(); err != nil {
return errors.Wrap(err, "close temporary file")
}
assetName = tmpFile.Name()
src = tmpFile.Name()
}
// based of format of "docker cp containerName:destination"
destination := fmt.Sprintf("%s:%s/%s", k.nameOrID, f.GetTargetDir(), f.GetTargetName())
perms, err := strconv.ParseInt(f.GetPermissions(), 8, 0)
if err != nil {
return errors.Wrapf(err, "error converting permissions %s to integer", f.GetPermissions())
return errors.Wrapf(err, "converting permissions %s to integer", f.GetPermissions())
}
// Rely on cp -a to propagate permissions
if err := os.Chmod(assetName, os.FileMode(perms)); err != nil {
if err := os.Chmod(src, os.FileMode(perms)); err != nil {
return errors.Wrapf(err, "chmod")
}
if out, err := exec.Command(k.ociBin, "cp", "-a", assetName, destination).CombinedOutput(); err != nil {
return errors.Wrapf(err, "error copying %s into node, output: %s", f.GetAssetName(), string(out))
dest := fmt.Sprintf("%s:%s", k.nameOrID, path.Join(f.GetTargetDir(), f.GetTargetName()))
if k.ociBin == oci.Podman {
return copyToPodman(src, dest)
}
return copyToDocker(src, dest)
}
// Podman cp command doesn't match docker and doesn't have -a
func copyToPodman(src string, dest string) error {
if out, err := exec.Command(oci.Podman, "cp", src, dest).CombinedOutput(); err != nil {
return errors.Wrapf(err, "podman copy %s into %s, output: %s", src, dest, string(out))
}
return nil
}
func copyToDocker(src string, dest string) error {
if out, err := exec.Command(oci.Docker, "cp", "-a", src, dest).CombinedOutput(); err != nil {
return errors.Wrapf(err, "docker copy %s into %s, output: %s", src, dest, string(out))
}
return nil
}

View File

@ -27,92 +27,81 @@ import (
)
const (
// DefaultKubernetesVersion is the default kubernetes version
DefaultKubernetesVersion = "v1.17.2"
// NewestKubernetesVersion is the newest Kubernetes version to test against
NewestKubernetesVersion = "v1.17.2"
// OldestKubernetesVersion is the oldest Kubernetes version to test against
OldestKubernetesVersion = "v1.11.10"
// DefaultMachineName is the default name for the VM
DefaultMachineName = "minikube"
// DefaultNodeName is the default name for the kubeadm node within the VM
DefaultNodeName = "minikube"
// DockerDaemonPort is the port Docker daemon listening inside a minikube node (vm or container).
DockerDaemonPort = 2376
// SSHPort is the SSH serviceport on the node vm and container
SSHPort = 22
// APIServerPort is the default API server port
APIServerPort = 8443
// SSHPort is the SSH serviceport on the node vm and container
SSHPort = 22
// APIServerName is the default API server name
APIServerName = "minikubeCA"
// ClusterDNSDomain is the default DNS domain
ClusterDNSDomain = "cluster.local"
// DefaultServiceCIDR is The CIDR to be used for service cluster IPs
DefaultServiceCIDR = "10.96.0.0/12"
// DockerTLSVerifyEnv is used for docker daemon settings
DockerTLSVerifyEnv = "DOCKER_TLS_VERIFY"
// DockerHostEnv is used for docker daemon settings
DockerHostEnv = "DOCKER_HOST"
// DockerCertPathEnv is used for docker daemon settings
DockerCertPathEnv = "DOCKER_CERT_PATH"
// DockerTLSVerifyEnv is used for docker daemon settings
DockerTLSVerifyEnv = "DOCKER_TLS_VERIFY"
// MinikubeActiveDockerdEnv holds the docker daemon which user's shell is pointing at
// value would be profile or empty if pointing to the user's host daemon.
// DockerDaemonEnvs has list of environment variables to control docker daemon shell is using
MinikubeActiveDockerdEnv = "MINIKUBE_ACTIVE_DOCKERD"
// PodmanVarlinkBridgeEnv is used for podman settings
PodmanVarlinkBridgeEnv = "PODMAN_VARLINK_BRIDGE"
)
var DockerDaemonEnvs = [3]string{DockerHostEnv, DockerTLSVerifyEnv, DockerCertPathEnv}
// DefaultMinipath is the default Minikube path (under the home directory)
var DefaultMinipath = filepath.Join(homedir.HomeDir(), ".minikube")
// KubeconfigPath is the path to the Kubernetes client config
var KubeconfigPath = clientcmd.RecommendedHomeFile
// KubeconfigEnvVar is the env var to check for the Kubernetes client config
var KubeconfigEnvVar = clientcmd.RecommendedConfigPathEnvVar
// DefaultMachineName is the default name for the VM
const DefaultMachineName = "minikube"
// DefaultNodeName is the default name for the kubeadm node within the VM
const DefaultNodeName = "minikube"
// MountProcessFileName is the filename of the mount process
var MountProcessFileName = ".mount-process"
const (
// SHASuffix is the suffix of a SHA-256 checksum file
SHASuffix = ".sha256"
)
// DefaultISOURL is the default location of the minikube.iso file
var DefaultISOURL = fmt.Sprintf("https://storage.googleapis.com/%s/minikube-%s.iso", minikubeVersion.GetISOPath(), minikubeVersion.GetISOVersion())
// DefaultISOSHAURL is the default location of the minikube.iso.sha256 file
var DefaultISOSHAURL = DefaultISOURL + SHASuffix
// DefaultKubernetesVersion is the default kubernetes version
var DefaultKubernetesVersion = "v1.17.2"
// NewestKubernetesVersion is the newest Kubernetes version to test against
var NewestKubernetesVersion = "v1.17.2"
// OldestKubernetesVersion is the oldest Kubernetes version to test against
var OldestKubernetesVersion = "v1.11.10"
const (
var (
// IsMinikubeChildProcess is the name of "is minikube child process" variable
IsMinikubeChildProcess = "IS_MINIKUBE_CHILD_PROCESS"
)
// ImageRepositories contains all known image repositories
var ImageRepositories = map[string][]string{
"global": {""},
"cn": {"registry.cn-hangzhou.aliyuncs.com/google_containers"},
}
// KubernetesReleaseBinaries are Kubernetes release binaries required for
// kubeadm (kubelet, kubeadm) and the addon manager (kubectl)
var KubernetesReleaseBinaries = []string{"kubelet", "kubeadm", "kubectl"}
// ImageCacheDir is the path to the image cache directory
var ImageCacheDir = localpath.MakeMiniPath("cache", "images")
const (
// GvisorConfigTomlTargetName is the go-bindata target name for the gvisor config.toml
GvisorConfigTomlTargetName = "gvisor-config.toml"
// MountProcessFileName is the filename of the mount process
MountProcessFileName = ".mount-process"
// SHASuffix is the suffix of a SHA-256 checksum file
)
var (
SHASuffix = ".sha256"
// DefaultISOURL is the default location of the minikube.iso file
DefaultISOURL = fmt.Sprintf("https://storage.googleapis.com/%s/minikube-%s.iso", minikubeVersion.GetISOPath(), minikubeVersion.GetISOVersion())
// DefaultISOSHAURL is the default location of the minikube.iso.sha256 file
DefaultISOSHAURL = DefaultISOURL + SHASuffix
// DockerDaemonEnvs is list of docker-daemon related environment variables.
DockerDaemonEnvs = [3]string{DockerHostEnv, DockerTLSVerifyEnv, DockerCertPathEnv}
// DefaultMinipath is the default Minikube path (under the home directory)
DefaultMinipath = filepath.Join(homedir.HomeDir(), ".minikube")
// KubeconfigEnvVar is the env var to check for the Kubernetes client config
KubeconfigEnvVar = clientcmd.RecommendedConfigPathEnvVar
// KubeconfigPath is the path to the Kubernetes client config
KubeconfigPath = clientcmd.RecommendedHomeFile
// ImageRepositories contains all known image repositories
ImageRepositories = map[string][]string{
"global": {""},
"cn": {"registry.cn-hangzhou.aliyuncs.com/google_containers"},
}
// KubernetesReleaseBinaries are Kubernetes release binaries required for
// kubeadm (kubelet, kubeadm) and the addon manager (kubectl)
KubernetesReleaseBinaries = []string{"kubelet", "kubeadm", "kubectl"}
// ImageCacheDir is the path to the image cache directory
ImageCacheDir = localpath.MakeMiniPath("cache", "images")
)

View File

@ -28,6 +28,8 @@ import (
)
const (
// Podman is Kubernetes in container using podman driver
Podman = "podman"
// Docker is Kubernetes in container using docker driver
Docker = "docker"
// Mock driver
@ -85,7 +87,7 @@ func Supported(name string) bool {
// IsKIC checks if the driver is a kubernetes in continer
func IsKIC(name string) bool {
return name == Docker
return name == Docker || name == Podman
}
// IsMock checks if the driver is a mock
@ -106,6 +108,16 @@ func BareMetal(name string) bool {
return name == None || name == Mock
}
// NeedsRoot returns true if driver needs to run with root privileges
func NeedsRoot(name string) bool {
return name == None || name == Podman
}
// HasResourceLimits returns true if driver can set resource limits such as memory size or CPU count.
func HasResourceLimits(name string) bool {
return name == None || name == Podman
}
// FlagHints are hints for what default options should be used for this driver
type FlagHints struct {
ExtraOptions []string

View File

@ -26,6 +26,7 @@ var supportedDrivers = []string{
HyperKit,
VMware,
Docker,
Podman,
}
func VBoxManagePath() string {

View File

@ -29,6 +29,7 @@ var supportedDrivers = []string{
VMware,
None,
Docker,
Podman,
}
// VBoxManagePath returns the path to the VBoxManage command

View File

@ -154,8 +154,9 @@ func CommandRunner(h *host.Host) (command.Runner, error) {
if driver.BareMetal(h.Driver.DriverName()) {
return command.NewExecRunner(), nil
}
if h.Driver.DriverName() == driver.Docker {
return command.NewKICRunner(h.Name, "docker"), nil
if driver.IsKIC(h.Driver.DriverName()) {
return command.NewKICRunner(h.Name, h.Driver.DriverName()), nil
}
client, err := sshutil.NewSSHClient(h.Driver)
if err != nil {

View File

@ -56,17 +56,18 @@ func configure(mc config.MachineConfig) (interface{}, error) {
}
func status() registry.State {
_, err := exec.LookPath("docker")
_, 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/kic/"}
return registry.State{Error: err, Installed: false, Healthy: false, Fix: "Docker is required.", Doc: "https://minikube.sigs.k8s.io/docs/reference/drivers/docker/"}
}
// Allow no more than 2 seconds for querying state
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
// Allow no more than 3 seconds for docker info
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
err = exec.CommandContext(ctx, "docker", "info").Run()
err = exec.CommandContext(ctx, oci.Docker, "info").Run()
if err != nil {
return registry.State{Error: err, Installed: true, Healthy: false, Fix: "Docker is not running. Try: restarting docker desktop."}
return registry.State{Error: err, Installed: true, Healthy: false, Fix: "Docker is not running or is responding too slow. Try: restarting docker desktop."}
}
return registry.State{Installed: true, Healthy: true}

View File

@ -24,6 +24,7 @@ import (
_ "k8s.io/minikube/pkg/minikube/registry/drvs/kvm2"
_ "k8s.io/minikube/pkg/minikube/registry/drvs/none"
_ "k8s.io/minikube/pkg/minikube/registry/drvs/parallels"
_ "k8s.io/minikube/pkg/minikube/registry/drvs/podman"
_ "k8s.io/minikube/pkg/minikube/registry/drvs/virtualbox"
_ "k8s.io/minikube/pkg/minikube/registry/drvs/vmware"
_ "k8s.io/minikube/pkg/minikube/registry/drvs/vmwarefusion"

View File

@ -0,0 +1,98 @@
/*
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 podman
import (
"context"
"fmt"
"os/exec"
"strings"
"time"
"github.com/blang/semver"
"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"
"k8s.io/minikube/pkg/minikube/driver"
"k8s.io/minikube/pkg/minikube/localpath"
"k8s.io/minikube/pkg/minikube/registry"
)
// minReqPodmanVer is required the mininum version of podman to be installed for podman driver.
var minReqPodmanVer = semver.Version{Major: 1, Minor: 7, Patch: 0}
func init() {
if err := registry.Register(registry.DriverDef{
Name: driver.Podman,
Config: configure,
Init: func() drivers.Driver { return kic.NewDriver(kic.Config{OCIBinary: oci.Podman}) },
Status: status,
Priority: registry.Experimental,
}); err != nil {
panic(fmt.Sprintf("register failed: %v", err))
}
}
func configure(mc config.MachineConfig) (interface{}, error) {
return kic.NewDriver(kic.Config{
MachineName: mc.Name,
StorePath: localpath.MiniPath(),
ImageDigest: strings.Split(kic.BaseImage, "@")[0], // for podman does not support docker images references with both a tag and digest.
CPU: mc.CPUs,
Memory: mc.Memory,
OCIBinary: oci.Podman,
APIServerPort: mc.Nodes[0].Port,
}), nil
}
func status() registry.State {
_, err := exec.LookPath(oci.Podman)
if err != nil {
return registry.State{Error: err, Installed: false, Healthy: false, Fix: "Podman is required.", Doc: "https://minikube.sigs.k8s.io/docs/reference/drivers/podman/"}
}
// Allow no more than 2 seconds for version command
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
cmd := exec.CommandContext(ctx, oci.Podman, "version", "-f", "{{.Version}}")
o, err := cmd.CombinedOutput()
output := string(o)
if err != nil {
return registry.State{Error: err, Installed: true, Healthy: false, Fix: "Cant verify mininim required version for podman . See podman website for installation guide.", Doc: "https://podman.io/getting-started/installation.html"}
}
v, err := semver.Make(output)
if err != nil {
return registry.State{Error: err, Installed: true, Healthy: false, Fix: "Cant verify mininim required version for podman . See podman website for installation guide.", Doc: "https://podman.io/getting-started/installation.html"}
}
if v.LT(minReqPodmanVer) {
glog.Warningf("Warning ! mininim required version for podman is %s. your version is %q. minikube might not work. use at your own risk. To install latest version please see https://podman.io/getting-started/installation.html ", minReqPodmanVer.String(), v.String())
}
// Allow no more than 3 seconds for querying state
ctx, cancel = context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
err = exec.CommandContext(ctx, oci.Podman, "info").Run()
if err != nil {
return registry.State{Error: err, Installed: true, Healthy: false, Fix: "Podman is not running or taking too long to respond. Try: restarting podman."}
}
return registry.State{Installed: true, Healthy: true}
}

View File

@ -341,7 +341,7 @@ func validateCacheCmd(ctx context.Context, t *testing.T, profile string) {
}
}
})
t.Run("delete busybox:1.28.4-glibc", func(t *testing.T) {
t.Run("delete_busybox:1.28.4-glibc", func(t *testing.T) {
_, err := Run(t, exec.CommandContext(ctx, Target(), "cache", "delete", "busybox:1.28.4-glibc"))
if err != nil {
t.Errorf("failed to delete image busybox:1.28.4-glibc from cache: %v", err)
@ -361,7 +361,7 @@ func validateCacheCmd(ctx context.Context, t *testing.T, profile string) {
}
})
t.Run("verify cache inside node", func(t *testing.T) {
t.Run("verify_cache_inside_node", func(t *testing.T) {
rr, err := Run(t, exec.CommandContext(ctx, Target(), "-p", profile, "ssh", "sudo", "crictl", "images"))
if err != nil {
t.Errorf("failed to get images by %q ssh %v", rr.Command(), err)
@ -372,7 +372,7 @@ func validateCacheCmd(ctx context.Context, t *testing.T, profile string) {
})
t.Run("cache reload", func(t *testing.T) { // deleting image inside minikube node manually and expecting reload to bring it back
t.Run("cache_reload", func(t *testing.T) { // deleting image inside minikube node manually and expecting reload to bring it back
img := "busybox:latest"
// deleting image inside minikube node manually
rr, err := Run(t, exec.CommandContext(ctx, Target(), "-p", profile, "ssh", "sudo", "docker", "rmi", img)) // for some reason crictl rmi doesn't work

View File

@ -24,6 +24,8 @@ import (
"os/exec"
"testing"
"time"
"k8s.io/minikube/pkg/minikube/vmpath"
)
func TestGuestEnvironment(t *testing.T) {
@ -59,7 +61,7 @@ func TestGuestEnvironment(t *testing.T) {
"/var/lib/docker",
"/var/lib/cni",
"/var/lib/kubelet",
"/var/lib/minikube",
vmpath.GuestPersistentDir,
"/var/lib/toolbox",
"/var/lib/boot2docker",
} {