in pkg/drivers/kic/oci/oci.go [143:296]
func CreateContainerNode(p CreateParams) error {
// on windows os, if docker desktop is using Windows Containers. Exit early with error
if p.OCIBinary == Docker && runtime.GOOS == "windows" {
info, err := DaemonInfo(p.OCIBinary)
if info.OSType == "windows" {
return ErrWindowsContainers
}
if err != nil {
klog.Warningf("error getting dameon info: %v", err)
return errors.Wrap(err, "daemon info")
}
}
runArgs := []string{
"-d", // run the container detached
"-t", // allocate a tty for entrypoint logs
// running containers in a container requires privileged
// NOTE: we could try to replicate this with --cap-add, and use less
// privileges, but this flag also changes some mounts that are necessary
// including some ones docker would otherwise do by default.
// for now this is what we want. in the future we may revisit this.
"--privileged",
// enable /dev/fuse explicitly for fuse-overlayfs
// (Rootless Docker does not automatically mount /dev/fuse with --privileged)
"--device", "/dev/fuse",
"--security-opt", "seccomp=unconfined", // ignore seccomp
"--tmpfs", "/tmp", // various things depend on working /tmp
"--tmpfs", "/run", // systemd wants a writable /run
// logs,pods be stroed on filesystem vs inside container,
// some k8s things want /lib/modules
"-v", "/lib/modules:/lib/modules:ro",
"--hostname", p.Name, // make hostname match container name
"--name", p.Name, // ... and set the container name
"--label", fmt.Sprintf("%s=%s", CreatedByLabelKey, "true"),
// label the node with the cluster ID
"--label", p.ClusterLabel,
// label the node with the role ID
"--label", fmt.Sprintf("%s=%s", nodeRoleLabelKey, p.Role),
// label th enode wuth the node ID
"--label", p.NodeLabel,
}
// to provide a static IP
if p.Network != "" && p.IP != "" {
runArgs = append(runArgs, "--network", p.Network)
runArgs = append(runArgs, "--ip", p.IP)
}
memcgSwap := hasMemorySwapCgroup()
memcg := HasMemoryCgroup()
// https://www.freedesktop.org/wiki/Software/systemd/ContainerInterface/
var virtualization string
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", p.Name))
if memcgSwap {
runArgs = append(runArgs, fmt.Sprintf("--memory-swap=%s", p.Memory))
}
if memcg {
runArgs = append(runArgs, fmt.Sprintf("--memory=%s", p.Memory))
}
virtualization = "podman" // VIRTUALIZATION_PODMAN
}
if p.OCIBinary == Docker {
runArgs = append(runArgs, "--volume", fmt.Sprintf("%s:/var", p.Name))
// ignore apparmore github actions docker: https://github.com/kubernetes/minikube/issues/7624
runArgs = append(runArgs, "--security-opt", "apparmor=unconfined")
if memcg {
runArgs = append(runArgs, fmt.Sprintf("--memory=%s", p.Memory))
}
if memcgSwap {
// Disable swap by setting the value to match
runArgs = append(runArgs, fmt.Sprintf("--memory-swap=%s", p.Memory))
}
virtualization = "docker" // VIRTUALIZATION_DOCKER
}
cpuCfsPeriod := true
cpuCfsQuota := true
if runtime.GOOS == "linux" {
if _, err := os.Stat("/sys/fs/cgroup/cpu/cpu.cfs_period_us"); os.IsNotExist(err) {
cpuCfsPeriod = false
}
if _, err := os.Stat("/sys/fs/cgroup/cpu/cpu.cfs_quota_us"); os.IsNotExist(err) {
cpuCfsQuota = false
}
if !cpuCfsPeriod || !cpuCfsQuota {
// requires CONFIG_CFS_BANDWIDTH
klog.Warning("Your kernel does not support CPU cfs period/quota or the cgroup is not mounted.")
}
}
if cpuCfsPeriod && cpuCfsQuota {
runArgs = append(runArgs, fmt.Sprintf("--cpus=%s", p.CPUs))
}
runArgs = append(runArgs, "-e", fmt.Sprintf("%s=%s", "container", virtualization))
for key, val := range p.Envs {
runArgs = append(runArgs, "-e", fmt.Sprintf("%s=%s", key, val))
}
// adds node specific args
runArgs = append(runArgs, p.ExtraArgs...)
if enabled := isUsernsRemapEnabled(p.OCIBinary); enabled {
// We need this argument in order to make this command work
// in systems that have userns-remap enabled on the docker daemon
runArgs = append(runArgs, "--userns=host")
}
if err := createContainer(p.OCIBinary, p.Image, withRunArgs(runArgs...), withMounts(p.Mounts), withPortMappings(p.PortMappings)); err != nil {
return errors.Wrap(err, "create container")
}
checkRunning := func() error {
r, err := ContainerRunning(p.OCIBinary, p.Name)
if err != nil {
return fmt.Errorf("temporary error checking running for %q : %v", p.Name, err)
}
if !r {
return fmt.Errorf("temporary error created container %q is not running yet", p.Name)
}
s, err := ContainerStatus(p.OCIBinary, p.Name)
if err != nil {
return fmt.Errorf("temporary error checking status for %q : %v", p.Name, err)
}
if s != state.Running {
return fmt.Errorf("temporary error created container %q is not running yet", p.Name)
}
if !iptablesFileExists(p.OCIBinary, p.Name) {
return fmt.Errorf("iptables file doesn't exist, see #8179")
}
klog.Infof("the created container %q has a running status.", p.Name)
return nil
}
if err := retry.Expo(checkRunning, 15*time.Millisecond, 25*time.Second); err != nil {
excerpt := LogContainerDebug(p.OCIBinary, p.Name)
_, err := DaemonInfo(p.OCIBinary)
if err != nil {
return errors.Wrapf(ErrDaemonInfo, "container name %q", p.Name)
}
return errors.Wrapf(ErrExitedUnexpectedly, "container name %q: log: %s", p.Name, excerpt)
}
return nil
}