المحتوى عن 'حاويات'.



مزيد من الخيارات

  • ابحث بالكلمات المفتاحية

    أضف وسومًا وافصل بينها بفواصل ","
  • ابحث باسم الكاتب

نوع المُحتوى


التصنيفات

  • التخطيط وسير العمل
  • التمويل
  • فريق العمل
  • دراسة حالات
  • نصائح وإرشادات
  • التعامل مع العملاء
  • التعهيد الخارجي
  • التجارة الإلكترونية
  • الإدارة والقيادة
  • السلوك التنظيمي
  • مقالات ريادة أعمال عامة

التصنيفات

  • PHP
    • Laravel
    • ووردبريس
  • جافاسكريبت
    • Node.js
    • jQuery
    • AngularJS
    • Cordova
    • React
  • HTML
    • HTML5
  • CSS
  • SQL
  • لغة C#‎
  • لغة C++‎
  • بايثون
    • Flask
    • Django
  • لغة روبي
    • Sass
    • إطار عمل Bootstrap
    • إطار العمل Ruby on Rails
  • لغة Go
  • لغة جافا
  • لغة Kotlin
  • برمجة أندرويد
  • لغة Swift
  • لغة R
  • لغة TypeScript
  • ‎.NET
    • ASP.NET
  • سير العمل
    • Git
  • صناعة الألعاب
    • Unity3D
    • منصة Xamarin
  • سهولة الوصول
  • مقالات برمجة عامة

التصنيفات

  • تجربة المستخدم
  • الرسوميات
    • إنكسكيب
    • أدوبي إليستريتور
    • كوريل درو
  • التصميم الجرافيكي
    • أدوبي فوتوشوب
    • أدوبي إن ديزاين
    • جيمب
  • التصميم ثلاثي الأبعاد
    • 3Ds Max
    • Blender
  • نصائح وإرشادات
  • مقالات تصميم عامة

التصنيفات

  • خواديم
    • الويب HTTP
    • قواعد البيانات
    • البريد الإلكتروني
    • DNS
    • Samba
  • الحوسبة السّحابية
    • Docker
  • إدارة الإعدادات والنّشر
    • Chef
    • Puppet
    • Ansible
  • لينكس
  • FreeBSD
  • حماية
    • الجدران النارية
    • VPN
    • SSH
  • مقالات DevOps عامة

التصنيفات

  • التسويق بالأداء
    • أدوات تحليل الزوار
  • تهيئة محركات البحث SEO
  • الشبكات الاجتماعية
  • التسويق بالبريد الالكتروني
  • التسويق الضمني
  • التسويق بالرسائل النصية القصيرة
  • استسراع النمو
  • المبيعات
  • تجارب ونصائح
  • مبادئ علم التسويق

التصنيفات

  • إدارة مالية
  • الإنتاجية
  • تجارب
  • مشاريع جانبية
  • التعامل مع العملاء
  • الحفاظ على الصحة
  • التسويق الذاتي
  • مقالات عمل حر عامة

التصنيفات

  • الإنتاجية وسير العمل
    • مايكروسوفت أوفيس
    • ليبر أوفيس
    • جوجل درايف
    • شيربوينت
    • Evernote
    • Trello
  • تطبيقات الويب
    • ووردبريس
    • ماجنتو
  • أندرويد
  • iOS
  • macOS
  • ويندوز

التصنيفات

  • شهادات سيسكو
    • CCNA
  • شهادات مايكروسوفت
  • شهادات Amazon Web Services
  • شهادات ريدهات
    • RHCSA
  • شهادات CompTIA
  • مقالات عامة

أسئلة وأجوبة

  • الأقسام
    • أسئلة ريادة الأعمال
    • أسئلة العمل الحر
    • أسئلة التسويق والمبيعات
    • أسئلة البرمجة
    • أسئلة التصميم
    • أسئلة DevOps
    • أسئلة البرامج والتطبيقات
    • أسئلة الشهادات المتخصصة

التصنيفات

  • ريادة الأعمال
  • العمل الحر
  • التسويق والمبيعات
  • البرمجة
  • التصميم
  • DevOps

تمّ العثور على 9 نتائج

  1. عند تشغيل خدمات وتطبيقات متعددة على عنقود Kubernetes، يمكن أن يساعدك مكدس سجلات مركزي على مستوى العنقود على فرز الحجم الكبير لبيانات السجلات التي تنتجها كائنات Pod، وتحليل تلك السجلّات بسرعة. أحد حلول التسجيل المركزية الشائعة هو مكدس EFK الذي يضم التطبيقات الثلاث Elasticsearch، وFluentd وKibana. Elasticsearch هو محرك بحث فوري ومُوزّع وقابل للتحجيم يسمح بالبحث في النصوص والبيانات المنظَّمة وكذلك التحليلات. يُستخدم Elasticsearch عادةً لفهرسة كميات كبيرة من بيانات السجلّات والبحث فيها، ولكن يمكن استخدامه أيضًا للبحث في العديد من أنواع المستندات المختلفة. يُنشَر Elasticsearch عادة جنبًا إلى جنب مع Kibana، وهي واجهة أمامية ولوحة تحكم فعّالة لعرض البيانات. تتيح Kibana استكشاف بيانات سجل Elasticsearch الخاص بك من خلال واجهة ويب، وإنشاء لوحات تحكم واستعلامات للإجابة بسرعة على الأسئلة والحصول على نظرة مفصَّلة عن تطبيقات Kubernetes. سنستخدم في هذا الدرس Fluentd لجمع بيانات السجل وتحويلها وشحنها إلى سند Elasticsearch الخلفي. Fluentd هو مُجمِّع بيانات شائع الاستخدام، ومفتوح المصدر، سنعدّه على عُقد Kubernetes لتتبّع ملفات سجلّات الحاوية، وتصفية وتحويل بيانات السجل، وتسليمها إلى عنقود Elasticsearch، حيث تُفهرَس وتُخزَّن. سنبدأ بإعداد وتشغيل عنقود Elasticearch قابل للتحجيم، ثم ننشئ خدمة Kibana وعمليّة النشر الخاصّة بها على Kubernetes. في الختام، سنعدّ Fluentd بصيغة متحكّم DaemonSet حتى يُشغَّل على كل عقدة عاملة على Kubernetes. المتطلبات الأساسية قبل أن تبدأ بهذا الدليل، تأكد من توفر ما يلي لك: عنقود Kubernetes، الإصدار 1.10 فما فوق، مع تفعيل التحكّم في الوصول اعتمادًا على الدور (Role-Based Accedd Control, RBAC). تأكّد أن العنقود لديه موارد كافية لتشغيل مكدس EFK، وإن لم يكن، زد حجم العنقود بإضافة عقَد عاملة جديدة. سننشر Elasticsearch على ثلاث كائنات Pod (يمكنك تقليل العدد إلى 1 إنْ لزم الأمر)، بالإضافة إلى كائن Pod واحد لبيئة Kibana. ستشغّل كل عقدة عاملة كائن Pod لتطبيق Fluentd. يتكون العنقود في هذا الدليل من ثلاث عقد عاملة ومستوى تحكم مُدبَّر (Managed control plane) واحد. أداة سطر الأوامر kubectl مُثبّتة على جهازك المحلي، مُعدَّة للاتصال بالعنقود. يمكنك قراءة المزيد حول تثبيت kubectl في التوثيق الرسمي. بمجرد الانتهاء من إعداد هذه المكونات، تكون جاهزًا للبدء بهذا الدليل. الخطوة الأولى: إنشاء فضاء أسماء (Namespace) قبل إطلاق عنقود Elasticsearch، سنُنشئ أولاً فضاء أسماء نثبّت فيه جميع أدوات التسجيل الخاصة بنا. يتيح لك Kubernetes فصل الكائنات التي تعمل في العنقود باستخدام تجريد ينشئ "عنقودَا افتراضيًّا" يُسمّى فضاء الأسماء. سننشئ في هذا الدليل فضاء أسماء نطلق عليه kube-logging نثبّت فيه مكونات مكدس EFK. علاوةً على ذلك، سيسمح لنا فضاء الأسماء هذا بتنظيف مكدس EFK وإزالته بسرعة دون فقدان وظائف أخرى في عنقود Kubernetes. للبدء، تَحقَّق أولاً من فضاءات الأسماء الموجودة في العنقود باستخدام kubectl: $ kubectl get namespaces يجب أن ترى فضاءات الأسماء الثلاثة المبدئية التالية، والتي تأتي مُثبَّتة مسبقًا مع عنقود Kubernetes: NAME STATUS AGE default Active 5m kube-system Active 5m kube-public Active 5m يحتوي فضاء الأسماء default على كائنات أنشئت بدون تحديد فضاء أسماء لها. يحتوي فضاء الأسماء kube-system على كائنات أنشأها واستخدمها نظام Kubernetes، مثلkube-dns، kube-proxy، وkubernetes-dashboard. من الجيد الحفاظ على نظافة فضاءات الأسماء هذه وعدم تلويثها بأحمال عمل التطبيقات والأدوات الأخرى. فضاء الأسماء kube-public هو الآخرأنشئ تلقائيًا ويمكن استخدامه لتخزين الكائنات التي تريد لها أن تكون قابلة للقراءة ويمكن الوصول إليها عبر العنقود بأكمله، حتى للمستخدمين الذين لم تستوثق منهم (Unauthenticated users). لإنشاء فضاء الأسماء kube-logging، أولًا افتح ملفًّا يُسمى kube-logging.yaml باستخدام المحرر المفضل لديك، مثل nano: $ nano kube-logging.yaml داخل المحرر، الصق كائن فضاء الأسماء التالي المكتوب بصيغة YAML: kind: Namespace apiVersion: v1 metadata: name: kube-logging ثم احفظ الملف وأغلقه. هنا، نحدد نوع كائن Kubernetes بأنه فضاء أسماء. لمعرفة المزيد حول كائنات فضاء الأسماء، راجع إرشادات فاضاءات الأسماء في توثيق Kubernetes. نحدد أيضًا إصدار واجهة تطبيقات Kubernetes المستخدم لإنشاء الكائن (v1)، ونعيّن قيمة الحقل name (الاسم) لتكون kube-logging. أنشئ فضاء أسماء باستخدام الأمر kubectl create مع خيار اسم الملف f-، مباشرة بعد تحرير ملف كائن فضاء الأسماء kube-logging.yaml، وذلك على النحو التالي: $kubectl create -f kube-logging.yaml تظهر المُخرجات كالتالي: namespace/kube-logging created يمكنك بعد ذلك التأكد من إنشاء فضاء الأسماء بنجاح: $ kubectl get namespaces عند هذه النقطة، من المُفترض أن ترى فضاء الأسماء الجديد kube-logging : NAME STATUS AGE default Active 23m kube-logging Active 1m kube-public Active 23m kube-system Active 23m يمكننا الآن نشر عنقود Elasticsearch في فضاء الأسماء المعزول الخاص بالتسجيل. الخطوة 2 - إنشاء Elasticsearch StatefulSet الآن بعد أن أنشأنا فضاء أسماء لاستيعاب مكدس السجلّات، يمكننا البدء في طرح مكوناته المختلفة. سنبدأ أولاً بنشر عنقود Elasticsearch من ثلاث عُقد. في هذا الدليل نستخدم ثلاث كائنات Pod ليعمل عليها عنقود Elasticsearch، والهدف هو تجنب مشكلة "الدماغ المنصدع" (Split-brain)، التي قد تحدث في العنقود متعدّد العقد. تحدث مشكلة "الدماغ المنصدع" عندما يتعذر على عُقدة (أو عدة عقد) التواصل مع العقد الأخرى، فتُختار عدة عقد لتلعب دور القبطان (Master). مع ثلاث عقد، إذا انفصلت عقدة عن العنقود يمكن للعقدتين الأخريين انتخاب قبطان جديد ويمكن للعنقود أن يستمر في العمل بينما تحاول العقدة الضائعة الالتحاق. راجع المقالين A new era for cluster coordination in Elasticsearch وVoting configurations لمعرفة المزيد عن المشكلة المذكورة. إنشاء خدمة مجهولة العنوان (Headless Service) للبدء، سننشئ خدمة Kubernetes مجهولة العنوان تسمى elasticsearch تعرّف اسم نطاق لكائنات Pod الثلاثة الموجودة في عنقود Elasticsearch. لا توازن الخدمة مجهولة العنوان الحمل وليس لديها عنوان IP ثابت. راجع توثيق Kubernetes للمزيد عن هذه الخدمات. افتح الملف elasticsearch_svc.yaml بمحرّر النصوص المفضل لديك: $ nano elasticsearch_svc.yaml الصق فيه خدمة Kubernetes التالية (بصيغة YAML): elasticsearch_svc.yaml kind: Service apiVersion: v1 metadata: name: elasticsearch namespace: kube-logging labels: app: elasticsearch spec: selector: app: elasticsearch clusterIP: None ports: - port: 9200 name: rest - port: 9300 name: inter-node ثم احفظ الملف وأغلقه. نعيّن خدمة (service) تسمى elasticearch في فضاء الأسماء kube-logging ، ونعطيها اللصيقة app: elasticsearch. ثم نعيّن القيمة app: elasticsearch للحقل spec.selector. لكي تختار لخدمة كائن Pod عن طريق اللصيقة app: elasticsearch. عندما نربط متحكّم StatefulSet في عنقود Elasticsearch الخاص بنا مع هذه الخدمة، سترجع الخدمة سجل DNS من النوع A يشير إلى كائنات Pod ذات اللصيقة app: elasticsearch في عنقود Elasticsearch. ثم نعيّن الحقل clusterIP لتكون قيمته None، ممّا يجعل الخدمة مجهولة العنوان. أخيرًا، نُحدد المنافذ 9200 و9300 التي تُستخدَم على التوالي للتفاعل مع واجهة التطبيقات من النوع، وللتواصل الداخلي بين العقد. أنشئ الخدمة باستخدام kubectl: $ kubectl create -f elasticsearch_svc.yaml يجدر أن تظهر مُخرجات كالتالي: service/elasticsearch created أخيرًا، تحقق جيدًا من إنشاء الخدمة بنجاح باستخدام kubectl get: kubectl get services --namespace=kube-logging يجب أن ترى ما يلي: NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE elasticsearch ClusterIP None <none> 9200/TCP,9300/TCP 26s الآن بعد أن أعددنا خدمتنا المستقرة مجهولة العنوان والنطاق elasticsearch.kube-logging.svc.cluster.local. لكائنات Pod الخاصة بنا، يمكننا المضي قدمًا وإنشاء متحكّم المجموعة ذات الحالة (StatefulSet). إنشاء مجموعة ذات حالة (StatefulSet) من كائنات Pod يسمح لك كائن StatefulSet في Kubernetes بتعيين هوية ثابتة لكائنات Pod ومنحها تخزينًا مستقرًّا ودائما. يحتاج Elasticsearch لتخزين مستقر لضمان ديمومة البيانات عند إعادة جدولة كائنات Pod وإعادة تشغيلها. راجع التوثيق الرسمي للمزيد حول كائنات StatefulSet. افتح الملف المُسمّى elasticsearch_statefulset.yaml في المُحرر المفضل لديك: $ nano elasticsearch_statefulset.yaml سنمرّ خطوة خطوة على تعريف كائن StatefulSet من خلال لصق أجزاء من التعريف في الملف المذكور. نبدأ بنسخ ثم لصق الجزء التالي: apiVersion: apps/v1 kind: StatefulSet metadata: name: es-cluster namespace: kube-logging spec: serviceName: elasticsearch replicas: 3 selector: matchLabels: app: elasticsearch template: metadata: labels: app: elasticsearch نعرّف في الجزء أعلاه كائن StatefulSet باسم es-cluster في فضاء الأسماء kube-logging. ثم نربطه بخدمة elasticsearch التي أنشئت مسبقًا باستخدام حقل serviceName، ممّا يضمن إمكانية الوصول إلى كل كائن Pod في المجموعة باستخدام النطاق التالي: es-cluster-[0,1,2].elasticsearch.kube-logging.svc.cluster.local، حيث [0,1,2] يُشير إلى العدد الترتيبي لكائن Pod. نحدد ثلاث نسخ متطابقة (كائنات Pod) بتعيين القيمة 3 للحقل replicas، ونعيّن القيمة app: elasticseach للمُحدِّد matchLabels، ونكرّر الأمر مع الحقل spec.template.metadata.. يجب أن تتطابق قيمتا الحقلين .spec.selector.matchLabels و .spec.template.metadata.labels. يمكننا الآن الانتقال إلى مواصفات الكائن. ألصق الجزء التعريفي التالي، المكتوب بصيغة YAML، أسفل الجزء السابق: . . . spec: containers: - name: elasticsearch image: docker.elastic.co/elasticsearch/elasticsearch:7.2.0 resources: limits: cpu: 1000m requests: cpu: 100m ports: - containerPort: 9200 name: rest protocol: TCP - containerPort: 9300 name: inter-node protocol: TCP volumeMounts: - name: data mountPath: /usr/share/elasticsearch/data env: - name: cluster.name value: k8s-logs - name: node.name valueFrom: fieldRef: fieldPath: metadata.name - name: discovery.seed_hosts value: "es-cluster-0.elasticsearch,es-cluster-1.elasticsearch,es-cluster-2.elasticsearch" - name: cluster.initial_master_nodes value: "es-cluster-0,es-cluster-1,es-cluster-2" - name: ES_JAVA_OPTS value: "-Xms512m -Xmx512m" هنا نحدد كائنات Pod في المجموعة ذات الحالة (StatefulSet). نسمّي الحاويات elasticsearch ونختار صورة Docker من الرابط docker.elastic.co/elasticsearch/elasticsearch:7.2.0. في هذه المرحلة، يمكنك تعديل وسم الصورة هذا ليتوافق مع صورة Elasticsearch الداخلية الخاصة بك، أو مع إصدار مختلف. لاحظ أنه لأغراض هذا الدليل، اقتصر الااختبارعلى الإصدار 7.2.0 من Elasticsearch. ثم نستخدم الحقل resources لتحديد أن الحاوية تحتاج على الأقل لضمان 10% من وحدة المعالجة المركزية الافتراضية ( 0.1vCPU)، ويمكن أن يزيد الاستخدام ليصل إلى وحدة معالجة كاملة (1vCPU)، أي أننا نعيّن الحد الأقصى لاستهلاك المورد في حالات مثل استقبال كائن Pod لكمية أولية كبيرة من البيانات أو في أوقات الذروة). يجب تعديل هذه القيم اعتمادًا على الحمل المتوقع والموارد المتاحة. راجع توثيق Kubernetes للمزيد عن الطلبات على الموارد وحدوها. ثم نفتح المنفذين 9200 و 9300، مع تسميتهما، بغرض الاتصال بواجهة تطبيقات REST والاتصال الداخلي، على التوالي. نحدد نقطة لتركيب تجزئات التخزين (الحقل volumeMount) ونسمّيها data. وظيفة نقطة التركيب تلك هي تحميل التجزئة المستقرّة (كائن من النوع PersistentVolume) المُسماة data الموجودة ضمن الحاوية على المسار usr/share/elasticsearch/data/. سنحدد مطالب الحجم (VolumeClaims) لهذه المجموعة في جزء لاحق من التعريف. أخيرًا، نعيّن بعض متغيرات البيئة في الحاوية: cluster.name: اسم عنقود Elasticsearch، والذي في هذا الدليل هو k8s-logs. node.name: اسم العقدة، الذي عيّناه للحقل metadata.name. باستخدام valueFrom. ستُترجم هذه القيمة إلى [es-cluster-[0,1,2، اعتمادًا على العدد الترتيبي المعيّن للعقدة. discovery.seed_hosts: يعين هذا الحقل قائمة بالعقد المؤهلة لتؤدّي دور القبطان في العنقود الذي سيؤسس لعملية استكشاف العقد. في هذا الدليل، وبفضل الخدمة مجهولة العنوان التي أعددناها سابقًا، تأخذ كائنات Pod نطاقات بالصيغة es-cluster-[0,1,2].elasticsearch.kube-logging.svc.cluster.local، لذلك عيّنا هذا المتغير وفقًا لذلك. يمكننا تقصير النطاق إلى es-cluster-[0,1,2].elasticsearch باستخدام ترجمة أسماء النطاقات الداخلية في Kubernetes. راجع توثيق Elasticsearch للمزيد عن الاستكشاف في Elasticsearch. cluster.initial_master_nodes: يحدد هذا الحقل أيضًا قائمة عقد مؤهلة لتؤدّي دور القبطان في العنقود ستشارك في عملية انتخاب القبطان. لاحظ أنه في هذا الحقل، يجب تحديد العقد من خلال node.name وليس أسماء المضيفين. ES_JAVA_OPTS: ضبطنا المتغيّر على القيم Xms512m -Xmx512m- لإخبار آلة جافا الافتراضية (JVM) برغبتنا في استخدام 512 ميجابايت لتكون الحد الأدنى والحد الأقصى لحجم كومة الذاكرة المؤقتة. يجب ضبط هذه المعاملات بناءً على توفر الموارد للعنقود واحتياجاته. راجع المقال التالي للمزيد من التفاصيل. يظهر الجزء الموالي من التعريف على النحو التالي: . . . initContainers: - name: fix-permissions image: busybox command: ["sh", "-c", "chown -R 1000:1000 /usr/share/elasticsearch/data"] securityContext: privileged: true volumeMounts: - name: data mountPath: /usr/share/elasticsearch/data - name: increase-vm-max-map image: busybox command: ["sysctl", "-w", "vm.max_map_count=262144"] securityContext: privileged: true - name: increase-fd-ulimit image: busybox command: ["sh", "-c", "ulimit -n 65536"] securityContext: privileged: true في هذه الجزء، نحدد العديد من الحاويات الأولية التي تُشغَّب قبل حاوية تطبيق elasticearch الرئيسية. تُشغَّل هذه الحاويات الأولية (Init Containers) حتى إكمال عملها بالترتيب المحدد. راجع التوثيق الرسمي لمعرفة المزيد عن الحاويات الأولية. تنفّذ الحاوية الأولى، المُسمّاة fix-permissions، أمر chown لتغيير الحساب والمجموعة المالكيْن لمجلّد بيانات دليل Elasticsearch ليصبحا 1000: 1000، وهما معرّفا (UID) مستخدم ومجموعة Elasticsearch. يركّب Kubernetes مجلّد البيانات بالحساب الجذر (root)، مما يجعل وصول Elasticsearch إليه غير ممكن. راجع توثيق Elasticsearch لمزيد من المعلومات حول هذه الخطوة. تنفّذ الحاوية الثانية، المسمّاة increase-fd-ulimit، أمرًا لزيادة حدود استدعاءات mmap التي يمكن لنظام التشغيل إجراؤها، والتي قد يكون عددها افتراضيًا منخفضًا جدًا، مما ينتج عنه أخطاء في الذاكرة. راجع توثيق Elasticsearch لمزيد من المعلومات حول هذه الخطوة. الحاوية الأوليّة التالية هي increase-fd-ulimit والتي تنفّذ الأمر ulimit لزيادة الحد الأقصى لعدد واصفات الملفات المفتوحة (File descriptor). راجع توثيق Elasticsearch لمزيد من المعلومات حول هذه الخطوة. الآن بعد أن حددنا حاوية التطبيق الرئيسية والحاويات الأوليّة التي تُشغَّل قبلها لضبط نظام تشغيل الحاوية، يمكننا إضافة الجزء الأخير إلى ملف تعريف كائن StatefulSet، وهو الجزء المتعلّق بقوالب مطالب الحجم (volumeClaimTemplates). ألصق الجزء التالي المتعلّق بتعريف volumeClaimTemplate: . . . volumeClaimTemplates: - metadata: name: data labels: app: elasticsearch spec: accessModes: [ "ReadWriteOnce" ] storageClassName: do-block-storage resources: requests: storage: 100Gi في هذا الجزء، نحدد المجلد VolumeClaimTemplates الخاص بكائن StatefulSet. سيستخدم Kubernetes هذا المجلّد لإنشاء تجزئات دائمة (PersistentVolumes) لكائنات Pod. في التعريف أعلاه، نسميها data (وهو الاسم الذي نشير إليه في وحدة التخزين التي تم تعريفها سابقًا)، ونعطيها نفس اللصيقة (app: elasticsearch) اللتي أعطيناها لكائن StatefulSet سابقا. ثم نحدد وضع الوصول إلى التجزئات ليكون ReadWriteOnce، مما يعني أنه لا تمكن القراءة والكتابة منها إلّا بواسطة عُقدة واحدة. نحدد الصنف do-block-storage ليكون صنف التخزين إذ أننا نستخدم عنقود Kubernetes من DigitalOcean لأغراض الشرح. يجب تغيير هذه القيمة اعتمادًا على أين تشغّل عنقود Kubernetes الخاص بك. راجع توثيق Kubernetes للمزيد عن التخزين الدائم. أخيرًا، نحدد حجم كل مجلد دائم (PersistentVolume) ليكون 100 غيغابايت. يجب تعديل هذه القيمة حسب احتياجات بيئة الإنتاج الخاصة بك. تبدو المواصفات الكاملة لكائن StatefulSet كالتالي: apiVersion: apps/v1 kind: StatefulSet metadata: name: es-cluster namespace: kube-logging spec: serviceName: elasticsearch replicas: 3 selector: matchLabels: app: elasticsearch template: metadata: labels: app: elasticsearch spec: containers: - name: elasticsearch image: docker.elastic.co/elasticsearch/elasticsearch:7.2.0 resources: limits: cpu: 1000m requests: cpu: 100m ports: - containerPort: 9200 name: rest protocol: TCP - containerPort: 9300 name: inter-node protocol: TCP volumeMounts: - name: data mountPath: /usr/share/elasticsearch/data env: - name: cluster.name value: k8s-logs - name: node.name valueFrom: fieldRef: fieldPath: metadata.name - name: discovery.seed_hosts value: "es-cluster-0.elasticsearch,es-cluster-1.elasticsearch,es-cluster-2.elasticsearch" - name: cluster.initial_master_nodes value: "es-cluster-0,es-cluster-1,es-cluster-2" - name: ES_JAVA_OPTS value: "-Xms512m -Xmx512m" initContainers: - name: fix-permissions image: busybox command: ["sh", "-c", "chown -R 1000:1000 /usr/share/elasticsearch/data"] securityContext: privileged: true volumeMounts: - name: data mountPath: /usr/share/elasticsearch/data - name: increase-vm-max-map image: busybox command: ["sysctl", "-w", "vm.max_map_count=262144"] securityContext: privileged: true - name: increase-fd-ulimit image: busybox command: ["sh", "-c", "ulimit -n 65536"] securityContext: privileged: true volumeClaimTemplates: - metadata: name: data labels: app: elasticsearch spec: accessModes: [ "ReadWriteOnce" ] storageClassName: do-block-storage resources: requests: storage: 100Gi احفظ الملف ثم أغلقه بعد التأكد من محتواه. الآن، انشر ملف StatefulSet باستخدام kubectl: $ kubectl create -f elasticsearch_statefulset.yaml يجب أن تشاهد المُخرجات التالية: statefulset.apps/es-cluster created يمكنك مراقبة حالة StatefulSet أثناء إطلاقه باستخدام kubectl rollout status: $ kubectl rollout status sts/es-cluster --namespace=kube-logging يجب أن ترى المخرجات التالية أثناء إطلاق العنقود: Waiting for 3 pods to be ready... Waiting for 2 pods to be ready... Waiting for 1 pods to be ready... partitioned roll out complete: 3 new pods have been updated... بمجرد نشر كل كائنات Pod، يمكنك التحقق من أن عنقود Elasticsearch الخاص بك يعمل من خلال إرسال طلب إلى واجهة تطبيقات REST. لذا، أعد توجيه المنفذ المحلي 9200 إلى المنفذ 9200 على إحدى عُقد Elasticsearch وهي (es-cluster-0)، باستخدام kubectl port-forward: $ kubectl port-forward es-cluster-0 9200:9200 --namespace=kube-logging ثم، في نافذة طرفية منفصلة، نفذ طلب curl باتجاه واجهة REST: $ curl http://localhost:9200/_cluster/state?pretty يجب أن تظهر المخرجات التالية: { "cluster_name" : "k8s-logs", "compressed_size_in_bytes" : 348, "cluster_uuid" : "QD06dK7CQgids-GQZooNVw", "version" : 3, "state_uuid" : "mjNIWXAzQVuxNNOQ7xR-qg", "master_node" : "IdM5B7cUQWqFgIHXBp0JDg", "blocks" : { }, "nodes" : { "u7DoTpMmSCixOoictzHItA" : { "name" : "es-cluster-1", "ephemeral_id" : "ZlBflnXKRMC4RvEACHIVdg", "transport_address" : "10.244.8.2:9300", "attributes" : { } }, "IdM5B7cUQWqFgIHXBp0JDg" : { "name" : "es-cluster-0", "ephemeral_id" : "JTk1FDdFQuWbSFAtBxdxAQ", "transport_address" : "10.244.44.3:9300", "attributes" : { } }, "R8E7xcSUSbGbgrhAdyAKmQ" : { "name" : "es-cluster-2", "ephemeral_id" : "9wv6ke71Qqy9vk2LgJTqaA", "transport_address" : "10.244.40.4:9300", "attributes" : { } } }, ... تشير المخرجات إلى أنّ العنقود k8s-logs المكوَّن من ثلاث عقد ( es-cluster-1، es-cluster-0 وes-cluster-2.) قد أنشئ بنجاح. العقدة التي تؤدي دور القبطان هي حاليًّا es-cluster-0. الآن بعد أن أصبح عنقود Elasticsearch جاهزًا يمكنك الانتقال إلى إعداد واجهة Kibana الأمامية. الخطوة 3: إنشاء خدمة ونشر كيبانا لإطلاق Kibana على Kubernetes، سننشئ خدمة تسمى kibana، وننشئ أيضًا عملية نشر (Deployment) تتكوّن من كائن Pod واحد. يمكنك تحديد عدد النسخ التي تحتاجها بناءً على احتياجات بيئة الإنتاج الخاصة بك، وتحديد النوع LoadBalancer لتوزيع عبء بين كائنات Pod. هذه المرة ، سننشئ الخدمة والنشر في الملف نفسه. افتح ملفًا يسمى kibana.yaml في محررك المفضل: $ nano kibana.yaml ألصق المواصفات التالية للخدمة: apiVersion: v1 kind: Service metadata: name: kibana namespace: kube-logging labels: app: kibana spec: ports: - port: 5601 selector: app: kibana --- apiVersion: apps/v1 kind: Deployment metadata: name: kibana namespace: kube-logging labels: app: kibana spec: replicas: 1 selector: matchLabels: app: kibana template: metadata: labels: app: kibana spec: containers: - name: kibana image: docker.elastic.co/kibana/kibana:7.2.0 resources: limits: cpu: 1000m requests: cpu: 100m env: - name: ELASTICSEARCH_URL value: http://elasticsearch:9200 ports: - containerPort: 5601 ثم احفظ الملف وأغلقه. في هذه المواصفات، حددنا خدمة تسمى kibana في فضاء الأسماء kube-logging، وأعطيناها اللصيقة app: kibana. حددنا أيضًا أنه يجب الوصول إليها على المنفذ 5601 واستخدمنا اللصيقة app: kibana لتحديد كائنات Pod المُستهدَفة بالخدمة. في مواصفات النشر Deployment، نحدد عملية نشر تُسمى kibana ونحدد أننا نريد كائن Pod واحدا. نستخدم صورة Kibana من الرابط docker.elastic.co/kibana/kibana:7.2.0. عند هذه النقطة يمكنك وضع صورة كيبانا الخاصة أو العامة التي تودّ استخدامها. نحدد أن الحاوية تحتاج على الأقل لضمان 10% من وحدة المعالجة المركزية الافتراضية ( 0.1vCPU)، ويمكن أن يزيد الاستخدام ليصل إلى وحدة معالجة كاملة (1vCPU)، أي أننا نعيّن الحد الأقصى لاستهلاك المورد. يمكنك تغيير هذه المعاملات اعتمادًا على الحمل المتوقع والموارد المتاحة. بعد ذلك ، نستخدم متغير البيئة ELASTICSEARCH_URL لتعيين نقطة النهاية والمنفذ لعنقود Elasticsearch. باستخدام نطاقات Kubernetes نجد أن نقطة النهاية تتوافق مع اسم الخدمة الخاص بها elasticsearch. سيُترجم اسم النطاق إلى قائمة عناوين IP الخاصة بكائنات Pod الثلاث. راجع توثيق Kubernetes للمزيد عن إدارة أسماء النطاقات في Kubernetes. أخيرًا، عيّنا 5601 ليكون منفذ حاويات Kibana، حيث ستعيد خدمة Kibana توجيه الطلبات إليه. يمكنك - بعد التأكّد من إعدادات Kibana - إطلاق الخدمة وتشغيل عملية النشر باستخدام kubectl: $ kubectl create -f kibana.yaml يجب أن تشاهد المخرجات التالية: service/kibana created deployment.apps/kibana created يمكنك التحقق من نجاح إطلاق الخدمة عن طريق تشغيل الأمر التالي: $ kubectl rollout status deployment/kibana --namespace=kube-logging يجب أن تشاهد المخرجات التالية: deployment "kibana" successfully rolled out للوصول إلى واجهة Kibana، سنعيد توجيه منفذ محلي مرة أخرى إلى عُقدة Kubernetes التي تشغّل Kibana. احصل على تفاصيل كائن Pod الخاص بعقدة Kibana باستخدام kubectl get: $ kubectl get pods --namespace=kube-logging المخرجات: NAME READY STATUS RESTARTS AGE es-cluster-0 1/1 Running 0 55m es-cluster-1 1/1 Running 0 54m es-cluster-2 1/1 Running 0 54m kibana-6c9fb4b5b7-plbg2 1/1 Running 0 4m27s هنا نلاحظ أن كائن Pod الخاص بعقدة Kibana يُسمّى kibana-6c9fb4b5b7-plbg2. أعد توجيه المنفذ المحلي 5601 إلى المنفذ 5601 على ذلك الكائن: $ kubectl port-forward kibana-6c9fb4b5b7-plbg2 5601:5601 --namespace=kube-logging يجب أن تظهر المخرجات التالية: Forwarding from 127.0.0.1:5601 -> 5601 Forwarding from [::1]:5601 -> 5601 الآن، زر رابط URL التالي: http://localhost:5601 إذا رأيت صفحة ترحيب Kibana التالية، فقد نجحت في نشر Kibana في عنقود Kubernetes: يمكنك الآن الانتقال إلى إطلاق المكون النهائي لمكدس EFK وهو مُجمِّع السجلات Fluentd. الخطوة 4: إنشاء Fluentd DaemonSet في هذا الدليل، سنعدّ Fluentd بصيغة DaemonSet، وهو نوع من أعباء العمل في Kubernetes يشغّل نسخة من كائن Pod على كل عقدة في عنقود Kubernetes. باستخدام وحدة تحكم DaemonSet هذه، سنطلق وكيل تسجيل Fluentd عبارة عن كائن Pod على كل عقدة من العنقود. راجع هذا المقال من توثيق Kubernetes الرسمي لمعرفة المزيد حول بنية التسجيل هذه. تُلتَقط سجّلات المُخرجات والأخطاء المعيارية (stdout و stderr على التوالي) للتطبيقات العاملة ضمن حاويّات ويُعاد توجيهها إلى ملفات JSON على العقد. سيتتبّع وكيل Fluentd ملفّات السجلّات تلك، ويفرز الأحداث الموجودة فيها، ويحوّل بيانات السجلّات وفي الأخير يشحنها إلى السند الخلفي لحفظ السجلّات على Elasticsearch الذي نشرناه في الخطوة الثانية من هذا الدليل. بالإضافة إلى سجلات الحاوية، يتتبّع وكيل Fluentd سجلات مكونات نظام Kubernetes مثل سجلات kubelet وkube-proxy وDocker. راجع ملف kubernetes.conf المستخدم لإعداد وكيل التسجيل للاطلاع على قائمة كاملة بالمصادر التي يتتبعها وكيل تسجيل Fluentd. راجع توثيق Kubernetes لمعرفة المزيد حول تسجيل الأحداث على مستوى عقد Kubernetes. ابدأ بفتح الملف fluentd.yaml في محرر النصوص المفضل لديك: $ nano fluentd.yaml مرة أخرى ، سنلصق تعريفات الكائن جزءًا جزءًا، مع شرح سياق التعريفات في كل جزء. نستند في هذا الدليل على مواصفات متحكّم Fluentd DaemonSet التي يوفرها فريق صيانة Fluentd. مورد مفيد آخر يقدمه مشرفو Fluentd هو مقالات Flunetd ضمن توثيق Kuberentes. أولاً، الصق في تعريف ServiceAccount التالي: apiVersion: v1 kind: ServiceAccount metadata: name: fluentd namespace: kube-logging labels: app: fluentd هنا، قمنا بإنشاء حساب خدمة باسم flentd ستستخدمه كائنات Pod التابعة لخدمة Fluentd في الوصول إلى واجهة تطبيقات Kubernetes. ننشئ الحساب في فضاء الأسماء kube-logging ونعطيه مرة أخرى اللصيقة app: fluentd. راجع توثيق Kubernetes للمزيد عن حسابات الخدمة في Kubernetes. بعد ذلك، الصق الجزء التالي الذي يعرّف الكائن ClusterRole : . . . --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: fluentd labels: app: fluentd rules: - apiGroups: - "" resources: - pods - namespaces verbs: - get - list - watch هنا نحدد ClusterRole يسمى fluentd نمنحه صلاحيات get،وlist و watch على كائنات Pod وفضاءات الأسماء. تسمح الكائنات من النوع ClusterRoles بمنح الوصول إلى موارد Kubernetes في نطاق العنقود مثل العقَد. راجع [فصل استخدام تراخيص RBAC]() ضمن توثيق Kubernetes، للمزيد عن التحكم في الوصول المعتمد على الأدوار (RBAC). الآن، الصق الجزء التعريفي التالي المتعلق بكائن ClusterRoleBinding: . . . --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: fluentd roleRef: kind: ClusterRole name: fluentd apiGroup: rbac.authorization.k8s.io subjects: - kind: ServiceAccount name: fluentd namespace: kube-logging نعرّف كائنًا من النوع ClusterRoleBinding ونسمّيهfluentd. وظيفة هذا الكائن هي الربط بين الكائن من النوع ClusterRole وحساب خدمة fluentd، ممّا يمنح الخدمة الصلاحيّات المدرجة في الكائن من النوع ClusterRole الذي أسميناهfluentd . عند هذه النقطة يمكننا البدء بلصق التعريفات ضمن المواصفات الفعليّة لمتحكّم DaemonSet: . . . --- apiVersion: apps/v1 kind: DaemonSet metadata: name: fluentd namespace: kube-logging labels: app: fluentd هنا، نحدد متحكّم DaemonSet يُسمى fluentd في فضاء أسماء kube-logging ونعطيها اللصيقة app: fluentd. بعد ذلك، الصق الجزء التعريفي التالي: . . . spec: selector: matchLabels: app: fluentd template: metadata: labels: app: fluentd spec: serviceAccount: fluentd serviceAccountName: fluentd tolerations: - key: node-role.kubernetes.io/master effect: NoSchedule containers: - name: fluentd image: fluent/fluentd-kubernetes-daemonset:v1.4.2-debian-elasticsearch-1.1 env: - name: FLUENT_ELASTICSEARCH_HOST value: "elasticsearch.kube-logging.svc.cluster.local" - name: FLUENT_ELASTICSEARCH_PORT value: "9200" - name: FLUENT_ELASTICSEARCH_SCHEME value: "http" - name: FLUENTD_SYSTEMD_CONF value: disable هنا، نطابق اللصيقة app: fluentd المُعرَّفة في metadata.labels.، ثم نعيّن متحكّم DaemonSet لحساب خدمة fluentd. نختار أيضًا كائنات Pod التي تطابق المحدّد app: fluentd ليتولّى المتحكّم DaemonSet إدارتها. بعد ذلك، نحدد تسهيلاً بلا جدول زمني (NoSchedule toleration) لمطابقة الشائبة (Taint) المكافئة على عقد Kubernetes الرئيسية (القبطان). نضمن بذلك أنّ المتحكّم DaemonSet سيُطلَق أيضًا على العقد الرئيسيى في على سادة Kubernetes. أزل هذا التسهيل إذا كنت لا ترغب في تشغيل كائن Pod لتطبيق Fluentd على العقد الرئيسية الخاصة بك. راجع هذا الفصل في توثيق Kubernetes للمزيد عن التسهيلات والشوائب. بعد ذلك، نبدأ في تحديد حاوية كائن Pod، والتي نسميها fluentd. يستخدم هذا الدليل صورة رسمية من توزيعة دبيان يوفّرها فريق صيانة Fluentd. عدّل وسم image في مواصفات الحاوية إذا كنت ترغب في استخدام صورة Fluentd خاصة أو عامة، أو استخدام صورة بإصدار مختلف. يتوفر ملف Dockerfile ومحتويات هذه الصورة في مستودع fluentd-kubernetes-daemonset على Github. بعد ذلك، نضبط Fluentd باستخدام بعض متغيرات البيئة: FLUENT_ELASTICSEARCH_HOST: نعيّن قيمة هذا المتغيّر لتكون اسم نطاق خدمة Elasticsearch مجهولة العنوان المُحدَّد سابقًا elasticsearch.kube-logging.svc.cluster.local. يُترجم اسم النطاق هذا إلى قائمة عناوين IP لكائنات Pod الثلاث الخاصة بتطبيق Elasticsearch. من المُرجَّح أن يكون عنوان مضيف Elasticsearch الحالي هو عنوان IP الأول في القائمة المُرجَعة. لتوزيع السجلات على العنقود، ستحتاج إلى تعديل إعدادات مُلحَق Fluentd الخاص بمُخرجات Elasticsearch. راجع توثيق Fluentd للمزيد حول هذا الملحق. FLUENT_ELASTICSEARCH_PORT: نحدّد قيمة المتغيّر لتكون المنفذ الذي عيّناه سابقًا، 9200. FLUENT_ELASTICSEARCH_SCHEME: نعيّن القيمة http. FLUENTD_SYSTEMD_CONF: نعيّن القيمة disable لحذف مُخرجات systemd غير المضبوطة في الحاوية. أخيرًا، نلصق الجزء التالي من التعريف: . . . resources: limits: memory: 512Mi requests: cpu: 100m memory: 200Mi volumeMounts: - name: varlog mountPath: /var/log - name: varlibdockercontainers mountPath: /var/lib/docker/containers readOnly: true terminationGracePeriodSeconds: 30 volumes: - name: varlog hostPath: path: /var/log - name: varlibdockercontainers hostPath: path: /var/lib/docker/containers هنا نحدد القيمة 512 ميجابايت لتكون الحد الأقصى للذاكرة على كائن Pod الخاص بتطبيق Fluentd الذي نضمن له 0.1 من المعالج الافتراضي (0.1vCPU) و 200 ميجابايت من الذاكرة. يمكنك تدقيق حدود الموارد والطلبات بناءً على حجم السجلّات المتوقعة والموارد المتاحة. بعد ذلك، نقوم نركّب مسارات المضيف var/log/ و var/lib/docker/containers/ في الحاوية باستخدام نقطتيْ التركيب (volumeMounts) المذكورتيْن varlog و varlibdockercontainers . تُعرَّف التجزئات (volumes) في نهاية الجزء السابق. الوسيط الأخير الذي نعرّفه هو terminationGracePeriodSeconds، والذي يمنح 30 ثانية لإيقاف Fluentd بأمان عند استقبال إشارة SIGTERM. بعد 30 ثانية، تُرسَل إلى الحاويات إشارة SIGKILL. القيمة الافتراضية للوسيط terminationGracePeriodSeconds هي 30 ثانية، لذلك في معظم الحالات يمكن إغفال هذا الوسيط. راجع هذا المقال من غوغل عن أفضل الممارسات لإيقاف أعباء العمل على Kubernetes. يجب أن تبدو المواصفات الكاملة لتطبيق Fluentd كما يلي: apiVersion: v1 kind: ServiceAccount metadata: name: fluentd namespace: kube-logging labels: app: fluentd --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: fluentd labels: app: fluentd rules: - apiGroups: - "" resources: - pods - namespaces verbs: - get - list - watch --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: fluentd roleRef: kind: ClusterRole name: fluentd apiGroup: rbac.authorization.k8s.io subjects: - kind: ServiceAccount name: fluentd namespace: kube-logging --- apiVersion: apps/v1 kind: DaemonSet metadata: name: fluentd namespace: kube-logging labels: app: fluentd spec: selector: matchLabels: app: fluentd template: metadata: labels: app: fluentd spec: serviceAccount: fluentd serviceAccountName: fluentd tolerations: - key: node-role.kubernetes.io/master effect: NoSchedule containers: - name: fluentd image: fluent/fluentd-kubernetes-daemonset:v1.4.2-debian-elasticsearch-1.1 env: - name: FLUENT_ELASTICSEARCH_HOST value: "elasticsearch.kube-logging.svc.cluster.local" - name: FLUENT_ELASTICSEARCH_PORT value: "9200" - name: FLUENT_ELASTICSEARCH_SCHEME value: "http" - name: FLUENTD_SYSTEMD_CONF value: disable resources: limits: memory: 512Mi requests: cpu: 100m memory: 200Mi volumeMounts: - name: varlog mountPath: /var/log - name: varlibdockercontainers mountPath: /var/lib/docker/containers readOnly: true terminationGracePeriodSeconds: 30 volumes: - name: varlog hostPath: path: /var/log - name: varlibdockercontainers hostPath: path: /var/lib/docker/containers احفظ الملف وأغلقه بعد ضبط إعداد المتحكّم DaemonSet لتطبيق Fluentd. الآن، أطلق DaemonSet باستخدام kubectl: $ kubectl create -f fluentd.yaml يجب أن تشاهد الناتج التالي: serviceaccount/fluentd created clusterrole.rbac.authorization.k8s.io/fluentd created clusterrolebinding.rbac.authorization.k8s.io/fluentd created daemonset.extensions/fluentd created تحقق من نجاح إطلاق DaemonSet باستخدام kubectl: $ kubectl get ds --namespace=kube-logging يجب أن ترى الحالة الظاهرة في المُخرجات التالية: NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE fluentd 3 3 3 3 3 <none> 58s تشير النتيجة أعلاه إلى وجود ثلاث كائنات Pod قيد التشغيل ويعمل عليها المتحكّم fluentd. يتوافق هذا العدد مع عقد Kubernetes. يمكننا الآن النظر في Kibana للتحقق من أن بيانات السجلّات تُجمَع وتُشحَن كما نريد إلى Elasticsearch. استخدم المتصفّح لفتح العنوان التالي http://localhost:5601، مع استمرار تنفيذ الأمرkubectl port-forward. اضغط على زر Discover (اكتشف) في قائمة التنقل اليسرى: يجب أن تظهر نافذة الإعدادات التالية: تتيح لك هذه النافذة تحديد مؤشرات Elasticsearch التي ترغب في استكشافها في Kibana. لمعرفة المزيد، راجع المقال التالي في توثيق Kibana للمزيد عن أنماط الفهرسة في Kibana. في الوقت الحالي، سنستخدم نمط محارف البدل logstash-* لالتقاط جميع بيانات السجلّات في عنقود Elasticsearch الخاص بنا. اكتبlogstash-* في مربع النص ثم انقر على Next (التالي). ستنتقل بعد ذلك إلى الصفحة التالية. تسمح هذه النفاذة بإعداد الحقل الذي سيستخدمه Kibana لتصفية بيانات السجل حسب الوقت. في القائمة المنسدلة، حدد حقلtimestamp@، واضغط على Create index pattern (إنشاء نمط فهرس). الآن، اضغط على Discover (اكتشف) في قائمة التنقل اليسرى. يجب أن تشاهد مخطّطًا بيانيّا وبعض المُدخلات الأخيرة في السجلّات. بالوصول إلى هذه النقطة تكون قد نجحت في إعداد حزمة EFK وإطلاقها على عنقود Kubernetes. راجع دليل مستخدم Kibana لمعرفة كيفية استخدام Kibana لتحليل بيانات السجل. في القسم الاختياري التالي، سننشر كائن Pod لعدّاد بسيط يطبع أعدادًا على وحدة الإخراج المعيارية (stdout)، ونعثر على سجلاته في Kibana. الخطوة 5 (اختياري) - اختبار تسجيل الحاويات لتوضيح حالة بسيطة لاستخدام Kibana لاستكشاف أحدث السجلات على كائن Pod معيّن، سننشر كائن Pod محدود الإمكانيّات يطبع أعدادًا متسلسلة على وحدة stdout. لنبدأ بإنشاء كائن Pod. افتح ملفًا يسمى counter.yaml في محررك المفضل: $ nano counter.yaml ثم الصق مواصفات التالية لكائن Pod: apiVersion: v1 kind: Pod metadata: name: counter spec: containers: - name: count image: busybox args: [/bin/sh, -c, 'i=0; while true; do echo "$i: $(date)"; i=$((i+1)); sleep 1; done'] احفظ الملف ثم أغلقه. تعرّف المواصفات كائن Pod محدود يُسمى counter ينفّذ حلقة while تكرارية تطبع أعدادًا تسلسلية. ننشر counter باستخدامkubectl: $ kubectl create -f counter.yaml بمجرد إنشاء كائن Pod وتشغيله، انتقل مرة أخرى إلى لوحة معلومات Kibana. أدخل العبارة kubernetes.pod_name: counter في شريط البحث ضمن صفحة Discover (اكتشف). تصفّي العبارة السابقة بيانات السجلّات لعرض البيانات القادمة من كائن Pod المسمَّىcounter دون غيره. يمكنك النقر على أي من مُدخلات السجل لعرض بيانات وصفية إضافية مثل اسم الحاوية، وعقدة Kubernetes، وفضاء الأسماء، والمزيد. خاتمة أوضحنا في هذا الدليل كيفية إعداد وتهيئة Elasticsearch و Fluentd و Kibana على عنقود Kubernetes. استخدمنا الحد الأدنى لإنشاء بنية تسجيل تتكون من وكيل تسجيل واحد يعمل على كل عقدة Kubernetes عاملة. قبل نشر مكدس التسجيل هذا على عنقود Kubernetes ضمن بيئة إنتاج، من الأفضل ضبط متطلبات الموارد وحدودها كما هو موضح في هذا الدليل. قد تحتاج أيضًا إلى إعدادX-Pacl لتمكين ميزات المراقبة والأمان المضمنة. تتكون بنية التسجيل التي استخدمناها هنا من ثلاث كائنات Pod لتطبيق Elasticsearch، وكائن Pod واحد لتطبيق Kibana (بدون موازنة الحِمل)، ومجموعة من كائنات Pod لتطبيق Fluentd تُشغَّل على أنها متحكّمات DaemonSet. قد ترغب في تحجيم هذا الإعداد وفقًا لحالة استخدام بيئة الإنتاج الخاصة بك. راجع هذا المقال للمزيد عن حجيم Elasticsearch و Kibana. يسمح Kubernetes أيضًا ببُنى أكثر تغقيدًا لوكلاء التسجيل ممّا قد يتناسب أكثر مع استخداماتك. راجع هذا المقال على توثيق Kubernetes للمزيد عن بنية السجلّات في Kubernetes. ترجمة - وبتصرّف - للمقال How To Set Up an Elasticsearch, Fluentd and Kibana (EFK) Logging Stack on Kubernetes لصاحبه Hanif Jetha.
  2. يوفر هذا الدرس نظرة عامة على أساسيات نظام تنسيق العناقيد (Cluster orchestration) في Kubernetes. تحتوي كل وحدة على معلومات أساسية عن ميزات ومفاهيم Kubernetes الرئيسية، وتتضمن برنامجًا تعليميًا تفاعليًا عبر الإنترنت. تتيح لك هذه الدروس التفاعلية إدارة عنقود بسيط والتطبيقات العاملة على حاويّات فيه. باستخدام الدروس التفاعلية، يمكنك تعلم ما يلي: نشر تطبيق يعمل ضمن حاوية على عنقود. تحجيم النشر. تحديث التطبيق العامل ضمن حاوية بإصدار جديد من البرنامج. تنقيح التطبيقات العاملة ضمن حاويات. تستخدم البرامج التعليمية منصَّة Katacoda لتشغيل طرفية افتراضية في متصفح الويب يشغّل Minikube، وهو بيئة نشر Kubernetes محلية محدودة الحجم يمكن تشغيلها في أي مكان. لا داعي لتثبيت أي برنامج أو ضبط أي شيء؛ يعمل كل درس تفاعلي مباشرة من متصفح الويب. ما الذي يمكن أن يقدمه لك Kubernetes؟ مع خدمات الويب الحديثة، يتوقع المستخدمون أن تكون التطبيقات متاحة على مدار الساعة طوال أيام الأسبوع، ويتوقع المطورون نشر إصدارات جديدة من هذه التطبيقات عدة مرات في اليوم. يُساعد مفهوم "الحاويات" على تحزيم البرامج لخدمة هذه الأهداف، مما يتيح إصدار التطبيقات وتحديثها بطريقة سهلة وسريعة دون توقف. يساعدك Kubernetes على التأكد من تشغيل هذه التطبيقات الحاوية أينما ومتى تريد، ويساعد في العثور على الموارد والأدوات التي تحتاجها تلك الحاويّات للعمل. Kubernetes هي منصّة مفتوحة المصدر، جاهزة للإنتاج ومصممة بخبرة Google المتراكمة في تنسيق الحاويات، جنبًا إلى جنب مع أفضل الأفكار والممارسات التي يقترحها المجتمع. سننتقل الآن إلى التحدث عن وحدات Kubernetes الأساسية: إنشاء عنقود Kubernetes نشر التطبيق استكشاف التطبيق الإعلان عن التطبيق تحجيم التطبيق تحديث التطبيق 1. استخدام Minikube لإنشاء عنقود Kubernetes عناقيد Kubernetes تنسق Kubernetes عناقيد من الحواسيب عالية التوفّر المتصلة في ما بينها للعمل كوحدة منفردة. تسمح لك التجريدات (Abstractions) في Kubernetes بنشر تطبيقات تعمل ضمن حاويات على عنقود دون ربط الحاويّات بأجهزة مخصوصة. للاستفادة من هذا النموذج الجديد للنشر، يجب تحزيم التطبيقات بطريقة تفصلها عن المضيفات الفردية، أي أنه يجب وضعها في حاويات. التطبيقات العاملة ضمن حاويات أكثر مرونة وتوفّرًا مما كانت عليه في نماذج النشر السابقة، إذ كانت التطبيقات تثبّت مباشرة على أجهزة معينة بصيغة حزم مدمجة شديدة الارتباط بالمضيف. يؤتمت Kubernetes عمليات توزيع حاويّات التطبيقات وجدولتها على عنقود من المضيفات بطريقة أكثر كفاءة. Kubernetes هي منصة مفتوحة المصدر وجاهزة للإنتاج. يتكون عنقود Kubernetes من نوعين من الموارد: القبطان (The Master) الذي ينسق عمل العنقود. العُقَد (Nodes) وهي الموارد العاملة على تشغيل التطبيق. مخطط عنقود القبطان هو المسؤول عن إدارة الدفة. ينسّق القبطان جميع الأنشطة في العنقود، مثل جدولة التطبيقات، والحفاظ على الحالة المرغوبة، وتحجيم التطبيقات، وطرح تحديثات جديدة. العقدة هي آلة افتراضية (VM) أو حاسوب فيزيائي يُستخدم كآلة عاملة في عنقود Kubernetes. تحتوي كل عقدة على Kubelet، وهو وكيل لإدارة العقدة والتواصل مع القبطان. يجب أن تحتوي العقدة أيضًا على أدوات للتعامل مع عمليات الحاوية، مثل Docker أو rkt. يجب أن يحتوي عنقود Kubernetes الذي يتعامل مع حركة البيانات في بيئة إنتاج على ثلاث عقد على الأقل. عندما تنشر تطبيقات على Kubernetes، فأنت تطلب من القبطان تشغيل حاويات التطبيقات. يجدول القبطان الحاويات لتعمل على عقد العنقود. **تتواصل العُقَد مع القبطان باستخدام واجهة تطبيقات Kubernetes التي يبرزها القبطان. يمكن للمستخدمين النهائيين أيضًا استخدام واجهة تطبيقات Kubernetes مباشرةً للتفاعل مع العنقود. يمكن نشر عنقود Kubernetes على الأجهزة الفيزيائية أو الافتراضية على حد السواء. يمكنك بدء التطوير على Kubernetes باستخدام Minikube، وهو إصدار مخفّف من Kubernetes ينشئ آلة افتراضية على جهازك المحلي وينشر عنقودًا بسيطًا يحتوي على عقدة واحدة فقط. يتوفر Minikube لأنظمة لينكس و ماك وويندوز. توفّر طرفية Minikube عمليات التمهيد الأساسية للعمل مع العناقيد، بما في ذلك البدء (Start) والإيقاف (Stop) والحالة (Status) والحذف (Delete). توجد على هذه الصفحة طرفية جاهزة للاستخدام يُثبّت عليها Minikube مسبقا. 2. نشر تطبيق باستخدام kubectl عمليات النشر في Kubernetes يمكن نشر تطبيقات تعمل على حاويّات ضمن منصة Kubernetes بمجرّد توفر عنقود قيد التشغيل. لذا أنشئ إعدادات نشر (Deployment). يوجِّه كائن النشر Kubernetes إلى كيفية إنشاء نظائر (Instances) للتطبيق وتحديثها. يجدول قبطان Kubernetes، بعد إعداد كائن النشر، نظائر التطبيق للعمل على عقد العنقود. تراقب وحدة تحكم (Controller) باستمرار عمل النظائر بعد إنشائها. إنْ تعطلت عقدة مضيفة أو حذفت، فإن وحدة التحكم تستبدلها بعقدة أخرى من العنقود ليعمل عليها التطبيق، ممّا يوفّر آلية للإصلاح الذاتي لمعالجة إخفاق الآلة أو لصيانتها. في عالم ما قبل التنسيق، غالبًا ما كان تُشتخدَم سكربتات تثبيت لبدء التطبيقات، لكن لم توفر الحلول حينئذٍ لاستعادة عمل التطبيق عند إخفاق الآلة. من خلال إنشاء نظائر لتطبيقك والحفاظ على تشغيلها عبر العُقَد، توفر عمليات النشر في Kubernetes نهجًا مختلفًا جذريًا لإدارة التطبيقات. نشر تطبيقك الأول على Kubernetes يمكنك إنشاء عملية نشر وإدارتها باستخدام واجهة سطر أوامر Kubernetes ‏(Kubectl). يستخدم Kubectl واجهة برمجة تطبيقات Kubernetes للتفاعل مع العنقود. في هذا الجزء، ستتعلم أوامر Kubectl الأكثر شيوعًا اللازمة لإنشاء عمليات النشر التي تشغّل تطبيقاتك على عنقود Kubernetes. عندما تنشئ عملية نشر، ستحتاج إلى تحديد صورة حاوية التطبيق وعدد النظائر التي تريد تشغيلها. يمكنك تغيير هذه المعلومات لاحقًا عن طريق تحديث النشر. تناقش النقطتان 5 و 6 من هذا الدرس كيفية تحجيم عمليات النشر وتحديثها. بالنسبة إلى عملية النشر الأولى، ستستخدم تطبيق Node.js معبَّأ في حاوية Docker. (إذا لم تكن قد حاولت بالفعل إنشاء تطبيق Node.js ونشره باستخدام حاوية، فيمكنك القيام بذلك أولاً باتباع الإرشادات من مقال مدخل إلى Kubernetes. 3. استكشاف التطبيق: عرض العناقيد والعُقد الكائنات من نوع Pod عندما أنشأت عملية نشر في الجزء 2 أعلاه، أنشأ Kubernetes كائنًا من نوع Pod لاستضافة نظير من التطبيق. كائنات Pod هي تجريد Kubernetes لتمثيل مجموعة واحدة أو أكثر من حاويات التطبيقات (مثل Docker أو rkt)، إضافة إلى موارد مشتركة بين تلك الحاويات. تشمل تلك الموارد: التخزين المشترك، بصيغة تجزئات (Partitions). الشبكات، مثل عنوان IP فريد لكل عنقود. معلومات حول كيفية تشغيل كل حاوية، مثل إصدار صورة الحاوية أو منافذ معينة لاستخدامها. يصمّم كائن Pod "مضيفًا منطقيًّا" خاصًّا بالتطبيق، ويمكن أن يحتوي على حاويات تطبيق مختلفة مقترنة في ما بينها بإحكام نسبيًا. على سبيل المثال، قد يحتوي الكائن على حاوية تطبيق Node.js بالإضافة إلى حاوية أخرى تغذي البيانات التي سينشرها خادم الويب Node.js الذي يعمل في الحاوية الأولى. تشترك الحاويات الموجودة في كائن واحد عنوانَ IP وفضاء منافذ (Port Space)، كما أنها تشترك دائمًا العقدة والجدولة، وتعمل في سياق مشترك على العقدة نفسها. كائنات Pod هي أصغر وحدة على منصة Kubernetes. عندما تنشئ عملية نشر فإن هذا النشر ينشئ كائنات Pod مع حاويات بداخل الكائن (بدلًا من إنشاء حاويات مباشرة). يرتبط كل كائن Pod بالعقدة التي جُدولت عليها، وتظل هناك حتى الإنهاء (وفقًا لسياسة إعادة التشغيل) أو الحذف. في حالة إخفاق العقدة، تُجدول كائنات Pod متطابقة على العقد الأخرى المتاحة في العنقود. نظرة عامة على كائنات Pod عقد Kubernetes تُشَغَّل كائنات Pod دائمًا على عقدة. العقدة هي آلة عاملة في Kubernetes وقد تكون إما آلة افتراضية أو فيزيائية، حسب العنقود. يدير القبطان كل العُقد. يمكن أن تحتوي العُقدة على عدة كائنات Pod. يتولّى القبطان في Kubernetes جدولة كائنات Pod تلقائيًا على عقد العنقود. تأخذ الجدولة التلقائية من طرف القبطان في الاعتبار الموارد المتاحة لكل عقدة. تُشغِّل كل عقدة Kubernetes على الأقل: Kubelet، عملية مسؤولة عن التواصل بين القبطان و العُقدة؛ تُدير كائنات Pod والحاويات التي تعمل على الجهاز. بيئة تشغيل حاويات (مثل Docker وrkt) مسؤولة عن سحب صورة الحاوية من تقييد (Registry)، فك ضغط الحاوية، وتشغيل التطبيق. نظرة عامة على العقد استكشاف الأخطاء وإصلاحها باستخدام kubectl تحدّثنا في الجزء 2 أعلاه عن واجهة سطر الأوامر kubectl. سنستمر في الحديث عنه في هذا الجزء للحصول على معلومات حول التطبيقات المنشورة وبيئاتها. يمكن تنفيذ العمليات الأكثر شيوعًا باستخدام أوامر kubectl التالية: kubectl get - سرد الموارد. kubectl describe - عرض معلومات تفصيلية حول مورد. kubectl logs - طباعة السجلات من حاوية في كائن Pod. kubectl exec - تنفيذ أمر على حاوية في كائن Pod. يمكنك استخدام هذه الأوامر لمعرفة متى نُشرت التطبيقات، وما حالاتها الراهنة، وأين تعمل وما إعداداتها. الآن بعد أن عرفنا المزيد عن مكونات المجموعة لدينا وسطر الأوامر، دعنا نستكشف تطبيقنا. توجد على هذا الرابط بيئة تفاعلية لعرض العناقيد والعقد واستكشاف أوامر kubectl. 4. الإعلان عن التطبيق للعموم استخدام خدمة للإعلان عن التطبيق الخاص بك نظرة عامة على خدمات Kubernetes كائنات Pod في Kubernetes فانية. وهي في الواقع لها دورة حياة. عند توقّف عقدة عاملة تفقد كل كائنات Pod التي تعمل كانت تعمل على العقدة. قد تعيد وحدة التحكم ReplicaSet بعد ذلك العنقود ديناميكيًّا إلى الحالة المرغوبة من خلال إنشاء كائنات Pod جديدة للحفاظ على تشغيل التطبيق الخاص بك. مثال آخر، فلنفترض سندًا (Backend) لمعالجة الصور مع ثلاث حاويّات متماثلة. هذه النسخ المتماثلة قابلة للاستبدال؛ يجب ألا يهتم نظام الواجهة الأمامية بالنسخ المتماثلة للسند أو حتى في حالة فقد كائن Pod وإعادة إنشائه. ومع ذلك، فإن كل كائن Pod في عنقود Kubernetes له عنوان IP فريد، حتى الكائنات على العقدة نفسها. لذا يجب أن تكون هناك طريقة للتوفيق بين التغييرات تلقائيًا بين كائنات Pod حتى تستمر تطبيقاتك في العمل. الخدمة في Kubernetes عبارة عن تجريد يعرّف مجموعة منطقية من كائنات Pod وسياسة للوصول إليها. تتيح الخدمات اقترانًا فضفاضًا بين كائنات Pod المترابطة في ما بينها. تُعرّف الخدمة باستخدام YAML (وهي الوسيلة المفضّلة) أو JSON، مثل جميع كائنات Kubernetes. عادةً ما تُحدّذ مجموعة كائنات Pod التي تستهدفها الخدمة بواسطة كائن من النوع LabelSelector (انظر أدناه لمعرفة الحالات التي قد تدعوك لإنشاء خدمة بطريقة مغايرة). على الرغم من أن كل كائن Pod لديه عنوان IP فريد، إلّا أنّ تلك العناوين لا تُعرَض خارج العنقود بدون خدمة. تسمح الخدمات لتطبيقاتك بتلقي حركة المرور. يمكن الإعلان عن الخدمات بطرق مختلفة عن طريق تحديد النوع type في ServiceSpec: ClusterIP (قيمة افتراضية): يعرض الخدمة على عنوان IP داخلي في العنقود. يجعل هذا النوع الوصول للخدمة متاحًا فقط من داخل العنقود. NodePort: يعرض الخدمة على نفس المنفذ لكل عقدة محددة في العنقود باستخدام ترجمة عناوين الشبكة (NAT). يتيح الوصول إلى خدمة من خارج العنقود باستخدام عنوان IP العنقود ورقم المنفذ (<NodeIP>:<NodePort>). امتداد للطريقة السابقة (ClusterIP). LoadBalancer : ينشئ موازن حِمْل خارجي في السحابة الحالية (إذا كانت تدعم ذلك) ويعين عنوان IP ثابتًا خارجيًا للخدمة. امتداد للطريقة السابقة (NodePort). ExternalName: يُعلن عن الخدمة باستخدام اسم عشوائي (محدد بواسطة القيمة externalName في المواصفات spec) عن طريق إرجاع سجل CNAME يتضمّن الاسم. لا يُستخدَم أي وكيل (Proxy). يتطلب هذا النوع الإصدار v1.7 أو أعلى من حزمة kube-dns. يمكن العثور على مزيد من المعلومات حول الأنواع المختلفة من الخدمات في الدرس التالي، وأيضًا من خلال هذا المقال. بالإضافة إلى ذلك، يُرجى ملاحظة أن هناك حالات استخدام لا تتضمن فيها الخدمات تحديد حقل selector في المواصفات (spec). لن تنشئ الخدمة في تلك الحالة الكائن الطرفي (Endpoint object) المقابل، وهو ما يسمح للمستخدمين بالتعيين اليدوي للنقاط الطرفية للخدمة. توجد إمكانية أخرى لعدم وجود حقل selector وهي أنك تستخدم النوع ExternalName. الخدمات واللصائق (Labels) توجّه الخدمة البيانات عبر مجموعة من كائنات Pod. الخدمات هي طبقة تجريد تسمح بزوال كائنات Pod وتكرارها دون التأثير على عمل التطبيق في بيئة Kubernetes. تتولّى خدمات Kubernetes اكتشاف كائنات Pod المترابطة (مثل تطبيق يتكوّن من سند وواجهة أمامية) والتوجيه بينها. تتعرّف الخدمات على كائنات Pod المترابطة من خلال المحدّدات واللصائق (Selectors and Labels). المحدّدات هي دوال للتجميع تسمح بإجراء عمليات منطقية على كائنات Kubernetes، أمّا اللصائق فهي أزواج مفاتيح وقيم (Key/Value) مرفقة بالكائنات، ويمكن استخدامها بأي واحدة من الطرق التالية: تعيين كائنات للتطوير والاختبار والإنتاج، تضمين وسوم الإصدار، تصنيف كائن حسب الوسوم. يمكن إرفاق التسميات أو اللصائق (label) بالكائنات في وقت الإنشاء أو لاحقا. يمكن تعديلها في أي وقت. تجربة تفاعلية لعرض التطبيق للعموم باستخدام خدمات Kubernetes. 5. تحجيم التطبيق تشغيل نُسَخ متعددة للتطبيق رأينا أعلاه كيفية إنشاء عملية نشر (Deplyment)، ثم كيفية الإعلان عنها للعموم عبر خدمة. أنشأت عملية النشر كائن Pod واحدًا لتشغيل التطبيق. عندما تزداد حركة البيانات، سنحتاج إلى تحجيم (Scaling) التطبيق لمواكبة طلب المستخدم. يتحقّق التحجيم عن طريق تغيير عدد النظائر المنشورة. نظرة عامة على التحجيم سيضمن تحجيم النشر إنشاء كائنات Pod جديدة وجدولتها على العقد ذات الموارد المتاحة. سيؤدي التحجيم إلى زيادة عدد كائنات Pod إلى الحالة المرغوبة الجديدة. يدعم Kubernetes أيضًا التحجيم التلقائي Autoscaling لكائنات Pod، ولكنّ ذلك خارج نطاق هذا الدرس. التحجيم باتجاه الصفر ممكن أيضًا، وسيؤدي إلى إنهاء جميع كائنات Pod في عملية النشر المحددة. يتطلب تشغيل نسخ متعددة من تطبيق ما طريقة لتوزيع حركة البيانات عليها جميعا. تتضمّن الخدمات موازِن حِمل متكامل من شأنه أن يوزِّع البيانات المارة في الشبكة على جميع كائنات Pod الموجود ضمن نشر متاح للعموم. تراقب الخدماتُ كائنات Pod العاملة باستمرار باستخدام النقاط الطرفية لضمان إرسال البيانات إلى كائنات Pod المتاحة فقط. بمجرد أن يكون لديك نُسَخ متعددة للتطبيق قيد التشغيل، ستتمكن من دحرجة التحديثات دون توقف. سنغطي ذلك في الأجزاء التالية، وهو ما سنراه في الجزء اللاحق. يمكنك تجربة تحجيم التطبيق (بتوسيعه أو تقليصه) عبر هذه الطرفية التفاعلية. 6. تحديث التطبيق التحديث المتدحرج (Rolling update) يتوقع المستخدمون أن تكون التطبيقات متاحة طوال الوقت، ويُنتظر من المطورين أن ينشروا إصدارات جديدة منها عدة مرات في اليوم. في Kubernetes يتم ذلك عن طريق التحديثات المتدحرجة. تسمح التحديثات المتدحرجة بتحديث عمليات النشر دون توقف عن طريق التحديث التدريجي بإحلال كائنات Pod جديدة تدريجيًّا مكان الكائنات الحالية. تُجدول كائنات Pod الجديدة على العُقد التي لديها موارد متاحة. تحدّثنا في الجزء السابق عن تحجيم التطبيق لتشغيل نُسَخ متعددة. هذا الأمر مطلوب لإجراء التحديثات دون التأثير على توفر التطبيق. افتراضيًّا، الحد الأقصى لعدد كائنات Pod التي يمكن أن تكون غير متاحة ولعدد كائنات Pod الجديدة التي يمكن إنشاؤها أثناء التحديث، هو واحد. يمكن ضبط كل واحد من الخيارين إما بالأرقام أو بالنسب المئوية (من كائنات Pod). تؤصدر (Versioned) التحديثات في Kubernetes، ويمكن التراجع عن أي تحديث نشر إلى إصدار سابق (مستقر). نظرة عامة على التحديثات المتدحرجة على غرار تحجيم التطبيق، إذا كان النشر متاحًا للعموم، فإن الخدمة ستوازن حركة البيانات فقط بين كائنات Pod المتاحة أثناء التحديث. كائن Pod متاح هو نظير متوفّر لمستخدمي التطبيق. تسمح التحديثات المتدحرجة بالإجراءات التالية: نقل تطبيق من بيئة إلى أخرى (عبر تحديثات صورة الحاوية). التراجع إلى إصدارات سابقة. التكامل المستمر والتوصيل المستمر للتطبيقات بدون توقف. يمكن استخدام هذه النافذة التفاعلية لاختبار تحديث تطبيق إلى إصدار جديد والتراجع عن ذلك. ترجمة - وبتصرّف - لأجزاء kubernetes basics من توثيق Kubernetes.
  3. يعرّف هذا المقال منصَّة Kubernetes، نتناول فيه ثلاث نقاط مهمة، وهي: ما Kubernetes؟ كائنات Kubernetes Objects مرحبا Miniku ما Kubernetes؟ هذا الجزء عبارة عن نظرة عامة على Kubernetes، نتناول فيه ما يلي: نظرة على نشر التطبيقات قبل وجود Kubernetes. لماذا نحتاج Kubernetes وما الذي يمكنه فعله؟ الحالات التي لا ينفع فيها Kubernetes. Kubernetes هو منصة مفتوحة المصدر قابلة للنقل والتوسيع لإدارة أعباء العمل والخدمات الموجودة في حاويات، والتي تُسهِّل كلًا من الضبط التصريحي (Declarative) والأتمتة (Automation). تتوفّر منصة Kubernates على نظام بيئي غني وسريع النمو، كما أن دعم المنصة، وخدماتها، وأدواتها مُتاحة على نطاقٍ واسع. تنحدر كلمة Kubernetes من اليونانية، وتعني قائد الدّفة أو الطيار. جعلت غوغل مشروع Kubernetes مفتوح المصدر عام 2014. تستند Kubernetes على عقد ونصف من الخبرة التي تتمتع بها Google في تشغيل أعباء الإنتاج على نطاق واسع، جنبًا إلى جنب مع أفضل الأفكار والممارسات التي يقترحها المجتمع. نظرة على نشر التطبيقات قبل وجود Kubernetes دعنا نلق نظرة على الماضي لنفهم السبب الذي يجعل Kubernetes مفيدًا جدا. عصر النشر التقليدي في البداية، كانت المؤسسات تشغّل التطبيقات على خوادم فعلية (Physical Servers). لم تكن هناك طريقة لتعريف حدود على موارد التطبيقات في الخادم الفعلي، وقد تسبب ذلك في مشكلات تخصيص الموارد. على سبيل المثال، إذا شُغّلت تطبيقات متعددة على خادم فعلي، فقد تكون هناك حالات يستهلك فيها تطبيق واحد معظم الموارد، ونتيجة لذلك، يتراجع أداء التطبيقات الأخرى. قد يكون الحل لتلك المشكلة هو تشغيل كل تطبيق على خادم فعلي مختلف، إلّا ذلك لم يُحدِث فارقًا، إذ كانت الموارد غير مستغلة، وكان مكلفًا للمؤسسات استخدام الكثير من الخوادم الفعلية. عصر النشر الافتراضي قُدّمت الحوسبة الافتراضية (Virtualization) كحل يتيح لك تشغيل العديد من الأجهزة الافتراضية (Virtual machines، أو VM اختصارا) على وحدة المعالجة المركزية (CPU) لخادم فعلي واحد. تسمح المحاكاة الافتراضية بتقسيم التطبيقات بين الأجهزة الافتراضية وتوفِّر مستوى من الأمان إذ لا يمكن الوصول إلى معلومات أحد التطبيقات من خلال تطبيق آخر. تتيح المحاكاة الافتراضية استغلالًا أفضل للموارد في الخادم الفعلي وتتيح قابلية تطوير أفضل لأنه يمكن إضافة تطبيق أو تحديثه بسهولة، ويقلل من تكاليف العتاد (Hardware)، وأكثر من ذلك بكثير. يمكنك من خلال الحوسبة الافتراضية تقديم مجموعة من الموارد المادية على شكل مجموعة من الأجهزة الافتراضية القابلة للتدوير. كل آلة افتراضية عبارة عن آلة كاملة تقوم بتشغيل جميع المكونات، بما في ذلك نظام التشغيل الخاص بها، على الآلات الافتراضية. عصر النشر على الحاويات (Containers) تتشابه الحاويات مع الآلات الافتراضية، لكن لها خصائص عزل مريحة لمشاركة نظام التشغيل (OS) بين التطبيقات. لذلك، تعدّ الحاويات خفيفة. تحتوي الحاوية، على غرار الآلة الافتراضية ، على نظام ملفات (File System) خاص بها، ووحدة معالجة مركزية (CPU)، وذاكرة حية (Memory)، وفضاء معالجة (Process Space)، والمزيد. يمكن نقل الحاويات بين سحابات (Clouds) وتوزيعات نظم تشغيل مختلفة، نظرًا لكونها غير مقترنة بالبنية التحتية التي تعمل عليها. أصبحت "الحاويات" شائعة لأنها توفر فوائد إضافية، مثل: إنشاء ونشر تطبيقات مرنة (Agile Applications): سهولة وكفاءة إنشاء صور الحاويات مقارنة باستخدام صور الآلات الافتراضية. التطوير المستمر والتكامل والنشر (CD/CI): يُوفَّر بنية تحتية لبناء صور موثوقة ومتكررة للحاويات ونشرها مع إمكانية التراجع السريع والسهل (بسبب ثبات الصورة). فصل الاهتمامات بين التطوير وإدارة العمليات: إنشاء صور الحاويات عند إنشاء التطبيق أو أثناء إصداربدلاً من إنشائها عند نشر التطبيق، وبالتالي فصل التطبيقات عن البنية التحتية. سهولة الملاحظة: لا تقتصر الملاحظات على المعلومات والمقاييس على مستوى نظام التشغيل، بل تتعذّاه إلى سلامة التطبيق وإشارات أخرى. الاتساق البيئي عبر التطوير والاختبار والإنتاج: يعمل بنفس الطريقة على الحاسوب المحمول كما هو الحال في السحابة. قابلية التوزيع بغض النظر عن السحابة ونظام التشغيل: تعمل على أوبونتو، ردهات (RHEL)، CoreOS، لدى العميل أو على السحابات العامة الرئيسية، وفي أي مكان آخر. إدارة تتمحور حول التطبيقات: ترفع مستوى التجريد من تشغيل نظام تشغيل على آلات افتراضية إلى تشغيل تطبيق على نظام تشغيل باستخدام الموارد المنطقية. خدمات صغيرة (Micro services) موزعة، ومرنة، ومتحررة وذات اقتران محدود: تُقسَّم التطبيقات إلى قطع أصغرومستقلة يمكن نشرها وإدارتها ديناميكيًا، وليس مكدسًا (Stack) متجانسًا يعمل على آللة واحدة كبيرة أحادية الغرض. عزل الموارد: إمكانية التنبؤ بأداء التطبيقات. استغلال الموارد: كفاءة وكثافة عالية. لماذا تحتاج Kubernetes ومالذي يمكن أن يفعله تُعَد الحاويات طريقة جيدة لتجميع التطبيقات وتشغيلها. في بيئة الإنتاج، تحتاج إلى إدارة الحاويات التي تشغّل التطبيقات والتأكد من عدم وجود وقت تعطل. على سبيل المثال، في حالة تعطل الحاوية، يجب أن تبدأ حاوية أخرى. ألن يكون أسهل إذا كان النظام هو ما يتعامل مع هذا السلوك؟ هنا يأتي دور منصة Kubernates. يوفر لك Kubernetes إطار عمل لتشغيل أنظمة موزعة متكيّفة، ويعتني بتحجيم (Scaling) التطبيقات، وتجاوز إخفاقها (Failover)، ويوفر أنماطًا لنشرها، وأمور أخرى. على سبيل المثال، يمكن لمنصة Kubernetes إدارة نشر الكناري (ِCanary deployment)، وهو طريقة لنشر الإصدارات إلى مجموعة فرعية من المستخدمين أو الخوادم واختبارها أولًا ثم طرحها على بقية الخوادم، لنظامك بسهولة. يوفر لك Kubernetes ما يلي: اكتشاف الخدمات وموازنة الحِمل (Load balancing): يمكن لـ Kubernetes كشف حاوية باستخدام اسم نطاق أو باستخدام عنوان IP الخاص بها، كما يمكنه موازنة الحِمل إذا كانت حركة البيانات إلى الحاوية عالية، وتوزيع حركة البيانات عبرالشبكة لكي يكون النشر مستقرا. تنسيق التخزين (Storage orchestration): يسمح لك Kubernetes بتركيب نظام تخزين من اختيارك تلقائيًا، مثل المخازن المحلية، وموفري السحابة العامة والمزيد. أتمتة طرح الحاويات (Rollout) واستردادها (Rollback) : يمكنك وصف الحالة المرغوبة للحاويات التي تُنشَر باستخدام Kubernetes، ويمكنك تغيير الحالة الراهنة إلى الحالة المرغوبة بمعدل يُتحكّم فيه. على سبيل المثال، يمكنك إعداد Kubernetes لإنشاء حاويات جديدة للنشر آليًا، وإزالة الحاويات الموجودة وإسناد جميع مواردها في الحاوية الجديدة. التعبئة التلقائية للحاويات: تزوّد Kubernetes بمجموعة من العقد (الأجهزة) التي يمكن استخدامها لتشغيل المهام في حاويات، وتخبر المنصة بما تحتاجه كل حاوية من قدرة معالجة وذاكرة حية. يستطيع Kubernetes وضع الحاويات على العقد الخاصة بك لتحقيق أقصى استفادة من مواردك. التعالج الذاتي: يعيد Kubernetes تشغيل الحاويات التي أخفقت، ويستبدل الحاويات، ويوقف الحاويات التي لا تستجيب لمعايير التحقق التي يحددها المستخدم، ولا يعلن عن الحاويات للعملاء إلا إذا كانت جاهزة للخدمة. الإدارة السرية والتكوين: يتيح لك Kubernetes تخزين المعلومات الحساسة وإدارتها، مثل كلمات المرور ورموز OAuth ومفاتيح SSH. يمكنك نشر وتحديث هذه المعلومات الحساسة، وبناء التطبيق دون إعادة إنشاء صور الحاوية، وبدون الكشف عن الأسرار في تكوين المكدس (Stack) الخاص بك. الحالات التي لا ينفع فيها Kubernetes Kubernetes ليس نظامًا تقليديًّا وشاملًا لتقديم المنصات بصيغة خدمة (PaaS - Platform as a Service). نظرًا لأن Kubernetes يعمل على مستوى الحاوية بدلاً من مستوى الأجهزة، فإنه يوفر بعض الميزات القابلة للتطبيق عمومًا والشائع وجودها في المنصات المُقدّمة بصيغة خدمة، مثل النشر، والتحجيم، وموازنة الحِمل، والتسجيل، والمراقبة. ومع ذلك، فإن Kubernetes غير متجانس، وهذه الحلول الافتراضية اختيارية وقابلة للتوصيل بالمنصة. يوفر Kubernetes اللبنات الأساسية لبناء منصات للمطورين، ولكنه يحافظ على اختيار المستخدم والمرونة حيث يكون ذلك مهما. إنَّ Kubernetes: لا يحد من أنواع التطبيقات المدعومة. يهدف Kubernetes إلى دعم مجموعة متنوعة للغاية من أعباء العمل، بما في ذلك أعباء العمل عديمة الحالة (Stateless)، وذات الحالة (Stetful)، والتي تعالج البيانات. إذا كان يمكن تشغيل تطبيق في حاوية، فبالتأكيد سيعمل على نحو رائع على Kubernetes. لا ينشر الشفرة المصدرية ولا يبني تطبيقك. يُحدَّد سير عمل آليّات التكامل والتسليم والنشر المستمر (CI/CD) من خلال ثقافات المؤسسة وتفضيلاتها، بالإضافة إلى المتطلبات التقنية. لا يوفر خدمات على مستوى التطبيق، مثل البرامج الوسيطة (على سبيل المثال، قنوات الرسائل)، وأطر معالجة البيانات (Spark مثلًَا)، وقواعد البيانات (MySQL مثلًا)، وذاكرة التخزين المؤقت، وأنظمة التخزين العقدية (Ceph مثلًا) لا يقدّمها كخدمات مدمجة. يمكن تشغيل هذه المكونات على Kubernetes، مع الوصول إليها - أو عدمه - عن طريق التطبيقات التي تعمل على Kubernetes من خلال آليات محمولة، مثل Open Service Broker. لا يفرض حلول التسجيل أو المراقبة أو التنبيه. يوفر إرشادات إلى عمليات التكامل، وآليات جمع المقاييس وتصديرها. لا يوفر ولا يفرض لغة أو نظامًا للضبط (Jsonnet مثلا). يوفر واجهة تطبيقات برمجية تصريحية يمكن استهدافها من خلال أشكال عشوائية من المواصفات التصريحية. لا يوفر ولا يعتمد أي أنظمة ضبط أو صيانة أو إدارة أو معالجة ذاتية شاملة للأنظمة. بالإضافة إلى ذلك، Kubernetes ليس مجرد نظام تنسيق. في الواقع، يلغي Kubernetes الحاجة إلى التنسيق. التعريف الفني للتنسيق هو تنفيذ سير عمل محدد: أولاً قم بـ أ، ثم ب، ثم ج. على النقيض من ذلك، يشتمل Kubernetes على مجموعة من عمليات تحكم مستقلة قابلة للتوليف تدفع باستمرار الحالة الحالية نحو الحالة المطلوبة المقدمة. لا يهم كيف تنتقل من أ إلى ج. التحكم المركزي ليس مطلوبًا أيضًا. ينتج عن ذلك نظام أسهل استخدامًا، وأكثر قوة وصلابة وقابلية للتكيّف والتوسع. فهم كائنات Kubernetes يشرح هذا الجزء كيفية تمثيل الكائنات في واجهة برمجة تطبيقات Kubernetes ‏(Kubernetes API)، وكيف يمكنك التعبير عنها بتنسيق yaml. ونتناول به ما يلي: شرح كائنات Kubernetes. مواصفات الكائن وحالته وصف كائن Kubernetes الحقول المطلوبة شرح كائنات Kubernetes الكائنات (Kubernetes objects) هي كيانات مستديمة (Persistent) في نظام Kubernetes. تُستخدم هذه الكيانات لتمثيل حالة العنقود (Cluster) الخاصة بك. على وجه التحديد، يمكن للكائنات وصف: التطبيقات المُحتواة (Containerized) المشغَّلة الآن (وعلى أي عقدة Node). الموارد المتاحة لتلك التطبيقات. السياسات المتعلقة بكيفية تصرف هذه التطبيقات، مثل سياسات إعادة التشغيل، والتحديثات، والتسامح مع الأخطاء (Fualt tolerance). كائن Kubernetes هو "سجل نيات". بمجرد أن تُنشئ الكائن، سيعمل نظام Kubernetes باستمرار للتأكد من وجوده. من خلال إنشاء كائن، فأنت تخبر نظام Kubernetes عمليَّا بالكيفية التي تريد أن يبدو عليها عبء عمل العنقود. هذه هي الحالة المرغوبة (Desired state) للعنقود. للعمل مع كائنات Kubernetes، سواء لإنشائها أو تعديلها أو حذفها، ستحتاج إلى استخدام واجهة برمجة تطبيقات Kubernetes. عند استخدام واجهة سطر الأوامر، kubectl على سبيل المثال، تستدعي واجهة سطر الأوامر واجهةَ برمجة تطبيقات Kubernetes الضرورية. يمكنك أيضًا استخدام واجهة التطبيقات البرمجية مباشرة في برامجك الخاصة باستخدام إحدى المكتبات العميلة. مواصفات الكائن وحالته يحتوي كل كائن Kubernetes تقريبًا على حقلين مضمَّنيْن في الكائن يتحكمان في تكوينه، وهما مواصفات الكائن spec وحالتهstatus. بالنسبة للكائنات التي لها مواصفات (الحقل spec)، يجب عليك تعيين الحقل عند إنشاء الكائن، مع تقديم وصف للخصائص التي يجب توافرها في المورد: الحالة المرغوبة. يصف حقل status الحالة الراهنة للكائن. يتولّى Kubernetes ومكوّناته تبديل الحالة الراهنة للكائن وتحديثها. يدير مستوى التحكم (Controle plane) في Kubernetes باستمرار ونشاط، الحالة الفعلية لكل كائن لمطابقتها مع الحالة المرغوبة التي حدّدتها. على سبيل المثال: في Kubernetes ، النشر (Deployment) هو كائن يمكن أن يمثل تطبيقًا يعمل على عنقودك. عند إنشاء النشر، يمكنك تعيين مواصفات النشر spec لتحديد أنك تريد تشغيل ثلاث نسخ متماثلة من التطبيق. يقرأ نظام Kubernetes مواصفات النشر ويبدأ ثلاث نظائر من التطبيق المطلوب، مع تحديث الحالة لتتوافق مع المواصفات الخاصة بك. في حالة تعطّل واحدة من تلك النظائر (تغيير الحالة)، يستجيب نظام Kubernetes لوجود فرق بين المواصفات spec والحالة statusعن طريق إجراء تصحيح، في هذه الحالة، بدء نسخة بديلة من التطبيق. راجع اتفاقيّات واجهة برمجة تطبيقات Kubernetes ‏(Kubernetes API Conventions) لمزيد من المعلومات حول مواصفات الكائن وحالته والبيانات الوصفية. وصف كائن Kubernetes عندما تنشئ كائنًا في Kubernetes، يجب عليك تقديم مواصفات الكائن التي تصف حالته المرغوبة، بالإضافة إلى بعض المعلومات الأساسية حول الكائن (مثل الاسم). عند استخدام واجهة برمجة تطبيقات Kubernetes لإنشاء الكائن (إما مباشرة أو عبر kubectl)، يجب أن يتضمن طلب واجهة برمجة التطبيقات (API request) تلك المعلومات على أنها JSON في متن الطلب (Request body). في معظم الأحيان، تُقدَّم المعلومات إلى kubectl في ملف yaml. و يحوِّل kubectl المعلومات إلى JSON عند تقديم طلب واجهة برمجة التطبيقات. ها هو مثال لملف yaml. يعرض الحقول المطلوبة ومواصفات كائن نشر Kubernetes: الملف application/deployment.yaml apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2 kind: Deployment metadata: name: nginx-deployment spec: selector: matchLabels: app: nginx replicas: 2 # tells deployment to run 2 pods matching the template template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80 تتمثل إحدى طرق إنشاء النشر باستخدام ملف yaml.، مثل الملف أعلاه، في استخدام الأمر kubectl apply في واجهة سطر أوامر kubectl، وتمرير ملف yaml. كوسيط. إليك مثال: kubectl apply -f https://k8s.io/examples/application/deployment.yaml --record الناتج مشابه لهذا: deployment.apps/nginx-deployment created الحقول المطلوبة ستحتاج إلى تعيين قيم للحقول التالية في ملف yaml. لكائن Kubernetes الذي تريد إنشاءه: apiVersion: إصدار واجهة برمجة تطبيقات Kubernetes التي تستخدمها لإنشاء هذا الكائن. kind: نوع الكائن الذي تريد إنشاءه. metadata: البيانات الوصفية التي تساعد على تحديد الكائن على نحو فريد، بما في ذلك سلسلة محارف (String) الاسم (الحقل name)، والمعرّف الفريد (UID)، و فضاء أسماء (namespace) اختياري. spec: الحالة المرغوبة للكائن. تختلف الصيغة الدقيقة للمواصفات حسب كائنات Kubernetes، وتحتوي على حقول متداخلة خاصة بكل كائن. يمكن أن يساعدك مرجع واجهة برمجة تطبيقات Kubentes ‏(The Kubernetes API Reference) في العثور على صيغة المواصفات لجميع الكائنات التي يمكنك إنشاؤها باستخدام Kubernetes. على سبيل المثال، يمكن العثور على صيغة مواصفات الكائنات (الحقل spec) من نوع Pod على الرابط التالي. PodSpec v1 core، ويمكن العثور على صيغة المواصفات spec لكائن نشر (Deployment) هنا. مرحبا Minikube تشرح الفقرات التالية من الدرس كيفية تشغيل برنامج "مرحبا بالعالم!" بسيط في بيئة Node.js على منصة Kubernetes باستخدام Minikube و Katacoda الذي يوفر بيئة Kubernetes مجانية في المتصفح. ملحوظة: تصلح التعليمات المذكورة هنا في بيئات Kubernetes المثبَّتة محلّيا. سنتناول ما يلي: الأهداف المتطلبات إنشاء عنقود Minikube إنشاء كائن نشر إنشاء خدمة تمكين الإضافات تنظيف المخلفات الأهداف نشر برنامج "مرحبا بالعالم!" على MiniKube. تشغيل التطبيق. عرض سجلات التطبيق. المتطلبات يوفر هذا الدرس صورة حاوية أنشئت من الملفات التالية: الملف minikube/server.js var http = require('http'); var handleRequest = function(request, response) { console.log('Received request for URL: ' + request.url); response.writeHead(200); response.end('Hello World!'); }; var www = http.createServer(handleRequest); www.listen(8080); الملف minikube/Dockerfile FROM node:6.14.2 EXPOSE 8080 COPY server.js . CMD [ "node", "server.js" ] راجع توثيق Docker للمزيد من المعلومات عن أمر docker build. إنشاء عنقود Minikube اضغط على Launch Terminal. افتح لوحة معلومات Kubernetes في متصفح: minikube dashboard بالنسبة لمستخدمي بيئة Katacoda فقط: في الجزء العلوي من لوجة الطرفية، اضغط على علامة الجمع (+)، ثم اضغط على Select port to view on Host 1. بالنسبة لمستخدمي بيئة Katacoda فقط: اكتب 30000، ثم اضغط على Display Port. إنشاء كائن نشر (Deployment) كائنات Pod في Kubernetes عبارة عن حاوية واحدة أو مجموعة من الحاويات مرتبطة ببعضها البعض لأغراض الإدارة والتواصل. تحتوي كائنات Pod في هذا الدرس على حاوية واحدة فقط. يتحقق كائن النشر (Deployment) في Kubernetes من صحة Pod الخاص بك ويعيد تشغيل حاوية Pod إنْ توقفت عن العمل. عمليات النشر هي الطريقة الموصى بها لإدارة إنشاء وتحجيم مجموعات الحاويات المسمّاة Pods. استخدم الأمر create kubectl لإنشاء كائن نشر يدير Pod. يقوم Pod بتشغيل الحاوية بناءً على صورة Docker المتوفرة. kubectl create deployment hello-node --image=gcr.io/hello-minikube-zero-install/hello-node عرض كائن النشر: kubectl get deployments الناتج مشابه لما يلي: NAME READY UP-TO-DATE AVAILABLE AGE hello-node 1/1 1 1 1m عرض Pod: kubectl get pods الناتج مشابه لما يلي: NAME READY STATUS RESTARTS AGE hello-node-5f76cf6ccf-br9b5 1/1 Running 0 1m عرض أحداث العنقود (Cluster Events): kubectl get events عرض إعدادات kubectl: kubectl config view إنشاء خدمة لا يمكن الوصول إلى كائن Pod افتراضيَّا إلا من خلال عنوان IP الداخلي الخاص به ضمن عنقود Kubernetes. لإتاحة الوصول إلى حاوية hello-node من خارج شبكة Kubernetes الافتراضية، يجب عليك عرض كائن Pod بصيغة خدمة Kubernetes. استخدم الأمر kubectl expose لعرض كائن Pod للعموم: kubectl expose deployment hello-node --type=LoadBalancer --port=8080 يشير الخيار type=LoadBalancer-- إلى أنك تريد إتاحة الخدمة للوصول إليها من خارج العنقود. اعرض الخدمة التي أنشأتها للتو: kubectl get services الناتج مشابه لما يلي: NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE hello-node LoadBalancer 10.108.144.78 <pending> 8080:30369/TCP 21s kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 23m بالنسبة لمزوّدي السحابة الذين يدعمون موازنة الحمل، فسيتوفّر عنوان IP خارجي للوصول إلى الخدمة. في بيئة Minikube، يتيح النوع LoadBalancer الوصول إلى الخدمة من خلال الأمر minikube service. نفّذ الأمر التالي: minikube service hello-node بالنسبة لمستخدمي بيئة Katacoda: اضغط على علامة الجمع (+)، ثم اضغط على Select port to view on Host 1. بالنسبة لمستخدمي بيئة Katacoda: لاحظ رقم المنفذ المكون من 5 أرقام المعروض مقابل 8080 في مُخرجات الخدمات (Services Output). يُولّد رقم المنفذ هذا عشوائيًّا ويمكن أن يكون مختلفًا بالنسبة لك. اكتب رقمك في مربع نص رقم المنفذ، ثم اضغط على Display Port. باستخدام المثال السابق ، يمكنك كتابة 30369 يؤدي ذلك إلى فتح نافذة متصفح تخدم تطبيقك وتظهر رسالة "Hello World". تمكين الإضافات يحتوي Minikube على مجموعة من الإضافات المدمجة، وهي موارد تضيف وظائف جديدة إلى Kubernetes. يمكن تمكين الإضافات وتعطيلها وفتحها في بيئة Kubernetes المحلية. أظهر قائمة بالإضافات المدعومة حاليّا: minikube addons list الناتج مشابه لما يلي: addon-manager: enabled dashboard: enabled default-storageclass: enabled efk: disabled freshpod: disabled gvisor: disabled helm-tiller: disabled ingress: disabled ingress-dns: disabled logviewer: disabled metrics-server: disabled nvidia-driver-installer: disabled nvidia-gpu-device-plugin: disabled registry: disabled registry-creds: disabled storage-provisioner: enabled storage-provisioner-gluster: disabled تمكين إضافة، على سبيل المثال، metrics-server: minikube addons enable metrics-server الناتج مشابه لما يلي: metrics-server was successfully enabled عرض Pod والخدمة التي أنشأتها للتو: kubectl get pod,svc -n kube-system الناتج مشابه لما يلي: NAME READY STATUS RESTARTS AGE pod/coredns-5644d7b6d9-mh9ll 1/1 Running 0 34m pod/coredns-5644d7b6d9-pqd2t 1/1 Running 0 34m pod/metrics-server-67fb648c5 1/1 Running 0 26s pod/etcd-minikube 1/1 Running 0 34m pod/influxdb-grafana-b29w8 2/2 Running 0 26s pod/kube-addon-manager-minikube 1/1 Running 0 34m pod/kube-apiserver-minikube 1/1 Running 0 34m pod/kube-controller-manager-minikube 1/1 Running 0 34m pod/kube-proxy-rnlps 1/1 Running 0 34m pod/kube-scheduler-minikube 1/1 Running 0 34m pod/storage-provisioner 1/1 Running 0 34m NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/metrics-server ClusterIP 10.96.241.45 <none> 80/TCP 26s service/kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP 34m service/monitoring-grafana NodePort 10.99.24.54 <none> 80:30002/TCP 26s service/monitoring-influxdb ClusterIP 10.111.169.94 <none> 8083/TCP,8086/TCP 26s تعطيل metrics-server: minikube addons disable metrics-server والناتج مشابه لما يلي: metrics-server was successfully disabled التخلّص من الموارد يمكنك الآن التخلص من الموارد التي أنشأتها في العنقود: kubectl delete service hello-node kubectl delete deployment hello-node يوجد خيار آخر يتمثّل في إيقاف آلة Minikube الافتراضية: minikube stop كما يمكن حذف Minikube: minikube delete ترجمة وبتصرُّف للمقالات التالية: What is Kubernetes Understanding Kubernetes Objects Hello Minikube
  4. يعد دوكر Docker أداة فعالة لأتمتة تثبيت تطبيقات لينكس داخل حاويات للبرامج، للاستفادة الكاملة من إمكاناته، يجب تشغيل كل مكون من مكونات التطبيق في حاويته الخاصة. وبالنسبة للتطبيقات المعقدة التي تحوي الكثير من المكونات، يمكن أن يصبح تنسيق جميع الحاويات لبدء التشغيل والاتصال وإيقاف التشغيل معًا أمرًا غير عملي. توصل مجتمع دوكر إلى حل شائع يسمى Fig، والذي يسمح باستخدام ملف YAML واحد لتنظيم جميع حاويات دوكر وتكويناتها. حيث أصبح هذا شائعًا جدًا لدرجة أن مجتمع دوكر قرر جعل Docker Compose يعتمد على مصدر Fig، والذي تم إلغاؤه الآن. يتيح Docker Compose للمستخدمين تنظيم عمليات حاويات دوكر، بما في ذلك بدء وإيقاف التشغيل وإعداد الربط بين الحاويات ووحدات التخزين. في هذا الدليل، ستقوم بتثبيت أحدث إصدار من Docker Compose لمساعدتك في إدارة التطبيقات متعددة الحاويات على خادم دبيان 10. المتطلبات الأساسية لكي تتمكن من المتابعة مع هذه المقالة، ستحتاج إلى: خادم دبيان 10 ومستخدم عادي (non-root) بامتيازات sudo. حيث يشرح هذا الإعداد الأولي للخادم مع دليل دبيان 10 التعليمي كيفية إعداد ذلك. دوكر مثبّت بإرشادات من الخطوة الأولى والخطوة الثانية لكيفية تثبيت واستخدام دوكر على دبيان 10 ملاحظة: على الرغم من أن المتطلبات المسبقة تعطي تعليمات لتثبيت دوكر على دبيان 10، فإن أوامر docker في هذه المقالة يمكن أن تعمل على أنظمة تشغيل أخرى طالما أن دوكر مثبت. الخطوة الأولى - تثبيت Docker Compose على الرغم من أنه يمكن تثبيت Docker Compose من مستودعات Debian الرسمية، إلا أن هناك عدة إصدارات ثانوية ظهرت بعد الإصدار الأخير، لذلك في هذا الدليل ستقوم بتثبيته من مستودع GitHub الخاص بــدوكر. يختلف الأمر التالي قليلاً عن الأمر الذي ستجده في صفحة الإصدارات. فباستخدام الراية ‎-o لتحديد ملف الإخراج أولاً بدلاً من إعادة توجيه الإخراج، هذه الصيغة تتجنب حدوث خطأ "رفض الإذن" الذي يحدث عند استخدام sudo. تحقق من الإصدار الحالي، وإذا لزم الأمر قم بتحديثه في الأمر التالي: $ sudo curl -L https://github.com/docker/compose/releases/download/1.25.3/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose بعد ذلك سنقوم بتعيين الأذونات: $ sudo chmod +x /usr/local/bin/docker-compose ثم سنتحقق من نجاح التثبيت عن طريق التحقق من الإصدار: $ docker-compose --version سيؤدي ذلك إلى طباعة النسخة التي قمنا بتثبيتها: $ docker-compose version 1.25.3, build d4d1b42b الخطوة الثانية - تشغيل حاوية مع Docker Compose يتضمن سجل دوكر العام Docker Hub، صورة Hello World للتوضيح والاختبار. حيث توضح الحد الأدنى من التكوين المطلوب لتشغيل حاوية باستخدام Docker Compose: ملف YAML الذي يستدعي صورة واحدة. سنقوم بإنشاء أصغر ملف إعدادت ممكن لتشغيل حاوية hello-world الخاصة بنا. أولاً ، قم بإنشاء دليل لملف YAML وقم بالتحويل إليه: $ mkdir hello-world cd hello-world ثم قم بإنشاء ملف YAML: $ nano docker-compose.yml ضع المحتويات التالية في الملف docker-compose.yml واحفظ الملف واخرج من محرر النصوص: $ my-test: image: hello-world يتم استخدام السطر الأول في ملف YAML كجزء من اسم الحاوية. ويحدد السطر الثاني الصورة التي سيتم استخدامها لإنشاء الحاوية. فعندما نقوم بتنفيذ الأمر docker-compose up، سيبحث عن صورة محلية بالاسم الذي حددناه، ألا وهو hello-world. بعد ذلك سنقوم بحفظ الملف والخروج منه. يمكنك النظر يدويًا إلى الصور الموجودة على نظامنا باستخدام الأمر docker images: $docker images عندما لا تكون هناك صور محلية على الإطلاق، يتم عرض عناوين الأعمدة فقط: REPOSITORY TAG IMAGE ID CREATED SIZE الآن ، أثناء وجودك في مجلد ‎~/hello-world، نفّذ الأمر التالي: $docker-compose up في المرة الأولى التي تقوم فيها بتنفيذ هذا الأمر، إذا لم تكن هناك صورة محلية باسم hello-world، فسوف يسحبها Docker Compose من مستودع Docker Hub العام: Pulling my-test (hello-world:)... latest: Pulling from library/hello-world 9db2ca6ccae0: Pull complete Digest: sha256:4b8ff392a12ed9ea17784bd3c9a8b1fa3299cac44aca35a85c90c5e3c7afacdc Status: Downloaded newer image for hello-world:latest . . . بعد سحب الصورة، يقوم docker-compose بإنشاء حاوية تقوم بإرفاق وتشغيل برنامج hello، والذي بدوره يؤكد أن التثبيت يعمل: . . . Creating helloworld_my-test_1... Attaching to helloworld_my-test_1 my-test_1 | my-test_1 | Hello from Docker. my-test_1 | This message shows that your installation appears to be working correctly. my-test_1 | . . . ثم يطبع شرحًا لما فعله: To generate this message, Docker took the following steps: my-test_1 | 1. The Docker client contacted the Docker daemon. my-test_1 | 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. my-test_1 | (amd64) my-test_1 | 3. The Docker daemon created a new container from that image which runs the my-test_1 | executable that produces the output you are currently reading. my-test_1 | 4. The Docker daemon streamed that output to the Docker client, which sent it my-test_1 | to your terminal. تعمل حاويات دوكر فقط عندما يكون الأمر نشطًا، لذلك بمجرد الانتهاء من تشغيل [hello]، تتوقف الحاوية. وبالتالي عندما ننظر إلى العمليات النشطة ستظهر عناوين الأعمدة، لكن لن يتم إدراج حاوية hello-world كونها لا تعمل: $docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES يمكنك الاطلاع على معلومات الحاوية، وهذا ما ستحتاجه في الخطوة التالية باستخدام الراية ‎-a. يعرض هذا الأمر جميع الحاويات وليس فقط الحاويات النشطة: $docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 06069fd5ca23 hello-world "/hello" 35 minutes ago Exited (0) 35 minutes ago hello-world_my-test_1 و يعرض هذا المعلومات التي ستحتاج إليها لإزالة الحاوية عند الانتهاء منها. الخطوة الثالثة - إزالة الصورة (اختياري) لتجنب استخدام مساحة قرص غير ضرورية، سنقوم بإزالة الصورة المحلية. وللقيام بذلك، سنحتاج إلى حذف جميع الحاويات التي تشير إلى الصورة باستخدام الأمر docker rm، متبوعًا إما بمعرف الحاوية CONTAINER ID أو الاسم NAME. في المثال التالي، نستخدم معرف الحاوية CONTAINER ID من الأمر docker ps -a الذي قمنا بتشغيله للتو. وتأكد من استبدال معرف الحاوية: $docker rm 06069fd5ca23 بمجرد إزالة جميع الحاويات التي تشير إلى الصورة، يمكننا إزالة الصورة: $docker rm 06069fd5ca23 الخلاصة لقد قمت بتثبيت Docker Compose على دبيان 10، واختبرت التثبيت عن طريق تشغيل مثال Hello World، وأزلت صورة الاختبار والحاوية. بينما أكد مثال Hello World التثبيت، فإن هذا التكوين الأساسي لا يُظهر إحدى الفوائد الرئيسية لـ Docker Compose – وهي القدرة على إحضار مجموعة من حاويات دوكر للأعلى وللأسفل في نفس الوقت. ترجمة -وبتصرف- للمقال How To Install Docker Compose on Debian 10 لصاحبيه Brian Hogan و Kathleen Juell
  5. يعد دوكر تطبيقًا يبسّط إدارة عمليات التطبيق في الحاويات. حيث تتيح لك الحاويات تشغيل تطبيقاتك في عمليات معزولة الموارد فيما بينها. فهي من ناحية المبدأ تشبه Virtual Machines، لكن الحاويات أكثر قابلية للنقل وأكثر ملاءمة للموارد وأكثر اعتمادًا على نظام تشغيل المضيف. وللحصول على مقدمة تفصيلية للمكونات المختلفة لحاوية دوكر، راجع المقال نظام Docker Ecosystem: مقدمة إلى المكونات المشتركة.. في هذا الدليل، ستقوم بتثبيت واستخدام Docker Community Edition ‏(CE) على دبيان 10. حيث ستقوم بتثبيت دوكر بذاته والتعامل مع الحاويات والنِسخ، ورفع نسخة إلى مستودع دوكر. المتطلبات لمتابعة هذا الدليل، ستحتاج إلى ما يلي: خادم دبيان 10 مع مستخدم عادي بصلاحيات sudo بالإضافة لجدار الحماية. حساب على Docker Hub في حال كنت ترغب في إنشاء نسخك الخاصة ورفعها إلى Docker Hub، كما هو موضح في الخطوتين 7 و 8. الخطوة 1- تثبيت دوكر قد لا تكون حزمة تثبيت دوكر المتوفرة في مستودع دبيان الرسمي حزمًة ذو أحدث إصدار. لذا لضمان حصولنا على أحدث إصدار، سنقوم بتثبيت دوكر من مستودع دوكر الرسمي وذلك بإضافة مصدر حزمة جديد مع مفتاح GPG من دوكر للتأكد من صلاحية التنزيلات، ومن ثم تثبيت الحزمة. أولاً، قم بتحديث قائمة الحزم الموجودة لديك: $ sudo apt update بعد ذلك قم بتثبيت بعض الحزم الأساسية التي تتيح لـ apt استخدام الحزم عبر HTTPS: $ sudo apt install apt-transport-https ca-certificates curl gnupg2 software-properties-common ثم أضف مفتاح GPG لمستودع دوكر الرسمي إلى نظامك: $ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add أضف مستودع دوكر إلى مصادر APT: $ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable" بعد ذلك قم بتحديث قاعدة بيانات الحزم بحزم دوكر من المستودع المضاف حديثًا: $ sudo apt update تأكد من أنك على وشك التثبيت من مستودع دوكر بدلاً من مستودع دبيان الافتراضي: $ apt-cache policy docker-ce سترى مخرجات مثل هذا على الرغم من أن رقم إصدار دوكر قد يكون مختلفًا: $ docker-ce: Installed: (none) Candidate: 5:18.09.7~3-0~debian-buster Version table: 5:18.09.7~3-0~debian-buster 500 500 https://download.docker.com/linux/debian buster/stable amd64 Packages لاحظ أن docker-ce غير مثبت، لكن المرشح للتثبيت هو من مستودع دوكر لـ دبيان 10 (buster) أخيرًا، قم بتثبيت دوكر: $ sudo apt install docker-ce تم الآن تثبيت دوكر وبدأ البرنامج الخفي (daemon، العفريت كما يطلق عليه مستخدمو لينكس)، و تم تمكين العملية للبدء في التشغيل. تحقق من أنه يعمل بتنفيذ الأمر التالي: $ sudo systemctl status docker سيكون الناتج مشابهًا لما يلي، مما يدل على أن الخدمة نشطة وتعمل: docker.service - Docker Application Container Engine Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2019-07-08 15:11:19 UTC; 58s ago Docs: https://docs.docker.com Main PID: 5709 (dockerd) Tasks: 8 Memory: 31.6M CGroup: /system.slice/docker.service └─5709 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock لا يمنحك تثبيت دوكر خدمة Docker daemon وحسب، بل يمنحك أيضًا خط أوامر docker، أو عميل دوكر. سنكتشف كيفية استخدام أمر docker لاحقًا في هذا الدليل التعليمي. الخطوة 2- تنفيذ أمر دوكر دون sudo (اختياري) افتراضيًا، لا يمكن تشغيل أمر docker إلا للمستخدم الجذر أو بواسطة مستخدم في مجموعة docker، والتي يتم إنشاؤها تلقائيًا أثناء عملية تثبيت دوكر. وإذا حاولت تشغيل الأمر docker دون أن تضيفه إلى sudo أو دون أن تكون في مجموعة docker، فستحصل على ناتج مثل هذا: docker: Cannot connect to the Docker daemon. Is the docker daemon running on this host?. See 'docker run –help'. إذا كنت تريد تجنب كتابة sudo كلما قمت بتشغيل أمر docker، أضف اسم المستخدم الخاص بك إلى مجموعة docker: $ sudo usermod -aG docker ${USER} لتطبيق عضوية المجموعة الجديدة، قم بتسجيل الخروج من الخادم والعودة مرة أخرى أو اكتب ما يلي: $ su - ${USER} عندها سيُطلب منك إدخال كلمة مرور المستخدم للمتابعة. تأكد من إضافة المستخدم الآن إلى مجموعة docker عن طريق كتابة: $ id -nG sammy sudo docker وإذا كنت بحاجة إلى إضافة مستخدم آخر إلى مجموعة docker التي لم تسجل الدخول بها من قبل، فيمكنك الإعلان عن اسم المستخدم هذا باستخدام: $ sudo usermod -aG docker username تفترض بقية المقالة هذه أنك تقوم بتشغيل أمر docker كمستخدم في مجموعة docker. في حال اخترت عدم القيام بذلك، يرجى إلحاق الأوامر بـsudo. دعنا نستكشف أمر docker تاليًا. الخطوة 3- استخدام أمر docker يتكون استخدامdocker من تمرير سلسلة من الخيارات والأوامر متبوعة بالوسطاء (arguments). حيث تأخذ الصيغة هذا الشكل: $ docker [option] [command] [arguments] لعرض كافة الأوامر الفرعية المتاحة، اكتب: $ docker فبالنسبة لـ دوكر 18، تتضمن القائمة الكاملة للأوامر الفرعية المتاحة ما يلي: Attach إرفاق تدفقات الإدخال والإخراج والخطأ القياسية المحلية إلى حاوية قيد التشغيل Build إنشاء نسخة من ملف Dockerfile Commit إنشاء نسخة جديدة من تغييرات الحاوية Cb نسخ الملفات / المجلدات بين الحاوية ونظام الملفات المحلي Create إنشاء حاوية جديدة Diff فحص التغييرات بالملفات أو المجلدات على نظام ملفات الحاوية Events معرفة الأحداث مباشرًة من الخادم Exec تشغيل أمر في حاوية قيد التشغيل Export استخراج نظام ملفات الحاوية كإنشاء محفوظة (tar archive) History إظهار تاريخ النسخة Images عرض قائمة النسخ Import استيراد المحتويات من tarball لإنشاء نسخة نظام ملفات Info عرض المعلومات على مستوى النظام Inspect إظهار معلومات منخفضة المستوى عن كائنات دوكر Kill إيقاف حاوية واحدة قيد التشغيل أو أكثر Load تحميل نسخة من أرشيف tar أو STDIN Login تسجيل الدخول إلى سجل دوكر Logout تسجيل الخروج من سجل دوكر Logs عرض سجلات الحاوية Pause إيقاف جميع العمليات مؤقتًا داخل حاوية واحدة أو أكثر Port سرد تعيينات المنافذ (port mappings) أو تعيين معين للحاوية Ps قائمة الحاويات Pull سحب نسخة أو وحدة تخزين (repository) من سجل Push رفع نسخة أو وحدة تخزين إلى السجل Rename إعادة تسمية الحاوية Restart إعادة تشغيل حاوية واحدة أو أكثر Rm إزالة حاوية واحدة أو أكثر Rmi إزالة نسخة واحدة أو أكثر Run تشغيل أمر في حاوية جديدة Save حفظ نسخة أو أكثر في أرشيف tar (يتم بثها إلى STDOUT افتراضيًا) Search بحث في Docker Hub عن النسخ Start بدء تشغيل حاوية واحدة أو أكثر Stats عرض بث مباشر لإحصائيات استخدام موارد الحاوية Stop إيقاف تشغيل حاوية واحدة أو أكثر Tag إنشاء علامة TARGET_IMAGE تشير إلى SOURCE_IMAGE Top عرض العمليات الجارية للحاوية Unpause إلغاء الإيقاف المؤقت لجميع العمليات داخل حاوية واحدة أو أكثر Update تحديث التكوين لحاوية واحدة أو أكثر Version إظهار معلومات إصدار دوكر Wait القيام بالحظر حتى تتوقف حاوية واحدة أو أكثر، ثم اطبع رموز الخروج الخاصة بها لعرض الخيارات المتاحة لأمر معين، اكتب: $ docker docker-subcommand –help أما لعرض معلومات على مستوى النظام حول دوكر، يمكنك استخدام: $ docker info دعنا نستكشف بعضًا من هذه الأوامر. حيث سنبدأ بالعمل مع النسخ. الخطوة 4 – التعامل مع نسخ دوكر يتم إنشاء حاويات دوكر من نسخ دوكر عندها يقوم تلقائيًّا بسحب هذه النسخات من Docker Hub، وهو سجل تديره الشركة المسؤولة عن مشروع دوكر. حيث يمكن لأي شخص إنزال نسخ دوكر على Docker Hub، لذا فإن معظم التطبيقات وتوزيعات Linux التي ستحتاج إليها ستتم استضافتها هناك. للتحقق مما إذا كان يمكنك الوصول إلى النسخ وتنزيلها من Docker Hub، اكتب: $ docker run hello-world سيشير الإخراج إلى أن دوكر يعمل بشكل صحيح: Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 1b930d010525: Pull complete Digest: sha256:41a65640635299bab090f783209c1e3a3f11934cf7756b09cb2f1e02147c6ed8 Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. … بدايةً لم يتمكن دوكر من العثور على نسخة hello-world محليًا، لذلك تم تنزيل النسخة من وحدة التخزين الافتراضية Docker Hub. فبمجرد تنزيل النسخة، يقوم دوكر بإنشاء حاوية من النسخة ويتم تنفيذ التطبيق ضمن الحاوية عارضاً الرسالة. يمكنك البحث عن النسخات المتاحة على Docker Hub باستخدام أمر docker مع الأمر الفرعي search. على سبيل المثال، للبحث عن نسخة Ubuntu، اكتب: $ docker search ubuntu سيقوم هذا البرنامج بالبحث ضمن Docker Hub ويعرض قائمة بجميع النسخات التي يتطابق اسمها مع سلسلة البحث. وفي هذه الحالة، سيكون الناتج مشابهًا لما يلي: NAME DESCRIPTION STARS OFFICIAL AUTOMATED ubuntu Ubuntu is a Debian-based Linux operating sys… 9704 [OK] dorowu/ubuntu-desktop-lxde-vnc Docker image to provide HTML5 VNC interface … 319 [OK] rastasheep/ubuntu-sshd Dockerized SSH service, built on top of offi… 224 [OK] consol/ubuntu-xfce-vnc Ubuntu container with "headless" VNC session… 183 [OK] ubuntu-upstart Upstart is an event-based replacement for th… 99 [OK] ansible/ubuntu14.04-ansible Ubuntu 14.04 LTS with ansible 97 [OK] neurodebian NeuroDebian provides neuroscience research s… 57 [OK] 1and1internet/ubuntu-16-nginx-php-phpmyadmin-mysql-5 ubuntu-16-nginx-php-phpmyadmin-mysql-5 50 [OK] ubuntu … في العمود OFFICIAL، تشير OK إلى نسخة تم إنشاؤها ودعمها من قبل الشركة المسؤولة عن المشروع. فبمجرد تحديد النسخة التي ترغب باستخدامها، يمكنك تنزيلها على الحاسوب باستخدام الأمر الفرعي pull. قم بتنفيذ الأمر التالي لتنزيل نسخة ubuntu الرسمية على الحاسب: $ docker pull ubuntu سترى الناتج التالي: Using default tag: latest latest: Pulling from library/ubuntu 5b7339215d1d: Pull complete 14ca88e9f672: Pull complete a31c3b1caad4: Pull complete b054a26005b7: Pull complete Digest: sha256:9b1702dcfe32c873a770a32cfd306dd7fc1c4fd134adfb783db68defc8894b3c Status: Downloaded newer image for ubuntu:latest يمكنك بعد ذلك تشغيل حاوية باستخدام النسخة التي تم تنزيلها بالأمر run. وكما رأيت في مثال hello-world، في حال لم يتم تنزيل صورة عند تنفيذ docker باستخدام الأمر الفرعي run، فسيقوم عميل دوكر بتنزيل النسخة أولاً ثم تشغيل حاوية باستخدامها. لرؤية النسخات التي تم تنزيلها على الحاسوب، اكتب: $ docker images ستبدو المخرجات مشابهة لما يلي: REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu latest 4c108a37151f 2 weeks ago 64.2MB hello-world latest fce289e99eb9 6 months ago 1.84kB كما سترى لاحقًا في هذا الدليل، يمكن تعديل النسخ التي تستخدمها لتشغيل الحاويات واستخدامها لإنشاء نسخ اخرى جديدة، والتي قد يتم رفعها بعد ذلك (يعني يتم عمل push لها حسب المصطلح التقني) إلى Docker Hub أو سجلات دوكر الأخرى. سنرى في الخطوة التالية كيفية تشغيل الحاويات بمزيد من التفاصيل. الخطوة 5 - تشغيل حاوية دوكر إن حاوية hello-world التي قمت بتشغيلها في الخطوة السابقة هي مثال على حاوية يتم تشغيلها والخروج منها بعد بث رسالة اختبار. فيمكن للحاويات ان تكون تفاعلية و أكثر فائدة من ذلك. فهي تشبه الآلات الافتراضية، لكن أكثر ملاءمة للموارد. كمثال، لنقم بتشغيل حاوية باستخدام أحدث نسخة لـ Ubuntu. حيث يمنحك الجمع بين المبدلين ‎-i و ‎-t إمكانية الوصول التفاعلي إلى القشرة في الحاوية (interactive shell access): $ docker run -it ubuntu يجب تغيير موجه الأوامر ليعكس حقيقة أنك تعمل الآن داخل الحاوية ويجب أن يأخذ هذا النموذج: root@d9b100f2f636:/# لاحظ معرف الحاوية في موجه الأوامر. نظرًا الى هذا المثال، يكون المعرف d9b100f2f636. فستحتاج إلى معرّف الحاوية هذا لاحقًا لتحديد الحاوية عندما تريد إزالتها. الآن يمكنك تشغيل أي أمر داخل الحاوية. فعلى سبيل المثال، فلنقم بتحديث قاعدة بيانات الحزمة داخل الحاوية. لست بحاجة إلى إضافة أي أمر باستخدام sudo، لأنك تعمل داخل الحاوية كمستخدم جذر (root): root@d9b100f2f636:/# apt update ثم قم بتثبيت أي تطبيق فيه. دعنا نثبت Node.js: root@d9b100f2f636:/# apt install nodejs يؤدي هذا إلى تثبيت Node.js في الحاوية من مستودع Ubuntu الرسمي. وعند انتهاء التثبيت، تحقق من تثبيت Node.js: root@d9b100f2f636:/# node -v سترى رقم الإصدار المعروض في جهازك الطرفي: v8.10.0 أي تغييرات تجريها داخل الحاوية تنطبق فقط على الحاوية نفسها. للخروج من الحاوية، اكتب exit في واجهة الأوامر. دعنا نلقي نظرة على إدارة الحاويات على نظامنا بعد ذلك. الخطوة 6- إدارة حاويات دوكر بعد استخدام دوكر لفترة من الوقت، سيكون لديك العديد من الحاويات النشطة (قيد التشغيل) وغير النشطة على الحاسوب الخاص بك. ولعرض الحاويات النشطة، استخدم: $ docker ps سترى ناتج مشابه لما يلي: CONTAINER ID IMAGE COMMAND CREATED في هذا الدليل التعليمي، بدأت حاويتين؛ واحدة من نسخة hello-world والأخرى من نسخة ubuntu. بحيث لم يعد كلا الحاويتين قيد التشغيل، لكنهما لا تزالان موجودتان على نظامك. لعرض جميع الحاويات - النشطة وغير النشطة، قم بتشغيل docker ps باستخدام المبدّل ‎-a: $ docker ps -a سترى مخرجات مشابهة لهذا: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d42d0bbfbd35 ubuntu "/bin/bash" About a minute ago Exited (0) 20 seconds ago friendly_volhard 0740844d024c hello-world "/hello" 3 minutes ago Exited (0) 3 minutes ago elegant_neumann لعرض أحدث حاوية قمت بإنشائها، قم بتشغيل docker ps باستخدام ‎-l: $ docker ps -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d42d0bbfbd35 ubuntu "/bin/bash" About a minute ago Exited (0) 34 seconds ago friendly_volhard لبدء تشغيل حاوية ما، استخدم docker start، متبوعًا بمعرف الحاوية أو اسم الحاوية. لنبدأ الحاوية القائمة على Ubuntu بمعرف d9b100f2f636: $ docker start d42d0bbfbd35 عندها ستبدأ الحاوية، ويمكنك استخدام docker ps لمعرفة حالتها: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d42d0bbfbd35 ubuntu "/bin/bash" About a minute ago Up 8 seconds friendly_volhard لإيقاف حاوية جارية، استخدم docker stop، متبوعًا بمعرف الحاوية أو الاسم. وهذه المرة سنستخدم الاسم الذي خصصه دوكر للحاوية، الا وهو friendly_volhard: $ docker stop friendly_volhard بمجرد أن تقرر أنك لم تعد بحاجة إلى الحاوية بعد الآن، قم بإزالتها باستخدام الأمر docker rm، مرة أخرى باستخدام إما معرف الحاوية أو إسمها. يمكنك استخدام الأمر docker ps -a للعثور على معرف الحاوية أو اسم الحاوية المرتبط بصورة hello-world وإزالتها. $ docker rm elegant_neumann يمكنك بدء حاوية جديدة وتسميتها باستخدام المفتاح--name. ويمكنك أيضًا استخدام المبدل ‎--rm لإنشاء حاوية تزيل نفسها عندما تتوقف. راجع الأمر help docker run للحصول على مزيد من المعلومات حول هذه الخيارات وغيرها. يمكن تحويل الحاويات إلى صور يمكنك استخدامها لبناء حاويات جديدة. دعونا نلقي نظرة على كيفية عمل ذلك. الخطوة 7- إحداث التغييرات في حاوية لنسخة دوكر عند بدء تشغيل نسخة من دوكر، يمكنك إنشاء الملفات وتعديلها وحذفها تمامًا كما يمكنك باستخدام جهاز افتراضي (virtual machine). حيث ستنطبق التغييرات التي تجريها على تلك الحاوية فقط.. يمكنك تشغيلها وإيقافها، لكن بمجرد ازالتها باستخدام الأمر docker rm، ستفقد التغييرات للأبد. يوضح لك هذا القسم كيفية حفظ حالة الحاوية كنسخة دوكر جديدة. بعد تثبيت Node.js داخل حاوية Ubuntu، لديك الآن حاوية تعمل على نسخة معينة، لكن هذه الحاوية مختلفة عن النسخة (image) التي استخدمتها لإنشائها. عندها قد ترغب في إعادة استخدام حاوية Node.js هذه كأساس للنسخ الجديدة لاحقًا. ثم قم بتنفيذ التغييرات على نسخة دوكر جديدة باستخدام الأمر التالي. $ docker commit -m "What you did to the image" -a "Author Name" container_id repository/new_image_name إن المفتاح ‎-m مخصص لرسالة التنفيذ (commit message) التي تساعدك والآخرين على معرفة التغييرات التي أجريتها، بينما يُستخدم ‎-a لتحديد المؤلف. معرف الحاوية container_id هو الحاوية التي لاحظتها سابقًا في الدليل عندما بدأت جلسة دوكر التفاعلية. إلا إذا قمت بإنشاء مستودعات إضافية على Docker Hub، فعادة ما يكون المستودع هو اسم مستخدم Docker Hub. على سبيل المثال، بالنسبة للمستخدم sammy بمعرّف الحاوية d9b100f2f636، سيكون الأمر كما يلي: $ docker commit -m "added Node.js" -a "sammy" d42d0bbfbd35 sammy/ubuntu-nodejs وعند تنفيذك نسخة ما، يتم حفظ النسخة الجديدة محليًا على جهاز الحاسب الخاص بك. لاحقًا في هذا الدليل، ستتعلم كيفية رفع نسخة إلى سجل دوكر مثل Docker Hub حتى يتمكن الآخرون من الوصول إليها. سيؤدي إدراج نسخ دوكر مرة أخرى إلى إظهار النسخة الجديدة، بالإضافة إلى النسخة القديمة التي تم اشتقاقها منها: $ docker images سترى مخرجات مثل هذا: REPOSITORY TAG IMAGE ID CREATED SIZE sammy/ubuntu-nodejs latest d441c62350b4 10 seconds ago 152MB ubuntu latest 4c108a37151f 2 weeks ago 64.2MB hello-world latest fce289e99eb9 6 months ago 1.84kB في هذا المثال، ubuntu-nodejs هي النسخة الجديدة التي تم اشتقاقها من نسخة ubuntu الموجودة من Docker Hub. حيث يعكس اختلاف الحجم التغييرات التي تم إجراؤها. وفي هذا المثال، كان التغيير هو تثبيت NodeJS. لذا في المرة القادمة التي تحتاج فيها إلى تشغيل حاوية باستخدام Ubuntu مع NodeJS مثبتة مسبقًا، يمكنك فقط استخدام النسخة الجديدة. يمكنك أيضًا إنشاء نسخ من ملف Dockerfile، والذي يتيح لك أتمتة تثبيت البرنامج في نسخة جديدة. لكن يعد هذا خارج نطاق المقال. الآن دعنا نشارك النسخة الجديدة مع الآخرين حتى يتمكنوا من إنشاء حاويات منها. الخطوة 8- رفع نسخ دوكر إلى مستودع دوكر الخطوة المنطقية التالية بعد إنشاء نسخة جديدة من نسخة موجودة هي مشاركتها مع عدد قليل من أصدقائك أو العالم كله على Docker Hub أو أي سجل دوكر آخر يمكنك الوصول إليه. و لرفع نسخة ما إلى Docker Hub أو أي سجل دوكر آخر، يجب أن يكون لديك حساب هناك. يوضح لك هذا القسم كيفية رفع نسخة دوكر إلى Docker Hub. ولمعرفة كيفية إنشاء سجل دوكر الخاص بك، تفقد كيفية إعداد سجل دوكر خاص على Ubuntu 14.04 لرفع نسختك، قم أولاً بتسجيل الدخول إلى Docker Hub. $ docker login -u docker-registry-username عندها ستتم مطالبتك بالمصادقة باستخدام كلمة مرور Docker Hub. و إذا حددت كلمة المرور الصحيحة، فيجب أن تنجح المصادقة. ملاحظة: إذا كان اسم مستخدم سجل دوكر الخاص بك مختلفًا عن اسم المستخدم المحلي الذي استخدمته لإنشاء النسخة، فسيتعين عليك وضع علامة على نسختك باسم مستخدم التسجيل خاصتك. بالنسبة للمثال الوارد في الخطوة الأخيرة، اكتب: $ docker tag sammy/ubuntu-nodejs docker-registry-username/ubuntu-nodejs ثم يمكنك رفع نسختك باستخدام: $ docker push docker-registry-username/docker-image-name لرفع نسخة ubuntu-nodejs إلى مستودع sammy، سيكون الأمر على الشكل التالي: $ docker push sammy/ubuntu-nodejs قد تستغرق العملية بعض الوقت حتى تكتمل أثناء تحميل النسخ، ولكن عند اكتمالها سيبدو الإخراج كما يلي: The push refers to a repository [docker.io/sammy/ubuntu-nodejs] e3fbbfb44187: Pushed 5f70bf18a086: Pushed a3b5c80a4eba: Pushed 7f18b442972b: Pushed 3ce512daaf78: Pushed 7aae4540b42d: Pushed … بعد رفع النسخة إلى السجل، يجب أن تكون مدرجة في لوحة تحكم حسابك مثل تلك التي تظهر في الصورة أدناه. إذا أظهرت محاولة الرفع خطأ من هذا النوع، فمن المحتمل أنك لم تقم بتسجيل الدخول: The push refers to a repository [docker.io/sammy/ubuntu-nodejs] e3fbbfb44187: Preparing 5f70bf18a086: Preparing a3b5c80a4eba: Preparing 7f18b442972b: Preparing 3ce512daaf78: Preparing 7aae4540b42d: Waiting unauthorized: authentication required قم بتسجيل الدخول باستخدام docker login وتكرار محاولة الرفع. ثم أثبت وجوده في صفحة مستودع Docker Hub الخاص بك. يمكنك الآن استخدام docker pull sammy/ubuntu-nodejs لسحب النسخة إلى جهاز جديد واستخدامها لتشغيل حاوية جديدة. الخلاصة لقد قمت بتثبيت دوكر، وعملت بالنسخ والحاويات، ورفعت نسخة معدلة إلى Docker Hub. الآن بعد أن تعرفت على الأساسيات، استكشف بقية دروس أكاديمية حسوب قسم DevOps. ترجمة -وبتصرف- للمقال How To Install and Use Docker on Debian 10 لصاحبه Brian Hogan
  6. ما الفرق بين دوكر (Docker) والأجهزة الافتراضية (والمسماة أيضًا بالأجهزة الظاهرية Virtual Machines)؟ سنشرح في هذا المقال الاختلافات بينهما، وسنذكر وجهة نظرنا لمساعدتك على الاختيار. ما هو دوكر؟ تسعى المؤسسات هذه الأيام إلى تحويل أعمالها إلى أعمال إلكترونية، ولكن يعيقها التنوع الكبير في البنية التحتية في داخل المؤسسة نفسها وفي الحوسبة السحابية والتطبيقات. يحل دوكر هذه المشكلة بتوفير منصة حاويات تساعد على تحويل الخدمات الصغيرة والتطبيقات التقليدية المبنية لويندوز ولينكس والخوادم الكبيرة إلى سلسلة إمداد مؤتمتة وآمنة. إنّ دوكر أداة تطوير برمجيات وتقنية حوسبة ظاهرية تسهِّل تطوير ونشر وإدارة التطبيقات باستخدام حاويات. والحاويات هي حزم تنفيذية خفيفة وقائمة بذاتها لتطبيق ما، تحوي كل المكتبات وملفات الإمداد والاعتماديات والأجزاء الأخرى الضرورية ليعمل التطبيق. وبعبارة أخرى، فإنّ التطبيقات تعمل بنفس الطريقة بغضّ النظر عن مكانها أو نوع الجهاز الذي تعمل عليه، وذلك لأن الحاوية توفّر بيئة التطبيق طوال دورة حياة البرنامج. وبما أنّ الحاويات معزولة، فأنها توفر أمنًا إضافيًّا، مما يسمح لتشغيل أكثر من حاوية على نفس الجهاز في نفس الوقت. إضافة إلى ذلك، فهذه الحاويات خفيفة لأنها لا تتطلّب حملًا إضافيًّا كالأجهزة الافتراضية. تشغّل الأجهزة الافتراضية أنظمة مستضافة (كما في حالة VMWare و VirtualBox)، أما الحاويات فتعمل ضمن نواة النظام المضيف مباشرة دون الحاجة إلى نظام ضيف. تتميّز الحاويات عن الأجهزة الافتراضية بما يلي: تحتاج موارد أقل لإدارتها. حجم نسخ احتياطيّة فوريّة (snapshots) أصغر. أسرع في عمل نسخ معدّلة للتطبيقات. تحديثات أمنية أقل وأبسط. كتابة شيفرات أقلّ لنقل وترحيل ورفع العمل. ما هي الأجهزة الافتراضية؟ أما عن الأجهزة الافتراضية، فتُستَخدَم لتنفيذ مهام قد تكون خطرة لو تم تنفيذها على النظام المضيف. الأجهزة الافتراضية معزولة عن بقية النظام، ولا يمكن للنظام الضيف أن يعبث بالجهاز المضيف. ولهذا، فبعض المهام - كالوصول إلى ملفات مصابة بفيروسات، واختبار أنظمة التشغيل - تُستخدَم معها الأجهزة الافتراضية. يمكننا تعريف الجهاز الافتراضيّ كما يلي: الجهاز الافتراضيّ هو ملف أو برمجيّة حاسوب يُشار إليها عادة بـ"الضيف" (guest) تُنشَأ في داخل بيئة حاسوبيّة أخرى تُسمّى "المضيف". باستطاعة الجهاز الافتراضيّ تنفيذ مهام كتشغيل التطبيقات أو البرامج كحاسوبٍ مستقِلّ، مما يجعله بيئة مثاليّة لتجربة أنظمة تشغيل أخرى، كالإصدارات التجريبيّة، وعمل نسخ احتياطيّة لأنظمة التشغيل، وتشغيل تطبيقات وبرمجيات. ويمكن للنظام المضيف أن يحوي عددًا من الأجهزة الافتراضية، وأن تعمل كلّها أو بعضها في نفس الوقت. ومن الملفات التي يتكوّن منها الجهاز الافتراضيّ: ملفات التقارير، وإعدادات الذاكرة، وملف القرص الصلب الافتراضيّ، وملف الإعدادات. ومن المجالات الأخرى التي تحتاج إلى أجهزة افتراضيّة الخوادم؛ حيث يمكن تقسيم خادم حقيقيّ إلى عدد من الخوادم الافتراضيّة المنفصلة والمعزولة عن بعضها، ممّا يسمح لهذه الخوادم الافتراضيّة أن تعمل بأنظمة تشغيل خاصة بها. ويوفِّر كلّ جهاز افتراضيّ عتاده الافتراضيّ، كالمُعالِج، والذاكرة، وواجهات الشبكة، والأقراص الصلبة، وأجهزة أخرى. عمومًا، تقسَّم الأجهزة الافتراضيّة إلى فئتين حسب استخدامها: أجهزة افتراضيّة على مستوى النظام: وهي منصّات تسمح بوجود عدد من الأجهزة الافتراضيّة يعمل كلّ منها بنسخة نظام تشغيل خاصّة به وتتشارك كلها في موارد الجهاز المضيف. وتوفِّر الطبقة البرمجيّة التي تشغّل الأجهزة الافتراضيّة من هذا النوع (والمسماة Hypervisor) التقنيات المتعلقة بتنفيذ الأجهزة الافتراضيّة. وتُنفَّذ هذه الطبقة فوق نظام التشغيل المضيف أو على العتاد مباشرة. أجهزة افتراضية على مستوى الخدمات: تتيح هذه الأجهزة بيئة برمجة مستقلّة. وتُصمَّم خدمة الجهاز الافتراضيّ لإخفاء المعلومات المتعلّقة بالعتاد ونظام التشغيل وتسمح للبرنامج بالعمل بنفس الطريقة في كلّ منصّة من هذا النوع. وعلى الرغم من أن تشغيل عدد من الأجهزة الافتراضيّة يبدو للوهلة الأولى استغلالًا جيّدًا للموارد، إلّا أنّه يؤدي إلى أداء سيء؛ إذ سيكون لكلّ نظام ضيف نواته ومجموعة مكتباته واعتمادياته، مما سيشغل قدرًا كبيرًا من موارد النظام. ومن العيوب الأخرى للأجهزة الافتراضيّة قلّة أداء برمجية مشرف الجهاز الافتراضيّ (Hypervisor) موازنة بالعتاج الحقيقيّ، وكذلك المدة الطويلة التي يحتاجها ليقلع النظام ويكون جاهزًا للعمل. يتغلّب مفهوم الحاويات -بما في ذلك منصّة دوكر- على هذه العقبات. الموازنة فيما يلي الاختلافات المهمّة بين دوكر والأجهزة الافتراضيّة. 1. المعمارية ودعم أنظمة التشغيل الاختلاف الرئيسي بين دوكر والأجهزة الافتراضيّة يكمن في المعمارية، كما هو موضّح في ما يلي. في حال الأجهزة الافتراضيّة، لدينا نظام تشغيل مضيف، ولدينا نظام تشغيل ضيف في كلّ جهاز افتراضيّ، ويمكن ان يكون نظام التشغيل الضيف أيّ نظام تشغيل - مثل ويندوز أو لينكس - بغض النظر عن النظام المضيف. أما دوكر فيستضيف البرمجيات على نفس النظام المضيف. مشاركة النظام المضيف بين الحاويات يجعلها خفيفة وسريعة عند تشغيلها. وتعدّ حاويات دوكر مناسبة لتشغيل عدد من التطبيقات على نواة نظام تشغيل واحدة؛ أما الأجهزة الافتراضية فهي ضروريّة إذا كان التطبيق أو الخدمة بحاجة إلى نظام تشغيل مختلف. 2. الأمن الأجهزة الافتراضيّة قائمة بذاتها، ولها نواتها وخصائصها المتعلقة بالأمن. ولهذا، تُستخدَم الأجهزة الافتراضيّة لتشغيل التطبيقات التي تحتاج إلى صلاحيات وأمان أكثر. أما بالنسبة لدوكر، فلا يُنصح بإعطاء صلاحيات عُليا للتطبيقات أو تشغيلها بصلاحيات المسؤول أو الجذر، وذلك لأنّ هذه الحاويات تتشارك مع النظام المضيف نواته؛ حيث يمكن لتقنية الحاويات الوصول إلى الأنظمة التابعة للنواة؛ مما يعني أن وجود تطبيق واحد مُصاب ببرمجية خبيثة يمكن أن يؤدّي إلى اختراق النظام المستضيف بأكمله. 3. إمكانية النقل الأجهزة الافتراضيّة معزولة عن النظام الذي تعمل عليه، ولهذا فهي لا تنتقل إلى أنظمة أخرى بدون حدوث مشكلات تتعلق بالتوافقيّة. ولهذا، إذا كان من الضروريّ اختبار التطبيق على منصات مختلفة في مرحلة التطوير، فيجب أخذ دوكر بالحسبان في هذه الحالة. إنّ حزم حاويات دوكر تحوي كل ما تحتاجه، ويمكنها تشغيل التطبيقات في أيّ بيئة، وبما أنها لا تحتاج إلى نظام تشغيل ضيف، فيمكن نقلها بسهولة إلى منصات مختلفة. كذلك، يمكن نشر حاويات دوكر في الخوادم، وذلك لأنها خفيفة، ويمكن تشغيلها وإيقافها في وقت أقلّ بكثير من الأجهزة الافتراضيّة. 4. الأداء تحتاج الأجهزة الافتراضيّة إلى موارد أكثر من حاويات دوكر، فهي بحاجة إلى تحميل نظام تشغيل بأكمله عند بدئها. أما حاويات دوكر فهي ذات معمارية خفيفة ولا تحتاج موارد كثيرة كما في الأجهزة الافتراضيّة. في حال الأجهزة الافتراضيّة تكون الموارد - بما فيها المعالج والذاكرة والدخل/الخرج - ثابتة لا تتغير، على خلاف الحاويات، والتي يزداد استخدام الموارد فيها حسب الحمل أو كمية البيانات المارّة. توسعة واستنساخ الحاويات بسيط وسهل مقارنة بالأجهزة الافتراضيّة، حيث لا تحتاج هذه الحاويات إلى تثبيت أنظمة تشغيل فيها. في ما يلي بعض الاختلافات الأخرى بين الاثنين، عدا عن الاختلافات الرئيسيّة: ... دوكر الأجهزة الافتراضيّة وقت الإقلاع تُقلِع في ثوانٍ قليلة يستغرق تشغيل الجهاز الافتراضي بضع دقائق تعمل على يستفيد دوكر من محرّك التنفيذ (excution engine) تستخدم مشرف الأجهزة الافتراضيّة (hypervisor) كفاءتها في استخدام الذاكرة تحتاج ذاكرة قليلة وذلك لعدم حاجتها إلى جهاز افتراضيّ تحتاج إلى تحميل نظام تشغيل كامل قبل أن تبدأ التطبيق، ولهذا فهي أقل كفاءة من هذه الناحية. العزل معرّضة لاستغلالها بطريقة سيئة، وذلك لعدم وجود احتياطات لأنظمة العزل إمكانيّة التعارض بينها منخفضة بسبب كفاءة آليّة العزل فيها النشر نشرها سهل، حيث يمكن استخدام نسخة واحدة في حاوية على كل المنصات النشر يأخذ وقتًا أطول، وذلك لوجود نماذج منفصلة مسؤولة عن التنفيذ الاستخدام لدى دوكر آليّة استخدام مركّبة تتكون من أدوات تديرها دوكر وأخرى من أطراف خارجيّة الأدوات سهلة وأبسط في الاستخدام table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } أيّ الخيارين أفضل؟ لا يمكن موازنة دوكر بالأجهزة الافتراضيّة بعدالة، إذ صُمِّمت كلّ منها لاستخدامات مختلفة. لا شكّ بأنّ دوكر ينتشر بقوّة هذه الأيّام، ولكن لا يمكنه أن يحلّ محلّ الأجهزة الافتراضيّة. وعلى الرغم من أنّ دوكر يزداد شعبيّة، إلّا انّ الأجهزة الافتراضيّة خيار أفضل في حالات معيّنة. تُعدّ الأجهزة الافتراضيّة خيارًا مناسبًا في الإصدارات النهائيّة، وهي أفضل من حاويات دوكر في هذه الحالة، حيث تعمل هذه الأجهزة الافتراضيّة بنظام تشغيلها الخاص دون أن تشكّل خطرًا على الحاسوب المضيف. ولكن إذا كانت التطبيقات بحاجة إلى اختبار، فالخيار الأفضل هو دوكر، إذ يقدّم منصات أنظمة تشغيل مختلفة يمكن استخدامها لعمل اختبارات كثيرة للتطبيق أو البرنامج. إضافة إلى ذلك، تستخدم حاويات دوكر محرّك دوكر (docker-engine) بدلًا من استخدام مشرف (hypervisor) كالذي تستخدمه الأجهزة الافتراضيّة. وبما أنّ النواة المضيفة مشتركة، فإنّ استخدام محرك دوكر يجعل الحاويات صغيرة ومعزولة ومتوافقة وعالية الأداء وسريعة الاستجابة. لحاويات دوكر عبء اقلّ، حيث أنها متوافقة بتشارك نفس النواة ومكتبات تطبيقات. تستفيد المؤسسات من خليط من الاثنين غالبًا، حيث يعتمد الاختيار في كلّ حالة على نوع الحمل الذي تحتاجه المؤسسة. لا تعتمد كثير من المؤسسات على الأجهزة الافتراضيّة كخيارها الرئيسيّ، وتفضّل الانتقال إلى استخدام الحاويات، حيث انّ عمليّة النشر تكون طويلة وتأخذ وقتًا، وتشغيل خدمات مصغّرة من التحديات الكبيرة التي تنشأ منها. على الرغم من هذا، ما زالت هناك شركات تفضّل الأجهزة الافتراضيّة على دوكر، أما الشركات التي تستخدم خدمات أمن مخصصة للشركات لبنيتها التحتيّة تفضل الاستفادة من دوكر. خلاصة القول أن الحاويات ودوكر ليست في صراع مع الأجهزة الافتراضيّة، حيث تكمل كلّ منهما الأخرى في أعمال واستخدامات مختلفة. تُنشأ الأجهزة الافتراضيّة للتطبيقات التي عادة تكون ثابتة ولا تتغير كثيرًا، أمّا منصّة دوكر فهي مصمّمة لتكون مرنة أكثر بحيث يمكن تحديث هذه الحاويات بسهولة وباستمرار. هل دوكر مجرد "موضة"؟ أم أنّه سيحلّ محلّ الأجهزة الافتراضيّة؟ هل لديك ما تشاركنا به؟ شاركنا برأيك في التعليقات. ترجمة -وبتصرف- للمقال Docker vs. Virtual Machines: Differences You Should Know لصاحبه Simran Arora
  7. تعرفنا في الدرسين الماضيين عن مفهوم حاويات لينكس (LXC) ومبدأ عملها ثم شرعنا في كيفية البدء في استعمالها. سنعرج في هذا الدرس إلى كيفية استغلال مختلف نقاط ومراحل دورة حياة حاويات لينكس (LXC) لإدراج بعض من الإضافات (hooks) التي تقوم بإجراء مهمة ما. إضافات إدارة دورة التشغيل بدءًا من أوبنتو 12.10، أصبح من الممكن تعريف إضافات (hooks) تُنفَّذ عند نقاط محددة من دورة تشغيل الحاوية: الإضافات التي تحدث قبل التشغيل تُنفَّذ من مجال أسماء المضيف قبل أن تُنشَأ طرفيات أو نقاط وصل الحاويات؛ إذا أُجري أي وصل في هذه الفترة، فيجب أن يُنظَّف في إضافة تحدث بعد إيقاف التشغيل. الإضافات التي تحدث قبل الوصل تُنفَّذ في مجال أسماء الحاوية، لكن قبل أن يوصل جذر نظام الملفات؛ سينظف أي وصل لنظام الملفات في هذه الفترة تلقائيًا عند إيقاف تشغيل الحاوية. إضافات الوصل هي إضافات تنفذ بعد وصل أنظمة ملفات الحاوية، لكن قبل أن تُنفِّذ الحاوية pivot_root لتغيير جذر نظام ملفاتها. الإضافات التي تحدث بعد إيقاف التشغيل ستنفَّذ بعد إيقاف تشغيل الحاوية. إذا أعادت أيّة إضافة خطأً، فسيلغى تشغيل الحاوية، لكن أي إضافة تحدث بعد إيقاف التشغيل ستنفَّذ، ستُسجَّل أيّة مخرجات تولد من السكربت بأولوية التنقيح (debug). رجاءً راجع صفحة دليل lxc.container.conf لصيغة ملف الضبط التي سيحدد الإضافات؛ يمكن أن تأتي بعض أمثلة الإضافات في الحزمة lxc لتخدم كمثال حول طريقة كتابة إحدى تلك الإضافات. سطر الأوامر لدى الحاويات عدد مضبوط من «أسطر الأوامر» (consoles)؛ أحدها موجودٌ دائمًا في ‎/dev/console؛ الذي يظهر في الطرفية عندما تُشغِّل lxc-start ما لم تحدد الخيار ‎-d؛ يمكن إعادة توجيه ناتج خرج ‎/dev/console إلى ملف باستخدام ‎-c console-file في الأمر lxc-start؛ يمكن تحديد عدد إضافي من أسطر الأوامر باستخدام المتغير lxc.tty المضبوط عادةً إلى 4؛ يمكن أن تظهر أسطر الأوامر تلك في ‎/dev/ttyN (حيث N أكبر أو تساوي 1، وأصغر أو تساوي 4)؛ ولتسجيل الدخول إلى console 3 من المضيف، فنفِّذ الأمر: sudo lxc-console -n container -t 3 إذا لم تحدد الخيار ‎-t N، فسيتم اختيار سطر أوامر غير مُستخدَم؛ للخروج منه، استخدام عبارة الخروج Ctrl-a q؛ لاحظ أن عبارة الخروج لا تعمل في سطر الأوامر الناتج عن lxc-start دون الخيار ‎-d. استكشاف الأخطاء التسجيل إذا حدث شيء ما خاطئ عند تشغيل حاوية، فإن أول خطوة هي الحصول على سجل كامل من LXC: sudo lxc-start -n C1 -l trace -o debug.out هذا سيؤدي إلى جعل lxc يسجل في أعلى درجة إسهاب، التي هي trace، وسيكون ملف التخزين هو ملف باسم «debug.out»، إذا كان الملف debug.out موجودًا مسبقًا، فستُضاف معلومات السجل الجديد إليه. مراقبة حالة الحاوية هنالك أمران متوفران لمراقبة تغيرات حالة الحاوية: lxc-monitor الذي يراقب حاويةً أو أكثر ﻷي تغيرات في الحالة، حيث يأخذ اسم الحاوية مع الخيار ‎-n كالعادة؛ لكن في هذا الحالة، يمكن أن يكون اسم الحاوية تعبيرًا نمطيًا من نمط POSIX للسماح بمراقبة مجموعة من الحاويات؛ يستمر lxc-monitor بالعمل ويعرض تغيرات حالات الحاويات؛ أما lxc-wait فينتظر تغيِّرًا محددًا في الحالة ثم ينتهي تنفيذه؛ على سبيل المثال: sudo lxc-monitor -n cont[0-5]* هذا سيعرض جميع تغيرات الحالة لأي حاوية تطابق التعبير النمطي؛ بينما: sudo lxc-wait -n cont1 -s 'STOPPED|FROZEN' سينتظر إلى أن تتغير حالة الحاوية cont1 إلى STOPPED أو FROZEN ثم ينتهي. الوصل من الممكن في أوبنتو 14.04 الوصل (attach) إلى مجال أسماء حاوية، أبسط طريقة هي تنفيذ: sudo lxc-attach -n C1 الذي سيبدأ صدفة موصولة لمجال الحاوية C1، أو داخل الحاوية؛ آلية عمل الوصل هي معقدة جدًا، مما يسمح بوصل مجموعة فرعية من مجالات أسماء (namespaces) الحاوية ونمط الحماية (security context)، راجع صفحة الدليل لمزيدٍ من المعلومات. درجة إسهاب init في الحاوية إذا أكمل LXC بدء تشغيل الحاوية، لكن فشل إكمال تنفيذ init فيها (على سبيل المثال، لم يُعرَض محث الدخول)، فمن المفيد طلب درجة إسهاب أكبر من عملية init، فلحاوية upstart: sudo lxc-start -n C1 /sbin/init loglevel=debug يمكنك أيضًا بدء تشغيل برامج مختلفة عن init، على سبيل المثال: sudo lxc-start -n C1 /bin/bash sudo lxc-start -n C1 /bin/sleep 100 sudo lxc-start -n C1 /bin/cat /proc/1/status واجهة LXC البرمجية API يمكن الوصول إلى غالبية وظائف LXC عبر واجهة برمجية (API) مُصدَّرة من liblxc التي تكون ارتباطاتها متوفرة لعدة لغات برمجية بما فيها بايثون، و lua، وروبي، و go. ما يلي هو مثال عن استخدام ربط بايثون (المتوفرة في حزمة python3-lxc)، التي تُنشِئ وتبدأ حاوية، ثم تنتظر إلى أن يوقف تشغيلها: # sudo python3 Python 3.2.3 (default, Aug 28 2012, 08:26:03) [GCC 4.7.1 20120814 (prerelease)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import lxc __main__:1: Warning: The python-lxc API isn't yet stable and may change at any p oint in the future. >>> c=lxc.Container("C1") >>> c.create("ubuntu") True >>> c.start() True >>> c.wait("STOPPED") True الحماية يربط مجال الأسماء المعرفات (ids) إلى الموارد؛ لكنه لا يوفر للحاوية أي معرِّف يمكنه أن يشير إلى المورد، لذلك يمكن أن يُحمى المورد؛ وهذا هو أساس بعض الحماية الموفرة لمستخدمي الحاوية؛ على سبيل المثال، مجال أسماء IPC معزول تمامًا؛ لكن مجالات أسماء أخرى فيها بعض «التسربات» (leaks) التي تسمح للامتيازات بأن تُستخرَج بشكل غير ملائم من الحاوية إلى حاوية أخرى، أو إلى المضيف. افتراضيًا، تُشغَّل حاويات LXC بسياسة AppArmor التي تقيّد بعض الأفعال، تفاصيل دمج AppArmor مع LXC موجودة في قسم «AppArmor» في الدرس السابق، الحاويات دون امتيازات تربط الجذر في الحاوية إلى مستخدم دون امتيازات في المضيف، وهذا يمنع الوصول إلى ملفات ‎/proc و ‎/sys التي تمثل موارد المضيف، وغيرها من الملفات المملوكة من الجذر في المضيف. الثغرات في استدعاءات النظام ميزة أساسية من مزايا الحاويات أنها تشارك النواة مع المضيف؛ وهذا يعني أنه إذا حوت النواة على أيّة ثغرات في استدعاءات النظام (system calls)، فيمكن أن تستغلها الحاوية؛ وبعد أن تتحكم حاوية بالنواة، فيمكنها أن تسيطر سيطرةً كاملةً على أي مورد معروف للمضيف! بدءًا من أوبنتو 12.10، يمكن أن تقيَّد الحاوية من مرشِّح seccomp، إن Seccomp هو ميزة جديدة في النواة التي تُرشِّح استدعاءات النظام التي يمكن أن تُستخدَم من المهمة وأولادها؛ بينما يتوقع الوصول إلى إدارة سهلة ومحسنة للسياسة في المستقبل القريب، لكن تحتوي السياسة الحالية على قائمة بيضاء بسيطة لأرقام استدعاءات النظام؛ يبدأ ملف السياسة برقم الإصدار (الذي يجب أن يكون 1) في أول سطر ونوع السياسة (الذي يجب أن يكون whitelist) في ثاني سطر؛ وتُلحَق بقائمة أرقام، كل رقم في سطر. سنحتاج عادةً لتشغيل حاوية بتوزيعة كاملة إلى عدد كبير من استدعاءات النظام؛ لكن لحاويات البرامج، يمكن أن نقلل عدد استدعاءات النظام المتوفرة إلى رقم قليل؛ وحتى للحاويات التي تشغل توزيعات كاملة يمكن الحصول على فوائد أمنية إذا حذفت -على سبيل المثال- استدعاءات النظام المتوافقة مع 32 بت في حاوية 64 بت؛ راجع صفحة دليل lxc.container.conf للمزيد من التفاصيل حول كيفية ضبط الحاوية لتستخدم seccomp؛ لن تُحمَّل افتراضيًا سياسة seccomp. مصادر كتاب «Secure Containers Cookbook» يشرح كيفية استخدام أنماط الحماية لجعل الحاويات أكثر أمانًا. مشروع LXC مُستضاف في linuxcontainers.org. مشاكل LXC الأمنية مذكورة ومناقشة في صفحة وكي «LXC Security». ترجمة -وبتصرف- للمقال Ubuntu Server Guide: LXC.
  8. تعرفنا في الدرس الماضي على مفهوم حاويات لينكس (LXC)، مبدأ عملها وكيفية تثبيتها، سنشرع في هذا الدرس إلى كيفية بدء تشغيلها واستعمالها. لا يملك LXC عفريتًا (daemon) يعمل طوال الوقت، لكنه يملك مهام upstart: المهمة ‎/etc/init/lxc-net.conf: هي مهمة اختيارية تعمل فقط إذا حَدَّد الملف ‎/etc/default/lxc الخاصية USE_LXC_BRIDGE (قيمتها هي true افتراضيًا)؛ حيث تهيِّء جسر NAT لكي تستخدمه الحاويات. المهمة ‎/etc/init/lxc.conf: تعمل إذا كانت الخاصية LXC_AUTO (قيمتها true افتراضيًا) مضبوطة إلى true في ‎/etc/default/lxc؛ حيث تبحث عن القيود في المجلد ‎/etc/lxc/auto‎/‎ حيث توجد وصلات رمزية إلى ملفات الضبط للحاويات التي يجب أن تُشغَّل في وقت الإقلاع. المهمة ‎/etc/init/lxc-instance.conf: تُستخدَم من ‎/etc/init/lxc.conf للبدء التلقائي لتشغيل حاوية. التخزين يدعم LXC عدّة أنماط من التخزين لجذر نظام ملفات الحاوية؛ افتراضيًا يكون مجلدًا بسيطًا، لأنه لا يتطلب أي ضبط مسبق للمضيف طالما أن نظام الملفات فيه مساحة تخزينية كافية؛ وهو لا يتطلب أيضًا امتيازات الجذر لإنشاء المخزن، لذلك سيكون ملائمًا للاستخدام دون امتيازات؛ جذر نظام الملفات للاستخدام مع امتيازات موجود افتراضيًا في ‎/var/lib/lxc/C1/rootfs، بينما جذر نظام الملفات للحاويات التي تعمل دون امتيازات يكون في ‎~/.local/share/lxc/C1/rootfs، إذا حُدِّد lxcpath خاص في lxc.system.com، فإن جذر نظام ملفات الحاوية سيكون موجودًا في ‎$lxcpath/C1/rootfs. نسخة snapshot باسم C2 لحاوية C1 التي تُخزَّن في مجلد ستصبح حاوية overlayfs، بجذر نظام ملفات هو overlayfs:/var/lib/lxc/C1/rootfs:/var/lib/lxc/C2/delta0، أنواع التخزين الأخرى تتضمن loop، و btrfs، و LVM، و zfs. حاوية تعتمد على تخزين btrfs تبدو عمومًا مثل حاوية تعتمد على التخزين في مجلد، ويكون جذر نظام الملفات في نفس المكان؛ لكن جذر نظام الملفات يحتوي على حجم فرعي (subvolume)، لذلك تكون نسخة snapshot مُنشَأة باستخدام نسخة snapshot لحجم فرعي. جذر نظام الملفات لحاوية تستخدم LVM يمكن أن يكون أي حجم منطقي منفصل؛ اسم مجموعة الحجوم الافتراضي يمكن أن يُحدَّد في ملف lxc.conf؛ ويُضبَط نوع وحجم نظام الملفات لكل حاوية باستخدام lxc-create. جذر نظام الملفات لحاوية تستخدم zfs هو نظام ملفات zfs منفصل، وموصول في المكان التقليدي ‎/var/lib ‎/lxc/C1/rootfs، يمكن تحديد zfsroot باستخدام lxc-create، ويمكن تحديد قيمة افتراضية في ملف lxc.system.conf. المزيد من المعلومات حول إنشاء الحاويات بمختلف طرائق التخزين يمكن أن توجد في صفحة دليل lxc-create. القوالب يتطلب إنشاء حاوية عادةً إنشاء جذر نظام ملفات للحاوية؛ يفوض الأمر lxc-create هذا العمل إلى القوالب (templates)، التي تكون عادةً خاصة بالتوزيعة؛ قوالب lxc التي تأتي مع lxc يمكن أن توجد في مجلد ‎/usr/share/lxc/templates، بما فيها القوالب لإنشاء أوبنتو، ودبيان، وفيدورا، وأوراكل، وسنتوس، وجنتو بالإضافة لغيرها. إنشاء صور للتوزيعات في أغلب الحالات يتطلب القدرة على إنشاء عقد أجهزة، ويتطلب ذلك أدوات التي ليست متوفرة في بقية التوزيعات، وعادةً يستغرق هذا الأمر وقتًا طويلًا؛ فلذلك يأتي lxc بقالب download، الذي ينزل صور مبنية مسبقًا للحاويات من خادوم lxc مركزي؛ أهم حالة استخدام هي السماح بإنشاء بسيط لحاويات دون امتيازات بواسطة مستخدمين غير الجذر، الذين لن يستطيعوا ببساطة تشغيل الأمر debootstrap. عند تشغيل lxc-create، فجميع الخيارات التي تأتي بعد «--» تُمرَّر إلى القالب؛ ففي الأمر الآتي، تمرر الخيارات ‎--name و ‎--template و ‎--bdev إلى lxc-create، بينما يمرر الخيار ‎--release إلى القالب: lxc-create --template ubuntu --name c1 --bdev loop -- --release trusty يمكنك الحصول على مساعدة حول الخيارات المدعومة في حاوية معينة بتمرير الخيار ‎--help واسم القالب إلى الأمر lxc-create؛ فعلى سبيل المثال، للحصول على مساعدة حول تنزيل قالب: lxc-create --template download --help البدء التلقائي يدعم LXC تعليم الحاويات لكي تُشغَّل عند إقلاع النظام؛ ففي الإصدارات قبل أوبنتو 14.04، كان يتم ذلك باستخدام وصلات رمزية في المجلد ‎/etc/lxc/auto؛ وبدءًا من أوبنتو 14.04، يتم ذلك عبر ملفات ضبط الحاوية؛ القيد: lxc.start.auto = 1 lxc.start.delay = 5 يعني أن على الحاوية البدء عند إقلاع النظام ويجب الانتظار 5 ثواني قبل بدء تشغيل الحاوية التالية؛ يدعم LXC أيضًا ترتيب وتجميع الحاويات، وأيضًا إعادة الإقلاع وإيقاف التشغيل عبر مجموعات autostart؛ راجع صفحات دليل lxc-autostart و lxc-container.conf للمزيد من المعلومات. AppArmor يأتي LXC مع ملف ضبط AppArmor مهمته هي حماية المضيف من الإساءة العرضية للامتيازات داخل الحاوية؛ على سبيل المثال، لن تكون الحاوية قادرةً على الكتابة إلى ‎/proc/sysrq-trigger أو أغلبية ملفات ‎/sys. الملف usr.bin.lxc-start يدخل حيز التنفيذ عند تشغيل lxc-start؛ يمنع ملف الضبط lxc-start من وصل أنظمة ملفات جديدة خارج نظام ملفات الجذر الخاص بالحاوية؛ قبل تنفيذ init للحاوية، فإن LXC يطلب تبديلًا لملف ضبط الحاوية؛ افتراضيًا، هذا الضبط هو السياسة lxc-container-default المعرَّفة في ملف الضبط ‎/etc/apparmor.d/lxc/lxc-default. يمنع هذا الضبط الحاوية من الوصول إلى مسارات خطرة، ومن وصل أغلبية أنظمة الملفات. لا يمكن تقييد البرامج في الحاوية أكثر من ذلك؛ فعلى سبيل المثال، خادوم MySQL الذي يعمل ضمن نطاق الحاوية (مما يحمي المضيف) لا يمكن أن يدخل في نطاق ملف ضبط MySQL (لحماية الحاوية). لا يدخل lxc-execute ضمن سلطة AppArmor، لكن الحاوية التي يُنشِئها (spawn) ستكون مقيدةً. تعديل سياسات الحاوية إذا وجدت أن lxc-start لا يعمل بسبب تقييد في الوصول من سياسة AppArmor، فيمكنك تعطيل ملف ضبط lxc-start بتنفيذ: sudo apparmor_parser -R /etc/apparmor.d/usr.bin.lxc-start sudo ln -s /etc/apparmor.d/usr.bin.lxc-start /etc/apparmor.d/disabled/ هذا سيجعل lxc-start يعمل دون قيود، لكن ستبقى الحدود موجودةً للحاوية نفسها، وإذا أردت إزالة التقييد عن الحاوية، فعليك بالإضافة إلى تعطيل ملف الضبط usr.bin.lxc-start أن تضيف السطر: lxc.aa_profile = unconfined إلى ملف ضبط الحاوية. يأتي LXC مع سياسات بديلة للحاويات، فإذا أردت إنشاء حاويات داخل حاويات (تشعب)، فعليك استخدام ملف الضبط lxc-container-default-with-nasting بإضافة السطر الآتي إلى ملف ضبط الحاوية: lxc.aa_profile = lxc-container-default-with-nesting إذا أردت استخدام libvirt داخل الحاويات، فستحتاج إلى تعديل تلك السياسة (المعرفة في ‎‎/etc/apparmor.d/lxc/lxc-default-with-nasting) وإزالة التعليق عن السطر الآتي: mount fstype=cgroup -> /sys/fs/cgroup/**, ثم أعد تحميل السياسة. لاحظ أن سياسة التشعب للحاويات ذات الامتيازات هي أقل أمانًا من السياسة الافتراضية، حيث تسمح للحاويات بإعادة وصل ‎/sys و ‎/proc في أمكان غير قياسية، مما يتجاوز سياسة AppArmor؛ لا تملك الحاويات دون امتيازات هذا التأثير الجانبي، ﻷن جذر الحاوية لا يمكنه الكتابة إلى ملفات proc و sys المملوكة من الجذر. إذا أردت تشغيل الحاوية بملف ضبط مخصص، فبإمكانك إنشاء ملف ضبط في ‎/etc/apparmor.d/lxc، ويجب أن يبدأ اسمه بالكلمة lxc-‎ لكي يُسمَح لبرنامج lxc-start بالانتقال إليه؛ ملف lxc-default يتضمن إعادة استعمال الملف المجرد ‎/etc/apparmor.d/abstraction/lxc/container-base؛ طريقة سهلة لإنشاء ملف ضبط جديد هي فعل المثل، ثم إضافة الأذونات الإضافية في نهاية السياسة. حَمِّل الضبط الجديد بعد إنشاءه كما يلي: sudo apparmor_parser -r /etc/apparmor.d/lxc-containers سيُحمَّل هذا الضبط تلقائيًا بعد إعادة الإقلاع، ﻷنه يُقرَأ من الملف ‎/etc/apparmor.d/lxc-containers؛ وفي النهاية ولجعل الحاوية CN تستخدم ملف الضبط الجديد lxc-CN-profile، فأضف السطر الآتي إلى ملف الضبط: lxc.aa_profile = lxc-CN-profile مجموعات التحكم إن مجموعات التحكم (cgroups) هي ميزة من ميزات النواة توفر تجميع للمهام تجميعًا هيكليًا، وإسناد وتحديد الموارد لكل مجموعة تحكم؛ تُستخدَم في الحاويات للحد من الوصول إلى الأجهزة الكتلية أو المحرفية (block or character devices) وتجمِّد عمل الحاويات؛ يمكن استعمالها أيضًا لتحديد استخدام الذاكرة وإيقاف الدخل أو الخرج، وضمانة استخدام أصغري للمعالج، والسماح للحاوية بالوصول إلى معالجات محددة. افتراضيًا، سيُسند للحاوية CN ذات امتيازات مجموعةُ تحكمٍ باسم ‎/lxc/CN؛ وفي حال حدوث تضارب بالاسم (الذي قد يحدث عند استخدام lxcpaths مخصصة)، فستُضاف لاحقة «‎-n» حيث n هو رقم صحيح يبدأ من الصفر، ويُسنَد إلى اسم مجموعة التحكم. افتراضيًا، سيُسند للحاوية CN دون امتيازات مجموعة تحكم باسم CN في مجموعة التحكم الخاصة بالمهمة التي بدأت الحاوية، على سبيل المثال ‎/usr/1000.user/1.session/CN سيُمنَح جذر الحاوية ملكية المجموعة للمجلد (لكن ليس جميع الملفات)، وهذا ما سيسمح بإنشاء مجموعات تحكم فرعية. وفي أوبنتو 14.04، يستخدم LXC مدير مجموعات التحكم cgmanager لإدارة مجموعات التحكم؛ يستقبل مدير مجموعات التحكم طلبات D-Bus عبر مقبس يونكس ‎/sys/fs/cgroup/cgmanager/sock؛ يجب أن يُضاف السطر الآتي لاستخدام آمن للحاويات المتشعبة: lxc.mount.auto = cgroup إلى ملف ضبط الحاوية، مما يصل المجلد ‎/sys/fs/cgroup/cgmanager وصلًا ترابطيًا (bind-mounted) إلى الحاوية؛ ويجب على الحاوية في المقابل تشغيل وسيط إدارة مجموعات التحكم (ويتم ذلك افتراضيًا إذا كانت الحزمة cgmanager مثبتةً على الحاوية) الذي سينقل المجلد ‎/sys/fs/cgroup/cgmanager إلى ‎/sys/fs/cgroup‎/cgmanager.lower ثم سيبدأ الاستماع إلى الطلبات للوسيط على مقبسه ‎/sys/fs/cgroup ‎/cgmanager‎/sock؛ سيتأكد مدير مجموعات التحكم في المضيف أن الحاويات المتشعبة لن تستطيع «الهروب» من مجموعات التحكم المُسندَة إليها أو إنشاء طلبات غير مصرح لها بها. الاستنساخ للتزويد السريع بالحاويات، ربما تريد تخصيص حاوية تبعًا لحاجاتك ثم تُنشِئ عدَّة نسِخٍ منها؛ ويمكن فعل ذلك بالبرنامج lxc-clone. الاستنساخ إما أن يكون عبر snapshots أو بنسخ حاوية أخرى؛ فالنسخ هو إنشاء حاوية جديدة منسوخة من الأصلية، وتأخذ مساحة تخزينية مثل الحاوية الأصلية؛ أما snapshot فإنها تستخدم قدرة آلية التخزين على إنشاء snapshots لإنشاء حاوية النسخ-عند-الكتابة (copy-on-write) تُشير إلى الحاوية الأولى؛ يمكن إنشاء snapshots للحاويات المخزنة في btrfs، و LVM، و zfs، وتلك التي تكون مخزنة في مجلدات؛ حيث كل آلية تخزين لها خصوصياتها؛ فمثلًا، حاويات LVM التي ليست thinpool-provisioned لا تدعم إنشاء snapshots من snapshots؛ ولا يمكن حذف حاويات zfs مع snapshots قبل أن تُطلَق (release) جميع snapshots؛ ويجب أن يُخطط جيدًا لحاويات LVM فقد لا يدعم نظام الملفات أن يزيد حجمه. لا يعاني btrfs من تلك السلبيات، لكنه يعاني من أداء fsync منخفض يسبب جعل dpkg و apt-get أبطئ. تُنشَأ snapshots من الحاويات المخزنة في مجلدات عبر نظام الملفات؛ فمثلًا يكون لحاوية ذات امتيازات C1 جذر نظام ملفات في ‎/var/lib/lxc/C1/rootfs، وستبدأ نسخة snapshot للحاوية C1 باسم C2 بجذر نظام الملفات للحاوية C1 موصولًا للقراءة فقط في ‎/var/lib/lxc/C2/delta0؛ كل ما يهم في هذه الحالة أنه لا يفترض أن تعمل أو تحذف الحاوية C1 أثناء عمل C2؛ من المستحسن اعتبار الحاوية C1 هي حاوية أساسية واستخدام نسخة snapshot لها فقط. لنفترض أن لدينا حاوية باسم C1، فيمكن إنشاء نسخة منها باستخدام الأمر: sudo lxc-clone -o C1 -n C2 يمكن إنشاء snapshot باستخدام: sudo lxc-clone -s -o C1 -n C2 راجع صفحة دليل lxc-clone لمزيد من المعلومات. Snapshots LXC يدعم snapshots لتسهيل دعم نسخ snapshot لتطوير تكراري للحاوية؛ فعندما تعمل على حاوية C1 -وقبل إنشاء تغيير خطير وصعب العكس- يمكنك إنشاء snapshot: sudo lxc-snapshot -n C1 التي هي نسخة snapshot باسم «snap0» في مجلد ‎/var/lib/lxcsnaps أو ‎$HOME/.local ‎/share/lxcsnaps، النسخة الثانية ستُسمى «snap1» وهكذا؛ يمكن عرض النسخ الموجودة حاليًا باستخدام الأمر lxc-snapshot -L -n C1، ويمكن أن تُستعاد نسخة snapshot وتمحى حاوية C1 الحالية باستخدام الأمر lxc-snapshot -r snap1 -n C1، وبعد تنفيذ أمر الاستعادة، فستبقى النسخة snap1 موجودةً. تُدعَم snapshots لحاويات btrfs، و lvm، وzfs، و overlayfs؛ إذا استدعي الأمر lxc-snapshot على حاوية تُخزَّن في مجلد، فسيسجل خطأ وستُنشَأ نسخة copy-clone؛ وسبب ذلك أنه لو أنشأ المستخدم نسخة overlayfs snapshot لحاوية تخزن في مجلد، فسينعكس جزء من تغيرات الحاوية الأصلية على نسخة snapshot؛ إذا كنت تريد إنشاء snapshots لحاوية C1 مخزنة في مجلد، فيمكن إنشاء نسخة overlayfs للحاوية C1، ويجب ألّا تلمس C1 بعد ذلك قط، لكن يمكن أن نعدِّل overlayfs وننسخها نسخ snapshots كما نريد، أي: lxc-clone -s -o C1 -n C2 lxc-start -n C2 -d # make some changes lxc-stop -n C2 lxc-snapshot -n C2 lxc-start -n C2 # etc الحاويات العابرة «الحاويات العابرة» (Ephemeral containers) هي حاويات تستخدم لمرة واحدة فقط؛ فليكن لدينا حاوية موجودة مسبقًا باسم C1، فيمكنك إنشاء حاوية عابرة باستخدام: lxc-start-ephemeral -o C1 ستبدأ الحاوية كنسخة snapshot للحاوية C1، وستطبع التعليمات للدخول إلى الحاوية على الطرفية، وستدمر الحاوية العابرة بعد إيقاف التشغيل، راجع صفحة الدليل lxc-start-ephemeral لمزيد من الخيارات. ترجمة -وبتصرف- للمقال Ubuntu Server Guide: LXC.
  9. ubuntu server guide

    الحاويات (containers) هي تقنية أنظمة وهمية خفيفة؛ حيث تجنح لأن تكون شبيهةً بطريقة chroot محسّنة بدلًا من كونها تقنية أنظمة وهمية كاملة مثل Qemu أو VMware؛ لأن كلاهما لا يحاكي العتاد ولأن الحاويات تشارك نفس نظام التشغيل للمضيف؛ لذلك من الأفضل مقارنة الحاويات إلى «نطاقات سولارس» (Solaris zones) أو «سجون BSD» ‏(BSD jails). إن Linux-vserver و OpenVZ هما نسختان من الحاويات لنظام لينُكس مطورتان بشكل منفصل عن بعضهما؛ في الواقع، ظهرت الحاويات نتيجةً للعمل على تطوير وظائف vserver و OpenVZ. هنالك نسختان في «مجال المستخدم» (user-space) للحاويات تستخدمان نفس مزايا النواة؛ تسمح Libvirt باستخدام الحاويات عبر محرك LXC بالاتصال إلى «lxc:///‎»، قد يكون هذا أمرًا ملائمًا لأنها تملك نفس طريقة الاستخدام الموجودة في المحركات الأخرى. النسخة الأخرى المُسماة ببساطة «LXC» هي غير متوافقة مع libvirt؛ لكنها أكثر مرونةً بأدوات أكثر في مجال المستخدم؛ من الممكن التبديل بين النسختين آنفتَيّ الذكر، لكن هنالك بعض الخصوصيات التي قد تسبب ارتباكًا. سنشرح في هذا الدرس حزمة lxc شرحًا رئيسيًا، حيث أن استخدام libvirt-lxc ليس مستحسنًا ﻷنه يفتقر إلى حماية AppArmor لحاويات libvirt-lxc؛ وستكون أسماء الحاويات الموجودة في هذا الفصل هي CN، أو C1، أو C2. التثبيت يمكن تثبيت حزمة lxc باستخدام الأمر: sudo apt-get install lxc سنحتاج إلى تنزيل الاعتماديات المطلوبة والمستحسنة، وضبط جسر الشبكة لكي يستخدمه الحاويات؛ إذا أردت استخدام حاويات دون امتيازات، فربما تحتاج إلى أن تتأكد أن للمستخدمِين امتيازات subuids و subgids، وتريد أن تسمح للمستخدمين بوصل الحاويات إلى جسر؛ راجع القسم «الاستخدام الأساسي دون امتيازات». الاستخدام الأساسي يمكن أن نستخدم LXC بطريقتين مختلفتين، الأولى بامتيازات عبر تنفيذ أوامر lxc بحساب المستخدم الجذر؛ أو دون امتيازات بتنفيذ أوامر lxc بحساب أي مستخدم عدا الجذر (في الواقع، يمكن تشغيل حاويات دون امتيازات بحساب الجذر، لكننا لن نشرح ذلك هاهنا)؛ الحاويات دون امتيازات محدودة أكثر، فمثلًا لن تستطيع إنشاء عقد أجهزة أو تصل أنظمة ملفات كتلية؛ لكنها أقل خطرًا للمضيف، حيث يكون الجذر في الحاوية مربوطًا بحساب غير جذر في المضيف. الاستخدام الأساسي بامتيازات لإنشاء حاوية ذات امتيازات، كل ما عليك فعله هو تنفيذ الأمر: sudo lxc-create --template download --name u1 أو بشكل مختصر: sudo lxc-create -t download -n u1 الذي سيسألك تفاعليًا عن نوع جذر نظام الملفات لكي يُنزَّل، وخصوصًا التوزيعة والإصدارة والمعمارية؛ يمكنك تحديد هذه القيم في سطر الأوامر لإنشاء حاوية دون الإجابة على تلك الأسئلة تفاعليًا: sudo lxc-create -t download -n u1 -- --dist ubuntu --release trusty --arch amd64 أو sudo lxc-create -t download -n u1 -- -d ubuntu -r trusty -a amd64 يمكنك الآن استخدام lxc-ls لعرض قائمة بالحاويات، و lxc-info للحصول على معلومات مفصلة عن حاوية، و lxc-start لبدء و lxc-stop لإيقاف الحاوية؛ بينما يسمح لك الأمران lxc-attach و lxc-console بالدخول إلى حاوية إذا لم يكن الاتصال إليها عبر SSH متاحًا؛ والأمر lxc-destory يحذف الحاوية، بما في ذلك جذر نظام الملفات؛ راجع صفحات الدليل للأوامر السابقة للمزيد من المعلومات؛ أمثلة: sudo lxc-ls --fancy sudo lxc-start --name u1 --daemon sudo lxc-info --name u1 sudo lxc-stop --name u1 sudo lxc-destroy --name u1 مجالات أسماء المستخدم تسمح الحاويات دون امتيازات للمستخدمين بإنشاء وإدارة الحاويات دون الحصول على امتيازات الجذر؛ أساس هذه الميزة هو ما يسمى «مجالات أسماء المستخدم» (user namespaces)، إن مجالات أسماء المستخدم هيكليةٌ، حيث تكون المهام ذات امتيازات في مجال الأسماء الأب قادرة على ربط معرِّفاتها إلى مجالات أسماء الأبناء؛ افتراضيًا، كل مهمة على المضيف تعمل في مجال أسماء مبدئي (initial user namespace)، حيث المجال الكامل لمعرفاتها مربوطٌ مع المجال الكامل؛ يمكن مشاهدة ذلك بالنظر إلى ‎/proc/self/uid_map و ‎/proc/self ‎/gid_map؛ اللذان سيظهران القيمة «‎‎0 0 4294967295‎» عندما يُقرأ من مجال الأسماء المبدئي؛ وفي أوبنتو 14.04، المستخدمون الجدد الذين يُنشؤون يكون لهم افتراضيًا مجال من معرفات المستخدم؛ هذه القائمة من المعرفات المُسنَدة يمكن أن تُشاهد في الملفين ‎/etc/subuid و ‎/etc/subgid؛ انظر إلى صفحات الدليل الموافقة لهم للمزيد من المعلومات؛ ويبدأ subuid و subgid عرفيًا من المعرف 100000 لتجنب التضارب مع مستخدمي النظام. إذا أُنشِئ المستخدم في إصدارة قديمة، فيمكنك منحه مجالًا من المعرفات باستخدام usermod، كما يلي: sudo usermod -v 100000-200000 -w 100000-200000 user1 برنامجا newuidmap و newgidmap هما برنامجا setuid-root في حزمة uidmap، اللذان يُستخدمان داخليًا بواسطة lxc لربط subuids و subgids من المضيف إلى حاوية دون امتيازات؛ ويتأكدان من أن المستخدم يربط المعرفات المصرَّح بها فقط من ضبط المضيف. الاستخدام الأساسي دون امتيازات لإنشاء حاويات دون امتيازات، فإن هنالك خطوات أولية ضرورية؛ حيث تحتاج إلى إنشاء ملف ضبط حاوية افتراضي، مُحدِّدًا ربط المعرفات الذي تريده وضبط الشبكة، بالإضافة إلى ضبط المضيف للسماح لمستخدم دون امتيازات بالارتباط إلى شبكة المضيف؛ يفترض المثال الآتي أنك ربطت معرفات المستخدم والمجموعة ذات المجال 100000 – 165536. mkdir -p ~/.config/lxc echo "lxc.id_map = u 0 100000 65536" > ~/.config/lxc/default.conf echo "lxc.id_map = g 0 100000 65536" >> ~/.config/lxc/default.conf echo "lxc.network.type = veth" >> ~/.config/lxc/default.conf echo "lxc.network.link = lxcbr0" >> ~/.config/lxc/default.conf echo "$USER veth lxcbr0 2" | sudo tee -a /etc/lxc/lxc-usernet بعد ذلك، يمكنك إنشاء حاويات دون امتيازات بنفس طريقة إنشاء حاويات بامتيازات، لكن ببساطة دون sudo: lxc-create -t download -n u1 -- -d ubuntu -r trusty -a amd64 lxc-start -n u1 -d lxc-attach -n u1 lxc-stop -n u1 lxc-destroy -n u1 التشعب لكي نشغِّل حاويات داخل حاويات – الأمر الذي يُشار إليه بتشعّب الحاويات – فإن سطرين يجب أن يوجدا في ملف ضبط الحاوية الأب: lxc.mount.auto = cgroup lxc.aa_profile = lxc-container-default-with-nesting سيسبب السطر الأول بدمج مقبس مدير مجموعات التحكم في الحاوية، لذلك سيكون lxc داخل الحاوية قادرًا على إدارة مجموعات التحكم للحاويات المتشعبة الخاصة به؛ أما السطر الثاني فيسبب تشغيل الحاوية بوضع أكثر سماحيةً بالنسبة إلى AppArmor، مما يسمح للحاوية بإجراء عمليات الوصل اللازمة لبدء تشغيل الحاويات؛ لاحظ أن سياسة AppArmor التي ستُطبَّق أقل أمنًا من السياسة العادية أو سياسة حاوية دون امتيازات؛ راجع القسم «AppArmor» في هذا الدرس القادم لمزيدٍ من المعلومات. الضبط العام تُستخدَم ملفات الضبط الآتية من LXC؛ للاستخدام ذو الامتيازات، فإنها ستتواجد في مجلد ‎/etc/lxc، بينما للاستخدام دون امتيازات فستكون موجودةً في ‎~/.config/lxc. lxc.conf: يُحدِّد اختياريًا القيم البديلة لمختلف خيارات ضبط lxc، بما فيها lxcpath، والضبط الافتراضي، ومجموعات التحكم التي ستُستخدَم، ونمط إنشاء مجموعة تحكم، وإعدادات الواجهات الخلفية لتخزين lvm و zfs. default.conf: يحدد الضبط الذي يجب أن يحتويه كل ملف ضبط للحاويات المُنشأة حديثًا؛ يحتوي هذا الملف عادةً على الأقل على قسم للشبكة؛ ويحتوي على قسم لربط المعرفات للمستخدمين دون امتيازات. lxc-usernet.conf: يحدد كيف يوصل المستخدمون دون امتيازات حاوياتهم إلى شبكة مملوكة من المضيف. الملفان lxc.conf و default.conf موجودان في ‎/etc/lxc و ‎$HOME/.config/lxc؛ بينما الملف lxc-usernet.conf هو ملف لعموم المضيف. افتراضيًا، تقبع الحاويات في مجلد ‎/var/lib/lxc بالنسبة للمستخدم الجذر، و ‎$HOME/.local/share/lxc عدا ذلك؛ يمكن تحديد المسار لجميع أوامر lxc باستخدام المعامل «‎-P|--lxcpath». ضبط الشبكة افتراضيًا، يُنشِئ LXC مجال أسماء شبكي خاص لكل حاوية، الذي يتضمن مجموعة الاتصال الشبكي من الطبقة الثانية (layer 2)، تتصل الحاويات عادةً إلى العالم الخارجي إما بالحصول على بطاقة شبكية فيزيائية، أو عبر نفق veth يُمرَّر إلى الحاوية؛ ينُشِئ LXC جسر NAT، الذي هو lxcbr0 عند إقلاع المضيف؛ والحاويات المُنشَأة باستخدام ملف الضبط الافتراضي سيكون لها بطاقة شبكية veth تكون نهايتها موصولةٌ إلى الجسر lxcbr0، يمكن للبطاقة الشبكية أن تتواجد في مجال أسماء واحد في وقتٍ واحد، لذلك البطاقة الشبكية الفيزيائية المُمررة إلى الحاوية ستكون غير قابلة للاستخدام في المضيف. من الممكن إنشاء حاويات دون مجال أسماء شبكي خاص، ففي هذه الحالة، ستحصل الحاوية على وصول إلى شبكة المضيف مثل أي تطبيق آخر، لاحظ أنه هذا خطير خصوصًا إذا كانت الحاوية تُشغِّل توزيعة تستخدم upstart، مثل أوبنتو، لأن البرامج التي «تتحدث» إلى init، مثل shutdown، سيتحدثون عبر مقبس مجال يونكس مجرد (abstract Unix domain socket) إلى upstart للمضيف، مما سيوقف تشغيل المضيف! لمنح الحاويات في lxcbr0 عنوان IP ثابت بناءً على اسم المضيف، فيمكنك كتابة هذه المدخلات إلى ‎/etc/lxc/dnsmasq.conf: dhcp-host=lxcmail,10.0.3.100 dhcp-host=ttrss,10.0.3.101 إذا كان من المطلوب أن يُسمَح بالوصول إلى الحاوية من الخارج، فهنالك عدِّة طرق للالتفاف على ذلك، إحداها هي استخدام iptables لتمرير منافذ المضيف إلى الحاوية، فمثلًا: iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 587 -j DNAT \ --to-destination 10.0.3.100:587 طريقة أخرى هي إنشاء جسر إلى إلى البطاقة الشبكية للمضيف (راجع درس ضبط الشبكة لمزيدٍ من المعلومات)؛ ثم حدد جسر المضيف في ملف ضبط الحاوية بدلًا من lxcbr0، فمثلًا: lxc.network.type = veth lxc.network.link = br0 في النهاية، يمكنك سؤال LXC ليستخدم macvlan كبطاقة شبكية للحاوية؛ لاحظ أن لهذه الطريقة حدود واعتمادًا على الضبط قد لا تتمكن الحاوية من «التحدث» إلى المضيف نفسه، وبالتالي الخياران السابقان أفضل ويُستخدمان أكثر. هنالك عدِّة طرق لتحديد عنوان IP للحاوية، فأولًا، يمكنك استخدام lxc-ls --fancy الذي سيطبع عناوين IP لجميع الحاويات التي تعمل؛ أو lxc-info -i -H -n C1 الذي سيطبع عنوان IP للحاوية C1؛ إذا كان dnsmasq مثبتًا على المضيف، فيمكنك إضافة قيد إلى ‎/etc/dnsmasq.conf كما يلي: server=/lxc/10.0.3.1 بعد أن يستبين dnsmasq عنوان C1.lxc محليًا، فيمكنك تنفيذ: ping C1 ssh C1 للمزيد من المعلومات، راجع صفحة دليل lxc.conf ومثال ضبط الشبكة في ‎/usr/share/doc/lxc ‎/examples/‎. ترجمة -وبتصرف- للمقال Ubuntu Server Guide: LXC.