AWS::CloudFormation::Init - AWS CloudFormation

AWS::CloudFormation::Init

使用类型 AWS::CloudFormation::Init 来将 Amazon EC2 实例上的元数据置入 cfn-init 帮助程序脚本。如果您的模板调用 cfn-init 脚本,该脚本会查找来源于 AWS::CloudFormation::Init 元数据键内的资源元数据。有关 cfn-init 的详细信息,请参阅 cfn-init

cfn-init 支持 Linux 系统的所有元数据类型。在满足下面部分中说明的条件时,它还支持 Windows 的元数据类型。

有关使用 AWS::CloudFormation::Init 和 cfn-init 帮助程序脚本创建 Linux 堆栈的示例,请参阅 在 Amazon EC2 上部署应用程序。有关 Windows 堆栈示例,请参阅 引导 AWS CloudFormation Windows 堆栈

语法

配置过程分为几个部分。以下模板代码段演示如何在模板内将 cfn-init 的元数据附加到 EC2 实例资源。

元数据分成数个配置键,您可以将它们分成几个配置集。您可以在模板中调用 cfn-init 时指定配置集。如果未指定配置集,cfn-init 将查找名为 config 的单个配置键。

注意

cfn-init 帮助程序脚本将以下列顺序处理这些配置部分:packages、groups、users、sources、files、commands,然后是 services。如果您需要以不同顺序处理,请将各节分为不同的配置键,然后使用配置集指定处理这些配置键应采用的顺序。

JSON

"Resources": { "MyInstance": { "Type": "AWS::EC2::Instance", "Metadata" : { "AWS::CloudFormation::Init" : { "config" : { "packages" : { : }, "groups" : { : }, "users" : { : }, "sources" : { : }, "files" : { : }, "commands" : { : }, "services" : { : } } } }, "Properties": { : } } }

YAML

Resources: MyInstance: Type: AWS::EC2::Instance Metadata: AWS::CloudFormation::Init: config: packages: : groups: : users: : sources: : files: : commands: : services: : Properties: :
注意

以下各节包含使用类似 Unix 的 Shell 脚本语言(例如 Bash)编写的脚本示例。要改为为 PowerShell 创建脚本,请确保您熟悉 PowerShell 语言。PowerShell 语法与类似 Unix 的 Shell 不同,需要您熟悉 PowerShell 的工作方式。

配置集

如果您创建多个配置键并使 cfn-init 以特定的顺序处理这些键,则可创建一个配置集,其中包含以特定顺序排列的多个配置键。

单个配置集

以下模板代码段创建名为 ascendingdescending 的两个配置集,每个各包含 2 个配置键。

JSON

"AWS::CloudFormation::Init" : { "configSets" : { "ascending" : [ "config1" , "config2" ], "descending" : [ "config2" , "config1" ] }, "config1" : { "commands" : { "test" : { "command" : "echo \"$CFNTEST\" > test.txt", "env" : { "CFNTEST" : "I come from config1." }, "cwd" : "~" } } }, "config2" : { "commands" : { "test" : { "command" : "echo \"$CFNTEST\" > test.txt", "env" : { "CFNTEST" : "I come from config2" }, "cwd" : "~" } } } }

YAML

AWS::CloudFormation::Init: configSets: ascending: - "config1" - "config2" descending: - "config2" - "config1" config1: commands: test: command: "echo \"$CFNTEST\" > test.txt" env: CFNTEST: "I come from config1." cwd: "~" config2: commands: test: command: "echo \"$CFNTEST\" > test.txt" env: CFNTEST: "I come from config2" cwd: "~"

相关 cfn-init 调用

以下示例 cfn-init 调用引用了前述示例配置集。为明确起见,示例调用采用的是缩写形式。完整的语法请参阅 cfn-init

  • 如果 cfn-init 调用指定了 ascending 配置集:

    cfn-init -c ascending

    该脚本会首先处理 config1,然后再处理 config2,而 test.txt 文件将包含文本 I come from config2

  • 如果 cfn-init 调用指定了 descending 配置集:

    cfn-init -c descending

    该脚本会首先处理 config2,然后再处理 config1,而 test.txt 文件将包含文本 I come from config1

多个配置集

您可以创建多个配置集,并使用 cfn-init 脚本对其进行一连串调用。每个配置集都包含配置键列表或对其他配置集的引用的列表。例如,以下模板代码段可创建三个配置集。第一个配置集test1 包含一个名为 1 的配置键。第二个配置集test2 包含对 test1配置集的引用和一个名为 2 的配置键。在默认情况下,第三个配置集包含对配置集test2 的引用。

JSON

"AWS::CloudFormation::Init" : { "configSets" : { "test1" : [ "1" ], "test2" : [ { "ConfigSet" : "test1" }, "2" ], "default" : [ { "ConfigSet" : "test2" } ] }, "1" : { "commands" : { "test" : { "command" : "echo \"$MAGIC\" > test.txt", "env" : { "MAGIC" : "I come from the environment!" }, "cwd" : "~" } } }, "2" : { "commands" : { "test" : { "command" : "echo \"$MAGIC\" >> test.txt", "env" : { "MAGIC" : "I am test 2!" }, "cwd" : "~" } } } }

YAML

AWS::CloudFormation::Init: 1: commands: test: command: "echo \"$MAGIC\" > test.txt" env: MAGIC: "I come from the environment!" cwd: "~" 2: commands: test: command: "echo \"$MAGIC\" >> test.txt" env: MAGIC: "I am test 2!" cwd: "~" configSets: test1: - "1" test2: - ConfigSet: "test1" - "2" default: - ConfigSet: "test2"

相关 cfn-init 调用

以下 cfn-init 调用引用了前述模板代码段中声明的配置集。为明确起见,示例调用采用的是缩写形式。完整的语法请参阅 cfn-init

  • 如果您仅指定 test1

    cfn-init -c test1

    cfn-init 仅处理配置键 1

  • 如果您仅指定 test2

    cfn-init -c test2

    cfn-init 会首先处理配置键 1,然后再处理配置键 2

  • 如果您指定 default配置集(或根本没有配置集):

    cfn-init -c default

    如果您指定 configset test2,则将获得相同的特性。

命令

您可以使用命令键在 EC2 实例上执行命令。其执行顺序即为命令名称的字母顺序。

必需 描述

命令

必需

指定要运行的命令的数组或字符串。如果您使用了数组,则不需要对空格字符进行转义或用引号将命令参数引起来。请勿使用数组指定多个命令。

env

可选

设置该命令的环境变量。这个属性会覆盖而不是追加到现有的环境。

cwd

可选

工作目录。

测试

可选

用于确定 cfn-init 是否运行在命令键中指定的命令的测试命令。如果测试通过,则 cfn-init 将运行命令。cfn-init 脚本在命令解释器(如 Bash 或 cmd.exe)中运行测试。测试能否通过取决于解释器返回的退出代码。

对于 Linux,测试命令必须返回退出代码 0,才表示测试通过。对于 Windows,测试命令必须返回 %ERRORLEVEL% 0

ignoreErrors

可选

一个用于确定在命令键中包含的命令失败(返回非零值)时,cfn-init 是否继续运行的布尔值。如果您希望即使命令失败 cfn-init 也会继续运行,则将其设置为 true。如果您希望命令失败时 cfn-init 停止运行,则将其设置为 false。默认值为 false

waitAfterCompletion

可选

仅限于 Windows 系统。指定命令执行结束后,在该命令引起重启的情况下需要等待的时间长短 (以秒为单位)。默认值为 60 秒,而值“forever”会使 cfn-init 退出,并且仅在重启完成后继续。如果您不想等待每条命令,请将该值设置为 0

示例

以下示例代码段在 ~/test.txt 文件不存在时调用 echo 命令。

JSON

"commands" : { "test" : { "command" : "echo \"$MAGIC\" > test.txt", "env" : { "MAGIC" : "I come from the environment!" }, "cwd" : "~", "test" : "test ! -e ~/test.txt", "ignoreErrors" : "false" }, "test2" : { "command" : "echo \"$MAGIC2\" > test2.txt", "env" : { "MAGIC2" : "I come from the environment!" }, "cwd" : "~", "test" : "test ! -e ~/test2.txt", "ignoreErrors" : "false" } }

YAML

commands: test: command: "echo \"$MAGIC\" > test.txt" env: MAGIC: "I come from the environment!" cwd: "~" test: "test ! -e ~/test.txt" ignoreErrors: "false" test2: command: "echo \"$MAGIC2\" > test2.txt" env: MAGIC2: "I come from the environment!" cwd: "~" test: "test ! -e ~/test2.txt" ignoreErrors: "false"

文件

您可以使用 files 密钥在 EC2 实例上创建文件。其内容既可以来自模板,也可以从 URL 抽取。这些文件会按词典顺序写入磁盘。下表列出了支持的键。

描述

content

字符串或格式正确的 JSON 对象。如果您将 JSON 对象用作内容,则 JSON 将被写到磁盘上的文件中。在 JSON 对象写入磁盘之前,对所有内置函数(例如 Fn::GetAttRef)进行评估。在创建符号链接时,将符号链接目标指定为内容。

注意

如果创建符号链接,帮助程序脚本会修改目标文件的权限。目前,您无法在不修改目标文件的权限的情况下创建符号链接。

用于加载文件的 URL。不能使用内容键指定该选项。

encoding

编码格式。仅限在内容为字符串时使用。如果使用的是源,则不会应用编码。

有效值:plain | base64

拥有这个文件的组的名称。在 Windows 系统中不受支持。

owner

拥有这个文件的用户的名称。在 Windows 系统中不受支持。

mode

是一个六位数的八进制值,表示这个文件的模式。在 Windows 系统中不受支持。将前三位数用于符号链接,将后三位数用于设置权限。要创建符号链接,请指定 120xxx,其中 xxx 定义目标文件的权限。要指定文件的权限,请使用最后三位,例如 000644

身份验证

要使用的身份验证方法的名称。这会覆盖任何默认的身份验证。您可以使用该属性选择通过 AWS::CloudFormation::Authentication 资源定义的身份验证方法。

context

指定需要作为 Mustache 模板处理的文件的上下文。若要使用此键,必须已安装 aws-cfn-bootstrap 1.3-11 或更高版本以及 pystache

示例

以下示例代码段将在更大范围的安装中创建一个名为 setup.mysql 的文件。

JSON

"files" : { "/tmp/setup.mysql" : { "content" : { "Fn::Join" : ["", [ "CREATE DATABASE ", { "Ref" : "DBName" }, ";\n", "CREATE USER '", { "Ref" : "DBUsername" }, "'@'localhost' IDENTIFIED BY '", { "Ref" : "DBPassword" }, "';\n", "GRANT ALL ON ", { "Ref" : "DBName" }, ".* TO '", { "Ref" : "DBUsername" }, "'@'localhost';\n", "FLUSH PRIVILEGES;\n" ]]}, "mode" : "000644", "owner" : "root", "group" : "root" } }

YAML

files: /tmp/setup.mysql: content: !Sub | CREATE DATABASE ${DBName}; CREATE USER '${DBUsername}'@'localhost' IDENTIFIED BY '${DBPassword}'; GRANT ALL ON ${DBName}.* TO '${DBUsername}'@'localhost'; FLUSH PRIVILEGES; mode: "000644" owner: "root" group: "root"

完整的模板可通过以下网址获取:https://s3.amazonaws.com/cloudformation-templates-us-east-1/Drupal_Single_Instance.template

下面的示例代码段创建指向现有文件 /tmp/myfile2.txt 的符号链接 /tmp/myfile1.txt。目标文件 /tmp/myfile1.txt 的权限由模式值 644 定义。

JSON

"files" : { "/tmp/myfile2.txt" : { "content" : "/tmp/myfile1.txt", "mode" : "120644" } }

YAML

files: /tmp/myfile2.txt: content: "/tmp/myfile1.txt" mode: "120644"

Mustache 模板主要用于创建配置文件。例如,您可以将配置文件存储在一个 S3 存储桶中,并从模板插入 Refs 和 GetAtts,而不是使用 Fn::Join。以下示例片段会将 Content for test9 输出到 /tmp/test9.txt

JSON

"files" : { "/tmp/test9.txt" : { "content" : "Content for {{name}}", "context" : { "name" : "test9" } } }

YAML

files: /tmp/test9.txt: content: "Content for {{name}}" context: name: "test9"

在使用 Mustache 模板时,请注意以下几点:

  • 必须存在用于要处理的文件的上下文键。

  • 上下文键必须是键值映射,但可以嵌套。

  • 您可以使用内容键来处理含有内联内容的文件,并使用源键来处理远程文件。

  • Mustache 支持取决于 pystache 版本。版本 0.5.2 支持 Mustache 1.1.2 规范

您可以使用组键创建 Linux/UNIX 组,并分配组 ID。该组键在 Windows 系统中不受支持。

要创建组,请添加新的密钥值对,将新的组名映射到可选组 ID。组键可以包含一个或多个组名。下表列出了可用的密钥。

描述

gid

组 ID 编号。

如果指定了组 ID,且存在该名称的组,那么创建组将失败。如果其他组已使用指定的 ID,则操作系统可能会拒绝创建该组。

例如:{ "gid" : "23" }

示例代码段

以下代码段指定两个组,其中一个名为 groupOne 但没有分配组 ID,另一个组名为 groupTwo,指定的相应组 ID 值为 45

JSON

"groups" : { "groupOne" : {}, "groupTwo" : { "gid" : "45" } }

YAML

groups: groupOne: {} groupTwo: gid: "45"

软件包

您可以使用包键下载和安装各种预包装的应用程序和组件。在 Windows 系统上,软件包键仅支持 MSI 安装程序。

支持的软件包格式

cfn-init 脚本目前支持以下软件包格式:apt、msi、python、rpm、rubygems、yum 和 Zypper。软件包的处理顺序如下:先是 rpm、yum/apt/zypper,然后是 rubygems 和 python。rubygems 和 python 之间没有处理顺序,且不保证以任何顺序安装每个包管理器内的包。

指定版本

在每个包管理器内,会使用包名和一系列版本对每个包进行指定。版本可以是字符串、一系列版本、空字符串或者空列表。空字符串或者空列表表示您需要最新的版本。对于 rpm 管理器,版本是以磁盘或 URL 上的文件的路径的方式指定的。

如果指定了软件包版本,cfn-init 会尝试安装该版本,即使实例上已经安装了更高的软件包版本。一些包管理器支持多个版本,但其他的包管理器可能不支持。有关更多信息,请查看相关的包管理器文档。如果您不指定版本且已安装了某版本的软件包,则 cfn-init 脚本将不安装新版本,因为将假定您要保留并使用现有版本。

示例代码段

RPM、yum、Rubygems 和 Zypper

下面的代码段为 rpm 指定版本 URL,从 yum 和 Zypper 请求最新版本并从 rubygems 请求 chef 的版本 0.10.2:

JSON
"rpm" : { "epel" : "http://download.fedoraproject.org/pub/epel/5/i386/epel-release-5-4.noarch.rpm" }, "yum" : { "httpd" : [], "php" : [], "wordpress" : [] }, "rubygems" : { "chef" : [ "0.10.2" ] }, "zypper" : { "git" : [] }
YAML
rpm: epel: "http://download.fedoraproject.org/pub/epel/5/i386/epel-release-5-4.noarch.rpm" yum: httpd: [] php: [] wordpress: [] rubygems: chef: - "0.10.2" zypper: git: []

MSI 包

下面的代码段为 MSI 包指定 URL:

JSON
"msi" : { "awscli" : "https://s3.amazonaws.com/aws-cli/AWSCLI64.msi" }
YAML
msi: awscli: "https://s3.amazonaws.com/aws-cli/AWSCLI64.msi"

服务

您可以使用此服务键来定义实例启动后应启用或禁用哪些服务。在 Linux 系统上,将通过使用 sysvinit 或 systemd 来支持此键。在 Windows 系统上,将通过使用 Windows 服务管理器来支持此键。

您还可以借助服务键来指定源、软件包和文件之间的依赖关系,从而确保在因安装的文件导致重启时,cfn-init 会完成服务重启。例如,如果您下载 Apache HTTP Server 软件包,则在堆栈创建过程中,软件包安装将自动启动 Apache HTTP Server。然而,如果 Apache HTTP Server 配置在堆栈创建过程的后期被更新,则要等到重启 Apache 服务器之后,更新才会生效。您可以使用服务键来确保 Apache HTTP 服务启动。

下表列出了支持的键。

描述

ensureRunning

设置为 true 以确保该服务在 cfn-init 完成后运行。

设置为 false 可确保 cfn-init 完成后服务不再运行。

忽略该键,将不更改服务状态。

已启用

设置为 true 可确保启动时自动启动服务。

设置为 false 可确保启动时不会自动启动服务。

忽略该键,将不更改这个属性。

文件

一系列文件。如果 cfn-init 直接通过文件块更改其中一个文件,则该服务将重启。

来源

一系列目录。如果 cfn-init 将存档扩展到其中的一个目录,则该服务将重启。

软件包

软件包管理器映射至软件包名称列表。如果 cfn-init 安装或更新其中一个软件包,则该服务将重启。

命令

一系列命令名称。如果 cfn-init 运行指定的命令,则该服务将重启。

示例

Linux

下面的 Linux 代码段配置服务如下:

  • 如果 cfn-init 修改了 /etc/nginx/nginx.conf/var/www/html,则 nginx 服务会重启。

  • 如果 cfn-init 使用 yum 安装或更新 php 或 spawn-fcgi,则 php-fastcgi 服务将会重启。

  • sendmail 服务将使用 systemd 停止和禁用。

JSON
"services" : { "sysvinit" : { "nginx" : { "enabled" : "true", "ensureRunning" : "true", "files" : ["/etc/nginx/nginx.conf"], "sources" : ["/var/www/html"] }, "php-fastcgi" : { "enabled" : "true", "ensureRunning" : "true", "packages" : { "yum" : ["php", "spawn-fcgi"] } } }, "systemd": { "sendmail" : { "enabled" : "false", "ensureRunning" : "false" } } }
YAML
services: sysvinit: nginx: enabled: "true" ensureRunning: "true" files: - "/etc/nginx/nginx.conf" sources: - "/var/www/html" php-fastcgi: enabled: "true" ensureRunning: "true" packages: yum: - "php" - "spawn-fcgi" systemd: sendmail: enabled: "false" ensureRunning: "false"

要将 systemd 与服务一起使用,该服务必须配置一个 systemd 单元文件。以下单元文件允许 systemd 启动和停止多用户服务目标中的 cfn-hup 进程守护程序:

[Unit] Description=cfn-hup daemon [Service] ExecStart=/usr/bin/cfn-hup -v PIDFile=/var/run/cfn-hup.pid [Install] WantedBy=multi-user.target

此配置假设 cfn-hup 安装在 /usr/bin 目录下。但是,安装 cfn-hup 的实际位置可能因平台而不同。您可以通过在 /etc/systemd/system/cfn-hup.service.d/override.conf 中创建覆盖文件来覆盖此配置,如下所示:

# In this example, cfn-hup executable is available under /usr/local/bin [Service] ExecStart= ExecStart=/usr/local/bin/cfn-hup -v

Windows

下面的 Windows 代码段启动 cfn-hup 服务,将其设置为自动,并在 cfn-init 修改指定配置文件的情况下重新启动该服务:

JSON
"services" : { "windows" : { "cfn-hup" : { "enabled" : "true", "ensureRunning" : "true", "files" : ["c:\\cfn\\cfn-hup.conf", "c:\\cfn\\hooks.d\\cfn-auto-reloader.conf"] } } }
YAML
services: windows: cfn-hup: enabled: "true" ensureRunning: "true" files: - "c:\\cfn\\cfn-hup.conf" - "c:\\cfn\\hooks.d\\cfn-auto-reloader.conf"

您可以使用该资源键来下载存档文件并在 EC2 实例上的目标目录中取出文件。此键在 Linux 和 Windows 系统中完全受支持。

支持的格式

支持的格式为:

  • tar

  • tar+gzip

  • tar+bz2

  • zip

示例

GitHub

如果您将 GitHub 用作源控制系统,则可以使用 cfn-init 和源打包机制来提取特定的应用程序版本。GitHub 允许您通过 URL 从特定版本创建 .zip 或 .tar,如下所示:

https://github.com/<your directory>/(zipball|tarball)/<version>

例如,下面的代码段会将版本 main 作为一个 .tar 文件拉取。

JSON
"sources" : { "/etc/puppet" : "https://github.com/user1/cfn-demo/tarball/main" }
YAML
sources: /etc/puppet: "https://github.com/user1/cfn-demo/tarball/main"

S3Bucket

以下示例从 S3 桶下载一个 tarball 并将其解压到 /etc/myapp

注意

您可以对来源使用身份验证凭证,但不能将身份验证键放在源数据块中。相反,您可以将存储桶密钥包含在 S3AccessCreds 数据块中。有关 Amazon S3 身份验证凭证的更多信息,请参阅 AWS::CloudFormation::Authentication

有关示例,请参阅 https://s3.amazonaws.com/cloudformation-templates-us-east-1/S3Bucket_SourceAuth.template

JSON
"sources" : { "/etc/myapp" : "https://s3.amazonaws.com/amzn-s3-demo-bucket/myapp.tar.gz" }
YAML
sources: /etc/myapp: "https://s3.amazonaws.com/amzn-s3-demo-bucket/myapp.tar.gz"

用户

您可以使用用户键在 EC2 实例上创建 Linux/UNIX 用户。该用户键在 Windows 系统中不受支持。

下表列出了支持的键。

描述

uid

用户 ID。如果用户名还有另一个用户 ID,那么此创建过程会失败。如果该用户 ID 已分配给现有用户,则操作系统可能会拒绝创建请求。

groups

一系列组名。该用户将被添加到列表的每个组中。

homeDir

用户的主目录。

示例

创建的用户属于非交互式系统用户,带有 /sbin/nologin Shell。这是特意设计的,无法修改。

JSON

"users" : { "myUser" : { "groups" : ["groupOne", "groupTwo"], "uid" : "50", "homeDir" : "/tmp" } }

YAML

users: myUser: groups: - "groupOne" - "groupTwo" uid: "50" homeDir: "/tmp"