DevOps and Infrastructure

بناء خطوط أنابيب CI/CD قوية لخدمات مصغرة غير كوبرنيتيس باستخدام GitHub Actions

مع استمرار هيمنة هندسة الخدمات المصغرة في تطوير البرمجيات الحديثة، تزداد تعقيدات إدارة دورة حياة الخدمات الفردية بشكل أسي. بينما تتسارع العديد من الفرق نحو كوبرنيتيس (Kubernetes) للتنسيق، لا يزال جزء كبير من الصناعة يعتمد على أهداف نشر أبسط مثل الآلات الافتراضية، أو عروض المنصة كخدمة (PaaS) مثل AWS Elastic Beanstalk أو Heroku، أو الخوادم المخصصة (bare-metal). بالنسبة لهذه البيئات، يجب ألا تقتصر خطوط أنابيب التكامل المستمر والنشر المستمر (CI/CD) على أتمتة عمليات البناء فحسب، بل يجب أن تتعامل مع منطق النشر، وتكوين البيئة، واستراتيجيات التراجع بدقة.

يقدم GitHub Actions نهجاً قوياً يركز على الكود لأغراض التكامل المستمر والنشر المستمر (CI/CD). في هذا المنشور، سنستكشف كيفية بناء خط أنابيب قوي للخدمات المصغرة غير كوبرنيتيس، مع التركيز على الوحدة، والأمان، والموثوقية.

فلسفة خطوط الأنابيب الوحدوية

أحد أكثر الأخطاء شيوعاً التي يرتكبها المطورون هو ترميز كل خطوة من خطوات عملية النشر بشكل ثابت في ملف YAML واحد ضخم. بالنسبة لهندسة الخدمات المصغرة، يصبح هذا النهج غير قابل للإدارة بسرعة. بدلاً من ذلك، يجب أن نتعامل مع سير عمل GitHub Actions كوحدات قابلة للتكوين.

من خلال الاستفادة من سير العمل القابل لإعادة الاستخدام والتكوين الخاص بالبيئة، يمكننا الحفاظ على مصدر واحد للحقيقة لمنطق البناء مع السماح لأهداف النشر بالتغير. هذا أمر بالغ الأهمية بشكل خاص للبيئات غير كوبرنيتيس حيث قد يتم إدارة البنية التحتية ككود (Infrastructure-as-Code) بشكل مختلف عبر الخدمات (على سبيل المثال، بعضها يستخدم Terraform، والبعض الآخر يستخدم نصوص shell بسيطة).

المكونات الأساسية للخط الأنابيب

يتكون خط الأنابيب القوي للخدمات غير كوبرنيتيس عادةً من ثلاث مراحل متميزة: البناء، والاختبار، والنشر. دعونا نلقي نظرة على كيفية هيكلة سير عمل GitHub Actions الذي يجمع هذه المراحل بكفاءة.

1. مرحلة البناء والاختبار

تمثل السرعة والموثوقية أساس أي خط أنابيب CI/CD. نريد أن نفشل بسرعة إذا تعطلت الاختبارات. باستخدام GitHub Actions، يمكننا موازاة تنفيذ الاختبارات لتقليل حلقات التغذية الراجعة.

إليك مثال على سير عمل يتعامل مع تثبيت التبعيات، والتنظيف (linting)، واختبار الوحدات:

name: Build and Test

on:
  pull_request:
    branches: [ main ]
  push:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [18.x, 20.x]

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Set up Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Run linter
        run: npm run lint

      - name: Run unit tests
        run: npm test -- --coverage

2. الحاويات (Containerization) للاتساق

حتى إذا لم تكن تستخدم كوبرنيتيس، تظل الحاويات المعيار الذهبي لضمان الاتساق بين بيئات التطوير، والاختبار التجريبي (staging)، والإنتاج. يسمح لك Docker بتشغيل خدمتك المصغرة بشكل متوقع بغض النظر عن نظام التشغيل المضيف الأساسي.

يمكننا دمج بناء Docker ودفع الصور (push) مباشرةً في خط الأنابيب. يضمن ذلك أن الأداة البرمجية (artifact) التي يتم نشرها هي نفسها التي اجتازت جميع الاختبارات.

      - name: Build and Push Docker Image
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ghcr.io/${{ github.repository }}:${{ github.sha }}

3. النشر الخاص بالبيئة

بالنسبة للخدمات غير كوبرنيتيس، غالباً ما يتضمن النشر الاتصال بخادم عبر SSH أو استدعاء واجهة برمجة تطبيقات (API) لمزود PaaS. يعد الأمان أمراً بالغ الأهمية هنا. لا ينبغي أبداً ترميز بيانات الاعتماد بشكل ثابت. بدلاً من ذلك، استخدم أسرار GitHub (GitHub Secrets) مقترنة بقواعد حماية البيئة.

لنفترض أننا ننشر إلى خادم Linux عبر SSH. يمكننا استخدام `appleboy/ssh-action` لتنفيذ نصوص النشر.

  deploy-staging:
    needs: build
    runs-on: ubuntu-latest
    environment: staging

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Deploy to Staging Server
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.STAGING_HOST }}
          username: ${{ secrets.SSH_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd /opt/my-service
            docker pull ghcr.io/${{ github.repository }}:${{ github.sha }}
            docker-compose up -d --no-deps my-service
            # Perform health check
            curl -f http://localhost:8080/health || exit 1

أفضل الممارسات للمرونة

  • القابلية للتكرار (Idempotency): تأكد من أن نصوص النشر الخاصة بك يمكن تشغيلها مراراً وتكراراً دون آثار جانبية. يجعل Docker هذا أسهل، لكن قابلية التكرار على مستوى التطبيق لا تزال مطلوبة للهجرة إلى قواعد البيانات.
  • استراتيجية التراجع: في البيئات غير كوبرنيتيس، قد يكون التراجع يدوياً. قم بأتمتة ذلك عن طريق وضع علامات على صور Docker باستخدام الإصدارات الدلالية (semantic versions) والحفاظ على الإصدارات السابقة متاحة. إذا فشل فحص الصحة، يجب أن يحفز خط الأنابيب تلقائياً سير عمل للتراجع.
  • إدارة الأسرار: قم بتدوير مفاتيح SSH ورموز API بانتظام. استخدم بيئات GitHub لتقييد من يمكنه الموافقة على عمليات النشر إلى بيئة الإنتاج.

الخاتمة

يتطلب بناء خطوط أنابيب CI/CD للخدمات المصغرة غير كوبرنيتيس تغييراً في العقلية. بدلاً من الاعتماد على محرك التنسيق لإدارة عمليات النشر والتراجع، تنتقل المسؤولية بالكامل إلى خط الأنابيب نفسه. من خلال الاستفادة من الطبيعة الوحدوية لـ GitHub Actions، والتحاوي (containerization)، وإدارة الأسرار الآمنة، يمكنك إنشاء نظام نشر يكون بنفس قوة وقابلية التوسع لنظرائه في كوبرنيتيس. احتضن الأتمتة، واولِ الأمان الأولوية، وقم دائماً بالتحقق من صحة عمليات النشر الخاصة بك باستخدام فحوصات الصحة الآلية.

Share: