Ansible 入门指南 - ansible-playbook 命令
上篇文章Ansible 入门指南 - 安装及 Ad-Hoc 命令使用介绍的额是 Ad-Hoc 命令方式,本文将介绍 Playbook 方式。
Playbook 译为「剧本」,觉得还挺恰当的。
playbook 执行语法
Playbook 译为「剧本」,觉得还挺恰当的。那么 play 那我就译为 「场景」吧。playbook 由一个或多个 ‘plays’ 组成.它的内容是一个以 ‘plays’ 为元素的列表
playbook 基础
可以为 playbook 中的每一个 play,个别地选择操作的目标机器是哪些,以哪个用户身份去完成要执行的步骤(called tasks)
$ ansible-playbook  -h
Usage: ansible-playbook [options] playbook.yml [playbook2 ...]
Runs Ansible playbooks, executing the defined tasks on the targeted hosts.
palybook 小栗子
在指定的目标主机上执行定义好的 tasks。
playbook.yml 常包含下面几个关键字:
- hosts:为主机的IP,或者主机组名,或者关键字all
- remote_user: 以哪个用户身份执行。
- vars: 变量
- tasks: playbook的核心,定义顺序执行的动作- action。每个- action调用一个- ansbile module。
- action语法:- module: module_parameter=module_value
- 常用的 module有yum、copy、template等,module在 ansible 的作用,相当于 bash 脚本中yum,copy这样的命令。
- 每一个 task 必须有一个名称 name,这样在运行 playbook 时,从其输出的任务执行信息中可以很好的辨别出是属于哪一个 task 的
- handers: 是 playbook 的 event ,默认不会执行,在 action 里触发才会执行。多次触发只执行一次。
一个简单的示例:
deploy.yml 的功能为 web 主机部署 apache, 其中包含以下部署步骤:
- 安装apache包;
- 拷贝配置文件httpd,并保证拷贝文件后,apache服务会被重启;
- 拷贝默认的网页文件index.html;
- 启动apache服务;
---
- hosts: centos
  vars:
    httpd_port: 8080
    max_clients: 200
  remote_user: root
  tasks:
  - name: ensure apache is at the latest version
    yum: name=httpd state=present
  - name: Write the configuration file
    template: src=templates/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
    notify:
    - restart apache
    ignore_errors: False
  - name: Write the default index.html file
    template: src=templates/index.html.j2 dest=/var/www/html/index.html
    ignore_errors: False
  - name: ensure apache is running
    service: name=httpd state=started
  handlers:
    - name: restart apache
      service: name=httpd state=restarted
运行ansible-playbook deploy.yml即可执行。
tasks
taks 参数其实是有不同写法的,当参数比较少时,可用key=value的方式
tasks:
  - name: make sure apache is running
    service: name=httpd state=running
当tasks 参数比较多时,为了美观和不易出错,用 yml的字典传参比较好:
tasks:
  - name: make sure apache is running
    service:
      name: httpd
      state: running
task中每个action会调用一个module,在module中会去检查当前系统状态是否需要重新执行。
- 如果本次执行了,那么 action会得到返回值changed;
- 如果不需要执行,那么 action得到返回值ok
module 的执行状态的具体判断规则由各个 module 自己决定和实现的。例如,”copy” module的判断方法是比较文件的checksum,代码如下:
ansbile-playbook 常用命令
查看脚本影响到的 hosts
下面这条命令,指定 inventory 文件,列出 hosts 列表,并不会去执行定义的 tasks,观察 host 是否配置正确很有用:
ansible-playbook -i inventory/slave_init.yml execute_slave_init.yml --list-hosts
查看输出的细节
ansible-playbook playbook.yml  --verbose
并行执行脚本
ansible-playbook playbook.yml -f 10
输入密码
playbook 中使用到了 become,执行playbook时可以加上--ask-become-pass参数:
ansible-playbook deploy.yml --ask-become-pass
yml 语法简介
- 大小写敏感
- 使用缩进表示层级关系
- 缩进时不允许使用Tab键,只允许使用空格。
- 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
- #表示注释,从这个字符一直到行尾,都会被解析器忽略
- YAML 还有一个小的怪癖. 所有的 YAML 文件(无论和 Ansible 有没有关系)开始行都应该是 ---. 这是 YAML 格式的一部分, 表明一个文件的开始.
- 列表中的所有成员都开始于相同的缩进级别, 并且使用一个 "- " 作为开头(一个横杠和一个空格)
- 一个字典是由一个简单的 键: 值的形式组成(这个冒号后面必须是一个空格)
- Ansible 使用 “{{ var }}” 来引用变量,foo: "{{ variable }}"。
参考
Play vs Playbook
其实在一个Playbook文件中还可以有针对两组server进行不同的操作,例如给web安装http服务器,和给lb安装mysql放在一个文件中:
---
#安装apache的play
- hosts: web
  remote_user: root
  tasks:
  - name: ensure apache is at the latest version
    yum: pkg=httpd state=latest
# 安装mysql server的play
- hosts: lb
  remote_user: root
  tasks:
  - name: ensure mysqld is at the latest version
    yum: pkg=mariadb state=latest
上面例子中针对每一组 server 的所有操作就组成一个 play,一般一个 playbook 中只包含一个 play,play 的内容称为 tasks,即任务。
参考:
响应事件 Hanlder
handlers与tasks不同,tasks会默认的按定义顺序执行每一个task,handlers则不会,它需要在tasks中被调用,才有可能被执行。
Handlers will only be fired for tasks which report a changed state.
只有当 task 执行状态显示是 changed 时,handler 动作才会被触发
Tasks中的任务都是有状态的,changed或者ok。 在Ansible中,只在task的执行状态为 changed 的时候,才会执行该task调用的handler。
在所有的task列表执行之后执行,如果有多个task notify同一个handler,那么 handlers 也只执行一次。
什么情况下使用handlers呢?
如果你在tasks中修改了apache的配置文件。需要重起apache。此外还安装了apache的插件。那么还需要重起apache。像这样的应该场景中,重起apache就可以设计成一个handler.
当一个文件的内容被改动时,重启两个 services:
- name: template configuration file
  template: src=template.j2 dest=/etc/foo.conf
  notify:
     - restart memcached
     - restart apache
- notify下列出的即是 handlers.
- Handlers 也是一些 task 的列表,通过名字(name)来引用。
- Handlers 是由通知者进行 notify, 如果没有被 notify,handlers 不会执行。
- 不管有多少个通知者进行了 notify,等到 play 中的所有 task 执行完成之后,handlers 也只会被执行一次.
handlers:
    - name: restart memcached
      service:  name=memcached state=restarted
    - name: restart apache
      service: name=apache state=restarted
此外,还有个注意点:
- handlers是按照在handlers中定义个顺序执行的,而不是安装notify的顺序执行的。比如,handlers定义的顺序是1>2>3,notify 的顺序是3>2>1,实际执行顺序:1>2>3.
总结,Handlers 最佳的应用场景是用来重启服务,或者触发系统重启操作.除此以外很少用到。
参考
变量
playbook 中常用的集中变量:
- 在 playbook 中,用户自定义的变量
- 无需用户定义,ansible 在执行 playbook 之前,去远程主机上搜集的关于远程主机的系统信息变量
- task 运行的结果「注册」为一个变量来使用,这个变量叫做「注册变量」
- 允许用户在执行的时候传入变量的值,这时候用到的是「额外变量」
playbook 中定义的变量
在 playbook 中,通过关键字 vars 自定义变量,用 {{}} 引用变量。
将变量放在单独的文件中
通过 vars_files 关键字指定了变量文件:
---
- hosts: centos
  vars:
    httpd_port: 80
  vars_files:
      - ./vars_servers.yml
  remote_user: root
  tasks:
  - debug:
      msg: "http_port: {{httpd_port}}"
  - debug:
      msg: "x86 passwd: {{x86.password}}"
  - debug:
      msg: "arm passwd: {{arm.password}}"
      # 也可以用 arm['password'] 表示
专门存放变量的文件:
# vars_servers.yml
x86:
    password: 123
arm:
    password: 456
远程节点的系统变量(facts)
ansible 通过 module setup 收集主机的系统信息,这些收集到的系统信息叫做 facts,这些facts可以直接以变量的形式使用。
哪些 facts 变量可以引用的?通过如下命令行调用setup module 可以查看:
ansible all -m setup -u root
可以看到它输出的变量信息有很多!
复杂的facts变量的使用可以用如下两种形式:
- {{ ansible_ens3["ipv4"]["address"] }}
- {{ ansible_ens3.ipv4.address }}
好用的一些 facts 变量
- ansible_hostname指定的 host 名称
- ansible_default_ipv4.address主机真实的 ipv4 地址,小网IP
ansible_os_family 查看系统类型的变量
---
- hosts: all
  user: root
  tasks:
  - name: echo system
    shell: echo {{ ansible_os_family }}
  - name install ntp on Debian linux
    apt: name=git state=installed
    when: ansible_os_family == "Debian"
  - name install ntp on redhat linux
    yum: name=git state=present
    when: ansible_os_family == "RedHat"
关闭 facts
在 playbook 中,如果不收集系统信息,那么上面的变量就不能再 playbook 中使用了,但是有时候关闭会加快执行的效率:
- hosts: all
  gather_facts: no
注册变量 register
将某个 task 执行的结果「注册」为一个变量。后面的 action 就可以使用它
---
- hosts: centos
  tasks:
      - name: ls /tmp
        shell: ls -l /tmp
        register: result
        ignore_errors: True
      - name: echo result when rc==5
        shell: echo "{{result}}"
        when: result.rc == 5
      - name: debug show stdout
        debug:
          msg: "{{result.stdout}}"
「注册变量」经常和debug module一起使用,这样可以获得 action 更多的输出信息,帮助调试。
参考
- 注册Ansible变量属性 介绍到了一个set_facts的模块
- 朱双印-ansible 变量5
- Ansible系列(五):各种变量定义方式和变量引用
命令行传递变量 --extra-vars
---
- hosts: "{{hosts}}"
  remote_user: "{{user}}""
  tasks:
    - debug: msg="{{hosts}}""
命令输入变量:
ansible-playbook extra_learn.yml --extra-vars "{'hosts':'x86','user':‘’michael'}"
# or
ansible-playbook extra_learn.yml --extra-vars "hosts=x86 user=michael"
playbook 中的逻辑控制语句
- when:条件判断,类似编程语言中的- if
- loop:循环,类似编程语言中的- while
- block:将几个- task组成一块代码,便于针对一组操作进行异常处理等
条件语句 wehn
例如,在某个特定版本的系统上装包,或者只在磁盘空间满了的文件系统上执行清理操作。这些操作在Playbook中用when语句实现。
主机为Debian Linux立刻关机
tasks:
  - name: "shutdown Debian flavored systems"
    command: /sbin/shutdown -t now
    when: ansible_os_family == "Debian"
根据action的执行结果,来决定接下来执行的action。
tasks:
  - command: /bin/false
    register: result
    ignore_errors: True
  - command: /bin/something
    when: result|failed
  - command: /bin/something_else
    when: result|success
  - command: /bin/still/something_else
    when: result|skipped
远程中的系统变量facts变量作为when的条件,用“|int”还可以转换返回值的类型:
---
- hosts: web
  tasks:
    - debug: msg="only on Red Hat 7, derivatives, and later"
      when: ansible_os_family == "RedHat" and ansible_lsb.major_release|int >= 6
循环语句 loop
标准循环 with_items
为了保持简洁,重复的任务可以用以下简写的方式:
- name: add several users
  user: name="{{ item }}" state=present groups=wheel
  with_items:
     - michael
     - qq
如果你在变量文件中或者 ‘vars’ 区域定义了一组YAML列表,你也可以这样做:
vars:
  userlist: ["micahel", "qq"]
tasks:
  -name: add several user
   user:
     name: "{{ item }}"
     state: present
     groups: wheel
   with_items: "{{userlist}}"
使用 with_items 用于迭代的条目类型不仅仅支持简单的字符串列表.如果你有一个哈希列表,那么你可以用以下方式来引用子项:
- name: add several users
  user: name="{{ item.name }}" state=present groups="{{ item.groups }}"
  with_items:
    - { name: 'michael', groups: 'wheel' }
    - { name: 'qq', groups: 'root' }
对哈希表使用循环 with_dict
这个例子不仅演示了 with_dict 用法,还使用循环安装了 RPM 包
---
- hosts: centos
  vars:
    users:
      michael:
        name: michael xiang
        phone: 123
      qq:
        name: qq huang
        phone: 456
    rpms:
        - httpd
        - lrzsz
        - vim
        - git
  tasks:
    - name: print phone records
      debug: msg="User {{item.key }} is {{ item.value.name }} {{item.value.phone}}"
      with_dict: "{{ users }}"
    - name: install rpms
      yum: name="{{item}}" state=installed
      with_items: "{{rpms}}"

对文件列表使用循环 with_filegloab
with_fileglob 可以以非递归的方式来模式匹配单个目录中的文件.如下面所示:
tasks:
    # first ensure our target directory exists
    - file: dest=/etc/fooapp state=directory
    # copy each file over that matches the given pattern
    - copy: src=\{\{ item \}\} dest=/etc/fooapp/ owner=root mode=600
      with_fileglob:
        - /playbooks/files/fooapp/*
参考
块语句
多个action组装成块,可以根据不同条件执行一段语句 :
 tasks:
     - block:
         - yum: name=\{\{ item \}\} state=installed
           with_items:
             - httpd
             - memcached
         - template: src=templates/src.j2 dest=/etc/foo.conf
         - service: name=bar state=started enabled=True
       when: ansible_distribution == 'CentOS'
       become: true
       become_user: root
ansible 示例
- ansible/ansible-examples Ansible官方提供了一些比较常用的、经过测试的Playbook例子
- galaxy-ansible Playbook分享平台
参考
Ansible 入门指南 - ansible-playbook 命令的更多相关文章
- Ansible 入门指南 - 安装及 Ad-Hoc 命令使用
		安装及配置 ansible Ansilbe 管理员节点和远程主机节点通过 SSH 协议进行通信.所以 Ansible 配置的时候只需要保证从 Ansible 管理节点通过 SSH 能够连接到被管理的远 ... 
- Ansible 入门指南 - 学习总结
		概述 这周在工作中需要去修改 nginx 的配置,发现了同事在使用 ansible 管理者系统几乎所有的配置,从数据库的安装.nginx 的安装及配置.于是这周研究起了 ansible 的基础用法.回 ... 
- Ansible入门篇:playbook的使用
		playbooks介绍 playbooks是 一个不同于使用Ansible命令行执行方式的模式,其功能更强大灵活.简单来说,playbook是一个非常简单的配置管理和多主机部署系统,不同于任何已经存在 ... 
- Ansible 入门指南 - 常用模块
		介绍 module 文档: 官宣-模块分类的索引 官宣-全部模块的索引 在playbook脚本中,tasks 中的每一个 action都是对 module的一次调用.在每个 action中: 冒号前面 ... 
- 《Ansible权威指南》笔记(1)——安装,ssh密钥登陆,命令
		2016-12-23 读这本<Ansible权威指南>学习ansible,根据本书内容和网上的各种文档,以及经过自己测试,写出以下笔记.另,这本书内容很好,但印刷错误比较多,作者说第二版会 ... 
- Linux centosVMware 自动化运维Ansible介绍、Ansible安装、远程执行命令、拷贝文件或者目录、远程执行脚本、管理任务计划、安装rpm包/管理服务、 playbook的使用、 playbook中的循环、 playbook中的条件判断、 playbook中的handlers、playbook实战-nginx安装、管理配置文件
		一.Ansible介绍 不需要安装客户端,通过sshd去通信 基于模块工作,模块可以由任何语言开发 不仅支持命令行使用模块,也支持编写yaml格式的playbook,易于编写和阅读 安装十分简单,ce ... 
- 《Ansible权威指南》笔记(3)——Ad-Hoc命令集,常用模块
		五.Ad-Hoc命令集1.Ad-Hoc命令集通过/usr/bin/ansible命令实现:ansible <host-pattern> [options] -v,--verbose ... 
- Ansible入门笔记(3)之Playbook
		目录 Ansible-playbook 1.1.什么是playbook? 1.2.playbook的核心组成 1.3.playbook的handlers.notify触发 1.4.playbook的变 ... 
- [转帖]Ansible 入门秘诀
		Ansible 入门秘诀 作者: Jose Delarosa 译者: LCTT jdh8383 | 2019-03-08 09:24 收藏: 2 用 Ansible 自动化你的数据中心的关键点. ... 
随机推荐
- 单例模式:Qt本身就提供了专门的宏 Q_GLOBAL_STATIC  通过这个宏不但定义简单,还可以获得线程安全性
			标题起的是有点大 主要是工作和学习中,遇到些朋友,怎么说呢,代码不够Qt化 可能是由于他们一开始接触的是 Java MFC 吧 接触 Qt 7个年头了 希望我的系列文章能抛砖引玉吧 单例模式 很多人洋 ... 
- 洛谷P3966 单词 [TJOI2013] AC自动机
			正解:AC自动机 解题报告: 传送门! 先来提供一个40pts错解QAQ 首先看到这题就会想到AC自动机板子题2鸭!然后就照着那题的套路打一下,随便改一点儿,简单来说就是每次经过一个节点都要++,然后 ... 
- 【剑指offer】 二叉树中和为某一值的路径
			一.题目: 输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径.(注意: 在返回值的list中,数组长度 ... 
- 性能测试之nmon对linux服务器的监控
			大家都知道在做性能测试的时候,需要监控服务器的资源情况,而大多数服务器是Linux系统,网上资料嘿多,这里汇总介绍下Nmon监控工具: -------------------------------- ... 
- IP追踪
			cmd里输入:tracert www.baidu.com 上图箭头方框中就是对应公司的总网IP 
- Oracle多关键字模糊查询
			以前写SQL时,知道MySQL多字段模糊查询可以使用[charlist] 通配符,如: SELECT * FROM Persons WHERE City LIKE '[ALN]%'但是在Oracle中 ... 
- Apache下设置网站目录的访问权限
			禁止用户对某一个目录及目录下文件的访问,仅允许本地访问 <Directory "/wwwroot/cert/"> Require local </Director ... 
- [LeetCode] 595. Big Countries_Easy tag: SQL
			There is a table World +-----------------+------------+------------+--------------+---------------+ ... 
- testng入门教程8 TestNG异常测试
			TestNG跟踪异常处理代码提供了一个选项.可以测试是否需要代码抛出异常或不抛出. @Test注释expectedExceptions 参数一起使用.现在,让我们来看看@Test(expectedEx ... 
- Summary: Deep Copy vs. Shallow Copy vs. Lazy Copy
			Object copy An object copy is an action in computing where a data object has its attributes copied t ... 
