Day13 CloudFormation3
Parameters
在 CloudFormation 模板中, Parameters
是用来定义模板的参数的。这些参数可以在模板部署时由用户提供,并在模板中用来定义资源的属性或者用来作为条件判断。
举个例子, 如果你要在模板中创建一个 EC2 实例,并且实例的类型是由用户来指定的,那么你可以在模板中定义一个叫做 InstanceType
的参数,并在模板中引用这个参数来定义实例的类型。
这是一个示例,演示如何在模板中定义一个叫做 InstanceType
的参数,并在定义 EC2 实例时使用该参数:
Parameters:
InstanceType:
Type: String
Default: t2.micro
AllowedValues:
- t2.micro
- t2.small
- m3.medium
Description: Type of the EC2 instance
Resources:
MyEC2Instance:
Type: 'AWS::EC2::Instance'
Properties:
InstanceType: !Ref InstanceType
ImageId: ami-0bba69335379e
练习1
Parameters:
Qlite:
Type: String
Default: Qlite
来看看上面的这段代码。
这段代码中定义了一个名为 Qlite 的参数。这个参数是一个字符串类型,并设置了一个默认值 "Qlite".
当使用这个模板创建资源时,如果没有在命令行或者控制台中提供这个参数的值,那么会使用默认值 "Qlite"。如果用户在命令行或者控制台中提供了参数值,那么会使用用户提供的值而不是默认值。
例如,在模板中,如果我们需要将参数 Qlite
的值作为一个字符串替换到其它地方,我们可以使用 !Sub
函数来实现。
!Sub "This is my ${Qlite} stack"
这段代码中 !Sub 函数会把 ${Qlite} 参数的值替换到字符串中,如果 Qlite 参数的值是 "Qlite",那么最终的字符串就是 "This is my Qlite stack"。
我们再在上面的基础上添加几条,然后在引用他们试试。
Parameters:
Qlite:
Type: String
Default: Qlite
Dev:
Type: String
Default: Dev
MyName:
Type: String
Default: tutu
Resources:
tutuvpc:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.10.0.0/16
Tags:
- Key: Name
Value: !Sub ${Qlite}-${Dev}-${MyName}-vpc
看最后一行代码
我们使用!sub
来引用我们的参数,这样我们的标签都会变成Qlite-Dev-tutu-vpc
注意⚠️:
1.只在第一个需要被引用的值前面打 !Sub 就可以
2.在所有{}前面都要加$符号
3.大概格式为!Sub ${}-${}-${}-xxxx
4.改tag部分
Conditions
Conditions 是 CloudFormation 模板中的一个部分,用于定义一组条件,并在模板中的其他部分引用。这些条件可以用于控制资源的创建、更新和删除。
例如,当某些特定条件为 true 时,我们可能希望创建某个资源。或者,当某些特定条件为 false 时,我们可能希望删除某个资源。
Conditions 的语法如下:
Conditions:
ConditionName:
!Fn::Equals:
- !Ref some_parameter
- some_value
在上面的代码中,我们定义了一个名为 "ConditionName" 的条件,它检查某个参数是否等于某个值。 在模板中的其他部分,可以使用 !Condition 运算符来引用这个条件,例如在 Resources 或者 Outputs 中。
Resources:
MyBucket:
Type: "AWS::S3::Bucket"
Condition: CreateBucket
Properties:
BucketName: !Ref BucketName
Outputs:
BucketUrl:
Value: !Sub "http://${MyBucket}.s3.amazonaws.com"
Condition: CreateBucket
上面的代码中, 如果条件 "CreateBucket" 为 true,那么就会创建一个S3 bucket,并输出Bucket的url,如果条件为false,则不会创建S3 bucket和输出Bucket的url
通过使用 Conditions,可以更灵活地控制模板中的资源和输出,并使模板更具可重用性和可维护性。
Mappings
Mappings 是 CloudFormation 模板中的一个部分,用于定义一组映射关系,并在模板中的其他部分引用。这些映射关系可以用于根据某些特定条件来选择不同的值。
例如,我们可能希望根据某个参数的值来选择不同的 AMI ID。或者,我们可能希望根据某个参数的值来选择不同的资源配置。
Mappings 的语法如下:
Mappings:
RegionMap:
us-east-1:
AMI: ami-0ff8a91507f77f867
us-west-2:
AMI: ami-0bdb828fd58c71cb2
在上面的代码中,我们定义了一个名为 "RegionMap" 的映射,它包含了不同地区的 AMI ID。 在模板中的其他部分,可以使用 !FindInMap 运算符来引用这个映射,例如在 Resources 或者 Outputs 中。
Resources:
MyEC2Instance:
Type: "AWS::EC2::Instance"
Properties:
ImageId: !FindInMap [RegionMap, !Ref 'AWS::Region', AMI]
上面的代码中, !FindInMap 运算符会查找RegionMap这个映射表中当前Region下的AMI ID,并赋值给ImageId属性。
Mappings和Conditions综合练习
我们来看看这段代码
Mappings:
env:
id:
'318752096736': dev #自己用的账号
'000000000000': prod #可能使用的第二个账号
'111111111111': test #可能使用的第三个账号
#------------------------------------------------------------
#在YAML中,数字和字符串需要使用单引号或双引号来指定,如果不加引号可能会被解释器误认为是数字。
#如果'318752096736' : dev中不加引号就会被识别成两个变量而不是字符串。
#------------------------------------------------------------
# !FindInMap [ env, id, !Ref 'AWS::AccountId' ]
Conditions:
createNGW:
!Equals [ !FindInMap [ env, id, !Ref 'AWS::AccountId' ], prod]
#----------------------------------------------------------------------------
#AWS::AccountId是一个AWS CloudFormation内置变量,表示当前使用AWS CloudFormation模板创建资源的AWS账户#ID。你可以在模板中引用它来获取当前账户ID,并将其用于条件语句、资源属性或输出值。
#----------------------------------------------------------------------------
Resources:
NATGateway:
Type: AWS::EC2::NatGateway
Condition: createNGW
Properties:
AllocationId: !GetAtt NATGatewayEIP.AllocationId
SubnetId: !Ref oybpub1a
NATGatewayEIP:
Type: AWS::EC2::EIP
Condition: createNGW
Properties:
Domain: !Ref oybvpc
RouteNATGateway:
DependsOn: NATGateway
Type: AWS::EC2::Route
Condition: createNGW #这段代码会在符合条件createNGW的情况下创建一个NAT网关和一个公共IP,并且将其关联到私有子网的路由表上。
Properties:
RouteTableId: !Ref oybrtbpri1a
DestinationCidrBlock: '0.0.0.0/0'
NatGatewayId: !Ref NATGateway
这段代码定义了一个名为 "env" 的 Mappings。Mappings 是 CloudFormation 中的一种数据类型,它允许您在模板中存储键/值对。在这个例子中,Mappings "env" 定义了三个键/值对,分别是 "318752096736" 和 "dev"、 "000000000000" 和 "prod"、 "111111111111" 和 "test"。
Mappings是CloudFormation中的一种配置结构,用于存储可重用的键值对。在上面的代码中,它表示了一个名为"env"的映射,其中定义了一个名为"id"的键,该键关联了三个值:’318752096736′ dev ,’000000000000′ prod ,’111111111111′ test。每个值都用一个键与一个值关联。在这种情况下,键为账户ID,值为字符串,表示环境或账户类型。 这些映射可以通过使用Fn::FindInMap函数在模板的其他部分中引用。
!FindInMap是CloudFormation中用来在Mappings定义的数据中查找数据的一种函数。它接受三个参数:
- Map名称,这是Mappings中定义的名称。
- 在Map中查找的键(key)。
- 如果找不到键,则返回的默认值。
使用方式类似下面的例子:
Mappings: env: id: '318752123214' : dev #自己用的账号 '000000000000' : prod #可能使用的第二个账号 '111111111111' : test #可能使用的第三个账号 # !FindInMap [ Map名称, 键, 默认值 ] !FindInMap [ env, id, "default" ]
在上面的例子中,如果当前账号为‘318752123214’ 则返回 dev,如果为‘000000000000’ 则返回 prod, 如果为’111111111111′ 则返回 test, 如果没有找到就返回 default.
接着在Conditions 定义了一个条件判断,使用了Fn::FindInMap 函数来获取某一个Mappings中的值,其中第一个参数 env 是我们定义的Mappings,第二个参数 id 是我们要获取的键,第三个参数是当前账号ID(!Ref ‘AWS::AccountId’)。Fn::FindInMap 函数返回的值为对应的值。
随后使用 !Equals 函数将返回值与 "prod" 进行比较,如果返回值与 "prod" 相等,条件为 true,否则为 false。这句话就是判断当前账号是否为prod账号。
最后这段代码会在符合条件createNGW的情况下创建一个NAT网关和一个公共IP,并且将其关联到私有子网的路由表上。
Mappings练习2
我们来看看这段代码
Mappings:
env:
id:
'318752096736': dev #自己用的账号
'000000000000': prod #可能使用的第二个账号
'111111111111': test #可能使用的第三个账号
dev:
1a:
pub1a: 10.0.0.0/24
pri1a: 10.0.1.0/24
1c:
pub1c: 10.0.2.0/24
pri1c: 10.0.3.0/24
vpccidr:
vpc: 10.0.0.0/16
tutupub1a:
Type: AWS::EC2::Subnet
Properties:
# AssignIpv6AddressOnCreation: false
AvailabilityZone: ap-northeast-1a
# AvailabilityZoneId: "String"
CidrBlock: !FindInMap [ !FindInMap [ env, id, !Ref 'AWS::AccountId' ], 1a, pri1a ]
Tags:
- Key: Name
Value: !Sub ${Qlite}-${Dev}-${Oyb}-subnet-pub1a
VpcId: !Ref tutuvpc # Required
这段代码中的Mappings配置了两个映射,分别为env和dev。env映射中定义了三个可能使用的账号ID,分别为’318752096736′: dev、’000000000000′: prod和’111111111111′: test,对应的是dev、prod和test三种环境。
dev映射中定义了三种可能的子网类型,分别为1a、1c和vpccidr。其中1a和1c中分别定义了两种子网类型,分别为pub1a和pri1a,以及pub1c和pri1c。vpccidr中定义了一种类型,vpc。
!FindInMap [ !FindInMap [ env, id, !Ref ‘AWS::AccountId’ ], 1a, pub1a ]这句话的意思是在env映射中通过当前账号ID(!Ref ‘AWS::AccountId’)找到对应的环境,在dev映射中找到对应的1a类型,并取出对应的pub1a的值。这个值就是10.0.0.0/24
换种说法:
这段代码中,Mappings 块中有一个 env 对象,它包含一个 id 属性,定义了三个账号 ID(dev,prod,test)。在 dev 对象中,定义了三个子网的 CIDR 块,分别是 1a,1c 和 vpccidr。
最后一行 !FindInMap [ !FindInMap [ env, id, !Ref ‘AWS::AccountId’ ], 1a, pub1a ] 是在使用这个函数来查找这个账号 ID 对应的 CIDR 块, 首先在 env 对象中查找 id 属性和当前 AWS 账号 ID 匹配的值,然后在 dev 对象中查找 1a 属性对应的值,最后在 1a 对象中查找 pub1a 属性对应的值。
这个函数返回的结果是 10.0.0.0/24 。
总结
注意点⚠️:
使用 !FindInMap 函数时需要注意以下几点:
- 在使用 !FindInMap 函数时,需要先在 Mappings 段落中定义好映射关系。
- !FindInMap 函数需要三个参数,分别是映射名称、键值、和默认值。
- 映射名称和键值应该是字符串类型。
- !FindInMap 函数返回的结果是映射中键值对应的值。如果键值不存在,函数会返回默认值。
- 使用 !FindInMap 函数时需要确保键值已经在 Mappings 段落中定义过。
- 使用 !FindInMap 函数时需要注意大小写,映射名称和键值需要与 Mappings 段落中定义的一致。
- Parameters: 通过 !Ref 引用参数值,可以在模板中动态指定。
- Conditions: 通过 !Equals, !If, !And 等函数设置条件,控制资源的创建。
- Mappings: 通过 !FindInMap 函数引用映射表中的值,可以在模板中按照不同条件使用不同的值。
- !FindInMap: 使用时需要注意三个参数的顺序和类型,第一个参数是映射表名,第二个参数是第一层键值,第三个参数是第二层键值。
- !Ref: 使用时需要注意引用的变量是否存在,并且类型是否正确。
- !Sub: 使用时需要注意替换变量的格式是 ${var} 还是 $var。