Ansible:如何在DNS分配之前设置主机名

时间:2014-02-12 21:54:32

标签: ansible ansible-playbook

在将主机名分配给服务器之前,是否有人有更好的解决方案来配置具有主机名的实例?

假设我们正在使用AWS并实例化实例 ec2-1-2-3-4.compute-1.amazonaws.com 。配置完成后,我们最终会在 new-instance.example.com 的DNS中为其分配一个CNAME,以替换已在生产中的现有实例。

new-instance.example.com 已经存在且正在制作中,因此我们无法将CNAME重新分配给 ec2-1-2-3-4.compute-1。 amazonaws.com 直到机器配置正确,我们准备切换。我们现在希望内部配置文件和实例上的主机名 new-instance.example.com ,以准备DNS更改。因此,我们无法使用 inventory_hostname 变量,因为它将是 ec2-1-2-3-4.compute-1.amazonaws.com 。我也有普通的生产服务器,不需要使用新的主机名,所以我希望能够使用现有的 inventory_hostname

到目前为止,我最好的想法是在清单文件中分配一个变量:

[production]
ec2-1-2-3-4.compute-1.amazonaws.com new_hostname=new-instance.example.com

在剧本中,我可以测试是否存在 new_hostname 。如果 new_hostname 存在,则使用它,如果不存在,则使用 inventory_hostname 。这将导致致命错误,除非 error_on_undefined_vars 设置为 false ,并且我不希望将其设置为防止打字错误的好处。以下是失败的一个例子。

测试手册:

- hosts: all
  tasks:
    - name: "Debug hostname"
      debug: msg="inventory_hostname={{ inventory_hostname }}, hostvars[inventory_hostname]['inventory_hostname']={{ hostvars[inventory_hostname]['inventory_hostname'] }}, ansible_hostname={{ ansible_hostname }}, new_hostname={{ new_hostname }}"
      ignore_errors: yes

结果:

TASK: [Debug hostname] ********************************************************
fatal: [ec2-1-2-3-4.compute-1.amazonaws.com] => One or more undefined variables: 'new_hostname' is undefined

为每个服务器设置 new_hostname 都可以,但我不想为每个服务器设置它,只需要为需要新主机名的服务器设置它。它还会破坏主机名分组,如:

ec2-1-2-3- [4:5] .compute-1.amazonaws.com

如果 new_hostname 存在,则可以:

- name: "set hostname fact"
  set_fact: testvar1={{ new_hostname }} || {{ inventory_hostname }}

- name: "show hostname fact"
  debug: msg="testvar1={{ testvar1 }}"

结果:

TASK: [set hostname fact] *****************************************************
ok: [ec2-1-2-3-4.compute-1.amazonaws.com]

TASK: [show hostname fact] ****************************************************
ok: [ec2-1-2-3-4.compute-1.amazonaws.com] => {"msg": "testvar1=new-instance.example.com"}

如果 error_on_undefined_vars 设置为默认值 true ,但未设置 new_hostname ,则会失败。

此策略的最佳做法?

4 个答案:

答案 0 :(得分:6)

非常害羞,因为我也是新手,如果我理解你的问题,一种方法是在任务上使用when: something is defined

示例:

  tasks:
    - name: "Debug hostname"
      debug: msg="inventory_hostname={{ inventory_hostname }}, hostvars[inventory_hostname]['inventory_hostname']={{ hostvars[inventory_hostname]['inventory_hostname'] }}, ansible_hostname={{ ansible_hostname }}, new_hostname={{ new_hostname }}"
      when: new_hostname is defined

现在这是一种方法。另一种方法是为此发挥作用,并且只能从库存中添加的条目中将该角色(旋转过程)分别发挥到目标机器。如果您愿意,可以查看best practices以获得额外的阅读。

答案 1 :(得分:4)

站起来cloud-init设置主机名。 (我使用Chef,但这与解决方案无关)。这解决了在自动化框架中设置主机名的问题,因为它已经在节点启动时设置了。

我的部分云配置设置了fqdnmanage_etc_hosts选项,如下所示:

fqdn: new-instance.example.com
manage_etc_hosts: true

doc/examples directory中有很多示例配置片段,很容易玩,并找到你喜欢的设置。

答案 2 :(得分:3)

如果您的DNS名称具有模式,则when的一种方法如下:假定您始终定义new_hostname变量:

- include: tasks/sometasks.yml
  when: "'new' in new_hostname"

然后,您可以像您提到的那样在广告资源中定义new_hostname变量:

[production]
ec2-1-2-3-4.compute-1.amazonaws.com new_hostname=new-instance.example.com
ec2-5-6-7-8.compute-1.amazonaws.com new_hostname=nada

此处的关键是始终定义变量并查找匹配或不匹配的模式。您的广告资源和命令行变量应覆盖您的Playbook变量。

更多地应用于您的案例:

tasks:
  - name: "set hostname fact"
    set_fact: testvar1={{ new_hostname }}
    when: "'new' in new_hostname"

  - name: "set hostname fact"
    set_fact: testvar1={{ inventory_hostname }}
    when: "'nada' in new_hostname"

要记住的一点是不要在你的剧本中定义new_hostname变量,否则你的库存变量会被覆盖。

此外,您不希望通过命令行传递它,该命令行也将覆盖清单文件中定义的命令行(对于所有服务器):

ansible-playbook -i <your-inventory> -e "new_hostname=new-instance.example.com" yourplaybook.xml

这是根据Ansible变量优先级:

  
      
  • -e变量总是胜利
  •   
  • 然后出现“最重要的一切”
  •   
  • 然后是库存中定义的变量
  •   
  • 然后是“角色默认值”,这是最“默认”并且优先于所有内容。
  •   

答案 3 :(得分:0)

[production]]

ec2-1-2-3-4.compute-1.amazonaws.com new_hostname=new-instance.example.com

我认为以这种方式设置主机名是可以的,但是Ansible可能需要单独的主机

  tasks:

     - name: change name

       raw: "echo {{new_hostname|quote}} > /etc/hostname"

     - name:

       shell: hostname {{new_hostname|quote}}