diff --git a/internal/oci/oci.go b/internal/oci/oci.go index 7f8ad91b6d9..5a13272cf53 100644 --- a/internal/oci/oci.go +++ b/internal/oci/oci.go @@ -31,6 +31,10 @@ const ( // SystemdCgroupsManager represents systemd native cgroup manager SystemdCgroupsManager = "systemd" + // CrioScopePrefix is the crio specific scope prefix + // used for container cgroups + CrioScopePrefix = "crio" + // killContainerTimeout is the timeout that we wait for the container to // be SIGKILLed. killContainerTimeout = 2 * time.Minute diff --git a/internal/oci/oci_linux.go b/internal/oci/oci_linux.go index 92818be919f..f7e5403d82f 100644 --- a/internal/oci/oci_linux.go +++ b/internal/oci/oci_linux.go @@ -86,7 +86,7 @@ func newPipe() (parent, child *os.File, err error) { return os.NewFile(uintptr(fds[1]), "parent"), os.NewFile(uintptr(fds[0]), "child"), nil } -func (r *runtimeOCI) containerStats(ctr *Container, cgroup string) (stats *ContainerStats, err error) { +func (r *runtimeOCI) containerStats(ctr *Container, sandboxParent string) (stats *ContainerStats, err error) { stats = &ContainerStats{} stats.Container = ctr.ID() stats.SystemNano = time.Now().UnixNano() @@ -94,23 +94,25 @@ func (r *runtimeOCI) containerStats(ctr *Container, cgroup string) (stats *Conta // technically, the CRI does not mandate a CgroupParent is given to a pod // this situation should never happen in production, but some test suites // (such as critest) assume we can call stats on a cgroupless container - if cgroup == "" { + if sandboxParent == "" { return stats, nil } + var suffix string // this correction has to be made because the libpod cgroups package can't find a // systemd cgroup that isn't converted to a fully qualified cgroup path if r.config.CgroupManager == SystemdCgroupsManager { - logrus.Debugf("Expanding systemd cgroup slice %v", cgroup) - cgroup, err = systemd.ExpandSlice(cgroup) + logrus.Debugf("Expanding systemd cgroup slice %v", sandboxParent) + sandboxParent, err = systemd.ExpandSlice(sandboxParent) if err != nil { return nil, errors.Wrapf(err, "error expanding systemd slice to get container %s stats", ctr.ID()) } + suffix = ".scope" } - - cg, err := cgroups.Load(cgroup) + cgroupPath := filepath.Join(sandboxParent, CrioScopePrefix+"-"+ctr.ID()+suffix) + cg, err := cgroups.Load(cgroupPath) if err != nil { - return nil, errors.Wrapf(err, "unable to load cgroup at %s", cgroup) + return nil, errors.Wrapf(err, "unable to load cgroup at %s", cgroupPath) } cgroupStats, err := cg.Stat() diff --git a/server/container_create.go b/server/container_create.go index 7acee17a2ab..f96fccdbf12 100644 --- a/server/container_create.go +++ b/server/container_create.go @@ -33,7 +33,6 @@ const ( seccompDockerDefault = "docker/default" seccompLocalhostPrefix = "localhost/" - scopePrefix = "crio" defaultCgroupfsParent = "/crio" defaultSystemdParent = "system.slice" ) diff --git a/server/container_create_linux.go b/server/container_create_linux.go index 9ce31790fa1..4e680272138 100644 --- a/server/container_create_linux.go +++ b/server/container_create_linux.go @@ -562,9 +562,9 @@ func (s *Server) createSandboxContainer(ctx context.Context, containerID, contai parent = sb.CgroupParent() } if useSystemd { - cgPath = parent + ":" + scopePrefix + ":" + containerID + cgPath = parent + ":" + oci.CrioScopePrefix + ":" + containerID } else { - cgPath = filepath.Join(parent, scopePrefix+"-"+containerID) + cgPath = filepath.Join(parent, oci.CrioScopePrefix+"-"+containerID) } specgen.SetLinuxCgroupsPath(cgPath) diff --git a/server/sandbox_run_linux.go b/server/sandbox_run_linux.go index 003c479b53a..b9a74f0f208 100644 --- a/server/sandbox_run_linux.go +++ b/server/sandbox_run_linux.go @@ -736,7 +736,7 @@ func AddCgroupAnnotation(ctx context.Context, g generate.Generator, mountPath, c if strings.HasSuffix(path.Base(cgroupParent), ".slice") { return "", fmt.Errorf("cri-o configured with cgroupfs cgroup manager, but received systemd slice as parent: %s", cgroupParent) } - cgPath := filepath.Join(cgroupParent, scopePrefix+"-"+id) + cgPath := filepath.Join(cgroupParent, oci.CrioScopePrefix+"-"+id) g.SetLinuxCgroupsPath(cgPath) } } diff --git a/test/stats.bats b/test/stats.bats index af8a13d40ff..75f096f0bd6 100644 --- a/test/stats.bats +++ b/test/stats.bats @@ -16,6 +16,7 @@ function teardown() { # given run crictl run "$TESTDATA"/container_redis.json "$TESTDATA"/sandbox_config.json [ "$status" -eq 0 ] + id="$output" # when run crictl stats -o json @@ -23,19 +24,45 @@ function teardown() { [ "$status" -eq 0 ] # then - JSON="$output" - echo $JSON | jq -e '.stats[0].attributes.id != ""' - [ "$status" -eq 0 ] + jq -e '.stats[0].attributes.id = "'$id'"' <<< "$output" + jq -e '.stats[0].cpu.timestamp > 0' <<< "$output" + jq -e '.stats[0].cpu.usageCoreNanoSeconds.value > 0' <<< "$output" + jq -e '.stats[0].memory.timestamp > 0' <<< "$output" + jq -e '.stats[0].memory.workingSetBytes.value > 0' <<< "$output" +} - echo $JSON | jq -e '.stats[0].cpu.timestamp > 0' +@test "container stats" { + # given + container2config=$(cat "$TESTDATA"/container_config_sleep.json | python -c 'import json,sys;obj=json.load(sys.stdin);obj["name"] = ["container10000"];obj["metadata"]["name"] = "container10000"; json.dump(obj, sys.stdout)') + echo "$container2config" > "$TESTDIR"/container_config_sleep2.json + run crictl runp "$TESTDATA"/sandbox_config.json + echo "$output" [ "$status" -eq 0 ] - - echo $JSON | jq -e '.stats[0].cpu.usageCoreNanoSeconds.value > 0' + pod_id="$output" + run crictl create "$pod_id" "$TESTDATA"/container_config_sleep.json "$TESTDATA"/sandbox_config.json + echo "$output" [ "$status" -eq 0 ] - - echo $JSON | jq -e '.stats[0].memory.timestamp > 0' + ctr1_id="$output" + run crictl create "$pod_id" "$TESTDIR"/container_config_sleep2.json "$TESTDATA"/sandbox_config.json + echo "$output" [ "$status" -eq 0 ] - - echo $JSON | jq -e '.stats[0].memory.workingSetBytes.value > 0' + ctr2_id="$output" + run crictl start "$ctr1_id" + echo "$output" + [ "$status" -eq 0 ] + run crictl start "$ctr2_id" + echo "$output" [ "$status" -eq 0 ] + + # when + ctr1_stats_JSON=$(crictl stats -o json --id "$ctr1_id") + echo $ctr1_stats_JSON + ctr2_stats_JSON=$(crictl stats -o json --id "$ctr2_id") + echo $ctr2_stats_JSON + + ctr1_memory_bytes=$(echo $ctr1_stats_JSON | jq -e '.stats[0].memory.workingSetBytes.value') + ctr2_memory_bytes=$(echo $ctr2_stats_JSON | jq -e '.stats[0].memory.workingSetBytes.value') + + # then + [[ $ctr1_memory_bytes != $ctr2_memory_bytes ]] }