

# 使用实例元数据管理 EC2 实例
<a name="ec2-instance-metadata"></a>

*实例元数据* 是有关您的实例的数据，可以用来配置或管理正在运行的实例。实例元数据包括以下内容：

**实例元数据属性**  
实例元数据属性分为[几类](#instancedata-data-categories)，例如，主机名、事件和安全组。

**动态数据**  
动态数据是实例启动时生成的元数据，如实例身份文件。有关更多信息，请参阅 [动态数据类别](#dynamic-data-categories)。

**用户数据**  
您也可以使用实例元数据访问您启动实例时指定的*用户数据*。例如，您可以指定参数以配置实例，或者包含简单的脚本。您还可以构建通用 AMI，并使用用户数据修改启动时提供的配置文件。例如，如果您为各种小型企业运行 Web 服务器，则这些企业可以全部使用相同的通用 AMI，并在启动时从您在用户数据中指定的 Amazon S3 存储桶中检索其内容。要随时添加新客户，请为客户创建一个存储桶，添加其内容，并使用在用户数据中为您的代码提供的唯一存储桶名称启动 AMI。如果使用同一个 `RunInstances` 调用启动多个实例，则用户数据可供该预留中的所有实例使用。属于同一保留的每个实例都具有唯一的 `ami-launch-index` 编号，这允许您编写代码控制实例的行为。例如，第一台主机可能会选择将自己作为集群中的原始节点。有关详细的 AMI 启动示例，请参阅。[识别在单个请求中启动的每个实例](AMI-launch-index-examples.md)

**重要**  
虽然您只能从实例本身中访问实例元数据和用户数据，但并未使用身份验证或加密方法对数据进行保护。任何可以直接访问实例的人以及可能在实例上运行的任何软件都可以查看其元数据。因此，您不应将敏感数据（例如密码或长期保存的加密密钥）存储为用户数据。

**Topics**
+ [

## 实例元数据类别
](#instancedata-data-categories)
+ [

## 动态数据类别
](#dynamic-data-categories)
+ [

# 访问 EC2 实例的实例元数据
](instancedata-data-retrieval.md)
+ [

# 配置实例元数据服务选项
](configuring-instance-metadata-options.md)
+ [

# 在启动包含用户数据输入的 EC2 实例时运行命令
](user-data.md)
+ [

# 识别在单个请求中启动的每个实例
](AMI-launch-index-examples.md)

## 实例元数据类别
<a name="instancedata-data-categories"></a>

实例元数据属性分为几类。要检索实例元数据属性，请在请求中指定类别，然后响应中会返回元数据。

有新类别发布时，系统会使用新版本号创建新的实例元数据构建。在下表中，**Version when category was released**（类别发布时的版本）列指定实例元数据类别发布时的构建版本。为避免每次 Amazon EC2 发布新的实例元数据构建时都必须更新您的代码，请在元数据请求中使用 `latest`，而不是版本号。有关更多信息，请参阅 [获取实例元数据的可用版本](configuring-instance-metadata-service.md#instance-metadata-ex-1)。

当 Amazon EC2 发布新的实例元数据类别时，新类别的实例元数据可能不适用于现有实例。对于[基于 Nitro 的实例](instance-types.md#instance-hypervisor-type)，只能检索启动时可用类别的实例元数据。对于具有 Xen 虚拟机管理程序的实例，可以[停止然后启动](Stop_Start.md)实例以更新可用于实例的类别。

下表列举了实例元数据的类别。一些类别名称包括实例独有的数据的占位符。例如，*mac* 表示网络接口的 MAC 地址。在检索实例元数据时，您必须使用实际值替换占位符。


| 类别 | 说明 | 类别发布时的版本 | 
| --- | --- | --- | 
| ami-id  | 用于启动实例的 AMI ID。 | 1.0 | 
| ami-launch-index  | 如果使用同一个 RunInstances 调用启动多个实例，此值将指明各个实例的启动顺序。第一个启动的实例的值是 0。如果使用自动扩缩或 EC2 实例集启动实例，此值将始终为 0。 | 1.0 | 
| ami-manifest-path  | 指向 Amazon S3 中的 AMI 清单文件的路径。如果您使用 Amazon EBS-backed AMI 来启动实例，则返回的结果为 unknown。 | 1.0 | 
| ancestor-ami-ids  | 为创建此 AMI 而重新绑定的任何实例的 AMI ID。仅当 AMI 清单文件包含一个 ancestor-amis 密钥时，此值才存在。 | 2007-10-10 | 
| autoscaling/target-lifecycle-state |  显示 Auto Scaling 实例正在转换到的目标 Auto Scaling 生命周期状态的值。当实例在 2022 年 3 月 10 日之后转换到目标生命周期状态之一时显示。可能的值：`Detached` \$1 `InService` \$1 `Standby` \$1 `Terminated` \$1 `Warmed:Hibernated` \$1 `Warmed:Running` \$1 `Warmed:Stopped` \$1 `Warmed:Terminated`。有关更多信息，请参阅《*Amazon EC2 Auto Scaling 用户指南*》中的[通过实例元数据检索目标生命周期状态](https://docs.aws.amazon.com/autoscaling/ec2/userguide/retrieving-target-lifecycle-state-through-imds.html)。  | 2021-07-15 | 
| block-device-mapping/ami | 包含根/启动文件系统的虚拟设备。 | 2007-12-15 | 
| block-device-mapping/ebs否  | 与任何 Amazon EBS 卷关联的虚拟设备。仅当 Amazon EBS 卷在启动时存在或者在上一次启动该实例时存在时，这些卷才在元数据中可用。N 表示 Amazon EBS 卷的索引（例如 ebs1 或 ebs2）。 | 2007-12-15 | 
| block-device-mapping/ephemeral否  | 任何非 NVMe 实例存储卷的虚拟设备。N 表示每个卷的索引。块储存设备映射中的实例存储卷数可能与实例的实际实例存储卷数不匹配。实例类型将决定对实例可用的实例存储卷的数量。如果块储存设备映射中的实例存储卷数超过了对实例可用的实例存储卷数，则其他实例存储卷将被忽略。 | 2007-12-15 | 
| block-device-mapping/root  | 与根设备关联的虚拟设备或分区或虚拟设备上的分区，其中根（/ 或 C:）文件系统与给定实例相关联。 | 2007-12-15 | 
| block-device-mapping/swap  | 与 swap 关联的虚拟设备。并不总是存在。 | 2007-12-15 | 
| events/maintenance/history | 如果实例存在已完成或已取消的维护事件，则包含一个 JSON 字符串，其中包含有关事件的信息。 | 2018-08-17 | 
| events/maintenance/scheduled | 如果实例存在活动的维护事件，则包含一个 JSON 字符串，其中包含有关事件的信息。有关更多信息，请参阅[查看会影响 Amazon EC2 实例的计划事件](viewing_scheduled_events.md)。 | 2018-08-17 | 
| events/recommendations/rebalance | 为实例发出 EC2 实例再平衡建议通知的大致时间 (UTC)。下面是此类别的元数据示例：\$1"noticeTime": "2020-11-05T08:22:00Z"\$1。此类别仅在发出通知后可用。有关更多信息，请参阅 [EC2 实例再平衡建议](rebalance-recommendations.md)。 | 2020-10-27 | 
| hostname | 如果 EC2 实例使用的是基于 IP 的命名 (IPBN)，则此为实例的私有 IPv4 DNS 主机名。如果 EC2 实例使用的是基于资源的命名 (RBN)，则此为 RBN。在存在多个网络接口的情况下，其指的是 eth0 设备 (设备号为 0 的设备)。有关 IPBN 和 RBN 的更多信息，请参阅 [EC2 实例主机名和域](ec2-instance-naming.md)。 | 1.0 | 
|  iam/info  | 如果存在与实例关联的 IAM 角色，则包含有关实例配置文件上次更新时间的信息 (包括实例的 LastUpdated 日期、InstanceProfileArn 和 InstanceProfileId)。如果没有，则不显示。 | 2012-01-12 | 
|  iam/security-credentials/role-name  | 如果存在与实例关联的 IAM 角色，则 role-name 为角色的名称，并且 role-name 包含与角色关联的临时安全凭证 (有关更多信息，请参阅 [从实例元数据中检索安全凭证](instance-metadata-security-credentials.md))。如果没有，则不显示。 | 2012-01-12 | 
| identity-credentials/ec2/info | identity-credentials/ec2/security-credentials/ec2-instance 中凭证的相关信息。 | 2018-05-23 | 
| identity-credentials/ec2/security-credentials/ec2-instance | 允许实例软件向 AWS 确认自身身份，以支持 EC2 Instance Connect 及 AWS Systems Manager 默认主机管理配置等功能的实例身份角色凭证。这些凭证并未附加策略，因此除了将实例标识为 AWS 功能外，它们没有其他AWS API 权限。有关更多信息，请参阅 [Amazon EC2 实例的实例身份角色](iam-roles-for-amazon-ec2.md#ec2-instance-identity-roles)。 | 2018-05-23 | 
| instance-action | 通知实例在准备打包时重新启动。有效值：none \$1 shutdown \$1 bundle-pending。 | 2008-09-01 | 
| instance-id | 此实例的 ID。 | 1.0 | 
| instance-life-cycle | 此实例的采购选项。有关更多信息，请参阅[Amazon EC2 账单和购买选项](instance-purchasing-options.md)。 | 2019-10-01 | 
| instance-type  | 实例的类型。有关更多信息，请参阅[Amazon EC2 实例类型](instance-types.md)。 | 2007-08-29 | 
| ipv6  | 实例的 IPv6 地址。在存在多个网络接口的情况下，其指的是 eth0 设备（设备号为 0 的设备）的网络接口和第一个分配的 IPv6 地址。若网络接口 [0] 上不存在 IPv6 地址，则不会设置此项目且会导致 HTTP 404 响应。 | 2021-01-03 | 
|  kernel-id  | 此实例启动的内核的 ID，如果适用的话。 | 2008-02-01 | 
|  local-hostname  | 在存在多个网络接口的情况下，其指的是 eth0 设备 (设备号为 0 的设备)。如果 EC2 实例使用的是基于 IP 的命名 (IPBN)，则此为实例的私有 IPv4 DNS 主机名。如果 EC2 实例使用的是基于资源的命名 (RBN)，则此为 RBN。有关 IPBN、RBN 和 EC2 实例命名的更多信息，请参阅 [EC2 实例主机名和域](ec2-instance-naming.md)。 | 2007-01-19 | 
|  local-ipv4  | 实例的私有 IPv4 地址。在存在多个网络接口的情况下，其指的是 eth0 设备 (设备号为 0 的设备)。若此为仅 IPv6 的实例，则不会设置此项目且会导致 HTTP 404 响应。 | 1.0 | 
|  mac  | 实例的媒体访问控制 (MAC) 地址。在存在多个网络接口的情况下，其指的是 eth0 设备 (设备号为 0 的设备)。 | 2011 年 1 月 1 日 | 
| metrics/vhostmd | 不再可用。 | 2011-05-01 | 
|  network/interfaces/macs/mac/device-number  | 与该接口关联的唯一设备号。设备号与设备名称对应；例如，device-number 为 2 对应于 eth2 设备。此类别对应的是 AWS CLI 的 Amazon EC2 API 和 EC2 命令使用的 DeviceIndex 和 device-index 字段。 | 2011 年 1 月 1 日 | 
|  network/interfaces/macs/mac/interface-id  | 网络接口的 ID。 | 2011 年 1 月 1 日 | 
|  network/interfaces/macs/mac/ipv4-associations/public-ip  | 与每个公用 IP 地址相关联并被分配到该接口的私有 IPv4 地址。 | 2011 年 1 月 1 日 | 
| network/interfaces/macs/mac/ipv6s | 分配给接口的 IPv6 地址。 | 2016-06-30 | 
| network/interfaces/macs/mac/ipv6-prefix | 分配给网络接口的 IPv6 前缀。 |  | 
|  network/interfaces/macs/mac/local-hostname  |  实例的私有 IPv4 DNS 主机名。在存在多个网络接口的情况下，其指的是 eth0 设备 (设备号为 0 的设备)。若此为仅 IPv6 的实例，则此为基于资源的名称。有关 IPBN 和 RBN 的更多信息，请参阅 [EC2 实例主机名和域](ec2-instance-naming.md)。  | 2007-01-19 | 
|  network/interfaces/macs/mac/local-ipv4s  | 与接口关联的私有 IPv4 地址。若此为仅 IPv6 的网络接口，则不会设置此项目且会导致 HTTP 404 响应。 | 2011 年 1 月 1 日 | 
|  network/interfaces/macs/mac/mac  | 该实例的 MAC 地址。 | 2011 年 1 月 1 日 | 
|  network/interfaces/macs/mac/network-card  | 网卡的索引。有些实例类型支持多个网卡。 | 2020-11-01 | 
| network/interfaces/macs/mac/owner-id  | 网络接口拥有者的 ID。在多个接口的环境中，接口可由第三方连接，如 Elastic Load Balancing。接口拥有者需为接口上的流量付费。 | 2011 年 1 月 1 日 | 
|  network/interfaces/macs/mac/public-hostname  | 接口的公有 DNS (IPv4)。仅当 enableDnsHostnames 属性设置为 true 时，才返回此类别。有关更多信息，请参阅《Amazon VPC 用户指南》中的 [VPC 的 DNS 属性](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-dns.html)。如果实例仅具有公有 IPv6 地址而没有公有 IPv4 地址，则不会设置此项目并导致 HTTP 404 响应。 |  2011 年 1 月 1 日 | 
|  network/interfaces/macs/mac/public-ipv4s  | 与接口关联的公有 IP 地址或弹性 IP 地址。一个实例上可能有多个 IPv4 地址。 | 2011 年 1 月 1 日 | 
| network/interfaces/macs/mac/security-groups  | 网络接口所属的安全组。 | 2011 年 1 月 1 日 | 
|  network/interfaces/macs/mac/security-group-ids  | 网络接口所属的安全组的 ID。 | 2011 年 1 月 1 日 | 
|  network/interfaces/macs/mac/subnet-id  | 接口所驻留的子网的 ID。 | 2011 年 1 月 1 日 | 
|  network/interfaces/macs/mac/subnet-ipv4-cidr-block  | 接口所在子网的 IPv4 CIDR 块。 | 2011 年 1 月 1 日 | 
| network/interfaces/macs/mac/subnet-ipv6-cidr-blocks  | 接口所在子网的 IPv6 CIDR 块。 | 2016-06-30  | 
|  network/interfaces/macs/mac/vpc-id  | 接口所驻留的 VPC 的 ID。 | 2011 年 1 月 1 日 | 
| network/interfaces/macs/mac/vpc-ipv4-cidr-block | VPC 的主 IPv4 CIDR 块。 | 2011 年 1 月 1 日 | 
| network/interfaces/macs/mac/vpc-ipv4-cidr-blocks | VPC 的 IPv4 CIDR 块。 | 2016-06-30  | 
| network/interfaces/macs/mac/vpc-ipv6-cidr-blocks | 接口所在 VPC 的 IPv6 CIDR 块。 | 2016-06-30  | 
|  placement/availability-zone | 实例启动的可用区。 | 2008-02-01 | 
|  placement/availability-zone-id | 在其中启动实例的静态可用区 ID。可用区 ID 在账户之间保持一致。但是，它可能与可用区不同，后者可能因账户而异。 | 2019-10-01 | 
|  placement/group-name  | 在其中启动实例的置放群组的名称。 | 2020-08-24 | 
|  placement/host-id  | 启动实例的主机的 ID。仅适用于专用主机。 | 2020-08-24 | 
|  placement/partition-number  | 在其中启动实例的分区编号。 | 2020-08-24 | 
|  placement/region  | 在其中启动实例的 AWS 区域。 | 2020-08-24 | 
|  product-codes  | 与实例相关联的 AWS Marketplace 产品代码（如果有）。 | 2007-03-01 | 
|  public-hostname  | 实例的公有 DNS (IPv4)。仅当 enableDnsHostnames 属性设置为 true 时，才返回此类别。有关更多信息，请参阅《Amazon VPC 用户指南》中的 [VPC 的 DNS 属性](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-dns.html)。如果实例仅具有公有 IPv6 地址而没有公有 IPv4 地址，则不会设置此项目并导致 HTTP 404 响应。 | 2007-01-19 | 
|  public-ipv4  | 公有 IPv4 地址。如果弹性 IP 地址与实例相关联，返回的值是弹性 IP 地址。 | 2007-01-19 | 
|  public-keys/0/openssh-key  | 公有密钥。仅在实例启动时提供了公有密钥的情况下可用。 | 1.0 | 
|  ramdisk-id  | 启动时指定的 RAM 磁盘 的 ID，如果适用的话。 | 2007-10-10 | 
|  reservation-id  | 预留的 ID。 | 1.0 | 
|  security-groups  |  应用到实例的安全组的名称。 在启动后，您可以更改实例的安全组。这些更改将体现在此处和 network/interfaces/macs/**mac**/security-groups 中。  | 1.0 | 
|  services/domain  |  区域的 AWS 资源所在的域。  | 2014-02-25 | 
|  services/partition  |  资源所处的分区。对于标准 AWS 区域，分区是 `aws`。如果资源位于其他分区，则分区是 `aws-partitionname`。例如，中国（北京）区域中的资源的分区为 `aws-cn`。  | 2015-10-20 | 
|  spot/instance-action  |  操作（休眠、停止或终止）和操作发生的大致时间（用 UTC 表示）。仅在已将竞价型实例标记为休眠、停止或终止时才提供此项目。有关更多信息，请参阅[instance-action](spot-instance-termination-notices.md#instance-action-metadata)。  | 2016-11-15 | 
|  spot/termination-time  |  竞价型实例 操作系统将收到关闭信号的大致时间 (UTC)。仅当竞价型实例已由 Amazon EC2 标记为终止时，此项目才会出现并包含时间值（例如，2015-01-05T18:02:00Z）。如果您自己终止了竞价型实例，那么终止时间项目不会设置为时间。有关更多信息，请参阅[termination-time](spot-instance-termination-notices.md#termination-time-metadata)。  | 2014-11-05 | 
| system | 实例的底层虚拟化类型（虚拟机监控程序）。 | 2022-09-24 | 
| tags/instance | 与实例关联的实例标签。只有明确允许访问实例元数据中的标签时才可用。有关更多信息，请参阅 [启用对实例元数据中标签的访问权限](work-with-tags-in-IMDS.md#allow-access-to-tags-in-IMDS)。 | 2021-03-23 | 

## 动态数据类别
<a name="dynamic-data-categories"></a>

下表列举了动态数据的类别。


| 类别 | 说明 | 类别发布时的版本 | 
| --- | --- | --- | 
| fws/instance-monitoring  | 显示客户是否在 CloudWatch 中启用了详细的一分钟监控的值。有效值：enabled \$1 disabled | 2009-04-04 | 
| instance-identity/document  | 包含实例属性 (如实例 ID、私有 IP 地址等) 的 JSON。请参阅 [Amazon EC2 实例的实例身份文档](instance-identity-documents.md)。 | 2009-04-04 | 
| instance-identity/pkcs7  | 用于验证签名的文档的真实性和内容。请参阅 [Amazon EC2 实例的实例身份文档](instance-identity-documents.md)。 | 2009-04-04 | 
| instance-identity/signature  | 可被其他各方用于验证来源和真实性的数据。请参阅 [Amazon EC2 实例的实例身份文档](instance-identity-documents.md)。 | 2009-04-04 | 

# 访问 EC2 实例的实例元数据
<a name="instancedata-data-retrieval"></a>

您可以从实例内或者从 EC2 控制台、API、SDK 或 AWS CLI 访问 EC2 实例元数据。要从控制台或命令行获取实例的当前实例元数据设置，请参阅[查询现有实例的实例元数据选项](#query-IMDS-existing-instances)。

您还可以修改具有 EBS 根卷的实例的用户数据。该实例必须处于已停止状态。有关控制台说明，请参阅 [更新实例用户数据](user-data.md#user-data-modify)。有关使用 AWS CLI 的 Linux 示例，请参阅 [modify-instance-attribute](https://docs.aws.amazon.com/cli/latest/reference/ec2/modify-instance-attribute.html)。有关使用 Tools for Windows PowerShell 的 Windows 示例，请参阅 [用户数据和 Tools for Windows PowerShell](user-data.md#user-data-powershell)。

**注意**  
您无需为用于检索实例元数据和用户数据的 HTTP 请求付费。

## 实例元数据访问注意事项
<a name="imds-considerations"></a>

为避免实例元数据问题，请注意以下因素。

**因 IMDSv2 强制使用 (`HttpTokensEnforced=enabled`) 导致实例启动失败**  
在启用 IMDSv2 强制使用之前，首先需要确保实例上的所有软件都支持 IMDSv2，然后才能将默认设置更改为禁用 IMDSv1 (`httpTokens=required`)，再后才可以启用强制使用。有关更多信息，请参阅 [转换为使用 实例元数据服务版本 2](instance-metadata-transition-to-version-2.md)。

**命令格式**  
根据使用的是实例元数据服务版本 1 (IMDSv1) 还是实例元数据服务版本 2 (IMDSv2)，命令格式会有所不同。默认情况下，您可以使用两个版本的实例元数据服务。要要求使用 IMDSv2，请参阅[使用实例元数据服务访问实例元数据](configuring-instance-metadata-service.md)。

**如果需要 IMDSv2，则 IMDSv1 不起作用**  
如果使用 IMDSv1 后未收到任何响应，则很可能需要 IMDSv2。要检查是否需要 IMDSv2，请选择实例以查看其详细信息。**IMDSv2** 值要么表示**必选**（即必须使用 IMDSv2），要么表示**可选**（即可以使用 IMDSv2 或 IMDSv1）。

**（IMDSv2）使用 /latest/api/token 来检索令牌**  
将 `PUT` 请求发放到任何版本特定的路径（例如 `/2021-03-23/api/token`）将导致元数据服务返回 403 禁止错误。这是预期行为。

**元数据版本**  
为避免每次 Amazon EC2 发布新的实例元数据构建时都必须更新您的代码，我们建议您在路径中使用 `latest`，而不是版本号。

**IPv6 支持**  
要使用 IPv6 地址检索实例元数据，必须确保启用并使用 IPv6 地址 IMDS `[fd00:ec2::254]` 而不是 IPv4 地址 `169.254.169.254`。该实例必须是在[支持 IPv6 的子网](https://docs.aws.amazon.com/vpc/latest/userguide/configure-subnets.html#subnet-ip-address-range)中启动的[基于 Nitro 的实例](instance-types.md#instance-hypervisor-type)。

**（Windows）使用 Windows Sysprep 创建自定义 AMI**  
为了确保在您从自定义 Windows AMI 启动实例时 IMDS 能够正常工作，AMI 必须是使用 Windows Sysprep 创建的标准化映像。否则，IMDS 将无法正常运行。有关更多信息，请参阅 [使用 Windows Sysprep 创建 Amazon EC2 AMI](ami-create-win-sysprep.md)。

**在容器环境中，考虑重新配置或将跃点限制增加到 2**  
默认情况下，AWS开发工具包使用 IMDSv2 调用。如果 IMDSv2 调用没有收到任何响应，某些 AWS SDK 将重试调用，如果仍然不成功，则使用 IMDSv1。这可能会导致延迟，尤其是在容器环境中。对于那些*需要* IMDSv2 的 AWS SDK，如果容器环境中的跃点限制为 1，则调用可能根本收不到响应，因为转到容器被视为额外的网络跃点。  
要缓解容器环境中的这些问题，请考虑更改配置以将设置（例如 AWS 区域）直接传递到容器，或者考虑将跃点限制增加到 2。有关跃点限制影响的信息，请参阅 [Add defense in depth against open firewalls, reverse proxies, and SSRF vulnerabilities with enhancements to the EC2 Instance Metadata Service](https://aws.amazon.com/blogs/security/defense-in-depth-open-firewalls-reverse-proxies-ssrf-vulnerabilities-ec2-instance-metadata-service/)。有关更改跃点限制的信息，请参阅[更改 PUT 响应跃点限制](configuring-IMDS-existing-instances.md#modify-PUT-response-hop-limit)。

**每秒数据包（PPS）限制**  
对于使用[本地链路](using-instance-addressing.md#link-local-addresses)地址的服务，每秒数据包数（PPS）限制为 1024 个。此限制是 [Route 53 Resolver DNS 查询](https://docs.aws.amazon.com/vpc/latest/userguide/AmazonDNS-concepts.html#vpc-dns-limits)、实例元数据服务（IMDS）请求、[Amazon Time Service 网络时间协议（NTP）](set-time.md)请求和 [Windows 许可服务（适用于基于 Microsoft Windows 的实例](https://aws.amazon.com/windows/resources/licensing/)）请求的总和。

**用户数据访问的其他注意事项**
+ 用户数据会被视为非透明数据；您指定什么数据就会在检索时得到什么数据。由实例来解释用户数据并对其进行操作。
+ 用户数据必须采用 base64 编码。根据您使用的工具或 SDK，可能会为您执行 base64 编码。例如：
  + Amazon EC2 控制台可以为您执行 base64 编码或接受 base64 编码的输入。
  + 默认情况下，[AWS CLI 版本 2](https://docs.aws.amazon.com/cli/latest/userguide/cliv2-migration-changes.html#cliv2-migration-binaryparam) 会为您执行二进制参数的 base64 编码。AWS CLI 版本 1 会为您执行 `--user-data` 参数的 base64 编码。
  + 适用于 Python (Boto3) 的 AWS SDK 会为您执行 `UserData` 参数的 base64 编码。
+ 用户数据在进行 base64 编码之前的原始格式的大小限制为 16 KB。长度为 *n* 的字符串在进行 base64 编码之后的大小为 ceil(*n*/3)\$14。
+ 在检索用户数据时，必须对其进行 base64 解码。如果您使用实例元数据或控制台检索数据，则会自动对数据进行解码。
+ 如果您停止实例，修改用户数据，然后启动实例，则在启动实例时，不会自动运行更新后的用户数据。对于 Windows 实例，您可以配置设置，这样更新后的用户数据脚本在您启动实例时运行一次，或者在每次重启或启动实例时运行。
+ 用户数据是一种实例属性。如果您从实例创建 AMI，则实例用户数据不包含在该 AMI 中。

## 从 EC2 实例内访问实例元数据
<a name="instancedata-inside-access"></a>

由于您的正在运行的实例存在实例元数据，因此您无需使用 Amazon EC2 控制台或 AWS CLI。这在您编写脚本以实现从实例运行时非常有用。例如，您可从实例元数据访问您的实例的本地 IP 地址来以管理与外部应用程序的连接。

以下所有内容均被视为实例元数据，但其访问方式不同。选择代表您要访问的实例元数据类型的选项卡，以查看更多信息。

------
#### [ Metadata ]

实例元数据属性分为几类。有关每个实例元数据类别的描述，请参阅[实例元数据类别](ec2-instance-metadata.md#instancedata-data-categories)。

要访问正在运行的实例内的实例元数据属性，请从以下 IPv4 或 IPv6 URI 获取数据。这些 IP 地址是链路本地地址，仅从该实例访问时有效。有关更多信息，请参阅 [链路本地地址](using-instance-addressing.md#link-local-addresses)。

**IPv4**

```
http://169.254.169.254/latest/meta-data/
```

**IPv6**

```
http://[fd00:ec2::254]/latest/meta-data/
```

------
#### [ Dynamic data ]

要从正在运行的实例中检索动态数据，请使用以下 URI 之一。

**IPv4**

```
http://169.254.169.254/latest/dynamic/
```

**IPv6**

```
http://[fd00:ec2::254]/latest/dynamic/
```

**示例：使用 cURL 访问**  
以下示例使用 `cURL` 检索高级实例身份类别。

*IMDSv2*

```
[ec2-user ~]$ TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/dynamic/instance-identity/
rsa2048
pkcs7
document
signature
dsa2048
```

*IMDSv1*

```
[ec2-user ~]$ curl http://169.254.169.254/latest/dynamic/instance-identity/
rsa2048
pkcs7
document
signature
dsa2048
```

**示例：使用 PowerShell 访问**  
以下示例使用 PowerShell 检索高级实例身份类别。

*IMDSv2*

```
PS C:\> [string]$token = Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token-ttl-seconds" = "21600"} -Method PUT -Uri http://169.254.169.254/latest/api/token
```

```
PS C:\> Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token" = $token} -Method GET -Uri http://169.254.169.254/latest/dynamic/instance-identity/
document
rsa2048
pkcs7
signature
```

*IMDSv1*

```
PS C:\> Invoke-RestMethod -uri http://169.254.169.254/latest/dynamic/instance-identity/
document
rsa2048
pkcs7
signature
```

有关动态数据的详细信息和如何对其进行检索的示例，请参阅 [Amazon EC2 实例的实例身份文档](instance-identity-documents.md)。

------
#### [ User data ]

要从实例中检索用户数据，请使用以下 URI 之一。要使用 IPv6 地址检索用户数据，必须将启用该功能，并且实例必须是在支持 IPv6 的子网中的[基于 Nitro 的实例](instance-types.md#instance-hypervisor-type)。

**IPv4**

```
http://169.254.169.254/latest/user-data
```

**IPv6**

```
http://[fd00:ec2::254]/latest/user-data
```

请求用户数据时，按原样返回数据 (内容类型 `application/octet-stream`)。如果该实例没有任何用户数据，则请求将返回 `404 - Not Found`。

**示例：使用 cURL 访问以检索逗号分隔的文本**  
以下示例使用 `cURL` 检索以逗号分隔文本形式指定的用户数据。

*IMDSv2*

```
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/user-data
1234,john,reboot,true | 4512,richard, | 173,,,
```

*IMDSv1*

```
curl http://169.254.169.254/latest/user-data
1234,john,reboot,true | 4512,richard, | 173,,,
```

**示例：使用 PowerShell 访问以检索逗号分隔的文本**  
以下示例使用 PowerShell 检索以逗号分隔文本形式指定的用户数据。

*IMDSv2*

```
[string]$token = Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token-ttl-seconds" = "21600"} -Method PUT -Uri http://169.254.169.254/latest/api/token
```

```
Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token" = $token} -Method GET -Uri http://169.254.169.254/latest/user-data
1234,john,reboot,true | 4512,richard, | 173,,,
```

*IMDSv1*

```
Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token" = Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token-ttl-seconds" = "21600"} `
-Method PUT -Uri http://169.254.169.254/latest/api/token} -Method GET -uri http://169.254.169.254/latest/user-data
1234,john,reboot,true | 4512,richard, | 173,,,
```

**示例：使用 cURL 访问以检索脚本**  
以下示例使用 `cURL` 检索指定为脚本的用户数据。

*IMDSv2*

```
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/user-data
#!/bin/bash
yum update -y
service httpd start
chkconfig httpd on
```

*IMDSv1*

```
curl http://169.254.169.254/latest/user-data
#!/bin/bash
yum update -y
service httpd start
chkconfig httpd on
```

**示例：使用 PowerShell 访问以检索脚本**  
以下示例使用 PowerShell 检索指定为脚本的用户数据。

*IMDSv2*

```
[string]$token = Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token-ttl-seconds" = "21600"} -Method PUT -Uri http://169.254.169.254/latest/api/token
```

```
Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token" = $token} -Method GET -Uri http://169.254.169.254/latest/user-data
<powershell>
$file = $env:SystemRoot + "\Temp\" + (Get-Date).ToString("MM-dd-yy-hh-mm")
New-Item $file -ItemType file
</powershell>
<persist>true</persist>
```

*IMDSv1*

```
Invoke-RestMethod -uri http://169.254.169.254/latest/user-data
<powershell>
$file = $env:SystemRoot + "\Temp\" + (Get-Date).ToString("MM-dd-yy-hh-mm")
New-Item $file -ItemType file
</powershell>
<persist>true</persist>
```

------

## 查询现有实例的实例元数据选项
<a name="query-IMDS-existing-instances"></a>

您可以查询现有实例的实例元数据选项。

------
#### [ Console ]

**查询现有实例的实例元数据选项**

1. 通过以下网址打开 Amazon EC2 控制台：[https://console.aws.amazon.com/ec2/](https://console.aws.amazon.com/ec2/)。

1. 在导航窗格中，选择 **Instances (实例)**。

1. 选择您的实例并选中以下字段：
   + **IMDSv2**：该值为**必填**或**可选**。
   + **允许在实例元数据中使用标签**：该值为**已启用**或**已禁用**。

1. 选择实例后，依次选择**操作**、**实例设置**、**修改实例元数据选项**。

   该对话框显示所选实例的实例元数据服务是处于已启用状态还是已禁用状态。

------
#### [ AWS CLI ]

**查询现有实例的实例元数据选项**  
可以使用 [describe-instances](https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-instances.html) 命令。

```
aws ec2 describe-instances \
    --instance-id i-1234567898abcdef0 \
    --query 'Reservations[].Instances[].MetadataOptions'
```

------
#### [ PowerShell ]

**使用 Tools for PowerShell 查询现有实例的实例元数据选项**  
使用 [Get-EC2Instance](https://docs.aws.amazon.com/powershell/latest/reference/items/Get-EC2Instance.html) cmdlet。

```
(Get-EC2Instance `
    -InstanceId i-1234567898abcdef0).Instances.MetadataOptions
```

------

## 响应和错误消息
<a name="instance-metadata-returns"></a>

所有实例元数据以文本形式返回（HTTP 内容类型 `text/plain`）。

特定元数据资源的请求返回相应的值；如果资源不可用，则返回 HTTP 错误代码 `404 - Not Found`。

对通用元数据资源的请求 (以 / 结尾的 URI) 会返回一个可用资源列表，如果此类资源不存在，则会返回 HTTP 错误代码 `404 - Not Found`。列表中的各个项目位于被换行符 (ASCII 10) 终止的不同的行上。

如果 IMDSv1 请求没有收到响应，则很可能需要 IMDSv2。

对于使用 IMDSv2 发出的请求，可能会返回以下 HTTP 错误代码：
+ `400 - Missing or Invalid Parameters` – `PUT` 请求无效。
+ `401 - Unauthorized` – `GET` 请求使用无效的令牌。建议的措施是生成新的令牌。
+ `403 - Forbidden` – 该请求不被允许，或者 IMDS 已关闭。
+ `404 - Not Found` – 资源不可用或没有此类资源。
+ `503` – 无法完成请求。重试请求。

如果 IMDS 返回错误，**curl** 会在输出中打印错误消息并返回成功状态代码。错误消息存储在 `TOKEN` 变量中，这会导致使用该令牌的 **curl** 命令失败。如果使用 **-f** 选项调用 **curl**，则会在出现 HTTP 服务器错误时返回错误状态代码。如果启用错误处理功能，Shell 可以捕获错误并停止脚本。

## 查询限制
<a name="instancedata-throttling"></a>

我们基于每个实例来限制对 IMDS 的查询，并且对从实例到 IMDS 的同时连接数进行限制。

如果您使用 IMDS 检索 AWS 安全凭证，请避免在每个事务期间查询凭证或从大量线程或进程中并发查询凭证，因为这可能会导致节流。相反，我们建议您缓存凭证，直到凭证开始接近其到期时间。有关 IAM 角色以及与其关联的安全凭证的更多信息，请参阅 [从实例元数据中检索安全凭证](instance-metadata-security-credentials.md)。

如果在访问 IMDS 时受到限制，请使用指数回退策略重试查询。

# 使用实例元数据服务访问实例元数据
<a name="configuring-instance-metadata-service"></a>

您可以使用以下其中一种方法，从正在运行的实例中访问实例元数据：
+ 实例元数据服务版本 2 (IMDSv2)：一种面向会话的方法

  有关示例，请参阅 [IMDSv2 的示例](#instance-metadata-retrieval-examples)。
+ 实例元数据服务版本 1（IMDSv1）– 一种请求/响应方法

  有关示例，请参阅 [IMDSv1 的示例](#instance-metadata-retrieval-examples-imdsv1)。

默认情况下，您可以使用 IMDSv1 和/或 IMDSv2。

您可以在每个实例上配置实例元数据服务（IMDS），使其仅接受 IMDSv2 调用，这将导致 IMDSv1 调用失败。有关如何配置实例以使用 IMDSv2 的信息，请参阅 [配置实例元数据服务选项](configuring-instance-metadata-options.md)。

`PUT` 或 `GET` 标头对于 IMDSv2 是唯一的。如果请求中存在这些标头，则该请求针对 IMDSv2。如果不存在标头，则假定该请求针对 IMDSv1。

有关 IMDSv2 的详细回顾，请参阅[借助 EC2 实例元数据服务的增强功能，为开放式防火墙、反向代理和 SSRF 漏洞增加深度防御](https://aws.amazon.com/blogs/security/defense-in-depth-open-firewalls-reverse-proxies-ssrf-vulnerabilities-ec2-instance-metadata-service/)。

**Topics**
+ [

## 实例元数据服务版本 2 的工作原理
](#instance-metadata-v2-how-it-works)
+ [

## 使用支持的 AWS 开发工具包
](#use-a-supported-sdk-version-for-imdsv2)
+ [

## IMDSv2 的示例
](#instance-metadata-retrieval-examples)
+ [

## IMDSv1 的示例
](#instance-metadata-retrieval-examples-imdsv1)

## 实例元数据服务版本 2 的工作原理
<a name="instance-metadata-v2-how-it-works"></a>

IMDSv2 使用面向会话的请求。对于面向会话的请求，您创建一个会话令牌以定义会话持续时间，该时间最少为 1 秒，最多为 6 小时。在指定的持续时间内，您可以将相同的会话令牌用于后续请求。在指定的持续时间到期后，您必须创建新的会话令牌以用于将来的请求。

**注意**  
本部分中的示例使用实例元数据服务（IMDS）的 IPv4 地址：`169.254.169.254`。如果要通过 IPv6 地址检索 EC2 实例的实例元数据，请确保启用并改用 IPv6 地址：`[fd00:ec2::254]`。IMDS 的 IPv6 地址与 IMDSv2 命令兼容。IPv6 地址仅可在[支持 IPv6 的子网](https://docs.aws.amazon.com/vpc/latest/userguide/configure-subnets.html#subnet-ip-address-range)（双栈或仅 IPv6）中[基于 Nitro 的实例](instance-types.md#instance-hypervisor-type)上访问。

以下示例使用 Shell 脚本和 IMDSv2 检索顶级实例元数据项。每个示例：
+ 使用 `PUT` 请求创建持续 6 小时（21600 秒）的会话令牌
+ 将会话令牌标头存储在名为 `TOKEN`（Linux 实例）或 `token`（Windows 实例）的变量中
+ 使用令牌请求顶级元数据项

### Linux 示例
<a name="how-imdsv2-works-example-linux"></a>

您可以运行两个单独的命令，也可以将它们组合使用。

**单独的命令**

首先，使用以下命令生成令牌。

```
[ec2-user ~]$ TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
```

然后，通过令牌使用以下命令生成顶级元数据项。

```
[ec2-user ~]$ curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/
```

**组合命令**

您可以存储令牌并组合命令。以下示例将上述两个命令组合在一起，并将会话令牌标头存储在名为 TOKEN 的变量中。

**注意**  
如果创建令牌时发生错误，则不会生成有效令牌，而会在变量中存储一条错误消息，该命令将不起作用。

```
[ec2-user ~]$ TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
	&& curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/
```

在创建令牌后，您可以重复使用令牌，直到令牌过期。在以下示例命令（获取用于启动实例的 AMI 的 ID）中，将重复使用上一示例中的令牌（存储在 `$TOKEN` 中）。

```
[ec2-user ~]$ curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/ami-id
```

### Windows 示例
<a name="how-imdsv2-works-example-windows"></a>

```
PS C:\> [string]$token = Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token-ttl-seconds" = "21600"} -Method PUT -Uri http://169.254.169.254/latest/api/token
```

```
PS C:\> Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token" = $token} -Method GET -Uri http://169.254.169.254/latest/meta-data/
```

在创建令牌后，您可以重复使用令牌，直到令牌过期。在以下示例命令（获取用于启动实例的 AMI 的 ID）中，将重复使用上一示例中的令牌（存储在 `$token` 中）。

```
PS C:\> Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token" = $token} `
	-Method GET -uri http://169.254.169.254/latest/meta-data/ami-id
```

在使用 IMDSv2 请求实例元数据时，请求必须包含以下内容：

1. 使用 `PUT` 请求启动到实例元数据服务的会话。`PUT` 请求返回一个令牌，该令牌必须包含在对实例元数据服务的后续 `GET` 请求中。需要具有该令牌才能使用 IMDSv2 访问元数据。

1. 将该令牌包含在对 IMDS 的所有 `GET` 请求中。如果将令牌使用设置为 `required`，没有有效令牌或令牌过期的请求将显示 `401 - Unauthorized` HTTP 错误代码。
   + 令牌是实例特定的密钥。令牌在其他 EC2 实例上无效，如果尝试在生成令牌的实例外部使用，令牌将会被拒绝。
   + `PUT` 请求必须包含一个标头，它以秒为单位指定令牌的生存时间 (TTL)，最多为 6 小时（21600 秒）。令牌表示一个逻辑会话。TTL 指定令牌的有效时间长度，因而指定会话的持续时间。
   + 在令牌过期后，要继续访问实例元数据，您必须使用另一 `PUT` 创建新会话。
   + 您可以选择在每个请求中重复使用令牌或创建新的令牌。对于少量请求，每次需要访问 IMDS 时生成令牌并立即使用可能会更容易。但为了提高效率，您可以为令牌指定更长的持续时间并重复使用令牌，而不必在每次需要请求实例元数据时都编写 `PUT` 请求。对并发令牌数量没有实际限制，每个令牌表示自己的会话。不过，IMDSv2 仍然受到正常 IMDS 连接和节流限制的制约。有关更多信息，请参阅 [查询限制](instancedata-data-retrieval.md#instancedata-throttling)。

允许在 IMDSv2 实例元数据请求中使用 HTTP `GET` 和 `HEAD` 方法。如果 `PUT` 请求包含 X-Forwarded-For 标头，则会被拒绝。

默认情况下，`PUT` 请求的响应在 IP 协议级别的响应跃点数限制（生存时间）为 `1`。如果需要更大的跃点数限制，可使用 [modify-instance-metadata-options](https://docs.aws.amazon.com/cli/latest/reference/ec2/modify-instance-metadata-options.html) AWS CLI 命令进行调整。例如，您可能需要使用更大的跃点数限制，以便与实例上运行的容器服务保持向后兼容。有关更多信息，请参阅 [为现有实例修改实例元数据选项](configuring-IMDS-existing-instances.md)。

## 使用支持的 AWS 开发工具包
<a name="use-a-supported-sdk-version-for-imdsv2"></a>

要使用 IMDSv2，EC2 实例必须使用支持 IMDSv2 的 AWS 开发工具包版本。所有 AWS 开发工具包的最新版本均支持使用 IMDSv2。

**重要**  
我们建议您及时了解开发工具包版本，以了解其最新功能、安全更新和底层依赖项。不建议继续使用不受支持的开发工具包版本，但是否继续使用由您自行决定。有关更多信息，请参阅《AWS SDK 和工具参考指南》**中的 [AWS SDK 和工具维护策略](https://docs.aws.amazon.com/sdkref/latest/guide/maint-policy.html)。

以下是支持使用 IMDSv2 的最低版本：
+ [AWS CLI](https://github.com/aws/aws-cli) – 1.16.289
+ [AWS Tools for Windows PowerShell](https://github.com/aws/aws-tools-for-powershell) – 4.0.1.0
+ [适用于 .NET 的 AWS SDK](https://github.com/aws/aws-sdk-net) – 3.3.634.1
+ [适用于 C\$1\$1 的 AWS SDK](https://github.com/aws/aws-sdk-cpp) – 1.7.229
+ [适用于 Go 的 AWS SDK](https://github.com/aws/aws-sdk-go) – 1.25.38
+ [AWS SDK for Go v2](https://github.com/aws/aws-sdk-go-v2) – 0.19.0
+ [适用于 Java 的 AWS SDK](https://github.com/aws/aws-sdk-java) – 1.11.678
+ [AWS SDK for Java 2.x](https://github.com/aws/aws-sdk-java-v2) – 2.10.21
+ [适用于 Node.js 中 JavaScript 的 AWS 开发工具包](https://github.com/aws/aws-sdk-js) – 2.722.0
+ [适用于 Kotlin 的 AWS SDK](https://github.com/awslabs/aws-sdk-kotlin)：1.1.4
+ [适用于 PHP 的 AWS SDK](https://github.com/aws/aws-sdk-php) – 3.147.7
+ [适用于 Python (Botocore) 的 AWS SDK](https://github.com/boto/botocore) – 1.13.25
+ [适用于 Python (Boto3) 的 AWS SDK](https://github.com/boto/boto3) – 1.12.6
+ [适用于 Ruby 的 AWS SDK](https://github.com/aws/aws-sdk-ruby) – 3.79.0

## IMDSv2 的示例
<a name="instance-metadata-retrieval-examples"></a>

在您的 Amazon EC2 实例上运行以下示例，以检索 IMDSv2 的实例元数据。

在 Windows 实例上，您可以使用 Windows PowerShell，也可以安装 cURL 或 wget。如果您在 Windows 实例上安装第三方工具，请确保您仔细阅读随附的文档，因为调用和输出格式可能与此处所述的内容不同。

**Topics**
+ [

### 获取实例元数据的可用版本
](#instance-metadata-ex-1)
+ [

### 获取顶级元数据项
](#instance-metadata-ex-2)
+ [

### 获取元数据项的值
](#instance-metadata-ex-2a)
+ [

### 获取可用的公有密钥列表
](#instance-metadata-ex-3)
+ [

### 显示可以使用公有密钥 0 的格式
](#instance-metadata-ex-4)
+ [

### 获取公有密钥 0（采用 OpenSSH 密钥格式）
](#instance-metadata-ex-5)
+ [

### 获取实例的子网 ID
](#instance-metadata-ex-6)
+ [

### 获取实例的实例标签
](#instance-metadata-ex-7)

### 获取实例元数据的可用版本
<a name="instance-metadata-ex-1"></a>

此示例可以获取实例元数据的可用版本。当有新的实例元数据类别发布时，每个版本都引用一个实例元数据构建。实例元数据构建版本与 Amazon EC2 API 版本不相关。如果您有依赖于以前版本中所存在的结构和信息的脚本，则您可使用早期版本。

------
#### [ cURL ]

```
[ec2-user ~]$ TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/
1.0
2007-01-19
2007-03-01
2007-08-29
2007-10-10
2007-12-15
2008-02-01
2008-09-01
2009-04-04
2011-01-01
2011-05-01
2012-01-12
2014-02-25
2014-11-05
2015-10-20
2016-04-19
...
latest
```

------
#### [ PowerShell ]

```
PS C:\> [string]$token = Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token-ttl-seconds" = "21600"} -Method PUT -Uri http://169.254.169.254/latest/api/token
```

```
PS C:\> Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token" = $token} -Method GET -Uri http://169.254.169.254/
1.0
2007-01-19
2007-03-01
2007-08-29
2007-10-10
2007-12-15
2008-02-01
2008-09-01
2009-04-04
2011-01-01
2011-05-01
2012-01-12
2014-02-25
2014-11-05
2015-10-20
2016-04-19
...
latest
```

------

### 获取顶级元数据项
<a name="instance-metadata-ex-2"></a>

此示例获得顶级元数据项目。有关响应中项目的更多信息，请参阅 [实例元数据类别](ec2-instance-metadata.md#instancedata-data-categories)。

请注意，只有在允许您访问的情况下，标签才会包含在此输出中。有关更多信息，请参阅 [启用对实例元数据中标签的访问权限](work-with-tags-in-IMDS.md#allow-access-to-tags-in-IMDS)。

------
#### [ cURL ]

```
[ec2-user ~]$ TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/    
ami-id
ami-launch-index
ami-manifest-path
block-device-mapping/
events/
hostname
iam/
instance-action
instance-id
instance-life-cycle
instance-type
local-hostname
local-ipv4
mac
metrics/
network/
placement/
profile
public-hostname
public-ipv4
public-keys/
reservation-id
security-groups
services/
tags/
```

------
#### [ PowerShell ]

```
PS C:\> [string]$token = Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token-ttl-seconds" = "21600"} -Method PUT -Uri http://169.254.169.254/latest/api/token
```

```
PS C:\> Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token" = $token} -Method GET -Uri http://169.254.169.254/latest/meta-data/
ami-id
ami-launch-index
ami-manifest-path
block-device-mapping/
hostname
iam/
instance-action
instance-id
instance-life-cycle
instance-type
local-hostname
local-ipv4
mac
metrics/
network/
placement/
profile
public-hostname
public-ipv4
public-keys/
reservation-id
security-groups
services/
tags/
```

------

### 获取元数据项的值
<a name="instance-metadata-ex-2a"></a>

这些示例获取在前面示例中获取的某些顶级元数据项的值。这些请求使用在前面的示例中使用命令创建的存储令牌。令牌不得过期。

------
#### [ cURL ]

```
[ec2-user ~]$ curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/ami-id
ami-0abcdef1234567890
```

```
[ec2-user ~]$ curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/reservation-id
r-0efghijk987654321
```

```
[ec2-user ~]$ curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/local-hostname
ip-10-251-50-12.ec2.internal
```

```
[ec2-user ~]$ curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/public-hostname
ec2-203-0-113-25.compute-1.amazonaws.com
```

------
#### [ PowerShell ]

```
PS C:\> Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token" = $token} -Method GET -Uri http://169.254.169.254/latest/meta-data/ami-id
ami-0abcdef1234567890
```

```
PS C:\> Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token" = $token} -Method GET -Uri http://169.254.169.254/latest/meta-data/reservation-id
r-0efghijk987654321
```

```
PS C:\> Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token" = $token} -Method GET -Uri http://169.254.169.254/latest/meta-data/local-hostname
ip-10-251-50-12.ec2.internal
```

```
PS C:\> Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token" = $token} -Method GET -Uri http://169.254.169.254/latest/meta-data/public-hostname
ec2-203-0-113-25.compute-1.amazonaws.com
```

------

### 获取可用的公有密钥列表
<a name="instance-metadata-ex-3"></a>

此示例获得可用公有密钥的列表。

------
#### [ cURL ]

```
[ec2-user ~]$ TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/public-keys/
0=my-public-key
```

------
#### [ PowerShell ]

```
PS C:\> [string]$token = Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token-ttl-seconds" = "21600"} -Method PUT -Uri http://169.254.169.254/latest/api/token
```

```
PS C:\> Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token" = $token} -Method GET -Uri http://169.254.169.254/latest/meta-data/public-keys/
0=my-public-key
```

------

### 显示可以使用公有密钥 0 的格式
<a name="instance-metadata-ex-4"></a>

此示例显示了可以使用公有密钥 0 的格式。

------
#### [ cURL ]

```
[ec2-user ~]$ TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/public-keys/0/
openssh-key
```

------
#### [ PowerShell ]

```
PS C:\> [string]$token = Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token-ttl-seconds" = "21600"} -Method PUT -Uri http://169.254.169.254/latest/api/token
```

```
PS C:\> Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token" = $token} -Method GET -Uri http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key
openssh-key
```

------

### 获取公有密钥 0（采用 OpenSSH 密钥格式）
<a name="instance-metadata-ex-5"></a>

此示例获得公有密钥 0 (以 OpenSSH 密钥格式)。

------
#### [ cURL ]

```
[ec2-user ~]$ TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key
ssh-rsa MIICiTCCAfICCQD6m7oRw0uXOjANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMC
VVMxCzAJBgNVBAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZBbWF6
b24xFDASBgNVBAsTC0lBTSBDb25zb2xlMRIwEAYDVQQDEwlUZXN0Q2lsYWMxHzAd
BgkqhkiG9w0BCQEWEG5vb25lQGFtYXpvbi5jb20wHhcNMTEwNDI1MjA0NTIxWhcN
MTIwNDI0MjA0NTIxWjCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAldBMRAwDgYD
VQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZBbWF6b24xFDASBgNVBAsTC0lBTSBDb25z
b2xlMRIwEAYDVQQDEwlUZXN0Q2lsYWMxHzAdBgkqhkiG9w0BCQEWEG5vb25lQGFt
YXpvbi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMaK0dn+a4GmWIWJ
21uUSfwfEvySWtC2XADZ4nB+BLYgVIk60CpiwsZ3G93vUEIO3IyNoH/f0wYK8m9T
rDHudUZg3qX4waLG5M43q7Wgc/MbQITxOUSQv7c7ugFFDzQGBzZswY6786m86gpE
Ibb3OhjZnzcvQAaRHhdlQWIMm2nrAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAtCu4
nUhVVxYUntneD9+h8Mg9q6q+auNKyExzyLwaxlAoo7TJHidbtS4J5iNmZgXL0Fkb
FFBjvSfpJIlJ00zbhNYS5f6GuoEDmFJl0ZxBHjJnyp378OD8uTs7fLvjx79LjSTb
NYiytVbZPQUQ5Yaxu2jXnimvw3rrszlaEXAMPLE my-public-key
```

------
#### [ PowerShell ]

```
PS C:\> [string]$token = Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token-ttl-seconds" = "21600"} -Method PUT -Uri http://169.254.169.254/latest/api/token
```

```
PS C:\> Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token" = $token} -Method GET -Uri http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key
ssh-rsa MIICiTCCAfICCQD6m7oRw0uXOjANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMC
VVMxCzAJBgNVBAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZBbWF6
b24xFDASBgNVBAsTC0lBTSBDb25zb2xlMRIwEAYDVQQDEwlUZXN0Q2lsYWMxHzAd
BgkqhkiG9w0BCQEWEG5vb25lQGFtYXpvbi5jb20wHhcNMTEwNDI1MjA0NTIxWhcN
MTIwNDI0MjA0NTIxWjCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAldBMRAwDgYD
VQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZBbWF6b24xFDASBgNVBAsTC0lBTSBDb25z
b2xlMRIwEAYDVQQDEwlUZXN0Q2lsYWMxHzAdBgkqhkiG9w0BCQEWEG5vb25lQGFt
YXpvbi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMaK0dn+a4GmWIWJ
21uUSfwfEvySWtC2XADZ4nB+BLYgVIk60CpiwsZ3G93vUEIO3IyNoH/f0wYK8m9T
rDHudUZg3qX4waLG5M43q7Wgc/MbQITxOUSQv7c7ugFFDzQGBzZswY6786m86gpE
Ibb3OhjZnzcvQAaRHhdlQWIMm2nrAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAtCu4
nUhVVxYUntneD9+h8Mg9q6q+auNKyExzyLwaxlAoo7TJHidbtS4J5iNmZgXL0Fkb
FFBjvSfpJIlJ00zbhNYS5f6GuoEDmFJl0ZxBHjJnyp378OD8uTs7fLvjx79LjSTb
NYiytVbZPQUQ5Yaxu2jXnimvw3rrszlaEXAMPLE my-public-key
```

------

### 获取实例的子网 ID
<a name="instance-metadata-ex-6"></a>

此示例获取实例的子网 ID。

------
#### [ cURL ]

```
[ec2-user ~]$ TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/network/interfaces/macs/02:29:96:8f:6a:2d/subnet-id
subnet-be9b61d7
```

------
#### [ PowerShell ]

```
PS C:\> [string]$token = Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token-ttl-seconds" = "21600"} -Method PUT -Uri http://169.254.169.254/latest/api/token
```

```
PS C:\> Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token" = $token} -Method GET -Uri http://169.254.169.254/latest/meta-data/network/interfaces/macs/02:29:96:8f:6a:2d/subnet-id
subnet-be9b61d7
```

------

### 获取实例的实例标签
<a name="instance-metadata-ex-7"></a>

如果对实例元数据中的实例标签的访问权限已开启，则可以从实例元数据中获得实例标签。有关更多信息，请参阅 [从实例元数据中检索标签](work-with-tags-in-IMDS.md#retrieve-tags-from-IMDS)。

## IMDSv1 的示例
<a name="instance-metadata-retrieval-examples-imdsv1"></a>

在您的 Amazon EC2 实例上运行以下示例，以检索 IMDSv1 的实例元数据。

在 Windows 实例上，您可以使用 Windows PowerShell，也可以安装 cURL 或 wget。如果您在 Windows 实例上安装第三方工具，请确保您仔细阅读随附的文档，因为调用和输出格式可能与此处所述的内容不同。

**Topics**
+ [

### 获取实例元数据的可用版本
](#instance-metadata-ex-1-imdsv1)
+ [

### 获取顶级元数据项
](#instance-metadata-ex-2-imdsv1)
+ [

### 获取元数据项的值
](#instance-metadata-ex-2a-imdsv1)
+ [

### 获取可用的公有密钥列表
](#instance-metadata-ex-3-imdsv1)
+ [

### 显示可以使用公有密钥 0 的格式
](#instance-metadata-ex-4-imdsv1)
+ [

### 获取公有密钥 0（采用 OpenSSH 密钥格式）
](#instance-metadata-ex-5-imdsv1)
+ [

### 获取实例的子网 ID
](#instance-metadata-ex-6-imdsv1)
+ [

### 获取实例的实例标签
](#instance-metadata-ex-7-imdsv1)

### 获取实例元数据的可用版本
<a name="instance-metadata-ex-1-imdsv1"></a>

此示例可以获取实例元数据的可用版本。当有新的实例元数据类别发布时，每个版本都引用一个实例元数据构建。实例元数据构建版本与 Amazon EC2 API 版本不相关。如果您有依赖于以前版本中所存在的结构和信息的脚本，则您可使用早期版本。

------
#### [ cURL ]

```
[ec2-user ~]$ curl http://169.254.169.254/
1.0
2007-01-19
2007-03-01
2007-08-29
2007-10-10
2007-12-15
2008-02-01
2008-09-01
2009-04-04
2011-01-01
2011-05-01
2012-01-12
2014-02-25
2014-11-05
2015-10-20
2016-04-19
...
latest
```

------
#### [ PowerShell ]

```
PS C:\> Invoke-RestMethod -uri http://169.254.169.254/
1.0
2007-01-19
2007-03-01
2007-08-29
2007-10-10
2007-12-15
2008-02-01
2008-09-01
2009-04-04
2011-01-01
2011-05-01
2012-01-12
2014-02-25
2014-11-05
2015-10-20
2016-04-19
...
latest
```

------

### 获取顶级元数据项
<a name="instance-metadata-ex-2-imdsv1"></a>

此示例获得顶级元数据项目。有关响应中项目的更多信息，请参阅 [实例元数据类别](ec2-instance-metadata.md#instancedata-data-categories)。

请注意，只有在允许您访问的情况下，标签才会包含在此输出中。有关更多信息，请参阅 [启用对实例元数据中标签的访问权限](work-with-tags-in-IMDS.md#allow-access-to-tags-in-IMDS)。

------
#### [ cURL ]

```
[ec2-user ~]$ curl http://169.254.169.254/latest/meta-data/    
ami-id
ami-launch-index
ami-manifest-path
block-device-mapping/
events/
hostname
iam/
instance-action
instance-id
instance-type
local-hostname
local-ipv4
mac
metrics/
network/
placement/
profile
public-hostname
public-ipv4
public-keys/
reservation-id
security-groups
services/
tags/
```

------
#### [ PowerShell ]

```
PS C:\> Invoke-RestMethod -uri http://169.254.169.254/latest/meta-data/    
ami-id
ami-launch-index
ami-manifest-path
block-device-mapping/
hostname
iam/
instance-action
instance-id
instance-type
local-hostname
local-ipv4
mac
metrics/
network/
placement/
profile
public-hostname
public-ipv4
public-keys/
reservation-id
security-groups
services/
tags/
```

------

### 获取元数据项的值
<a name="instance-metadata-ex-2a-imdsv1"></a>

这些示例获取在先前示例中获取的某些顶级元数据项的值。

------
#### [ cURL ]

```
[ec2-user ~]$ curl http://169.254.169.254/latest/meta-data/ami-id
ami-0abcdef1234567890
```

```
[ec2-user ~]$ curl http://169.254.169.254/latest/meta-data/reservation-id
r-0efghijk987654321
```

```
[ec2-user ~]$ curl http://169.254.169.254/latest/meta-data/local-hostname
ip-10-251-50-12.ec2.internal
```

```
[ec2-user ~]$ curl http://169.254.169.254/latest/meta-data/public-hostname
ec2-203-0-113-25.compute-1.amazonaws.com
```

------
#### [ PowerShell ]

```
PS C:\> Invoke-RestMethod -uri http://169.254.169.254/latest/meta-data/ami-id
ami-0abcdef1234567890
```

```
PS C:\> Invoke-RestMethod -uri http://169.254.169.254/latest/meta-data/reservation-id
r-0efghijk987654321
```

```
PS C:\> Invoke-RestMethod -uri http://169.254.169.254/latest/meta-data/local-hostname
ip-10-251-50-12.ec2.internal
```

```
PS C:\> Invoke-RestMethod -uri http://169.254.169.254/latest/meta-data/public-hostname
ec2-203-0-113-25.compute-1.amazonaws.com
```

------

### 获取可用的公有密钥列表
<a name="instance-metadata-ex-3-imdsv1"></a>

此示例获得可用公有密钥的列表。

------
#### [ cURL ]

```
[ec2-user ~]$ curl http://169.254.169.254/latest/meta-data/public-keys/
0=my-public-key
```

------
#### [ PowerShell ]

```
PS C:\> Invoke-RestMethod -uri http://169.254.169.254/latest/meta-data/public-keys/ 0=my-public-key
```

------

### 显示可以使用公有密钥 0 的格式
<a name="instance-metadata-ex-4-imdsv1"></a>

此示例显示了可以使用公有密钥 0 的格式。

------
#### [ cURL ]

```
[ec2-user ~]$ curl http://169.254.169.254/latest/meta-data/public-keys/0/
openssh-key
```

------
#### [ PowerShell ]

```
PS C:\> Invoke-RestMethod -uri http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key
openssh-key
```

------

### 获取公有密钥 0（采用 OpenSSH 密钥格式）
<a name="instance-metadata-ex-5-imdsv1"></a>

此示例获得公有密钥 0 (以 OpenSSH 密钥格式)。

------
#### [ cURL ]

```
[ec2-user ~]$ curl http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key
ssh-rsa MIICiTCCAfICCQD6m7oRw0uXOjANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMC
VVMxCzAJBgNVBAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZBbWF6
b24xFDASBgNVBAsTC0lBTSBDb25zb2xlMRIwEAYDVQQDEwlUZXN0Q2lsYWMxHzAd
BgkqhkiG9w0BCQEWEG5vb25lQGFtYXpvbi5jb20wHhcNMTEwNDI1MjA0NTIxWhcN
MTIwNDI0MjA0NTIxWjCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAldBMRAwDgYD
VQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZBbWF6b24xFDASBgNVBAsTC0lBTSBDb25z
b2xlMRIwEAYDVQQDEwlUZXN0Q2lsYWMxHzAdBgkqhkiG9w0BCQEWEG5vb25lQGFt
YXpvbi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMaK0dn+a4GmWIWJ
21uUSfwfEvySWtC2XADZ4nB+BLYgVIk60CpiwsZ3G93vUEIO3IyNoH/f0wYK8m9T
rDHudUZg3qX4waLG5M43q7Wgc/MbQITxOUSQv7c7ugFFDzQGBzZswY6786m86gpE
Ibb3OhjZnzcvQAaRHhdlQWIMm2nrAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAtCu4
nUhVVxYUntneD9+h8Mg9q6q+auNKyExzyLwaxlAoo7TJHidbtS4J5iNmZgXL0Fkb
FFBjvSfpJIlJ00zbhNYS5f6GuoEDmFJl0ZxBHjJnyp378OD8uTs7fLvjx79LjSTb
NYiytVbZPQUQ5Yaxu2jXnimvw3rrszlaEXAMPLE my-public-key
```

------
#### [ PowerShell ]

```
PS C:\> Invoke-RestMethod -uri http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key
ssh-rsa MIICiTCCAfICCQD6m7oRw0uXOjANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMC
VVMxCzAJBgNVBAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZBbWF6
b24xFDASBgNVBAsTC0lBTSBDb25zb2xlMRIwEAYDVQQDEwlUZXN0Q2lsYWMxHzAd
BgkqhkiG9w0BCQEWEG5vb25lQGFtYXpvbi5jb20wHhcNMTEwNDI1MjA0NTIxWhcN
MTIwNDI0MjA0NTIxWjCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAldBMRAwDgYD
VQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZBbWF6b24xFDASBgNVBAsTC0lBTSBDb25z
b2xlMRIwEAYDVQQDEwlUZXN0Q2lsYWMxHzAdBgkqhkiG9w0BCQEWEG5vb25lQGFt
YXpvbi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMaK0dn+a4GmWIWJ
21uUSfwfEvySWtC2XADZ4nB+BLYgVIk60CpiwsZ3G93vUEIO3IyNoH/f0wYK8m9T
rDHudUZg3qX4waLG5M43q7Wgc/MbQITxOUSQv7c7ugFFDzQGBzZswY6786m86gpE
Ibb3OhjZnzcvQAaRHhdlQWIMm2nrAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAtCu4
nUhVVxYUntneD9+h8Mg9q6q+auNKyExzyLwaxlAoo7TJHidbtS4J5iNmZgXL0Fkb
FFBjvSfpJIlJ00zbhNYS5f6GuoEDmFJl0ZxBHjJnyp378OD8uTs7fLvjx79LjSTb
NYiytVbZPQUQ5Yaxu2jXnimvw3rrszlaEXAMPLE my-public-key
```

------

### 获取实例的子网 ID
<a name="instance-metadata-ex-6-imdsv1"></a>

此示例获取实例的子网 ID。

------
#### [ cURL ]

```
[ec2-user ~]$ curl http://169.254.169.254/latest/meta-data/network/interfaces/macs/02:29:96:8f:6a:2d/subnet-id
subnet-be9b61d7
```

------
#### [ PowerShell ]

```
PS C:\> Invoke-RestMethod -uri http://169.254.169.254/latest/meta-data/network/interfaces/macs/02:29:96:8f:6a:2d/subnet-id
subnet-be9b61d7
```

------

### 获取实例的实例标签
<a name="instance-metadata-ex-7-imdsv1"></a>

如果对实例元数据中的实例标签的访问权限已开启，则可以从实例元数据中获得实例标签。有关更多信息，请参阅 [从实例元数据中检索标签](work-with-tags-in-IMDS.md#retrieve-tags-from-IMDS)。

# 转换为使用 实例元数据服务版本 2
<a name="instance-metadata-transition-to-version-2"></a>

如果要将实例配置为仅接受实例元数据服务版本 2（IMDSv2）调用，我们建议您使用以下工具和转换途径。

**Topics**
+ [

## 转换为 IMDSv2 的工具
](#tools-for-transitioning-to-imdsv2)
+ [

## 要求 IMDSv2 的建议途径
](#recommended-path-for-requiring-imdsv2)

## 转换为 IMDSv2 的工具
<a name="tools-for-transitioning-to-imdsv2"></a>

以下工具可以帮助您识别、监控和管理软件从 imdsv1 到 imdsv2 的转换。有关如何使用这些工具的说明，请参阅[要求 IMDSv2 的建议途径](#recommended-path-for-requiring-imdsv2)。

**AWS 软件**  
最新版本的 AWS CLI 和 AWS SDK 均支持 IMDSv2。要使用 IMDSv2，请更新 EC2 实例以使用最新版本。有关支持 IMDSv2 的最低 AWS 开发工具包版本，请参阅 [使用支持的 AWS 开发工具包](configuring-instance-metadata-service.md#use-a-supported-sdk-version-for-imdsv2)。  
所有的 Amazon Linux 2 和 Amazon Linux 2023 软件包都支持 IMDSv2。Amazon Linux 2023 默认禁用 IMDSv1。

**IMDS Packet Analyzer**  
IMDS Packet Analyzer 是一个开源工具，用于识别和记录您的实例启动阶段和运行时阶段的 IMDSv1 调用。通过分析这些日志，您可以精确地识别对您的实例进行 imdsv1 调用的软件，并确定需要更新哪些内容以仅在您的实例上支持 IMDSv2。您可以从命令行运行 IMDS Packet Analyzer，也可以将其作为服务安装。有关更多信息，请参阅 *GitHub* 上的 [AWS ImdsPacketAnalyzer](https://github.com/aws/aws-imds-packet-analyzer)。

**CloudWatch**  
CloudWatch 提供以下两个指标来监控实例：  
`MetadataNoToken`：IMDSv2 使用由令牌支持的会话，而 IMDSv1 不使用。`MetadataNoToken` 指标跟踪对使用 IMDSv1 的实例元数据服务（IMDS）的调用次数。通过查看该指标是否为零，您可以确定是否以及何时将所有软件升级为使用 IMDSv2。  
`MetadataNoTokenRejected`：禁用 IMDSv1 后，您可以使用 `MetadataNoTokenRejected` 指标来跟踪 IMDSv1 调用被尝试和拒绝的次数。通过跟踪该指标，您可以确定您的软件是否需要更新以使用 IMDSv2。  
对于每个 EC2 实例，这些指标是互斥的。启用 IMDSV1 (`httpTokens = optional`) 后，将仅会发出 `MetadataNoToken`。禁用 IMDSV1 (`httpTokens = required`) 后，将仅会发出 `MetadataNoTokenRejected`。有关何时该使用这些指标，请参阅[要求 IMDSv2 的建议途径](#recommended-path-for-requiring-imdsv2)。  
有关更多信息，请参阅 [实例指标](viewing_metrics_with_cloudwatch.md#ec2-cloudwatch-metrics)。

**启动 API**  
**新实例：**使用 [RunInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RunInstances.html) API 启动要求必须使用 IMDSv2 的新实例。有关更多信息，请参阅 [为新实例配置实例元数据选项](configuring-IMDS-new-instances.md)。  
**现有实例：**使用 [ModifyInstanceMetadataOptions](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_ModifyInstanceMetadataOptions.html) API 要求必须在现有实例上使用 IMDSv2。有关更多信息，请参阅 [为现有实例修改实例元数据选项](configuring-IMDS-existing-instances.md)。  
**自动扩缩组启动的新实例：**要规定必须在自动扩缩组启动的所有新实例上使用 IMDSv2，您的自动扩缩组可以使用启动模板或启动配置。当您[创建启动模板](https://docs.aws.amazon.com/cli/latest/reference/ec2/create-launch-template.html)或[创建启动配置](https://docs.aws.amazon.com/cli/latest/reference/autoscaling/create-launch-configuration.html)时，必须配置 `MetadataOptions` 参数以要求使用 IMDSv2。自动扩缩组将使用新的启动模板或启动配置来启动新实例，但现有实例不受影响。  
**自动扩缩组中的现有实例：**使用 [ModifyInstanceMetadataOptions](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_ModifyInstanceMetadataOptions.html) API 要求必须在现有实例上使用 IMDSv2，也可终止实例，然后由自动扩缩组使用在新启动模板或启动配置中定义的实例元数据选项设置启动新的替换实例。

**AMI**  
将 `ImdsSupport` 参数设置为 `v2.0` 的 AMI 将启动默认需要 imdsv2 的实例。Amazon Linux 2023 配置了 `ImdsSupport = v2.0`。  
**新 AMI：**创建新 AMI 时，使用 [register-image](https://docs.aws.amazon.com/cli/latest/reference/ec2/register-image.html) CLI 命令将 `ImdsSupport` 参数设置为 `v2.0`。  
**现有 AMI：**修改现有 AMI 时，使用 [modify-image-attribute](https://docs.aws.amazon.com/cli/latest/reference/ec2/modify-image-attribute.html) CLI 命令将 `ImdsSupport` 参数设置为 `v2.0`。  
有关更多信息，请参阅 [配置 AMI](configuring-IMDS-new-instances.md#configure-IMDS-new-instances-ami-configuration)。

**账户级别控制**  
可以在账户级别配置所有实例元数据选项的默认值。启动实例时将会自动应用默认值。有关更多信息，请参阅[将 IMDSv2 设置为账户默认设置](configuring-IMDS-new-instances.md#set-imdsv2-account-defaults)。  
您也可以在账户级别强制要求使用 IMDSv2。启用 IMDSv2 强制使用后：  
+ **新实例：**配置为在启动时启用 IMDSv1 的实例将会启动失败
+ **已禁用 IMDSv1 的现有实例：**将阻止尝试在现有实例上启用 IMDSv1。
+ **已启用 IMDSv1 的现有实例：**已启用 IMDSv1 的现有实例不受影响。
有关更多信息，请参阅 [在账户级别强制使用 IMDSv2](configuring-IMDS-new-instances.md#enforce-imdsv2-at-the-account-level)。

**IAM policy 和 SCP**  
您可以使用 IAM policy 或 AWS Organizations 服务控制策略（SCP）来控制用户，具体如下所示：  
+ 除非将实例配置为使用 IMDSv2，否则无法使用 [RunInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RunInstances.html) API 启动实例。
+ 无法通过使用 [ModifyInstanceMetadataOptions](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_ModifyInstanceMetadataOptions.html) API 修改正在运行的实例来重新启用 IMDSv1。
IAM policy 或 SCP 必须包含以下 IAM 条件键：  
+ `ec2:MetadataHttpEndpoint`
+ `ec2:MetadataHttpPutResponseHopLimit`
+ `ec2:MetadataHttpTokens`
如果 API 或 CLI 调用中的参数与包含该条件键的策略中指定的状态不一致，则 API 或 CLI 调用将失败并显示 `UnauthorizedOperation` 响应。  
此外，您还可以选择额外的保护层以强制从 IMDSv1 更改为 IMDSv2。在与通过 EC2 角色凭证调用的 API 相关的访问管理层上，您可以在 IAM 策略或 AWS Organizations 服务控制策略（SCP）中使用条件键。具体来说，通过在 IAM policy 中使用值为 `ec2:RoleDelivery` 的条件键 `2.0`，使用从 IMDSv1 获取的 EC2 角色凭证进行的 API 调用将会收到 `UnauthorizedOperation` 响应。通过使用 SCP 所需的该条件，可以更广泛地实现相同的效果。这会确保通过 IMDSv1 提供的凭证不能实际用于调用 API，因为任何不符合指定条件的 API 调用将会收到 `UnauthorizedOperation` 错误。  
有关示例 IAM policies，请参阅 [使用实例元数据](ExamplePolicies_EC2.md#iam-example-instance-metadata)。有关 SCP 的更多信息，请参阅《AWS Organizations User Guide》**中的 [Service control policies](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html)。

**声明性策略**  
使用声明性策略（AWS Organizations 的一项功能）为整个组织集中设置 IMDS 账户默认值，包括 IMDSv2 强制使用。有关示例策略，请参阅《AWS Organizations 用户指南》中 [Supported declarative policies](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_declarative_syntax.html#declarative-policy-examples) 部分的**实例元数据**选项卡**。

## 要求 IMDSv2 的建议途径
<a name="recommended-path-for-requiring-imdsv2"></a>

**Topics**
+ [

### 步骤1：识别 IMDSv2=optional 的实例，并审核 imdsV1 使用情况
](#path-step-1)
+ [

### 步骤 2：将软件更新为 IMDSv2
](#path-step-2)
+ [

### 步骤 3：在实例上要求 IMDSv2
](#path-step-3)
+ [

### 步骤 4：将 IMDSv2=required 设置为默认值
](#path-step-4)
+ [

### 步骤 5：强制实例要求 IMDSv2
](#path-step-5)

### 步骤1：识别 IMDSv2=optional 的实例，并审核 imdsV1 使用情况
<a name="path-step-1"></a>

要评测 IMDSv2 迁移范围，请识别配置为允许 IMDSv1 或 IMDSv2 的实例，并审核 imdsv1 调用。

1. **识别配置为允许 IMDSv1 或 IMDSv2 的实例：**

------
#### [ Amazon EC2 console ]

   1. 通过以下网址打开 Amazon EC2 控制台：[https://console.aws.amazon.com/ec2/](https://console.aws.amazon.com/ec2/)。

   1. 在导航窗格中，选择 **Instances (实例)**。

   1. 要仅查看配置为允许 IMDSv1 或 IMDSv2 的实例，请添加筛选条件 **IMDSv2 = optional**。

   1. 或者，要查看 IMDSv2 对于所有实例是 **optional** 还是 **required**，请打开**首选项**窗口（齿轮图标），打开 **IMDSv2**，然后选择**确认**。这会将 **IMDSv2** 列添加到**实例**表中。

------
#### [ AWS CLI ]

   使用 [describe-instances](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/modify-instance-metadata-options.html) 命令并按 `metadata-options.http-tokens = optional` 进行筛选，如下所示：

   ```
   aws ec2 describe-instances --filters "Name=metadata-options.http-tokens,Values=optional" --query "Reservations[*].Instances[*].[InstanceId]" --output text
   ```

------

1. **审核每个实例上的 IMDSv1 调用：**

   使用 CloudWatch 指标 `MetadataNoToken`。此指标显示对实例上 IMDS 的 IMDSv1 调用次数。有关更多信息，请参阅[实例指标](https://docs.aws.amazon.com/en_us/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.html#ec2-cloudwatch-metrics)。

1. **识别您的实例上进行 IMDSv1 调用的软件：**

   使用开源 [IMDS Packet Analyzer](https://github.com/aws/aws-imds-packet-analyzer) 在实例启动阶段和运行时操作期间识别和记录 IMDSv1调用。使用此信息确定要更新的软件，以使您的实例准备好仅使用 IMDSv2。您可以从命令行运行 IMDS Packet Analyzer，也可以将其作为服务安装。

### 步骤 2：将软件更新为 IMDSv2
<a name="path-step-2"></a>

将在您的实例上使用角色凭证的所有 SDK、CLI 和软件更新为与 IMDSv2 兼容的版本。有关更新 CLI 的更多信息，请参阅《AWS Command Line Interface 用户指南》**中的[安装或更新最新版本的 AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)。

### 步骤 3：在实例上要求 IMDSv2
<a name="path-step-3"></a>

在通过 `MetadataNoToken` 指标确认零个 IMDSv1 调用后，请将现有实例配置为需要 IMDSv2。此外，将所有新实例配置为需要 IMDSv2。换句话说，在所有现有实例和新实例上禁用 IMDSv1。

1. **将现有实例配置为需要 IMDSv2：**

------
#### [ Amazon EC2 console ]

   1. 通过以下网址打开 Amazon EC2 控制台：[https://console.aws.amazon.com/ec2/](https://console.aws.amazon.com/ec2/)。

   1. 在导航窗格中，选择 **Instances (实例)**。

   1. 选择实例。

   1. 依次选择**操作**、**实例设置**、**修改实例元数据选项**。

   1. 对于**IMDSv2**，选择**必需**。

   1. 选择**保存**。

------
#### [ AWS CLI ]

   使用 [modify-instance-metadata-options](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/modify-instance-metadata-options.html) CLI 命令指定仅使用 IMDSv2。

------
**注意**  
您可以在正在运行的实例上修改此设置。此更改立即生效，无需重启实例。

   有关更多信息，请参阅 [要求使用 IMDSv2](configuring-IMDS-existing-instances.md#modify-require-IMDSv2)。

1. **禁用 IMDSv1 后监控是否存在问题：**

   1. 使用 CloudWatch 指标 `MetadataNoTokenRejected` 跟踪 IMDSv1 调用尝试次数以及被拒绝的次数。

   1. 如果 `MetadataNoTokenRejected` 指标记录了遇到软件问题的实例上的 IMDSv1 调用，则表明该软件需要更新才能使用 IMDSv2。

1. **将新实例配置为需要 IMDSv2：**

------
#### [ Amazon EC2 console ]

   1. 通过以下网址打开 Amazon EC2 控制台：[https://console.aws.amazon.com/ec2/](https://console.aws.amazon.com/ec2/)。

   1. 按照以下步骤[启动实例](ec2-launch-instance-wizard.md)。

   1. 展开**高级详细信息**，对于**元数据版本**，选择**仅 V2（需要令牌）**。

   1. 在 **Summary**（摘要）面板中查看实例配置，然后选择 **Launch instance**（启动实例）。

      有关更多信息，请参阅 [在启动时配置实例](configuring-IMDS-new-instances.md#configure-IMDS-new-instances-instance-settings)。

------
#### [ AWS CLI ]

   AWS CLI：使用 [run-instances](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/run-instances.html) 命令并指定需要使用 IMDSv2。

------

### 步骤 4：将 IMDSv2=required 设置为默认值
<a name="path-step-4"></a>

您可以将 IMDSv2=required 设置为账户或组织级别的默认配置。这确保所有新启动的实例都自动配置为需要 IMDSv2。

1. **设置账户级别默认值：**

------
#### [ Amazon EC2 console ]

   1. 通过以下网址打开 Amazon EC2 控制台：[https://console.aws.amazon.com/ec2/](https://console.aws.amazon.com/ec2/)。

   1. 在导航窗格中，选择**控制面板**。

   1. 在**账户属性**卡的**设置**下，选择**数据保护和安全**。

   1. 在 **IMDS 默认值**下，选择**管理**。

   1. 对于**实例元数据服务**，选择**启用**。

   1. 对于**元数据版本**，选择**仅 V2（需要令牌）**。

   1. 选择**更新**。

------
#### [ AWS CLI ]

   使用 [modify-instance-metadata-defaults](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/modify-instance-metadata-defaults.html) CLI 命令并指定 `--http-tokens required` 和 `--http-put-response-hop-limit 2`。

------

   有关更多信息，请参阅 [将 IMDSv2 设置为账户默认设置](configuring-IMDS-new-instances.md#set-imdsv2-account-defaults)。

1. **或者，使用声明性策略设置组织级别默认值：**

   使用声明性策略将 IMDSv2 的组织默认值为 required。有关示例策略，请参阅《AWS Organizations 用户指南》中 [Supported declarative policies](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_declarative_syntax.html#declarative-policy-examples) 部分的**实例元数据**选项卡**。

### 步骤 5：强制实例要求 IMDSv2
<a name="path-step-5"></a>

确认没有任何实例依赖 IMDSv1 后，我们建议您在所有新实例上强制使用 IMDSv2。

使用以下选项之一来强制使用 IMDSv2：

1. **使用账户属性强制使用 IMDSv2**

   可以在账户级别为每个 AWS 区域强制要求使用 IMDSv2。强制使用后，实例只有配置为必须使用 IMDSv2 时才能启动。无论实例配置或 AMI 配置如何，都必须遵守此强制使用要求。有关更多信息，请参阅 [在账户级别强制使用 IMDSv2](configuring-IMDS-new-instances.md#enforce-imdsv2-at-the-account-level)。要在组织级别应用此设置，请设置声明性策略。有关示例策略，请参阅《AWS Organizations 用户指南》中 [Supported declarative policies](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_declarative_syntax.html#declarative-policy-examples) 部分的**实例元数据**选项卡**。

   要防止强制使用被撤销，应使用 IAM 策略来阻止对 [ModifyInstanceMetadataDefaults](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_ModifyInstanceMetadataDefaults.html) API 对访问。有关更多信息，请参阅 [使用 IAM policy](configuring-IMDS-new-instances.md#configure-IMDS-new-instances-iam-policy)。
**注意**  
此设置不会更改现有实例的 IMDS 版本，但会阻止在当前已禁用 IMDSv1 的现有实例上启用 IMDSv1。
**警告**  
如果启用了 IMDSv2 强制使用，但未在启动时的实例配置中或在账户设置或 AMI 配置中将 `httpTokens` 设置为 `required`，则实例启动将会失败。有关问题排查信息，请参阅[启动启用 IMDSv1 的实例时失败](troubleshooting-launch.md#launching-an-imdsv1-enabled-instance-fails)。

1. **也可使用以下 IAM 或 SCP 条件键强制使用 IMDSv2：**
   + `ec2:MetadataHttpTokens`
   + `ec2:MetadataHttpPutResponseHopLimit`
   + `ec2:MetadataHttpEndpoint`

   这些条件键控制 [RunInstances](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RunInstances.html) 和 [ModifyInstanceMetadataOptions](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_ModifyInstanceMetadataOptions.html) API 及相应 CLI 的使用。如果创建了策略，并且 API 调用中的参数与使用条件键的策略中指定的状态不匹配，API 或 CLI 调用将失败并显示 `UnauthorizedOperation` 响应。

   有关示例 IAM policies，请参阅 [使用实例元数据](ExamplePolicies_EC2.md#iam-example-instance-metadata)。

# 限制访问实例元数据服务
<a name="instance-metadata-limiting-access"></a>

您可以考虑使用本地防火墙规则，以禁止从某些或所有进程中访问实例元数据服务（IMDS）。

对于[基于 Nitro 的实例](instance-types.md#instance-hypervisor-type)，如果 VPC 内的网络设备（例如虚拟路由器）会将数据包转发到 IMDS 地址，且实例的默认[源/目标检查](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_NAT_Instance.html#EIP_Disable_SrcDestCheck)已被禁用，则可以从您自己的网络访问 IMDS。要防止来自 VPC 外的源访问 IMDS，建议您修改网络设备的配置，丢弃目标 IPv4 地址为 IMDS `169.254.169.254` 的数据包，如果您启用了 IPv6 端点，则丢弃目标 IPv6 地址为 IMDS `[fd00:ec2::254]` 的数据包。

## 限制 Linux 实例的 IMDS 访问
<a name="instance-metadata-limiting-access-linux"></a>

**使用 iptables 限制访问**

以下示例使用 Linux iptables 及其 `owner` 模块禁止 Apache Web 服务器（基于其默认安装用户 ID `apache`）访问 169.254.169.254。它使用*拒绝规则* 拒绝来自以该用户身份运行的任何进程的所有实例元数据请求（无论是 IMDSv1 还是 IMDSv2）。

```
$ sudo iptables --append OUTPUT --proto tcp --destination 169.254.169.254 --match owner --uid-owner apache --jump REJECT
```

或者，您可以考虑使用*允许规则* 以仅允许特定用户或组进行访问。从安全的角度看，允许规则可能更易于管理，因为它们要求您决定哪种软件需要访问实例元数据。如果使用*允许规则*，在您以后更改实例上的软件或配置时，不太可能会意外允许软件访问元数据服务（您不打算让该软件进行访问）。您还可以将组与允许规则结合使用，以便您可以在允许的组中添加和删除用户，而无需更改防火墙规则。

以下示例禁止所有进程访问 IMDS，但在用户账户 `trustworthy-user` 中运行的进程除外。

```
$ sudo iptables --append OUTPUT --proto tcp --destination 169.254.169.254 --match owner ! --uid-owner trustworthy-user --jump REJECT
```

**注意**  
要使用本地防火墙规则，您需要修改前面的示例命令以符合您的需求。
默认情况下，不会在系统重新引导之间持久保留 iptables 规则。可以使用此处未介绍的操作系统功能持久保留这些规则。
只有在组是给定本地用户的主要组时，iptables `owner` 模块才会匹配组成员资格。不会匹配其他组。

**使用 PF 或 IPFW 限制访问**

如果使用 FreeBSD 或 OpenBSD，则还可以考虑使用 PF 或 IPFW。以下示例将 IMDS 访问限制为仅根用户。

**PF**

```
$ block out inet proto tcp from any to 169.254.169.254
```

```
$ pass out inet proto tcp from any to 169.254.169.254 user root
```

**IPFW**

```
$ allow tcp from any to 169.254.169.254 uid root
```

```
$ deny tcp from any to 169.254.169.254
```

**注意**  
PF 和 IPFW 命令的顺序至关重要。PF 默认为最后一个匹配规则，而 IPFW 默认为第一个匹配规则。

## 限制 Windows 实例的 IMDS 访问
<a name="instance-metadata-limiting-access-windows"></a>

**使用 Windows 防火墙限制访问**

以下 PowerShell 示例使用内置的 Windows 防火墙禁止 Internet Information Server Web 服务器（基于其默认安装用户 ID `NT AUTHORITY\IUSR`）访问 169.254.169.254。它使用*拒绝规则* 拒绝来自以该用户身份运行的任何进程的所有实例元数据请求（无论是 IMDSv1 还是 IMDSv2）。

```
PS C:\> $blockPrincipal = New-Object -TypeName System.Security.Principal.NTAccount ("NT AUTHORITY\IUSR")
PS C:\> $BlockPrincipalSID = $blockPrincipal.Translate([System.Security.Principal.SecurityIdentifier]).Value
PS C:\> $BlockPrincipalSDDL = "D:(A;;CC;;;$BlockPrincipalSID)"
PS C:\> New-NetFirewallRule -DisplayName "Block metadata service from IIS" -Action block -Direction out `
-Protocol TCP -RemoteAddress 169.254.169.254 -LocalUser $BlockPrincipalSDDL
```

或者，您可以考虑使用*允许规则* 以仅允许特定用户或组进行访问。从安全的角度看，允许规则可能更易于管理，因为它们要求您决定哪种软件需要访问实例元数据。如果使用*允许规则*，在您以后更改实例上的软件或配置时，不太可能会意外允许软件访问元数据服务（您不打算让该软件进行访问）。您还可以将组与允许规则结合使用，以便您可以在允许的组中添加和删除用户，而无需更改防火墙规则。

以下示例禁止作为 `blockPrincipal` 变量中指定的操作系统组（在该示例中为 Windows 组 `Everyone`）运行的所有进程访问实例元数据，但在 `exceptionPrincipal` 中指定的进程除外（在该示例中为名为 `trustworthy-users` 的组）。您必须同时指定拒绝委托人和允许委托人，因为与 Linux iptables 中的 `! --uid-owner trustworthy-user` 规则不同，Windows 防火墙不提供拒绝所有其他委托人以仅允许特定委托人（用户或组）的快捷方法。

```
PS C:\> $blockPrincipal = New-Object -TypeName System.Security.Principal.NTAccount ("Everyone")
PS C:\> $BlockPrincipalSID = $blockPrincipal.Translate([System.Security.Principal.SecurityIdentifier]).Value
PS C:\> $exceptionPrincipal = New-Object -TypeName System.Security.Principal.NTAccount ("trustworthy-users")
PS C:\> $ExceptionPrincipalSID = $exceptionPrincipal.Translate([System.Security.Principal.SecurityIdentifier]).Value
PS C:\> $PrincipalSDDL = "O:LSD:(D;;CC;;;$ExceptionPrincipalSID)(A;;CC;;;$BlockPrincipalSID)"
PS C:\> New-NetFirewallRule -DisplayName "Block metadata service for $($blockPrincipal.Value), exception: $($exceptionPrincipal.Value)" -Action block -Direction out `
-Protocol TCP -RemoteAddress 169.254.169.254 -LocalUser $PrincipalSDDL
```

**注意**  
要使用本地防火墙规则，您需要修改前面的示例命令以符合您的需求。

**使用 netsh 规则限制访问**

您可以考虑使用 `netsh` 规则阻止所有软件，但这些规则不太灵活。

```
C:\> netsh advfirewall firewall add rule name="Block metadata service altogether" dir=out protocol=TCP remoteip=169.254.169.254 action=block
```

**注意**  
要使用本地防火墙规则，您需要修改前面的示例命令以符合您的需求。
必须从提升权限的命令提示符中设置 `netsh` 规则，并且不能将其设置为拒绝或允许特定委托人。

# 配置实例元数据服务选项
<a name="configuring-instance-metadata-options"></a>

实例元数据服务（IMDS）在每个 EC2 实例上本地运行。*实例元数据选项*是一组配置，可用于控制 EC2 实例上 IMDS 的可访问性和行为。

可在每个实例上配置以下实例元数据选项：

**实例元数据服务（IMDS）**：`enabled` \$1 `disabled`  
可在实例上启用或禁用 IMDS。禁用后，您或任何代码都将无法访问实例上的实例元数据。  
实例上的 IMDS 有两个端点：IPv4 (`169.254.169.254`) 和 IPv6 (`[fd00:ec2::254]`)。启用 IMDS 时，会自动启用 IPv4 端点。若要启用 IPv6 端点，需将其显式启用。

**IMDS IPv6 端点**：`enabled` \$1 `disabled`  
可在实例上显式启用 IPv6 IMDS 端点。启用 IPv6 端点后，IPv4 端点将保持启用状态。IPv6 端点仅在[支持 IPv6 的子网](https://docs.aws.amazon.com/vpc/latest/userguide/configure-subnets.html#subnet-ip-address-range)（双栈或仅 IPv6）中[基于 Nitro 的实例](instance-types.md#instance-hypervisor-type)上受支持。

**元数据版本**：`IMDSv1 or IMDSv2 (token optional)` \$1 `IMDSv2 only (token required)`  
请求实例元数据时，IMDSv2 调用需要令牌。IMDSv1 调用不需要令牌。可将实例配置为允许调用 IMDSv1 或 IMDSv2（可以使用令牌），或者仅允许调用 IMDSv2（必须使用令牌）。

**元数据响应跃点限制**：`1` – `64`  
跃点限制是允许进行 PUT 响应的网络跃点数。可以设置跃点限制，最小值为 `1`，最大值为 `64`。在容器环境中，跃点限制 `1` 可能会导致问题。有关如何缓解这些问题的信息，请参阅[实例元数据访问注意事项](instancedata-data-retrieval.md#imds-considerations)下方有关容器环境的信息。

**访问实例元数据中的标签**：`enabled` \$1 `disabled`  
可以启用或禁用从实例元数据访问实例标签。有关更多信息，请参阅 [使用实例元数据来查看 EC2 实例的标签](work-with-tags-in-IMDS.md)。

要查看实例的当前配置，请参阅 [查询现有实例的实例元数据选项](instancedata-data-retrieval.md#query-IMDS-existing-instances)。

## 在何处配置实例元数据选项
<a name="where-to-configure-instance-metadata-options"></a>

可以在不同级别配置实例元数据选项，如下所示：
+ **账户**：可以在账户级别为每个 AWS 区域 设置实例元数据选项的默认值。启动实例后，实例元数据选项会自动设置为账户级别的值。您可以在启动后更改这些值。账户级别的默认值不会影响现有实例。
+ **AMI**：注册或修改 AMI 时，可将 `imds-support` 参数设置为 `v2.0`。使用此 AMI 启动实例后，实例元数据版本会自动设置为 IMDSv2，并且跃点限制会设置为 2。
+ **实例**：可以在启动实例时，更改实例上的所有实例元数据选项，从而覆盖默认设置。也可以在正在运行或已停止的实例上启动后，再更改实例元数据选项。请注意，更改可能受到 IAM 或 SCP 策略的限制。

有关更多信息，请参阅[为新实例配置实例元数据选项](configuring-IMDS-new-instances.md)和[为现有实例修改实例元数据选项](configuring-IMDS-existing-instances.md)。

## 实例元数据选项的优先顺序
<a name="instance-metadata-options-order-of-precedence"></a>

每个实例元数据选项的值都会在启动实例时按照优先级分层顺序确定。分层顺序如下，按最高优先级从上至下依次排序：
+ **优先级 1：启动时的实例配置**：可以在启动模板或实例配置中指定值。此处指定的任何值都会覆盖在账户级别或 AMI 中指定的值。
+ **优先级 2：账户设置**：如果启动实例时未指定值，则该值将根据账户级别的设置（针对每个 AWS 区域 进行设置）确定。账户级别设置通常会包含各个元数据选项的值，或者不会指示任何首选项。
+ **优先级 3：AMI 配置**：如果启动实例时未指定值或账户级别设置未确定值，则该值将根据 AMI 配置确定。这适用于 `HttpTokens` 和 `HttpPutResponseHopLimit`。

每个元数据选项都将分开评估。可以通过组合使用直接实例配置、账户级别默认设置和 AMI 配置，配置实例。

在正在运行或已停止的实例上启动后，可以更改任何元数据选项的值，除非更改受到 IAM 或 SCP 策略的限制。

**注意**  
首先需要根据优先顺序确定好实例的 IMDS 设置之后，才会评估账户级别 IMDSv2 强制使用设置。启用 IMDSv2 强制使用后，使用 IMDSv1 启用的实例将会失败。有关强制使用的更多信息，请参阅[在账户级别强制使用 IMDSv2](configuring-IMDS-new-instances.md#enforce-imdsv2-at-the-account-level)。

**警告**  
如果启用了 IMDSv2 强制使用，但未在启动时的实例配置中或在账户设置或 AMI 配置中将 `httpTokens` 设置为 `required`，则启动将会失败。

**示例 1 – 确定元数据选项的值**

在此示例中，EC2 实例会启动到一个区域中，其中 `HttpPutResponseHopLimit` 在账户级别设置为 `1`。指定 AMI 会将 `ImdsSupport` 设置为 `v2.0`。启动时不会直接在实例上指定元数据选项。该实例通过以下元数据选项启动：

```
"MetadataOptions": {
    ...
    "HttpTokens": "required",
    "HttpPutResponseHopLimit": 1,
    ...
```

这些值如下所示确定：
+ **启动时未指定元数据选项：**实例启动期间，实例启动参数或启动模板中均未提供元数据选项的特定值。
+ **账户设置优先级次之：**如果启动时未指定特定值，则会优先应用区域内的账户级别设置。这意味着将应用账户级别配置的默认值。在本例中，`HttpPutResponseHopLimit` 设置为 `1`。
+ **AMI 设置优先级最低：**如果启动时或账户级别未指定 `HttpTokens`（实例元数据版本）的特定值，则应用 AMI 设置。在本例中，由 AMI 设置 `ImdsSupport: v2.0` 确定将 `HttpTokens` 设置为 `required`。请注意，虽然 AMI 设置 `ImdsSupport: v2.0` 旨在设置 `HttpPutResponseHopLimit: 2`，但其被账户级别设置 `HttpPutResponseHopLimit: 1` 覆盖，而后者的优先级更高。

**示例 2 – 确定元数据选项的值**

在此示例中，使用与前面示例 1 中相同的设置启动 EC2 实例，不过启动时直接在实例上将 `HttpTokens` 设置为 `optional`。该实例通过以下元数据选项启动：

```
"MetadataOptions": {
    ...
    "HttpTokens": "optional",
    "HttpPutResponseHopLimit": 1,
    ...
```

`HttpPutResponseHopLimit` 的值的确定方式与示例 1 中相同。但是，`HttpTokens` 的值按以下方式确定：启动时在实例上配置的元数据选项优先。即使 AMI 配置了 `ImdsSupport: v2.0`（也就是 `HttpTokens` 设置为 `required`），启动时在实例上指定的值（`HttpTokens` 设置为 `optional`）仍优先。

**示例 3 – 在启用 HttpTokensEnforced 的情况下确定元数据选项的值**

在此示例中，该账户在该区域中的设置为 `HttpTokens = required` 和 `HttpTokensEnforced = enabled`。

考虑以下 EC2 实例启动尝试：
+ 在将 `HttpTokens` 设置为 `optional` 的情况下尝试启动：启动将会失败，因为启用了账户级别强制使用 (`HttpTokensEnforced = enabled`)，并且启动参数的优先级高于账户默认设置。
+ 在将 `HttpTokens` 设置为 `required` 的情况下尝试启动：启动将会成功，因为它符合账户级别强制使用的要求。
+ 在未指定 `HttpTokens` 值的情况下尝试启动：启动将会成功，因为根据账户设置，该值默认为 `required`。

### 设置实例元数据版本
<a name="metadata-version-order-of-precedence"></a>

实例启动时，实例*元数据版本*的值为 **IMDSv1 或 IMDSv2（令牌可选）**(`httpTokens=optional`) 或**仅限 IMDSv2（需要令牌）(`httpTokens=required`)**。

实例启动时，您可以手动指定元数据版本的值，也可以使用默认值。如果手动指定该值，则将覆盖所有默认值。如果不手动指定该值，则该值将由默认设置的组合确定。

以下流程图显示了不同配置级别的设置如何确定实例启动时的元数据版本以及强制使用的评估位置。下表列举了每个级别的具体设置。

![\[显示实例元数据版本和 IMDSv2 强制使用评估点的流程图。\]](http://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/images/imds-defaults-launch-flow.png)


该表显示了不同配置级别的设置如何确定启动实例时的元数据版本（由第 4 列中**生成的实例配置**指示）。优先级顺序如下所示，从左到右，第一列优先级最高：
+ 第 1 列：**启动参数**：表示启动时手动指定的实例设置。
+ 第 2 列：**账户级别默认设置**：表示账户设置。
+ 第 3 列：**AMI 默认设置**：表示 AMI 设置。


| 启动参数 | 默认账户级别 | 默认 AMI | 生成的实例配置 | 
| --- | --- | --- | --- | 
| 仅 V2（需要令牌） | 无首选项 | 仅 V2 | 仅 V2 | 
| 仅 V2（需要令牌） | 仅 V2 | 仅 V2 | 仅 V2 | 
| 仅 V2（需要令牌） | V1 或 V2 | 仅 V2 | 仅 V2 | 
| V1 或 V2（可以使用令牌） | 无首选项 | 仅 V2 | V1 或 V2 | 
| V1 或 V2（可以使用令牌） | 仅 V2 | 仅 V2 | V1 或 V2 | 
| V1 或 V2（可以使用令牌） | V1 或 V2 | 仅 V2 | V1 或 V2 | 
| 未设置 | 无首选项 | 仅 V2 | 仅 V2 | 
| 未设置 | 仅 V2 | 仅 V2 | 仅 V2 | 
| 未设置 | V1 或 V2 | 仅 V2 | V1 或 V2 | 
| 仅 V2（需要令牌） | 无首选项 | null | 仅 V2 | 
| 仅 V2（需要令牌） | 仅 V2 | null | 仅 V2 | 
| 仅 V2（需要令牌） | V1 或 V2 | null | 仅 V2 | 
| V1 或 V2（可以使用令牌） | 无首选项 | null | V1 或 V2 | 
| V1 或 V2（可以使用令牌） | 仅 V2 | null | V1 或 V2 | 
| V1 或 V2（可以使用令牌） | V1 或 V2 | null | V1 或 V2 | 
| 未设置 | 无首选项 | null | V1 或 V2 | 
| 未设置 | 仅 V2 | null | 仅 V2 | 
| 未设置 | V1 或 V2 | null | V1 或 V2 | 

## 使用 IAM 条件键限制实例元数据选项
<a name="iam-condition-keys-and-imds"></a>

可以在 IAM 策略或 SCP 中使用 IAM 条件键，如下所示：
+ 仅在实例配置为要求使用 IMDSv2 时允许实例启动
+ 限制允许的跃点数
+ 关闭对实例元数据的访问

**Topics**
+ [

## 在何处配置实例元数据选项
](#where-to-configure-instance-metadata-options)
+ [

## 实例元数据选项的优先顺序
](#instance-metadata-options-order-of-precedence)
+ [

## 使用 IAM 条件键限制实例元数据选项
](#iam-condition-keys-and-imds)
+ [

# 为新实例配置实例元数据选项
](configuring-IMDS-new-instances.md)
+ [

# 为现有实例修改实例元数据选项
](configuring-IMDS-existing-instances.md)

**注意**  
在进行任何更改之前，您应谨慎执行操作并进行仔细的测试。记录以下内容：  
如果您强制使用 IMDSv2，则使用 IMDSv1 访问实例元数据的应用程序或代理将会中断。
如果禁用对实例元数据的所有访问，则依赖于实例元数据访问才能正常工作的应用程序或代理将会中断。
对于 IMDSv2，在检索令牌时必须使用 `/latest/api/token`。
（仅限 Windows）如果您的 PowerShell 版本早于 4.0，则必须[更新到 Windows Management Framework 4.0](https://devblogs.microsoft.com/powershell/windows-management-framework-wmf-4-0-update-now-available-for-windows-server-2012-windows-server-2008-r2-sp1-and-windows-7-sp1/) 才能要求使用 IMDSv2。

# 为新实例配置实例元数据选项
<a name="configuring-IMDS-new-instances"></a>

可为新实例配置以下实例元数据选项。

**Topics**
+ [

## 要求使用 IMDSv2
](#configure-IMDS-new-instances)
+ [

## 启用 IMDS IPv4 和 IPv6 端点
](#configure-IMDS-new-instances-ipv4-ipv6-endpoints)
+ [

## 关闭对实例元数据的访问
](#configure-IMDS-new-instances--turn-off-instance-metadata)
+ [

## 允许访问实例元数据中的标签
](#configure-IMDS-new-instances-tags-in-instance-metadata)

**注意**  
这些选项的设置在账户级别配置，可以直接在账户中配置，也可以使用声明式策略进行配置。必须在要配置实例元数据选项的每个 AWS 区域中对选项进行配置。使用声明式策略允许同时将设置应用于多个区域，也可以同时应用于多个账户。当使用声明式策略时，您无法直接在账户中修改设置。本主题介绍如何直接在账户中配置设置。有关使用声明式策略的信息，请参阅《AWS Organizations User Guide》**中的 [Declarative policies](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_declarative.html)。

## 要求使用 IMDSv2
<a name="configure-IMDS-new-instances"></a>

可以使用以下方法要求在新实例上使用 IMDSv2。

**Topics**
+ [

### 将 IMDSv2 设置为账户默认设置
](#set-imdsv2-account-defaults)
+ [

### 在账户级别强制使用 IMDSv2
](#enforce-imdsv2-at-the-account-level)
+ [

### 在启动时配置实例
](#configure-IMDS-new-instances-instance-settings)
+ [

### 配置 AMI
](#configure-IMDS-new-instances-ami-configuration)
+ [

### 使用 IAM policy
](#configure-IMDS-new-instances-iam-policy)

### 将 IMDSv2 设置为账户默认设置
<a name="set-imdsv2-account-defaults"></a>

可以在账户级别为每个 AWS 区域 设置实例元数据服务（IMDS）的默认版本。这意味着在启动*新*实例后，实例元数据版本会自动设置为该账户级别的默认值。但是，您可以在启动实例时或启动实例后手动覆盖该值。有关账户级别设置和手动覆盖会如何影响实例的更多信息，请参阅 [实例元数据选项的优先顺序](configuring-instance-metadata-options.md#instance-metadata-options-order-of-precedence)。

**注意**  
设置账户级别的默认值不会重置*现有的*实例。例如，假设您将账户级别的默认值设置为 IMDSv2，则任何设置为 IMDSv1 的现有实例都不会受到影响。如果要更改现有实例的值，则必须手动更改相关实例本身的值。

您可以将实例元数据版本的账户默认值设置为 IMDSv2，这样账户中的所有*新*实例启动时都会需要 IMDSv2，而 IMDSv1 将被禁用。如果应用此账户默认设置，以下是该实例启动时的默认值：
+ 控制台：**元数据版本**设置为**仅 V2（需要令牌）**，并且**元数据响应跃点限制**设置为 **2**。
+ AWS CLI：`HttpTokens` 设置为 `required`，并且 `HttpPutResponseHopLimit` 设置为 `2`。

**注意**  
在将账户默认值设置为 IMDSv2 之前，请确保您的实例不依赖 IMDSv1。有关更多信息，请参阅 [要求 IMDSv2 的建议途径](instance-metadata-transition-to-version-2.md#recommended-path-for-requiring-imdsv2)。

------
#### [ Console ]

**将 IMDSv2 设置为指定区域内的账户默认设置**

1. 通过以下网址打开 Amazon EC2 控制台：[https://console.aws.amazon.com/ec2/](https://console.aws.amazon.com/ec2/)。

1. 要更改 AWS 区域，请使用页面右上角的区域选择器。

1. 在导航窗格中，选择**控制面板**。

1. 在**账户属性**卡的**设置**下，选择**数据保护和安全**。

1. 选择 **IMDS 默认设置**旁边的**管理**。

1. 在**管理 IMDS 默认设置**页面上，执行以下操作：

   1. 对于**实例元数据服务**，选择**启用**。

   1. 对于 **Metadata version**（元数据版本），选择 **V2 only (token required)**（仅限 V2（需要令牌））。

   1. 对于**元数据响应跃点限制**，如果实例将托管容器，请指定 **2**。否则，请选择**无首选项**。如果未指定首选项，则在启动时，如果 AMI 具有设置 `ImdsSupport: v2.0`，则该值默认为 **2**；否则默认为 **1**。

   1. 选择**更新**。

------
#### [ AWS CLI ]

**将 IMDSv2 设置为指定区域内的账户默认设置**  
使用 [modify-instance-metadata-defaults](https://docs.aws.amazon.com/cli/latest/reference/ec2/modify-instance-metadata-defaults.html) 命令，并指定要在其中修改 IMDS 账户级别设置的区域。如果实例将托管容器，则将 `--http-tokens` 设置为 `required`，并将 `--http-put-response-hop-limit` 设置为 `2`。否则，请指定 `-1`，表示无首选项。如果已指定 `-1`（无首选项），则在启动时，如果 AMI 具有设置 `ImdsSupport: v2.0`，则该值默认为 `2`；否则默认为 `1`。

```
aws ec2 modify-instance-metadata-defaults \
    --region us-east-1 \
    --http-tokens required \
    --http-put-response-hop-limit 2
```

下面是示例输出。

```
{
    "Return": true
}
```

**查看指定区域的实例元数据选项的默认账户设置**  
使用 [get-instance-metadata-defaults](https://docs.aws.amazon.com/cli/latest/reference/ec2/get-instance-metadata-defaults.html) 命令并指定区域。

```
aws ec2 get-instance-metadata-defaults --region us-east-1
```

下面是示例输出。

```
{
    "AccountLevel": {
        "HttpTokens": "required",
        "HttpPutResponseHopLimit": 2
    },
    "ManagedBy": "account"
}
```

`ManagedBy` 字段表示配置了该设置的实体。在本例中，`account` 表示是直接在账户中配置的设置。值为 `declarative-policy` 表示设置是由声明式策略所配置。有关更多信息，请参阅《AWS Organizations User Guide》**中的 [Declarative policies](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_declarative.html)。

**将 IMDSv2 设置为所有区域的账户默认设置**  
使用 [modify-instance-metadata-defaults](https://docs.aws.amazon.com/cli/latest/reference/ec2/modify-instance-metadata-defaults.html) 命令修改所有区域的 IMDS 账户级别设置。如果实例将托管容器，则将 `--http-tokens` 设置为 `required`，并将 `--http-put-response-hop-limit` 设置为 `2`。否则，请指定 `-1`，表示无首选项。如果已指定 `-1`（无首选项），则在启动时，如果 AMI 具有设置 `ImdsSupport: v2.0`，则该值默认为 `2`；否则默认为 `1`。

```
echo -e "Region          \t Modified" ; \
echo -e "--------------  \t ---------" ; \
for region in $(
    aws ec2 describe-regions \
        --region us-east-1 \
        --query "Regions[*].[RegionName]" \
        --output text
    ); 
    do (output=$(
        aws ec2 modify-instance-metadata-defaults \
            --region $region \
            --http-tokens required \
            --http-put-response-hop-limit 2 \
            --output text)
        echo -e "$region        \t $output"
    );
done
```

下面是示例输出。

```
Region                   Modified
--------------           ---------
ap-south-1               True
eu-north-1               True
eu-west-3                True
...
```

**查看所有区域实例元数据选项的默认账户设置**  
使用 [get-instance-metadata-defaults](https://docs.aws.amazon.com/cli/latest/reference/ec2/get-instance-metadata-defaults.html) 命令。

```
echo -e "Region   \t Level          Hops    HttpTokens" ; \
echo -e "-------------- \t ------------   ----    ----------" ; \
for region in $(
    aws ec2 describe-regions \
        --region us-east-1 \
        --query "Regions[*].[RegionName]" \
        --output text
    ); 
    do (output=$(
        aws ec2 get-instance-metadata-defaults \
            --region $region \
            --output text)
        echo -e "$region \t $output" 
    );
done
```

下面是示例输出。

```
Region           Level          Hops    HttpTokens
--------------   ------------   ----    ----------
ap-south-1       ACCOUNTLEVEL   2       required
eu-north-1       ACCOUNTLEVEL   2       required
eu-west-3        ACCOUNTLEVEL   2       required
...
```

------
#### [ PowerShell ]

**将 IMDSv2 设置为指定区域内的账户默认设置**  
使用 [Edit-EC2InstanceMetadataDefault](https://docs.aws.amazon.com/powershell/latest/reference/items/Edit-EC2InstanceMetadataDefault.html) cmdlet，并指定要在其中修改 IMDS 账户级别设置的区域。如果实例将托管容器，则将 `-HttpToken` 设置为 `required`，并将 `-HttpPutResponseHopLimit` 设置为 `2`。否则，请指定 `-1`，表示无首选项。如果已指定 `-1`（无首选项），则在启动时，如果 AMI 具有设置 `ImdsSupport: v2.0`，则该值默认为 `2`；否则默认为 `1`。

```
Edit-EC2InstanceMetadataDefault `
    -Region us-east-1 `
    -HttpToken required `
    -HttpPutResponseHopLimit 2
```

下面是示例输出。

```
True
```

**查看指定区域的实例元数据选项的默认账户设置**  
使用 [Get-EC2InstanceMetadataDefault](https://docs.aws.amazon.com/powershell/latest/reference/items/Get-EC2InstanceMetadataDefault.html) cmdlet 并指定区域。

```
Get-EC2InstanceMetadataDefault -Region us-east-1 | Format-List
```

下面是示例输出。

```
HttpEndpoint            : 
HttpPutResponseHopLimit : 2
HttpTokens              : required
InstanceMetadataTags    :
```

**将 IMDSv2 设置为所有区域的账户默认设置**  
使用 [Edit-EC2InstanceMetadataDefault](https://docs.aws.amazon.com/powershell/latest/reference/items/Edit-EC2InstanceMetadataDefault.html) cmdlet 修改所有区域的 IMDS 账户级别设置。如果实例将托管容器，则将 `-HttpToken` 设置为 `required`，并将 `-HttpPutResponseHopLimit` 设置为 `2`。否则，请指定 `-1`，表示无首选项。如果已指定 `-1`（无首选项），则在启动时，如果 AMI 具有设置 `ImdsSupport: v2.0`，则该值默认为 `2`；否则默认为 `1`。

```
(Get-EC2Region).RegionName | `
    ForEach-Object {
    [PSCustomObject]@{
        Region   = $_
        Modified = (Edit-EC2InstanceMetadataDefault `
                -Region $_ `
                -HttpToken required `
                -HttpPutResponseHopLimit 2)
    } 
} | `
Format-Table Region, Modified -AutoSize
```

预期输出

```
Region         Modified
------         --------
ap-south-1         True
eu-north-1         True
eu-west-3          True
...
```

**查看所有区域实例元数据选项的默认账户设置**  
使用 [Get-EC2InstanceMetadataDefault](https://docs.aws.amazon.com/powershell/latest/reference/items/Get-EC2InstanceMetadataDefault.html) cmdlet。

```
(Get-EC2Region).RegionName | `
    ForEach-Object {
    [PSCustomObject]@{
        Region = $_
        HttpPutResponseHopLimit = (Get-EC2InstanceMetadataDefault -Region $_).HttpPutResponseHopLimit
        HttpTokens              = (Get-EC2InstanceMetadataDefault -Region $_).HttpTokens
    }
} | `
Format-Table -AutoSize
```

 输出示例

```
Region         HttpPutResponseHopLimit HttpTokens
------         ----------------------- ----------
ap-south-1                           2 required
eu-north-1                           2 required
eu-west-3                            2 required                    
...
```

------

### 在账户级别强制使用 IMDSv2
<a name="enforce-imdsv2-at-the-account-level"></a>

可以在账户级别为每个 AWS 区域强制要求使用 IMDSv2。强制使用后，实例只有配置为必须使用 IMDSv2 时才能启动。无论实例配置或 AMI 配置如何，都必须遵守此强制使用要求。

**注意**  
在账户级别启用 IMDSv2 强制使用之前，请确保您的应用程序和 AMI 支持 IMDSv2。有关更多信息，请参阅 [要求 IMDSv2 的建议途径](instance-metadata-transition-to-version-2.md#recommended-path-for-requiring-imdsv2)。如果启用了 IMDSv2 强制使用，但未在启动时的实例配置中或在账户设置或 AMI 配置中将 `httpTokens` 设置为 `required`，则实例启动将会失败。有关问题排查信息，请参阅[启动启用 IMDSv1 的实例时失败](troubleshooting-launch.md#launching-an-imdsv1-enabled-instance-fails)。

**注意**  
此设置不会更改现有实例的 IMDS 版本，但会阻止在当前已禁用 IMDSv1 的现有实例上启用 IMDSv1。

------
#### [ Console ]

**在指定区域中为账户强制使用 IMDSv2**

1. 通过以下网址打开 Amazon EC2 控制台：[https://console.aws.amazon.com/ec2/](https://console.aws.amazon.com/ec2/)。

1. 要更改 AWS 区域，请使用页面右上角的区域选择器。

1. 在导航窗格中，选择**控制面板**。

1. 在**账户属性**卡的**设置**下，选择**数据保护和安全**。

1. 选择 **IMDS 默认设置**旁边的**管理**。

1. 在**管理 IMDS 默认设置**页面上，执行以下操作：

   1. 对于 **Metadata version**（元数据版本），选择 **V2 only (token required)**（仅限 V2（需要令牌））。

   1. 对于**强制使用 IMDSv2**，请选择**已启用**。

   1. 选择**更新**。

------
#### [ AWS CLI ]

**在指定区域中为账户强制使用 IMDSv2**  
 使用 [modify-instance-metadata-defaults](https://docs.aws.amazon.com/cli/latest/reference/ec2/modify-instance-metadata-defaults.html) 命令，并指定要强制使用 IMDSv2 的区域。

```
aws ec2 modify-instance-metadata-defaults \
    --region us-east-1 \
    --http-tokens required \
    --http-tokens-enforced enabled
```

下面是示例输出。

```
{
"Return": true
}
```

**查看指定区域中的账户 IMDSv2 强制使用设置**  
使用 [get-instance-metadata-defaults](https://docs.aws.amazon.com/cli/latest/reference/ec2/get-instance-metadata-defaults.html) 命令并指定区域。

```
aws ec2 get-instance-metadata-defaults --region us-east-1
```

下面是示例输出。

```
{
    "AccountLevel": {
        "HttpTokens": "required",
        "HttpTokensEnforced": "enabled"
    },
    "ManagedBy": "account"
}
```

`ManagedBy` 字段表示配置了该设置的实体。在本例中，`account` 表示是直接在账户中配置的设置。值为 `declarative-policy` 表示设置是由声明式策略所配置。有关更多信息，请参阅《AWS 用户指南》中的 [Declarative policies](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_declarative.html)**。

**在所有区域为账户强制使用 IMDSv2**  
使用 [modify-instance-metadata-defaults](https://docs.aws.amazon.com/cli/latest/reference/ec2/modify-instance-metadata-defaults.html) 命令，以在所有区域强制使用 IMDSv2。

```
echo -e "Region          \t Modified" ; \
echo -e "--------------  \t ---------" ; \
for region in $(
    aws ec2 describe-regions \
        --region us-east-1 \
        --query "Regions[*].[RegionName]" \
        --output text
    ); 
    do (output=$(
        aws ec2 modify-instance-metadata-defaults \
            --region $region \
            --http-tokens-enforced enabled \
            --output text)
        echo -e "$region        \t $output"
    );
done
```

下面是示例输出。

```
Region                   Modified
--------------           ---------
ap-south-1               True
eu-north-1               True
eu-west-3                True
...
```

**查看所有区域中的账户 IMDSv2 强制使用设置**  
使用 [get-instance-metadata-defaults](https://docs.aws.amazon.com/cli/latest/reference/ec2/get-instance-metadata-defaults.html) 命令。

```
echo -e "Region   \t Level           HttpTokensEnforced" ; \
echo -e "-------------- \t ------------   ----------------" ; \
for region in $(
    aws ec2 describe-regions \
        --region us-east-1 \
        --query "Regions[*].[RegionName]" \
        --output text
    ); 
    do (output=$(
        aws ec2 get-instance-metadata-defaults \
            --region $region \
            --query 'AccountLevel.HttpTokensEnforced' \           
            --output text)
        echo -e "$region \t ACCOUNTLEVEL $output" 
    );
done
```

下面是示例输出。

```
Region           Level          HttpTokensEnforced
--------------   ------------   ------------------
ap-south-1       ACCOUNTLEVEL   enabled
eu-north-1       ACCOUNTLEVEL   enabled
eu-west-3        ACCOUNTLEVEL   enabled
...
```

------
#### [ PowerShell ]

**在指定区域中为账户强制使用 IMDSv2**  
使用 [Edit-EC2InstanceMetadataDefault](https://docs.aws.amazon.com/powershell/latest/reference/items/Edit-EC2InstanceMetadataDefault.html) cmdlet，并指定要强制使用 IMDSv2 的区域。

```
Edit-EC2InstanceMetadataDefault `
    -Region us-east-1 `
    -HttpToken required `
    -HttpPutResponseHopLimit 2
```

下面是示例输出。

```
@{
    Return = $true
}
```

**查看指定区域中的账户 IMDSv2 强制使用设置**  
使用 Get-EC2InstanceMetadataDefault 命令并指定区域。

```
Get-EC2InstanceMetadataDefault -Region us-east-1
```

下面是示例输出。

```
@{
    AccountLevel = @{
        HttpTokens = "required"
        HttpTokensEnforced = "enabled"
    }
    ManagedBy = "account"
}
```

`ManagedBy` 字段表示配置了该设置的实体。在本例中，`account` 表示是直接在账户中配置的设置。值为 `declarative-policy` 表示设置是由声明式策略所配置。有关更多信息，请参阅《AWS 用户指南》中的 [Declarative policies](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_declarative.html)**。

**在所有区域为账户强制使用 IMDSv2**  
使用 [modify-instance-metadata-defaults](https://docs.aws.amazon.com/cli/latest/reference/ec2/modify-instance-metadata-defaults.html) 命令，以在所有区域强制使用 IMDSv2。

```
echo -e "Region          \t Modified" ; \
echo -e "--------------  \t ---------" ; \
for region in $(
    aws ec2 describe-regions \
        --region us-east-1 \
        --query "Regions[*].[RegionName]" \
        --output text
    ); 
    do (output=$(
        aws ec2 modify-instance-metadata-defaults \
            --region $region \
            --http-tokens-enforced enabled \
            --output text)
        echo -e "$region        \t $output"
    );
done
```

下面是示例输出。

```
Region                   Modified
--------------           ---------
ap-south-1               True
eu-north-1               True
eu-west-3                True
...
```

**将 IMDSv2 设置为所有区域的账户默认设置**  
使用 [Edit-EC2InstanceMetadataDefault](https://docs.aws.amazon.com/powershell/latest/reference/items/Edit-EC2InstanceMetadataDefault.html) cmdlet 修改所有区域的 IMDS 账户级别设置。如果实例将托管容器，则将 `-HttpToken` 设置为 `required`，并将 `-HttpPutResponseHopLimit` 设置为 `2`。否则，请指定 `-1`，表示无首选项。如果已指定 `-1`（无首选项），则在启动时，如果 AMI 具有设置 `ImdsSupport: v2.0`，则该值默认为 `2`；否则默认为 `1`。

```
(Get-EC2Region).RegionName | `
    ForEach-Object {
    [PSCustomObject]@{
        Region   = $_
        Modified = (Edit-EC2InstanceMetadataDefault `
                -Region $_ `
                -HttpToken required `
                -HttpPutResponseHopLimit 2)
    } 
} | `
Format-Table Region, Modified -AutoSize
```

预期输出

```
Region         Modified
------         --------
ap-south-1         True
eu-north-1         True
eu-west-3          True
...
```

**查看所有区域实例元数据选项的默认账户设置**  
使用 [Get-EC2InstanceMetadataDefault](https://docs.aws.amazon.com/powershell/latest/reference/items/Get-EC2InstanceMetadataDefault.html) cmdlet。

```
(Get-EC2Region).RegionName | `
    ForEach-Object {
    [PSCustomObject]@{
        Region = $_
        HttpPutResponseHopLimit = (Get-EC2InstanceMetadataDefault -Region $_).HttpPutResponseHopLimit
        HttpTokens              = (Get-EC2InstanceMetadataDefault -Region $_).HttpTokens
    }
} | `
Format-Table -AutoSize
```

 输出示例

```
Region         HttpPutResponseHopLimit HttpTokens
------         ----------------------- ----------
ap-south-1                           2 required
eu-north-1                           2 required
eu-west-3                            2 required                    
...
```

------

### 在启动时配置实例
<a name="configure-IMDS-new-instances-instance-settings"></a>

当您 [启动实例](ec2-launch-instance-wizard.md) 时，您可以通过配置以下字段，从而将实例配置为要求使用 IMDSv2：
+ Amazon EC2 控制台：将 **Metadata version**（元数据版本）设置为 **V2 only (token required)** [仅 V2（必须使用令牌）]。
+ AWS CLI：将 `HttpTokens` 设置为 `required`。

当您指定必须使用 IMDSv2 时，还必须将**可访问元数据**设置为**已启用**（控制台），或将 `HttpEndpoint` 设置为 `enabled`（AWS CLI），以启用实例元数据服务（IMDS）端点。

在容器环境中，需要 IMDSv2 时，我们建议将跃点限制设置为 `2`。有关更多信息，请参阅 [实例元数据访问注意事项](instancedata-data-retrieval.md#imds-considerations)。

------
#### [ Console ]

**要求在新实例上使用 IMDSv2**
+ 在 Amazon EC2 控制台中启动新实例时，展开 **Advanced details**（高级详细信息），然后执行以下操作：
  + 对于 **Metadata accessible**（可访问的元数据），选择 **Enabled**（已启用）。
  + 对于 **Metadata version**（元数据版本），选择 **V2 only (token required)**（仅限 V2（需要令牌））。
  + （容器环境）对于**元数据响应跃点限制**，请选择 **2**。

  有关更多信息，请参阅 [高级详细信息](ec2-instance-launch-parameters.md#liw-advanced-details)。

------
#### [ AWS CLI ]

**要求在新实例上使用 IMDSv2**  
以下 [run-instances](https://docs.aws.amazon.com/cli/latest/reference/ec2/run-instances.html) 示例会启动 `c6i.large` 设置为 `--metadata-options` 的 `HttpTokens=required` 实例。在为 `HttpTokens` 指定值时，还必须将 `HttpEndpoint` 设置为 `enabled`。由于元数据检索请求的安全令牌标头设置为 `required`，这会在请求实例元数据时要求实例使用 IMDSv2。

在容器环境中，需要 IMDSv2 时，我们建议使用 `HttpPutResponseHopLimit=2` 将跃点限制设置为 `2`。

```
aws ec2 run-instances \
    --image-id ami-0abcdef1234567890 \
    --instance-type c6i.large \
	...
    --metadata-options "HttpEndpoint=enabled,HttpTokens=required,HttpPutResponseHopLimit=2"
```

------
#### [ PowerShell ]

**要求在新实例上使用 IMDSv2**  
以下 [New-EC2Instance](https://docs.aws.amazon.com/powershell/latest/reference/items/New-EC2Instance.html) cmdlet 示例启动了一个 `c6i.large` 实例，并将 `MetadataOptions_HttpEndpoint` 设置为 `enabled`，将 `MetadataOptions_HttpTokens` 参数设置为 `required`。在为 `HttpTokens` 指定值时，还必须将 `HttpEndpoint` 设置为 `enabled`。由于元数据检索请求的安全令牌标头设置为 `required`，这会在请求实例元数据时要求实例使用 IMDSv2。

```
New-EC2Instance `
    -ImageId ami-0abcdef1234567890 `
    -InstanceType c6i.large `
    -MetadataOptions_HttpEndpoint enabled `
    -MetadataOptions_HttpTokens required
```

------
#### [ CloudFormation ]

要使用 CloudFormation 指定实例的元数据选项，请参阅 *AWS CloudFormation 用户指南*中的 [亚马逊云科技::EC2::LaunchTemplate MetadataOptions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-metadataoptions.html) 属性。

------

### 配置 AMI
<a name="configure-IMDS-new-instances-ami-configuration"></a>

注册新 AMI 或修改现有 AMI 时，可将 `imds-support` 参数设置为 `v2.0`。从此 AMI 启动的实例会将**元数据版本**设置为 **仅 V2（必须使用令牌）**（控制台），或将 `HttpTokens` 设置为 `required`（AWS CLI）。借助这些设置，实例将要求在请求实例元数据时使用 IMDSv2。

请注意，如果您将 `imds-support` 设置为 `v2.0`，从此 AMI 启动的实例还会将 **Metadata response hop limit**（元数据响应跃点限制）（控制台）或 `http-put-response-hop-limit`（AWS CLI）将设置为 **2**。

**重要**  
除非 AMI 软件支持 IMDSv2，否则不要使用该参数。将值设置为 `v2.0` 后，无法撤消。“重置”AMI 的唯一方法是从底层快照创建新的 AMI。

**为 IMDSv2 配置新的 AMI**  
使用以下方法之一将新 AMI 配置为 IMDSv2。

------
#### [ AWS CLI ]

下面的 [register-image](https://docs.aws.amazon.com/cli/latest/reference/ec2/register-image.html) 示例将使用某个 EBS 根卷的指定快照的 AMI 注册为设备 `/dev/xvda`。为 `imds-support` 参数指定 `v2.0`，以便从此 AMI 启动的实例要求在请求实例元数据时使用 IMDSv2。

```
aws ec2 register-image \
    --name my-image \
    --root-device-name /dev/xvda \
    --block-device-mappings DeviceName=/dev/xvda,Ebs={SnapshotId=snap-0123456789example} \
    --architecture x86_64 \
    --imds-support v2.0
```

------
#### [ PowerShell ]

以下 [Register-EC2Image](https://docs.aws.amazon.com/powershell/latest/reference/items/Register-EC2Image.html) cmdlet 示例将 EBS 根卷的指定快照作为设备 `/dev/xvda` 来注册了一个 AMI。为 `ImdsSupport` 参数指定 `v2.0`，以便从此 AMI 启动的实例要求在请求实例元数据时使用 IMDSv2。

```
Register-EC2Image `
    -Name 'my-image' `
    -RootDeviceName /dev/xvda `
    -BlockDeviceMapping  ( 
    New-Object `
        -TypeName Amazon.EC2.Model.BlockDeviceMapping `
        -Property @{ 
        DeviceName = '/dev/xvda'; 
        EBS        = (New-Object -TypeName Amazon.EC2.Model.EbsBlockDevice -Property @{ 
                SnapshotId = 'snap-0123456789example'
                VolumeType = 'gp3' 
                } )      
        }  ) `
    -Architecture X86_64 `
    -ImdsSupport v2.0
```

------

**为 IMDSv2 配置现有 AMI**  
使用以下方法之一配置 IMDSv2 的现有 AMI。

------
#### [ AWS CLI ]

以下 [modify-image-attribute](https://docs.aws.amazon.com/cli/latest/reference/ec2/modify-image-attribute.html) 示例仅为 IMDSv2 修改现有 AMI。为 `imds-support` 参数指定 `v2.0`，以便从此 AMI 启动的实例要求在请求实例元数据时使用 IMDSv2。

```
aws ec2 modify-image-attribute \
    --image-id ami-0abcdef1234567890 \
    --imds-support v2.0
```

------
#### [ PowerShell ]

以下 [Edit-EC2ImageAttribute](https://docs.aws.amazon.com/powershell/latest/reference/items/Edit-EC2ImageAttribute.html) cmdlet 示例仅修改了 IMDSv2 的一个现有 AMI。为 `imds-support` 参数指定 `v2.0`，以便从此 AMI 启动的实例要求在请求实例元数据时使用 IMDSv2。

```
Edit-EC2ImageAttribute `
    -ImageId ami-0abcdef1234567890 `
    -ImdsSupport 'v2.0'
```

------

### 使用 IAM policy
<a name="configure-IMDS-new-instances-iam-policy"></a>

您可以创建一个将执行以下操作之一的 IAM 策略：
+ 除非要求必须在新实例上使用 IMDSv2，否则阻止用户启动新实例。
+ 阻止用户调用 ModifyInstanceMetadataOptions API 来更改正在运行的实例的元数据选项。限制对 ModifyInstanceMetadataOptions httpTokens 属性的访问，以防止对正在运行的实例进行意外的更新。
+ 阻止用户调用 ModifyInstanceMetadataDefaults API 来更改 httpTokens 和 httpTokensEnforced 的账户默认设置。限制对这两个属性的访问，将确保只有获得授权的角色才能修改账户默认值。

**使用 IAM policy 强制要求在所有新实例上使用 IMDSv2**  
要确保用户只能启动要求在请求实例元数据时使用 IMDSv2 的实例，请执行以下操作：
+ 限制对 `ModifyInstanceMetadataOptions` 和 `ModifyInstanceMetadataDefaults` API 的访问，更具体而言是限制对 `httpTokens` 和 `httpTokensEnforced` 属性的访问。
+ 然后将账户默认值设置为 `httpTokens = required` 和 `httpTokensEnforced = enabled`。

  有关示例 IAM policy，请参阅 [使用实例元数据](ExamplePolicies_EC2.md#iam-example-instance-metadata)。

## 启用 IMDS IPv4 和 IPv6 端点
<a name="configure-IMDS-new-instances-ipv4-ipv6-endpoints"></a>

实例上的 IMDS 有两个端点：IPv4 (`169.254.169.254`) 和 IPv6 (`[fd00:ec2::254]`)。启用 IMDS 时，会自动启用 IPv4 端点。即使将实例启动到仅限 IPv6 的子网中，IPv6 端点仍处于禁用状态。要启用 IPv6 端点，需将其显式启用。启用 IPv6 端点后，IPv4 端点将保持启用状态。

您可以在启动实例时或启动实例之后启用 IPv6 端点。

**启用 IPv6 端点的要求**
+ 所选的实例类型是[基于 Nitro 的实例](instance-types.md#instance-hypervisor-type)。
+ 选定的子网支持 IPv6，其中子网[要么为双堆栈，要么仅限 IPv6](https://docs.aws.amazon.com/vpc/latest/userguide/configure-subnets.html#subnet-ip-address-range)。

使用以下方法之一启动启用了 IMDS IPv6 端点的实例。

------
#### [ Console ]

**在启动实例时启用 IMDS IPv6 端点**
+ 在 Amazon EC2 控制台中 [启动实例](ec2-launch-instance-wizard.md)，并在 **Advanced details**（高级详细信息）下指定以下参数：
  + 对于**元数据 IPv6 端点**，选择**启用**。

有关更多信息，请参阅 [高级详细信息](ec2-instance-launch-parameters.md#liw-advanced-details)。

------
#### [ AWS CLI ]

**在启动实例时启用 IMDS IPv6 端点**  
下方 [run-instances](https://docs.aws.amazon.com/cli/latest/reference/ec2/run-instances.html) 示例会启动一个为 IMDS 启用了 IPv6 端点的 `c6i.large` 实例。要启用 IPv6 端点，请将 `--metadata-options` 参数指定为 `HttpProtocolIpv6=enabled`。在为 `HttpProtocolIpv6` 指定值时，还必须将 `HttpEndpoint` 设置为 `enabled`。

```
aws ec2 run-instances \
    --image-id ami-0abcdef1234567890 \
    --instance-type c6i.large \
    ...
    --metadata-options "HttpEndpoint=enabled,HttpProtocolIpv6=enabled"
```

------
#### [ PowerShell ]

**在启动实例时启用 IMDS IPv6 端点**  
以下 [New-EC2Instance](https://docs.aws.amazon.com/powershell/latest/reference/items/New-EC2Instance.html) cmdlet 示例启动了一个为 IMDS 启用了 IPv6 端点的 `c6i.large` 实例。要启用 IPv6 端点，请将 `MetadataOptions_HttpProtocolIpv6` 指定为 `enabled`。在为 `MetadataOptions_HttpProtocolIpv6` 指定值时，还必须将 `MetadataOptions_HttpEndpoint` 设置为 `enabled`。

```
New-EC2Instance `
    -ImageId ami-0abcdef1234567890 `
    -InstanceType c6i.large `
    -MetadataOptions_HttpEndpoint enabled `
    -MetadataOptions_HttpProtocolIpv6 enabled
```

------

## 关闭对实例元数据的访问
<a name="configure-IMDS-new-instances--turn-off-instance-metadata"></a>

您可以通过在启动实例时禁用 IMDS 来关闭对实例元数据的访问。您可以稍后通过重新启用 IMDS 来开启访问权限。有关更多信息，请参阅 [开启对实例元数据的访问权限](configuring-IMDS-existing-instances.md#enable-instance-metadata-on-existing-instances)。

**重要**  
您可以选择在启动时或启动后禁用 IMDS。如果您*在启动时*禁用 IMDS，则可能发生以下情况：  
您可能不再拥有对实例的 SSH 访问权限。`public-keys/0/openssh-key` 作为您的实例的 SSH 公钥，将无法访问，因为该密钥通常是从 EC2 实例元数据提供和访问的。
EC2 用户数据将不可用，也不会在实例启动时运行。EC2 用户数据托管在 IMDS 上。如果您禁用 IMDS，则实际上关闭了对用户数据的访问。
要访问此功能，您可以在启动后重新启用 IMDS。

------
#### [ Console ]

**要在启动时关闭对实例元数据的访问**
+ 在 Amazon EC2 控制台中 [启动实例](ec2-launch-instance-wizard.md)，并在 **Advanced details**（高级详细信息）下指定以下参数：
  + 对于 **Metadata accessible**（可访问的元数据），选择 **Disabled**（已禁用）。

有关更多信息，请参阅 [高级详细信息](ec2-instance-launch-parameters.md#liw-advanced-details)。

------
#### [ AWS CLI ]

**要在启动时关闭对实例元数据的访问**  
启动实例并将 `--metadata-options` 设置为 `HttpEndpoint=disabled`。

```
aws ec2 run-instances \
    --image-id ami-0abcdef1234567890 \
    --instance-type c6i.large \
    ... 
    --metadata-options "HttpEndpoint=disabled"
```

------
#### [ PowerShell ]

**要在启动时关闭对实例元数据的访问**  
以下 [New-EC2Instance](https://docs.aws.amazon.com/powershell/latest/reference/items/New-EC2Instance.html) cmdlet 示例启动了将 `MetadataOptions_HttpEndpoint` 设置为 `disabled` 的实例。

```
New-EC2Instance `
    -ImageId ami-0abcdef1234567890 `
    -InstanceType c6i.large `
    -MetadataOptions_HttpEndpoint disabled
```

------
#### [ CloudFormation ]

要使用 CloudFormation 指定实例的元数据选项，请参阅 *CloudFormation 用户指南*中的 [亚马逊云科技::EC2::LaunchTemplate MetadataOptions](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-launchtemplate-metadataoptions.html) 属性。

------

## 允许访问实例元数据中的标签
<a name="configure-IMDS-new-instances-tags-in-instance-metadata"></a>

默认情况下，无法访问实例元数据中的实例标签。对于每个实例，您必须明确允许访问。如果允许访问，则实例标签*键*必须符合特定的字符限制，否则实例启动将失败。有关更多信息，请参阅 [启用对实例元数据中标签的访问权限](work-with-tags-in-IMDS.md#allow-access-to-tags-in-IMDS)。

# 为现有实例修改实例元数据选项
<a name="configuring-IMDS-existing-instances"></a>

您可以修改现有实例的实例元数据选项。

您还可以创建 IAM policy，以阻止用户修改现有实例上的实例元数据选项。要控制哪些用户可以修改实例元数据选项，请指定一个策略，阻止除具有指定角色的用户以外的所有用户使用 [ModifyInstanceMetadataOptions](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_ModifyInstanceMetadataOptions.html) API。有关示例 IAM policy，请参阅 [使用实例元数据](ExamplePolicies_EC2.md#iam-example-instance-metadata)。

**注意**  
如果使用了声明式策略来配置实例元数据选项，则无法在账户中直接对选项进行修改。有关更多信息，请参阅《AWS Organizations User Guide》**中的 [Declarative policies](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_declarative.html)。

## 要求使用 IMDSv2
<a name="modify-require-IMDSv2"></a>

使用以下方法之一修改现有实例上的实例元数据选项，以要求在请求实例元数据时使用 IMDSv2。如果 IMDSv2 是必需的，则无法使用 IMDSv1。

**注意**  
在要求必须使用 IMDSv2 之前，请确保该实例没有进行 IMDSv1 调用。`MetadataNoToken` CloudWatch 指标会跟踪 IMDSv1 调用。当 `MetadataNoToken` 记录某个实例的 IMDSv1 使用量为零时，就可以要求该实例必须使用 IMDSv2。

------
#### [ Console ]

**要求在现有实例上使用 IMDSv2**

1. 通过以下网址打开 Amazon EC2 控制台：[https://console.aws.amazon.com/ec2/](https://console.aws.amazon.com/ec2/)。

1. 在导航窗格中，选择 **Instances (实例)**。

1. 选择实例。

1. 依次选择**操作**、**实例设置**、**修改实例元数据选项**。

1. 在**修改实例元数据选项**对话框中，执行以下操作：

   1. 对于**实例元数据服务**，选择**启用**。

   1. 对于**IMDSv2**，选择**必需**。

   1. 选择**保存**。

------
#### [ AWS CLI ]

**要求在现有实例上使用 IMDSv2**  
请使用 [modify-instance-metadata-options](https://docs.aws.amazon.com/cli/latest/reference/ec2/modify-instance-metadata-options.html) CLI 命令，并将 `http-tokens` 参数设置为 `required`。在为 `http-tokens` 指定值时，还必须将 `http-endpoint` 设置为 `enabled`。

```
aws ec2 modify-instance-metadata-options \
    --instance-id i-1234567890abcdef0 \
    --http-tokens required \
    --http-endpoint enabled
```

------
#### [ PowerShell ]

**要求在现有实例上使用 IMDSv2**  
使用 [Edit-EC2InstanceMetadataOption](https://docs.aws.amazon.com/powershell/latest/reference/items/Edit-EC2InstanceMetadataOption.html) cmdlet 并将 `HttpTokens` 参数设置为 `required`。在为 `HttpTokens` 指定值时，还必须将 `HttpEndpoint` 设置为 `enabled`。

```
(Edit-EC2InstanceMetadataOption `
    -InstanceId i-1234567890abcdef0 `
    -HttpTokens required `
    -HttpEndpoint enabled).InstanceMetadataOptions
```

------

## 恢复使用 imdsv1
<a name="modify-restore-IMDSv1"></a>

在实例上要求必须使用 IMDSv2 时，使用 IMDSv1 请求将会失败。如果 IMDSv2 是可选的，则 IMDSv2 和 IMDSv1 都将正常工作。因此，要恢复使用 IMDSv1，请使用以下方法之一将 IMDSv2 设为可选 (`httpTokens = optional`)。

`httpTokensEnforced` IMDS 属性还可以防止尝试在现有实例上启用 IMDSv1。在某个区域为账户启用此功能后，尝试将 `httpTokens` 设置为 `optional` 将导致 `UnsupportedOperation` 异常。有关更多信息，请参阅 [问题排查](#troubleshoot-modifying-an-imdsv1-enabled-instance-fails)。

**重要**  
如果实例因强制使用 IMDSv2 而启动失败，则可通过两种方法成功启动：  
**将实例启动为仅限 IMDSv2**：如果在实例上运行的软件仅使用 IMDSv2（不依赖 IMDSv1），则可以将实例启动为仅限 IMDSv2。要执行此操作，请通过在启动参数或账户在该区域的元数据默认值中设置 `httpTokens = required`，从而配置仅限 IMDSv2。
**禁用强制使用**：如果您的软件仍依赖于 IMDSv1，则在该区域将账户的 `httpTokensEnforced` 设置为 `disabled`。有关更多信息，请参阅 [在账户级别强制使用 IMDSv2](configuring-IMDS-new-instances.md#enforce-imdsv2-at-the-account-level)。

------
#### [ Console ]

**恢复在实例上使用 IMDSv1**

1. 通过以下网址打开 Amazon EC2 控制台：[https://console.aws.amazon.com/ec2/](https://console.aws.amazon.com/ec2/)。

1. 在导航窗格中，选择 **Instances (实例)**。

1. 选择实例。

1. 依次选择**操作**、**实例设置**、**修改实例元数据选项**。

1. 在**修改实例元数据选项**对话框中，执行以下操作：

   1. 对于**实例元数据服务**，请确保选择**启用**。

   1. 对于 **IMDSv2**，选择**可选**。

   1. 选择**保存**。

------
#### [ AWS CLI ]

**恢复在实例上使用 IMDSv1**  
您可以使用 [modify-instance-metadata-options](https://docs.aws.amazon.com/cli/latest/reference/ec2/modify-instance-metadata-options.html) CLI 命令并将 `http-tokens` 设置为 `optional`，以在请求实例元数据时恢复使用 IMDSv1。

```
aws ec2 modify-instance-metadata-options \
    --instance-id i-1234567890abcdef0 \
    --http-tokens optional \
    --http-endpoint enabled
```

------
#### [ PowerShell ]

**恢复在实例上使用 IMDSv1**  
您可以使用 [Edit-EC2InstanceMetadataOption](https://docs.aws.amazon.com/powershell/latest/reference/items/Edit-EC2InstanceMetadataOption.html) cmdlet 并将 `HttpTokens` 设置为 `optional`，以在请求实例元数据时恢复使用 IMDSv1。

```
(Edit-EC2InstanceMetadataOption `
    -InstanceId i-1234567890abcdef0 `
    -HttpTokens optional `
    -HttpEndpoint enabled).InstanceMetadataOptions
```

------

## 更改 PUT 响应跃点限制
<a name="modify-PUT-response-hop-limit"></a>

对于现有的实例，您可以更改 `PUT` 响应跃点数限制设置。

目前仅 AWS CLI 和 AWS SDK 支持更改 PUT 响应跃点限制。

------
#### [ AWS CLI ]

**更改 PUT 响应跃点限制**  
请使用 [modify-instance-metadata-options](https://docs.aws.amazon.com/cli/latest/reference/ec2/modify-instance-metadata-options.html) CLI 命令，并将 `http-put-response-hop-limit` 参数设置为所需的跃点数。在以下示例中，跃点数限制设置为 `3`。请注意，在为 `http-put-response-hop-limit` 指定值时，还必须将 `http-endpoint` 设置为 `enabled`。

```
aws ec2 modify-instance-metadata-options \
    --instance-id i-1234567890abcdef0 \
    --http-put-response-hop-limit 3 \
    --http-endpoint enabled
```

------
#### [ PowerShell ]

**更改 PUT 响应跃点限制**  
使用 [Edit-EC2InstanceMetadataOption](https://docs.aws.amazon.com/powershell/latest/reference/items/Edit-EC2InstanceMetadataOption.html) cmdlet 并将 `HttpPutResponseHopLimit` 参数设置为所需的跃点数。在以下示例中，跃点数限制设置为 `3`。请注意，在为 `HttpPutResponseHopLimit` 指定值时，还必须将 `HttpEndpoint` 设置为 `enabled`。

```
(Edit-EC2InstanceMetadataOption `
    -InstanceId i-1234567890abcdef0 `
    -HttpPutResponseHopLimit 3 `
    -HttpEndpoint enabled).InstanceMetadataOptions
```

------

## 启用 IMDS IPv4 和 IPv6 端点
<a name="enable-ipv6-endpoint-for-existing-instances"></a>

实例上的 IMDS 有两个端点：IPv4 (`169.254.169.254`) 和 IPv6 (`[fd00:ec2::254]`)。启用 IMDS 时，会自动启用 IPv4 端点。即使将实例启动到仅限 IPv6 的子网中，IPv6 端点仍处于禁用状态。要启用 IPv6 端点，需将其显式启用。启用 IPv6 端点后，IPv4 端点将保持启用状态。

您可以在启动实例时或启动实例之后启用 IPv6 端点。

**启用 IPv6 端点的要求**
+ 所选的实例类型是[基于 Nitro 的实例](instance-types.md#instance-hypervisor-type)。
+ 选定的子网支持 IPv6，其中子网[要么为双堆栈，要么仅限 IPv6](https://docs.aws.amazon.com/vpc/latest/userguide/configure-subnets.html#subnet-ip-address-range)。

目前，仅 AWS CLI 和 AWS SDK 支持在启动实例后启用 IMDS IPv6 端点。

------
#### [ AWS CLI ]

**为实例启用 IMDS IPv6 端点**  
请使用 [modify-instance-metadata-options](https://docs.aws.amazon.com/cli/latest/reference/ec2/modify-instance-metadata-options.html) CLI 命令，并将 `http-protocol-ipv6` 参数设置为 `enabled`。请注意，在为 `http-protocol-ipv6` 指定值时，还必须将 `http-endpoint` 设置为 `enabled`。

```
aws ec2 modify-instance-metadata-options \
	--instance-id i-1234567890abcdef0 \
	--http-protocol-ipv6 enabled \
	--http-endpoint enabled
```

------
#### [ PowerShell ]

**为实例启用 IMDS IPv6 端点**  
使用 [Edit-EC2InstanceMetadataOption](https://docs.aws.amazon.com/powershell/latest/reference/items/Edit-EC2InstanceMetadataOption.html) cmdlet 并将 `HttpProtocolIpv6` 参数设置为 `enabled`。请注意，在为 `HttpProtocolIpv6` 指定值时，还必须将 `HttpEndpoint` 设置为 `enabled`。

```
(Edit-EC2InstanceMetadataOption `
    -InstanceId i-1234567890abcdef0 `
    -HttpProtocolIpv6 enabled `
    -HttpEndpoint enabled).InstanceMetadataOptions
```

------

## 开启对实例元数据的访问权限
<a name="enable-instance-metadata-on-existing-instances"></a>

您可以通过启用实例上 IMDS 的 HTTP 端点来开启对实例元数据的访问权限，无论您使用的是哪个版本的 IMDS。您可以随时通过禁用 HTTP 端点来撤消该更改。

使用以下方法之一，即可开启对实例上实例元数据的访问权限。

------
#### [ Console ]

**开启对实例元数据的访问权限**

1. 通过以下网址打开 Amazon EC2 控制台：[https://console.aws.amazon.com/ec2/](https://console.aws.amazon.com/ec2/)。

1. 在导航窗格中，选择 **Instances (实例)**。

1. 选择实例。

1. 依次选择**操作**、**实例设置**、**修改实例元数据选项**。

1. 在**修改实例元数据选项**对话框中，执行以下操作：

   1. 对于**实例元数据服务**，选择**启用**。

   1. 选择**保存**。

------
#### [ AWS CLI ]

**开启对实例元数据的访问权限**  
请使用 [modify-instance-metadata-options](https://docs.aws.amazon.com/cli/latest/reference/ec2/modify-instance-metadata-options.html) CLI 命令，并将 `http-endpoint` 参数设置为 `enabled`。

```
aws ec2 modify-instance-metadata-options \
    --instance-id i-1234567890abcdef0 \
    --http-endpoint enabled
```

------
#### [ PowerShell ]

**开启对实例元数据的访问权限**  
使用 [Edit-EC2InstanceMetadataOption](https://docs.aws.amazon.com/powershell/latest/reference/items/Edit-EC2InstanceMetadataOption.html) cmdlet 并将 `HttpEndpoint` 参数设置为 `enabled`。

```
(Edit-EC2InstanceMetadataOption `
    -InstanceId i-1234567890abcdef0 `
    -HttpEndpoint enabled).InstanceMetadataOptions
```

------

## 关闭对实例元数据的访问
<a name="disable-instance-metadata-on-existing-instances"></a>

您可以通过禁用实例上 IMDS 的 HTTP 端点来关闭对实例元数据的访问权限，无论您使用的是哪个版本的 IMDS。您可以随时启用 HTTP 终端节点以撤消该更改。

使用以下方法之一，即可关闭对实例上实例元数据的访问权限。

------
#### [ Console ]

**关闭对实例元数据的访问**

1. 通过以下网址打开 Amazon EC2 控制台：[https://console.aws.amazon.com/ec2/](https://console.aws.amazon.com/ec2/)。

1. 在导航窗格中，选择 **Instances (实例)**。

1. 选择实例。

1. 依次选择**操作**、**实例设置**、**修改实例元数据选项**。

1. 在**修改实例元数据选项**对话框中，执行以下操作：

   1. 对于**实例元数据服务**，清除**启用**。

   1. 选择**保存**。

------
#### [ AWS CLI ]

**关闭对实例元数据的访问**  
请使用 [modify-instance-metadata-options](https://docs.aws.amazon.com/cli/latest/reference/ec2/modify-instance-metadata-options.html) CLI 命令，并将 `http-endpoint` 参数设置为 `disabled`。

```
aws ec2 modify-instance-metadata-options \
    --instance-id i-1234567890abcdef0 \
    --http-endpoint disabled
```

------
#### [ PowerShell ]

**关闭对实例元数据的访问**  
使用 [Edit-EC2InstanceMetadataOption](https://docs.aws.amazon.com/powershell/latest/reference/items/Edit-EC2InstanceMetadataOption.html) cmdlet 并将 `HttpEndpoint` 参数设置为 `disabled`。

```
(Edit-EC2InstanceMetadataOption `
    -InstanceId i-1234567890abcdef0 `
    -HttpEndpoint disabled).InstanceMetadataOptions
```

------

## 允许访问实例元数据中的标签
<a name="modify-access-to-tags-in-instance-metadata-on-existing-instances"></a>

您可允许访问正在运行或已停止实例上的实例元数据中的标签。对于每个实例，您必须明确允许访问。如果允许访问，则实例标签*键*必须符合特定的字符限制，否则会出错。有关更多信息，请参阅 [启用对实例元数据中标签的访问权限](work-with-tags-in-IMDS.md#allow-access-to-tags-in-IMDS)。

## 问题排查
<a name="troubleshoot-modifying-an-imdsv1-enabled-instance-fails"></a>

### 修改启用 IMDSv1 的实例时失败
<a name="modifying-an-imdsv1-enabled-instance-fails"></a>

#### 说明
<a name="modifying-an-imdsv1-enabled-instance-fails-description"></a>

您收到了以下错误消息：

`You can't launch instances with IMDSv1 because httpTokensEnforced is enabled for this account. Either launch the instance with httpTokens=required or contact your account owner to disable httpTokensEnforced using the ModifyInstanceMetadataDefaults API or the account settings in the EC2 console.`

#### 原因
<a name="modifying-an-imdsv1-enabled-instance-fails-cause"></a>

在 EC2 账户设置或 AWS 组织声明性策略强制使用 IMDSv2 (`httpTokensEnforced = enabled`) 的账户中，尝试将现有实例修改为启用 IMDSv1 (`httpTokens = optional`) 时，将会引发此错误。

#### 解决方案
<a name="modifying-an-imdsv1-enabled-instance-fails-solution"></a>

如果需要在现有实例上支持 IMDSv1，则需要在该区域为该账户禁用 IMDSv2 强制使用。要禁用 IMDSv2 强制使用，请将 `HttpTokensEnforced` 设置为 `disabled`。有关更多信息，请参阅《Amazon EC2 API 参考》中的 [ModifyInstanceMetadataDefaults](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_ModifyInstanceMetadataDefaults.html)。如果您更喜欢使用控制台来配置此设置，请参阅[在账户级别强制使用 IMDSv2](configuring-IMDS-new-instances.md#enforce-imdsv2-at-the-account-level)。

建议使用仅限 IMDSv2 (`httpTokens=required`)。有关更多信息，请参阅 [转换为使用 实例元数据服务版本 2](instance-metadata-transition-to-version-2.md)。

 

# 在启动包含用户数据输入的 EC2 实例时运行命令
<a name="user-data"></a>

启动 Amazon EC2 实例后，您可以将用户数据传递给实例，用于执行自动配置任务或在实例启动后运行脚本。

如果您对更复杂的自动化场景感兴趣，可以考虑使用 CloudFormation。有关更多信息，请参阅《*AWS CloudFormation 用户指南*》中的[使用 CloudFormation 在 Amazon EC2 上部署应用程序](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/deploying.applications.html)。

在 Linux 实例上，您可以将两类用户数据传递到 Amazon EC2：Shell 脚本和 cloud-init 指令。您还可以将此数据以纯文本、文件（这非常适合通过命令行工具启动实例）或者 base64 编码文本（用于 API 调用）的形式传递到启动实例向导中。

在 Windows 实例上，启动代理处理您的用户数据脚本。

**注意事项**
+ 用户数据会被视为非透明数据；您提供什么数据您就会得到什么数据。由实例对其进行解释。
+ 用户数据必须采用 base64 编码。Amazon EC2 控制台可以为您执行 base64 编码或接受 base64 编码的输入。如果您使用实例元数据或控制台检索用户数据，则会自动为您进行 base64 解码。
+ 用户数据在进行 base64 编码之前的原始格式的大小限制为 16 KB。长度为 *n* 的字符串在进行 base64 编码之后的大小为 ceil(*n*/3)\$14。
+ 用户数据是一种实例属性。如果您从实例创建 AMI，则实例用户数据不包含在该 AMI 中。

## AWS 管理控制台 中的用户数据
<a name="user-data-console"></a>

您可在启动实例时指定实例用户数据。如果实例的根卷是 EBS 卷，您还可以停止实例并更新其用户数据。

### 使用启动向导在启动时指定实例用户数据
<a name="user-data-launch-instance-wizard"></a>

您可以在 EC2 控制台中使用启动向导启动实例时指定用户数据。要在启动时指定用户数据，请按照[启动实例](ec2-launch-instance-wizard.md)的过程进行操作。**User data**（用户数据）字段位于启动实例向导的 [高级详细信息](ec2-instance-launch-parameters.md#liw-advanced-details) 部分。在**用户数据**字段中输入您的 PowerShell 脚本，然后完成实例启动程序。

在**用户数据**字段的屏幕截图中，示例脚本在 Windows 临时文件夹中创建文件，在文件名中使用当前日期和时间。当您包括 `<persist>true</persist>` 时，每次重新引导或启动实例时将运行脚本。如果将**用户数据已执行 base64 编码**复选框保留为空，则 Amazon EC2 控制台将执行 base64 编码。

![\[Advanced Details（高级详细信息）用户数据文本字段。\]](http://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/images/configure_ec2config_userdata.png)


有关更多信息，请参阅 [使用启动向导在启动时指定实例用户数据](#user-data-launch-instance-wizard)。有关使用 AWS CLI 的 Linux 示例，请参阅 [用户数据和 AWS CLI](#user-data-api-cli)。有关使用 Tools for Windows PowerShell 的 Windows 示例，请参阅 [用户数据和 Tools for Windows PowerShell](#user-data-powershell)。

### 查看和更新实例用户数据
<a name="user-data-view-change"></a>

您可以查看任何实例的实例用户数据，也可以更新已停止实例的实例用户数据。

**使用控制台更新实例的用户数据**

1. 通过以下网址打开 Amazon EC2 控制台：[https://console.aws.amazon.com/ec2/](https://console.aws.amazon.com/ec2/)。

1. 在导航窗格中，选择**实例**。

1. 选择所需实例，然后依次选择**操作**、**实例状态**、**停止实例**。
**警告**  
停止某个实例时，实例存储卷上的数据将会丢失。要保留这些数据，请将其备份到持久性存储中。

1. 当系统提示您确认时，选择 **Stop**。停止实例可能需要几分钟时间。

1. 在实例仍被选中的情况下，依次选择**操作**、**实例设置**和**编辑用户数据**。如果实例正在运行，您不能更改用户数据，但是可以查看。

1. 在 **Edit user data (编辑用户数据)** 对话框中，更新用户数据，然后选择 **Save (保存)**。要在每次重新引导或启动实例时运行用户数据脚本，请添加 `<persist>true</persist>`，如下例中所示。  
![\[编辑 User Data（用户数据）对话框。\]](http://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/images/view-change-user-data.png)

1. 启动实例。如果为后续重新引导或启动启用了用户数据运行，则在实例启动过程中执行更新后的用户数据脚本。

## Amazon EC2 如何处理 Linux 实例的用户数据
<a name="userdata-linux"></a>

以下示例使用用户数据在实例启动时运行设置 LAMP 服务器的命令。在每个示例中，执行以下任务：
+ 更新发行版软件包。
+ 安装 Web 服务器、`php` 和 `mariadb` 包。
+ 启动并启用 `httpd` 服务。
+ 用户 `ec2-user` 将添加到 apache 组。
+ 为 Web 目录以及其中的文件设置适当的所有权和文件权限。
+ 创建简单网页来测试 Web 服务器和 PHP 引擎。

**Topics**
+ [

### 前提条件
](#user-data-requirements)
+ [

### 用户数据和 Shell 脚本
](#user-data-shell-scripts)
+ [

### 更新实例用户数据
](#user-data-modify)
+ [

### 用户数据和 cloud-init 指令
](#user-data-cloud-init)
+ [

### 用户数据和 AWS CLI
](#user-data-api-cli)
+ [

### 将 Shell 脚本和 cloud-init 指令组合使用
](#user-data-mime-multi)

### 前提条件
<a name="user-data-requirements"></a>

本主题中的示例假定以下内容：
+ 您的实例具有可从互联网访问的公用 DNS 名称。
+ 与您的实例关联的安全组将被配置为允许 SSH（端口 22）流量，以便您可以连接到该实例，以查看输出日志文件。
+ 您的实例是使用 Amazon Linux AMI 启动的。这些命令和指令可能不适用于其他 Linux 发行版。有关其他发行版的更多信息（例如它们对 cloud-init 的支持），请参阅特定发行版的文档。

### 用户数据和 Shell 脚本
<a name="user-data-shell-scripts"></a>

如果您熟悉 Shell 脚本编写，要在启动时将指令发送到实例，这是最简单、最完整的方式。在启动时添加这些任务会增加启动实例所需的时间。您应多等待几分钟让这些任务完成，然后测试用户脚本是否已成功完成。

**重要**  
默认情况下，用户数据脚本和 cloud-init 指令仅在首次启动实例时在引导周期内运行。您可以更新您的配置，以确保您的用户数据脚本和 cloud-init 指令在每次重新启动实例时都会运行。有关更多信息，请参阅AWS知识中心中的[如何利用用户数据在每次重新启动 Amazon EC2 Linux 实例时自动运行脚本？](https://repost.aws/knowledge-center/execute-user-data-ec2)。

用户数据 Shell 脚本必须以 `#!` 字符以及指向要读取脚本的解释器的路径（通常为 **/bin/bash)**）开头。有关 shell 脚本的介绍，请参阅 *GNU 操作系统*网站上的 [Bash 参考手册](https://www.gnu.org/software/bash/manual/bash.html)。

作为用户数据输入的脚本是作为根用户加以运行的，因此在脚本中不使用 **sudo** 命令。请注意，您创建的任何文件都将归根用户所有；如果您需要非根用户具有文件访问权限，应在脚本中相应地修改权限。此外，这是因为脚本不交互运行，所以无法包含要求用户反馈的命令（如 **yum update**，无 `-y` 标志）。

如果您使用 AWS API（包括 AWS CLI），则在启动实例时必须使用实例配置文件。实例配置文件提供用户数据脚本发出 API 调用所需的适当 AWS 凭证。有关更多信息，请参阅《IAM 用户指南》中的[使用实例配置文件](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html)。您分配给 IAM 角色的权限取决于您使用 API 调用的服务。有关更多信息，请参阅 [适用于 Amazon EC2 的 IAM 角色](iam-roles-for-amazon-ec2.md)。

cloud-init 输出日志文件捕获控制台输出，因此，如果实例的行为不符合您的预期，可在启动后方便地调试脚本。要查看日志文件，[请连接到实例](connect-to-linux-instance.md)并打开 `/var/log/cloud-init-output.log`。

在处理用户数据脚本时，该脚本将复制到 `/var/lib/cloud/instances/instance-id/` 目录并从该目录运行。脚本在运行后无法删除。请在从实例创建 AMI 之前务必删除 `/var/lib/cloud/instances/instance-id/` 中的用户数据脚本。否则，该脚本将存在于从 AMI 启动的任何实例上的此目录中。

### 更新实例用户数据
<a name="user-data-modify"></a>

要更新实例用户数据，您必须先停止实例。如果实例正在运行，那么您可以查看用户数据，但不能进行修改。

**警告**  
停止某个实例时，实例存储卷上的数据将会丢失。要保留这些数据，请将其备份到持久性存储中。

**修改实例用户数据**

1. 通过以下网址打开 Amazon EC2 控制台：[https://console.aws.amazon.com/ec2/](https://console.aws.amazon.com/ec2/)。

1. 在导航窗格中，选择**实例**。

1. 选择所需实例，然后依次选择**实例状态**、**停止实例**。如果此选项处于禁用状态，则表示实例已停止，或者其根卷是实例存储卷。

1. 当系统提示您确认时，选择 **Stop**。停止实例可能需要几分钟时间。

1. 在实例仍被选中的情况下，依次选择**操作**、**实例设置**和**编辑用户数据**。

1. 根据需要修改用户数据，然后选择**保存**。

1. 开启实例。开启实例后，新的用户数据将在实例上可见；但不会运行用户数据脚本。

### 用户数据和 cloud-init 指令
<a name="user-data-cloud-init"></a>

cloud-init 程序包在启动时配置新 Amazon Linux 实例的特定方面；最值得注意的是，它为 ec2-user 配置 `.ssh/authorized_keys` 文件，以便您使用自己的私有密钥登录。有关 cloud-init 包为 Amazon Linux 实例执行的配置任务的更多信息，请参阅以下文档：
+ **Amazon Linux 2023** – [自定义 cloud-init](https://docs.aws.amazon.com/linux/al2023/ug/cloud-init.html)
+ **Amazon Linux 2** – [在 Amazon Linux 2 上 cloud-init](https://docs.aws.amazon.com/linux/al2/ug/amazon-linux-cloud-init.html)

可在启动时将 cloud-init 用户指令传递给实例，方式与传递脚本相同，只是语法不同。有关 cloud-init 的更多信息，请参阅 [https://cloudinit.readthedocs.org/en/latest/index.html](https://cloudinit.readthedocs.org/en/latest/index.html)。

**重要**  
默认情况下，用户数据脚本和 cloud-init 指令仅在首次启动实例时在引导周期内运行。您可以更新您的配置，以确保您的用户数据脚本和 cloud-init 指令在每次重新启动实例时都会运行。有关更多信息，请参阅AWS知识中心中的[如何利用用户数据在每次重新启动 Amazon EC2 Linux 实例时自动运行脚本？](https://repost.aws/knowledge-center/execute-user-data-ec2)。

在启动时添加这些任务会增加启动实例所需的时间。您应多等待几分钟让这些任务完成，然后测试用户数据指令是否已完成。

**将 cloud-init 指令传递给 Amazon Linux 实例**

1. 按照[启动实例](ec2-launch-instance-wizard.md)的程序进行操作。**User data**（用户数据）字段位于启动实例向导的 [高级详细信息](ec2-instance-launch-parameters.md#liw-advanced-details) 部分。在 **User data**（用户数据）字段中输入您的 cloud-init 指令文本，然后完成实例启动程序。

   在下面的示例中，指令在 Amazon Linux 上创建并配置了一个 Web 服务器。要将命令标识为 cloud-init 指令，顶部的 `#cloud-config` 行是必需的。

------
#### [ AL2023 ]

   ```
   #cloud-config
   package_update: true
   package_upgrade: all
   	
   packages:
   - httpd
   - mariadb105-server
   - php8.1
   - php8.1-mysqlnd
   
   runcmd:
   - systemctl start httpd
   - systemctl enable httpd
   - [ sh, -c, "usermod -a -G apache ec2-user" ]
   - [ sh, -c, "chown -R ec2-user:apache /var/www" ]
   - chmod 2775 /var/www
   - [ find, /var/www, -type, d, -exec, chmod, 2775, {}, \; ]
   - [ find, /var/www, -type, f, -exec, chmod, 0664, {}, \; ]
   - [ sh, -c, 'echo "<?php phpinfo(); ?>" > /var/www/html/phpinfo.php' ]
   ```

------
#### [ AL2 ]

   ```
   #cloud-config
   package_update: true
   package_upgrade: all
   	
   packages:
   - httpd
   - mariadb-server
   	
   runcmd:
   - [ sh, -c, "amazon-linux-extras install -y lamp-mariadb10.2-php7.2 php7.2" ]
   - systemctl start httpd
   - systemctl enable httpd
   - [ sh, -c, "usermod -a -G apache ec2-user" ]
   - [ sh, -c, "chown -R ec2-user:apache /var/www" ]
   - chmod 2775 /var/www
   - [ find, /var/www, -type, d, -exec, chmod, 2775, {}, \; ]
   - [ find, /var/www, -type, f, -exec, chmod, 0664, {}, \; ]
   - [ sh, -c, 'echo "<?php phpinfo(); ?>" > /var/www/html/phpinfo.php' ]
   ```

------

1. 让实例有足够的时间启动和运行用户数据中的指令，然后查看指令是否完成了预期的任务。

   对于此示例，在 Web 浏览器中输入指令创建的 PHP 测试文件的 URL。此 URL 是实例的公用 DNS 地址，后接正斜杠和文件名。

   ```
   http://my.public.dns.amazonaws.com/phpinfo.php
   ```

   您应该会看到 PHP 信息页面。如果您无法看到 PHP 信息页，请检查所用的安全组是否包含允许 HTTP (端口 80) 通信的规则。有关更多信息，请参阅 [配置安全组规则](changing-security-group.md#add-remove-security-group-rules)。

1. （可选）如果您的指令没有完成您期望的任务，或者如果您只是想验证您的指令是否已完成且没有错误，[请连接到实例](connect-to-linux-instance.md)，检查输出日志文件 (`/var/log/cloud-init-output.log`)，然后查找输出中的错误消息。对于其他调试信息，您可以将以下行添加到指令：

   ```
   output : { all : '| tee -a /var/log/cloud-init-output.log' }
   ```

   此指令将 **runcmd** 输出发送到 `/var/log/cloud-init-output.log`。

### 用户数据和 AWS CLI
<a name="user-data-api-cli"></a>

您可以使用 AWS CLI 指定、修改和查看实例的用户数据。有关使用实例元数据从实例查看用户数据的信息，请参阅[访问 EC2 实例的实例元数据](instancedata-data-retrieval.md)。

在 Windows 上，您可以使用 AWS Tools for Windows PowerShell 而不是使用 AWS CLI。有关更多信息，请参阅 [用户数据和 Tools for Windows PowerShell](#user-data-powershell)。

**示例：启动时指定用户数据**  
要在启动实例时指定用户数据，请结合使用 [run-instances](https://docs.aws.amazon.com/cli/latest/reference/ec2/run-instances.html) 命令与 `--user-data` 参数。使用 **run-instances**，AWS CLI 将对您的用户数据执行 base64 编码。

以下示例显示如何在命令行上指定字符串形式的脚本：

```
aws ec2 run-instances --image-id ami-abcd1234 --count 1 --instance-type m3.medium \
    --key-name my-key-pair --subnet-id subnet-abcd1234 --security-group-ids sg-abcd1234 \
    --user-data echo user data
```

以下示例显示如何使用文本文件指定脚本。请务必使用 `file://` 前缀指定该文件。

```
aws ec2 run-instances --image-id ami-abcd1234 --count 1 --instance-type m3.medium \
    --key-name my-key-pair --subnet-id subnet-abcd1234 --security-group-ids sg-abcd1234 \
    --user-data file://my_script.txt
```

以下是具有 Shell 脚本的示例文本文件。

```
#!/bin/bash
yum update -y
service httpd start
chkconfig httpd on
```

**示例：修改停止的实例的用户数据**  
您可以使用 [modify-instance-attribute](https://docs.aws.amazon.com/cli/latest/reference/ec2/modify-instance-attribute.html) 命令修改已停止的实例的用户数据。使用 **modify-instance-attribute**，AWS CLI 不会对用户数据执行 base64 编码。
+ 在 **Linux** 计算机上，使用 base64 命令对用户数据进行编码。

  ```
  base64 my_script.txt >my_script_base64.txt
  ```
+ 在 **Windows** 计算机上，使用 certutil 命令可对用户数据进行编码。您必须先删除第一行 (BEGIN CERTIFICATE) 和最后一行 (END CERTIFICATE)，然后才能将此文件用于 AWS CLI。

  ```
  certutil -encode my_script.txt my_script_base64.txt
  notepad my_script_base64.txt
  ```

使用 `--attribute` 和 `--value` 参数可通过编码的文本文件指定用户数据。请务必使用 `file://` 前缀指定该文件。

```
aws ec2 modify-instance-attribute --instance-id i-1234567890abcdef0 --attribute userData --value file://my_script_base64.txt
```

**示例：清除停止的实例的用户数据**  
要删除现有的用户数据，请按以下方式使用 [modify-instance-attribute](https://docs.aws.amazon.com/cli/latest/reference/ec2/modify-instance-attribute.html) 命令：

```
aws ec2 modify-instance-attribute --instance-id i-1234567890abcdef0 --user-data Value=
```

**示例：查看用户数据**  
要检索实例的用户数据，请使用 [describe-instance-attribute](https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-instance-attribute.html) 命令。使用 **describe-instance-attribute**，AWS CLI 不会对用户数据执行 base64 解码。

```
aws ec2 describe-instance-attribute --instance-id i-1234567890abcdef0 --attribute userData
```

以下是具有已进行 base64 编码的用户数据的示例输出。

```
{
    "UserData": {
        "Value": "IyEvYmluL2Jhc2gKeXVtIHVwZGF0ZSAteQpzZXJ2aWNlIGh0dHBkIHN0YXJ0CmNoa2NvbmZpZyBodHRwZCBvbg=="
    },
    "InstanceId": "i-1234567890abcdef0"
}
```
+ 在 **Linux** 计算机上，使用 `--query` 选项获取已编码的用户数据和用于对该数据进行解码的 base64 命令。

  ```
  aws ec2 describe-instance-attribute --instance-id i-1234567890abcdef0 --attribute userData --output text --query "UserData.Value" | base64 --decode
  ```
+ 在 **Windows** 计算机上，使用 `--query` 选项获取已编码的用户数据和用于对该数据进行解码的 certutil 命令。请注意，编码的输出存储在一个文件中，解码的输出存储在另一个文件中。

  ```
  aws ec2 describe-instance-attribute --instance-id i-1234567890abcdef0 --attribute userData --output text --query "UserData.Value" >my_output.txt
  certutil -decode my_output.txt my_output_decoded.txt
  type my_output_decoded.txt
  ```

下面是示例输出。

```
#!/bin/bash
yum update -y
service httpd start
chkconfig httpd on
```

### 将 Shell 脚本和 cloud-init 指令组合使用
<a name="user-data-mime-multi"></a>

默认情况下，一次只能在用户数据中包含一个内容类型。不过，您可以在 mime-multi part 文件中使用 `text/cloud-config` 和 `text/x-shellscript`，以便在用户数据中同时包含 Shell 脚本和 cloud-init 指令。

下面显示了 mime-multi part 的格式。

```
Content-Type: multipart/mixed; boundary="//"
MIME-Version: 1.0
	
--//
Content-Type: text/cloud-config; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="cloud-config.txt"
	
#cloud-config
cloud-init directives
	
--//
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="userdata.txt"
	
#!/bin/bash
shell script commands
--//--
```

例如，以下用户数据包含了 cloud-init 指令和 bash Shell 脚本。cloud-init 指令会创建一个文件（`/test-cloudinit/cloud-init.txt`），然后将 `Created by cloud-init` 写入该文件。bash Shell 脚本会创建一个文件（`/test-userscript/userscript.txt`），然后将 `Created by bash shell script` 写入该文件。

```
Content-Type: multipart/mixed; boundary="//"
MIME-Version: 1.0
	
--//
Content-Type: text/cloud-config; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="cloud-config.txt"
	
#cloud-config
runcmd:
- [ mkdir, /test-cloudinit ]
write_files:
- path: /test-cloudinit/cloud-init.txt
content: Created by cloud-init
	
--//
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="userdata.txt"
	
#!/bin/bash
mkdir test-userscript
touch /test-userscript/userscript.txt
echo "Created by bash shell script" >> /test-userscript/userscript.txt
--//--
```

## Amazon EC2 如何处理 Windows 实例的用户数据
<a name="ec2-windows-user-data"></a>

在 Windows 实例上，启动代理会执行与用户数据相关的任务。有关更多信息，请参阅下列内容：
+ [EC2Launch v2](ec2launch-v2.md) 
+ [EC2Launch](ec2launch.md) 
+ [EC2Config 服务](ec2config-service.md)

有关 `UserData` 模板中 CloudFormation 属性的程序集示例，请参阅 [Base64 编码 UserData 属性](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/quickref-general.html#scenario-userdata-base64)和[带 AccessKey 和 SecretKey 的 Base64 编码 UserData 属性](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/quickref-general.html#scenario-userdata-base64-with-keys)。

有关在使用生命周期挂钩的自动扩缩组中实例上运行命令的示例，请参阅《Amazon EC2 Auto Scaling User Guide》**中的 [Tutorial: Configure user data to retrieve the target lifecycle state through instance metadata](https://docs.aws.amazon.com/autoscaling/ec2/userguide/tutorial-lifecycle-hook-instance-metadata.html)。

**Topics**
+ [

### 用户数据脚本
](#user-data-scripts)
+ [

### 压缩后的用户数据
](#user-data-compressed)
+ [

### 用户数据执行
](#user-data-execution)
+ [

### 用户数据和 Tools for Windows PowerShell
](#user-data-powershell)

### 用户数据脚本
<a name="user-data-scripts"></a>

要让 `EC2Config` 或 `EC2Launch` 运行脚本，在将脚本添加到用户数据中时，您必须将脚本封装在特殊标签中。您使用的标签取决于命令是在命令提示符窗口（批处理命令）中还是使用 Windows PowerShell 运行。

如果同时指定批处理脚本和 Windows PowerShell 脚本，则批处理脚本先运行，然后运行 Windows PowerShell 脚本，不论这些脚本在实例用户数据中的显示顺序如何。

如果您在用户数据脚本中使用 AWS API（包括 AWS CLI），则在启动实例时必须使用实例配置文件。实例配置文件提供用户数据脚本执行 API 调用所需的适当 AWS 凭证。有关更多信息，请参阅[实例配置文件](iam-roles-for-amazon-ec2.md#ec2-instance-profile)。您分配给 IAM 角色的权限取决于您使用 API 调用的服务。有关更多信息，请参阅 [适用于 Amazon EC2 的 IAM 角色](iam-roles-for-amazon-ec2.md)。

**Topics**
+ [

#### 批处理脚本的语法
](#user-data-batch-scripts)
+ [

#### Windows PowerShell 脚本的语法
](#user-data-powershell-scripts)
+ [

#### YAML 配置脚本的语法
](#user-data-yaml-scripts)
+ [

#### Base64 编码
](#user-data-base64-encoding)

#### 批处理脚本的语法
<a name="user-data-batch-scripts"></a>

使用 `script` 标签指定批处理脚本。使用换行符分隔命令，如以下示例所示。

```
<script>
    echo Current date and time >> %SystemRoot%\Temp\test.log
    echo %DATE% %TIME% >> %SystemRoot%\Temp\test.log
</script>
```

默认情况下，用户数据脚本在您启动实例时运行一次。要在每次重新引导或启动实例时运行用户数据脚本，请将 `<persist>true</persist>` 添加到用户数据。

```
<script>
    echo Current date and time >> %SystemRoot%\Temp\test.log
    echo %DATE% %TIME% >> %SystemRoot%\Temp\test.log
</script>
<persist>true</persist>
```

**EC2Launch v2 代理**  
要在 EC2Launch v2 **executeScript** 任务处于 `UserData` 阶段时将 XML 用户数据脚本作为分离的进程运行，请向用户数据添加 `<detach>true</detach>`。

**注意**  
以前的启动代理不支持 detach 标签。

```
<script>
    echo Current date and time >> %SystemRoot%\Temp\test.log
    echo %DATE% %TIME% >> %SystemRoot%\Temp\test.log
</script>
<detach>true</detach>
```

#### Windows PowerShell 脚本的语法
<a name="user-data-powershell-scripts"></a>

AWS Windows AMI 包括 [AWS Tools for Windows PowerShell](https://aws.amazon.com/powershell/)，因此您可在用户数据中指定这些 cmdlet。如果您将一个 IAM 角色与实例相关联，那么您不必为 cmdlet 指定凭证，因为实例上运行的应用程序可以使用该角色的凭证访问AWS资源（例如 Amazon S3 存储桶）。

使用 `<powershell>` 标签指定 Windows PowerShell 脚本。使用换行符分隔命令。`<powershell>` 标签区分大小写。

例如：

```
<powershell>
    $file = $env:SystemRoot + "\Temp\" + (Get-Date).ToString("MM-dd-yy-hh-mm")
    New-Item $file -ItemType file
</powershell>
```

默认情况下，用户数据脚本会在您启动实例时运行一次。要在每次重新引导或启动实例时运行用户数据脚本，请将 `<persist>true</persist>` 添加到用户数据。

```
<powershell>
    $file = $env:SystemRoot + "\Temp\" + (Get-Date).ToString("MM-dd-yy-hh-mm")
    New-Item $file -ItemType file
</powershell>
<persist>true</persist>
```

您可以使用 `<powershellArguments>` 标签来指定一个或多个 PowerShell 参数。如果未传递任何参数，则默认情况下，EC2Launch 和 EC2Launch v2 会添加以下参数：`-ExecutionPolicy Unrestricted`。

**示例：**

```
<powershell>
    $file = $env:SystemRoot + "\Temp" + (Get-Date).ToString("MM-dd-yy-hh-mm")
    New-Item $file -ItemType file
</powershell>
<powershellArguments>-ExecutionPolicy Unrestricted -NoProfile -NonInteractive</powershellArguments>
```

**EC2Launch v2 代理**  
要在 EC2Launch v2 **executeScript** 任务处于 `UserData` 阶段时将 XML 用户数据脚本作为分离的进程运行，请向用户数据添加 `<detach>true</detach>`。

**注意**  
以前的启动代理不支持 detach 标签。

```
<powershell>
    $file = $env:SystemRoot + "\Temp\" + (Get-Date).ToString("MM-dd-yy-hh-mm")
    New-Item $file -ItemType file
</powershell>
<detach>true</detach>
```

#### YAML 配置脚本的语法
<a name="user-data-yaml-scripts"></a>

如果使用 EC2Launch v2 运行脚本，则可以使用 YAML 格式。要查看 EC2Launch v2 的配置任务、详细信息和示例，请参阅 [EC2Launch v2 任务配置](ec2launch-v2-settings.md#ec2launch-v2-task-configuration)。

使用 `executeScript` 任务指定 YAML 脚本。

**运行 PowerShell 脚本的 YAML 语法示例** 

```
version: 1.0
tasks:
- task: executeScript
  inputs:
  - frequency: always
    type: powershell
    runAs: localSystem
    content: |-
      $file = $env:SystemRoot + "\Temp\" + (Get-Date).ToString("MM-dd-yy-hh-mm")
      New-Item $file -ItemType file
```

**运行批处理脚本的 YAML 语法示例**

```
version: 1.1
tasks:
- task: executeScript
  inputs:
  - frequency: always
    type: batch
    runAs: localSystem
    content: |-
      echo Current date and time >> %SystemRoot%\Temp\test.log
      echo %DATE% %TIME% >> %SystemRoot%\Temp\test.log
```

#### Base64 编码
<a name="user-data-base64-encoding"></a>

如果使用的是 Amazon EC2 API 或不对用户数据执行 base64 编码的工具，则您必须自行对用户数据进行编码。否则，系统会记录找不到要运行的 `script` 或 `powershell` 标签的错误。下面是使用 Windows PowerShell 进行编码的示例。

```
$UserData = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($Script))
```

下面是一个使用 PowerShell 进行解码的示例。

```
$Script = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($UserData))
```

有关 base64 编码的更多信息，请参阅 [ https://www.ietf.org/rfc/rfc4648.txt](https://www.ietf.org/rfc/rfc4648.txt)。

### 压缩后的用户数据
<a name="user-data-compressed"></a>

EC2Launch v2 支持使用压缩用户数据的方法，来提交超过 16 KB 这一 IMDS 规定限制的用户数据。要使用此功能，请将用户数据脚本压缩为 `.zip` 存档，然后将其传递给 EC2 实例。检测到压缩用户数据时，EC2Launch v2 会自动将压缩后的用户数据脚本解压缩，然后再运行该脚本。

对于标准用户数据，如果使用的是 Amazon EC2 API 或不对用户数据执行 base64 编码的工具，则必须自行对压缩用户数据进行编码。有关用户数据大小限制和 base64 编码的更多信息，请参阅[访问 EC2 实例的实例元数据](instancedata-data-retrieval.md)。

### 用户数据执行
<a name="user-data-execution"></a>

默认情况下，所有 AWS Windows AMI 均已为初次启动启用了用户数据执行。您可以指定用户数据脚本在下次实例重新引导或重启时运行。此外，您可以指定用户数据脚本在每次实例重新引导或重启时运行。

**注意**  
默认情况下不会使用户数据在首次启动后运行。要使用户数据在实例重启或启动时运行，请参阅[在后续重启或启动期间运行脚本](#user-data-scripts-subsequent)。

生成随机密码之后，从本地管理员账户运行用户数据脚本。否则，从系统账户运行用户数据脚本。

#### 实例启动脚本
<a name="user-data-scripts-launch"></a>

实例用户数据中的脚本在实例的初次启动期间运行。如果找到 `persist` 标签，则为后续重新引导或启动启用用户数据执行。EC2Launch v2、EC2Launch 和 EC2Config 的日志文件包含源自标准输出和标准错误流的输出。

**EC2Launch v2**  
EC2Launch v2 的日志文件为 `C:\ProgramData\Amazon\EC2Launch\log\agent.log`。

**注意**  
`C:\ProgramData` 文件夹可能已隐藏。要查看该文件夹，您必须显示隐藏的文件和文件夹。

执行用户数据时将记录以下信息：
+ `Info: Converting user-data to yaml format` – 如果用户数据是以 XML 格式提供的
+ `Info: Initialize user-data state` – 用户数据执行开始
+ `Info: Frequency is: always` – 如果每次启动时都运行用户数据任务
+ `Info: Frequency is: once` – 如果用户数据任务只运行一次
+ `Stage: postReadyUserData execution completed` – 用户数据执行结束

**EC2Launch**  
EC2Launch 的日志文件为 `C:\ProgramData\Amazon\EC2-Windows\Launch\Log\UserdataExecution.log`。

`C:\ProgramData` 文件夹可能已隐藏。要查看该文件夹，您必须显示隐藏的文件和文件夹。

执行用户数据时将记录以下信息：
+ `Userdata execution begins` – 用户数据执行开始
+ `<persist> tag was provided: true` – 找到持久标签时
+ `Running userdata on every boot` – 找到持久标签时
+ `<powershell> tag was provided.. running powershell content` – 如果找到 PowerShell 标签
+ `<script> tag was provided.. running script content` – 如果找到脚本标签
+ `Message: The output from user scripts` – 如果运行用户数据脚本，则会记录其输出

**EC2Config**  
EC2Config 的日志文件为 `C:\Program Files\Amazon\Ec2ConfigService\Logs\Ec2Config.log`。执行用户数据时将记录以下信息：
+ `Ec2HandleUserData: Message: Start running user scripts` – 用户数据执行开始
+ `Ec2HandleUserData: Message: Re-enabled userdata execution` – 找到持久标签时
+ `Ec2HandleUserData: Message: Could not find <persist> and </persist>` – 如果未找到持久标签
+ `Ec2HandleUserData: Message: The output from user scripts` – 如果运行用户数据脚本，则会记录其输出

#### 在后续重启或启动期间运行脚本
<a name="user-data-scripts-subsequent"></a>

在更新实例用户数据后，更新后的用户将在下次重启或启动实例时自动反映在实例元数据中。但根据安装的启动代理不同，可能需要额外的配置才能将用户数据脚本配置为在后续重启或启动时运行。

如果选择了**使用 Sysprep 关闭**选项，则用户数据脚本将在下一次实例启动或重启时运行，即使没有为后续重启或启动启用用户数据执行，也是如此。

有关启用用户数据执行的说明，请选择与启动代理相匹配的选项卡。

------
#### [ EC2Launch v2 ]

与 EC2Launch v1 不同，EC2Launch v2 在每次启动时都会对用户数据任务进行评估。无需手动计划用户数据任务。用户数据基于包含的频率或持久性选项运行。

对于 XML 用户数据脚本  
要在每次启动时运行用户数据脚本，请在用户数据中添加 `<persist>true</persist>` 标志。如果未包含持久性标志，则用户数据脚本仅在首次启动时运行。

对于 YAML 用户数据  
+ 要在首次启动时运行用户数据中的任务，请将任务 `frequency` 设置为 `once`。
+ 要在每次启动时都运行用户数据中的任务，请将任务 `frequency` 设置为 `always`。

------
#### [ EC2Launch ]

1. 连接到您的 Windows 实例。

1. 打开 PowerShell 命令窗口，并运行以下命令之一：

**运行一次**  
要在下次启动时运行一次用户数据，请使用 `-Schedule` 标志。

   ```
   C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\InitializeInstance.ps1 -Schedule
   ```

**在所有后续启动时运行**  
要在所有后续启动时运行用户数据，请使用 `-SchedulePerBoot` 标志。

   ```
   C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\InitializeInstance.ps1 -SchedulePerBoot
   ```

1. 从 Windows 实例断开连接。要在下次实例启动时运行更新后的脚本，请停止实例并更新用户数据。

------
#### [ EC2Config ]

1. 连接到您的 Windows 实例。

1. 打开 `C:\Program Files\Amazon\Ec2ConfigService\Ec2ConfigServiceSetting.exe`。

1. 对于**用户数据**，选择 **Enable UserData execution for next service start** (为下次服务启动启用用户数据执行)。

1. 从 Windows 实例断开连接。要在下次实例启动时运行更新后的脚本，请停止实例并更新用户数据。

------

### 用户数据和 Tools for Windows PowerShell
<a name="user-data-powershell"></a>

您可以使用 Tools for Windows PowerShell 指定、修改和查看实例的用户数据。有关使用实例元数据从实例查看用户数据的信息，请参阅[访问 EC2 实例的实例元数据](instancedata-data-retrieval.md)。有关用户数据和 AWS CLI 的信息，请参阅 [用户数据和 AWS CLI](#user-data-api-cli)。

**示例：启动时指定实例用户数据**  
使用实例用户数据创建一个文本文件。要在每次重新引导或启动实例时运行用户数据脚本，请添加 `<persist>true</persist>`，如下例中所示。

```
<powershell>
    $file = $env:SystemRoot + "\Temp\" + (Get-Date).ToString("MM-dd-yy-hh-mm")
    New-Item $file -ItemType file
</powershell>
<persist>true</persist>
```

要在启动实例时指定实例用户数据，请使用 [New-EC2Instance](https://docs.aws.amazon.com/powershell/latest/reference/items/New-EC2Instance.html) 命令。该命令不会对用户数据进行 base64 编码。使用以下命令在名为 `script.txt` 的文本文件中对用户数据进行编码。

```
PS C:\> $Script = Get-Content -Raw script.txt
PS C:\> $UserData = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($Script))
```

使用 `-UserData` 参数可将用户数据传递到 **New-EC2Instance** 命令。

```
PS C:\> New-EC2Instance -ImageId ami-abcd1234 -MinCount 1 -MaxCount 1 -InstanceType m3.medium \
    -KeyName my-key-pair -SubnetId subnet-12345678 -SecurityGroupIds sg-1a2b3c4d \
    -UserData $UserData
```

**示例：更新已停止实例的实例用户数据**  
您可以使用 [Edit-EC2InstanceAttribute](https://docs.aws.amazon.com/powershell/latest/reference/items/Edit-EC2InstanceAttribute.html) 命令修改已停止的实例的用户数据。

使用新脚本创建一个文本文件。使用以下命令在名为 `new-script.txt` 的文本文件中对用户数据进行编码。

```
PS C:\> $NewScript = Get-Content -Raw new-script.txt
PS C:\> $NewUserData = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($NewScript))
```

使用 `-UserData` 和 `-Value` 参数可指定用户数据。

```
PS C:\> Edit-EC2InstanceAttribute -InstanceId i-1234567890abcdef0 -Attribute userData -Value $NewUserData
```

**示例：查看实例用户数据**  
要检索实例的用户数据，请使用 [Get-EC2InstanceAttribute](https://docs.aws.amazon.com/powershell/latest/reference/items/Get-EC2InstanceAttribute.html) 命令。

```
PS C:\> (Get-EC2InstanceAttribute -InstanceId i-1234567890abcdef0 -Attribute userData).UserData
```

下面是示例输出。请注意，用户数据已编码。

```
PHBvd2Vyc2hlbGw+DQpSZW5hbWUtQ29tcHV0ZXIgLU5ld05hbWUgdXNlci1kYXRhLXRlc3QNCjwvcG93ZXJzaGVsbD4=
```

使用以下命令可将已编码的用户数据存储在变量中，然后对其进行编码。

```
PS C:\> $UserData_encoded = (Get-EC2InstanceAttribute -InstanceId i-1234567890abcdef0 -Attribute userData).UserData
PS C:\> [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($UserData_encoded))
```

下面是示例输出。

```
<powershell>
    $file = $env:SystemRoot + "\Temp\" + (Get-Date).ToString("MM-dd-yy-hh-mm")
    New-Item $file -ItemType file
</powershell>
<persist>true</persist>
```

**示例：重命名实例以匹配标签值**  
要读取标签值、在首次启动时重命名实例以匹配标签值并重新启动，您可以使用 [Get-EC2Tag](https://docs.aws.amazon.com/powershell/latest/reference/items/Get-EC2Tag.html) 命令。要成功运行此命令，您必须将具有 `ec2:DescribeTags` 权限的角色附加到实例上，因为标签信息通过 API 调用检索。有关使用 IAM 角色的设置权限的更多信息，请参阅 [将 IAM 角色附加到实例](attach-iam-role.md)。

------
#### [ IMDSv2 ]

```
<powershell>
    [string]$token = Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token-ttl-seconds" = "21600"} -Method PUT -Uri 'http://169.254.169.254/latest/api/token' -UseBasicParsing
    $instanceId = Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token" = $token} -Method GET -Uri 'http://169.254.169.254/latest/meta-data/instance-id' -UseBasicParsing
	$nameValue = (Get-EC2Tag -Filter @{Name="resource-id";Value=$instanceid},@{Name="key";Value="Name"}).Value
	$pattern = "^(?![0-9]{1,15}$)[a-zA-Z0-9-]{1,15}$"
	#Verify Name Value satisfies best practices for Windows hostnames
	If ($nameValue -match $pattern) 
	    {Try
	        {Rename-Computer -NewName $nameValue -Restart -ErrorAction Stop} 
	    Catch
	        {$ErrorMessage = $_.Exception.Message
	        Write-Output "Rename failed: $ErrorMessage"}}
	Else
	    {Throw "Provided name not a valid hostname. Please ensure Name value is between 1 and 15 characters in length and contains only alphanumeric or hyphen characters"}
</powershell>
```

------
#### [ IMDSv1 ]

```
<powershell>
	$instanceId = (Invoke-WebRequest http://169.254.169.254/latest/meta-data/instance-id -UseBasicParsing).content
	$nameValue = (Get-EC2Tag -Filter @{Name="resource-id";Value=$instanceid},@{Name="key";Value="Name"}).Value
	$pattern = "^(?![0-9]{1,15}$)[a-zA-Z0-9-]{1,15}$"
	#Verify Name Value satisfies best practices for Windows hostnames
	If ($nameValue -match $pattern) 
	    {Try
	        {Rename-Computer -NewName $nameValue -Restart -ErrorAction Stop} 
	    Catch
	        {$ErrorMessage = $_.Exception.Message
	        Write-Output "Rename failed: $ErrorMessage"}}
	Else
	    {Throw "Provided name not a valid hostname. Please ensure Name value is between 1 and 15 characters in length and contains only alphanumeric or hyphen characters"}
</powershell>
```

------

您还可以使用实例元数据中的标签对实例进行重命名，前提是您的实例配置为从实例元数据访问标签。有关更多信息，请参阅 [使用实例元数据来查看 EC2 实例的标签](work-with-tags-in-IMDS.md)。

------
#### [ IMDSv2 ]

```
<powershell>
    [string]$token = Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token-ttl-seconds" = "21600"} -Method PUT -Uri 'http://169.254.169.254/latest/api/token' -UseBasicParsing
	$nameValue = Invoke-RestMethod -Headers @{"X-aws-ec2-metadata-token" = $token} -Method GET -Uri 'http://169.254.169.254/latest/meta-data/tags/instance/Name' -UseBasicParsing
	$pattern = "^(?![0-9]{1,15}$)[a-zA-Z0-9-]{1,15}$"
	#Verify Name Value satisfies best practices for Windows hostnames
	If ($nameValue -match $pattern) 
	    {Try
	        {Rename-Computer -NewName $nameValue -Restart -ErrorAction Stop} 
	    Catch
	        {$ErrorMessage = $_.Exception.Message
	        Write-Output "Rename failed: $ErrorMessage"}}
	Else
	    {Throw "Provided name not a valid hostname. Please ensure Name value is between 1 and 15 characters in length and contains only alphanumeric or hyphen characters"}
</powershell>
```

------
#### [ IMDSv1 ]

```
<powershell>
	$nameValue = Get-EC2InstanceMetadata -Path /tags/instance/Name
	$pattern = "^(?![0-9]{1,15}$)[a-zA-Z0-9-]{1,15}$"
	#Verify Name Value satisfies best practices for Windows hostnames
	If ($nameValue -match $pattern) 
	    {Try
	        {Rename-Computer -NewName $nameValue -Restart -ErrorAction Stop} 
	    Catch
	        {$ErrorMessage = $_.Exception.Message
	        Write-Output "Rename failed: $ErrorMessage"}}
	Else
	    {Throw "Provided name not a valid hostname. Please ensure Name value is between 1 and 15 characters in length and contains only alphanumeric or hyphen characters"}
</powershell>
```

------

# 识别在单个请求中启动的每个实例
<a name="AMI-launch-index-examples"></a>

本示例演示如何使用用户数据和实例元数据来配置 Amazon EC2 实例。

**注意**  
本部分中的示例使用 IMDS 的 IPv4 地址：`169.254.169.254`。如果要通过 IPv6 地址检索 EC2 实例的实例元数据，请确保启用并改用 IPv6 地址：`[fd00:ec2::254]`。IMDS 的 IPv6 地址与 IMDSv2 命令兼容。IPv6 地址仅可在[支持 IPv6 的子网](https://docs.aws.amazon.com/vpc/latest/userguide/configure-subnets.html#subnet-ip-address-range)（双栈或仅 IPv6）中[基于 Nitro 的实例](instance-types.md#instance-hypervisor-type)上访问。

Alice 想要启动她最喜欢的数据库 AMI 的四个实例，第一个实例用作原始实例，其余三个用作副本。当她启动它们时，她想为每个副本添加有关复制策略的用户数据。她知道这些数据将对所有四个实例都可用，因此她所采用的用户数据构建方式必须能够让每个实例识别出哪些部分适用于自己。她可通过 `ami-launch-index` 实例元数据值来实现这一点，该值对每个实例都是唯一的。如果她同时启动多个实例，则 `ami-launch-index` 表示实例启动的顺序。第一个启动的实例的值是 `0`。

以下是 Alice 构建的用户数据。

```
replicate-every=1min | replicate-every=5min | replicate-every=10min
```

`replicate-every=1min` 数据定义第一个副本的配置，`replicate-every=5min` 定义第二个副本的配置，以此类推。Alice 决定以 ASCII 字符串形式提供这些数据，用竖线符号 (`|`) 来分隔每个实例的数据。

Alice 使用 [run-instances](https://docs.aws.amazon.com/cli/latest/reference/ec2/run-instances.html) 命令启动 4 个实例，并指定用户数据。

```
aws ec2 run-instances \
    --image-id ami-0abcdef1234567890 \
    --count 4 \
    --instance-type t2.micro \
    --user-data "replicate-every=1min | replicate-every=5min | replicate-every=10min"
```

实例启动之后，所有实例都有以下用户数据和常用元数据的副本：
+ AMI ID：ami-0abcdef1234567890
+ 预留 ID：r-1234567890abcabc0
+ 公有密钥：无 
+ 安全组名称：默认值
+ 实例类型：t2.micro

但是，每个实例都有唯一的元数据，如下表所示。


| 元数据 | 值 | 
| --- | --- | 
| instance-id | i-1234567890abcdef0 | 
| ami-launch-index | 0 | 
| public-hostname | ec2-203-0-113-25.compute-1.amazonaws.com | 
| public-ipv4 | 67.202.51.223 | 
| local-hostname | ip-10-251-50-12.ec2.internal | 
| local-ipv4 | 10.251.50.35 | 


| 元数据 | 值 | 
| --- | --- | 
| instance-id | i-0598c7d356eba48d7 | 
| ami-launch-index | 1 | 
| public-hostname | ec2-67-202-51-224.compute-1.amazonaws.com | 
| public-ipv4 | 67.202.51.224 | 
| local-hostname | ip-10-251-50-36.ec2.internal | 
| local-ipv4 | 10.251.50.36 | 


| 元数据 | 值 | 
| --- | --- | 
| instance-id | i-0ee992212549ce0e7 | 
| ami-launch-index | 2 | 
| public-hostname | ec2-67-202-51-225.compute-1.amazonaws.com | 
| public-ipv4 | 67.202.51.225 | 
| local-hostname | ip-10-251-50-37.ec2.internal | 
| local-ipv4 | 10.251.50.37 | 


| 元数据 | 值 | 
| --- | --- | 
| instance-id | i-1234567890abcdef0 | 
| ami-launch-index | 3 | 
| public-hostname | ec2-67-202-51-226.compute-1.amazonaws.com | 
| public-ipv4 | 67.202.51.226 | 
| local-hostname | ip-10-251-50-38.ec2.internal | 
| local-ipv4 | 10.251.50.38 | 

Alice 可以使用 `ami-launch-index` 值确定用户数据的哪个部分适用于特定实例。

1. 她连接到其中一个实例并检索该实例的 `ami-launch-index`，以确保该实例是副本之一：

------
#### [ IMDSv2 ]

   ```
   [ec2-user ~]$ TOKEN=`curl -X PUT "http://169.254.169.254/latest/meta-data/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
   && curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/ami-launch-index
   2
   ```

   对于以下步骤，IMDSv2 请求使用前面的 IMDSv2 命令中存储的令牌，并假设令牌尚未过期。

------
#### [ IMDSv1 ]

   ```
   [ec2-user ~]$ curl http://169.254.169.254/latest/meta-data/ami-launch-index
   2
   ```

------

1. 她将 `ami-launch-index` 保存为一个变量。

------
#### [ IMDSv2 ]

   ```
   [ec2-user ~]$ ami_launch_index=`curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/ami-launch-index`
   ```

------
#### [ IMDSv1 ]

   ```
   [ec2-user ~]$ ami_launch_index=`curl http://169.254.169.254/latest/meta-data/ami-launch-index`
   ```

------

1. 她将用户数据保存为一个变量。

------
#### [ IMDSv2 ]

   ```
   [ec2-user ~]$ user_data=`curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/user-data`
   ```

------
#### [ IMDSv1 ]

   ```
   [ec2-user ~]$ user_data=`curl http://169.254.169.254/latest/user-data`
   ```

------

1. 最后，Alice 使用 **cut** 命令提取适用于该实例的用户数据部分。

------
#### [ IMDSv2 ]

   ```
   [ec2-user ~]$ echo $user_data | cut -d"|" -f"$ami_launch_index"
   replicate-every=5min
   ```

------
#### [ IMDSv1 ]

   ```
   [ec2-user ~]$ echo $user_data | cut -d"|" -f"$ami_launch_index"
   replicate-every=5min
   ```

------