أساسيات الحوسبة السحابية
الحاويات والخدمات المصغّرة
ما الذي تحزّمه الحاوية فعلياً، ولماذا يغيّر تقسيم تطبيق متجانس إلى خدمات مصغّرة طريقة شحن الفريق له وتوسيعه، وما الذي يضيفه منسّق مثل Kubernetes حين يفوق عدد الحاويات ما يستطيع بشري إدارته يدوياً.
- اشرح ما الحاوية ولماذا تبدأ أسرع من الجهاز الافتراضي
- صف كيف تُبقي صورة الحاوية بيئة التشغيل متطابقة من جهاز المطوّر إلى بيئة الإنتاج
- ميّز بين التطبيق المتجانس وبنية الخدمات المصغّرة من حيث طريقة النشر والتوسيع
- حدد ما تضيفه إدارة تنسيق الحاويات فوق تشغيل حاويات منفردة يدوياً
- تعرّف على المقايضات التشغيلية التي تفرضها الخدمات المصغّرة مقابل التوسّع والنشر المستقلَّين
الدرس السابق أجاب من يشغّل الكود. هذا الدرس يسأل كيف يُبنى
ترك الدرس السابق سؤال الحوسبة مجاباً: دالة بلا خوادم، أو جهاز افتراضي، أو شيء بينهما يشغّل كودك، ويتولى المزوّد قدراً أكبر أو أصغر من العمل المحيط حسب اختيارك. لا شيء من ذلك يقول أي شيء عن كيفية بناء التطبيق نفسه. تطبيق بدأ كقاعدة كود واحدة كبيرة، نشر واحد، فريق واحد، يواجه نوعاً محدداً من المتاعب مع نموه: إصلاح صغير في تدفق الدفع يعني اختبار وإعادة نشر التطبيق بأكمله، الكتالوج والحسابات وكل شيء، وارتفاع مفاجئ في الزيارات بجزء واحد من التطبيق يجبرك على توسيع التطبيق كله. الحاويات والخدمات المصغّرة فكرتان منفصلتان تحلّان معاً هذه المشكلة بالضبط.
ما الذي تحزّمه الحاوية فعلياً
الحاوية عملية معزولة، مُحزَّمة بكل ما تحتاجه للعمل: كودك، وبيئة تشغيله، وتبعياته، كل ذلك في وحدة واحدة قائمة بذاتها. حزّم تطبيق Node.js في صورة حاوية، وستعمل تلك الصورة بالطريقة نفسها تماماً سواء بدأت على جهاز مطوّر محمول أو خادم اختبار أو عنقود إنتاج، لأن الصورة تحمل بيئة تشغيلها الخاصة بدل الاعتماد على ما يصادف وجوده على المضيف.
FROM node:20-slim
WORKDIR /app
COPY package*.json ./
RUN npm install --production
COPY . .
CMD ["node", "server.js"]
docker build -t checkout-service:1.0 .
docker run -p 3000:3000 checkout-service:1.0
يصف ملف Dockerfile تلك الصورة، ويحزّمها docker build، ويشغّل docker run حاوية منها. وضع درس خدمات الحوسبة الحاويات بالفعل على طيف التحكم مقابل الراحة، تبدأ خلال ثوانٍ بدل دقائق الجهاز الافتراضي، لأن الحاوية تشارك نواة نظام تشغيل المضيف بدل إقلاع نظام تشغيل ضيف كامل خاص بها.
من التطبيق المتجانس إلى الخدمات المصغّرة
التطبيق المتجانس قاعدة كود واحدة، ونشر واحد، وعادة قاعدة بيانات مشتركة واحدة، بغض النظر عن عدد الميزات المتمايزة التي يحتويها. تقسّم بنية الخدمات المصغّرة التطبيق نفسه إلى مجموعة من الخدمات الصغيرة القابلة للنشر باستقلالية، كل واحدة مبنية حول قدرة عمل واحدة (الكتالوج، السلة، الدفع، حسابات المستخدمين)، وتتواصل عبر واجهات برمجة خفيفة بدل استدعاءات دوال داخل العملية نفسها. تمتلك كل خدمة عادة قاعدة بياناتها الخاصة بدل مشاركة واحدة، وهذا بالضبط ما يجعلها قابلة للنشر والتوسيع باستقلالية.
عد إلى سيناريو التخفيضات السريعة. في تطبيق متجانس، يجبرك تضاعف زيارات الدفع 3 مرات على توسيع النشر بأكمله، الكتالوج والحسابات معه، بما أنه لا توجد سوى وحدة نشر واحدة للتوسيع. قسّم التطبيق إلى خدمات مصغّرة، وتتوسّع خدمة الدفع وحدها، بينما يبقى الكتالوج والحسابات كما كانا تماماً، لأن كل واحدة أصبحت الآن قطعة مستقلة قابلة للنشر بذاتها.
المقايضة: استقلالية مقابل تنسيق
لا شيء من هذا مجاني. يقايض تقسيم تطبيق متجانس إلى خدمات مصغّرة بساطة قاعدة الكود الواحدة بمجموعة مشكلات جديدة لا تظهر إلا حين تنفصل الخدمات. استدعاء من الدفع إلى خدمة الحسابات يعبر الآن شبكة بدل استدعاء دالة داخل العملية نفسها، وهذا يعني أنه قد يمهل أو يفشل بطرق لا يفشل بها استدعاء داخلي أبداً. البيانات اللامركزية، كل خدمة بقاعدة بياناتها الخاصة، تعني التخلي عن معاملة واحدة مشتركة عبر الطلب كله لصالح اتساق نهائي بين الخدمات. وطلب عميل واحد يمر عبر 5 خدمات أصعب في التتبّع من طلب يمر عبر واحدة، إذ لم يعد هناك سجل استدعاء واحد تقرؤه. مزيد من الخدمات ليس أفضل تلقائياً؛ إنه مقايضة متعمَّدة للبساطة مقابل الاستقلالية، لا تُثمر إلا حين يملك الفريق الأدوات التشغيلية لإدارتها، وهذا بالضبط ما يغطيه الدرس التالي.
التنسيق: إدارة حاويات أكثر مما يستطيع بشري تتبّعه
شغّل حاوية واحدة يدوياً، ويكفي docker run. شغّل 3 نسخ متماثلة من خدمة الدفع للتكرار، بالإضافة إلى خدمة الكتالوج، بالإضافة إلى خدمة السلة، كل واحدة بنسخها الخاصة، وتتوقف مراقبة كل ذلك يدوياً عن الجدوى بسرعة. يأخذ منسّق حاويات مثل Kubernetes وصفاً تصريحياً لما تريده، ويعمل باستمرار على مطابقة الواقع له.
apiVersion: apps/v1
kind: Deployment
metadata:
name: checkout-service
spec:
replicas: 3
selector:
matchLabels:
app: checkout-service
template:
metadata:
labels:
app: checkout-service
spec:
containers:
- name: checkout
image: checkout-service:2.1
ports:
- containerPort: 8080
سطر replicas: 3 ذاك إعلان، لا أمر لمرة واحدة. إن تعطلت واحدة من النسخ الثلاث، يلاحظ Kubernetes الفارق بين الحالة المُعلَنة والواقع، ويطلق بديلاً تلقائياً، قدرة تُسمى الشفاء الذاتي. يتولى Kubernetes أيضاً اكتشاف الخدمات وتوزيع الحمل عبر تلك النسخ، ويطرح التحديثات تدريجياً بدل دفعة واحدة، فيتوقف الفريق عن مراقبة الحاويات يدوياً ويبدأ بوصف الحالة التي يريدها بدلاً من ذلك.
مفاتيح الاختبار: التقاط الملاءمة في سيناريو
| يقول السيناريو... | يشير إلى |
|---|---|
| "حزّم مرة واحدة، شغّل بالطريقة نفسها في كل مكان" | حاوية |
| "فرق مستقلة تشحن باستقلالية، كل واحدة تملك بياناتها" | خدمات مصغّرة |
| "إعادة تشغيل النسخ المعطوبة تلقائياً، وطرح التحديثات تدريجياً" | تنسيق حاويات (Kubernetes) |
| "قاعدة كود واحدة، نشر واحد، قاعدة بيانات واحدة" | تطبيق متجانس |
إلى أين يقودك هذا
تقسيم تطبيق إلى خدمات مصغّرة وتحزيم كل قطعة كحاوية قراران منفصلان يعزّز أحدهما الآخر: القابلية للنشر المستقل التي تعد بها الخدمات المصغّرة لا تصمد إلا إذا استطاعت كل قطعة فعلاً الشحن والتوسّع بمفردها، والحاوية بالضبط ما يجعل ذلك عملياً. لا شيء من هذا، عمليات البناء، وعمليات الطرح، وعدد القطع المتحركة المتزايد باستمرار، يبقى قابلاً للإدارة يدوياً لوقت طويل. يغطي الدرس التالي الممارسات والأدوات، DevOps والبنية التحتية ككود، التي تُبقيه قابلاً للإدارة.
