migration لـ Pack بين إصدارات Helm Chart
تحوّل Pack Migration ملفات Pack الحالية عند تغيير بنية values أو vars أو إصدار Chart، وتحافظ على اختيارات المستخدم من دون إعادة كتابة كل ملف يدويا.
هذه الصفحة مرجع إنشاء pack-migrations.yaml واختباره. راجع إمكانات Pack في Helm Chart للملفات والميزات الأخرى.
تعريف migration باستخدام pack-migrations.yaml
يحدد pack-migrations.yaml تحويل ملف Pack عند تغير البنية أو الإصدار. يجب أن يوجد بهذا الاسم في جذر Chart بجانب Chart.yaml.
يقرأ Pack Operator الملف من Chart الهدف. يجب أن يحتوي كل إصدار منشور على سلسلة كاملة من جميع الإصدارات القديمة المدعومة إلى الهدف، حتى لا يضطر المستخدم الذي يتجاوز عدة إصدارات إلى تثبيت الإصدارات الوسطية.
migrations:
- repo: kubit-paas
chart: redis
from_version: '>=0.1.0, <0.2.0'
to_version: '~=0.2.0'
context:
metrics_default: true
steps:
- set:
values: !var pack.spec.values
values.metrics.enabled: !default-var metrics_default
- if: values.password
set:
values.auth.password: !pop values.password
- reorder:
values:
- auth
- metrics
| الحقل | مطلوب | الاستخدام |
|---|---|---|
repo | نعم | اسم مورد المستودع في spec.chart.repository.name |
chart | نعم | اسم Chart في spec.chart.name |
from_version | نعم | إصدار المصدر أو قيده |
to_version | نعم | قيد الإصدار الذي يكتب في الملف الناتج |
steps | نعم | قائمة التحويلات المرتبة، أو قائمة فارغة إذا لم يلزم تحويل |
context | لا | متغيرات مؤقتة أولية لـ steps وتعبيرات Jinja |
repo هو اسم مورد المستودع وليس URL. تتطابق قيمتا repo وchart بدقة ولا تقبلان wildcard. لا يطابق ملف Pack الذي لا يحتوي على spec.chart.version أي migration.
اختيار الإصدارات وربطها
يدعم from_version مقارنات semantic version:
| المثال | الإصدارات المطابقة |
|---|---|
'<2.0.0' | أقل من 2.0.0 |
'>=2.0.0, <2.3.0' | من 2.0.0 وحتى ما قبل 2.3.0 |
'~=2.3.0' | فرع 2.3.x |
'<v1.19.4' | أقل من 1.19.4 مع بادئة v |
ضع التعبير بين علامتي اقتباس، خصوصا إذا بدأ بـ < أو >. يجب أن تتحقق كل الشروط المفصولة بفاصلة.
قبل كل migration، يضبط المشغّل spec.chart.version إلى to_version. ثم يفحص migrations اللاحقة بالإصدار الجديد، ولذلك يمكن لعدة entries تكوين سلسلة:
migrations:
- repo: kubit-paas
chart: redis
from_version: '<0.3.0'
to_version: '~=0.3.0'
steps: []
- repo: kubit-paas
chart: redis
from_version: '>=0.3.0, <0.5.0'
to_version: '~=0.5.0'
steps: []
ينتقل Pack بإصدار 0.2.0 إلى فرع 0.3 ثم 0.5. يجب ألا يطابق to_version قيمة from_version في entry نفسها حتى لا تتكرر لاحقا.
ترتيب entries في الملف ليس ترتيب التنفيذ النهائي. يرتبها المشغّل حسب المستودع واسم Chart وصيغة from_version المنظفة. اختبر الترتيب الفعلي في سلاسل مثل 1.9 و1.10.
المسارات وcontext
تُفصل المسارات بنقطة، مثل pack.spec.values.service.port. لكل entry سياق مستقل يحتوي على:
| الاسم | القيمة |
|---|---|
pack | ملف Pack كامل وقابل للتغيير |
true | قيمة boolean تساوي true |
false | قيمة boolean تساوي false |
null | قيمة null |
مفاتيح context | متغيرات مؤقتة في entry نفسها |
اختصر المسارات بإنشاء aliases في بداية migration:
- set:
chart: !var pack.spec.chart
values: !var pack.spec.values
chart.autoUpgrade: !default-var true
تشير mapping أو list المقروءة عبر !var إلى البيانات الأصلية، ولذلك يبقى تغيير values.service.port داخل pack.spec.values. لا يكتب متغير مؤقت مثل old_port في المخرجات ولا ينتقل بين entries.
تعيد قراءة مسار غائب null. وينشئ المسار المكتوب mappings الوسطية الغائبة، لكن تُتجاهل كتابة null.
إذا احتوى key على نقطة فعلية، استخدم \. وضع المسار كله بين علامتي اقتباس مفردتين:
- set:
copied: !var 'values.annotations.example\.com/key'
'values.annotations.example\.com/key': enabled
الجزء الرقمي من المسار ليس index في list. استخدم item_in_list لقراءة عنصر list أو تغييره.
عمليات migration
كل عنصر في steps هو step. تنفذ العمليات دائما بهذا الترتيب:
- شرط
ifأو فرعelse. - البحث عبر
item_in_list. - التعيين عبر
set. - تنفيذ
stepsالمتداخلة. - الترتيب عبر
reorder.
اجعل كل step صغيرا. اجمع عدة عمليات في step واحدة فقط إذا كان ترتيب تنفيذها الثابت مطلوبا، مثل العثور على عنصر list قبل تغييره عبر set.
tags الخاصة بـ set
| tag | السلوك |
|---|---|
!default | كتابة قيمة ثابتة إذا غاب key الهدف فقط |
!default-var | كتابة قيمة من context إذا غاب الهدف فقط |
!var | قراءة مسار من context من دون حذف المصدر |
!pop | حذف قيمة المصدر ونقلها إلى الهدف |
!pop-empty | حذف قيمة falsey فقط، لتنظيف mappings الفارغة |
!merge | دمج mapping المصدر داخل الهدف بشكل تكراري |
!jinja | معالجة القيمة عبر Jinja مع حفظ نوعها |
تستبدل القيمة من دون tag الهدف. للحفاظ على اختيار المستخدم، اقرأ key القديم بـ !pop واضبط القيمة الافتراضية للهدف بـ !default-var. استخدم !default لقيمة جديدة لا يجب أن تستبدل قيمة موجودة، حتى إذا كانت false أو صفرا أو فارغة.
لا تستخدم !pop-empty لنقل البيانات. فهي تحذف قيمة falsey فقط، وتكتب false في الهدف عندما لا يُحذف شيء. استخدم أسماء مؤقتة ونظف من المسار الأعمق إلى الأب:
- set:
_: !pop values.deprecatedOption
_1: !pop-empty values.legacy.child
_2: !pop-empty values.legacy
مع !merge يجب أن يكون المصدر والهدف mappings. أنشئ الهدف أولا بـ !default إذا كان قد لا يوجد.
يمكن لـ !jinja إنتاج boolean أو رقم أو list أو mapping. استخدم filter باسم default أو d للمسار الاختياري؛ الوصول المباشر إلى متغير غير معرّف يوقف migration بخطأ.
الشروط وsteps المتداخلة
يحوّل الشرط البسيط قيمة المسار إلى boolean. يعكس !not النتيجة، ويستخدم !jinja للمقارنة أو الشرط المركب:
- if: values.ingress.enabled
set:
values.ingress.className: !default nginx
- if: !not values.persistence.enabled
set:
_: !pop values.persistence
- if: !jinja '{{ values.mode | d("standard") == "legacy" }}'
steps:
- set:
values.mode: standard
else:
- set:
values.mode: !default standard
يجب أن يكون else بجانب if ويحتوي على قائمة steps. إذا لم يتحقق الشرط، تنفذ steps في else فقط وتُتجاهل العمليات الأخرى في step الخارجية.
تغيير عناصر list باستخدام item_in_list
يجد item_in_list mapping داخل list عبر key وvalue أو عبر index، ويحفظ العنصر في المتغير المؤقت var:
- set:
values.service.ports: !default []
- item_in_list:
list: values.service.ports
key: name
value: http
create: true
var: http_port
set:
http_port.port: !default 6379
http_port.protocol: !default TCP
أنشئ list أولا عبر !default []، وإلا فقد يُضاف العنصر إلى list مؤقتة غير مرتبطة بـ Pack.
لا يمكن استخدام key وindex معا. يسبب index خارج النطاق خطأ. من دون create: true، لا يأخذ var قيمة إذا لم يوجد عنصر؛ احم steps اللاحقة بـ if. تقبل value قيمة ثابتة أو !var أو !pop فقط.
أماكن tags المسموحة
| القيمة أو tag | قيمة set | شرط if | item_in_list.value |
|---|---|---|---|
| YAML عادي | نعم | مسار فقط | نعم |
!var | نعم | لا | نعم |
!pop | نعم | لا | نعم |
!pop-empty | نعم | لا | لا |
!default | نعم | لا | لا |
!default-var | نعم | لا | لا |
!merge | نعم | لا | لا |
!jinja | نعم | نعم | لا |
!not | لا | نعم | لا |
ترتيب المخرجات باستخدام reorder
ينقل reorder المفاتيح المحددة إلى بداية mapping موجودة حسب الترتيب المطلوب. تبقى المفاتيح الأخرى بعدها. يغير ذلك قراءة YAML فقط ولا يغير سلوك Helm.
- reorder:
pack.spec.values:
- global
- service
- ingress
pack.spec.values.service:
- enabled
- type
- ports
أخطاء شائعة في pack-migrations.yaml
| الخطأ | النتيجة أو التصحيح |
|---|---|
وضع URL المستودع في repo | لا تطابق؛ استخدم spec.chart.repository.name |
| حفظ آخر migration تدريجية فقط | لا تملك Packs التي تجاوزت إصدارات مسارا كاملا |
ضبط spec.chart.version في step | زائد؛ يطبق المشغّل to_version قبل steps |
استخدام !pop لقيمة افتراضية جديدة | المصدر الغائب لا ينتج شيئا؛ استخدم !default أو !default-var |
استخدام !pop-empty للنقل | تبقى القيمة truthy؛ استخدمها للتنظيف فقط |
استخدام Jinja من دون !jinja | يُحفظ التعبير كنص |
| افتراض أن ترتيب الملف هو التنفيذ | اختبر النطاقات والسلسلة بمحرك migration الفعلي |
اختبار migration قبل النشر
kubit pack migrate -f redis.pack.yaml \
--local-chartpath ./redis
يعرض الأمر الملف الناتج في stdout. قارنه بالإدخال وتأكد من تغير الإصدار والمسارات المطلوبة فقط. تُطبّع المخرجات وقد يُحذف spec.managed: true؛ غياب spec.managed يعادل true.
اختبر لكل مسار:
- أقدم إصدار مدعوم وحدي البداية والنهاية لكل
from_version. - Pack قبل كل migration وسطية وPack يمر بالسلسلة كاملة.
- قيم المستخدم المخصصة و
falseوالصفر والقيمة الفارغة والحقل الاختياري الغائب. - عنصر list موجود وغائب وindex غير صالح.
- التشغيل مرة ثانية، ويجب ألا ينشئ تغييرا جديدا خاصا بـ migration.
- معالجة Chart الهدف أو diff باستخدام الملف الناتج.
راجع التغيير الدلالي في values بالإضافة إلى diff النصي. قد يظهر ترتيب الحقول وتنظيف metadata حتى إذا لم تعرفه steps مباشرة.
kubit pack migrate -f redis.pack.yaml \
--local-chartpath ./redis \
--inline
يغير --inline ملف الإدخال. احتفظ بالإصدار السابق في Git وتحقق من المسار. راجع مرجع pack migrate لاختيار الهدف أو تشغيله على Pack في cluster.
في الترقية التلقائية، يفحص Pack Operator migration المطابقة. إذا أنتجت تغييرا صالحا، يُستبدل ملف Pack بالنتيجة. إذا لم توجد أو فشلت، تستمر الترقية العادية؛ لا يضمن خطأ migration توقف الترقية.