Openstack Heat 和 Ansible。虚拟机启动和应用程序部署

Openstack Heat & Ansible. VM spinup and App deployment

我正在使用 openstack heat 模板启动新的 VM,并获取新启动的 VM 的 IP 列表。我正在使用 Ansible 脚本。

我能够从 heat 中获取新的 IP 列表,并且能够使用 with_items 按顺序部署应用程序。

如何使用 Ansible 脚本并行部署,以便 "n" 服务器上的总部署时间与一台服务器上的总部署时间相同。

一个选项是创建一个 dynamic inventory script,它将从 Heat 获取实例 ips 并使它们可用于 Ansible。考虑一个如下所示的 Heat 模板:

heat_template_version: 2014-10-16

resources:

  nodes:
    type: OS::Heat::ResourceGroup
    properties:
      count: 3
      resource_def:
        type: node.yaml

outputs:

  nodes:
    value: {get_attr: [nodes, public_ip]}

这将定义三个 nova 实例,其中每个实例定义为:

heat_template_version: 2014-10-16

resources:

  node:
    type: OS::Nova::Server
    properties:
      image: rhel-atomic-20150615
      flavor: m1.small
      key_name: lars
      networks:
        - port: {get_resource: node_eth0}

  node_eth0:
    type: OS::Neutron::Port
    properties:
      network: net0
      security_groups:
        - default
      fixed_ips:
        - subnet: 82d04267-635f-4eec-8211-10e40fcecef0

  node_floating:
    type: OS::Neutron::FloatingIP
    properties:
      floating_network: public
      port_id: {get_resource: node_eth0}

outputs:

  public_ip:
    value: {get_attr: [node_floating, floating_ip_address]}

部署此堆栈后,我们可以获得 public 个 ip 列表,如下所示:

$ heat output-show mystack nodes
[
  "172.24.4.234", 
  "172.24.4.233", 
  "172.24.4.238"
]

我们可以写一个简单的Python脚本来实现动态库存接口:

#!/usr/bin/python

import os
import argparse
import json
import subprocess

def parse_args():
    p = argparse.ArgumentParser()
    p.add_argument('--list',
                   action='store_true')
    p.add_argument('--host')
    return p.parse_args()

def get_hosts():
    hosts = subprocess.check_output([
        'heat', 'output-show', 'foo', 'nodes'])

    hosts = json.loads(hosts)
    return hosts

def main():
    args = parse_args()

    hosts = get_hosts()

    if args.list:
        print json.dumps(dict(all=hosts))
    elif args.host:
        print json.dumps({})
    else:
        print 'Use --host or --list'
        print hosts

if __name__ == '__main__':
    main()

我们可以测试它是否有效:

$ ansible all -i inventory.py -m ping
172.24.4.238 | success >> {
    "changed": false,
    "ping": "pong"
}

172.24.4.234 | success >> {
    "changed": false,
    "ping": "pong"
}

172.24.4.233 | success >> {
    "changed": false,
    "ping": "pong"
}

假设我们有以下 Ansible 剧本:

- hosts: all
  gather_facts: false
  tasks:
  - command: sleep 60

这将 运行 每个主机上的 sleep 60 命令。 运行 并行处理大约需要一分钟,如果是序列化则大约需要三分钟。

正在测试:

$ time ansible-playbook -i inventory.py playbook.yaml
PLAY [all] ******************************************************************** 

TASK: [command sleep 60] ****************************************************** 
changed: [172.24.4.233]
changed: [172.24.4.234]
changed: [172.24.4.238]

PLAY RECAP ******************************************************************** 
172.24.4.233               : ok=1    changed=1    unreachable=0    failed=0   
172.24.4.234               : ok=1    changed=1    unreachable=0    failed=0   
172.24.4.238               : ok=1    changed=1    unreachable=0    failed=0   


real    1m5.141s
user    0m1.771s
sys 0m0.302s

如您所见,命令在所有三个上并行执行 主机,这是您正在寻找的行为(但请注意 这个 线程, 它描述了 Ansible 将序列化事物的情况 不告诉你)。