Day13 CloudFormation3
Day13 CloudFormation3

Day13 CloudFormation3

内容纲要

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定义的数据中查找数据的一种函数。它接受三个参数:

  1. Map名称,这是Mappings中定义的名称。
  2. 在Map中查找的键(key)。
  3. 如果找不到键,则返回的默认值。

使用方式类似下面的例子:

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 函数时需要注意以下几点:

  1. 在使用 !FindInMap 函数时,需要先在 Mappings 段落中定义好映射关系。
  2. !FindInMap 函数需要三个参数,分别是映射名称、键值、和默认值。
  3. 映射名称和键值应该是字符串类型。
  4. !FindInMap 函数返回的结果是映射中键值对应的值。如果键值不存在,函数会返回默认值。
  5. 使用 !FindInMap 函数时需要确保键值已经在 Mappings 段落中定义过。
  6. 使用 !FindInMap 函数时需要注意大小写,映射名称和键值需要与 Mappings 段落中定义的一致。
  • Parameters: 通过 !Ref 引用参数值,可以在模板中动态指定。
  • Conditions: 通过 !Equals, !If, !And 等函数设置条件,控制资源的创建。
  • Mappings: 通过 !FindInMap 函数引用映射表中的值,可以在模板中按照不同条件使用不同的值。
  • !FindInMap: 使用时需要注意三个参数的顺序和类型,第一个参数是映射表名,第二个参数是第一层键值,第三个参数是第二层键值。
  • !Ref: 使用时需要注意引用的变量是否存在,并且类型是否正确。
  • !Sub: 使用时需要注意替换变量的格式是 ${var} 还是 $var。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注