تحرير ملفات إعداد YAML باستخدام yq
اقرأ ملفات YAML الخاصة بـ Kubernetes وCI وعدّلها في موضعها باستخدام yq مع الحفاظ على البنية والتعليقات
تحرير ملفات إعداد YAML باستخدام yq درس مجاني في DevOps Bootcamp على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في DevOps Bootcamp، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة DevOps Bootcamp 4 دروس في المجموع.
ما هي yq ولماذا تُستخدم مع YAML؟
yq هو معالج YAML محمول لسطر الأوامر، ويشبه jq في طريقة تعامله مع JSON. يتيح لك قراءة ملفات YAML وتصفيتها وتعديلها من دون كتابة برنامج نصي بلغة Python أو Ruby.
توجد أداتان شائعتان تحملان اسم yq:
- mikefarah/yq (Go) — تُصان بنشاط، وتدعم YAML وJSON وXML وTOML. يستخدم هذا الدرس هذا الإصدار.
- kislyuk/yq (Python) — غلاف لـ
jqمخصص لـ YAML؛ وتختلف صياغته.
ثبّت إصدار Go:
brew install yqعلى macOSsnap install yqعلى Linux- أو نزّل الملف التنفيذي:
wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/local/bin/yq && chmod +x /usr/local/bin/yq
للتحقق: يجب أن يطبع yq --version الإصدار v4.x.x. يستخدم الإصدار 4 صياغة تعبيرات مختلفة عن الإصدار 3، لذلك يهمّ الإصدار المستخدم.
# Install yq (Go version) on Linux
wget -q https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 \
-O /usr/local/bin/yq
chmod +x /usr/local/bin/yq
# Confirm version
yq --versionقراءة القيم من ملف YAML لنشر Kubernetes
قبل تعديل أي شيء، تعلّم قراءة حقول YAML. انطلاقًا من Deployment في Kubernetes، يمكنك استخراج أي قيمة متداخلة باستخدام مسارات التدوين النقطي.
مثال على deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: production
spec:
replicas: 3
template:
spec:
containers:
- name: app
image: my-app:1.0.0أهم أوامر القراءة:
yq '.metadata.name' deployment.yaml— يطبعmy-appyq '.spec.replicas' deployment.yaml— يطبع3yq '.spec.template.spec.containers[0].image' deployment.yaml— يطبعmy-app:1.0.0
تكون المخرجات نصًا عاديًا افتراضيًا (من دون علامات اقتباس). أضف الخيار -r أو استخدم | yq -r إذا احتجت إلى سلاسل نصية خام في البرامج النصية.
# Create a sample deployment YAML
cat > /tmp/deployment.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: production
spec:
replicas: 3
template:
spec:
containers:
- name: app
image: my-app:1.0.0
EOF
# Read individual fields
echo "App name: $(yq '.metadata.name' /tmp/deployment.yaml)"
echo "Replicas: $(yq '.spec.replicas' /tmp/deployment.yaml)"
echo "Image: $(yq '.spec.template.spec.containers[0].image' /tmp/deployment.yaml)"التعديل في موضعه باستخدام الخيار -i
أهم خيار للاستخدام العملي هو -i (التعديل في موضعه). من دونه، تطبع yq النتائج إلى stdout وتترك الملف من دون تغيير.
الصياغة:
- القراءة فقط (stdout):
yq '.spec.replicas' file.yaml - التعديل في الموضع:
yq -i '.spec.replicas = 5' file.yaml
يعيّن عامل الإسناد = قيمة. والتعبير عبارة عن مرشح yq كامل، لذا يمكنك الجمع بين القراءة والكتابة في مرور واحد.
مهم: يعيد yq -i كتابة الملف بالكامل. تُحفظ التعليقات الموضوعة في السطر نفسه مع الحقل عمومًا، لكن قد تنتقل مجموعات التعليقات المستقلة. احرص دائمًا على حفظ YAML في نظام التحكم بالإصدارات قبل إجراء تعديلات جماعية في الموضع.
اختبر أولًا من دون -i، ثم أضفه عندما ترضى عن المخرجات.
# Start with the deployment from the previous scene
echo 'Before:' && yq '.spec.replicas' /tmp/deployment.yaml
# Edit in place: scale to 5 replicas
yq -i '.spec.replicas = 5' /tmp/deployment.yaml
echo 'After:' && yq '.spec.replicas' /tmp/deployment.yamlتحديث وسم صورة الحاوية
من مهام CI الشائعة جدًا تحديث وسم صورة Docker في بيان Kubernetes بعد إنشاء صورة جديدة. وباستخدام yq، يصبح ذلك أمرًا واحدًا.
النمط هو:
- استهدف الحاوية حسب الاسم باستخدام
select()لتجنب تثبيت فهرس المصفوفة على قيمة 0. - استخدم
|=(عامل التحديث) أو=لتعيين القيمة الجديدة.
باستخدام فهرس المصفوفة (وهو أسلوب هش إذا تغيرت قائمة الحاويات):
yq -i '.spec.template.spec.containers[0].image = "my-app:2.1.0"' deployment.yaml
باستخدام select() (أسلوب متين):
yq -i '(.spec.template.spec.containers[] | select(.name == "app")).image = "my-app:2.1.0"' deployment.yaml
في مسار CI، ستمرّر الوسم كمتغير shell:
NEW_TAG="my-app:2.1.0"
CONTAINER_NAME="app"
# Robust update: target by container name, not index
yq -i \
"(.spec.template.spec.containers[] | select(.name == \"${CONTAINER_NAME}\")).image = \"${NEW_TAG}\"" \
/tmp/deployment.yaml
# Verify
yq '.spec.template.spec.containers[0].image' /tmp/deployment.yamlإضافة الحقول وإزالتها
بالإضافة إلى تحديث الحقول الموجودة، يمكن لـ yq إضافة مفاتيح جديدة أو حذف المفاتيح الموجودة.
إضافة حقل:
- عيّن قيمة لمسار غير موجود ببساطة:
yq -i '.metadata.labels.version = "v2"' file.yaml - إذا كان المفتاح الأب (
labels) مفقودًا، ينشئه yq تلقائيًا.
حذف حقل:
- استخدم الدالة
del():yq -i 'del(.metadata.annotations)' file.yaml - احذف عنصرًا من مصفوفة حسب الفهرس:
yq -i 'del(.spec.template.spec.containers[1])' file.yaml
إضافة عنصر إلى مصفوفة:
yq -i '.spec.template.spec.containers += [{"name": "sidecar", "image": "envoy:latest"}]' file.yaml
# Add a label to the deployment
yq -i '.metadata.labels.version = "v2"' /tmp/deployment.yaml
yq -i '.metadata.labels.managed-by = "ci-pipeline"' /tmp/deployment.yaml
echo '--- Labels after adding ---'
yq '.metadata.labels' /tmp/deployment.yaml
# Delete one label
yq -i 'del(.metadata.labels.managed-by)' /tmp/deployment.yaml
echo '--- Labels after delete ---'
yq '.metadata.labels' /tmp/deployment.yamlالتعامل مع ملفات YAML متعددة المستندات
غالبًا ما تجمع بيانات Kubernetes عدة موارد في ملف واحد، وتفصل بينها ---. يعالج yq افتراضيًا جميع المستندات في هذا الملف.
أهم الأساليب:
- سرد أنواع جميع المستندات:
yq '.[].kind' multi.yaml— لاحظ.[]في البداية للتكرار على المستندات. - استهداف مستند معين حسب النوع:
yq 'select(.kind == "Service")' multi.yaml - تعديل المستندات المطابقة فقط في مواضعها:
yq -i 'select(.kind == "Deployment").spec.replicas = 2' multi.yaml
تمرَّر المستندات التي لا تطابق شرط select() من دون تغيير، لذلك تظل موارد Service وConfigMap وغيرها سليمة.
لتقسيم ملف متعدد المستندات إلى ملفات منفردة، يمكنك التكرار على مخرجات yq أو استخدام:
yq -s '.kind' multi.yaml— يكتب ملفًا واحدًا لكل مستند، ويسميه وفق قيمة.kindالخاصة به.
cat > /tmp/multi.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 1
---
apiVersion: v1
kind: Service
metadata:
name: web-svc
spec:
port: 80
EOF
# Scale ONLY the Deployment, leave Service untouched
yq -i 'select(.kind == "Deployment").spec.replicas = 4' /tmp/multi.yaml
echo '--- Deployment replicas ---'
yq 'select(.kind == "Deployment").spec.replicas' /tmp/multi.yaml
echo '--- Service port (unchanged) ---'
yq 'select(.kind == "Service").spec.port' /tmp/multi.yamlتعديل YAML الخاص بـ CI في GitHub Actions
ملفات إعداد CI (.github/workflows/*.yml و.gitlab-ci.yml) هي أيضًا ملفات YAML. تعمل أوامر yq نفسها معها، رغم أن المسارات قد تكون متداخلة بعمق.
مهام تعديل CI الشائعة:
- تثبيت إصدار بيئة التشغيل: حدّث
runs-onعبر جميع المهام. - تحديث إصدار إجراء: ابحث عن الخطوات التي تستخدم إجراءً معينًا، ثم حدّث قيمة الحقل
usesالخاص بها. - تبديل علامة: فعّل إعدادًا على مستوى سير العمل أو عطّله.
مثال: تحديث جميع الخطوات التي تستخدم actions/checkout إلى الإصدار v4:
yq -i '(.jobs[].steps[] | select(.uses == "actions/checkout@v3")).uses = "actions/checkout@v4"' .github/workflows/ci.ymlهذا الأسلوب — التكرار باستخدام []، والتضييق باستخدام select()، والإسناد باستخدام = — هو النمط الأساسي لأي تعديل منظم في YAML.
cat > /tmp/ci.yml << 'EOF'
name: CI
on: [push]
jobs:
build:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- run: npm test
lint:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- run: npm run lint
EOF
# Bump all checkout steps from v3 → v4
yq -i '(.jobs[].steps[] | select(.uses == "actions/checkout@v3")).uses = "actions/checkout@v4"' \
/tmp/ci.yml
# Verify both jobs were updated
yq '.jobs[].steps[] | select(.uses | test("checkout")).uses' /tmp/ci.ymlاستخدام متغيرات البيئة في تعبيرات yq
يجعل تثبيت القيم داخل تعبيرات yq البرامج النصية هشة. يدعم yq حقن متغيرات shell باستخدام الدالة env() أو الاختصار strenv().
env(VAR_NAME)— يقرأ متغير البيئة ويحوّله إلى نوع YAML المناسب (يبقى الرقم رقمًا، وتبقى السلسلة النصية سلسلة نصية).strenv(VAR_NAME)— يُرجع دائمًا سلسلة نصية، وهو مفيد لوسوم الصور.
يحول ذلك دون مشكلة الاقتباس المعقدة الناتجة عن إدراج المتغيرات داخل سلاسل shell المقتبسة بعلامات اقتباس مزدوجة، والتي تتضمن مسارات YAML.
النمط:
export IMAGE_TAG="my-app:3.0.0"
yq -i '.spec.template.spec.containers[0].image = strenv(IMAGE_TAG)' deployment.yamlاستخدم env() عند تعيين حقول رقمية مثل replicas للحفاظ على نوع YAML (عدد صحيح، وليس سلسلة نصية بين علامتي اقتباس).
export APP_IMAGE="my-app:3.0.0"
export REPLICA_COUNT=6
# Set image using strenv() — result is a YAML string
yq -i '.spec.template.spec.containers[0].image = strenv(APP_IMAGE)' \
/tmp/deployment.yaml
# Set replicas using env() — result is a YAML integer
yq -i '.spec.replicas = env(REPLICA_COUNT)' \
/tmp/deployment.yaml
# Confirm types are correct in the output
yq '.spec.replicas, .spec.template.spec.containers[0].image' /tmp/deployment.yamlدمج ملفَّي YAML
قد تحتاج أحيانًا إلى تطبيق ملف patch (ملف YAML صغير للتجاوز) على إعداد أساسي — مثل التجاوزات الخاصة بكل بيئة في أساليب العمل المشابهة لـ Kustomize.
يمكن لـ yq دمج ملفَّين باستخدام عامل الدمج *:
yq '. *= load("patch.yaml")' base.yaml— يدمج ملف patch بعمق في الملف الأساسي، ويكتب الناتج إلى stdout.- أضف
-iلتحديث الملف الأساسي في مكانه:yq -i '. *= load("patch.yaml")' base.yaml
سلوك الدمج:
- القيم المفردة في ملف patch تستبدل القيم الموجودة في الملف الأساسي.
- تُدمج الخرائط بعمق (وتُحافَظ على المفاتيح غير الموجودة في ملف patch).
- تُستبدل التسلسلات (المصفوفات) افتراضيًا ولا تُضاف إلى بعضها. استخدم
*+للإلحاق بدلًا من ذلك.
يستبدل هذا النمط نصوص sed الهشة التي تتعطل عند تغيّر المسافات البيضاء.
cat > /tmp/base.yaml << 'EOF'
app:
name: my-service
port: 8080
debug: false
database:
host: localhost
port: 5432
EOF
cat > /tmp/patch.yaml << 'EOF'
app:
port: 9090
debug: true
database:
host: db.production.svc
EOF
# Deep-merge patch into base (stdout preview first)
yq '. *= load("/tmp/patch.yaml")' /tmp/base.yaml
# Apply in place
yq -i '. *= load("/tmp/patch.yaml")' /tmp/base.yamlالتحقق من صحة YAML وتحويله إلى JSON
قبل تطبيق YAML المُعدَّل على عنقود، من الممارسات الجيدة التحقق من صحته، وتحويله اختياريًا إلى JSON لأدوات أخرى.
التحقق من البنية:
yq '.' file.yaml && echo "Valid"— يُنهي yq التنفيذ برمز خروج يساوي 1 عند حدوث أخطاء في التحليل، لذا يصلح ذلك في بوابات CI.
تحويل YAML إلى JSON:
yq -o=json '.' file.yaml— يطبع JSON منسقًا.- مرّر الناتج إلى
jqلإجراء مزيد من معالجة JSON:yq -o=json '.' file.yaml | jq '.metadata.name'
تحويل JSON إلى YAML:
yq -P '.' file.json— تفرض الراية-Pإخراج YAML (بتنسيق جميل) عندما يكون الإدخال بصيغة JSON.
تجعل هذه التحويلات من yq جسرًا بين الأدوات الأصلية لـ YAML (مثل Helm وkubectl) والأدوات الأصلية لـ JSON (مثل Terraform وAWS CLI وjq).
# Validate YAML (exits 0 on success, 1 on parse error)
if yq '.' /tmp/deployment.yaml > /dev/null 2>&1; then
echo "YAML is valid"
else
echo "YAML parse error!" >&2
exit 1
fi
# Convert to JSON and query with jq
yq -o=json '.' /tmp/deployment.yaml \
| jq '{name: .metadata.name, image: .spec.template.spec.containers[0].image}'
# Round-trip: JSON snippet back to YAML
echo '{"replicas": 7, "strategy": "RollingUpdate"}' \
| yq -P '.'برنامج CI متكامل لتطبيق patch على النشر
نجمع هنا كل التقنيات في مكان واحد: برنامج CI حقيقي يطبّق patch على بيان Kubernetes من النوع Deployment ضمن مسار GitOps.
ينفّذ البرنامج النصي ما يلي:
- يتحقق من صحة YAML المُدخل قبل إجراء أي تعديل عليه.
- يستخدم
env()/strenv()لجميع عمليات استبدال المتغيرات. - يحدّث وسم صورة الحاوية باستخدام
select()المعتمد على الاسم. - يزيد عدد النسخ المتماثلة.
- يضيف annotation باسم
deploy-timeيتضمن الطابع الزمني الحالي. - يتحقق من صحة الناتج مرة أخرى قبل إجراء commit.
يضمن هذا النمط أن تكون كل خطوة ذرّية وقابلة للتدقيق، حتى عند تشغيل مسار العمل بالتزامن مع مسار آخر.
#!/usr/bin/env bash
set -euo pipefail
MANIFEST="/tmp/deployment.yaml"
export NEW_IMAGE="my-app:$(date +%Y%m%d)-abc1234"
export NEW_REPLICAS=3
export DEPLOY_TIME="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
export CONTAINER="app"
# 1. Validate before patching
yq '.' "$MANIFEST" > /dev/null
# 2. Update image (by container name)
yq -i \
'(.spec.template.spec.containers[] | select(.name == strenv(CONTAINER))).image = strenv(NEW_IMAGE)' \
"$MANIFEST"
# 3. Set replicas
yq -i '.spec.replicas = env(NEW_REPLICAS)' "$MANIFEST"
# 4. Stamp annotation
yq -i '.metadata.annotations."deploy-time" = strenv(DEPLOY_TIME)' "$MANIFEST"
# 5. Validate result
yq '.' "$MANIFEST" > /dev/null && echo "Patch applied successfully"
# 6. Show diff summary
yq '{image: .spec.template.spec.containers[0].image, replicas: .spec.replicas}' "$MANIFEST"اختبار المعرفة: التحرير الآمن لملفات متعددة المستندات
اختبر مدى فهمك لتحرير ملفات Kubernetes بصيغة YAML متعددة المستندات باستخدام yq.
مراجعة الدرس: تحرير YAML باستخدام yq
لقد أتممت الدرس المتعلق بـ تحرير ملفات إعداد YAML باستخدام yq. إليك ملخصًا موجزًا لكل ما تناولناه:
- التثبيت: استخدم ملف Go الثنائي mikefarah/yq (الإصدار 4). تحقّق من الإصدار باستخدام
yq --version. - القراءة: مسارات التدوين النقطي مثل
.spec.replicas؛ والوصول إلى المصفوفات باستخدام[0]أو التكرار باستخدام[]. - التحرير في المكان: تعيد الراية
-iكتابة الملف. اعرض الناتج دائمًا أولًا من دون-i. - الاستهداف المتين: فضّل
select(.name == "app")على فهارس المصفوفات الثابتة. - الإضافة والحذف: أسند قيمة إلى مسار جديد لإنشائه؛ واستخدم
del()لإزالة الحقول. - الملفات متعددة المستندات: استخدم
select(.kind == "...")لاستهداف مورد واحد وترك الموارد الأخرى دون تعديل. - متغيرات CI: استخدم
strenv(VAR)للسلاسل النصية وenv(VAR)للقيم ذات النوع — لتجنب أخطاء اقتباس الصَدَفة. - الدمج: ينفّذ
. *= load("patch.yaml")دمجًا عميقًا لملف تجاوز من دون فقدان المفاتيح التي لم يشملها patch. - التحقق والتحويل: استخدم
yq '.'كبوابة لفحص الصياغة، و-o=jsonو-Pلتحويل التنسيق.
النمط الأساسي لأي patch لـ YAML في CI هو: تحقق → استهدف → أسند → تحقق. ادمج ذلك مع strenv() وselect()، ولن تحتاج مجددًا إلى اللجوء إلى أوامر sed المختصرة والهشة في سطر واحد.
الأسئلة الشائعة
هل درس «تحرير ملفات إعداد YAML باستخدام yq» مجاني؟
نعم — نص درس «تحرير ملفات إعداد YAML باستخدام yq» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة DevOps Bootcamp، انتقل إلى CoddyKit PRO. تتضمن دورة DevOps Bootcamp 4 دروس في المجموع.
ماذا ستتعلم في «تحرير ملفات إعداد YAML باستخدام yq»؟
اقرأ ملفات YAML الخاصة بـ Kubernetes وCI وعدّلها في موضعها باستخدام yq مع الحفاظ على البنية والتعليقات تتمرن على DevOps Bootcamp مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ DevOps Bootcamp؟
لا تُشترط خبرة سابقة. DevOps Bootcamp على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «تحرير ملفات إعداد YAML باستخدام yq»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس DevOps Bootcamp هذا؟
نعم. كل درس في DevOps Bootcamp يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- تصفية JSON وتحديد عناصره باستخدام مسارات jq
- تحويل كائنات JSON وإنشاؤها باستخدام jq
- استهلاك REST APIs باستخدام curl وjq معًا
- تحرير ملفات إعداد YAML باستخدام yq