مفاهيم البنية التحتية ككود
ما هو IaC؟
البنية التحتية ككود (IaC) هي ممارسة إدارة وتوفير البنية التحتية عبر ملفات التكوين بدلاً من العمليات اليدوية.
┌─────────────────────────────────────────────────────────────┐
│ IaC vs MANUEL │
├─────────────────────────────────────────────────────────────┤
│ │
│ PROVISIONING MANUEL │
│ ─────────────────── │
│ 1. Ouvrir la console AWS │
│ 2. Cliquer "Launch Instance" │
│ 3. Configurer manuellement... │
│ 4. Répéter pour chaque ressource │
│ 5. Documenter les paramètres │
│ │
│ Problèmes : │
│ ❌ Non reproductible │
│ ❌ Erreurs humaines │
│ ❌ Pas de versioning │
│ ❌ Documentation obsolète │
│ ❌ Difficile à auditer │
│ │
│ ──────────────────────────────────────────────────────── │
│ │
│ INFRASTRUCTURE AS CODE │
│ ────────────────────── │
│ 1. Écrire un template (YAML/JSON) │
│ 2. Versionner dans Git │
│ 3. Déployer avec CloudFormation │
│ 4. Automatiser via CI/CD │
│ │
│ Avantages : │
│ ✅ Reproductible (même résultat chaque fois) │
│ ✅ Versionné (historique complet) │
│ ✅ Revue de code (peer review) │
│ ✅ Documentation vivante (le code EST la doc) │
│ ✅ Automatisable (CI/CD) │
│ │
└─────────────────────────────────────────────────────────────┘
AWS CloudFormation
نظرة عامة
┌─────────────────────────────────────────────────────────────┐
│ CLOUDFORMATION │
├─────────────────────────────────────────────────────────────┤
│ │
│ COMPOSANTS : │
│ │
│ ┌─────────────┐ │
│ │ TEMPLATE │ Fichier YAML/JSON décrivant │
│ │ (code) │ l'infrastructure souhaitée │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ STACK │ Instance d'un template │
│ │ │ avec des ressources réelles │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ RESSOURCES AWS │ │
│ │ │ │
│ │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │ │
│ │ │ VPC │ │ EC2 │ │ RDS │ │ ALB │ │ SG │ │ │
│ │ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ CYCLE DE VIE : │
│ Create → Update → Delete │
│ (ou Rollback si erreur) │
│ │
└─────────────────────────────────────────────────────────────┘
هيكل القالب
الأقسام
AWSTemplateFormatVersion: "2010-09-09"
Description: وصف القالب
# 1. PARAMETERS - متغيرات الإدخال
Parameters:
EnvironmentType:
Type: String
Default: dev
AllowedValues: [dev, staging, prod]
# 2. MAPPINGS - جداول البحث
Mappings:
RegionAMI:
us-east-1:
AMI: ami-0123456789
# 3. CONDITIONS - منطق الشرط
Conditions:
IsProd: !Equals [!Ref EnvironmentType, prod]
# 4. RESOURCES - الموارد التي سيتم إنشاؤها (إلزامي)
Resources:
MyEC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: !FindInMap [RegionAMI, !Ref "AWS::Region", AMI]
InstanceType: t3.micro
# 5. OUTPUTS - القيم المصدرة
Outputs:
InstanceId:
Value: !Ref MyEC2Instance
Export:
Name: MyInstanceId
أنواع الموارد الشائعة
| النوع | الوصف |
|---|---|
AWS::EC2::Instance | مثيل EC2 |
AWS::EC2::VPC | VPC |
AWS::EC2::Subnet | شبكة فرعية |
AWS::EC2::SecurityGroup | مجموعة الأمان |
AWS::RDS::DBInstance | قاعدة بيانات RDS |
AWS::S3::Bucket | حاوية S3 |
AWS::Lambda::Function | وظيفة Lambda |
AWS::ElasticLoadBalancingV2::LoadBalancer | ALB/NLB |
الدوال المضمنة
الأكثر استخدامًا
Resources:
# !Ref - الإشارة إلى متغير أو مورد
MyInstance:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref InstanceType # متغير
SubnetId: !Ref MySubnet # مورد
# !GetAtt - الحصول على خاصية من مورد
MyDNSRecord:
Type: AWS::Route53::RecordSet
Properties:
Name: app.example.com
ResourceRecords:
- !GetAtt MyInstance.PublicIp # IP العامة للمثيل
# !Sub - استبدال المتغيرات
MyBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub "${AWS::StackName}-${AWS::Region}-data"
# !Join - دمج القيم
MyTag:
Type: AWS::EC2::Instance
Properties:
Tags:
- Key: Name
Value: !Join ["-", [web, !Ref EnvironmentType, server]]
# !If - شرط
MyVolume:
Type: AWS::EC2::Volume
Properties:
Size: !If [IsProd, 100, 20] # 100 جيجابايت في الإنتاج، 20 خلاف ذلك
# !FindInMap - البحث في Mappings
MyInstance2:
Type: AWS::EC2::Instance
Properties:
ImageId: !FindInMap [RegionAMI, !Ref "AWS::Region", AMI]
مثال كامل: بنية تحتية ويب
AWSTemplateFormatVersion: "2010-09-09"
Description: بنية تحتية ويب بسيطة مع EC2 ومجموعة الأمان
Parameters:
Environment:
Type: String
Default: dev
AllowedValues: [dev, staging, prod]
Description: اسم البيئة
InstanceType:
Type: String
Default: t3.micro
AllowedValues: [t3.micro, t3.small, t3.medium]
KeyName:
Type: AWS::EC2::KeyPair::KeyName
Description: زوج مفاتيح EC2 للوصول عبر SSH
Mappings:
RegionAMI:
us-east-1:
AMI: ami-0c55b159cbfafe1f0
eu-west-1:
AMI: ami-0d729a60
Resources:
# مجموعة الأمان
WebSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: السماح بـ HTTP و SSH
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: !Sub "${Environment}-web-sg"
- Key: Environment
Value: !Ref Environment
# مثيل EC2
WebServer:
Type: AWS::EC2::Instance
Properties:
ImageId: !FindInMap [RegionAMI, !Ref "AWS::Region", AMI]
InstanceType: !Ref InstanceType
KeyName: !Ref KeyName
SecurityGroupIds:
- !Ref WebSecurityGroup
Tags:
- Key: Name
Value: !Sub "${Environment}-web-server"
- Key: Environment
Value: !Ref Environment
UserData:
Fn::Base64: |
#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
echo "<h1>Hello from CloudFormation!</h1>" > /var/www/html/index.html
Outputs:
InstanceId:
Description: معرف المثيل
Value: !Ref WebServer
Export:
Name: !Sub "${Environment}-WebServerId"
PublicIP:
Description: عنوان IP العام
Value: !GetAtt WebServer.PublicIp
WebsiteURL:
Description: عنوان URL للموقع
Value: !Sub "http://${WebServer.PublicIp}"
أوامر CLI
# التحقق من صحة قالب
aws cloudformation validate-template \
--template-body file://template.yaml
# إنشاء stack
aws cloudformation create-stack \
--stack-name my-web-stack \
--template-body file://template.yaml \
--parameters \
ParameterKey=Environment,ParameterValue=dev \
ParameterKey=KeyName,ParameterValue=my-key
# عرض حالة stack
aws cloudformation describe-stacks \
--stack-name my-web-stack
# عرض الأحداث (تصحيح الأخطاء)
aws cloudformation describe-stack-events \
--stack-name my-web-stack
# تحديث stack
aws cloudformation update-stack \
--stack-name my-web-stack \
--template-body file://template.yaml \
--parameters \
ParameterKey=Environment,ParameterValue=staging
# حذف stack
aws cloudformation delete-stack \
--stack-name my-web-stack
أفضل الممارسات
┌─────────────────────────────────────────────────────────────┐
│ BONNES PRATIQUES CLOUDFORMATION │
├─────────────────────────────────────────────────────────────┤
│ │
│ ✅ FAIRE │
│ ──────── │
│ • Versionner les templates dans Git │
│ • Utiliser des paramètres pour la flexibilité │
│ • Ajouter des descriptions claires │
│ • Utiliser des noms logiques significatifs │
│ • Valider avant de déployer │
│ • Utiliser des Change Sets pour preview │
│ • Taguer toutes les ressources │
│ │
│ ❌ ÉVITER │
│ ───────── │
│ • Hardcoder des valeurs (AMIs, IPs...) │
│ • Créer des templates monolithiques (> 500 lignes) │
│ • Ignorer les erreurs de validation │
│ • Déployer sans revue de code │
│ • Oublier les outputs pour les références │
│ │
└─────────────────────────────────────────────────────────────┘
ملخص
| المفهوم | الوصف |
|---|---|
| Template | ملف YAML/JSON يصف البنية التحتية |
| Stack | مثيل منشور من قالب |
| Parameters | متغيرات إدخال قابلة للتكوين |
| Resources | الموارد AWS التي سيتم إنشاؤها |
| Outputs | القيم المصدرة للمرجعية |
| !Ref | الإشارة إلى مورد أو متغير |
| !GetAtt | الحصول على خاصية من مورد |
القسم التالي: مختبر CloudFormation