AWS DevOps Infrastructure Code: الـ9 خطوات الرئيسية للانتقال من الصفر إلى التشغيل
AWS DevOps Infrastructure Code: الأساسيات في مقال واحد — كود حقيقي، مخططات وخطوات ملموسة، مقتطفات من دورة مكونة من 39 درسًا.
يمكن للجميع تعلم AWS DevOps Infrastructure Code — بشرط اتباع الخطوات بالترتيب الصحيح. لقد قمنا بتلخيص دورة كاملة من 39 درسًا في مسار واضح، مع أكثر مقتطفات الكود فائدة.
- مقدمة وتكوين AWS
- ديف أوبس والبنية التحتية ككود
- AWS CloudFormation
- AWS CDK Cloud Development Kit
- CICD مع AWS CodePipeline
مقدمة إلى AWS CDK — Cloud Development Kit
الفصل 03 — الدرس 01 · AWS DevOps : البنية التحتية ككود
1. ما هو AWS CDK ؟
CloudFormation يشبه ملء نموذج إداري CERFA يدويًا، خانة بخانة، مع الالتزام بقواعد صيغة صارمة. إنه ممل لكنه يعمل. أما CDK فهو برنامج حاسوبي يملأ هذا النموذج نيابة عنك: تخبره بلغة Python "أريد خادمًا متوسط الحجم مع قاعدة بيانات"، فيولد تلقائيًا النموذج الكامل المملوء بشكل صحيح مع جميع الخانات الإلزامية. تكتب أقل بكثير، وتنجز أكثر بكثير، وتستفيد من قوة لغة برمجة حقيقية مثل الحلقات والدوال وإعادة استخدام الكود.
AWS Cloud Development Kit (CDK) هو إطار عمل مفتوح المصدر يتيح تعريف بنيتك التحتية على AWS بلغة برمجة حقيقية: Python أو TypeScript أو Java أو C# أو Go. يولد CDK بعد ذلك قوالب CloudFormation تلقائيًا من كودك.
CDK مقابل CloudFormation — مقارنة
| المعيار | CloudFormation (YAML) | AWS CDK (Python) |
|---|---|---|
| اللغة | YAML / JSON تصريحي | Python، TypeScript، Java، C#، Go |
| إعادة الاستخدام | نسخ ولصق، Nested Stacks | فئات، وحدات، وراثة |
| الإكمال التلقائي في IDE | محدود (YAML) | كامل مع الأنواع والتوثيق |
| المنطق | شروط وتعيينات محدودة | if/else، حلقات for، دوال كاملة |
| الاختبارات | صعب | اختبارات وحدة مع pytest، jest |
| منحنى التعلم | منخفض لـ YAML، لكنه مطول | يتطلب معرفة بلغة برمجة |
| تحت الغطاء | يُنفذ مباشرة بواسطة CloudFormation | يولد CloudFormation ثم ينشره |
المفاهيم الأربعة الأساسية لـ CDK
App (تطبيق CDK)
نقطة الدخول لأي مشروع CDK. يحتوي App على Stack واحد أو أكثر. وهو الحاوية الجذرية لبنيتك التحتية.
Stack (كومة CDK)
تتوافق مع stack CloudFormation. تحتوي على Constructs (موارد AWS). يمكن أن يحتوي App على عدة Stacks لبيئات مختلفة.
Construct
اللبنة الأساسية للبناء في CDK. تمثل مورد AWS (أو مجموعة موارد). توجد بثلاثة مستويات: L1، L2، L3.
Environment (بيئة)
التركيبة بين حساب AWS + المنطقة المستهدفة للنشر. تتيح نشر نفس الـ stack في عدة بيئات.
2. التثبيت — Node.js و CDK CLI و Python
CDK CLI أداة Node.js. حتى لو كنت تبرمج بلغة Python، يجب أن يكون Node.js مثبتًا.
المتطلبات الأساسية
# 1. التحقق من Node.js (الإصدار 18+ موصى به) node --version
# تهيئة في المنطقة الحالية cdk bootstrap # تهيئة في منطقة محددة cdk bootstrap aws://123456789012/eu-west-1
الـ Constructs هي اللبنات الأساسية لـ CDK. توجد بثلاثة مستويات من التجريد، كل منها يقدم توازنًا مختلفًا بين التحكم والبساطة.
L1 — Constructs منخفضة المستوى (CfnXxx)
الـ constructs L1 (مسبوقة بـ Cfn) هي تغليف مباشر حول موارد CloudFormation. تمنح وصولاً إلى جميع الخصائص لكن بدون قيم افتراضية — يجب تهيئة كل شيء صراحة.
from aws_cdk import aws_s3 as s3
import aws_cdk as cdk
class MaStack(cdk.Stack):
def __init__(self, scope, id, **kwargs):
super().__init__(scope, id, **kwargs)
# L1 : CfnBucket = wrapper direct CloudFormation AWS::S3::Bucket
bucket_l1 = s3.CfnBucket(self, "BucketL1",
bucket_name="mon-bucket-l1",
versioning_configuration=s3.CfnBucket.VersioningConfigurationProperty(
status="Enabled"
),
lifecycle_configuration=s3.CfnBucket.LifecycleConfigurationProperty(
rules=[s3.CfnBucket.RuleProperty(
id="expiration-anciens-objets",
status="Enabled",
expiration_in_days=90
)]
)
)L2 — Constructs عالية المستوى (موصى بها)
Nested Stacks و StackSets و Change Sets وأفضل الممارسات
الفصل 02 — الدرس 03 · AWS DevOps : البنية التحتية ككود
1. Nested Stacks — تفكيك البنى التحتية الكبيرة
تخيل بناء مبنى مكاتب. بدلاً من مقاول واحد يقوم بكل شيء من الألف إلى الياء ويُرهق سريعًا، نستعين بمتخصصين مستقلين: كهربائي للشبكة الكهربائية، وسباك للتمديدات، ونجار للحواجز، وفني شبكات للمعلوماتية. يعمل كل في مجاله، وينتج تقريره، وينسق رئيس الموقع الجميع. تعمل Nested Stacks بنفس الطريقة: كل وحدة (شبكة، أمان، قاعدة بيانات، تطبيق) هي قالب مستقل تديره فرقة مختلفة، وتتولى stack أم تنسيق الجميع.
عندما تصبح البنية التحتية معقدة (VPC، قواعد بيانات، تطبيقات، أمان...)، يصبح تجميع كل شيء في قالب واحد غير قابل للإدارة. تتيح Nested Stacks (الأكوام المتداخلة) تقسيم البنية التحتية إلى وحدات قابلة لإعادة الاستخدام، كل في قالبها الخاص.
هندسة طبقية باستخدام Nested Stacks
infrastructure/ ├── stack-parent.yaml # Stack racine — orchestre tout ├── modules/ │ ├── reseau.yaml # VPC, subnets, Internet Gateway │ ├── securite.yaml # Security Groups, IAM Roles │ ├── base-de-donnees.yaml # RDS, cache ElastiCache │ └── application.yaml # EC2, Load Balancer, Auto Scaling
الـ stack الأم التي تشير إلى الوحدات
AWSTemplateFormatVersion: "2010-09-09"
Description: "Stack parent — orchestre toute l'infrastructure"
Parameters:
Environnement:
Type: String
AllowedValues: [dev, prod]
URLTemplates:
Type: String
Description: "URL S3 de base où sont stockés les templates"
Default: "https://s3.amazonaws.com/mon-bucket-templates/v1"
Resources:
# Module réseau
StackReseau:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: !Sub "${URLTemplates}/reseau.yaml"
Parameters:
Environnement: !Ref Environnement
CIDRVpc: "10.0.0.0/16"
TimeoutInMinutes: 15
# Module sécurité — dépend du réseau
StackSecurite:
Type: AWS::CloudFormation::Stack
DependsOn: StackReseau
Properties:
TemplateURL: !Sub "${URLTemplates}/securite.yaml"
Parameters:
Environnement: !Ref Environnement
VpcId: !GetAtt StackReseau.Outputs.VpcId
# Module base de données
StackBDD:
Type: AWS::CloudFormation::Stack
DependsOn: StackSecurite
Properties:
TemplateURL: !Sub "${URLTemplates}/base-de-donnees.yaml"
Parameters:
Environnement: !Ref Environnement
VpcId: !GetAtt StackReseau.Outputs.VpcId
SubnetIds: !GetAtt StackReseau.Outputs.SubnetsPrives
SGBaseDeDonnees: !GetAtt StackSecurite.Outputs.SGBaseDeDonnees
TimeoutInMinutes: 30
# Module application
StackApplication:
Type: AWS::CloudFormation::Stack
DependsOn: StackBDD
Properties:
TemplateURL: !Sub "${URLTemplates}/application.yaml"
Parameters:
Environnement: !Ref Environnement
VpcId: !GetAtt StackReseau.Outputs.VpcId
SubnetPublics: !GetAtt StackReseau.Outputs.SubnetsPublics
URLBDD: !GetAtt StackBDD.Outputs.EndpointBDD
SGApplication: !GetAtt StackSecurite.Outputs.SGApplication
Outputs:
URLApplication:
Description: "URL du Load Balancer de l'application"
Value: !GetAtt StackApplication.Outputs.URLLoadBalancerمثال على قالب الوحدة reseau.yaml
AWSTemplateFormatVersion: "2010-09-09"
Description: "Module réseau — VPC, subnets publics et privés"
Parameters:
Environnement:
Type: String
CIDRVpc:
Type: String
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref CIDRVpc
EnableDnsHostnames: true
EnableDnsSupport: true
Tags:
- Key: Name
Value: !Sub "vpc-${Environnement}"
SubnetPublic1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: "10.0.1.0/24"
AvailabilityZone: !Select [0, !GetAZs ""]
MapPublicIpOnLaunch: true
SubnetPrive1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: "10.0.10.0/24"
AvailabilityZone: !Select [0, !GetAZs ""]
Outputs:
VpcId:
Value: !Ref VPC
Export:
Name: !Sub "${AWS::StackName}-VpcId"
SubnetsPublics:
Value: !Join [",", [!Ref SubnetPublic1]]
Export:
Name: !Sub "${AWS::StackName}-SubnetsPublics"
SubnetsPrives:
Value: !Join [",", [!Ref SubnetPrive1]]
Export:
Name: !Sub "${AWS::StackName}-SubnetsPrives"النشر باستخدام القوالب المخزنة في S3
# Uploader les templates dans S3 d'abord
aws s3 sync ./modules/ s3://mon-bucket-templates/v1/ --exclude "*.md"
# Déployer la stack parent
aws cloudformation deploy \
--stack-name infra-prod \
--template-file stack-parent.yaml \
--parameter-overrides \
Environnement=prod \
URLTemplates=https://s3.amazonaws.com/mon-bucket-templates/v1 \
--capabilities CAPABILITY_IAM CAPABILITY_NAMED_IAM2. StackSets — النشر على عدة حسابات ومناطق
تخيل سلسلة مطاعم تفتح فروعًا في جميع أنحاء العالم. ينشئ المدير العام وصفة قائمة قياسية، وهوية بصرية، وإجراءات تشغيل تنطبق على جميع المطاعم سواء في باريس أو نيويورك أو طوكيو. عند إضافة قاعدة جديدة (حساسية جديدة للعرض، لائحة صحية جديدة)، تُطبق في جميع مطاعم السلسلة بقرار مركزي واحد. تعمل StackSets بنفس الطريقة: تحدد بنيتك التحتية مرة واحدة وتنشرها في جميع حسابات AWS وجميع مناطقك بعملية واحدة.
تتيح StackSets نشر نفس قالب CloudFormation في عدة حسابات AWS و/أو عدة مناطق بعملية واحدة. وهي الأداة المثالية للمؤسسات متعددة الحسابات (Landing Zone، Control Tower).
حالات الاستخدام النموذجية
الحوكمة المركزية
نشر قواعد AWS Config و CloudTrail و GuardDuty في جميع حسابات المؤسسة تلقائيًا.
الامتثال الموحد
تطبيق نفس سياسات IAM ومجموعات الأمان الأساسية والإشعارات في كل حساب.
متعدد المناطق
نشر بنية تحتية متطابقة في us-east-1 و eu-west-1 و ap-southeast-1 للتكرار العالمي.
المتطلبات الأساسية: تهيئة الأذونات
# Deux modes de fonctionnement : # Mode 1 : Self-Managed (rôles IAM manuels dans chaque compte) # Créer AWSCloudFormationStackSetAdministrationRole dans le compte admin # Créer AWSCloudFormationStackSetExecutionRole dans chaque compte cible # Mode 2 : Service-Managed (via AWS Organizations — recommandé) # Activer la confiance avec Organizations dans CloudFormation aws organizations enable-aws-service-access \ --service-principal cloudformation.amazonaws.com
إنشاء ونشر StackSet
نشر وإدارة التطبيقات على EKS
الفصل 08 — Kubernetes على AWS EKS | AWS DevOps البنية التحتية ككود
1. نشر تطبيق — Deployment YAML
Deployment في Kubernetes يشبه سلسلة مطاعم سريعة. تحدد عدد "الكاونترات" (replicas) التي تريد فتحها في نفس الوقت. إذا تعطل أحدها، يفتح Kubernetes واحدًا جديدًا تلقائيًا دون أن يلاحظ العملاء. عندما تريد تغيير القائمة (إصدار جديد من الصورة)، يحدث Kubernetes التحديث كاونترًا تلو الآخر (rolling update) حتى لا تغلق جميع الكاونترات في وقت واحد. إذا لم تعجب القائمة الجديدة، يمكن العودة إلى القديمة فورًا (rollback).
يعلن Deployment Kubernetes عن الحالة المرغوبة لتطبيقك: أي صورة تستخدم، وعدد النسخ، وكيفية إجراء التحديثات. يحافظ Kubernetes على هذه الحالة باستمرار.
Deployment كامل مع جميع أفضل الممارسات
apiVersion: apps/v1
kind: Deployment
metadata:
name: mon-api-fastapi
namespace: mon-application
labels:
app: mon-api-fastapi
version: "1.0.0"
equipe: backend
spec:
replicas: 3
selector:
matchLabels:
app: mon-api-fastapi
# Stratégie de déploiement rolling update
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1 # Au plus 1 Pod indisponible pendant la mise à jour
maxSurge: 1 # Au plus 1 Pod en surplus pendant la mise à jour
template:
metadata:
labels:
app: mon-api-fastapi
version: "1.0.0"
spec:
serviceAccountName: sa-mon-api # IRSA — IAM Role for Service Account
terminationGracePeriodSeconds: 30
# Sécurité au niveau du Pod
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
containers:
- name: mon-api-fastapi
image: 123456789012.dkr.ecr.ca-central-1.amazonaws.com/mon-api-fastapi:1.0.0
ports:
- containerPort: 8080
protocol: TCP
# Limites de ressources obligatoires en production
resources:
requests:
cpu: "250m" # 0.25 vCPU garanti
memory: "256Mi" # 256 Mo garantis
limits:
cpu: "500m" # Maximum 0.5 vCPU
memory: "512Mi" # Maximum 512 Mo
# Variables d'environnement depuis ConfigMap et Secret
env:
- name: ENVIRONNEMENT
value: production
- name: PORT
value: "8080"
envFrom:
- configMapRef:
name: config-mon-api
- secretRef:
name: secrets-mon-api
# Sondes de santé
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
failureThreshold: 3
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
successThreshold: 1
startupProbe:
httpGet:
path: /health
port: 8080
failureThreshold: 30
periodSeconds: 5
# Sécurité du conteneur
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
# Distribution entre les zones de disponibilité
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: mon-api-fastapiأوامر النشر الأساسية
# Appliquer le manifeste kubectl apply -f deployment.yaml -n mon-application # Suivre le déploiement en temps réel kubectl rollout status deployment/mon-api-fastapi -n mon-application # Voir l'historique des déploiements kubectl rollout history deployment/mon-api-fastapi -n mon-application # Mettre à jour l'image (déclenche un rolling update) kubectl set image deployment/mon-api-fastapi \ mon-api-fastapi=123456789012.dkr.ecr.ca-central-1.amazonaws.com/mon-api-fastapi:1.1.0 \ -n mon-application # Revenir à la version précédente (rollback) kubectl rollout undo deployment/mon-api-fastapi -n mon-application # Revenir à une révision spécifique kubectl rollout undo deployment/mon-api-fastapi --to-revision=2 -n mon-application
2. خدمات Kubernetes: ClusterIP و NodePort و LoadBalancer
في Kubernetes، الخدمات تشبه عناوين بريدية مستقرة في مبنى يتغير سكانه كثيرًا. ClusterIP هو مكتب داخلي في المبنى: لا يمكن لأحد من الخارج الوصول إليه، وهو للتواصل بين الموظفين. LoadBalancer هو الباب الرئيسي للمبنى مع حارس أمن (Load Balancer AWS) يوجه الزوار الخارجيين إلى المكتب المناسب. حتى لو تغير السكان (إعادة تشغيل الـ Pods)، يبقى عنوان المبنى كما هو.
يعرض Service مجموعة من الـ Pods عبر IP مستقر واسم DNS داخلي، بغض النظر عن دورة حياة الـ Pods الفردية.
| النوع | إمكانية الوصول | حالة الاستخدام |
|---|---|---|
| ClusterIP | داخل العنقود فقط | التواصل بين الخدمات (قاعدة بيانات، ذاكرة تخزين مؤقت) |
| NodePort | من الخارج عبر IP الـ Node + منفذ ثابت (30000-32767) | الاختبارات، التطوير (غير موصى به في الإنتاج) |
| LoadBalancer | من الخارج عبر Load Balancer AWS (CLB/NLB) يُنشأ تلقائيًا | عرض خدمة مباشرة (بدون Ingress) |
| ExternalName | يحل إلى اسم DNS خارجي | الوصول إلى خدمات RDS، ElastiCache عبر اسم داخلي |
---
# Service ClusterIP — pour la communication interne
apiVersion: v1
kind: Service
metadata:
name: svc-mon-api
namespace: mon-application
labels:
app: mon-api-fastapi
spec:
type: ClusterIP
selector:
app: mon-api-fastapi # Correspond aux labels du Deployment
ports:
- name: http
port: 80 # Port du Service (interne)
targetPort: 8080 # Port du conteneur
protocol: TCP
---
# Service LoadBalancer — expose via un NLB AWS
apiVersion: v1
kind: Service
metadata:
name: svc-mon-api-public
namespace: mon-application
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "external"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"
service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
spec:
type: LoadBalancer
selector:
app: mon-api-fastapi
ports:
- name: http
port: 80
targetPort: 80803. ConfigMaps و Secrets في Kubernetes
ConfigMap — التكوين غير الحساس
apiVersion: v1
kind: ConfigMap
metadata:
name: config-mon-api
namespace: mon-application
data:
# Variables d'environnement
LOG_LEVEL: "info"
WORKERS: "4"
TIMEOUT: "30"
DATABASE_HOST: "rds-mon-app.ca-central-1.rds.amazonaws.com"
DATABASE_NAME: "production"
# Fichier de configuration complet
application.yaml: |
server:
host: 0.0.0.0
port: 8080
database:
pool_size: 10
max_overflow: 5
cache:
backend: redis
ttl: 300Secret Kubernetes
apiVersion: v1 kind: Secret metadata: name: secrets-mon-api namespace: mon-application type: Opaque stringData: # stringData accepte les valeurs en clair — K8s les encode en base64 automatiquement DATABASE_PASSWORD: "MonMotDePasseSecret" API_KEY: "sk-abc123..." JWT_SECRET: "ma-cle-jwt-super-secrete"
External Secrets Operator — المزامنة من Secrets Manager
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: secrets-aws-synchronises
namespace: mon-application
spec:
refreshInterval: 1h
secretStoreRef:
name: aws-secrets-manager
kind: ClusterSecretStore
target:
name: secrets-mon-api # Nom du Secret Kubernetes à créer
creationPolicy: Owner
data:
- secretKey: DATABASE_PASSWORD
remoteRef:
key: "mon-app/production/secrets"
property: "database_password"
- secretKey: API_KEY
remoteRef:
key: "mon-app/production/secrets"
property: "api_key"يغطي هذا المقال المقتطفات الأكثر فائدة — الدورة الكاملة AWS DevOps Infrastructure Code (10 فصول، 39 درسًا، تمارين مصححة ومشروع نهائي) تأخذك إلى النهاية.
./acceder-au-cours-complet cours gratuit : Maîtriser Claude Codeالأسئلة الشائعة
كم من الوقت لتعلم AWS DevOps Infrastructure Code ؟
هل هناك متطلبات أساسية ؟
من أين نبدأ عمليًا ؟
📬 هل تريد تلقي هذا النوع من الأدلة كل أسبوع ؟ اشترك مجانًا — كود حقيقي، بدون كلام زائد.