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_IDAWS_SECRET_ACCESS_KEY 环境变量配置您的凭据,分别代表您的 AWS 访问密钥和 AWS 机密密钥。请注意,这些环境变量生效的优先级高于 AWS_SHARED_CREDENTIALS_FILEAWS_PROFILE。另外还可以搭配使用 ​​AWS_DEFAULT_REGIONAWS_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 attemptsResourceNotReady: 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.
  • 您的 KMS 密钥有问题。您将在此处看到各种 ResourceNotReady: failed waiting for successful resource state 错误消息。这里的问题有:
    • KMS 密钥无效,可能是因为输入错误
    • KMS 密钥有效但没有必要的权限(必要的密钥权限见上文)
    • KMS 密钥有效,但不在您告诉我们使用它的区域。

results matching ""

    No results matching ""