简体   繁体   English

带有动态子项的静态组的 Ansible 动态清单

[英]Ansible Dynamic inventory with static group with dynamic children

I am sure many who work with Terraform and Ansible or just Ansible on a daily basis must have come across this question.我相信许多每天使用 Terraform 和 Ansible 或只是 Ansible 的人一定都遇到过这个问题。

Some background:一些背景:

I create my infrastructure on AWS using Terraform and configure my machines using Ansible.我使用 Terraform 在 AWS 上创建我的基础设施,并使用 Ansible 配置我的机器。 my inventory file contains hardcoded public ip addresses with some variables.我的清单文件包含带有一些变量的硬编码公共 IP 地址。 As the business demands, I create and destroy my machines very often.由于业务需要,我经常创建和销毁我的机器。

My question:我的问题:

I want don't want to update my inventory file with new public IP addresses every time I destroy and create my instances.我不想在每次销毁和创建实例时都用新的公共 IP 地址更新我的清单文件。 So my fundamental requirement is - every time I destroy my machine I should be able run my Terraform script to recreate the machines and when I run my Ansible Playbook, Ansible should be able to pick up the right target machines and run the playbook.所以我的基本要求是 - 每次我销毁我的机器时,我应该能够运行我的 Terraform 脚本来重新创建机器,当我运行我的 Ansible Playbook 时,Ansible 应该能够选择正确的目标机器并运行 playbook。 I need to know what I need to describe in my inventory file to achieve this automation.我需要知道我需要在我的库存文件中描述什么来实现这种自动化。 Domain name (www.fooexample.com) and static public IP addresses in the inventory file is not an option in my case?在我的情况下,清单文件中的域名 (www.fooexample.com) 和静态公共 IP 地址不是一个选项? I have seen scripts that do it with, what it looks like a hostname (webserver1)我见过使用它的脚本,它看起来像一个主机名(webserver1)

There are forums that talk about using the ec2.py option but ec2.py is getting all the public ip addresses associated with the account but i only want to target some of the machines as you can imagine and not all of them with my playbook.有一些论坛讨论使用 ec2.py 选项,但 ec2.py 正在获取与该帐户关联的所有公共 IP 地址,但我只想针对您可以想象的一些机器,而不是我的剧本中的所有机器。

Any help regarding this would be appreciated.对此的任何帮助将不胜感激。

Thanks in Advance提前致谢

I do something similar in GCP but the concept should apply to AWS.我在 GCP 中做了类似的事情,但这个概念应该适用于 AWS。

Starting with Ansible 2.7 there is a new inventory plugin architecture and some inventory plugins to replace the dynamic inventory scripts (such as ec2.py and gcp.py ).从 Ansible 2.7 开始,有一个新的清单插件架构和一些清单插件来替换动态清单脚本(例如ec2.pygcp.py )。 The AWS plugin documentation is at https://docs.ansible.com/ansible/2.9/plugins/inventory/aws_ec2.html . AWS 插件文档位于https://docs.ansible.com/ansible/2.9/plugins/inventory/aws_ec2.html

First, you need to tag the groups of hosts you want to target in AWS.首先,您需要标记要在 AWS 中定位的主机组。 You should be able to handle this with Terraform (such as Service = Web ).您应该能够使用 Terraform 处理此问题(例如Service = Web )。

Next, enable the aws_ec2 plugin in ansible.cfg by adding:接下来,使aws_ec2插件在ansible.cfg加入:

[inventory]
enable_plugins = aws_ec2

Now, convert over to using the new plugin instead of ec2.py .现在,转换为使用新插件而不是ec2.py This means creating a aws_ec2.yaml file based on the documentation.这意味着根据文档创建aws_ec2.yaml文件。 An example might look like:一个示例可能如下所示:

plugin: aws_ec2
regions:
  - us-east-1
keyed_groups:
  - prefix: tag
    key: tags
# Set individual variables with compose
compose:
  ansible_host: public_ip_address

The key parts here are the keyed_groups and compose section.这里的关键部分是keyed_groupscompose部分。 This will give you the public IP addresses as the host to connect to in inventory and groups you can limit to with -l or --limit .这将为您提供公共 IP 地址作为要连接到清单和组中的主机,您可以使用-l--limit进行限制。

Considering you had some instances in us-east-1 tagged with Service = Web you could target them like:考虑到您在us-east-1有一些带有Service = Web标记的实例,您可以像这样定位它们:

ansible -i aws_ec2.yaml -m ping -l tag_Service_Web

This would target just those tagged hosts on their public IP address.这将仅针对其公共 IP 地址上的那些标记主机。 Any dynamic scaling you do (such as increasing the count in Terraform for that resource) will be picked up by the inventory plugin on next run.您所做的任何动态缩放(例如在 Terraform 中增加该资源的计数)都将在下次运行时由清单插件获取。

You can also use the tag in playbooks.您还可以在剧本中使用该标签。 If you had a playbook that you always targeted at these hosts you can set hosts: tag_Service_Web in the playbook.如果你有一个总是针对这些主机的剧本,你可以在剧本中设置hosts: tag_Service_Web

Bonus:奖金:

I've been experimenting with an Ansible Pull model that automates some of this bootstrapping.我一直在试验Ansible Pull模型,该模型可以自动执行一些此类引导。 The idea is to combine cloud-init with a special script to bootstrap the playbook for that host automatically.这个想法是将cloud-init与一个特殊的脚本结合起来,以自动引导该主机的剧本。

Example script that cloud-init kicks off: cloud-init启动的示例脚本:

#!/bin/bash

set -euo pipefail

lock_files=(
    /var/lib/dpkg/lock
    /var/lib/apt/lists/lock
    /var/lib/dpkg/lock-frontend
    /var/cache/apt/archives/lock
    /var/lib/apt/daily_lock
)

export ANSIBLE_HOST_PATTERN_MISMATCH="ignore"
export PATH="/tmp/ansible-venv/bin:$PATH"

for file in "${lock_files[@]}"; do
    while fuser "$file" >/dev/null 2>&1; do
        echo "Waiting for lock $file to be available..."
        sleep 5
    done
done

apt-get update -qy
apt-get install --no-install-recommends -qy virtualenv python-virtualenv python-nacl python-wheel python-bcrypt

virtualenv -p /usr/bin/python --system-site-packages /tmp/ansible-venv
pip install ansible==2.7.10 apache-libcloud==2.3.0 jmespath==0.9.3

ansible-pull myplaybook.yaml \
    -U git@github.com:myorg/infrastructure.git \
    -i gcp_compute.yaml \
    --private-key /tmp/ansible-keys/infrastructure_ssh_deploy_key \
    --vault-password-file /tmp/ansible-keys/vault \
    -d /tmp/ansible-infrastructure \
    --accept-host-key

This script is a bit simplified from my actual one (leaving out some domain specific authentication and key providing stuff).这个脚本比我的实际脚本稍微简化了一些(省略了一些特定于域的身份验证和密钥提供的东西)。 But you can adapt it to AWS by doing something like bootstrapping keys from S3 or KMS or another boot time configuration service.但是您可以通过执行诸如从 S3 或 KMS 或其他启动时配置服务引导密钥之类的操作来使其适应 AWS。 I find that ansible-pull works well when the playbook only takes a minute or two to run and doesn't have any dependencies on external inventory (like references to other groups such as to gather IP addresses).我发现ansible-pull当剧本只需要运行一两分钟并且对外部清单没有任何依赖(例如对其他组的引用,例如收集 IP 地址)时效果很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM