الوحدة 4 · أساسيات Kubernetes
الـ ConfigMaps والـ Secrets والـ Namespaces
20 دقراءة 4 داملأ الفراغات
الدرس في لمحة
انقل إعدادات notes-api إلى ConfigMap وبيانات اعتماده إلى Secret، وضع كل شيء في namespace اسمه notes، وشغّل سير عمل apply وdiff قابلًا للمراجعة من مجلد k8s.
- 1namespace لـ notes-api
- 2الـ ConfigMaps للإعدادات
- 3الـ Secrets لبيانات الاعتماد
- 4ربطها بـ notes-api
- 5سير العمل اليومي
لا فيديو هنا، بل الشيء الحقيقي: درس مكتوب وأمثلة قابلة للتشغيل واختبار وتدريب.
حاليًا، الـ Deployment الخاص بـ notes-api مكتوب فيه PORT، والـ Deployment الخاص بقاعدة البيانات فيه كلمة المرور نصًّا صريحًا، وكل شيء يعيش في الـ namespace default بجوار كل ما يجرّبه الآخرون في هذا الـ cluster. هذه ثلاث طرق لإحداث حادث: غيّر إعدادًا فتضطر إلى تعديل حمل العمل؛ اقرأ المستودع فتحصل على كلمة المرور؛ شغّل kubectl delete متهوّرًا في default فتصيب عمل شخص آخر.
namespace لـ notes-api
الـ namespace (نطاق الأسماء) نطاق للأسماء. يستطيع فريقان أن يملك كل منهما Deployment اسمه api في namespaces مختلفة. والـ namespaces هي أيضًا حيث تربط الصلاحيات (RBAC) وحصص الموارد، ما يجعلها الوحدة الطبيعية لـ «تطبيق واحد» أو «فريق واحد».
apiVersion: v1
kind: Namespace
metadata:
name: notesأضف namespace: notes إلى metadata في كل كائن آخر في k8s/، ثم اجعله الافتراضي لهذا الـ context حتى لا تكتب -n notes في كل مرة:
kubectl apply -f k8s/namespace.yaml
kubectl config set-context --current --namespace=notesما لا تفعله الـ namespaces هو عزل الشبكة. يستطيع Pod في notes الاتصال بـ Service في أي namespace آخر ما لم تقل NetworkPolicy غير ذلك، وتفرضها إضافة الشبكة في الـ cluster لديك. لا تعامل الـ namespace كجدار أمني بمفرده.
الـ ConfigMaps للإعدادات
الـ ConfigMap يحفظ إعدادات مفتاح-قيمة غير حسّاسة:
apiVersion: v1
kind: ConfigMap
metadata:
name: notes-api-config
namespace: notes
data:
PORT: "3000"
LOG_LEVEL: infoالقيم نصوص دائمًا، ولهذا وُضعت "3000" بين علامتَي تنصيص. الآن تستطيع image notes-api نفسها العمل بسجلات info في الإنتاج وdebug في staging، بتطبيق ConfigMap مختلف بدلًا من بناء image مختلفة.
الـ Secrets لبيانات الاعتماد
الـ Secret له شكل الـ ConfigMap نفسه، لكنه مخصّص للقيم الحسّاسة. أنشئه من سطر الأوامر (أو من مدير الأسرار لديك) بدلًا من ملف محفوظ في المستودع:
kubectl create secret generic notes-db \
--from-literal=POSTGRES_PASSWORD='dev-only-change-me' \
--from-literal=DATABASE_URL='postgres://notes:dev-only-change-me@notes-db:5432/notes'وهنا الجزء المزعج. انظر إلى ما هو مخزّن:
kubectl get secret notes-db -o jsonpath='{.data.POSTGRES_PASSWORD}' | base64 -dتعود القيمة مباشرة. بيانات الـ Secret مرمّزة بـ base64، لا مشفّرة. ما يجعل الـ Secrets أكثر أمانًا من الـ ConfigMaps هو كل ما يحيط بها: يستطيع RBAC منح صلاحية قراءة الـ ConfigMaps دون الـ Secrets، ويستطيع الـ cluster تشفير الـ Secrets أثناء تخزينها في etcd (والمزوّدون المُدارون يفعلون ذلك عادةً)، ولا تستلم الـ kubelets إلا الـ Secrets الخاصة بالـ Pods المُجدولة على الـ node الخاص بها.
ربطها بـ notes-api
حدّث الـ container في k8s/deployment.yaml:
containers:
- name: api
image: ghcr.io/skylane/notes-api:1.4.0
ports:
- name: http
containerPort: 3000
envFrom:
- configMapRef:
name: notes-api-config
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: notes-db
key: DATABASE_URLالحقل envFrom يحوّل كل مفتاح في الـ ConfigMap إلى متغيّر بيئة. وsecretKeyRef يسحب مفتاحًا واحدًا من الـ Secret. وفي k8s/db.yaml، استبدل القيمة الحرفية لـ POSTGRES_PASSWORD بـ secretKeyRef إلى الـ Secret نفسه.
إذا لم يكن المفتاح المُشار إليه موجودًا، فلن يبدأ الـ container أبدًا. يُظهر الـ Pod الحالة CreateContainerConfigError، ويسمّي kubectl describe pod المفتاح المفقود.
يمكن أيضًا تركيب الـ Secrets والـ ConfigMaps كملفات عبر volume. الملفات المركّبة تتحدّث في الـ Pods العاملة بعد تأخير قصير؛ أما متغيّرات البيئة فثابتة منذ بدء الـ container. بعد تغيير إعدادات تصل عبر متغيّرات البيئة، أعِد تشغيل الـ Pods تدريجيًا:
kubectl rollout restart deployment/notes-apiسير العمل اليومي
مجلد k8s/ لديك يحتوي الآن على namespace.yaml وconfigmap.yaml وdb.yaml وdeployment.yaml وservice.yaml. والحلقة لكل تغيير هي نفسها:
kubectl diff -f k8s/
kubectl apply -f k8s/
kubectl get all -l app.kubernetes.io/name=notes-apiالأمر diff هو خطوة المراجعة: يُظهر ما سيتغيّر على الـ cluster الحيّ، حقلًا بحقل، قبل أن تغيّره. اجعله عادة وستلتقط التعديل الشارد الذي كان سيعيد ضبط إصلاح طارئ أجراه أحدهم. وحين تحتاج إلى قيم مختلفة لكل بيئة، فإن Kustomize (المدمج في kubectl كـ kubectl apply -k) يضع طبقات صغيرة (overlays) فوق هذه الملفات الأساسية؛ وHelm، في الدرس 5.3، هو الإجابة الشائعة الأخرى.
يعمل notes-api الآن على Kubernetes بشبكة وإعدادات سليمة. لكنه ليس جاهزًا للإنتاج بعد: لا يعرف Kubernetes هل هو سليم، ولا كم يحتاج من المعالج، ولا كيف يحدّثه بأمان. القسم الخامس يغطّي الثلاثة.
أهم النقاط
- الـ ConfigMaps تحفظ الإعدادات غير الحسّاسة؛ والـ Secrets تحفظ بيانات الاعتماد، وتُحقن كمتغيّرات بيئة أو كملفات مركّبة.
- قيم الـ Secret مرمّزة بـ base64 فقط، لا مشفّرة؛ احمِها بـ RBAC، وبالتشفير أثناء التخزين، وبإبقائها خارج Git.
- متغيّرات البيئة القادمة من ConfigMap أو Secret تُقرأ مرة واحدة عند بدء الـ container، لذا أعِد تشغيل الـ Deployment بعد تغييرها.
- الـ Namespaces تحدّد نطاق الأسماء والصلاحيات والحصص لفريق أو تطبيق، لكنها لا تعزل حركة الشبكة وحدها.
- تشغيل
kubectl diff -f k8s/قبلkubectl apply -f k8s/يُظهر بالضبط ما سيتغيّر، مثل pull request للـ cluster.