Tại sao conmon trong một nhóm khác nhau khi podman được bắt đầu với systemd?


10

Podman đã cho được cài đặt trên hệ thống linux và đơn vị systemd có tên baz.service:

# /etc/systemd/system/baz.service
[Service]
ExecStart=/usr/bin/podman run --rm --tty --name baz alpine sh -c 'while true; do date; sleep 1; done'
ExecStop=/usr/bin/podman stop baz

Và baz.service bắt đầu:

# systemctl daemon-reload
# systemctl start baz.service

Sau đó, khi tôi kiểm tra trạng thái của đơn vị, tôi không thấy shhoặc sleepxử lý trong nhóm /system.slice/baz.service

# systemctl status baz
● baz.service
   Loaded: loaded (/etc/systemd/system/baz.service; static; vendor preset: enabl
   Active: active (running) since Sat 2019-08-10 05:50:18 UTC; 14s ago
 Main PID: 16910 (podman)
    Tasks: 9
   Memory: 7.3M
      CPU: 68ms
   CGroup: /system.slice/baz.service
           └─16910 /usr/bin/podman run --rm --tty --name baz alpine sh -c while
# ...

Tôi đã mong đợi được nhìn thấy shsleeptrẻ em trong tình trạng baz.service của mình vì tôi đã nghe những người từ redhat nói rằng podman sử dụng mô hình fork-exec truyền thống.

Nếu podman thực hiện fork và exec, thì tôi shsleepprocess sẽ không phải là con của podman và ở cùng nhóm với quy trình podman ban đầu?

Tôi đã mong đợi có thể sử dụng systemd và podman để có thể quản lý các container của mình mà không cần con cái đi đến một phụ huynh khác và thoát khỏi đơn vị ssystemd baz.service của tôi.

Nhìn vào đầu ra của pstôi có thể thấy điều đó shsleepthực sự là con của một quá trình khác được gọi là conmon. Tôi không chắc conmon đến từ đâu, hoặc nó đã được bắt đầu như thế nào nhưng systemd đã không nắm bắt được nó.

# ps -Heo user,pid,ppid,comm
# ...
root     17254     1   podman
root     17331     1   conmon
root     17345 17331     sh
root     17380 17345       sleep

Từ đầu ra, rõ ràng đơn vị baz.service của tôi không quản lý conmon -> sh -> chuỗi ngủ.

  • Podman khác với mô hình máy chủ docker như thế nào?
  • Conmon của podman khác với container của docker như thế nào?

Có lẽ cả hai đều là thời gian chạy của container và dockerddaemon là thứ mà mọi người muốn loại bỏ.

Vì vậy, có thể docker giống như:

  • daemon bến tàu
  • bến tàu
  • thời gian chạy container container

Và podman giống như:

  • podman cli
  • thời gian chạy container conmon

Vì vậy, có thể podman sử dụng mô hình fork thực hiện truyền thống nhưng đó không phải là podman cli đang giả mạo và thực thi, đó là quá trình conmon.

Tôi cảm thấy bối rối.


Có cuộc thảo luận về câu hỏi này trong danh sách gửi thư của podman
mbigras

Câu trả lời:


7

Toàn bộ ý tưởng đằng sau podmanlà đi ra khỏi kiến ​​trúc tập trung với người giám sát siêu mạnh (ví dụ dockerd), trong đó daemon tập trung là một điểm thất bại duy nhất. Thậm chí còn có một hashtag về điều này - " #nobigfatdaemons ".

Làm thế nào để tránh việc quản lý container tập trung? Bạn xóa một daemon chính duy nhất (một lần nữa dockerd) và khởi động các container một cách độc lập (vào cuối ngày, các container chỉ là các tiến trình, vì vậy bạn không cần daemon để sinh ra chúng).

Tuy nhiên, bạn vẫn cần cách để

  • thu thập nhật ký của người chứa - ai đó phải giữ stdoutstderrcủa container;
  • thu thập mã thoát của người chứa - ai đó phải wait(2)vào PID 1 của người chứa;

Với mục đích này, mỗi thùng chứa podman vẫn được giám sát bởi một trình nền nhỏ, được gọi conmon(từ "trình giám sát vùng chứa"). Sự khác biệt với daemon Docker là daemon này càng nhỏ càng tốt (kiểm tra kích thước của mã nguồn ) và nó được sinh ra trên mỗi container. Nếu conmonmột container gặp sự cố, phần còn lại của hệ thống sẽ không bị ảnh hưởng.

Tiếp theo, làm thế nào các container được sinh sản?

Xem xét rằng người dùng có thể muốn chạy container trong nền, giống như với Docker, podman runquá trình này thực hiện hai lần và chỉ sau đó thực thi conmon:

$ strace -fe trace=fork,vfork,clone,execve -qq podman run alpine
execve("/usr/bin/podman", ["podman", "run", "alpine"], 0x7ffeceb01518 /* 30 vars */) = 0
...
[pid  8480] clone(child_stack=0x7fac6bffeef0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tid=[8484], tls=0x7fac6bfff700, child_tidptr=0x7fac6bfff9d0) = 8484
...
[pid  8484] clone(child_stack=NULL, flags=CLONE_VM|CLONE_VFORK|SIGCHLD <unfinished ...>
[pid  8491] execve("/usr/bin/conmon", ... <unfinished ...>
[pid  8484] <... clone resumed>)        = 8491

Quá trình giữa giữa podman runconmon(tức là cha mẹ trực tiếp củaconmon - trong ví dụ ở trên là PID 8484) sẽ thoát và conmonsẽ được sửa chữa lại init, do đó trở thành trình nền tự quản lý. Sau này, conmoncũng loại bỏ thời gian chạy (ví dụ runc) và cuối cùng, thời gian chạy thực thi điểm truy cập của bộ chứa (ví dụ /bin/sh).

Khi container đang chạy, podman runkhông còn cần thiết và có thể thoát, nhưng trong trường hợp của bạn, nó vẫn trực tuyến, vì bạn không yêu cầu nó tách ra khỏi container.

Tiếp theo, podmansử dụng các nhóm để giới hạn các container. Điều này có nghĩa là nó tạo ra các nhóm mới cho các thùng chứa mới và di chuyển các quy trình ở đó . Theo quy tắc của các nhóm, quy trình có thể là thành viên của một nhóm duy nhất tại một thời điểm và việc thêm quy trình vào một số nhóm sẽ loại bỏ nó khỏi nhóm khác (trước đây) trong cùng một hệ thống phân cấp. Vì vậy, khi container được khởi động, bố cục cuối cùng của các nhóm trông giống như sau: podman runvẫn nằm trong các nhóm của baz.service, được tạo bởisystemd , conmonquá trình được đặt trong các nhóm riêng của nó và các quy trình được chứa trong các nhóm riêng của chúng:

$ ps axf
<...>
 1660 ?        Ssl    0:01 /usr/bin/podman run --rm --tty --name baz alpine sh -c while true; do date; sleep 1; done
 1741 ?        Ssl    0:00 /usr/bin/conmon -s -c 2f56e37a0c5ca6f4282cc4c0f4c8e5c899e697303f15c5dc38b2f31d56967ed6 <...>
 1753 pts/0    Ss+    0:02  \_ sh -c while true; do date; sleep 1; done
13043 pts/0    S+     0:00      \_ sleep 1
<...>

$ cd /sys/fs/cgroup/memory/machine.slice
$ ls -d1 libpod*
libpod-2f56e37a0c5ca6f4282cc4c0f4c8e5c899e697303f15c5dc38b2f31d56967ed6.scope
libpod-conmon-2f56e37a0c5ca6f4282cc4c0f4c8e5c899e697303f15c5dc38b2f31d56967ed6.scope

$ cat libpod-2f56e37a0c5ca6f4282cc4c0f4c8e5c899e697303f15c5dc38b2f31d56967ed6.scope/cgroup.procs 
1753
13075

$ cat libpod-conmon-2f56e37a0c5ca6f4282cc4c0f4c8e5c899e697303f15c5dc38b2f31d56967ed6.scope/cgroup.procs 
1741

Lưu ý: PID 13075 ở trên thực sự là một sleep 1quá trình, sinh ra sau cái chết của PID 13043.

Hi vọng điêu nay co ich.


1
"Tạo các nhóm mới cho các thùng chứa mới và di chuyển các quy trình ở đó" Tôi không hiểu tại sao podman lại làm công việc đó thay vì systemd. Bạn có thể thêm một lời giải thích về lý do tại sao chúng tôi sử dụng conmon để giữ stdout và stderr thay vì systemd không? Từ việc tìm hiểu về systemd tôi nghĩ mục đích của systemd là quản lý các tiến trình và thực hiện các tác vụ như chụp stdout / stderr, tìm ra trạng thái thoát, xử lý khởi động lại.
mbigras

1
Podman quản lý các nhóm vì nó sở hữu container và phải đảm bảo rằng container sẽ hoạt động bất chấp những gì hệ thống init bạn có. Systemd quản lý các nhóm cho các dịch vụ vì nó sở hữu các dịch vụ (và các dịch vụ không được phép quản lý các nhóm theo mặc định, mặc dù systemd hỗ trợ một số loại ủy quyền - xem systemd.io/CGROUP_DELEGATION ). Nếu bạn muốn podman sử dụng lại các nhóm được tạo bởi systemd cho dịch vụ, thì phải có sự hỗ trợ từ phía podman và hiện tại tôi không thấy một nhóm nào (mặc dù tôi có thể mắc lỗi).
Danila Kiver

1
As stdout/ stderrstream - một lần nữa, podmansở hữu container và nắm bắt các luồng của quá trình được chứa. systemdsở hữu dịch vụ và nắm bắt các luồng của quy trình chính của dịch vụ (trong trường hợp của bạn, systemdthực sự là nắm bắt stdout/ stderrcủa podman runquy trình). Điều này hoạt động chính xác như nó nên hoạt động, bởi vì conmonbắt các luồng của container, podman rungắn vào conmon, systemdbắt các luồng của podman run, vì vậy, cuối cùng, tất cả các bản ghi từ container bị bắt systemdvà bạn nhìn thấy chúng systemctl status baz.service.
Danila Kiver
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.