somethings about ansible

  • task解析json并注册变量给其他task使用

    多个task涉及变量传递时,有时taskA取值是json格式,taskB若想使用json中的数据,可以通过如下方式:

# get config task stdout is json format
- name: "get_config"
  shell: /usr/local/sbin/kubectl get cm global-var -n alauda-system -o json
  register: cms

# use from_json plugin
- set_fact: data=""

- name: "read_config"
  shell: /usr/local/bin/redis-cli -a
  when: data['kind'] == 'ConfigMap'
  • ansible自定义模块执行命令支持管道

    自定义ansible module时,可以默认使用AnsibleModule的实例run_command来执行shell命令,可以指定use_unsafe_shell=True来让ansible支持管道。 use_shell会和shell模块类似,若不指定,默认为False,则以command模块运行,command是比较安全的隧道连接,但是不支持管道

def main():
    """The main function."""
    module = AnsibleModule(argument_spec=dict(),supports_check_mode=False)
    module.run_command("/usr/local/sbin/kubectl get po -n alauda-system |grep alauda-redis|awk \'END{print $1}", use_unsafe_shell=True)
    redis = Redis(module)
    rst = redis.get_redis_status()
    module.exit_json(**rst)
  • 多进程执行ansible任务

    实现故障定位工具时为提高执行效率,打算采用多线程方式同时执行多个任务,使用python多线程执行类方法, 发现由于ansible自身已经实现了多线程执行,如果在多线程中再次包裹ansible的多线程的话,会遇到各种诡异的问题(非线程安全),于是多线程调用多个ansible任务基本上行不通。 于是尝试使用多进程的方式,发现多进程下包裹ansible的多进程是可以正常运行的,与多线程方式不同的是,多线程需要使用multiprocessing的Manager管理共享数据,即需要在 主进程中传递Manager的变量到每个子进程中,否则主进程无法获取各子进程的数据。

def main():
    all_cls = get_all_subclasses(Collector)
    manager = Manager()
    results = manager.dict()  # 多进程共享数据
    processes = []  # 进程id
    for item, value in all_cls.items():
        fn_collect = getattr(value, 'grab', None)
        if callable(fn_collect):
            p = Process(target=fn_collect, name=item, args=(item, results))
            processes.append(p)
            p.start()
            print("执行{0}的collect 方法".format(item))
    for p in processes:
        p.join()  #
    print("main done")