قم بتشغيل systemd في حاوية

لقد كنا نتابع موضوع استخدام systemd في الحاويات لفترة طويلة. في عام 2014 كتب مهندس الأمن لدينا دانيال والش مقالاً تشغيل systemd داخل حاوية Docker، وبعد عامين - آخر ، والذي كان يسمى تشغيل systemd في حاوية غير مميزة، الذي ذكر فيه أن الوضع لم يتحسن كثيرًا. على وجه الخصوص ، كتب أنه "لسوء الحظ ، وبعد عامين ، إذا بحثت على google" نظام Docker "، فإن نفس المقالة القديمة في صورته المنبثقة أولاً. لذا حان وقت التغيير ". بالإضافة إلى ذلك ، لقد تحدثنا بالفعل عن الصراع بين مطوري Docker و systemd.

قم بتشغيل systemd في حاوية

في هذه المقالة ، سوف نوضح ما الذي تغير منذ ذلك الحين وكيف يمكن أن يساعدنا Podman في هذا الأمر.

هناك العديد من الأسباب لتشغيل systemd داخل الحاوية ، مثل:

  1. حاويات متعددة الخدمات - يرغب العديد من الأشخاص في سحب تطبيقاتهم متعددة الخدمات من الأجهزة الافتراضية وتشغيلها في حاويات. سيكون من الأفضل ، بالطبع ، تقسيم هذه التطبيقات إلى خدمات مصغرة ، ولكن لا يعرف الجميع كيفية القيام بذلك حتى الآن أو ببساطة لا يوجد وقت. لذا فإن تشغيل هذه التطبيقات كخدمات يديرها systemd من ملفات الوحدة أمر منطقي تمامًا.
  2. ملفات وحدة النظام - معظم التطبيقات التي تعمل داخل الحاويات مبنية من كود تم تشغيله مسبقًا على أجهزة افتراضية أو فعلية. تحتوي هذه التطبيقات على ملف وحدة تمت كتابته لهذه التطبيقات ويفهم كيفية تشغيلها. لذلك لا يزال من الأفضل بدء الخدمات باستخدام الأساليب المدعومة بدلاً من اختراق خدمة init الخاصة بك.
  3. Systemd هو مدير العمليات. يدير الخدمات (إيقاف تشغيل أو إعادة تشغيل الخدمات أو قتل الزومبي) بشكل أفضل من أي أداة أخرى.

ومع ذلك ، هناك الكثير من الأسباب لعدم تشغيل systemd في الحاويات. العامل الرئيسي هو أن systemd / journalald يتحكم في إخراج الحاويات وأدوات مثل Kubernetes أو فتح تتوقع الحاويات كتابة السجلات مباشرة إلى stdout و stderr. لذلك إذا كنت ستدير الحاويات من خلال أدوات التنسيق مثل تلك المذكورة أعلاه ، فأنت بحاجة إلى التفكير بجدية في استخدام الحاويات القائمة على النظام. بالإضافة إلى ذلك ، غالبًا ما عارض مطورو Docker و Moby بشدة استخدام systemd في الحاويات.

مجيء بودمان

يسعدنا أن نعلن أن الحالة قد تحركت إلى الأمام أخيرًا. قرر الفريق المسؤول عن تشغيل الحاويات في Red Hat التطوير محرك الحاوية الخاص بك. حصل على اسم Podman ويقدم نفس واجهة سطر الأوامر (CLI) مثل Docker. ويمكن استخدام جميع أوامر Docker تقريبًا في Podman بنفس الطريقة. غالبًا ما نعقد الندوات ، والتي تسمى الآن قم بتغيير Docker إلى Podman، والشريحة الأولى تدعو للكتابة: alias docker = podman.

كثير من الناس يفعلون ذلك بالضبط.

أنا و Podman لا نتعارض بأي حال من الأحوال مع الحاويات القائمة على النظام. بعد كل شيء ، يتم استخدام Systemd في كثير من الأحيان كنظام فرعي init الفرعي من Linux ، ومنعه من العمل بشكل صحيح في الحاويات يعني تجاهل الطريقة التي يستخدم بها آلاف الأشخاص لتشغيل الحاويات.

يعرف Podman ما يجب القيام به لجعل systemd يعمل بشكل صحيح في الحاوية. إنها بحاجة إلى أشياء مثل تركيب tmpfs on / run و / tmp. إنها تحب تمكين بيئة "حاوية" وتنتظر أذونات الكتابة إلى الجزء الخاص بها من دليل cgroup وإلى المجلد / var / log / journalald.

عند بدء تشغيل حاوية باستخدام init أو systemd كأمر أول ، يقوم Podman تلقائيًا بتكوين tmpfs و Cgroups بحيث يبدأ systemd بسلاسة. لتعطيل وضع التشغيل التلقائي هذا ، استخدم الخيار --systemd = false. لاحظ أن Podman يستخدم فقط وضع systemd عندما يرى أنه يحتاج إلى تشغيل أمر systemd أو init.

هذا مقتطف من الدليل:

رجل يركض podman
...

–systemd = صحيح | خطأ

تشغيل الحاوية في وضع 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 صحيحة

شاهد الآن كيف يبدو 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 .

أخبر SELinux بالسماح لـ 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 ، والذي سيبدأ الخدمة ويراقبها. يستخدم Podman نموذج fork-exec القياسي. بعبارة أخرى ، عمليات الحاوية هي جزء من عملية Podman ، لذلك يمكن أن يقوم systemd بمراقبتها بسهولة.

يستخدم Docker نموذج خادم العميل ، ويمكن أيضًا وضع أوامر Docker CLI مباشرة في ملف الوحدة. ومع ذلك ، بعد اتصال عميل Docker بشفرة Docker ، يصبح (العميل) مجرد عملية أخرى تتعامل مع stdin و stdout. في المقابل ، ليس لدى systemd أي فكرة عن الاتصال بين عميل Docker والحاوية التي تشغل Docker daemon ، وبالتالي ، ضمن هذا النموذج ، لا يستطيع systemd مراقبة الخدمة من حيث المبدأ.

تفعيل systemd عبر المقبس

يتعامل Podman مع تنشيط المقبس بشكل صحيح. نظرًا لأن Podman يستخدم نموذج fork-exec ، فيمكنه إعادة توجيه المقبس إلى عمليات الحاوية الفرعية الخاصة به. لا يستطيع Docker القيام بذلك لأنه يستخدم نموذج خادم العميل.

يتم استدعاء خدمة varlink التي يستخدمها Podman للسماح للعملاء البعيدين بالتواصل مع الحاويات عبر مقبس. تسمح حزمة Cockpit-podman ، المكتوبة في Node.js وجزء من مشروع قمرة القيادة ، للأشخاص بالتفاعل مع حاويات Podman من خلال واجهة ويب. يرسل عفريت الويب الذي يقوم بتشغيل cockpit-podman رسائل إلى مقبس varlink الذي يستمع إليه systemd. ثم يقوم Systemd بتنشيط برنامج Podman لتلقي الرسائل والبدء في إدارة الحاويات. يؤدي تنشيط systemd عبر المقبس إلى التخلص من الحاجة إلى برنامج خفي يعمل باستمرار عند تنفيذ واجهات برمجة التطبيقات عن بُعد.

نقوم أيضًا بتطوير عميل 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 ، الذي يستخدم نموذج خادم العميل ، كيف.

في الخطط

نحن نخطط لإضافة أمر CONTAINERID لإنشاء نظام podman والذي سينشئ ملف وحدة systemd لإدارة حاوية معينة. يجب أن يعمل هذا في كل من أوضاع الجذر وبدون جذر للحاويات غير المتميزة. حتى أننا رأينا طلبًا لوقت تشغيل systemd-nspawn متوافق مع OCI.

اختتام

يعد تشغيل systemd في حاوية حاجة مفهومة. وبفضل Podman ، لدينا أخيرًا وقت تشغيل حاوية لا يعادي systemd ، ولكنه يجعله سهل الاستخدام.

المصدر: www.habr.com

إضافة تعليق