הפעלת systemd במיכל

אנחנו עוקבים אחרי נושא השימוש ב-systemd בקונטיינרים כבר זמן רב. עוד בשנת 2014, מהנדס האבטחה שלנו דניאל וולש כתב מאמר הפעלת systemd בתוך Docker Container, וכעבור כמה שנים - אחר, שנקרא הפעלת systemd בקונטיינר לא מוגן, בו ציין כי המצב לא השתפר בהרבה. במיוחד הוא כתב כי "למרבה הצער, אפילו שנתיים לאחר מכן, אם תחפש בגוגל "מערכת דוקר", הדבר הראשון שעולה הוא אותו מאמר ישן שלו. אז הגיע הזמן לשנות משהו". בנוסף, כבר דיברנו על התנגשות בין Docker למפתחי systemd.

הפעלת systemd במיכל

במאמר זה נראה מה השתנה עם הזמן וכיצד פודמן יכול לעזור לנו בעניין זה.

ישנן סיבות רבות להפעיל systemd בתוך קונטיינר, כגון:

  1. מכולות מולטי שירות - אנשים רבים רוצים למשוך את יישומי ריבוי השירותים שלהם ממכונות וירטואליות ולהפעיל אותם בקונטיינרים. עדיף, כמובן, לחלק יישומים כאלה למיקרו-שירותים, אבל לא כולם יודעים לעשות זאת עדיין או פשוט אין להם זמן. לכן, הפעלת יישומים כגון שירותים שהושקו על ידי systemd מקובצי יחידה היא הגיונית לחלוטין.
  2. Systemd Unit Files – רוב היישומים הפועלים בתוך קונטיינרים בנויים מקוד שרץ בעבר על מכונות וירטואליות או פיזיות. לאפליקציות אלו יש קובץ יחידה שנכתב עבור אפליקציות אלו ומבין כיצד יש להפעיל אותן. אז עדיין עדיף להתחיל שירותים באמצעות שיטות נתמכות, במקום לפרוץ לשירות init משלך.
  3. Systemd הוא מנהל תהליכים. הוא מבצע ניהול שירות (כיבוי, הפעלה מחדש של שירותים או הורג תהליכי זומבים) טוב יותר מכל כלי אחר.

עם זאת, ישנן סיבות רבות לא להפעיל systemd בקונטיינרים. העיקרי שבהם הוא ש-systemd/journald שולט על הפלט של קונטיינרים, וכלים כמו קוברנט או הילוך פתוח מצפים ממכולות לכתוב יומן ישירות ל-stdout ול-stderr. לכן, אם אתה מתכוון לנהל קונטיינרים באמצעות כלי תזמור כמו אלה שהוזכרו לעיל, עליך לשקול ברצינות שימוש בקונטיינרים מבוססי מערכת. בנוסף, מפתחי Docker ו-Moby התנגדו לעתים קרובות מאוד לשימוש ב-systemd בקונטיינרים.

בואו של פודמן

אנו שמחים לדווח שהמצב סוף סוף התקדם. הצוות האחראי על הפעלת הקונטיינרים ב-Red Hat החליט לפתח מנוע מיכל משלך. יש לו שם פודמן ומציע את אותו ממשק שורת פקודה (CLI) כמו Docker. וכמעט כל פקודות Docker ניתן להשתמש ב- Podman באותו אופן. לעתים קרובות אנו עורכים סמינרים, אשר נקראים כיום שינוי דוקר לפודמן, והשקופית הראשונה קוראת לכתיבה: כינוי docker=podman.

אנשים רבים עושים בדיוק את זה.

פודמן ואני לא מתנגדים בשום צורה לקונטיינרים מבוססי systemd. אחרי הכל, Systemd משמש לעתים קרובות יותר מאחרים כתת-מערכת init. Linux, ואי-אפשרות לו לפעול כראוי בתוך קונטיינרים היא התעלמות מכך שאלפי אנשים רגילים להפעיל קונטיינרים.

Podman יודע מה לעשות כדי לגרום ל-systemd לעבוד כמו שצריך במיכל. זה צריך דברים כמו הרכבה של tmpfs על /run ו-/tmp. היא אוהבת שהסביבה "מכוללת" מופעלת ומצפה להרשאות כתיבה לחלק שלה בספריית cgroup ולתיקיית /var/log/journald.

כאשר אתה מפעיל קונטיינר שבו הפקודה הראשונה היא init או systemd, Podman מגדיר אוטומטית tmpfs ו-Cgroups כדי להבטיח ש-systemd מתחיל ללא בעיות. כדי לחסום את מצב ההשקה האוטומטית הזה, השתמש באפשרות --systemd=false. שימו לב ש-Podman משתמש במצב systemd רק כאשר הוא רואה שהוא צריך להפעיל פקודת systemd או init.

הנה קטע מהמדריך:

גבר פודמן לרוץ
...

–systemd=true|false

הפעלת קונטיינר במצב systemd. מופעל כברירת מחדל.

אם אתה מפעיל פקודת systemd או init בתוך קונטיינר, Podman יגדיר נקודות הרכבה של tmpfs בספריות הבאות:

/run, /run/lock, /tmp, /sys/fs/cgroup/systemd, /var/lib/journal

כמו כן, ברירת המחדל של אות העצירה תהיה SIGRTMIN+3.

כל זה מאפשר ל-systemd לפעול במיכל סגור ללא כל שינויים.

הערה: systemd מנסה לכתוב למערכת הקבצים cgroup. עם זאת, SELinux כברירת מחדל, פעולה זו מונעת ממכולות לעשות זאת. כדי לאפשר כתיבה, הפעל את הפרמטר הבוליאני container_manage_cgroup:

setsebool -P container_manage_cgroup true

כעת תראה איך נראה ה-Dockerfile להפעלת systemd בקונטיינר באמצעות Podman:

# cat Dockerfile

FROM fedora

RUN dnf -y install httpd; dnf clean all; systemctl enable httpd

EXPOSE 80

CMD [ "/sbin/init" ]

זה הכול.

כעת אנו מרכיבים את המיכל:

# podman build -t systemd .

אנחנו דוברים דרום-מזרחLinux אפשר ל-systemd לשנות את תצורת Cgroups:

# setsebool -P container_manage_cgroup true

אגב, אנשים רבים שוכחים מהשלב הזה. למרבה המזל, זה צריך להיעשות רק פעם אחת וההגדרה נשמרת לאחר אתחול המערכת.

עכשיו אנחנו רק מתחילים את המיכל:

# podman run -ti -p 80:80 systemd

systemd 239 running in system mode. (+PAM +AUDIT +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN2 -IDN +PCRE2 default-hierarchy=hybrid)

Detected virtualization container-other.

Detected architecture x86-64.

Welcome to Fedora 29 (Container Image)!

Set hostname to <1b51b684bc99>.

Failed to install release agent, ignoring: Read-only file system

File /usr/lib/systemd/system/systemd-journald.service:26 configures an IP firewall (IPAddressDeny=any), but the local system does not support BPF/cgroup based firewalling.

Proceeding WITHOUT firewalling in effect! (This warning is only shown for the first loaded unit using IP firewalling.)

[  OK ] Listening on initctl Compatibility Named Pipe.

[  OK ] Listening on Journal Socket (/dev/log).

[  OK ] Started Forward Password Requests to Wall Directory Watch.

[  OK ] Started Dispatch Password Requests to Console Directory Watch.

[  OK ] Reached target Slices.

…

[  OK ] Started The Apache HTTP Server.

זהו, השירות פועל:

$ curl localhost

<html  xml_lang="en" lang="en">

…

</html>

הערה: אל תנסה את זה ב-Docker! שם אתה עדיין צריך לרקוד עם טמבורין כדי לשגר סוגים כאלה של מיכלים דרך הדמון. (שדות וחבילות נוספים יידרשו כדי לגרום לכל זה לעבוד בצורה חלקה ב-Docker, או שיהיה צורך להפעיל אותו במיכל מועדף. לפרטים, ראה статье.)

עוד כמה דברים מגניבים על Podman ו-systemd

Podman עובד טוב יותר מ-Docker בקבצי יחידות מערכת

אם צריך להפעיל קונטיינרים כשהמערכת מאתחלת, אז אתה יכול פשוט להכניס את הפקודות המתאימות של Podman לקובץ systemd unit, שיפעיל את השירות וינטר אותו. Podman משתמש בדגם fork-exec הסטנדרטי. במילים אחרות, תהליכי מיכל הם ילדים של תהליך Podman, כך ש-systemd יכולה לנטר אותם בקלות.

Docker משתמש במודל שרת-לקוח, וניתן למקם פקודות Docker CLI ישירות בקובץ יחידה. עם זאת, ברגע שלקוח ה-Docker מתחבר לדימון ה-Docker, הוא (הלקוח) הופך לעוד תהליך שמטפל ב-stdin וב-stdout. בתורו, ל-systemd אין מושג לגבי הקשר בין לקוח ה-Docker לבין הקונטיינר שפועל תחת שליטת ה-Docker daemon, ולכן, בתוך המודל הזה, systemd ביסודו לא יכולה לפקח על השירות.

הפעלת systemd דרך שקע

פודמן מטפל בצורה נכונה בהפעלה דרך שקע. מכיוון ש-Podman משתמש במודל fork-exec, הוא יכול להעביר את השקע לתהליכי מיכל הצאצא שלו. Docker לא יכול לעשות זאת מכיוון שהוא משתמש במודל שרת-לקוח.

שירות varlink שבו משתמש פודמן כדי לתקשר עם לקוחות מרוחקים למכולות מופעל למעשה באמצעות שקע. חבילת cockpit-podman, שנכתבה ב-Node.js וחלק מפרויקט cockpit, מאפשרת לאנשים ליצור אינטראקציה עם קונטיינרים של Podman באמצעות ממשק אינטרנט. דמון האינטרנט שמפעיל את cockpit-podman שולח הודעות לשקע varlink שמערכת מאזינה לו. לאחר מכן Systemd מפעילה את תוכנית Podman כדי לקבל הודעות ולהתחיל בניהול קונטיינרים. הפעלת systemd מעל שקע מבטלת את הצורך בדמון הפועל כל הזמן בעת ​​יישום ממשקי API מרוחקים.

אנחנו גם מפתחים לקוח Podman נוסף בשם podman-remote, שמיישם את אותו Podman CLI אך משתמש ב-varlink כדי להפעיל קונטיינרים. Podman-remote יכול להריץ מעל סשנים של SSH, מה שמאפשר אינטראקציה מאובטחת עם קונטיינרים במכונות שונות. אנחנו מתכננים בסופו של דבר להרחיב את podman-remote כדי לתמוך ב-MacOS ו-. Windows יחד עם Linuxכך שמפתחים בפלטפורמות אלו יוכלו להריץ מכונה וירטואלית Linux כאשר Podman varlink פועל ויש לי תחושה מלאה שמכולות פועלות על המכונה המקומית.

SD_NOTIFY

Systemd מאפשרת לדחות את השקת שירותי העזר עד לתחילת השירות המכולות שהם דורשים. Podman יכול להעביר את שקע SD_NOTIFY לשירות המכולה, כך שהשירות יודיע ל-systemd שהוא מוכן לפעולה. ושוב, Docker, שמשתמש במודל שרת-לקוח, לא יכול לעשות זאת.

בתוכניות

אנו מתכננים להוסיף את הפקודה podman generate systemd CONTAINERID, שתיצור קובץ systemd unit לניהול קונטיינר ספציפי שצוין. זה אמור לעבוד הן במצב שורש והן במצב חסר שורש עבור קונטיינרים לא מורשים. אפילו ראינו בקשה לזמן ריצה תואם OCI systemd-nspawn.

מסקנה

הפעלת systemd בקונטיינר היא צורך מובן. ובזכות Podman, סוף סוף יש לנו זמן ריצה של מיכל שאינו מתנגש עם systemd, אבל מקל על השימוש בו.

מקור: www.habr.com

קנה אירוח אמין לאתרים עם הגנת DDoS, שרתי VPS VDS 🔥 קנה אחסון אתרים אמין עם הגנת DDoS, שרתי VPS VDS | ProHoster