我正在使用 Ansible 启动和配置当前基于 AMI(ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-server-20161020 (ami-40d28157))的 EC2 实例,该实例从一开始就没有安装 Python。
由于大多数 ansible 模块都需要远程机器上的 python 才能工作,因此我尝试使用用户数据脚本。
它有点工作正常(Python 安装正确),但 ansibleec2任务返回前user_data 脚本运行完毕,因此后续任务(实际配置实例的任务)失败并显示错误'/bin/sh: 1: /usr/bin/python: not found\r\n'
/usr/bin/python
由于没有 python,我甚至无法在远程主机上运行大多数任务,例如,我无法简单地检查标记文件是否存在,或者检查系统日志输出。
我考虑过nc -l $SOME_PORT
在 user_data 脚本末尾添加一个并使用wait_for
模块进行检查,但这对我来说听起来太过分了。
有没有办法使用ec2模块启动一个实例,以便它等待 user_data 脚本运行完成?
以供参考:
与我正在使用的类似的剧本:
- name: Create the EC2 instance
hosts: localhost
gather_facts: false
vars:
name: myinstance
ami: ami-40d28157
#Other vars ommited for brevity
tasks:
- name: Launch Instance
ec2:
key_name: "{{ keypair }}"
group: "{{ security_group }}"
instance_type: "{{ instance_type }}"
image: "{{ ami }}"
user_data: "{{ lookup('file', 'user_data.sh') }}"
wait: true
region: "{{ region }}"
vpc_subnet_id: "{{ subnet }}"
assign_public_ip: no
zone: "{{ zone }}"
instance_tags: "{{ tag_map }}"
exact_count: 1
count_tag:
Name: "{{ name }}"
register: ec2
- name: Add new Instance to host group
add_host: name={{ item.private_ip }} groups={{ name }}
with_items: "{{ ec2.instances }}"
- name: Wait for SSH to come up
wait_for: host={{ item.private_ip }} port=22 delay=60 timeout=320 state=started
with_items: "{{ ec2.instances }}"
- name: Configure instance(s)
hosts: myinstance
tasks:
- name: Example task
command: touch a_file
user_data.sh脚本:
#!/bin/bash
set -e -x
export DEBIAN_FRONTEND=noninteractive
sudo locale-gen pt_BR.UTF-8
sudo apt-get update && apt-get upgrade -y
sudo apt-get install -y python-minimal
答案1
这是你的问题的答案“使用 ansible 启动 EC2 实例时如何等待用户数据脚本运行?”:
- raw: test -f /var/lib/cloud/instance/boot-finished
retries: 20
register: cmd_res
changed_when: false
until: cmd_res | success
这将通过 ssh 连接并在boot-finished
存在时成功,这是cloud-init
在主机上的模块完成所有模块(包括 user_data 脚本)后创建的。
但我建议创建预装 Python 的 AMI,或者使用raw
Ansiblescript
模块来检查/安装 Python(这些模块不需要 Python)。
答案2
事实证明你可以使用cloud-init
命令来实现这一点,即:
cloud-init status --wait
因此,您应该将以下代码片段添加到您的剧本中:
- name: Wait for cloud-init / user-data to finish
command: cloud-init status --wait
changed_when: false
与第一个答案相比,它看起来更清晰一些。