404 Not Found

404 Not Found


nginx

تمرين عملي شامل: نشر مشروع OrderFlow

النشر هو الميل الأخير—أتمتة CI/CD وتنسيق K8s والمراقبة والتنبيهات تضمن رحلة سلسة للتطبيقات من التطوير إلى الإنتاج.

1. ما ستتعلمه


2. قصة حقيقية لمهندس DevOps

(1) نقطة الألم: النشر اليدوي كالوقوف على لغم

نشر Bob يدويًا OrderFlow إلى الإنتاج: محليًا mvn packagedocker build ← دفع الصورة ← kubectl apply ← فحص حالة الصحة. العملية بالكامل تستغرق 30 دقيقة وعرضة للأخطاء: نسيان تحديث التهيئة، دفع إصدار صورة خاطئ، أو عدم إيقاف Pods القديمة بأمان أثناء التحديثات المتداولة، مما يؤدي إلى أخطاء 502.

(2) حلول CI/CD

خدمة شاملة لخطوط الإنتاج المؤتمتة:

100%
graph LR
    A["Git Push"] --> B["GitHub Actions<br/>بناء + اختبار"]
    B --> C["Docker Build<br/>+ دفع إلى السجل"]
    C --> D["نشر K8s<br/>المتداول"]
    D --> E["فحص الصحة<br/>+ اختبار دخاني"]
    E --> F["المراقبة<br/>Grafana"]

(3) الإيرادات

بعد أن أنشأ Bob خط CI/CD، أدى دفع الكود إلى نشر تلقائي، وإتمام العملية من الكود إلى الإنتاج في 5 دقائق. مع HPA يتولى التحجيم التلقائي وPrometheus يتولى التنبيهات التلقائية، تحول Bob من "رجل إطفاء الحرائق" إلى "مراقب".


3. خط أنابيب CI/CD

(1) ▶ مثال: سير عمل GitHub Actions

YAML
# .github/workflows/deploy.yml
name: OrderFlow CI/CD

on:
  push:
    branches: [main]
    tags: ['v*']

env:
  REGISTRY: registry.example.com
  IMAGE_NAME: orderflow-service

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4

    - name: Set up JDK 17
      uses: actions/setup-java@v4
      with:
        java-version: '17'
        distribution: 'temurin'

    - name: Run tests
      run: mvn verify -B

    - name: Build Docker image
      run: docker build -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} .

    - name: Login to Registry
      run: echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login ${{ env.REGISTRY }} -u ${{ secrets.REGISTRY_USERNAME }} --password-stdin

    - name: Push image
      run: docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}

  deploy:
    needs: build
    runs-on: ubuntu-latest
    if: startsWith(github.ref, 'refs/tags/v')
    steps:
    - uses: actions/checkout@v4

    - name: Deploy to Kubernetes
      run: |
        kubectl set image deployment/orderflow \
          orderflow=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} \
          -n orderflow
        kubectl rollout status deployment/orderflow -n orderflow --timeout=300s

    - name: Smoke test
      run: |
        sleep 10
        curl -sf https://api.orderflow.example.com/actuator/health | grep '"status":"UP"'

الناتج:

TEXT
CONTAINER ID   IMAGE          STATUS         PORTS
abc123         nginx:latest   Up 2 hours     0.0.0.0:80->80/tcp
مرحلة الخط العملية معالجة الفشل
بناء + اختبار mvn verify حظر النشر
Docker Build بناء صورة متعددة المراحل حظر النشر
دفع إلى السجل دفع إلى مستودع الصور إعادة المحاولة 3 مرات
نشر K8s kubectl set image + rollout تراجع تلقائي
اختبار دخاني التحقق من فحص الصحة تراجع + إشعار

4. نشر K8s للإنتاج

(1) ▶ مثال: نشر إنتاجي + HPA

YAML
apiVersion: apps/v1
kind: Deployment
metadata:
  name: orderflow
  namespace: orderflow
spec:
  replicas: 3
  selector:
    matchLabels: { app: orderflow }
  strategy:
    rollingUpdate: { maxUnavailable: 0, maxSurge: 1 }
  template:
    metadata:
      labels: { app: orderflow }
    spec:
      terminationGracePeriodSeconds: 60
      containers:
      - name: orderflow
        image: registry.example.com/orderflow-service:latest
        ports:
        - { containerPort: 8080 }
        - { containerPort: 8081 }
        envFrom:
        - configMapRef: { name: orderflow-config }
        - secretRef: { name: orderflow-secrets }
        resources:
          requests: { memory: "512Mi", cpu: "250m" }
          limits: { memory: "1Gi", cpu: "1000m" }
        lifecycle:
          preStop:
            exec:
              command: ["sh", "-c", "sleep 10"]
        livenessProbe:
          httpGet: { path: /actuator/health/liveness, port: 8080 }
          initialDelaySeconds: 60
          periodSeconds: 30
        readinessProbe:
          httpGet: { path: /actuator/health/readiness, port: 8080 }
          initialDelaySeconds: 30
          periodSeconds: 10
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: orderflow-hpa
  namespace: orderflow
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: orderflow
  minReplicas: 3
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80

الناتج:

TEXT
Deployment.apps/my-app created
Service/my-app-service exposed
Ingress/my-app-ingress created
تهيئة K8s للإنتاج القيمة السبب
maxUnavailable: 0 بدون توقف الحفاظ دائمًا على عدد النسخ المستهدف
terminationGracePeriodSeconds: 60 إيقاف أنيق انتظار تصريف الطلبات
preStop: sleep 10 إنهاء مؤجل يستمر K8s في تصريف حركة المرور حتى بعد الإزالة من Service
resources.requests/limits تهيئة QoS ضمان تخصيص الموارد + تحديد التجاوزات

(2) ▶ مثال: Ingress + TLS

YAML
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: orderflow-ingress
  namespace: orderflow
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/rate-limit: "100"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  ingressClassName: nginx
  tls:
  - hosts: [api.orderflow.example.com]
    secretName: orderflow-tls
  rules:
  - host: api.orderflow.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service: { name: orderflow, port: { number: 80 } }

الناتج:

TEXT
Deployment.apps/my-app created
Service/my-app-service exposed
Ingress/my-app-ingress created

5. إطلاق القابلية للرصد

(1) ▶ مثال: Prometheus + AlertManager

YAML
# prometheus.yml
scrape_configs:
- job_name: orderflow
  metrics_path: /actuator/prometheus
  scrape_interval: 15s
  kubernetes_sd_configs:
  - role: pod
    namespaces:
      names: [orderflow]
  relabel_configs:
  - source_labels: [__meta_kubernetes_pod_label_app]
    action: keep
    regex: orderflow

الناتج:

TEXT
Deployment.apps/my-app created
Service/my-app-service exposed
Ingress/my-app-ingress created
YAML
# alert_rules.yml
groups:
- name: orderflow-slo
  rules:
  - alert: SLOErrorRateExceeded
    expr: |
      sum(rate(http_server_requests_seconds_total{namespace="orderflow",status=~"5.."}[5m]))
      / sum(rate(http_server_requests_seconds_total{namespace="orderflow"}[5m])) > 0.001
    for: 5m
    labels: { severity: critical }
    annotations:
      summary: "معدل خطأ OrderFlow يتجاوز SLO (0.1%)"

  - alert: SLOLatencyExceeded
    expr: |
      histogram_quantile(0.99,
        sum(rate(http_server_requests_seconds_bucket{namespace="orderflow"}[5m])) by (le))
      > 0.1
    for: 5m
    labels: { severity: warning }
    annotations:
      summary: "زمن استجابة P99 لـ OrderFlow يتجاوز SLO (100ms)"

(2) ▶ مثال: مقاييس لوحة SLO في Grafana

اللوحة PromQL هدف SLO
زمن استجابة P99 histogram_quantile(0.99, sum(rate(http_server_requests_seconds_bucket{namespace="orderflow"}[5m])) by (le)) < 100 مللي ثانية
معدل الخطأ sum(rate(http_server_requests_seconds_total{namespace="orderflow",status=~"5.."}[5m])) / sum(rate(http_server_requests_seconds_total{namespace="orderflow"}[5m])) < 0.1%
التوفر 1 - (sum(rate(http_server_requests_seconds_total{namespace="orderflow",status=~"5.."}[5m])) / sum(rate(http_server_requests_seconds_total{namespace="orderflow"}[5m]))) > 99.9%
إنتاجية الطلبات rate(orderflow_orders_created_total[1m]) * 60 > 100/دقيقة

6. تعزيزات أمان الإنتاج

(1) ▶ مثال: NetworkPolicy + أمان Pod

YAML
# NetworkPolicy: تقييد الوصول
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: orderflow-netpol
  namespace: orderflow
spec:
  podSelector:
    matchLabels: { app: orderflow }
  policyTypes: [Ingress]
  ingress:
  - from:
    - namespaceSelector:
        matchLabels: { name: ingress-nginx }
    ports:
    - { port: 8080, protocol: TCP }
  - from:
    - namespaceSelector:
        matchLabels: { name: monitoring }
    ports:
    - { port: 8081, protocol: TCP }
---
# أمان Pod: التشغيل كمستخدم غير جذر
apiVersion: v1
kind: LimitRange
metadata:
  name: orderflow-limits
  namespace: orderflow
spec:
  limits:
  - type: Container
    default:
      memory: "1Gi"
      cpu: "500m"
    defaultRequest:
      memory: "256Mi"
      cpu: "100m"

الناتج:

TEXT
Deployment.apps/my-app created
Service/my-app-service exposed
Ingress/my-app-ingress created
عنصر تعزيز الأمان الإجراء الوصف
التشغيل غير الجذر Dockerfile USER appuser منع هروب الحاوية
NetworkPolicy تقييد مصادر الدخول السماح فقط لـ Ingress والمراقبة
تشفير Secret تهيئة تشفير etcd منع تخزين Secrets بنص عادي
TLS شهادات cert-manager التلقائية نقل مشفر
حدود الموارد LimitRange منع تنازع الموارد

7. مثال شامل: قائمة نشر OrderFlow الكاملة

YAML
# k8s/orderflow-complete.yaml
---
apiVersion: v1
kind: Namespace
metadata:
  name: orderflow
  labels: { name: orderflow }

---
apiVersion: v1
kind: ConfigMap
metadata: { name: orderflow-config, namespace: orderflow }
data:
  SPRING_PROFILES_ACTIVE: "prod"
  DB_HOST: "mysql.orderflow.svc.cluster.local"
  REDIS_HOST: "redis.orderflow.svc.cluster.local"
  MANAGEMENT_SERVER_PORT: "8081"

---
apiVersion: v1
kind: Secret
metadata: { name: orderflow-secrets, namespace: orderflow }
type: Opaque
data:
  DB_PASSWORD: <base64-encoded>
  REDIS_PASSWORD: <base64-encoded>
  JWT_PRIVATE_KEY: <base64-encoded>

---
apiVersion: apps/v1
kind: Deployment
metadata: { name: orderflow, namespace: orderflow }
spec:
  replicas: 3
  selector: { matchLabels: { app: orderflow } }
  strategy: { rollingUpdate: { maxUnavailable: 0, maxSurge: 1 } }
  template:
    metadata: { labels: { app: orderflow } }
    spec:
      terminationGracePeriodSeconds: 60
      containers:
      - name: orderflow
        image: registry.example.com/orderflow-service:1.0.0
        ports: [{ containerPort: 8080 }, { containerPort: 8081 }]
        envFrom:
        - { configMapRef: { name: orderflow-config } }
        - { secretRef: { name: orderflow-secrets } }
        resources:
          requests: { memory: "512Mi", cpu: "250m" }
          limits: { memory: "1Gi", cpu: "1000m" }
        lifecycle:
          preStop: { exec: { command: ["sh", "-c", "sleep 10"] } }
        livenessProbe:
          httpGet: { path: /actuator/health/liveness, port: 8080 }
          initialDelaySeconds: 60; periodSeconds: 30
        readinessProbe:
          httpGet: { path: /actuator/health/readiness, port: 8080 }
          initialDelaySeconds: 30; periodSeconds: 10

---
apiVersion: v1
kind: Service
metadata: { name: orderflow, namespace: orderflow }
spec:
  selector: { app: orderflow }
  ports:
  - { name: http, port: 80, targetPort: 8080 }
  - { name: management, port: 8081, targetPort: 8081 }

---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata: { name: orderflow-hpa, namespace: orderflow }
spec:
  scaleTargetRef: { apiVersion: apps/v1, kind: Deployment, name: orderflow }
  minReplicas: 3
  maxReplicas: 10
  metrics:
  - { type: Resource, resource: { name: cpu, target: { type: Utilization, averageUtilization: 70 } } }

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: orderflow-ingress
  namespace: orderflow
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  ingressClassName: nginx
  tls:
  - { hosts: [api.orderflow.example.com], secretName: orderflow-tls }
  rules:
  - host: api.orderflow.example.com
    http:
      paths:
      - { path: /, pathType: Prefix, backend: { service: { name: orderflow, port: { number: 80 } } } }

❓ أسئلة شائعة

س أيهما أختار، GitHub Actions أم Jenkins؟
ج GitHub Actions يتكامل مع نظام GitHub البيئي وسهل التهيئة، مما يجعله مناسبًا للمشاريع الصغيرة والمتوسطة. Jenkins يقدم ميزات أقوى لكنه أكثر تعقيدًا في التهيئة، مما يجعله مناسبًا للمؤسسات الكبيرة. إذا كان لديك مستودع GitHub بالفعل، نوصي باستخدام GitHub Actions.
س كيف نضمن عدم وجود توقف أثناء التحديثات المتداولة؟
ج 1) maxUnavailable=0؛ 2) استخدم readinessProbe لضمان إضافة Pods إلى Service قبل أن تصبح جاهزة؛ 3) عيّن preStop sleep 10 لمنح K8s وقتًا لتصريف الطلبات بعد إزالة Pod من Service؛ 4) طبق التهيئة server.shutdown=graceful.
س كيف أحدد minReplicas وmaxReplicas لـ HPA؟
ج minReplicas = عدد النسخ المطلوبة للحمل العادي (OrderFlow = 3)؛ maxReplicas = الحمل الذروي المقدر (OrderFlow = 10). اضبط بناءً على بيانات المراقبة التاريخية. نوصي باستخدام المعالج المستهدف بنسبة 70%.
س ما هي أفضل الممارسات لإدارة Secrets؟
ج 1) K8s Secrets + تشفير etcd (النهج الأساسي)؛ 2) External Secrets Operator + AWS Secrets Manager/Vault (النهج الموصى به)؛ 3) Sealed Secrets (متوافق مع GitOps). لا تلتزم Secrets بنص عادي في Git.
س كيف أنفذ نشرًا أزرق-أخضر أو نشرًا الكناري؟
ج K8s لا يدعم نشرًا أزرق-أخضر أو نشر الكناري بشكل أصلي؛ يتطلب أدوات مثل Istio أو Argo Rollouts. يدعم Argo Rollouts نشر الكناري (ترحيل تدريجي لحركة المرور) والأزرق-الأخضر (التبديل الفوري)، مع التحقق عبر Prometheus.
س ما الذي يجب أن تغطيه تنبيهات المراقبة في بيئة الإنتاج؟
ج ثلاث فئات رئيسية: 1) تنبيهات SLO (زمن استجابة P99، معدل الخطأ، التوفر)؛ 2) تنبيهات الموارد (معالج > 80%، ذاكرة > 85%، قرص > 90%)؛ 3) تنبيهات الأعمال (انخفاض غير طبيعي في حجم الطلبات، انخفاض في معدل نجاح المدفوعات).

📖 ملخص


📝 تمارين

  1. مسألة أساسية (الصعوبة: ⭐): اكتب سير عمل GitHub Actions للاختبار التلقائي وبناء صورة Docker بعد دفع الكود.

  2. تمرين متقدم (الصعوبة: ⭐⭐): اكتب YAML نشر K8s إنتاجي كامل (Deployment + Service + Ingress + HPA + ConfigMap + Secret) لتنفيذ تحديثات متداولة بدون توقف.

  3. تحدٍ (الصعوبة: ⭐⭐⭐): أنشئ نظام قابلية للرصد كامل (Prometheus + Grafana + AlertManager + Jaeger)، وهيئ لوحات SLO وقواعد التنبيه، وحاكِ فشلاً لاختبار التنبيهات وقدرات الاسترداد التلقائي.

Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%