الورقة البيضاء للأمان في نزال (الإصدار v0.1 مسودة لفريق الأمان لدى المشتري)
نموذج النشر
يعمل نزال بالكامل داخل كلستر Kubernetes الخاص بالعميل. ويتكوّن من ثلاثة مكوّنات:
- مشغّل (operator) مع وكيل عكسي (reverse proxy) صغير لكل تطبيق
- واجهة API مع قاعدة بيانات مضمّنة على وحدة تخزين دائمة
- لوحة تحكم ثابتة تقدّمها تلك الواجهة
لا يتصل أي مكوّن بالإنترنت من تلقاء نفسه. والنقاط التي يتصل بها هي التي يضبطها المشرف:
- خادم API الخاص بالكلستر
- خادم git الخاص بالعميل (من المشغّل)
- سجل الصور لدى العميل (من المشغّل ومن عمليات البناء)
- مزوّد الهوية ومرحّل SMTP ومجمّع SIEM لدى العميل (من واجهة API)
- تخزين الكائنات لدى العميل لأرشيفات الأدلة عندما يضبطه المشرف (من واجهة API)
- نقطة نهاية للذكاء الاصطناعي عندما يفعّل المشرف الوكيل الذكي ويسمح بعنوان مضيفها (من واجهة API)
وتفتح سياسات الشبكة الإنترنت في الاتجاهين افتراضيًا لتكون تلك النقاط في أي مكان. ويُستثنى عنوان
البيانات الوصفية للسحابة من كل سياسة. ويضبط التثبيت المعزول networkPolicy.internet وenvironments.internet
على false ويذكر شبكاته الخاصة فيرفض CNI كل ما عداها.
العزل
كل بيئة مطوّر هي مساحة أسماء في Kubernetes تحمل ResourceQuota وLimitRange مستمدّين من سياسة
الفريق. تعمل فيها نسخ الخدمات التي تغيّرت. أما كل خدمة أخرى فهي اسم بديل من نوع ExternalName
يشير إلى الأساس المشترك. يقف الموجّه خلف أسماء خدمات (Service) الأساس ويوجّه الطلبات وفق
ترويسة X-Nezal-Env. عند حافة الكلستر تُستمد الترويسة من قيمة Host فقط. وتُهمل أي ترويسة
توجيه يرسلها العميل وتُحصى. أما البيئات غير المعروفة فتُوجَّه إلى الأساس ويُبلَّغ عنها أحداثًا (Events).
في الوضع الكامل تكون كل بيئة نسخة كاملة في مساحة أسماء مساحة العمل. وتعمل النسخة بلا رمز حساب
خدمة وبلا أي من أدوار المخطط نفسه. ولكل بيئة NetworkPolicy تسمح للـ Pods التابعة لها بالتواصل فيما بينها
ومع DNS ومع الإنترنت في الاتجاهين. وتمنع الوصول إلى كل بيئة أخرى وإلى نظام نزال ومساحات الأسماء
الأخرى والعقد وعنوان البيانات الوصفية للسحابة (cloud metadata). ولا يُوصَل إلى الشبكات الداخلية
إلا إذا ذكرها المشرف في egressCIDRs ضمن السياسة (Policy).
الهوية والوصول
تُفوَّض المصادقة إلى مزوّد الهوية لدى العميل عبر OIDC (تدفق رمز التفويض مع PKCE) أو SAML 2.0. رموز الجلسة موقّعة بـ EdDSA. ويُعاد قراءة الأدوار من قاعدة البيانات عند كل طلب. تُفرض ثلاثة أدوار في واجهة API ولا تُفرض في واجهة المستخدم وحدها أبدًا. يوجد رمز إعداد أولي للتشغيل الأول ويُهمل بعد ضبط SSO.
شخص واحد لكل هوية في كل مرة. كل تسجيل دخول جلسة مسجّلة يمكن عرضها وإنهاؤها. وينهي تسجيل
الدخول من متصفح جلسة المتصفح الأخرى للهوية نفسها. وينهي nezal login جلسة سطر الأوامر الأخرى.
ويسري ذلك على حساب كلمة المرور وحساب الدخول الموحّد ورمز الإعداد الأولي على السواء. ويُبلَّغ
الجهاز الذي خرج بالسبب. ولا يُستخدم رمز الإعداد نفسه للمصادقة أبدًا بل يُستبدل مرة واحدة بجلسة
تتبع القاعدة نفسها وتتوقف فور ضبط الدخول الموحّد. أما رموز API المسمّاة لأنظمة CI فتُنشأ واحدًا
واحدًا من الحساب ولا تخضع للحد. والهوية التي يتكرر تسجيل الدخول بها من أماكن أخرى يُبلَّغ عنها
المشرف وتُكتب في سجل التدقيق. راجع ADR 0021.
تحديد المعدل. كل نقطة نهاية تقبل سرًا من شخص لم يسجّل الدخول لها حدّان في الوقت نفسه: عشر كلمات مرور خاطئة تقفل حسابًا واحدًا وستون محاولة فاشلة خلال خمس عشرة دقيقة تستنفد حصة عنوان عميل واحد عبر جميع تلك النقاط. تُخزَّن العدادات في SQLite. ولذلك لا يمكن لإعادة تشغيل واجهة API أن تمسح قفلًا ويستطيع المدقّق أن يرى ما حدث. لا يُعتمد العنوان المُمرَّر (forwarded) إلا خلف وكيل موثوق مضبوط مسبقًا. وإلا لأمكن لأي مستدعٍ أن يختلق عنوانًا جديدًا مع كل طلب ويتحايل على الحد.
نقطة نهاية خطاف الويب (webhook) الخاصة ببيئات طلبات الدمج (per-PR) لا تتطلب مصادقة عن قصد (فمنصة استضافة git ترسل إليها طلبات موقّعة بـ HMAC) ولها حدّها الخاص. ولا يُحتسب من هذا الحد إلا الطلبات التي تفشل في المصادقة. فالمنصة التي ترسل أحداثًا موقّعة توقيعًا صحيحًا لا تُقيَّد أبدًا مهما بلغ نشاط المستودع. أما العنوان الذي يخمّن أسرار خطاف الويب فتنفد حصته. ولهذا الحد رصيد منفصل حتى لا تستهلك هذه الحركة الحد الذي يحمي تسجيل الدخول.
فرض السياسات
يرفض خطاف القبول (admission webhook) من نوع validating أي عملية كتابة على Environment تفعل أيّاً مما يلي:
- تتجاوز حصة لكل مستخدم أو لكل فريق
- تتجاوز حدّ المدة (TTL)
- تستبدل تبعية مشتركة بنسخة خاصة
- تطلب طرفية حيث تكون الطرفيات معطّلة
وتعيد حلقة التسوية (reconciler) التحقق من حدود المدة ومن صحة التجاوزات. ويُصدر المشغّل شهادة خطاف القبول ويجدّدها. واستخدام cert-manager اختياري.
الوصول إلى الأسرار
لا يحمل المشغّل أي صلاحية على Secret على مستوى الكلستر من أي نوع. لا قراءة ولا كتابة. يفرض ذلك حدّان مستقلان. ولا يكفي خطأ في أحدهما:
- تُمنح الصلاحية لكل Secret على حدة بالاسم. عند ربط مستودع تنشئ واجهة API دورًا (Role)
محدودًا بمساحة أسماء يسمّي ذلك الـ Secret بالتحديد في
resourceNamesويكون مرتبطًا بحساب الخدمة (ServiceAccount) الخاص بالمشغّل. وفصل المستودع يلغي هذا الدور. القائمة الكاملة لما يجوز للمشغّل قراءته هيkubectl get rolebindings -A. - لا تراقب ذاكرة الـ informer المؤقتة (informer cache) إلا الأسرار الموسومة (
nezal.dev/git-credentials=true). ولذلك لا يُجلب أي Secret غير ذي صلة تابع لتطبيق آخر ولا يُحتفظ به في الذاكرة أبدًا حتى حيث تسمح الصلاحية بذلك.
لا يوجد عن قصد أي وسم kubebuilder:rbac (marker) للأسرار في شيفرة المشغّل المصدرية. ويقرأ اختبار وحدة
الـ ClusterRole المولَّد ويفشل إذا ظهر واحد مجددًا: فتعديل ملف YAML وحده سيُلغيه
make manifests في المرة التالية.
كذلك لا يستطيع المشغّل كتابة أسرار خارج مساحة الأسماء الخاصة به. ولهذا السبب بالتحديد يمرّ توزيع مفتاح توقيع المعاينة إلى مساحات أسماء التطبيقات عبر واجهة API لا عبر المشغّل.
لا تظهر قيم بيانات الاعتماد أبدًا في السجلات أو الحالة أو مدخلات التدقيق. وتُنقّى رسائل الخطأ الصادرة من عمليات git من مواد بيانات الاعتماد بالقيمة وبالشكل.
التدقيق
يُضاف كل إجراء للمستخدم إلى سجل مسلسل بالتجزئة (hash-chained) في قاعدة بيانات ترفض UPDATE
وDELETE. والاستثناء الوحيد هو مدة الاحتفاظ: حين يضبط المخطط audit.retention.days تُحذف أقدم
المدخلات مرة كل ساعة. وتُتحقق السلسلة الباقية من نقطة ارتكاز تحمل تجزئة آخر مدخل حُذف. وتُكتب
كل عملية حذف في السجل نفسه. والتسجيل متوقف في التثبيت الجديد حتى يشغّله المشرف. ويبقى
مفعّلًا في التثبيت المُرقّى الذي يحوي مدخلات. ويُكتب تشغيله وإيقافه دائمًا مع اسم من فعل ذلك. تُوقَّع حزم الأدلة بمفتاح ed25519 خاص بكل تثبيت. يمكن إرسال المدخلات إلى SIEM.
تُدقَّق جلسات الطرفية عند الفتح وعند الإغلاق مع من فتح الجلسة وأي Pod دخلت إليه ولماذا انتهت.
ولا تُحفظ ضغطات المفاتيح ولا المخرجات ولا يمكن إعادة عرض الجلسة. ولا تظهر الأسرار أبدًا في سطور السجلات
أو تفاصيل التدقيق. وتُنقّى رسائل الخطأ الصادرة من عمليات git من مواد بيانات الاعتماد.
أين تُحفظ الأدلة. افتراضيًا يوجد كل ما يحتفظ به نزال على وحدة تخزين واحدة داخل الكلستر. ويشمل ذلك قاعدة البيانات وسجل التدقيق إلى جانب النسخ الاحتياطية. ويمكن للعميل بدلًا من ذلك ضبط تخزين كائنات متوافق مع S3 خاص به. وعندها تُنسخ إليه أرشيفات التدقيق الموقّعة والنسخ الاحتياطية المجدولة فور إنتاجها.
ونقطة النهاية هذه ملك للعميل نفسه: MinIO أو Ceph محليًا أو جهاز تخزين أو تخزين كائنات في سحابة سيادية ضمن نطاق اختصاصك القضائي. وهي معطّلة حتى يُدخلها المشرف. وعند إدخالها تنضم إلى القائمة القصيرة للجهات التي يتصل بها المنتج أصلًا. ولا شيء فيها يفترض سحابة عامة أو يصل إليها. تُحفظ بيانات الاعتماد في Secret في Kubernetes لا في قاعدة البيانات لأن قاعدة البيانات هي ما يُنسخ احتياطيًا ويُنقل من مكان إلى آخر. وبيانات اعتماد المكان الذي تذهب إليه النسخ الاحتياطية لا ينبغي أن تنتقل داخل النسخ الاحتياطية نفسها.
لا يحذف نزال الأرشيفات والنسخ الاحتياطية أبدًا بعد رفعها: فدورة حياتها من شأن العميل وتُفرض بقواعد الـ bucket. وحيث يكون قفل الكائنات (object lock) مفعّلًا على الـ bucket لا يستطيع أحد تعديل تلك الأرشيفات أو حذفها حتى انتهاء مدة الاحتفاظ بها ولا حتى مشرف نزال. وهذا هو ضابط الكتابة لمرة واحدة الذي يطلبه المدقّق. وتكتشف شاشة الإعدادات هل الـ bucket يدعمه وتصرّح بذلك لأن نزال لا يستطيع تفعيله بنفسه.
فشل الرفع لا يُفشل أبدًا العملية التي أنتجت الملف. يُكتب الملف محليًا أولًا تمامًا كما لو لم
يُضبط أي تخزين كائنات. ثم تُعاد محاولة الرفع. ويصرّح المقياس nezal_evidence_pending_uploads ولوحة
التحكم بوضوح عندما لا تفرغ قائمة الانتظار لأن الأدلة التي لا تصل أبدًا هي أدلة لا يملكها
العميل.
الترخيص
التراخيص حمولات (payloads) موقّعة بـ ed25519 يُتحقق منه دون اتصال بالإنترنت مقابل مفاتيح عامة للمورّد مضمّنة في الملفات التنفيذية. لا يوجد أي اتصال بالمورّد. ولذلك يعمل التحقق في بيئة معزولة تمامًا. مفتاح توقيع التطوير موضوع خلف وسم بناء (build tag) ولا يُصرَّف في الملفات التنفيذية للإصدارات.
فئة واحدة وما يعنيه غياب المفتاح. التثبيت بلا مفتاح ترخيص لا يُرفض. بل يعمل مجانًا لثلاثة مطوّرين ومساحة عمل واحدة مع كل الميزات. أي المشرف وشخصان آخران. والحدّ نفسه للدعوات ولأول تسجيل دخول عبر SSO. ويزيل الترخيص حدّ المقاعد لأي عدد من المطوّرين ومساحات العمل ويُصدَر لكلستر واحد مسمّى. وكل ميزة موجودة في الحالتين. وقد تظل التراخيص الصادرة قبل اعتماد الفئة الواحدة تسمّي خطة في حمولتها وكل خطة تحمل كل الميزات.
| حالة الترخيص | ما يحدث |
|---|---|
missing (لا مفتاح مثبّت) |
مجاني: 3 مطوّرين ومساحة عمل واحدة مع كل الميزات |
valid |
مقاعد الترخيص مع كل الميزات |
grace |
يستمر كل شيء. وتصرّح لوحة التحكم بتاريخ الانتهاء |
expired (بعد فترة السماح) |
يُرفض عمود «ما يُفحص» أدناه فقط. ولا يتوقف شيء |
invalid (توقيع غير صالح أو مفتاح تطوير في بناء إصدار) |
يُرفض في واجهة API وفي خطاف القبول |
missing وinvalid مختلفان عن قصد. فالحالة الأولى تعني شخصًا يقيّم المنتج. والثانية تعني شخصًا ثبّت
شيئًا بطريقة خاطئة. ومعاملة الثانية بصمت على أنها الفئة المجانية ستُخفي ذلك.
أين يُفرض بالتحديد. الترخيص آلية تجارية وليس حدًا أمنيًا. ومن المفيد تحديد ما يستطيع منعه وما لا يستطيع بدقة لأن فريق الأمان سيسأل عن ذلك.
| ما يُفحص | ما لا يُفحص |
|---|---|
| إنشاء بيئة | إيقاظ بيئة نائمة |
| تمديد المدة (TTL) لبيئة | فتح رابط معاينة |
| مزامنة بيئة | قراءة سجل التدقيق أو تصديره |
| إنشاء بيئة لطلب دمج (per-PR) من خطاف ويب | تسجيل الدخول وقراءة لوحة التحكم |
| بناء خدمة من المصدر | أي شيء يعمل بالفعل |
الميزات الاختيارية: terminal وsiem وsaml وper-pr وbuild وexec-reports |
قراءة حالة بناء أو سجلاته |
كل ما في عمود «ما لا يُفحص» مقصود. فالمطوّر الذي يفتح معاينته الخاصة يجب ألا يواجه خطأ فوترة أبدًا. والمدقّق يجب ألا يُقال له أبدًا إن الأدلة غير متاحة لأسباب تجارية. ولا يُحذف شيء أو يُوقف أبدًا بسبب حالة الترخيص.
عند انتهاء الترخيص تبدأ فترة سماح (30 يومًا أو 7 أيام للنسخة التجريبية) يستمر خلالها كل شيء في العمل وتصرّح لوحة التحكم بذلك. وبعد فترة السماح يُرفض عمود «ما يُفحص» فقط. يُنبَّه المشرفون قبل الانتهاء بـ 30 يومًا ثم مجددًا قبله بـ 14 و7 و3 أيام ويوم واحد. ويُنبَّهون في يوم الانتهاء نفسه وأسبوعيًا طوال فترة السماح ومرة أخرى عند التجميد. ويصدر كل تنبيه عبر كل قناة من القنوات التالية حتى يصل التنبيه أيضًا إلى الموقع المعزول عن الإنترنت الذي لا يملك مرحّل بريد:
- البريد الإلكتروني
- مقياس Prometheus
- حدث Kubernetes
- شريط في لوحة التحكم
- سطر في CLI
وتثبيت مفتاح مجدَّد يرفع التجميد عند الطلب التالي.
أعداد المقاعد مرنة: تجاوزها يُطلق تحذيرًا ويُتسامح مع زيادة مؤقتة بنسبة 10%. وما بعد ذلك تُرفض الدعوات الجديدة بينما يستمر كل من يعمل بالفعل. يجري الفرض في واجهة API. وهي أيضًا حيث يُكتب سجل التدقيق ولذلك يكون رفض الترخيص قابلًا للتدقيق. لا يفرض المشغّل الترخيص. ولا تُقطع بسببه أبدًا بيئة قيد التسوية.
البناء من المصدر
هذا هو الشيء الوحيد في نزال الذي ينفّذ عن قصد شيفرة كتبها مطوّرو العميل على كلستر العميل. ومن المفيد تحديد ما يكلّفه ذلك وما يحصره بدقة.
ما الذي يعمل. ملف Dockerfile من المستودع مع كل ما ينفّذه عبر RUN وكل تبعية يجلبها.
ويُعامل كل ذلك مدخلاتٍ غير موثوقة.
أين. مساحة أسماء واحدة اسمها nezal-build تحوي مهام (Jobs) البناء ولا شيء غيرها. وهي مساحة
الأسماء الوحيدة التي يشغّلها نزال بمعيار Pod Security Standard من مستوى privileged.
فـ BuildKit بلا صلاحيات الجذر (rootless) يربط مساحة أسماء المستخدم الخاصة به. وهذا يحتاج إلى
ملف seccomp غير مقيّد والمعيار "baseline" يمنع ذلك منعًا صريحًا. هذا هو ثمن بناء صور الحاويات
داخل كلستر من دون Docker daemon وهو غير مخفي في ملف values.
ما الذي يحصره:
| الضابط | الأثر |
|---|---|
لا رمز حساب خدمة (automountServiceAccountToken: false) |
لا يستطيع البناء التحدث إلى واجهة Kubernetes API إطلاقًا. |
| يعمل بالمعرّف uid 1000 وليس الجذر أبدًا | لا شيء في البناء يعمل بصلاحيات الجذر لا داخل الحاوية ولا على العقدة. |
إسقاط جميع القدرات (capabilities) عدا SETUID وSETGID |
القدرتان اللتان يحتاجهما BuildKit بلا صلاحيات الجذر لربط مساحة أسماء المستخدم. وتنطبق كلتاهما ضمن مساحة أسماء الحاوية نفسها. |
| لا مقبس Docker ولا مسار مضيف (host path) ولا حاوية مميزة الصلاحيات (privileged) | مقبس Docker المركّب يعني صلاحيات الجذر على العقدة. ولا يوجد أي مقبس. |
| قائمة سماح في NetworkPolicy | يصل البناء إلى DNS وخادم git وسجل الصور ومرايا التبعيات التي أعلنها الفريق. ولا شيء غير ذلك. أي جلب من الإنترنت العام يفشل بدلًا من أن ينجح بصمت. |
| استثناء نطاق link-local من كل نطاق مسموح | تسلّم البيانات الوصفية للمثيل السحابي على 169.254.169.254 بيانات اعتماد لأي شيء يستطيع الوصول إليها. |
activeDeadlineSeconds وحدود المعالج والذاكرة المضبوطة لكل فريق |
لا يستطيع البناء أن يتعلّق بلا نهاية ولا أن يستنزف الكلستر بأمر make -j. |
backoffLimit: 0 |
يُبلَّغ عن البناء الفاشل ويُفحص. ولا يُعاد بصمت أبدًا في Pod جديد بعد ضياع سجلات الـ Pod السابق. |
| حاوية منفصلة لجلب الشيفرة (checkout) | تُستخدم بيانات اعتماد git في حاوية تهيئة (init container) ولا تكون مرئية أبدًا لحاوية البناء حيث تعمل شيفرة المستودع. |
| فحص وسائط البناء عند القبول | تُسجَّل في تاريخ الصورة ويستطيع قراءتها كل من يقدر على سحبها. ولذلك يُرفض أي شيء يحمل اسمًا يشبه بيانات الاعتماد. |
| فحص مسارَي السياق وDockerfile عند القبول | المسار الذي يخرج من مجلد الشيفرة المجلوبة سيقرأ نظام ملفات المهمة (Job) نفسها. |
ما الذي ينتجه. صورة تُدفع إلى سجل الصور الخاص بالعميل وتُوسم بالـ commit وتُنشر بالملخّص (digest): فالوسم يمكن نقله لاحقًا أما الملخّص فلا. يُدقَّق كل بناء مع الـ commit والملخّص. والبناء دائمًا لـ commit واحد محدَّد لا لفرع. ولذلك لا يستطيع بناءان لـ "main" أن ينتجا صورتين مختلفتين تحت اسم واحد.
إيقافه. يزيل build.enabled: false في المخطط (chart) مساحة الأسماء بالكامل. وتتحكم ميزة
الترخيص build في إتاحته تجاريًا. ويمكن لسياسة الفريق تعطيله على نحو مستقل: فقد يُسمح لفريق ببيئات
شخصية من دون أن يُسمح له بتنفيذ خطوات بناء عشوائية.
لا فحص مدمج للصور. لا يفحص نزال الصور ولا يعتمد على أي أداة فحص. تصل الصورة المبنية إلى سجل الصور لدى العميل حيث تستطيع أداة الفحص الخاصة به أن تفحصها.
صور المعاينة ما زالت غير موقّعة. يوقّع خط الإصدار ما يُطرح للعملاء. أما صورة المعاينة فتُبنى من
فرع مطوّر وتستخدمها بيئة واحدة وتُحذف معها. ولذلك فإن التوقيع سيشهد على شيء لا يرقّيه أحد إلى الإنتاج.
والعميل الذي تشترط سياسته توقيع كل صورة في الكلستر ينبغي أن يبني الصور في سجل الصور وخط البناء (pipeline)
الخاصين به بدلًا من ذلك. وإعداد registry لكل مساحة عمل موجود لهذا الغرض بالتحديد.
سلسلة الإمداد
جميع الملفات التنفيذية مبنية بلغة Go بربط ثابت (static) على صور distroless. وتعمل بمستخدم غير الجذر مع نظام ملفات جذر للقراءة فقط وإسقاط جميع القدرات. والتبعيات الخارجية هي:
- مكتبات عميل Kubernetes
- Helm SDK
- kustomize
- go-git
- go-oidc
- crewjam/saml
- golang-jwt
- coder/websocket
- modernc SQLite
- cobra
- عميل Prometheus
يقوم كل إصدار بثلاثة أشياء:
- يبني صورًا متعددة المعماريات (amd64 وarm64)
- ينتج SBOM لكل صورة بصيغتَي SPDX وCycloneDX
- يوقّع كل صورة بالملخّص (digest) باستخدام cosign ويُرفق SBOM بوصفه شهادة (attestation)
والتوقيع بالملخّص لا بالوسم مهم: فالوسم يمكن نقله إلى صورة مختلفة بعد التوقيع وسيظل التوقيع على الاسم صالحًا عند التحقق.
تحمل حزمة التثبيت المعزول (air-gap bundle) ملفات SBOM هذه والتوقيعات إلى جانب الصور. ولذلك يستطيع العميل الذي لا يملك مسارًا إلى الإنترنت التحقق مما يثبّته.
الفجوات المعروفة
نذكرها بوضوح لأن الورقة البيضاء التي لا تذكر أي فجوة لا تُصدَّق.
- روابط المعاينة في الوضع الكامل لا تتطلب تسجيل الدخول بعد. النسخة الكاملة ليس لها موجّه. ويرسل الـ Ingress الخاص بها الحركة مباشرة إلى الـ Service ولذلك يستطيع كل من يصل إلى الـ ingress أن يفتح المعاينة. أبقِ الـ ingress خلف ضوابط الشبكة الخاصة بك حتى تُغلق هذه الفجوة.
- واجهة API نسخة واحدة (single replica) ونقطة فشل واحدة لمستوى التحكم. تسمح SQLite بكاتب واحد. يوقف انقطاع واجهة API تسجيل الدخول وإنشاء البيئات ولوحة التحكم. ولا يوقف البيئات العاملة ولا حركة مرور المعاينة ولا التوجيه المعتمد على الترويسات ولا عمليات التسوية في المشغّل. يُغطّى التعطّل المخطط له بـ PodDisruptionBudget. أما فقدان عقدة غير مخطط له فيعني إعادة جدولة ومدة إعادة الجدولة هذه هي زمن التعافي المستهدف (RTO).
- ملف تعريف الارتباط الخاص بالمعاينة ليس جلسة. إبطال جلسة نزال لا يبطل ملف تعريف ارتباط للمعاينة (preview cookie) صدر من قبل حتى تنتهي صلاحيته. وتحدّ مدة ثماني ساعات من ذلك. وتقليصها تغيير في ملف values.
- مفتاح الترخيص المسرَّب يعمل حتى انتهاء صلاحيته. يملك العميل صلاحية cluster-admin على أي حال ولذلك فهذا رادع تعاقدي لا تقني. ويثبّت الربط الاختياري بالكلستر المفتاح على كلستر واحد.
- لا تُنقل إلا الحاوية الأولى من كل عبء عمل (workload). وتُسقط الحاويات الجانبية (sidecars) مع تحذير يسمّي كل واحدة منها.
- لا يُنقل ConfigMap أو Secret مركّب كمجلد كامل لأن مفاتيحه لا تُعرف إلا وقت النشر. أما
الملفات المسمّاة فتُنقل. اذكرها تحت
itemsفي المصدر. - تصبح طلبات وحدات التخزين الدائمة (PVC) مجلدات فارغة في البيئة ويصرّح تحذير بذلك. فالمعاينة المعاد بناؤها من المستودع لا تستطيع أن تحمل حالة وأن تبقى قابلة للاستنساخ في الوقت نفسه.
- حصص الفريق لكل مساحة أسماء تطبيق لا لكل شخص عبر مساحات الأسماء.
أُغلقت منذ v0.1:
- روابط المعاينة في الوضع المشترك تتطلب الآن تسجيل الدخول. ويتحقق الموجّه من ملف تعريف ارتباط موقّع تصدره واجهة API بعد التحقق المعتاد من الجلسة.
- تُنقل الآن من المصدر مسابر الفحص (probes) وConfigMap وSecret المركّبة. وكذلك وحدات التخزين المؤقتة ومجلد العمل والمعرّف uid.
- يقدّم سجل الصور المضمّن الاختياري TLS من شهادة يُصدرها المشغّل ويجدّدها من جهة الإصدار (CA) الخاصة به بدلًا من HTTP عادي مع تعطيل التحقق على كل عقدة.