خرائط الإعداد (ConfigMaps)
خرائط الإعداد (ConfigMaps)
كل تطبيق يحتاج إلى إعدادات: أسماء مضيفي قواعد البيانات، وعلامات الميزات، وأحجام مجمعات الخيوط، ومستويات السجل، ونطاقات CORS الموثوقة. الطريقة التي تُسلَّم بها هذه الإعدادات إلى التطبيق هي من أكثر قرارات البنية التحتية أثرًا. تضمينها مباشرةً في صورة الحاوية — النهج الساذج — يربط دورة الإصدار بدورة الإعداد. تغيير مستوى السجل يستلزم إعادة البناء وإعادة النشر. والأسوأ من ذلك أنك تنتهي بـ"صور خاصة ببيئة معينة"، مما يُفسد ضمان قابلية نقل الحاويات الأساسي.
يحل Kubernetes هذه المشكلة عبر ConfigMaps: كائن API من الدرجة الأولى يحمل بيانات إعداد غير حساسة على شكل أزواج مفتاح-قيمة أو محتوى ملفات كاملة. تبقى الصورة محايدة للبيئة، بينما يحمل ConfigMap القيم الخاصة بكل بيئة. تعمل الصورة ذاتها في بيئات التطوير والاختبار والإنتاج — ويختلف ConfigMap فحسب. هذا هو مبدأ تطبيق 12-Factor الثالث ("تخزين الإعداد في البيئة") معبَّرًا عنه بشكل أصيل في Kubernetes.
إنشاء ConfigMaps
يمكن إنشاء ConfigMaps بأسلوب أمري (مفيد للنصوص البرمجية والتصحيح السريع) أو بإعلانها كملفات YAML (النهج الملائم للإنتاج، المخزَّن في نظام التحكم في الإصدارات). يجب دائمًا تخزين الملف في Git — فالشكل الأمري مؤقت وغير قابل للتتبع.
الشكل التصريحي YAML هو ما تُخزِّنه في Git وتنشره عبر خط CI الخاص بك. يبدو ملف ConfigMap هكذا:
get configmap في ذلك النطاق قراءته. لا تضع أبدًا بيانات اعتماد في ConfigMap.استهلاك ConfigMaps: متغيرات البيئة
أكثر أنماط الاستهلاك شيوعًا يضخ مفاتيح فردية كمتغيرات بيئة. يقرأها التطبيق عبر آليته القياسية os.Getenv / process.env / System.getenv — لا يلزم تغيير أي كود إذا كان التطبيق يقرأ من متغيرات البيئة أصلًا.
envFrom كل مفتاح في ConfigMap كمتغير بيئة. إذا أضاف أحدهم مفتاحًا يتعارض مع متغير نظام يعتمد عليه تطبيقك (مثل PATH أو HOME أو متغير داخلي لمكتبة)، فسيكون السلوك غير محدد وغالبًا صامتًا. على مستوى الشركات الكبرى، يُفضَّل استخدام إدخالات env[].valueFrom.configMapKeyRef الصريحة حتى يكون العقد بين ConfigMap والتطبيق واضحًا وقابلًا للتدقيق في مراجعة الكود.استهلاك ConfigMaps: تثبيت وحدات التخزين (Volumes)
نمط تثبيت وحدة التخزين ضروري عندما يقرأ تطبيقك من ملف إعداد بدلًا من متغيرات البيئة — وهو أمر شائع مع NGINX وPrometheus وKafka وRedis والتطبيقات القديمة التي لا يمكنك تعديلها. كل مفتاح في ConfigMap يصبح ملفًا منفصلًا داخل المجلد المُثبَّت. اسم الملف هو المفتاح؛ ومحتوى الملف هو القيمة.
subPath للتثبيت الجراحي: بدون subPath، يؤدي تثبيت حجم ConfigMap على مجلد إلى استبدال المجلد بأكمله. إذا كان /etc/nginx/conf.d/ يحتوي بالفعل على إعدادات افتراضية تحتاجها، استخدم subPath: nginx.conf لتثبيت ذلك الملف وحده دون المساس ببقية المجلد. المقايضة: تثبيتات subPath لا تتلقى تحديثات مباشرة عند تغيير ConfigMap — راجع قسم سلوك التحديث أدناه.سلوك التحديث: الفرق الحاسم
هنا يقع المهندسون في مشكلات إنتاجية. يختلف سلوك تحديث ConfigMaps بحسب طريقة استهلاكها، وفهم ذلك يمنع الانقطاعات:
- متغيرات البيئة (
env/envFrom): تُحقن عند بداية تشغيل الحاوية. لا تُحدَّث أبدًا في حاوية قيد التشغيل. لتطبيق تغيير ConfigMap، يجب إعادة تشغيل الـ Pod — إما بحذفه (تُعيد ReplicaSet إنشاءه) أو بتشغيل تحديث متدرج. - تثبيتات Volume بدون
subPath: يحدِّث Kubernetes الملفات المُثبَّتة تلقائيًا. فترة مزامنة kubelet (افتراضيًا--sync-frequency=1mفي معظم الكلاسترات المُدارة) تعني أن التغييرات تنتشر خلال نحو 60 ثانية. لا يزال التطبيق بحاجة إلى مراقبة الملف للتغييرات — عملية تقرأ إعداداتها مرة واحدة فقط عند البداية لن تستفيد من ذلك. - تثبيتات Volume مع
subPath: التغييرات لا تنتشر. هذا قيد معروف في Kubernetes. تعامل مع هذه التثبيتات كثابتة — مثل متغيرات البيئة تمامًا.
kubectl rollout restart deployment/my-api. في سير عمل GitOps (ArgoCD أو Flux)، النهج الأنظف هو تعليق Deployment بتجزئة محتوى ConfigMap — حيلة sha256sum في Helm — حتى يُشغِّل تغيير ConfigMap تلقائيًا طرحًا جديدًا دون تدخل يدوي.ConfigMaps غير القابلة للتعديل (Immutable)
يدعم Kubernetes 1.21+ تحديد ConfigMap على أنه غير قابل للتعديل بضبط immutable: true في الملف. لا يمكن تحديث ConfigMaps غير القابلة للتعديل — يجب حذفها وإعادة إنشائها. في المقابل، يتوقف Kubernetes عن مراقبتها للتغييرات، مما يُقلِّص ملحوظًا حِمل خادم API و kubelet على نطاق واسع (الكلاسترات التي تحتوي على عشرات الآلاف من ConfigMaps). تستخدم فرق Google SRE على نطاق Kubernetes ConfigMaps غير القابلة للتعديل كممارسة: تغييرات الإعداد تحمل رقم نسخة (مثلًا app-config-v42 → app-config-v43) وتُحدَّث Deployments للإشارة إلى الاسم الجديد. يمنحك هذا النمط تاريخًا كاملًا للإعداد في Git، وتراجعًا فوريًا بالرجوع إلى مرجع Deployment، وصفر خطر من تعديل ConfigMap مباشر عن طريق الخطأ.
{app}-{component}-{env} (مثلًا payments-api-production) وتخزِّنها في نطاق مخصص لكل بيئة. مع RBAC الذي يمنح ServiceAccount الخاص بـpayments صلاحية get فقط على ConfigMaps في نطاق payments، تحقق وصولًا للإعداد بأقل الصلاحيات اللازمة — لا تستطيع الـ Pod قراءة ConfigMap فريق آخر حتى لو حاولت.