المستوى المطلوب: متوسط. تحتاج معرفة أساسية بـ AWS، وتشغيل سكربت Python، وقراءة صلاحيات IAM. مدة القراءة حوالي 6 دقائق.
لو خوادم التطوير والـ staging عندك شغّالة 24 ساعة في اليوم وانت بتستخدمها 8 ساعات بس، انت بتدفع فاتورة الحوسبة كاملة مقابل استخدام ثلثها. سكربت واحد يطفّي أي خادم عليه وسم محدد كل ليلة ويشغّله الصبح، فينزّل فاتورة الحوسبة لغير الإنتاج بما يقارب 65%.
المشكلة باختصار
خوادم بيئات التطوير مالهاش لازمة بالليل ولا في عطلة الأسبوع. محدش بيشتغل عليها الساعة 3 الفجر يوم الجمعة. ومع ذلك الفاتورة بتعدّ كل ثانية. الطريقة الشائعة إن كل واحد يطفّي خادمه بإيده قبل ما يمشي بتفشل دايمًا: حد بينسى، وحد بيسيب الخادم شغّال أسبوع كامل. الحل مش تذكير الناس، الحل أتمتة تشيل القرار من إيدهم.
ليه بتدفع على وقت مش بتستخدمه؟
تخيّل عدّاد تاكسي شغّال. طول ما العربية واقفة بموتور دائر، العدّاد بيزيد حتى لو انت نازل بتشتري حاجة. لو قفلت الموتور، العدّاد بيقف، بس الإيجار الشهري للجراج اللي راكنها فيه بيفضل عليك.
ده بالظبط اللي بيحصل في AWS. الخادم من نوع on-demand بتتحاسب عليه بالثانية طول ما هو في حالة running. أول ما تعمله stop، تكلفة المعالج والذاكرة (vCPU وRAM) بتقف تمامًا. لكن قرص التخزين المرتبط به (EBS) والـ Elastic IP بيفضلوا محسوبين، زي إيجار الجراج. يعني الإطفاء بيوفّر الجزء الأكبر (الحوسبة) بدون ما تفقد بياناتك على القرص.
الحل: EventBridge يشغّل Lambda يطفّي بالوسم
الفكرة في ثلاث قطع بسيطة: منبّه بمواعيد ثابتة (EventBridge Scheduler)، ودالة تنفّذ القرار (Lambda)، ووسم على الخوادم يحدد مين اللي ينطفّي. الخطوات:
- حط وسم على كل خادم تطوير تقبل إطفاءه:
AutoStop = true. الخوادم اللي من غير الوسم مش هتتلمس. - اكتب دالة Lambda تدوّر على الخوادم بالوسم وتطفّيها أو تشغّلها حسب الحدث.
- اربط قاعدتين في EventBridge Scheduler: وحدة تبعت
stopالساعة 8 مساءً، ووحدة تبعتstartالساعة 8 صباحًا، أيام العمل بس.
ده كود الدالة بلغة Python كامل وقابل للنسخ:
import boto3
ec2 = boto3.client("ec2")
def lambda_handler(event, context):
action = event.get("action", "stop") # "stop" أو "start"
filters = [{"Name": "tag:AutoStop", "Values": ["true"]}]
# اطفي اللي شغّال، وشغّل اللي واقف — بدون أخطاء
wanted_state = "running" if action == "stop" else "stopped"
filters.append({"Name": "instance-state-name", "Values": [wanted_state]})
ids = []
pages = ec2.get_paginator("describe_instances").paginate(Filters=filters)
for page in pages:
for res in page["Reservations"]:
for inst in res["Instances"]:
ids.append(inst["InstanceId"])
if not ids:
return {"action": action, "count": 0}
if action == "stop":
ec2.stop_instances(InstanceIds=ids)
else:
ec2.start_instances(InstanceIds=ids)
return {"action": action, "count": len(ids), "ids": ids}
لاحظ إن الفلترة بحالة الخادم بتخلّي الدالة آمنة عند التكرار: لو اتنفّذت مرتين بالغلط، مش هتحاول توقف خادم واقف أصلًا. القاعدتان في EventBridge Scheduler بيستخدما تعبير cron مع المنطقة الزمنية بتاعتك:
# قاعدة الإطفاء: 8 مساءً، الأحد إلى الخميس، بتوقيت القاهرة
aws scheduler create-schedule \
--name dev-stop \
--schedule-expression "cron(0 20 ? * SUN-THU *)" \
--schedule-expression-timezone "Africa/Cairo" \
--flexible-time-window '{"Mode":"OFF"}' \
--target '{"Arn":"","RoleArn":"","Input":"{\"action\":\"stop\"}"}'
# قاعدة التشغيل: 8 صباحًا بنفس الأيام
aws scheduler create-schedule \
--name dev-start \
--schedule-expression "cron(0 8 ? * SUN-THU *)" \
--schedule-expression-timezone "Africa/Cairo" \
--flexible-time-window '{"Mode":"OFF"}' \
--target '{"Arn":"","RoleArn":"","Input":"{\"action\":\"start\"}"}'
الدالة محتاجة صلاحيات IAM بسيطة بس: ec2:DescribeInstances وec2:StopInstances وec2:StartInstances. متديهاش أكتر من كده.
الأرقام: قبل وبعد
خلّينا نحسبها على أسطول تطوير صغير تكلفة حوسبته حوالي 3 دولار في الساعة (كام خادم متوسط). الأرقام دي تقديرية للتوضيح:
- 24/7: 730 ساعة في الشهر تقريبًا × 3 دولار = حوالي 2,190 دولار شهريًا.
- مجدول (12 ساعة × 5 أيام): حوالي 260 ساعة في الشهر × 3 دولار = حوالي 780 دولار شهريًا.
- التوفير: (730 − 260) ÷ 730 = ما يقارب 64%، أي حوالي 1,410 دولار شهريًا على الحوسبة وحدها.
وتكلفة تشغيل الأتمتة نفسها؟ EventBridge وLambda بيدخلوا عمليًا في الطبقة المجانية لهذا الحجم، يعني قريبة من صفر شهريًا.
الـ trade-offs وما يجب الانتباه له
مفيش حل مجاني بالكامل. اللي بتكسبه توفير كبير، واللي بتخسره حاجات لازم تحسب حسابها:
- التخزين بيفضل محسوب. أقراص EBS والـ Elastic IP بتتحاسب حتى والخادم واقف. قرص gp3 بحجم 100 جيجا ممكن يكلّفك حوالي 8 دولار شهريًا لكل خادم بغض النظر عن الإطفاء.
- الشغل الجاري بيتقطع. لو حد بيشغّل اختبار طويل الساعة 8 مساءً، الإطفاء هيوقفه. الحل: وسم استثناء زي
AutoStop=falseللخوادم اللي بتشتغل بالليل. - تأخير الصبح. الخادم بياخد دقيقة أو اتنين علشان يقلع وتشتغل خدماته. لو فريقك بيبدأ 9 صباحًا، خلّي التشغيل 8 علشان يكون جاهز.
- الـ IP العام بيتغيّر. بعد الإطفاء والتشغيل، الخادم بياخد IP عام جديد إلا لو مربوط بـ Elastic IP.
لو عايز حل مُدار بميزات أكتر (جداول متعددة، تقارير)، AWS عندها حل جاهز اسمه Instance Scheduler on AWS، بس بيضيف تكلفة صغيرة لـ DynamoDB وLambda. الافتراض هنا إن أسطولك صغير ومتوسط، فالسكربت البسيط أوفر.
متى لا تستخدم هذه الطريقة
ما تطبّقهاش على الإنتاج ولا أي خدمة لازم تفضل متاحة 24 ساعة. وما تستخدمهاش لو خوادمك بتعتمد على تخزين instance-store مؤقت بيتمسح مع الإطفاء. ولو عندك خادم واحد صغير على الطبقة المجانية، التوفير مش هيستاهل مجهود الإعداد. وأخيرًا، لو الفريق موزّع على مناطق زمنية بعيدة، وحّد جدولًا يغطّي الجميع أو اعمل جدول لكل منطقة.
الخطوة التالية
دلوقتي حالًا: افتح كونسول EC2، اختار خادم تطوير واحد مش مهم، وحط عليه الوسم AutoStop=true. انشر دالة Lambda وقاعدة الإطفاء بس (من غير التشغيل الأوتوماتيكي) وسيبها تطفّيه الليلة. الصبح افتح الكونسول وتأكد إنه stopped، وشغّله بإيدك. لو نجح على خادم واحد، وسّعها على الباقي.
مصادر
- دورة حياة الخادم والفوترة عند الإيقاف — AWS EC2 Instance lifecycle
- كيف تُحسب فاتورة EC2 والحالات — AWS: How EC2 billing works
- الجدولة بـ EventBridge Scheduler — AWS EventBridge Scheduler
- واجهة إيقاف الخوادم في boto3 — boto3 stop_instances
- الحل المُدار الجاهز — Instance Scheduler on AWS
- مرجع عملي إضافي — OneUptime: Schedule EC2 start/stop to save costs