السحابة المتعددة: Azure وGCP

استراتيجية التعدد السحابي والتجريدات

18 دقيقة الدرس 9 من 28

استراتيجية التعدد السحابي والتجريدات

Kubernetes يعمل بشكل متطابق على GCP وAzure. Terraform يتحدث إلى كلا السحابتين بنفس صياغة HCL. إذن لماذا تفشل بنى التعدد السحابي في الإنتاج بانتظام كبير؟ لأن المهندسين يجرِّدون في الطبقة الخاطئة، في الوقت الخاطئ، لأسباب خاطئة. يرسم هذا الدرس حدًا دقيقًا بين التجريد الذي يعوض تكلفته والتجريد الذي يتحول إلى عبء صيانة لا أحد يرصد له ميزانية. الحكم الصحيح هنا هو الفارق بين منصة قابلة للنقل والتطور وبين وساطة سحابية مخصصة لا يستطيع أحد الحفاظ عليها.

طيف التجريد

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

  • المستوى 0 — لا تجريد. يستخدم المهندسون AWS CLI وGCP CLI وAzure CLI مباشرة. البرامج النصية خاصة بكل مزود. هذا مقبول حين يملك فريق واحد مزودًا واحدًا، لكنه ينهار حين تحتاج إلى تدقيق أو تدوير أو تكرار البنية التحتية عبر مزودين.
  • المستوى 1 — IaC تصريحي بوحدات خاصة بكل مزود. Terraform أو Pulumi مع وحدات منفصلة لكل مزود. صياغة HCL مشتركة؛ تعريفات الموارد ليست كذلك. تحصل على إدارة متسقة للحالة وكشف الانجراف وسير عمل plan/apply عبر جميع السحاب دون ادعاء قابلية النقل على مستوى الموارد. هذه النقطة المثلى لغالبية المؤسسات.
  • المستوى 2 — Kubernetes كتجريد للحوسبة. تُعبَّأ أعباء العمل كمخططات Helm أو تراكبات Kustomize. توفير الكتلة خاص بالمزود (وحدة EKS مقابل وحدة GKE)؛ كل شيء داخل الكتلة قابل للنقل.
  • المستوى 3 — تجريد منصة المطورين الداخلية (IDP). واجهة برمجية للمنصة (Backstage أو Port أو مخصصة) تعرض واجهة مبسطة: "أعطني خدمة بـ 3 نسخ وقاعدة بيانات Postgres ونقطة نهاية عامة." المنصة تترجم ذلك إلى موارد خاصة بالمزود. هذا النموذج تستخدمه Netflix وSpotify. قوي للغاية ومكلف للغاية في البناء والصيانة الصحيحة.
  • المستوى 4 — بيئة تشغيل قابلة للنقل الكاملة (نمط مضاد لغالبية الحالات). شيء مثل Crossplane أو وسيط سحابي مطور داخليًا يحاول جعل AWS S3 وGCS قابلَين للتبادل عبر واجهة برمجية واحدة. ما لم تكن بائع سحابة نفسك، هذا المستوى يمحو قيمة الخدمات المدارة السحابية الأصيلة أسرع مما يزيل العبء التشغيلي.
القاعدة في شركات التقنية الكبرى: جرِّد سير عمل النشر وخط أنابيب الرصد؛ لا تجرِّد واجهة برمجة موارد السحابة. مهندسون في Stripe وCloudflare وUber جميعهم يحتفظون بوحدات Terraform منفصلة خاصة بكل مزود بدلًا من إخفاء المزودين خلف واجهة مشتركة — لأن دلالات الموارد مختلفة فعلًا والتظاهر بخلاف ذلك يُدخل أخطاء غير مرئية.

متى تجرِّد: Kubernetes

Kubernetes هو تجريد الحوسبة الأكثر نجاحًا في الصناعة. الحجة لصالحه في سياق التعدد السحابي قوية تحديدًا لأنه يستهدف الطبقة الصحيحة — جدولة الحوسبة ودورة حياة أعباء العمل — ولا يتظاهر بتجريد التخزين أو الشبكات أو قواعد البيانات المدارة.

جرِّد باستخدام Kubernetes عندما:

  • أعباء عملك عديمة الحالة أو شبه عديمة الحالة. Pods وDeployments وHorizontalPodAutoscalers وServices قابلة للنقل فعلًا. مخطط Helm الذي ينشر واجهة برمجتك على EKS سينشر بشكل متطابق على GKE بتبديل الكتلة.
  • تحتاج إلى تجنب قيد المزود على طبقة جدولة الحوسبة تحديدًا. الانتقال من EKS إلى GKE يكلف تبديل وحدة Terraform واحدة وتحديث kubeconfig — لا إعادة كتابة تطبيقك.
  • تشغِّل Kubernetes بالفعل لأسباب أخرى (تعقيد داخلي، خبرة الفريق، نظام أدوات) والتعدد السحابي متطلب إضافي، لا الأساسي.

لا تتوقع من Kubernetes تجريد:

  • Ingress وتوازن الحمل. تعليق توضيحي لـ AWS ALB Ingress Controller غير متوافق مع Ingress المدار في GKE. تحتاج تكوينات ingress خاصة بكل مزود حتى حين تشغِّل كلتا الكتلتين نفس مخطط Helm.
  • فئات التخزين. gp3 على AWS وpd-ssd على GCP وPremium_LRS على Azure فئات تخزين مختلفة بنماذج أداء وتسعير وتكرار مختلفة. كائن StorageClass خاص بالمزود.
  • IAM / حسابات الخدمة. EKS IRSA وGKE Workload Identity وAKS Pod Identity آليات مختلفة لنفس الهدف (بيانات اعتماد السحابة على مستوى Pod). مخطط Helm يجب أن يكون معاملًا لهذه الاختلافات وإلا ستُرمِّز نمط التعليق التوضيحي لمزود واحد وتكسر البقية.
# ── نمط قيم Helm لقابلية نقل Kubernetes متعدد السحاب ────────────────────────── # values-aws.yaml serviceAccount: annotations: eks.amazonaws.com/role-arn: "arn:aws:iam::123456789012:role/my-app-role" ingress: className: "alb" annotations: alb.ingress.kubernetes.io/scheme: "internet-facing" alb.ingress.kubernetes.io/target-type: "ip" storage: className: "gp3" --- # values-gcp.yaml serviceAccount: annotations: iam.gke.io/gcp-service-account: "my-app@my-project.iam.gserviceaccount.com" ingress: className: "gce" annotations: kubernetes.io/ingress.class: "gce" storage: className: "premium-rwo" # أمر النشر — نفس المخطط، تراكب قيم خاص بالبيئة: # helm upgrade --install my-app ./charts/my-app \ # -f values-base.yaml \ # -f values-aws.yaml # أو values-gcp.yaml # --namespace production

متى تجرِّد: Terraform

Terraform هو التجريد الصحيح لتوفير البنية التحتية عبر السحاب — لكنه يُساء استخدامه كثيرًا. النمط الصحيح هو وحدات خاصة بكل مزود، سير عمل مشترك. النمط الخاطئ هو وحدة واحدة تحاول توفير موارد AWS وGCP خلف منطق شرطي.

جرِّد باستخدام Terraform عندما:

  • تحتاج إلى كشف انجراف متسق وإدارة حالة ومراجعة plan/apply عبر كلا السحابتين.
  • تريد خط CI واحد يوفر البنية التحتية على أي مزود باستخدام نفس سلسلة الأدوات — terraform plan وterraform apply وterraform destroy.
  • تحتاج إلى تطبيق السياسات التنظيمية (الوسوم، اتفاقيات التسمية، المناطق المسموح بها) باتساق بغض النظر عن المزود.

لا تحاول تجريد الاختلافات بين المزودين في HCL:

# ── خطأ: منطق مزود شرطي يخفي اختلافات الموارد (نمط مضاد) ───────────────────── # main.tf variable "cloud_provider" { type = string # "aws" أو "gcp" } resource "aws_db_instance" "db" { count = var.cloud_provider == "aws" ? 1 : 0 # ... تكوين خاص بـ AWS } resource "google_sql_database_instance" "db" { count = var.cloud_provider == "gcp" ? 1 : 0 # ... تكوين خاص بـ GCP — حقول مختلفة، دلالات مختلفة } # ── صحيح: وحدات منفصلة لكل مزود، اتفاقية استدعاء مشتركة ───────────────────── # modules/aws-postgres/main.tf — يحتوي aws_db_instance + security groups + KMS # modules/gcp-postgres/main.tf — يحتوي google_sql_database_instance + VPC peering # environments/prod-aws/main.tf module "database" { source = "../../modules/aws-postgres" instance_class = "db.r7g.xlarge" multi_az = true backup_retention_period = 7 } # environments/prod-gcp/main.tf module "database" { source = "../../modules/gcp-postgres" tier = "db-n1-highmem-4" availability_type = "REGIONAL" backup_enabled = true }

هذا الهيكل يمنحك فوائد Terraform (الحالة، الخطة، المراجعة، تطبيق السياسة) دون التظاهر بأن نسخة Aurora ونسخة Cloud SQL شيء واحد. الوحدات تشترك في اتفاقيات التسمية وواجهات الإخراج، لكن التنفيذ أصيل لكل مزود.

استخدم Terragrunt أو Terraform workspaces لعزل الحالة متعددة البيئات ومتعددة السحاب. كل مزيج بيئة+مزود يحصل على خلفية حالة خاصة به (دلو S3 في AWS، دلو GCS في GCP). ملف root.hcl في Terragrunt يولِّد تكوين الخلفية تلقائيًا من مسار الدليل. هذا يمنع أكثر حوادث Terraform متعددة السحاب شيوعًا: تصادم ملفات الحالة وحذف الموارد عبر البيئات.

متى لا تجرِّد

هذا القسم الذي تتخطاه معظم أدلة التعدد السحابي. قرار عدم التجريد بنفس أهمية قرار التجريد. إليك الحالات التي تكلف فيها التجريد أكثر مما توفر:

  • خدمات البيانات المدارة. BigQuery وRedshift وCloud Spanner وAurora وCosmos DB — لا تجرِّد هذه. محركات استعلاماتها ونماذج تسعيرها وسلوك التزامن ودلالات التكرار مختلفة جوهريًا. طبقة تجريد تعاملها بقابلية التبادل تمنحك أسوأ العالمين: لا تستطيع استخدام التسعير القائم على الـ slot في BigQuery أو التوسع التلقائي في Aurora Serverless v2، واستعلامك "المحمول" سيؤدي أداءً سيئًا على الجميع.
  • آليات الهوية والوصول. لا تبنِ تجريدًا مخصصًا لـ IAM. سياسات AWS IAM وروابط GCP IAM وAzure RBAC لها نماذج تعبير مختلفة. فريق الأمان يحتاج إلى تدقيق السياسات الأصيلة، لا طبقة ترجمة.
  • بدائل الشبكات. VPCs والشبكات الفرعية ومجموعات الأمان وجداول التوجيه خاصة بكل مزود عن قصد. تجريد يحاول جعل AWS Security Groups وGCP Firewall Rules تبدو متشابهة سيفوته الفارق الدلالي الحرج: مجموعات أمان AWS ذات حالة ومرتبطة بـ ENIs؛ قواعد جدار حماية GCP عديمة الحالة ومرتبطة بـ VPC. سياسة تبدو صحيحة في التجريد قد تكون ثغرة أمنية في التنفيذ.
  • خلفيات الرصد. لا تحاول تجريد CloudWatch وCloud Monitoring وAzure Monitor إلى واجهة برمجية متجانسة. بدلًا من ذلك، شغِّل منصة رصد خارجية واحدة (Datadog أو Grafana Cloud) تستهلك من بيانات القياس الأصيلة لكل مزود.
نمط وسيط السحابة الداخلي المضاد: بنت عدة مؤسسات كبيرة منصات داخلية تعرض "واجهة موارد سحابية موحدة" لإخفاء اختلافات المزودين — بناء وساطة سحابية خاصة فعليًا. دون استثناء، هذه المشاريع تتأخر سنوات عن إصدارات مزايا المزود، وتتراكم فيها تصحيحات أمنية حرجة لا تُشحن لأن طبقة التجريد لا تدعم مزايا IAM الجديدة. إذا ورثت واحدة، خطِّط لإيقاف تدريجي حذر لا لتمديد.
Abstract vs. native: what to abstract across clouds and what to leave provider-native Abstraction Decision Map Abstract (shared tooling) Kubernetes Workloads Helm charts, Deployments, HPA, Services IaC Workflow (Terraform) plan/apply pipeline, policy checks, state mgmt Secrets Management Vault with per-provider auth backends Observability Pipeline Datadog / Grafana ingests from all providers CI/CD Pipelines GitHub Actions / GitLab CI with env-specific secrets Cost Reporting (OpenCost / CloudHealth) Keep Provider-Native Managed Data Services BigQuery, Aurora, Cosmos DB — semantics differ Networking Primitives VPC, SG, firewall rules — stateful vs stateless differ IAM / RBAC Policies Audit requires native policy format; no hiding Ingress / Load Balancers ALB, GCE LB, Azure AppGW — different annotation models Storage Classes gp3, pd-ssd, Premium_LRS — different IOPS guarantees Provider-Specific ML / AI Services
خريطة قرار التجريد: العمود الأخضر يستخدم أدوات مشتركة؛ العمود الأحمر يبقى أصيلًا لكل مزود للحفاظ على الدلالات والأمان والأداء.

إطار قرار استراتيجية التعدد السحابي

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

  1. صنِّف كل حمل عمل بقيمة قابلية النقل. لكل خدمة، اسأل: "إذا اضطررنا إلى نقل هذه إلى مزود مختلف في 90 يومًا، ما التكلفة؟" أعباء العمل ذات قيمة نقل شبه معدومة يجب أن تُعلَّم صراحةً كمُلتزمة بسحابة واحدة. هذا ليس فشلًا — بل مقايضة واعية موثقة.
  2. افصل مستوى التحكم عن مستوى البيانات. مستوى التحكم (CI/CD، تدوير الأسرار، الإبلاغ عن التكلفة، التنبيه) يجب أن يكون معتدلًا للسحاب أو مستضافًا ذاتيًا. مستوى البيانات (حيث يتدفق حركة مستخدميك) يمكن ويجب أن يستخدم الخدمات الأصيلة للمزود للأداء والتكلفة.
  3. عرِّف عقود التجريد كواجهات، لا تنفيذات. وثِّق ما يجب أن تنتجه "وحدة الحوسبة" (نقطة نهاية، سياسة توسع، حساب خدمة) دون تحديد الكيفية. التنفيذ على AWS يستوفي العقد بـ EKS + IRSA؛ التنفيذ على GCP يستوفيه بـ GKE + Workload Identity.
  4. عامل مزايا المزود الخاصة كاشتراك اختياري، لا إلغاء اشتراك. الافتراضي لأي خدمة جديدة هو: التشغيل على Kubernetes بمخطط Helm، واستخدام Vault للأسرار، وإصدار تتبعات OpenTelemetry. يمكن للفرق الاشتراك في خدمات خاصة بالمزود (BigQuery أو Pub/Sub) حين تكون الحالة التجارية واضحة وموثقة.
# ── سياسة OPA: تطبيق معايير التجريد متعدد السحاب في خطط Terraform ───────────── # policy/multicloud_standards.rego package terraform.multicloud import future.keywords.if import future.keywords.contains # رفض أي دلو S3 لا يحتوي وسم cost_center deny contains msg if { resource := input.resource_changes[_] resource.type == "aws_s3_bucket" not resource.change.after.tags.cost_center msg := sprintf("S3 bucket %v missing required cost_center tag", [resource.address]) } # رفض إنشاء مفاتيح IAM المباشرة (يجب استخدام IRSA أو Workload Identity) deny contains msg if { resource := input.resource_changes[_] resource.type == "aws_iam_access_key" msg := sprintf("Direct IAM access key %v is forbidden; use IRSA or Vault dynamic credentials", [resource.address]) } # اشتراط تمكين Workload Identity لجميع تجمعات عُقد GKE deny contains msg if { resource := input.resource_changes[_] resource.type == "google_container_node_pool" not resource.change.after.workload_metadata_config msg := sprintf("GKE node pool %v must enable Workload Identity (workload_metadata_config)", [resource.address]) } # التشغيل في CI: conftest test --policy policy/ plan.json

أوضاع الفشل في الإنتاج لتجريدات التعدد السحابي

فهم لماذا تفشل طبقات التجريد في الإنتاج بنفس أهمية معرفة كيفية بنائها. هذه الأنماط المتكررة في المؤسسات التي تمتلك سنتين أو أكثر من التشغيل متعدد السحاب:

  • انجراف التجريد. النسخة AWS والنسخة GCP من وحدة Terraform الخاصة بك تتباعد على مدى ستة أشهر لأن فريق AWS يضيف مزية ولا أحد يحدِّث وحدة GCP. الآن لديك نظامان مختلفان يُستدعيان بنفس الاسم. التخفيف: اختبارات العقد وفحوصات الانجراف المجدولة في CI.
  • انحراف الساعة في أعباء العمل العابرة للسحاب. سير عمل يكتب في AWS SQS ويقرأ من GCP Pub/Sub لا يملك حدود معاملة مشتركة. يمكن أن تصل الرسائل خارج الترتيب، والتعامل مع الأخطاء في سحابة واحدة لا يتراجع تلقائيًا عن حالة الأخرى. التخفيف: مستهلكون خاملون المعرِّف، وأرقام تسلسل صريحة، وطوابير الرسائل الميتة العابرة للسحاب مع تنبيه موحَّد.
  • تأخر تدوير الأسرار. سر مخزَّن في AWS Secrets Manager ومنسوخ يدويًا إلى GCP Secret Manager يُدار على AWS ولا يُدار على GCP. حمل العمل على GCP يعمل ببيانات اعتماد قديمة حتى يفشل. التخفيف: Vault كمصدر حقيقة واحد مع أسرار ديناميكية.
  • انهيار إسناد التكلفة. حين يتوزع طلب مستخدم واحد عبر AWS وGCP وAzure، لا تلتقط تقارير التكلفة لأي مزود منفرد التكلفة الحقيقية لذلك الطلب. فرق FinOps تفقد الرؤية والتجاوزات تمر دون اكتشاف. التخفيف: تصنيف وسوم متسق مُطبَّق على مستوى IaC ومنصة FinOps موحَّدة.
فخ "قابلية النقل بشكل افتراضي": إلزام كل خدمة بالقابلية للنقل عبر السحاب يبدو حوكمة جيدة. في الواقع يجبر المهندسين على تجنب جميع الخدمات المدارة الأصيلة — لا RDS ولا BigQuery ولا Azure Cognitive Services — لأنها "غير قابلة للنقل." النتيجة هي فرق تشغِّل PostgreSQL المدار ذاتيًا على EC2 بدلًا من RDS وKafka المدار ذاتيًا بدلًا من MSK. العبء التشغيلي لإدارة تلك الخدمات ذاتيًا يفوق أي فائدة من قابلية النقل. قابلية النقل يجب أن تكون قرارًا خاصًا بكل حمل عمل، لا ولاءً على مستوى المؤسسة.

استراتيجية التعدد السحابي الناضجة لا تُعرَّف بمقدار ما تجرِّده — بل بمدى تعمُّدك في اختيار ما تجرِّده. Kubernetes وTerraform يمنحانك تجريدات مُثبَّتة وقياسية في الصناعة عند الطبقات التي تتوفر فيها قابلية النقل فعلًا. خارج هاتين الطبقتين، هدفك ليس إخفاء السحاب عن بعضها؛ بل تشغيلها باتساق عبر أدوات موحَّدة للرصد والأسرار والتكلفة والهوية. الدرس القادم يفحص كيف تتحد هذه الاستراتيجيات في بنية مرجعية حقيقية عابرة للسحاب.