bug: clistat only checks the nearest limit, but every parent's limit applies (cgroup v2)
Một pull request liên quan đã được merge.
- #44 của @david-fraley — đã merge
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 48/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- go, linux
- Lĩnh vực
- operating-systems
Hướng nghiên cứu
Start by tracing the memory and CPU limit checks that read cgroup data, then compare each ancestor's usage with its own limit as described in the issue. The reproduction uses cgroup v2 and a static probe calling ContainerMemory(PrefixMebi); run that scenario to check whether the reported limit matches the one exhausted first. Done means the display reflects the ancestor with the least room left; the issue leaves open whether to report only that limit or all limits.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Summary
For memory and CPU, clistat goes up from the process's cgroup and stops at the first limit it finds. But the kernel checks the limit of every parent cgroup, not just the nearest one. Whichever parent runs out of room first is the one that matters. This means a process can be killed for using too much memory while clistat says it is only using a small part of its limit.
This can happen even when every child limit is smaller than its parent's. If other cgroups have used up most of the parent's memory, the child hits the parent's limit first.
#38 and #39 fix the case where only one cgroup has a limit. This issue is about the general case.
Why this is wrong
- When memory is used, the kernel adds it to the cgroup and to every parent above it. If any of them goes over its limit, the allocation fails and that parent's limit is the one hit (
page_counter_try_charge()inmm/page_counter.c, v6.17). memory.currentis the memory used by a cgroup and everything below it (cgroup v2 docs). This is the number the kernel compares againstmemory.max.- Child limits can add up to more than the parent's limit (cgroup v2 docs). So a child's limit alone does not tell you if there is room left.
- CPU limits work the same way. A limit applies to the cgroup and everything below it (cgroup v2 docs).
How to reproduce
We tested this with #39 applied. The container root has a 1 GiB limit. Cgroup A, where clistat runs, has a 600 MiB limit. Cgroup B has no limit and uses 850 MiB:
docker run --rm --privileged --memory 1g -v "$PWD/probe:/probe:ro" alpine sh -c '
cd /sys/fs/cgroup && mkdir leaf A B
echo $$ > leaf/cgroup.procs && echo +memory > cgroup.subtree_control
echo 629145600 > A/memory.max
mkdir /t && mount -t tmpfs -o size=2g tmpfs /t
sh -c "echo \$\$ > B/cgroup.procs; dd if=/dev/zero of=/t/f bs=1M count=850"
sh -c "echo \$\$ > A/cgroup.procs; exec /probe"
sh -c "echo \$\$ > A/cgroup.procs; exec dd if=/dev/zero of=/t/g bs=1M count=300"'
probe is a small static binary that prints ContainerMemory(PrefixMebi).
| cgroup | Memory used | Limit |
|---|---|---|
| Container root | 895 MB | 1 GiB |
A |
0 | 600 MiB |
B |
893 MB | none |
- clistat in
Ashows9.71/600 MiB (2%). - We then used 300 MiB in
A, which is half of its own limit. The process was killed for using too much memory. The root'smemory.eventsshowsoom 1, butA's ownoomcount is still0. The root's limit was the one hit, notA's.
What should happen
clistat should show the limit that will actually be hit first. Here that is the root: about 895 MB of 1 GiB (83%), not 2%.
How to fix it
Go up from the process's cgroup to the top of the container. For each cgroup that has a limit, read usage from that same cgroup:
- Memory:
memory.current - inactive_file, compared withmemory.max. - CPU: the change in
cpu.statusage_usecover the sample time, compared withcpu.max.
Report the cgroup with the least room left (limit minus usage). This also covers #38, #39 and #41.
Open question: should clistat report only the limit that will be hit first, or every limit it finds?
Not covered by this issue
clistat cannot see limits set outside the container. For example, a Kubernetes pod-level limit is not visible from inside a container that has its own cgroup namespace. We should document this, not try to fix it here.
Generated by Coder Agents on behalf of @DanielleMaywood.
- Ngôn ngữ chính
- Go
- Star
- 11
- Fork
- 2
- Merge trung bình
- 2 ngày 21 giờ
- Pull request đã merge (30 ngày)
- 1
Chuẩn bị môi trường
Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của coder/clistat
-
bug: CPU usage misses other processes that share the same CPU limit (cgroup v2)Có thể đã có người làm @DanielleMaywood đã nhận 6 ngày trước. Đang mở
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 67/100
-
Bug
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 48/100
-
feat: add directory-level disk usage statsCó thể làm lại được Pull request cho issue này đã bị đóng mà không được merge. Đang mởenhancement
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 35/100
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 45/100
Tất cả issue của coder/clistat
Issue tương tự
-
area:web p3
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
Lets-Parley/Parley#912 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
enhancement help wanted
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
Git-Hospital/githealthcheck#61 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
afreidah/s3-orchestrator#1824 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Type: Bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
projectdiscovery/notify#569 ·
-
internal
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
Maintainer thường phản hồi trong vòng 1 ngày