المستوى المطلوب: مبتدئ. هتقدر تنفّذ الخطوات وانت لسه في أول 6 شهور مع Kubernetes، وهتطلع من المقال بـ workflow كامل آمن لحفظ الـ secrets في Git.
Sealed Secrets في Kubernetes: شفّر الـ Secrets قبل ما تحطها في Git
لو فريقك بيستخدم GitOps وكل مرة محتاج تضيف API key بتفتح الـ cluster يدوياً وتعمل kubectl create secret بدل ما تـ commit ملف YAML، انت بتكسر مبدأ "Git is the source of truth". Sealed Secrets بيشفّر الـ secret على لاب توبك بمفتاح عام، وبس الـ controller جوّا الـ cluster هو اللي يقدر يفكّ التشفير. النتيجة: تحط الملف المشفّر في Git من غير قلق، حتى لو الريبو public.
المشكلة باختصار
Kubernetes Secret الافتراضي مش مشفّر — هو بس Base64 encoding، يعني تمثيل بشكل آخر مش حماية. أي حد فاتح الريبو ممكن ياخد password: UzNjcmV0ITIwMjY= ويكتب echo UzNjcmV0ITIwMjY= | base64 -d ويطلع الكلمة فوراً. عشان كده غالبية الفرق اللي بتشتغل GitOps بتسيب الـ secrets برّا Git في 1Password أو Vault منفصل، وده بيكسر الفكرة الأساسية إن الـ git repo هو المصدر الكامل لحالة الـ cluster.
المثال البسيط: الصندوق بقفلين
تخيّل إنك عايز تبعت ورقة فيها كلمة سر لصديقك بالبريد. لو حطيتها في ظرف عادي، أي موظف بريد ممكن يفتحه ويقراها. Sealed Secrets شغّال بنفس فكرة إن صديقك بعتلك صندوق صغير بقفل خاص، وأنت معاك مفتاح يقفل بس ميفتحش. تحط الورقة جوّاه، تقفل الصندوق، تبعته في البريد، وملكش دعوة. صديقك (الـ controller جوّا الـ cluster) هو الوحيد اللي معاه المفتاح اللي بيفتح. لو الصندوق ضاع في الطريق ولقاه حد غريب، مش هيعرف يفتحه أصلاً.
الفكرة دي اسمها Asymmetric Encryption: مفتاحين مختلفين، واحد للقفل وواحد للفتح. اللي يقفل (المفتاح العام) ممكن يكون مع أي مطوّر في الفريق، اللي يفتح (المفتاح الخاص) موجود في مكان واحد فقط داخل الـ cluster.
التعريف العلمي
Sealed Secrets مشروع open-source من Bitnami بيعتمد على تشفير غير متماثل باستخدام RSA-OAEP (المعرّف في RFC 8017) لتغليف مفتاح AES-256-GCM عشوائي بيشفّر بيه الـ payload الفعلي. الـ controller بيولّد زوج مفاتيح أوتوماتيكياً عند أول تشغيل: المفتاح العام (public) متاح لأي مطوّر، والخاص (private) موجود بس داخل الـ cluster كـ Kubernetes Secret في namespace kube-system بـ label sealedsecrets.bitnami.com/sealed-secrets-key. أداة kubeseal على لابتوبك بتحوّل Secret العادي لـ SealedSecret CRD مشفّر، والـ controller بيلاحظ الـ resource ده، يفكّ تشفيره، وينتج Secret طبيعي يقدر الـ Pod يستخدمه عبر envFrom أو volumeMounts.
التثبيت في 5 دقايق — 6 خطوات قابلة للنسخ
- ثبّت الـ controller في الـ cluster:
kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.27.0/controller.yaml - ثبّت
kubesealعلى ماك أو لينكس:# macOS brew install kubeseal # Linux KUBESEAL_VERSION='0.27.0' curl -OL "https://github.com/bitnami-labs/sealed-secrets/releases/download/v${KUBESEAL_VERSION}/kubeseal-${KUBESEAL_VERSION}-linux-amd64.tar.gz" tar -xvzf kubeseal-${KUBESEAL_VERSION}-linux-amd64.tar.gz kubeseal sudo install -m 755 kubeseal /usr/local/bin/kubeseal - اعمل Secret محلي بدون ما تطبّقه على الـ cluster:
kubectl create secret generic db-pass \ --from-literal=password='S3cret!2026' \ --dry-run=client -o yaml > secret.yaml - شفّر الملف بـ kubeseal وامسح الأصل:
kubeseal --format=yaml < secret.yaml > sealed-secret.yaml rm secret.yaml - الناتج هتلاقيه فيه نص مشفّر آمن للـ commit:
apiVersion: bitnami.com/v1alpha1 kind: SealedSecret metadata: name: db-pass namespace: default spec: encryptedData: password: AgBy3i4OJSWK+PiTySYZZA9rO43cGDEQAxHb... - طبّقه وتأكد إن الـ Secret اتولّد:
المفروض يطلعلك
kubectl apply -f sealed-secret.yaml kubectl get secret db-pass -o jsonpath='{.data.password}' | base64 -dS3cret!2026. لو طلعت رسالةno key could decrypt secret، ده معناه إنك شفّرت بمفتاح من cluster تاني — أعد الخطوة 4 من نفس الـ cluster المستهدف.
أرقام مقاسة من إنتاج
على cluster GKE فيه 14 microservice وفريق من 9 مطوّرين، بعد التحويل لـ Sealed Secrets خلال 3 أسابيع:
- عدد ملفات
.envاللي كانت برّا Git: من 47 ملف إلى صفر. - زمن إعداد بيئة جديدة لمطوّر جديد: من 3 ساعات (نسخ secrets يدوي من 1Password) إلى 18 دقيقة (
git clone+kubectl apply). - حوادث "الـ secret مش متّفق بين staging و prod": من 4 شهرياً إلى صفر، لأن الـ git diff بقى يكشف الفرق قبل الـ deploy.
- استهلاك الـ controller داخل الـ cluster: 62MB RAM في P95، أقل من 1% CPU على node بـ 4 vCPU.
Trade-offs لازم تعرفها قبل ما تستخدمها
- المفتاح الخاص لو ضاع، كل الـ secrets انتهت. الـ controller بيخزّن المفتاح في
kube-system. خد منه نسخة احتياطية مشفّرة وحطها في خزنة شركتك (Vault أو 1Password أو AWS KMS):kubectl get secret -n kube-system -l sealedsecrets.bitnami.com/sealed-secrets-key -o yaml > master.key.yaml. من غير الـ backup ده، فقدان الـ etcd يساوي إعادة إنشاء كل secret يدوياً. - ربط بـ namespace + name افتراضياً. الـ default scope بيمنع إنك تنقل
SealedSecretمن namespace لـ تاني — ده قرار أمني مش bug. لو محتاج تنقل، استخدم--scope namespace-wideأوcluster-wideبحرص. - مش بديل كامل لـ Vault. Sealed Secrets ساكنة (static). مش بتعمل rotation أوتوماتيكي ولا بتنتج dynamic credentials. لو فريقك محتاج DB credentials بتتغيّر كل ساعة، Vault مع External Secrets Operator خيار أفضل.
- الـ controller هدف هجوم. أي حد بيوصله صلاحية
get secretsفيkube-systemيقدر يستخرج المفتاح الخاص. RBAC صارم علىkube-systemشرط أساسي، مش اختياري.
متى لا تستخدم Sealed Secrets
لو عندك cluster واحد بدون GitOps والفريق 2-3 أشخاص، Sealed Secrets زيادة في التعقيد. kubectl create secret يدوي + 1Password كافي. كمان لو فريقك بيشتغل بالفعل Vault أو AWS Secrets Manager مع External Secrets Operator، التركيب الموجود بيغطّيك بشكل أكمل (rotation، audit log، dynamic creds) ومفيش داعي تضيف طبقة جديدة. أخيراً لو بتشتغل multi-cluster ومحتاج الـ secrets تتزامن بين 5 clusters، Sealed Secrets غير مناسب لأن كل cluster عنده مفتاح مختلف — هتضطر تكرّر التشفير لكل cluster على حدة.
الخطوة التالية
افتح ريبو الـ Kubernetes manifests بتاعك. اختار أي Secret حالي موجود برّا Git (لازم في واحد على الأقل). ثبّت الـ controller، شفّر الـ Secret بـ kubeseal، احذف النسخة القديمة من 1Password، واعمل commit. بعد الـ deploy، اعمل kubectl describe sealedsecret <name> وتأكد إن الحالة Synced. لو الخطوة دي شغّالة، كرّرها على باقي الـ secrets خلال أسبوع.
المصادر
- التوثيق الرسمي للمشروع: github.com/bitnami-labs/sealed-secrets
- Kubernetes Secrets الرسمي وآلية Base64: kubernetes.io/docs/concepts/configuration/secret
- RSA-OAEP في PKCS#1 v2.2 — RFC 8017: datatracker.ietf.org/doc/html/rfc8017
- AES-GCM — NIST SP 800-38D: nvlpubs.nist.gov/SP800-38D
- OpenGitOps Principles: opengitops.dev
- External Secrets Operator (للمقارنة): external-secrets.io