在 EC2 实例上使用用户数据脚本运行 ansible-playbook

Posted

技术标签:

【中文标题】在 EC2 实例上使用用户数据脚本运行 ansible-playbook【英文标题】:Run ansible-playbook with a user-data script on an EC2 instance 【发布时间】:2016-10-14 06:20:58 【问题描述】:

我正在使用 Packer 和 Ansible 创建 AWS EC2 映像 (AMI)。 Ansible 用于安装 Java 8,安装数据库(Cassandra),安装 Ansible 并上传 Ansible playbook(我知道我应该将 playbook 推送到 git 并拉取它,但当它工作时我会这样做)。我正在安装 Ansible 并上传剧本,因为当从 AMI 启动实例时,我必须更改一些 Cassandra 属性(例如,在 Cassandra 选项中添加当前实例 IP)。为了实现这一点,我编写了一个简单的 bash 脚本,将其添加为 user-data-file 属性。这是脚本:

#cloud-boothook
#!/bin/bash 

#cloud-config
output: all: '| tee -a /var/log/cloud-init-output.log'


ansible-playbook -i "localhost," -c local /usr/local/etc/replace_cassandra.yaml

如您所见,我正在本地模式下执行 ansible-playbook。

问题是当我启动实例时,我在/var/log/cloud-init.log 文件中发现了一个错误。错误指出,找不到ansible-playbook。所以我在用户数据脚本中添加了一个ls 行来检查/usr/bin/ 文件夹(安装Ansible 的文件夹)的内容并且其中没有Ansible,但是当我使用ssh 访问实例时我可以看到 Ansible 存在于 /usr/bin/ 文件夹中,执行 ansible-playbook 没有问题。

有没有人遇到过类似的问题?我认为这应该是 Ansible 与 EC2 的一个非常流行的用例。


编辑

经过一些日志,我发现在执行用户数据的过程中,不仅没有 Ansible,而且数据库也丢失了。

是否有可能在实例启动时执行 Packer 中 Ansible 配置程序中的部分代码(或全部代码)?


EDIT2

我发现这里发生了什么。当我通过加壳程序通过user_data_file 属性添加用户数据时,用户数据在加壳程序午餐实例以构建 AMI 时执行。该脚本在执行 Ansible 配置程序之前启动,这就是缺少 Ansible 的原因。

我想要做的是自动将用户数据添加到 AMI,这样当从 AMI 启动实例时,将执行用户数据,而不是在打包程序构建所述 AMI 时执行。

关于如何做到这一点的任何想法?

【问题讨论】:

您的#cloud-config 格式似乎有误。尝试将 ansible-playbook 命令放入 bootcmd: 像这样 doc 我认为这不是问题所在。正如我在问题中所说,/usr/bin 文件夹中没有 ansible-playbook,这就是代码不起作用的原因。 这里有类似的问题,只是没有打包器: pip install ansible; ansible-playbook ... 失败,命令 not foud for ansible-playbook 很高兴知道我不是唯一一个遇到同样问题的人。 @JukkaDahlbom 你可以检查pip install ansible 是否真的安装了ansible。我正在使用 apt,它需要添加 ansible repo,然后才能安装。 【参考方案1】:

只需运行多个配置器,不要尝试通过 cloud-init 运行 ansible。

我在这里假设您的剧本和角色存储在您开始运行打包程序的本地。与其将 ansible 内容硬塞到用户数据中,不如运行一个 shell 配置器来安装 ansbile,运行 ansible-local 配置器来运行你想要的剧本/角色。

下面是我所说的一个简化示例。如果没有构建器配置中的更多值,它将无法运行,但为了简洁起见,我将它们省略了。

在示例 json 中,install-prereqs.sh 只是添加 ansible ppa apt repo 并运行 apt-get update -y,然后安装 ansible。

#!/bin/bash

sudo apt-get install software-properties-common
sudo apt-add-repository -y ppa:ansible/ansible
sudo apt-get update
sudo apt-get install -y ansible

然后,第二个配置器会将您指定的剧本和角色复制到目标主机并运行它们。


"builders": [
  
    "type": "amazon-ebs",
    "ssh_username": "ubuntu",
    "image_name": "some-name",
    "source_image": "some-ami-id",
    "ssh_pty": true
  
],
"provisioners": [
  
    "type": "shell",
    "script": "scripts/install-prereqs.sh"
  ,
  
    "type": "ansible-local",
    "playbook_file": "path/to/playbook.yml",
    "role_paths": ["path/to/roles"]
  ,
 ]

【讨论】:

【参考方案2】:

这是可能的!请确认以下事项。

Ansible 服务器(如果未内置在 AMI 中,则通过云形成用户数据安装 ansible)并且您的目标在您在 cloudformation 中创建的安全组中具有 SSH 访问权限。 在 ansible 服务器上安装 ansible 后,您的 ansible.cfg 文件指向 ansible 服务器上的私钥 与 ansible 私钥匹配的公钥被复制到服务器上您希望运行 playbook 的 root 用户 .ssh 目录中的 authorized_keys 文件中 -您已启用 ansible 服务器和目标服务器之间的 root ssh 访问,这可以通过编辑 /etc/ssh/sshd_config 文件并确保没有任何东西阻止 root 用户的 SSH 访问来完成目标服务器上的 authorized_keys 文件

【讨论】:

以上是关于在 EC2 实例上使用用户数据脚本运行 ansible-playbook的主要内容,如果未能解决你的问题,请参考以下文章

如何将 redshift 数据库连接到在 ec2 实例上运行的 bash 脚本

我想在代码部署运行时在新的自动扩展组替换的EC2实例上运行脚本

如何触发 EC2 实例并在每个实例上上传/运行启动脚本?

我想在运行代码部署时在被新自动缩放组替换的 EC2 实例上运行脚本

通过用户数据在 EC2 实例上安装 CodeDeploy 代理

使用用户指定的脚本重新启动现有 Amazon EC2 实例?