diff options
-rw-r--r-- | docs/source/markdown/options/device.md | 8 | ||||
-rw-r--r-- | pkg/specgen/generate/kube/kube.go | 22 | ||||
-rw-r--r-- | pkg/specgen/generate/kube/play_test.go | 59 | ||||
-rw-r--r-- | test/system/030-run.bats | 33 |
4 files changed, 104 insertions, 18 deletions
diff --git a/docs/source/markdown/options/device.md b/docs/source/markdown/options/device.md index 619c70a9b..bd6d7f9d9 100644 --- a/docs/source/markdown/options/device.md +++ b/docs/source/markdown/options/device.md @@ -12,3 +12,11 @@ The <<container|pod>> will only store the major and minor numbers of the host de Podman may load kernel modules required for using the specified device. The devices that Podman will load modules for when necessary are: /dev/fuse. + +In rootless mode, the new device is bind mounted in the container from the host +rather than Podman creating it within the container space. Because the bind +mount retains its SELinux label on SELinux systems, the container can get +permission denied when accessing the mounted device. Modify SELinux settings to +allow containers to use all device labels via the following command: + +$ sudo setsebool -P container_use_devices=true diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go index bc9013afc..2a0d80cb8 100644 --- a/pkg/specgen/generate/kube/kube.go +++ b/pkg/specgen/generate/kube/kube.go @@ -500,20 +500,22 @@ func setupLivenessProbe(s *specgen.SpecGenerator, containerYAML v1.Container, re probe := containerYAML.LivenessProbe probeHandler := probe.Handler - // append `exit 1` to `cmd` so healthcheck can be marked as `unhealthy`. - // append `kill 1` to `cmd` if appropriate restart policy is configured. - if restartPolicy == "always" || restartPolicy == "onfailure" { - // container will be restarted so we can kill init. - failureCmd = "kill 1" - } - // configure healthcheck on the basis of Handler Actions. switch { case probeHandler.Exec != nil: execString := strings.Join(probeHandler.Exec.Command, " ") commandString = fmt.Sprintf("%s || %s", execString, failureCmd) case probeHandler.HTTPGet != nil: - commandString = fmt.Sprintf("curl %s://%s:%d/%s || %s", probeHandler.HTTPGet.Scheme, probeHandler.HTTPGet.Host, probeHandler.HTTPGet.Port.IntValue(), probeHandler.HTTPGet.Path, failureCmd) + // set defaults as in https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#http-probes + var uriScheme v1.URIScheme = "http" + if probeHandler.HTTPGet.Scheme != "" { + uriScheme = probeHandler.HTTPGet.Scheme + } + host := "localhost" // Kubernetes default is host IP, but with Podman there is only one node + if probeHandler.HTTPGet.Host != "" { + host = probeHandler.HTTPGet.Host + } + commandString = fmt.Sprintf("curl -f %s://%s:%d%s || %s", uriScheme, host, probeHandler.HTTPGet.Port.IntValue(), probeHandler.HTTPGet.Path, failureCmd) case probeHandler.TCPSocket != nil: commandString = fmt.Sprintf("nc -z -v %s %d || %s", probeHandler.TCPSocket.Host, probeHandler.TCPSocket.Port.IntValue(), failureCmd) } @@ -521,6 +523,10 @@ func setupLivenessProbe(s *specgen.SpecGenerator, containerYAML v1.Container, re if err != nil { return err } + // if restart policy is in place, ensure the health check enforces it + if restartPolicy == "always" || restartPolicy == "onfailure" { + s.HealthCheckOnFailureAction = define.HealthCheckOnFailureActionRestart + } return nil } return nil diff --git a/pkg/specgen/generate/kube/play_test.go b/pkg/specgen/generate/kube/play_test.go index ec0dc4bcd..efe2e51b1 100644 --- a/pkg/specgen/generate/kube/play_test.go +++ b/pkg/specgen/generate/kube/play_test.go @@ -11,6 +11,8 @@ import ( v1 "github.com/containers/podman/v4/pkg/k8s.io/api/core/v1" "github.com/containers/podman/v4/pkg/k8s.io/apimachinery/pkg/api/resource" v12 "github.com/containers/podman/v4/pkg/k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/containers/podman/v4/pkg/k8s.io/apimachinery/pkg/util/intstr" + "github.com/containers/podman/v4/pkg/specgen" "github.com/docker/docker/pkg/system" "github.com/stretchr/testify/assert" ) @@ -858,3 +860,60 @@ var ( }, } ) + +func TestHttpLivenessProbe(t *testing.T) { + tests := []struct { + name string + specGenerator specgen.SpecGenerator + container v1.Container + restartPolicy string + succeed bool + expectedURL string + }{ + { + "HttpLivenessProbeUrlSetCorrectly", + specgen.SpecGenerator{}, + v1.Container{ + LivenessProbe: &v1.Probe{ + Handler: v1.Handler{ + HTTPGet: &v1.HTTPGetAction{ + Scheme: "http", + Host: "127.0.0.1", + Port: intstr.FromInt(8080), + Path: "/health", + }, + }, + }, + }, + "always", + true, + "http://127.0.0.1:8080/health", + }, + { + "HttpLivenessProbeUrlUsesDefaults", + specgen.SpecGenerator{}, + v1.Container{ + LivenessProbe: &v1.Probe{ + Handler: v1.Handler{ + HTTPGet: &v1.HTTPGetAction{ + Port: intstr.FromInt(80), + Path: "/", + }, + }, + }, + }, + "always", + true, + "http://localhost:80/", + }, + } + + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + err := setupLivenessProbe(&test.specGenerator, test.container, test.restartPolicy) + assert.Equal(t, err == nil, test.succeed) + assert.Contains(t, test.specGenerator.ContainerHealthCheckConfig.HealthConfig.Test, test.expectedURL) + }) + } +} diff --git a/test/system/030-run.bats b/test/system/030-run.bats index 65a1150a3..6847880ab 100644 --- a/test/system/030-run.bats +++ b/test/system/030-run.bats @@ -901,22 +901,35 @@ $IMAGE--c_ok" \ run_podman rm $ctr_name } +# 15895: --privileged + --systemd = hide /dev/ttyNN @test "podman run --privileged as root with systemd will not mount /dev/tty" { skip_if_rootless "this test only makes sense as root" - ctr_name="container-$(random_string 5)" - run_podman run --rm -d --privileged --systemd=always --name "$ctr_name" "$IMAGE" /home/podman/pause + # First, confirm that we _have_ /dev/ttyNN devices on the host. + # ('skip' would be nicer in some sense... but could hide a regression. + # Fedora, RHEL, Debian, Ubuntu, Gentoo, all have /dev/ttyN, so if + # this ever triggers, it means a real problem we should know about.) + assert "$(ls /dev/tty* | grep -vx /dev/tty)" != "" \ + "Expected at least one /dev/ttyN device on host" - TTYs=$(ls /dev/tty*|sed '/^\/dev\/tty$/d') + # Ok now confirm that without --systemd, podman exposes ttyNN devices + run_podman run --rm -d --privileged $IMAGE ./pause + cid="$output" - if [[ $TTYs = "" ]]; then - die "Did not find any /dev/ttyN devices on local host" - else - run_podman exec "$ctr_name" ls /dev/ - assert "$(grep tty <<<$output)" = "tty" "There must be no /dev/ttyN devices in the container" - fi + run_podman exec $cid sh -c 'ls /dev/tty*' + assert "$output" != "/dev/tty" \ + "ls /dev/tty* without systemd; should have lots of ttyN devices" + run_podman stop -t 0 $cid + + # Actual test for 15895: with --systemd, no ttyN devices are passed through + run_podman run --rm -d --privileged --systemd=always $IMAGE ./pause + cid="$output" + + run_podman exec $cid sh -c 'ls /dev/tty*' + assert "$output" = "/dev/tty" \ + "ls /dev/tty* with --systemd=always: should have no ttyN devices" - run_podman stop "$ctr_name" + run_podman stop -t 0 $cid } # vim: filetype=sh |