تشغيل السكريبتات عند بدء تشغيل EC2: دليل User Data العملي

عندما تحتاج إلى تثبيت Nginx أو أي حزمة أخرى تلقائياً على كل نسخة EC2 جديدة، فإن الاعتماد على الإعداد اليدوي بعد الإطلاق يُعدّ خطأً تشغيلياً كلاسيكياً — خاصةً في بيئات Auto Scaling حيث تُطلق النسخ وتُوقف دون تدخل بشري. ميزة EC2 User Data هي الحل الأصلي لهذه المشكلة.

ملخص سريع (TL;DR): تشغيل السكريبتات عند بدء EC2

الخطوةالإجراءالملاحظة
1كتابة سكريبت Shell يبدأ بـ #!/bin/bashيُنفَّذ بصلاحيات root
2لصق السكريبت في حقل 'User Data' عند إنشاء النسخةأو تمريره عبر CLI
3يُنفَّذ السكريبت مرة واحدة فقط عند الإقلاع الأولالسلوك الافتراضي
4مراجعة السجلات في /var/log/cloud-init-output.logلتشخيص أي أخطاء

كيف يعمل EC2 User Data

عند إطلاق نسخة EC2، تقوم خدمة cloud-init بجلب بيانات User Data من نقطة نهاية بيانات التعريف الداخلية (http://169.254.169.254/latest/user-data) وتنفيذها. هذه العملية تحدث في مرحلة مبكرة جداً من دورة حياة الإقلاع، قبل أن يكون النظام جاهزاً للاستخدام الكامل.

السلوك الافتراضي: السكريبت يُنفَّذ مرة واحدة فقط عند الإقلاع الأول للنسخة. إعادة تشغيل النسخة (stop/start) لا تُعيد تنفيذ User Data بشكل افتراضي. هذا التمييز مهم — كثير من المهندسين يتوقعون إعادة التنفيذ عند كل إقلاع ثم يتساءلون لماذا لا تُطبَّق تغييراتهم.

graph TD A["إطلاق نسخة EC2"] --> B["Hypervisor يُقلع النظام"] B --> C["cloud-init تبدأ"] C --> D["جلب User Data من 169.254.169.254"] D --> E{"نوع User Data؟"} E -->|"يبدأ بـ #!/bin/bash"| F["تنفيذ Shell Script بصلاحيات root"] E -->|"يبدأ بـ #cloud-config"| G["تنفيذ YAML Directives"] E -->|"فارغ أو غير معروف"| H["تجاهل User Data"] F --> I["كتابة المخرجات في /var/log/cloud-init-output.log"] G --> I I --> J["النسخة تصبح Running"] H --> J
  1. إطلاق النسخة: يُرسل AWS طلب الإقلاع إلى hypervisor.
  2. تهيئة cloud-init: تجلب الخدمة User Data من نقطة نهاية بيانات التعريف.
  3. التحقق من النوع: إذا بدأ النص بـ #! فهو سكريبت Shell، وإذا بدأ بـ #cloud-config فهو YAML directive.
  4. التنفيذ: يُنفَّذ السكريبت بصلاحيات root، والمخرجات تُكتب في /var/log/cloud-init-output.log.
  5. إشارة الاكتمال: بعد انتهاء cloud-init، تُرسل النسخة إشارة 'running' إلى AWS.

كتابة سكريبت User Data لتثبيت Nginx

السكريبت التالي يُثبّت Nginx ويُشغّله على Amazon Linux 2 / Amazon Linux 2023. السطر الأول (#!/bin/bash) إلزامي — بدونه لن تعرف cloud-init كيف تُفسّر النص.

#!/bin/bash
# تحديث الحزم وتثبيت Nginx
yum update -y
yum install -y nginx

# تشغيل Nginx وتفعيله عند الإقلاع
systemctl start nginx
systemctl enable nginx

# اختياري: كتابة صفحة ترحيبية بسيطة
echo "<h1>مرحباً من $(hostname)</h1>" > /usr/share/nginx/html/index.html

لنسخ Ubuntu، استبدل yum بـ apt-get واسم الخدمة يبقى nginx:

#!/bin/bash
apt-get update -y
apt-get install -y nginx
systemctl start nginx
systemctl enable nginx

أين تلصق سكريبت User Data في AWS Console

الخطوات التالية تنطبق على تجربة إطلاق النسخ الحديثة في AWS Management Console:

  1. انتقل إلى EC2 → Instances → Launch instances.
  2. أكمل إعدادات النسخة (AMI، النوع، الشبكة، Security Group — تأكد من فتح المنفذ 80 إذا أردت اختبار Nginx).
  3. في قسم 'Advanced details'، مرّر للأسفل حتى تجد حقل 'User data'.
  4. اختر 'As text' والصق السكريبت مباشرةً.
  5. أكمل الإطلاق.
فكّر في User Data كـ 'رسالة تعليمات' تُرفق مع النسخة قبل شحنها — النسخة تقرأها مرة واحدة عند 'فتح الصندوق' لأول مرة، ثم تتجاهلها في كل مرة تُعاد تشغيلها.

تمرير User Data عبر AWS CLI

في بيئات الإنتاج، نادراً ما تُطلق النسخ يدوياً من Console. الطريقة الأكثر شيوعاً هي عبر CLI أو Infrastructure as Code. الأمر التالي يُطلق نسخة مع تمرير ملف السكريبت مباشرةً:

aws ec2 run-instances \
  --image-id ami-0c02fb55956c7d316 \
  --instance-type t3.micro \
  --key-name MyKeyPair \
  --security-group-ids sg-0123456789abcdef0 \
  --subnet-id subnet-0123456789abcdef0 \
  --user-data file://install-nginx.sh \
  --region us-east-1

المعامل file://install-nginx.sh يُحيل إلى ملف محلي على جهازك. AWS CLI يقرأ الملف ويُرسل محتواه مُشفَّراً بـ base64 إلى API. لا تحتاج إلى تشفيره يدوياً عند استخدام هذا الأسلوب.

تشخيص مشاكل User Data: الخطأ الأكثر شيوعاً

السيناريو الكلاسيكي: تُطلق النسخة، تنتظر دقيقتين، تتصل بـ SSH، تجد أن Nginx غير مثبّت. تفتح Console وترى النسخة في حالة 'running'. ما الخطأ؟

التشخيص الخاطئ الأول: 'ربما User Data لم يُنفَّذ'. الحقيقة في معظم الحالات: السكريبت نُفِّذ لكنه فشل بصمت. السبب الأكثر شيوعاً هو غياب #!/bin/bash في السطر الأول، أو وجود مسافة بيضاء قبله.

السجل الذي يحسم الأمر:

# الاتصال بالنسخة ومراجعة سجل cloud-init
ssh -i MyKeyPair.pem ec2-user@<public-ip>
cat /var/log/cloud-init-output.log

إذا رأيت خطأ مثل bash: command not found أو No such file or directory، فالمشكلة في السكريبت نفسه. إذا كان الملف فارغاً أو لا يحتوي على أي مخرجات من سكريبتك، فالمشكلة في تنسيق User Data.

للتحقق من أن User Data وصل بشكل صحيح إلى النسخة:

# من داخل النسخة
curl http://169.254.169.254/latest/user-data

إذا أعاد هذا الأمر السكريبت كاملاً، فـ User Data وصل. إذا أعاد خطأ 404، فهناك مشكلة في تمرير البيانات عند الإطلاق.

graph TD A["Nginx غير مثبّت بعد الإطلاق"] --> B{"هل وصل User Data؟"} B -->|"curl 169.254.169.254/latest/user-data"| C{"السكريبت موجود؟"} C -->|"نعم"| D["مراجعة /var/log/cloud-init-output.log"] C -->|"لا / 404"| E["مشكلة في تمرير User Data أعد الإطلاق مع التحقق من الحقل"] D --> F{"يوجد خطأ في السجل؟"} F -->|"نعم"| G["إصلاح السكريبت تأكد من وجود #!/bin/bash"] F -->|"لا أخطاء"| H["تحقق من حالة nginx: systemctl status nginx"] H --> I{"الخدمة تعمل؟"} I -->|"نعم"| J["تحقق من Security Group هل المنفذ 80 مفتوح؟"] I -->|"لا"| K["راجع أخطاء nginx: journalctl -u nginx"]
  1. التحقق من User Data: هل وصل السكريبت للنسخة؟ استخدم نقطة نهاية بيانات التعريف للتأكد.
  2. مراجعة سجل cloud-init: يكشف عن أخطاء التنفيذ الصامتة.
  3. التحقق من حالة الخدمة: حتى لو نُفِّذ السكريبت بنجاح، قد تفشل الخدمة لاحقاً.
  4. فحص Security Group: Nginx يعمل لكن المنفذ 80 مغلق — خطأ شائع منفصل عن User Data.

صلاحيات IAM المطلوبة لإطلاق نسخة مع User Data

User Data نفسه لا يتطلب صلاحيات IAM إضافية — فهو مجرد نص يُمرَّر مع طلب الإطلاق. لكن إذا كان السكريبت يستدعي خدمات AWS أخرى (مثل جلب ملفات من S3 أو قراءة أسرار من Secrets Manager)، فالنسخة تحتاج إلى IAM Instance Profile بالصلاحيات المناسبة.

مثال: سكريبت يجلب ملف إعدادات من S3 عند الإقلاع:

🔽 عرض سياسة IAM لقراءة ملف من S3
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject"
      ],
      "Resource": "arn:aws:s3:::my-config-bucket/nginx/nginx.conf"
    }
  ]
}

ربط Instance Profile بالنسخة عند الإطلاق عبر CLI:

aws ec2 run-instances \
  --image-id ami-0c02fb55956c7d316 \
  --instance-type t3.micro \
  --key-name MyKeyPair \
  --security-group-ids sg-0123456789abcdef0 \
  --subnet-id subnet-0123456789abcdef0 \
  --iam-instance-profile Name=MyInstanceProfile \
  --user-data file://install-nginx.sh \
  --region us-east-1

حدود User Data العملية

User Data مفيد للإعداد الأولي البسيط، لكنه يُظهر قيوداً واضحة مع تزايد التعقيد. الحد الأقصى لحجم User Data هو 16 كيلوبايت للنص غير المُشفَّر. في الممارسة العملية، السكريبتات التي تتجاوز هذا الحجم غالباً تكون علامة على أن الأداة الصحيحة هي AWS Systems Manager State Manager أو Ansible أو أدوات إدارة الإعدادات الأخرى — وليس User Data.

لإعادة تنفيذ User Data عند كل إقلاع (وليس مرة واحدة فقط)، يمكن تعديل سلوك cloud-init، لكن هذا يتطلب فهماً دقيقاً لآلية cloud-init لتجنب التنفيذ المتكرر غير المقصود لعمليات مثل تهيئة قواعد البيانات.

الخلاصة والخطوات التالية لتشغيل السكريبتات على EC2

EC2 User Data هو نقطة البداية الصحيحة لأتمتة إعداد النسخ — بسيط، مباشر، ولا يتطلب أي بنية تحتية إضافية. للسكريبتات البسيطة مثل تثبيت Nginx، هو الخيار الأمثل. للبيئات الأكثر تعقيداً، انظر في:

  • AWS Systems Manager Run Command: لتنفيذ الأوامر على نسخ قائمة دون SSH.
  • Launch Templates: لتوحيد إعدادات User Data عبر Auto Scaling Groups.
  • EC2 Image Builder: لبناء AMIs مُعدَّة مسبقاً بدلاً من الإعداد عند الإقلاع.

الوثائق الرسمية: AWS EC2 User Data — التوثيق الرسمي.

قاموس المصطلحات

المصطلحالتعريف
User Dataنص أو سكريبت يُمرَّر إلى نسخة EC2 عند إطلاقها لأول مرة وتُنفِّذه cloud-init تلقائياً.
cloud-initأداة تهيئة النسخ السحابية المعيارية، مسؤولة عن تنفيذ User Data وإعدادات الإقلاع الأولية.
Instance Profileحاوية IAM تربط Role بنسخة EC2، تمنحها صلاحيات للوصول إلى خدمات AWS الأخرى.
AMIAmazon Machine Image — قالب النسخة الذي يحدد نظام التشغيل والإعدادات الأساسية.
Instance Metadataبيانات تعريفية متاحة من داخل النسخة عبر 169.254.169.254، تشمل User Data وبيانات الهوية.

تعليقات

المشاركات الشائعة من هذه المدونة

استرجاع معرّف نسخة EC2 عبر خدمة البيانات الوصفية IMDSv2

أوضاع سعة DynamoDB: متى تختار On-Demand ومتى تختار Provisioned؟

فهم مهلة الرؤية في SQS: لماذا تُعالَج رسائلك مرتين؟