AWS DevOps Infrastructure Code: الـ9 خطوات الرئيسية للانتقال من الصفر إلى التشغيل

AWS DevOps Infrastructure Code: الأساسيات في مقال واحد — كود حقيقي، مخططات وخطوات ملموسة، مقتطفات من دورة مكونة من 39 درسًا.

AWS DevOps Infrastructure Code: الـ9 خطوات الرئيسية للانتقال من الصفر إلى التشغيل

يمكن للجميع تعلم AWS DevOps Infrastructure Code — بشرط اتباع الخطوات بالترتيب الصحيح. لقد قمنا بتلخيص دورة كاملة من 39 درسًا في مسار واضح، مع أكثر مقتطفات الكود فائدة.

tl;dr
  • مقدمة وتكوين AWS
  • ديف أوبس والبنية التحتية ككود
  • AWS CloudFormation
  • AWS CDK Cloud Development Kit
  • CICD مع AWS CodePipeline
~$ cat ./parcours.md # AWS DevOps Infrastructure Code — 10 فصول
01
مقدمة وتكوين AWS
→ الفصل 00 — إنشاء حساب AWS Free Tier→ الفصل 00 — IAM : المستخدمين، الأدوار والسياسات+ 2 دروس أخرى
02
DevOps والبنية التحتية ككود
→ الفصل 01 — فلسفة DevOps→ الفصل 01 — البنية التحتية ككود (IaC)+ 2 دروس أخرى
03
AWS CloudFormation
→ مقدمة إلى AWS CloudFormation→ Parameters, Outputs, Mappings و Conditions+ 2 دروس أخرى
04
AWS CDK Cloud Development Kit
→ مقدمة إلى AWS CDK — Cloud Development Kit→ CDK بالتفصيل — إنشاء بنية تحتية حقيقية+ 2 دروس أخرى
05
CICD مع AWS CodePipeline
→ CodeCommit و CodeBuild→ CodeDeploy و CodePipeline+ 2 دروس أخرى
06
الحاويات على AWS Docker ECS Fargate
→ Docker و Amazon ECR→ Amazon ECS و Fargate+ 2 دروس أخرى
07
المراقبة والملاحظة
→ CloudWatch — Logs، المقاييس والإنذارات→ AWS X-Ray و CloudTrail+ 2 دروس أخرى
08
Terraform على AWS
→ مقدمة إلى Terraform على AWS→ Terraform — State، Variables و Modules+ 2 دروس أخرى
🏁
المشروع النهائي (+ 2 فصول في الطريق)
→ تعود بمشروع ملموس وقابل للعرض

مقدمة إلى 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 تلقائيًا من كودك.

NOTEالمبدأ: تكتب بلغة Python (أو TypeScript، إلخ)، يترجم CDK هذا الكود إلى قالب CloudFormation صالح، ثم ينشر CloudFormation الموارد على AWS. تستفيد من قوة لغة برمجة حقيقية (حلقات، شروط، دوال، وراثة) لوصف بنيتك التحتية.

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 مثبتًا.

المتطلبات الأساسية

bash
# 1. التحقق من Node.js (الإصدار 18+ موصى به)
node --version
bash
# تهيئة في المنطقة الحالية
cdk bootstrap

# تهيئة في منطقة محددة
cdk bootstrap aws://123456789012/eu-west-1

الـ Constructs هي اللبنات الأساسية لـ CDK. توجد بثلاثة مستويات من التجريد، كل منها يقدم توازنًا مختلفًا بين التحكم والبساطة.

L1 — Constructs منخفضة المستوى (CfnXxx)

الـ constructs L1 (مسبوقة بـ Cfn) هي تغليف مباشر حول موارد CloudFormation. تمنح وصولاً إلى جميع الخصائص لكن بدون قيم افتراضية — يجب تهيئة كل شيء صراحة.

output
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

output
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 الأم التي تشير إلى الوحدات

output
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

output
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

bash
# 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_IAM
TIPمزايا Nested Stacks: النمطية (كل وحدة مستقلة)، إعادة الاستخدام (نفس وحدة الشبكة لـ dev و prod)، القابلية للقراءة (تبقى القوالب قصيرة)، وحدود CloudFormation (500 مورد كحد أقصى لكل stack — تتجاوز الـ nested stacks هذا الحد).

2. StackSets — النشر على عدة حسابات ومناطق

تخيل سلسلة مطاعم تفتح فروعًا في جميع أنحاء العالم. ينشئ المدير العام وصفة قائمة قياسية، وهوية بصرية، وإجراءات تشغيل تنطبق على جميع المطاعم سواء في باريس أو نيويورك أو طوكيو. عند إضافة قاعدة جديدة (حساسية جديدة للعرض، لائحة صحية جديدة)، تُطبق في جميع مطاعم السلسلة بقرار مركزي واحد. تعمل StackSets بنفس الطريقة: تحدد بنيتك التحتية مرة واحدة وتنشرها في جميع حسابات AWS وجميع مناطقك بعملية واحدة.

تتيح StackSets نشر نفس قالب CloudFormation في عدة حسابات AWS و/أو عدة مناطق بعملية واحدة. وهي الأداة المثالية للمؤسسات متعددة الحسابات (Landing Zone، Control Tower).

حالات الاستخدام النموذجية

الحوكمة المركزية

نشر قواعد AWS Config و CloudTrail و GuardDuty في جميع حسابات المؤسسة تلقائيًا.

الامتثال الموحد

تطبيق نفس سياسات IAM ومجموعات الأمان الأساسية والإشعارات في كل حساب.

متعدد المناطق

نشر بنية تحتية متطابقة في us-east-1 و eu-west-1 و ap-southeast-1 للتكرار العالمي.

المتطلبات الأساسية: تهيئة الأذونات

bash
# 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 كامل مع جميع أفضل الممارسات

output
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

أوامر النشر الأساسية

bash
# 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 عبر اسم داخلي
output
---
# 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: 8080

3. ConfigMaps و Secrets في Kubernetes

ConfigMap — التكوين غير الحساس

output
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: 300

Secret Kubernetes

output
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"
WARNINGتنبيه: افتراضيًا، تُشفر Secrets Kubernetes بـ base64 فقط (غير مشفرة) في etcd. لتعزيز الأمان على EKS، فعّل تشفير Secrets بمفتاح KMS، وفكر في استخدام AWS Secrets Manager + External Secrets Operator لمزامنة الأسرار تلقائيًا.

External Secrets Operator — المزامنة من Secrets Manager

output
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"
va-plus-loin

يغطي هذا المقال المقتطفات الأكثر فائدة — الدورة الكاملة AWS DevOps Infrastructure Code (10 فصول، 39 درسًا، تمارين مصححة ومشروع نهائي) تأخذك إلى النهاية.

./acceder-au-cours-complet cours gratuit : Maîtriser Claude Code

الأسئلة الشائعة

كم من الوقت لتعلم AWS DevOps Infrastructure Code ؟
مع تقدم منظم (10 فصول، 39 درسًا قصيرًا وعمليًا)، يمكن الوصول إلى مستوى تشغيلي في بضعة أسابيع بمعدل 30 إلى 60 دقيقة يوميًا. المهم هو تطبيق كل مفهوم فورًا.
هل هناك متطلبات أساسية ؟
يفضل أن تكون مرتاحًا مع أساسيات المجال: هذا المحتوى يتعمق، مع حالات حقيقية.
من أين نبدأ عمليًا ؟
طبّق الأوامر الواردة في هذا المقال، ثم تابع الدورة الكاملة AWS DevOps Infrastructure Code: تربط الـ 39 درسًا بالترتيب، مع تمارين ومشروع نهائي.

📬 هل تريد تلقي هذا النوع من الأدلة كل أسبوع ؟ اشترك مجانًا — كود حقيقي، بدون كلام زائد.