معمارية Jenkins والإعداد
معمارية Jenkins والإعداد
Jenkins هو أكثر خوادم الأتمتة انتشاراً في الصناعة. مبني على Java، يُشغّل pipelines CI/CD في شركات من كل الأحجام منذ 2011 — وبالرغم من ظهور بدائل مستضافة، يظل الحل الأول حين تحتاج الفرق إلى تخصيص عميق، أو تشغيل معزول عن الإنترنت، أو تنسيق العمل عبر مئات الأجهزة غير المتجانسة. قبل أن تكتب سطراً واحداً في Jenkinsfile، تحتاج إلى نموذج ذهني دقيق عن بنية Jenkins والسبب وراء هذه البنية.
معمارية Controller / Agent
Jenkins مبني على نموذج طبقتين واضح. Controller (كان يُسمى تاريخياً "master") هو الدماغ: يستضيف واجهة الويب، يحتفظ بالتهيئة وسجل البناء، يقرأ تعريفات الـ pipeline، يجدول الوظائف، ويوزّع العمل على agents (كانت تُسمى تاريخياً "slaves"). الـ agents هم العضلات: عمال بسيطون يُنفّذون أوامر البناء الفعلية ويُعيدون النتائج إلى الـ controller.
يوجد هذا الفصل لثلاثة أسباب بالغة الأهمية في الإنتاج:
- العزل: عمليات البناء تُنفّذ كوداً غير موثوق، وتستهلك CPU/ذاكرة كبيرة، وقد تُخلّف ملفات على القرص. إبقاء ذلك بعيداً عن الـ controller يحمي محرك الجدولة من عمليات بناء جامحة وهجمات سلسلة التوريد.
- القابلية للتوسع: يمكن لـ controller واحد إدارة مئات الـ agents. التوسع الأفقي للـ agents مستقل عن سعة الـ controller — إضافة إنتاجية البناء لا تستلزم لمس الـ controller أبداً.
- التنوع: وظائف مختلفة تحتاج بيئات مختلفة. بناء iOS يحتاج macOS؛ وظيفة .NET على Windows تحتاج Visual Studio؛ وظيفة GPU تحتاج مشغّلات CUDA. كل agent يمكنه حمل نظام تشغيل مختلف أو سلسلة أدوات أو أجهزة مختلفة.
كيف يتصل الـ Agents
يتصل الـ agents بالـ controller بأحد نمطين:
- SSH (صادر من الـ controller): يتصل الـ controller بـ SSH بالـ agent، ينسخ
agent.jar(مكتبة الاتصال عن بُعد)، ويبدأ تشغيله. تحتاج آلة الـ agent إلى خادم SSH وعنوان قابل للوصول. هذا هو النمط التقليدي للـ VMs الدائمة. - JNLP / WebSocket (صادر من الـ agent): الـ agent هو من يبدأ الاتصال بالـ controller على البورت
50000(أو عبر WebSocket على البورت8080). هذا ضروري حين يكون الـ agents خلف NAT، داخل pods في Kubernetes، أو على VMs سحابية مؤقتة. يستخدم إضافة Kubernetes هذا النمط حصرياً — الـ pods تتصل للخارج، والـ controller لا يتصل للداخل أبداً.
8080 أو 443 خلف reverse proxy)، مما يُلغي الحاجة إلى فتح البورت 50000 عبر جدران الحماية. فعّله من Manage Jenkins ← Security ← Agents ← WebSocket.تثبيت Jenkins (مستوى الإنتاج)
أسرع طريق إلى controller دائم على Ubuntu هو مستودع APT الرسمي، الذي يمنحك حزماً موقّعة ومسارات ترقية نظيفة. فيما يلي تسلسل التثبيت القياسي لعام 2025.
يستمع Jenkins الآن على http://<server-ip>:8080. افتحه في المتصفح والصق كلمة مرور المسؤول الأولية لبدء معالج الإعداد. اختر Install suggested plugins للحصول على قاعدة تشمل إضافات Git وPipeline وBlue Ocean وCredentials.
تقوية الأمان الأولية
Jenkins حديث التثبيت بالإعدادات الافتراضية ليس آمناً للإنتاج. الخطوات التالية غير قابلة للتفاوض قبل كشف الـ controller للشبكة.
نموذج الأمان: ما يجب تهيئته فوراً
بعد معالج الإعداد، انتقل إلى Manage Jenkins → Security وقفّل المجالات التالية:
- المصادقة: انتقل من "قاعدة بيانات مستخدمي Jenkins" إلى SSO المؤسسي في أقرب وقت. يدعم Jenkins LDAP وSAML 2.0 (عبر إضافة) وGitHub OAuth. تسجيل الدخول الموحّد يعني لا عبء تدوير كلمات مرور Jenkins منفصلة وإلغاء تفعيل فوري عند مغادرة الموظفين.
- التفويض: اضبط الاستراتيجية على Role-Based Access Control (RBAC) باستخدام إضافة Role Strategy. عرّف على الأقل ثلاثة أدوار:
admin(وصول كامل)،developer(قراءة + بناء + إلغاء بناءاته الخاصة)، وread-only(عرض السجلات، لا تشغيل). لا تُشغّل أبداً في وضع "أي شخص يمكنه فعل أي شيء" على controller حقيقي. - أمان الـ Agent: فعّل Agent → Controller Security (Manage Jenkins → Security → Agent Protocols). يمنع هذا agent مخترقاً من قراءة ملفات الـ controller الاعتباطية أو التلاعب في قائمة الوظائف. هو معطّل افتراضياً في بعض التثبيتات القديمة.
- أمان السكريبت: إضافة Script Security تقيّد ما يمكن لكود Groovy في الـ pipelines تنفيذه. وضع Groovy sandbox إلزامي — عطّله فقط للمكتبات المشتركة الموثوقة وبمراجعة كود فقط.
مجلد Jenkins الرئيسي
كل ما يملكه Jenkins يعيش تحت JENKINS_HOME — افتراضياً /var/lib/jenkins. فهم تخطيطه ضروري للنسخ الاحتياطي والتعافي من الكوارث:
config.xml— التهيئة العامة: إعدادات الأمان، أدوات SCM، تعريفات أدوات JDK/Maven/Node.credentials.xml— مخزن الاعتمادات المشفّر. احرص على هذا الملف؛ فقدانه يعني فقدان القدرة على فك تشفير الأسرار المخزّنة.jobs/— مجلد فرعي لكل وظيفة يحتويconfig.xml(تعريف الوظيفة) وbuilds/(سجل البناء، السجلات، الحزم).nodes/— ملفات تهيئة عقد الـ agent.plugins/— ملفات JARs للإضافات المثبّتة وبياناتها.secrets/— مفتاح التشفير الرئيسي وملفات الأسرار. الوضع0700؛ لا تنسخه احتياطياً في مكان عام.workspace/— مساحات عمل البناء. لا تنسخها احتياطياً؛ هي مؤقتة وغالباً كبيرة.
JENKINS_HOME/jobs/<job>/builds/ ينمو بلا حدود. كل Declarative Pipeline يجب أن يتضمن خيار buildDiscarder: options { buildDiscarder(logRotator(numToKeepStr: '30', artifactNumToKeepStr: '5')) }. اضبطه عالمياً في Manage Jenkins → System ومحلياً في كل Jenkinsfile. الـ controllers التي ينفد قرصها تتعطل بشدة ويمكنها إتلاف قاعدة بيانات الوظائف.ربط أول Agent
مع تشغيل الـ controller وتأمينه، أضف agent Linux دائماً عبر SSH لنقل أعباء البناء فوراً.
ما يجب ألا يفعله الـ Controller أبداً
يجب أن يكون لدى controller المُقوّى صفر منفّذين (executors) — انتقل إلى Manage Jenkins → Nodes → Built-In Node → Configure واضبط عدد المنفّذين على 0. هذه واحدة من أهم خطوات تقوية الإنتاج وتُتجاهل باستمرار من الفرق الجديدة على Jenkins.
تشغيل بناءات على الـ controller يكشف JENKINS_HOME بأكمله — بما فيه الاعتمادات وأسرار الوظائف ومفتاح التشفير — لكود البناء الاعتباطي. إذا أخذ pipeline مستودعاً يحتوي Jenkinsfile خبيثاً أو سكريبت بناء ضار، يمكنه قراءة secrets/master.key مباشرة. نقل كل التنفيذ إلى الـ agents يُحصر نطاق تأثير agent مخترق في مساحة عمل agent واحد فقط.
المعمارية على نطاق واسع: كيف يبدو Jenkins على مستوى Google
المؤسسات الكبيرة (Netflix وLinkedIn وWalmart Labs) تُشغّل Jenkins في طوبولوجيا controller لكل فريق أو controller لكل نطاق بدلاً من controller مشترك واحد. للـ controller الواحد سقف عملي حول 200-300 بناء متزامن قبل أن تصبح ذاكرة JVM وI/O نظام الملفات عوائق. إضافة Kubernetes هي الحل القياسي للتجهيز المرن للـ agents: كل مرحلة بناء تُشغّل pod جديداً، تُنفّذ، ثم تُدمَّر — مما يُلغي انجراف الـ agent ويُتيح عزل سلسلة أدوات خاصة بكل وظيفة دون الحفاظ على أسطول من الـ VMs الدائمة.
الدرس التالي يستكشف الفرق بين وظائف Freestyle والـ Pipelines — نوعا الوظائف اللذان يوفرهما Jenkins ولماذا حلّت Declarative Pipelines محل Freestyle في كل حالة استخدام CI/CD جادة.