动态清单插件
动态清单插件允许用户指向数据源来编译 Ansible 用于定位任务的主机清单,可以通过 -i /path/to/file
和/或 -i 'host1, host2'
命令行参数或其他配置源实现。
当使用 Ansible 与 AWS 时,清单文件的维护将是一项繁琐的任务,因为 AWS 经常更改 IP 地址、自动伸缩实例等等。一旦您的 AWS EC2 主机启动,您可能又需要再次与它们通信。对于云端设置,最好不要在文本文件中维护静态的云主机名列表。相反,最佳方法是使用 aws_ec2
动态清单插件。
aws_ec2
动态清单插件会调用 AWS API 来获取运行时 Amazon Web Services EC2 中的主机清单列表。它动态地提供 EC2 实例详细信息以管理 AWS 基础设施。
该插件还会返回在 Ansible 之外创建的实例,并允许 Ansible 管理它们。
要开始使用带有 YAML 配置源的 aws_ec2
动态清单插件,请创建一个符合插件文档中所述的已接受文件名模式的文件(以 aws_ec2.(yml|yaml)
结尾的 YAML 配置文件,例如 demo.aws_ec2.yml
),然后添加 plugin: amazon.aws.aws_ec2
。如果插件位于集合中,请使用完全限定名称。
身份验证
如果您的 Ansible 控制器不在 AWS 中,则身份验证通过指定您的访问密钥和密钥作为环境变量或清单插件参数来处理。
对于环境变量
export AWS_ACCESS_KEY_ID='AK123'
export AWS_SECRET_ACCESS_KEY='abc123'
也可以使用 AWS_SECURITY_TOKEN
环境变量,但这仅为了向后兼容而支持。AWS_SECURITY_TOKEN
是 AWS_SESSION_TOKEN
的替代品,只有在使用临时凭据时才需要它。
或者您可以在清单配置文件中设置 aws_access_key
、aws_secret_key
和 security_token
。
# demo.aws_ec2.yml
plugin: amazon.aws.aws_ec2
# The access key for your AWS account.
aws_access_key: <YOUR-AWS-ACCESS-KEY-HERE>
# The secret access key for your AWS account.
aws_secret_key: <YOUR-AWS-SECRET-KEY-HERE>
如果您对不同的工具或应用程序使用不同的凭据,则可以使用配置文件。
profile
参数与 aws_access_key
、aws_secret_key
和 security_token
选项互斥。当没有明确提供凭据时,Ansible 使用的 AWS SDK (boto3) 将回退到其配置文件(通常为 ~/.aws/credentials
)。共享凭据文件的默认位置为 ~/.aws/credentials
。您可以通过设置 AWS_SHARED_CREDENTIALS_FILE
环境变量来更改共享凭据文件的位置。
# demo.aws_ec2.yml
plugin: amazon.aws.aws_ec2
# Attach the default AWS profile
aws_profile: default
# You could use Jinja2 to attach the AWS profile from the environment variable.
aws_profile: "{{ lookup('env', 'AWS_PROFILE') | default('dev-profile', true) }}"
您也可以将您的 AWS 配置文件设置为环境变量
export AWS_PROFILE='test-profile'
如果您的 Ansible 控制器运行在分配了 IAM 角色的 EC2 实例上,则可以省略凭据。有关更多详细信息,请参阅控制器的文档 了解更多详情。
您还可以使用 IAM 角色的 ARN 来承担执行清单查找的操作。这对于跨不同帐户连接或限制用户访问非常有用。为此,您应该指定 iam_role_arn
。您仍然应该提供具有足够权限来执行 AssumeRole 操作的 AWS 凭据。
# demo.aws_ec2.yml
plugin: amazon.aws.aws_ec2
iam_role_arn: arn:aws:iam::1234567890:role/assumed-ansible
最小示例
获取 us-east-1 中的所有主机,主机名如果存在则为公共 DNS,否则为私有 IP 地址。
# demo.aws_ec2.yml
plugin: amazon.aws.aws_ec2
# This sets the region. If empty (the default) default this will include all regions, except possibly
# restricted ones like us-gov-west-1 and cn-north-1.
regions:
- us-east-1
提供任何必要的选项后,您可以使用 ansible-inventory -i demo.aws_ec2.yml --graph
查看已填充的清单。
@all:
|--@aws_ec2:
| |--ip-10-210-0-189.ec2.internal
| |--ip-10-210-0-195.ec2.internal
|--@ungrouped:
允许的选项
下面详细解释了一些 aws_ec2
动态清单插件选项。有关完整列表,请参阅 插件文档。
hostnames
hostnames
选项提供了不同的设置来选择如何显示主机名。
下面显示了一些示例
hostnames:
# This option allows displaying the public ip addresses.
- ip-address
# This option allows displaying the private ip addresses using `tag:Name` as a prefix.
# `name` can be one of the options specified in http://docs.aws.amazon.com/cli/latest/reference/ec2/describe-instances.html#options.
- name: 'private-ip-address'
separator: '_'
prefix: 'tag:Name'
# Using literal values for hostname
# # Hostname will be aws-test_literal
- name: 'test_literal'
separator: '-'
prefix: 'aws'
# To use tags as hostnames use the syntax `tag:Name=Value` to use the hostname `Name_Value`, or
# `tag:Name` to use the value of the Name tag. If value provided does not exist in the above options,
# it will be used as a literal string.
- name: 'tag:Tag1=Test1,Tag2=Test2'
# Use dns-name attribute as hostname
- dns-name
# You can also specify a list in order of precedence for hostname variables.
- ip-address
- dns-name
- tag:Name
- private-ip-address
默认情况下,清单只会返回与hostnames
条目中第一个匹配项。您可能希望获取清单中所有潜在的匹配项,这也意味着您将获得重复的条目。要切换到此行为,请将allow_duplicated_hosts
配置键设置为True
。
keyed_groups
您可以使用主机变量和keyed_groups
选项创建动态组。keyed_groups
采用前缀和键的格式。前缀将是主机组的名称,它将与键连接。
下面显示了一些示例
keyed_groups:
# This creates host groups based on architecture.
- prefix: arch
key: architecture
# This creates host groups based on `x86_64` architecture.
- prefix: arch
key: architecture
value:
'x86_64'
# This creates host groups based on availability zone.
- prefix: az
key: placement.availability_zone
# If the EC2 tag Name had the value `redhat` the tag variable would be: `tag_Name_redhat`.
# Similarly, if a tag existed for an AWS EC2 instance as `Applications` with the value of `nodejs` the
# variable would be: `tag_Applications_nodejs`.
- prefix: tag
key: tags
# This creates host groups using instance_type, e.g., `instance_type_z3_tiny`.
- prefix: instance_type
key: instance_type
# This creates host groups using security_groups id, e.g., `security_groups_sg_abcd1234` group for each security group.
- key: 'security_groups|json_query("[].group_id")'
prefix: 'security_groups'
# This creates a host group for each value of the Application tag.
- key: tags.Application
separator: ''
# This creates a host group per region e.g., `aws_region_us_east_2`.
- key: placement.region
prefix: aws_region
# This creates host groups based on the value of a custom tag `Role` and adds them to a metagroup called `project`.
- key: tags['Role']
prefix: foo
parent_group: "project"
# This creates a common parent group for all EC2 availability zones.
- key: placement.availability_zone
parent_group: all_ec2_zones
# This creates a group per distro (distro_CentOS, distro_Debian) and assigns the hosts that have matching values to it,
# using the default separator "_".
- prefix: distro
key: ansible_distribution
groups
也可以使用groups
选项创建组。
下面显示了一些示例
groups:
# This created two groups - `Production` and `PreProduction` based on tags
# These conditionals are expressed using Jinja2 syntax.
redhat: "'Production' in tags.Environment"
ubuntu: "'PreProduction' in tags.Environment"
# This created a libvpc group based on specific condition on `vpc_id`.
libvpc: vpc_id == 'vpc-####'
compose
compose
根据Jinja2表达式创建和修改主机变量。
compose:
# This sets the ansible_host variable to connect with the private IP address without changing the hostname.
ansible_host: private_ip_address
# This sets location_vars variable as a dictionary with location as a key.
location_vars:
location: "east_coast"
server_type: "ansible_hostname | regex_replace ('(.{6})(.{2}).*', '\\2')"
# This sets location variable.
location: "'east_coast'"
# This lets you connect over SSM to the instance id.
ansible_host: instance_id
ansible_connection: 'community.aws.aws_ssm'
# This defines combinations of host servers, IP addresses, and related SSH private keys.
ansible_host: private_ip_address
ansible_user: centos
ansible_ssh_private_key_file: /path/to/private_key_file
# This sets the ec2_security_group_ids variable.
ec2_security_group_ids: security_groups | map(attribute='group_id') | list | join(',')
# Host variables that are strings need to be wrapped with two sets of quotes.
# See https://docs.ansible.org.cn/ansible/latest/plugins/inventory.html#using-inventory-plugins for details.
ansible_connection: '"community.aws.aws_ssm"'
ansible_user: '"ssm-user"'
include_filters
和 exclude_filters
include_filters
和 exclude_filters
选项使您可以使用多个查询组合清单(参见可用过滤器)。
include_filters:
# This includes everything in the inventory that has the following tags.
- tag:Project:
- 'planets'
- tag:Environment:
- 'demo'
# This excludes everything from the inventory that has the following tag:Name.
exclude_filters:
- tag:Name:
- '{{ resource_prefix }}_3'
filters
filters
用于根据条件过滤AWS EC2实例(参见可用过滤器)。
filters:
# This selects only running instances with tag `Environment` tag set to `dev`.
tag:Environment: dev
instance-state-name : running
# This selects only instances with tag `Environment` tag set to `dev` and `qa` and specific security group id.
tag:Environment:
- dev
- qa
instance.group-id: sg-xxxxxxxx
# This selects only instances with tag `Name` fulfilling specific conditions.
- tag:Name:
- dev-*
- share-resource
- hotfix
use_contrib_script_compatible_ec2_tag_keys
和 use_contrib_script_compatible_sanitization
当use_contrib_script_compatible_ec2_tag_keys
为True时,它会像旧的ec2.py清单脚本一样公开带有ec2_tag_TAGNAME键的主机标签。
默认情况下,aws_ec2
插件使用一般的组名清理方法来创建安全且可用的组名,以便在Ansible中使用。
use_contrib_script_compatible_ec2_tag_keys
允许您覆盖此设置,以方便从旧的清单脚本迁移,并在脚本的replace_dash_in_groups选项设置为False时匹配组的清理。要使用构造的组复制replace_dash_in_groups = True的行为,您需要使用regex_replace过滤器将这些条目的连字符替换为下划线。
要使此方法有效,您还应关闭TRANSFORM_INVALID_GROUP_CHARS设置,否则核心引擎将只使用标准清理方法。
这不是默认设置,因为这样的名称会破坏某些功能,因为并非所有字符都是有效的Python标识符,而组名最终会被用作Python标识符。
不建议使用此功能,我们建议迁移到新的标签结构。
# demo.aws_ec2.yml
plugin: amazon.aws.aws_ec2
regions:
- us-east-1
filters:
tag:Name:
- 'instance-*'
hostnames:
- tag:Name
use_contrib_script_compatible_sanitization: True
use_contrib_script_compatible_ec2_tag_keys: True
提供任何必需的选项后,您可以使用ansible-inventory -i demo.aws_ec2.yml --list
查看填充的清单。
{
"_meta": {
"hostvars": {
"instance-01": {
"aws_ami_launch_index_ec2": 0,
"aws_architecture_ec2": "x86_64",
...
"ebs_optimized": false,
"ec2_tag_Environment": "dev",
"ec2_tag_Name": "instance-01",
"ec2_tag_Tag1": "Test1",
"ec2_tag_Tag2": "Test2",
"ena_support": true,
"enclave_options": {
"enabled": false
},
...
},
"instance-02": {
...
"ebs_optimized": false,
"ec2_tag_Environment": "dev",
"ec2_tag_Name": "instance-02",
"ec2_tag_Tag1": "Test3",
"ec2_tag_Tag2": "Test4",
"ena_support": true,
"enclave_options": {
"enabled": false
},
...
}
}
},
all": {
"children": [
"aws_ec2",
"ungrouped"
]
},
"aws_ec2": {
"hosts": [
"instance-01",
"instance-02"
]
}
}
hostvars_prefix
和 hostvars_suffix
hostvars_prefix
和 hostvars_sufix
允许为主机变量设置前缀和后缀。
# demo.aws_ec2.yml
plugin: amazon.aws.aws_ec2
regions:
- us-east-1
filters:
tag:Name:
- 'instance-*'
hostvars_prefix: 'aws_'
hostvars_suffix: '_ec2'
hostnames:
- tag:Name
现在是ansible-inventory -i demo.aws_ec2.yml --list
的输出。
{
"_meta": {
"hostvars": {
"instance-01": {
"aws_ami_launch_index_ec2": 0,
"aws_architecture_ec2": "x86_64",
"aws_block_device_mappings_ec2": [
{
"device_name": "/dev/sda1",
"ebs": {
"attach_time": "2022-06-27T09:04:57+00:00",
"delete_on_termination": true,
"status": "attached",
"volume_id": "vol-06e065bca44e6eae5"
}
}
],
"aws_capacity_reservation_specification_ec2": {
"capacity_reservation_preference": "open"
}
...,
},
"instance-02": {
...,
}
}
},
all": {
"children": [
"aws_ec2",
"ungrouped"
]
},
"aws_ec2": {
"hosts": [
"instance-01",
"instance-02"
]
}
}
strict
和 strict_permissions
strict: False
如果缺少事实,将跳过而不是产生错误。
strict_permissions: False
将忽略403错误,而不是失败。
use_ssm_inventory
use_ssm_inventory: True
启用从AWS Systems Manager (SSM)清单服务获取附加的EC2实例信息到hostvars。通过利用SSM清单数据,use_ssm_inventory
选项提供了关于清单中EC2实例的更多详细信息和属性。这些详细信息可能包括操作系统信息、已安装软件、网络配置以及在SSM中定义的自定义清单属性。
cache
aws_ec2
清单插件支持缓存,可以使用ansible.cfg
文件[defaults]
部分中定义的事实缓存的一般设置,或者在[inventory]
部分中定义清单特定的设置。您可以在配置文件中定义插件特定的缓存设置。
# demo.aws_ec2.yml
plugin: aws_ec2
# This enables cache.
cache: yes
# Plugin to be used.
cache_plugin: jsonfile
cache_timeout: 7200
# Location where files are stored in the cache.
cache_connection: /tmp/aws_inventory
cache_prefix: aws_ec2
这是一个在ansible.cfg
文件中设置清单缓存以及用于缓存插件的一些事实缓存默认值和超时的示例。
[defaults]
fact_caching = ansible.builtin.jsonfile
fact_caching_connection = /tmp/ansible_facts
cache_timeout = 3600
[inventory]
cache = yes
cache_connection = /tmp/ansible_inventory
复杂示例
这是一个使用前面列出的一些选项的aws_ec2
复杂示例。
# demo.aws_ec2.yml
plugin: amazon.aws.aws_ec2
regions:
- us-east-1
- us-east-2
keyed_groups:
# add hosts to tag_Name_value groups for each aws_ec2 host's tags.Name variable.
- key: tags.Name
prefix: tag_Name_
separator: ""
groups:
# add hosts to the group dev if any of the dictionary's keys or values is the word 'dev'.
development: "'dev' in (tags|list)"
filters:
tag:Name:
- 'instance-01'
- 'instance-03'
include_filters:
- tag:Name:
- 'instance-02'
- 'instance-04'
exclude_filters:
- tag:Name:
- 'instance-03'
- 'instance-04'
hostnames:
# You can also specify a list in order of precedence for hostname variables.
- ip-address
- dns-name
- tag:Name
- private-ip-address
compose:
# This sets the `ansible_host` variable to connect with the private IP address without changing the hostname.
ansible_host: private_ip_address
如果主机没有上述配置中的变量(即tags.Name
,tags
,private_ip_address
),则主机将不会添加到清单插件创建的组以外的组中,并且ansible_host
主机变量将不会被修改。
现在是ansible-inventory -i demo.aws_ec2.yml --graph
的输出。
@all:
|--@aws_ec2:
| |--instance-01
| |--instance-02
|--@tag_Name_instance_01:
| |--instance-01
|--@tag_Name_instance_02:
| |--instance-02
|--@ungrouped:
在剧本中使用动态清单
如果您想在剧本中使用动态清单,您只需要在hosts变量中提及组名,如下所示。
---
- name: Ansible Test Playbook
gather_facts: false
hosts: tag_Name_instance_02
tasks:
- name: Run Shell Command
command: echo "Hello World"