تطوير الويب

ConfigMaps وSecrets وServiceAccounts وSecurityContext CKAD 2026

6 دقائق للقراءة

السلسلة: هذا الدرس جزء من سلسلة شهادة CKAD. للحصول على نظرة شاملة، اقرأ المقال الرئيسي أولاً.

مقدمة

المجال 3 «Application Environment, Configuration and Security» يزن 25% من امتحان CKAD — أكثف جزء في المنهج. كذلك المجال الذي يخسر فيه معظم المرشحين نقاطاً بجهل دقائق: الفرق بين حقن ConfigMap عبر متغيّر بيئة وعبر ملف مربوط، base64 مقابل تشفير حقيقي للأسرار، ServiceAccount الافتراضي مقابل مخصّص، requests مقابل limits، ResourceQuota على مستوى namespace مقابل LimitRange. هذا الدرس يدرّب كل مفهوم بـ manifests مُختبَرة على عنقود kind 1.35.

المتطلبات

  • عنقود kind 1.35 شغّال
  • إكمال الدروس السابقة من السلسلة
  • 40 دقيقة

الخطوة 1 — إنشاء ConfigMap من ملف

ConfigMap يخزّن بيانات إعداد غير سرية: URLs API، مستويات log، feature flags، معاملات runtime. ثلاث طرق للإنشاء: --from-literal، --from-file، أو manifest YAML مباشر.

cat > app.properties <<EOF
LOG_LEVEL=info
API_BASE_URL=https://api.example.com
FEATURE_FLAGS=new_ui,fast_search
EOF

k create configmap app-config --from-file=app.properties $do > cm.yaml
k apply -f cm.yaml
k get configmap app-config -o yaml | head -20

مخرَج YAML يُظهر البيانات في قسم data:، مع مفتاح app.properties يحتوي كامل الملف كقيمة. هذا تماماً ما يُربط حين تشير إلى هذا ConfigMap بصفته ملفاً في Pod.

الخطوة 2 — حقن ConfigMap عبر متغيّر بيئة

الحقن عبر env هو الطريقة الأبسط: كل مفتاح في ConfigMap يصير متغيّر بيئة للحاوية. القيد: التغييرات لا تُروَّج ديناميكياً — يلزم إعادة تشغيل الـ Pod.

k create configmap envs-cm --from-literal=APP_ENV=production --from-literal=DEBUG=false

cat > pod-env.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: env-consumer
spec:
  containers:
    - name: app
      image: busybox:1.37
      command: ["sh","-c","env | grep -E 'APP_ENV|DEBUG'; sleep 3600"]
      envFrom:
        - configMapRef:
            name: envs-cm
EOF

k apply -f pod-env.yaml
sleep 5
k logs env-consumer | head -5

المخرَج يعرض APP_ENV=production وDEBUG=false. envFrom يحقن كل مفاتيح ConfigMap دفعةً. لأخذ مفتاح واحد، استخدم env.valueFrom.configMapKeyRef.

الخطوة 3 — حقن ConfigMap عبر ملف مربوط

الحقن عبر ملف مربوط يعامل ConfigMap كـ volume: كل مفتاح يصير ملفاً في المجلد المربوط. ميزة حاسمة: تغييرات ConfigMap تُروَّج في الـ volume دون إعادة تشغيل الـ Pod (بتأخير عشرات الثواني مرتبط بـ kubelet sync).

cat > pod-mount.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: file-consumer
spec:
  volumes:
    - name: config-vol
      configMap:
        name: app-config
  containers:
    - name: app
      image: busybox:1.37
      command: ["sh","-c","cat /etc/conf/app.properties; sleep 3600"]
      volumeMounts:
        - name: config-vol
          mountPath: /etc/conf
EOF

k apply -f pod-mount.yaml
sleep 5
k logs file-consumer

محتوى ملف app.properties يظهر في السجلات. هذه الطريقة مفضّلة لملفات إعداد كاملة (nginx.conf، my.cnf، application.yml) لا لمتغيّرات فردية.

الخطوة 4 — إنشاء Secret وفهم ترميز base64

Secrets تخزّن بيانات حساسة. نقطة حاسمة في الامتحان: Secrets مُرمَّزة base64، ليست مشفَّرة. أي شخص لديه وصول إلى etcd أو API Kubernetes يستطيع فكّ ترميز السر. التشفير at-rest في etcd ميزة منفصلة تُفعَّل يدوياً بـ EncryptionConfiguration.

k create secret generic db-creds \
  --from-literal=username=admin \
  --from-literal=password=Tr0ub4dor

k get secret db-creds -o yaml
echo "YWRtaW4=" | base64 -d        # admin
echo "VHIwdWI0ZG9y" | base64 -d    # Tr0ub4dor

ترى بوضوح username وpassword بالنص الصريح بعد فكّ base64. هذه التوضيح يأتي منهجياً في الامتحان كسؤال فخّ: «هل Secrets مشفَّرة؟» — الجواب الصحيح «لا، فقط مُرمَّزة base64؛ التشفير at-rest يجب ضبطه منفصلاً».

الخطوة 5 — حقن Secret كمتغيّر بيئة

حقن Secret يتبع نفس منطق ConfigMap. ممارسة شائعة: كلمة سرّ قاعدة البيانات تُحقَن في تطبيق عبر env.

cat > pod-secret.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: db-app
spec:
  containers:
    - name: app
      image: busybox:1.37
      command: ["sh","-c","echo User=$DB_USER; echo Pass=$DB_PASS; sleep 3600"]
      env:
        - name: DB_USER
          valueFrom:
            secretKeyRef:
              name: db-creds
              key: username
        - name: DB_PASS
          valueFrom:
            secretKeyRef:
              name: db-creds
              key: password
EOF

k apply -f pod-secret.yaml
sleep 5
k logs db-app

المخرَج يعرض User=admin وPass=Tr0ub4dor — الأسرار مُحقَنة بالنص الصريح في الحاوية. هكذا تستهلكها التطبيقات. الأمان يعتمد على تقييد الوصول للـ Pod وعلى تشفير at-rest في etcd.

الخطوة 6 — ServiceAccount مخصّص وtoken automounted

كل Pod يشتغل بـ ServiceAccount، افتراضياً default. لـ Pod يتفاعل مع API Kubernetes (مثل controller، job رصد)، أنشئ ServiceAccount مخصّصاً بأدنى الصلاحيات الضرورية.

k create serviceaccount monitor-sa
k create role pod-reader --verb=get,list,watch --resource=pods
k create rolebinding monitor-sa-binding --role=pod-reader --serviceaccount=default:monitor-sa

cat > pod-sa.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: monitor-pod
spec:
  serviceAccountName: monitor-sa
  containers:
    - name: monitor
      image: bitnami/kubectl:1.35
      command: ["sh","-c","kubectl get pods; sleep 3600"]
EOF

k apply -f pod-sa.yaml
sleep 5
k logs monitor-pod | head -10

الـ Pod يدرج pods في namespace default لأن ServiceAccount له صلاحية get pods. إن جرّبت kubectl get nodes داخل هذا الـ Pod، تحصل على خطأ 403 Forbidden — مثبتاً أن الصلاحيات مُحدّدة المجال بصرامة.

الخطوة 7 — ضبط requests وlimits وResourceQuota

requests تضمن حجز موارد على العقدة. limits تعرّف السقف — التجاوز يطلق OOMKill (RAM) أو throttling (CPU). ResourceQuota يحدّ الموارد الكلية لـ namespace.

k create namespace dev-team
k create quota dev-quota --hard=cpu=2,memory=2Gi,pods=10 -n dev-team

cat > pod-resources.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: app-with-limits
  namespace: dev-team
spec:
  containers:
    - name: app
      image: nginx:1.27
      resources:
        requests:
          cpu: "100m"
          memory: "64Mi"
        limits:
          cpu: "500m"
          memory: "128Mi"
EOF

k apply -f pod-resources.yaml
k describe quota dev-quota -n dev-team
k describe pod app-with-limits -n dev-team | grep -A 5 Limits

مخرَج describe quota يُظهر الاستهلاك الحالي («used: cpu=100m, memory=64Mi, pods=1») مقابل السقف. أي Pod يُنشأ في هذا namespace يجب أن يعلن resources، وإلا يرفضه admission webhook.

الخطوة 8 — SecurityContext للتحصين

SecurityContext يطبّق قيود Linux على الحاوية: مستخدم غير root، إسقاط capabilities Linux، نظام ملفات للقراءة فقط، منع تصعيد الامتيازات. المجال 3c من المنهج.

cat > pod-secure.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: secure-app
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    fsGroup: 2000
  containers:
    - name: app
      image: busybox:1.37
      command: ["sh","-c","id; ls -la /; sleep 3600"]
      securityContext:
        allowPrivilegeEscalation: false
        capabilities:
          drop: ["ALL"]
        readOnlyRootFilesystem: true
EOF

k apply -f pod-secure.yaml
sleep 5
k logs secure-app | head -5

مخرَج id يجب أن يعرض uid=1000. نظام الملفات read-only، يمنع أي malware من تعديل الثنائي التطبيقي. هذه الوضعية الأمنية الموصى بها بـ Pod Security Standards Restricted.

فهم env مقابل envFrom مقابل volumeMounts

ثلاث طرق لحقن إعداد في حاوية، لكل واحدة حالات استخدامها. env يحقن متغيّراً فردياً يشير إلى مفتاح محدّد في ConfigMap أو Secret. مطوَّل لكنه صريح. envFrom يحقن كل مفاتيح ConfigMap/Secret في توجيه واحد. عملي لكن مبهم — مطوّر جديد يجب أن يقرأ ConfigMap لمعرفة ما يُكشَف. volumeMounts يربط ConfigMap/Secret كشجرة ملفات. مفضّل لملفات config كاملة ويسمح بترويج التعديلات ديناميكياً.

قاعدة عملية CKAD: env لـ 1-3 متغيّرات حرجة (DATABASE_URL، API_KEY)، envFrom لمجموعات متغيّرات بيئة، volumeMounts لملفات nginx.conf، application.yml، settings.json.

أخطاء شائعة

الخطأ السبب الحل
Pod يرفض التشغيل مع runAsNonRoot صورة الحاوية تشتغل root افتراضياً اختر صورة تحدّد USER غير root، أو عدّل Dockerfile
Secret غير موجود اختلاف namespace Secret يجب أن يكون في نفس namespace كـ Pod
ResourceQuota يحجب الإنشاء Pod بلا requests/limits صريحة أعلن دائماً resources في manifests إن كان quota نشطاً
Permission denied على ServiceAccount RoleBinding مفقودة أو namespace خاطئ kubectl auth can-i --as=system:serviceaccount:NS:NAME VERB RESOURCE
تحديث ConfigMap لا يُروَّج حقن عبر env أعد نشر Pod (kubectl rollout restart) أو استخدم volumeMount

دروس مرافقة

أسئلة شائعة

هل أنشئ دائماً ServiceAccount مخصّصاً؟
لـ Pods التي لا تتفاعل مع API Kubernetes: لا، default يكفي. لـ Pods controllers أو jobs إدارية أو agents: نعم، أنشئ SA مخصّصاً بأدنى الصلاحيات.

كيف نشفّر Secrets at-rest؟
اضبط EncryptionConfiguration في kube-apiserver مع مزوّد AES-CBC أو KMS. خارج نطاق CKAD لكنه أساسي في الإنتاج.

مقالات ذات صلة

Sponsoriser ce contenu

Cet emplacement est à vous

Position premium en fin d'article — c'est l'instant où les lecteurs sont le plus engagés. Réservez cet espace pour votre marque, votre formation ou votre offre.

Recevoir nos tarifs
Publicité