انتقل إلى المحتوى الرئيسي

بناء الجملة والقوالب في CloudFormation

مقدمة​

يستخدم CloudFormation قوالب بصيغة YAML أو JSON لتعريف البنية التحتية. يغطي هذا الفصل بناء الجملة بالتفصيل ويقدم أمثلة عملية على القوالب.

هيكل القالب​

# الهيكل الكامل لقالب CloudFormation
AWSTemplateFormatVersion: "2010-09-09"

Description: >
وصف لما يفعله القالب
(اختياري ولكن يوصى به)

Metadata:
# معلومات إضافية (اختياري)

Parameters:
# قيم إدخال قابلة للتخصيص (اختياري)

Mappings:
# تطابقات مفتاح-قيمة ثابتة (اختياري)

Conditions:
# منطق شرطي (اختياري)

Transform:
# ماكرو أو SAM (اختياري)

Resources:
# موارد AWS المراد إنشاؤها (إلزامي)

Outputs:
# قيم الإخراج (اختياري)

قسم Parameters​

بناء الجملة الأساسي​

Parameters:
EnvironmentType:
Type: String
Default: dev
AllowedValues:
- dev
- staging
- prod
Description: نوع البيئة

InstanceType:
Type: String
Default: t3.micro
AllowedValues:
- t3.micro
- t3.small
- t3.medium
Description: نوع مثيل EC2

KeyPairName:
Type: AWS::EC2::KeyPair::KeyName
Description: اسم زوج مفاتيح SSH

VpcCidr:
Type: String
Default: 10.0.0.0/16
AllowedPattern: ^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$
Description: CIDR الخاص بـ VPC

أنواع المعلمات AWS​

Parameters:
# أنواع أساسية
StringParam:
Type: String

NumberParam:
Type: Number
MinValue: 1
MaxValue: 100

ListParam:
Type: List<Number>

CommaListParam:
Type: CommaDelimitedList

# أنواع AWS محددة
EC2KeyPair:
Type: AWS::EC2::KeyPair::KeyName

SecurityGroupId:
Type: AWS::EC2::SecurityGroup::Id

SubnetId:
Type: AWS::EC2::Subnet::Id

VpcId:
Type: AWS::EC2::VPC::Id

AMIId:
Type: AWS::EC2::Image::Id

AvailabilityZone:
Type: AWS::EC2::AvailabilityZone::Name

# قوائم AWS
SubnetIds:
Type: List<AWS::EC2::Subnet::Id>

SecurityGroupIds:
Type: List<AWS::EC2::SecurityGroup::Id>

قسم Resources​

بناء جملة المورد​

Resources:
NomLogiqueRessource:
Type: AWS::Service::Resource
Properties:
Property1: Value1
Property2: Value2
DependsOn:
- AutreRessource
DeletionPolicy: Retain | Delete | Snapshot
UpdateReplacePolicy: Retain | Delete | Snapshot
Condition: MaCondition

أمثلة على الموارد الشائعة​

VPC​

Resources:
MonVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsHostnames: true
EnableDnsSupport: true
Tags:
- Key: Name
Value: MonVPC-Production

Subnet​

  PublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref MonVPC
CidrBlock: 10.0.1.0/24
AvailabilityZone: !Select [0, !GetAZs '']
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: Public-Subnet-1

Internet Gateway​

  InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: MonIGW

AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref MonVPC
InternetGatewayId: !Ref InternetGateway

Security Group​

  WebSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group pour serveur web
VpcId: !Ref MonVPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 10.0.0.0/8
Tags:
- Key: Name
Value: Web-SG

EC2 Instance​

  WebServer:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Ref InstanceType
ImageId: !Ref AMIId
KeyName: !Ref KeyPairName
SubnetId: !Ref PublicSubnet1
SecurityGroupIds:
- !Ref WebSecurityGroup
Tags:
- Key: Name
Value: WebServer-1
UserData:
Fn::Base64: !Sub |
#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
systemctl enable httpd
echo "Hello from ${AWS::StackName}" > /var/www/html/index.html

الدوال الداخلية​

Ref​

# مرجع إلى معلمة أو مورد
VpcId: !Ref MonVPC
InstanceType: !Ref ParametreInstanceType

# بناء جملة طويل
VpcId:
Ref: MonVPC

GetAtt​

# الحصول على سمة من مورد
Outputs:
InstancePublicIP:
Value: !GetAtt WebServer.PublicIp

SecurityGroupId:
Value: !GetAtt WebSecurityGroup.GroupId

# بناء جملة طويل
Value:
Fn::GetAtt:
- WebServer
- PublicIp

Sub (استبدال)​

# استبدال المتغيرات
UserData:
Fn::Base64: !Sub |
#!/bin/bash
echo "Region: ${AWS::Region}"
echo "Stack: ${AWS::StackName}"
echo "Instance: ${WebServer}"

# مع متغيرات مخصصة
Value: !Sub
- "arn:aws:s3:::${BucketName}/*"
- BucketName: !Ref MonBucket

Join​

# دمج العناصر مع فاصل
Value: !Join
- ","
- - subnet-12345
- subnet-67890
- subnet-abcde
# النتيجة: "subnet-12345,subnet-67890,subnet-abcde"

# بناء جملة قصير
Value: !Join [",", [!Ref Subnet1, !Ref Subnet2]]

Select​

# اختيار عنصر من قائمة
AvailabilityZone: !Select
- 0
- !GetAZs ''
# اختيار أول AZ من المنطقة

Split​

# تقسيم سلسلة
Value: !Select
- 0
- !Split [",", "a,b,c"]
# النتيجة: "a"

If (شرط)​

Conditions:
IsProd: !Equals [!Ref Environment, prod]

Resources:
MyInstance:
Type: AWS::EC2::Instance
Properties:
InstanceType: !If
- IsProd
- m5.large
- t3.micro

GetAZs​

# الحصول على AZs لمنطقة
AvailabilityZones: !GetAZs '' # المنطقة الحالية
AvailabilityZones: !GetAZs 'us-east-1' # منطقة محددة

قسم Conditions​

Parameters:
Environment:
Type: String
AllowedValues: [dev, staging, prod]

Conditions:
IsProd: !Equals [!Ref Environment, prod]
IsNotProd: !Not [!Equals [!Ref Environment, prod]]
IsProdOrStaging: !Or
- !Equals [!Ref Environment, prod]
- !Equals [!Ref Environment, staging]
IsProdAndMultiAZ: !And
- !Equals [!Ref Environment, prod]
- !Equals [!Ref MultiAZ, true]

Resources:
ProdOnlyResource:
Type: AWS::EC2::Instance
Condition: IsProd # يتم الإنشاء فقط إذا كانت IsProd تساوي true
Properties:
# ...

قسم Mappings​

Mappings:
RegionAMI:
us-east-1:
HVM64: ami-0123456789abcdef0
HVM32: ami-0123456789abcdef1
us-west-2:
HVM64: ami-abcdef0123456789a
HVM32: ami-abcdef0123456789b
eu-west-1:
HVM64: ami-fedcba9876543210f
HVM32: ami-fedcba9876543210e

EnvironmentConfig:
dev:
InstanceType: t3.micro
MinSize: 1
MaxSize: 2
prod:
InstanceType: m5.large
MinSize: 2
MaxSize: 10

Resources:
MyInstance:
Type: AWS::EC2::Instance
Properties:
ImageId: !FindInMap [RegionAMI, !Ref "AWS::Region", HVM64]
InstanceType: !FindInMap [EnvironmentConfig, !Ref Environment, InstanceType]

قسم Outputs​

Outputs:
VpcId:
Description: ID الخاص بـ VPC الذي تم إنشاؤه
Value: !Ref MonVPC
Export:
Name: !Sub "${AWS::StackName}-VpcId"

PublicSubnetId:
Description: ID الخاص بالشبكة الفرعية العامة
Value: !Ref PublicSubnet1
Export:
Name: !Sub "${AWS::StackName}-PublicSubnetId"

WebServerPublicIP:
Description: IP العام للخادم الويب
Value: !GetAtt WebServer.PublicIp
Condition: IsProd # إخراج شرطي

WebsiteURL:
Description: URL الموقع الإلكتروني
Value: !Sub "http://${WebServer.PublicDnsName}"

مثال كامل على القالب​

AWSTemplateFormatVersion: "2010-09-09"
Description: بنية تحتية ويب بسيطة مع VPC و EC2 و Security Group

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: زوج مفاتيح SSH

Mappings:
RegionAMI:
us-east-1:
AMI: ami-0123456789abcdef0
ca-central-1:
AMI: ami-0abcdef1234567890

Conditions:
IsProd: !Equals [!Ref Environment, prod]

Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsHostnames: true
Tags:
- Key: Name
Value: !Sub "${Environment}-VPC"

PublicSubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.1.0/24
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: !Sub "${Environment}-Public-Subnet"

InternetGateway:
Type: AWS::EC2::InternetGateway

AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway

RouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC

PublicRoute:
Type: AWS::EC2::Route
DependsOn: AttachGateway
Properties:
RouteTableId: !Ref RouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway

SubnetRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet
RouteTableId: !Ref RouteTable

SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Web Server Security Group
VpcId: !Ref VPC
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

WebServer:
Type: AWS::EC2::Instance
Properties:
InstanceType: !If [IsProd, t3.small, !Ref InstanceType]
ImageId: !FindInMap [RegionAMI, !Ref "AWS::Region", AMI]
KeyName: !Ref KeyName
SubnetId: !Ref PublicSubnet
SecurityGroupIds:
- !Ref SecurityGroup
Tags:
- Key: Name
Value: !Sub "${Environment}-WebServer"
UserData:
Fn::Base64: !Sub |
#!/bin/bash
yum update -y
yum install -y httpd
systemctl start httpd
echo "<h1>Env: ${Environment}</h1>" > /var/www/html/index.html

Outputs:
VpcId:
Value: !Ref VPC
Export:
Name: !Sub "${AWS::StackName}-VpcId"

WebServerIP:
Value: !GetAtt WebServer.PublicIp
Description: IP العام للخادم

WebsiteURL:
Value: !Sub "http://${WebServer.PublicDnsName}"
Description: URL الموقع الإلكتروني

ملخص​

  • يحتوي القالب على هيكل محدد مع موارد إلزامية
  • تسمح المعلمات بالتخصيص عند النشر
  • دوال داخلية (!Ref, !GetAtt, !Sub, إلخ) للإشارة
  • شروط لإنشاء الموارد بشكل شرطي
  • تطابقات للقيم الثابتة حسب المنطقة/البيئة
  • مخرجات لتصدير القيم

القسم التالي: اختبار التحقق