Amazon AMI 构建器
Amazon 插件能够创建 Amazon AMI。为实现这一点,该插件带有多个构建器,具体取决于您要用于构建 AMI 的策略。
目前本书只翻译其中一种构建器:
amazon-ebs
- 通过启动源 AMI 并在配置后将其重新打包到新的 AMI 中来创建基于 EBS 的 AMI。如果有疑问,请使用这个最容易上手的构建器。
如何使用 amazone
插件
从 Packer v1.7.0 开始,可以在 Packer 配置中声明以下代码以安装此插件。然后,运行 packer init
:
packer {
required_plugins {
amazon = {
version = ">= 1.1.1"
source = "github.com/hashicorp/amazon"
}
}
}
认证
AWS Provider 提供了一种灵活的方式来提供身份验证凭据。按此优先级顺序支持以下方法:
- 静态凭证
- 环境变量
- 共享凭证文件
- EC2 角色
静态凭证
静态凭证设置 access_key
以及 secret_key
,看起来像这样:
source "amazon-ebs" "basic-example" {
access_key = "AKIAIOSFODNN7EXAMPLE"
secret_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
region = "us-east-1"
}
如果愿意,您还可以使用 assume_role
配置选项 assume 一个角色。您仍然必须拥有上面解释的有效凭证资源之一,并且您的用户必须有权承担相关角色。这是一种使用的账号所拥有的权限更严格的权限子集运行 Packer 的方法。
AssumeRoleConfig 允许用户配置在执行 Packer 时 assume 的角色。
使用示例:
source "amazon-ebs" "example" {
assume_role {
role_arn = "arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME"
session_name = "SESSION_NAME"
external_id = "EXTERNAL_ID"
}
}
role_arn
(string)- 要 assume 的 IAM 角色的 Amazon 资源名称 (ARN)。duration_seconds
(int) - 限制 assume 角色的会话持续时间的秒数。external_id
(string) - assume 角色时使用的外部 ID。如果忽略,则不会将外部 ID 传递给 AssumeRole 调用。policy
(string) - IAM 策略 JSON,进一步限制所 assume 的 IAM 角色的权限。policy_arns
([]string) - IAM 策略的 Amazon 资源名称 (ARN) 集,进一步限制 IAM 角色的权限session_name
(string) - assume 角色时使用的会话名称。tags
(map[string]string) - assume 角色会话标签的映射。transitive_tag_keys
([]string) - 一组假定角色会话标签键,用以传递给所有后续的会话。
环境变量
您可以通过 AWS_ACCESS_KEY_ID
和 AWS_SECRET_ACCESS_KEY
环境变量配置您的凭据,分别代表您的 AWS 访问密钥和 AWS 机密密钥。请注意,这些环境变量生效的优先级高于 AWS_SHARED_CREDENTIALS_FILE
和 AWS_PROFILE
。另外还可以搭配使用 AWS_DEFAULT_REGION
和 AWS_SESSION_TOKEN
环境变量:
$ export AWS_ACCESS_KEY_ID="anaccesskey"
$ export AWS_SECRET_ACCESS_KEY="asecretkey"
$ export AWS_DEFAULT_REGION="us-west-2"
$ packer build template.pkr.hcl
共享凭证文件
您可以使用 AWS 凭证文件来指定您的凭证。在 Linux 和 OS X 上,默认位置是 $HOME/.aws/credentials
,对于 Windows 用户,默认位置是 %USERPROFILE%.aws\credentials
。如果我们未能在代码或者环境变量中检测到凭证,Amazon 插件将检查该位置。您可以选择通过使用 AWS_SHARED_CREDENTIALS_FILE
环境变量来指定指定不同的位置。
凭据文件的格式如下
[default]
aws_access_key_id=<your access key id>
aws_secret_access_key=<your secret access key>
您还可以通过设置 profile
参数或设置 AWS_PROFILE
环境变量来配置要使用的配置文件:
source "amazon-ebs" "basic-example" {
profile = "customprofile"
region = "us-east-1"
}
任务或实例的 IAM 角色
最后,插件将使用任务或实例的 IAM 角色提供的凭证(如果有的话)。
在 EC2 中运行时,这是最好的方法,因为这样可以避免对凭证进行硬编码。相反,这些凭证是由插件即时生成的租约,这减少了泄漏的机会。
以下策略文档提供了 Amazon 插件运行所需的最小设置权限:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:AttachVolume",
"ec2:AuthorizeSecurityGroupIngress",
"ec2:CopyImage",
"ec2:CreateImage",
"ec2:CreateKeypair",
"ec2:CreateSecurityGroup",
"ec2:CreateSnapshot",
"ec2:CreateTags",
"ec2:CreateVolume",
"ec2:DeleteKeyPair",
"ec2:DeleteSecurityGroup",
"ec2:DeleteSnapshot",
"ec2:DeleteVolume",
"ec2:DeregisterImage",
"ec2:DescribeImageAttribute",
"ec2:DescribeImages",
"ec2:DescribeInstances",
"ec2:DescribeInstanceStatus",
"ec2:DescribeRegions",
"ec2:DescribeSecurityGroups",
"ec2:DescribeSnapshots",
"ec2:DescribeSubnets",
"ec2:DescribeTags",
"ec2:DescribeVolumes",
"ec2:DetachVolume",
"ec2:GetPasswordData",
"ec2:ModifyImageAttribute",
"ec2:ModifyInstanceAttribute",
"ec2:ModifySnapshotAttribute",
"ec2:RegisterImage",
"ec2:RunInstances",
"ec2:StopInstances",
"ec2:TerminateInstances"
],
"Resource": "*"
}
]
}
请注意,如果您想创建一个竞价型实例,您还必须添加:
ec2:CreateLaunchTemplate,
ec2:DeleteLaunchTemplate,
ec2:CreateFleet
如果您将 spot_price
参数设置为 auto
,您还必须添加:
ec2:DescribeSpotPriceHistory
如果您使用 vpc_filter
选项,您还必须添加:
ec2:DescribeVpcs
故障排查
将 IAM 策略关联到角色上
IAM 策略可以与用户或角色相关联。如果您的插件运行时使用了 IAM 角色,您可能会遇到如下错误:
==> amazon-ebs: Error launching source instance: You are not authorized to perform this operation.
您可以在 Amazon 安全博客上详细了解为什么会发生这种情况。下面的示例策略可能有助于插件使用 IAM 角色。请注意,此示例提供的不仅仅是 Amazon 插件工作所需的最小权限集,但具体情况将取决于您的用例。
{
"Sid": "PackerIAMPassRole",
"Effect": "Allow",
"Action": ["iam:PassRole", "iam:GetInstanceProfile"],
"Resource": ["*"]
}
如果使用具有竞价实例/竞价定价的现有实例配置文件,则还需要 iam:CreateServiceLinkedRole
权限:
{
"Sid": "PackerIAMPassRole",
"Effect": "Allow",
"Action": ["iam:PassRole", "iam:GetInstanceProfile", "iam:CreateServiceLinkedRole"],
"Resource": ["*"]
}
如果您创建临时实例配置文件,您将需要赋予以下 IAM 策略:
{
"Sid": "PackerIAMCreateRole",
"Effect": "Allow",
"Action": [
"iam:PassRole",
"iam:CreateInstanceProfile",
"iam:DeleteInstanceProfile",
"iam:GetRole",
"iam:GetInstanceProfile",
"iam:DeleteRolePolicy",
"iam:RemoveRoleFromInstanceProfile",
"iam:CreateRole",
"iam:DeleteRole",
"iam:PutRolePolicy",
"iam:AddRoleToInstanceProfile"
],
"Resource": "*"
}
如果您使用 KMS 密钥进行加密,您的密钥至少需要以下策略:
{
"Sid": "Allow use of the key",
"Effect": "Allow",
"Action": ["kms:ReEncrypt*", "kms:GenerateDataKey*"],
"Resource": "*"
}
如果您使用的密钥由与您用于运行 Packer 构建的帐户不同的帐户提供,您的密钥还需要:
("kms:CreateGrant", "kms:DescribeKey")
检查系统时间是否准确
Amazon 使用当前时间作为请求签名过程的一部分。如果您的系统时钟与当前时间偏差太大,您的请求可能会失败。这时您可能会看到如下错误:
==> amazon-ebs: Error querying AMI: AuthFailure: AWS was not able to validate the provided access credentials
如果您怀疑系统的日期有误,可以将其与 http://www.time.gov/
进行比较。在 Linux/OS X 上,您可以运行 date
命令来获取当前时间。如果您使用的是 Linux,则可以通过运行 sudo ntpd -q
尝试使用 ntp 设置时间。
ResourceNotReady 错误
此错误通常显示为 ResourceNotReady: exceeded wait attempts
或 ResourceNotReady: failed waiting for successful resource state
。
通常是在镜像复制/加密期间从 AWS 的 API 返回此令人费解的错误,原因可能有多种。错误的可能原因包括:
- 等待时间不够长。在这里您这样的错误消息
exceeded wait attempts
:我们使用 AWS SDK 内置的等待方法来等待运行时间较长的任务完成。这些等待方法默认的延迟最大重试次数并不总是对当前操作适用。
如果您发现您受到速率限制或已超过您的最大等待重试次数,您可以通过设置以下 Packer 环境变量来覆盖默认值(请注意,这些将适用于我们必须等待的所有 AWS 任务):
AWS_MAX_ATTEMPTS
- 这是重新发送状态更新请求的次数。除了我们知道可能需要很长时间的任务外,默认重试 40 次。AWS_POLL_DELAY_SECONDS
- 状态更新请求之间等待的秒数。通常默认为 2 或 5 秒,具体取决于任务。
或者,您可以在 Packer 配置文件的 source
部分配置这些设置,例如:
aws_polling {
delay_seconds = 40
max_attempts = 5
}
- 您使用的是在构建期间过期的短生命周期凭据。如果这是问题所在,您可能在Packer 输出中看到
RequestExpired: Request has expired.
:- 如果您使用的是 STS 凭据,请确保它们仅在构建完成后过期
- 如果您链接角色,请确保您的构建不会持续超过一个小时,因为当您链接角色时,您的凭证将持续的最长时间为一个小时:https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html
- 您的 KMS 密钥有问题。您将在此处看到各种
ResourceNotReady: failed waiting for successful resource state
错误消息。这里的问题有:- KMS 密钥无效,可能是因为输入错误
- KMS 密钥有效但没有必要的权限(必要的密钥权限见上文)
- KMS 密钥有效,但不在您告诉我们使用它的区域。