0Pricing
Linux Command Line & Bash Scripting Mastery · درس

تحرير ملفات إعداد YAML باستخدام yq

اقرأ ملفات YAML الخاصة بـ Kubernetes وCI وعدّلها في موضعها باستخدام yq مع الحفاظ على البنية والتعليقات

تحرير ملفات إعداد YAML باستخدام yq درس مجاني في Linux Command Line & Bash Scripting Mastery على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Linux Command Line & Bash Scripting Mastery، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Linux Command Line & Bash Scripting Mastery 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 على macOS
  • snap 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-app
  • yq '.spec.replicas' deployment.yaml — يطبع 3
  • yq '.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.

ينفّذ البرنامج النصي ما يلي:

  1. يتحقق من صحة YAML المُدخل قبل إجراء أي تعديل عليه.
  2. يستخدم env() / strenv() لجميع عمليات استبدال المتغيرات.
  3. يحدّث وسم صورة الحاوية باستخدام select() المعتمد على الاسم.
  4. يزيد عدد النسخ المتماثلة.
  5. يضيف annotation باسم deploy-time يتضمن الطابع الزمني الحالي.
  6. يتحقق من صحة الناتج مرة أخرى قبل إجراء 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) وفتح باقي دورة Linux Command Line & Bash Scripting Mastery، انتقل إلى CoddyKit PRO. تتضمن دورة Linux Command Line & Bash Scripting Mastery 4 دروس في المجموع.

ماذا ستتعلم في «تحرير ملفات إعداد YAML باستخدام yq»؟

اقرأ ملفات YAML الخاصة بـ Kubernetes وCI وعدّلها في موضعها باستخدام yq مع الحفاظ على البنية والتعليقات تتمرن على Linux Command Line & Bash Scripting Mastery مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Linux Command Line & Bash Scripting Mastery؟

لا تُشترط خبرة سابقة. Linux Command Line & Bash Scripting Mastery على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.

كم من الوقت يستغرق درس «تحرير ملفات إعداد YAML باستخدام yq»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Linux Command Line & Bash Scripting Mastery هذا؟

نعم. كل درس في Linux Command Line & Bash Scripting Mastery يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. تصفية JSON وتحديد عناصره باستخدام مسارات jq
  2. تحويل كائنات JSON وإنشاؤها باستخدام jq
  3. استهلاك REST APIs باستخدام curl وjq معًا
  4. تحرير ملفات إعداد YAML باستخدام yq
← العودة إلى Linux Command Line & Bash Scripting Mastery