Ansible Playbook详解

文章目录

    • 1.playbook是什么?
    • 2.Playbook语言示例
    • 3.Playbook基础
          • 3.1playbook运行方式
          • 3.2 主机和用户
          • 3.3tasks列表
    • 4.定义变量
          • 4.1 合法的变量名
          • 4.2 在playbook中定义变量
    • 5.变量的引用
          • 5.1 playbook中引用变量
          • 5.2模板文件中引用变量
          • 5.3YAML陷阱
          • 5.4使用Facts获取的信息
          • 5.5变量文件分割
    • 6.Handlers: 在发生改变时执行的操作
    • 7.Tags
    • 8.when语句

1.playbook是什么?

Playbooks 是 Ansible的配置,部署,编排语言.他们可以被描述为一个需要希望远程主机执行命令的方案,或者一组IT程序运行的命令集合.
Playbooks 与 adhoc 相比,是一种完全不同的运用 ansible 的方式,是非常之强大的.
简单来说,playbooks 是一种简单的配置管理系统与多机器部署系统的基础, 非常适合于复杂应用的部署.
在playbook中我们可以编排有序的执行过程,甚至可以实现多组机器之间来回有序执行我们指定的任务!并且可以实现同步或异步的发起任务
在使用adhoc时,我们主要使用/usr/bin/ansible 程序执行任务,在使用playbook时,我们更多的是将任务写在剧本文件当中,使用ansible-playbook命令读取执行任务

2.Playbook语言示例

Playbooks 的格式是YAML, playbook 由一个或多个 ‘plays’ 组成.它的内容是一个以 ‘plays’ 为元素的列表! 在 play 之中,一组机器被映射为定义好的角色.在 ansible 中,play 的内容,被称为 tasks,即任务.在基本层次的应用中,一个任务就是一个对 ansible 模块的调用
通过 playbook,可以编排步骤进行多机器的部署,比如在 webservers 组的所有机器上运行一定的步骤, 然后在 dbservers 组运行一些步骤,最后回到 webservers 组,再运行一些步骤,诸如此类.

---
- hosts: webservers
  vars:
    http_port: 80
    max_clients: 200
  remote_user: root
  tasks:
  - name: ensure apache is at the latest version
    yum: pkg=httpd state=latest
  - name: write the apache config file
    template: src=/srv/httpd.j2 dest=/etc/httpd.conf
    notify:
    - restart apache
  - name: ensure apache is running
    service: name=httpd state=started
  handlers:
    - name: restart apache
      service: name=httpd state=restarted

3.Playbook基础

核心元素
Tasks:任务,由模板定义的操作列表
Variables:变量
Templates:模板,即使用模板语法的文件
Handlers:处理器 ,当某条件满足时,触发执行的操作
Roles:角色

3.1playbook运行方式

通过ansible-playbook命令运行
格式:ansible-playbook

[root@ansible PlayBook]# ansible-playbook -h
#ansible-playbook常用选项:
--check  or -C    #只检测可能会发生的改变,但不真正执行操作
--list-hosts      #列出运行任务的主机
--list-tags       #列出playbook文件中定义所有的tags
--list-tasks      #列出playbook文件中定义的所以任务集
--limit           #主机列表 只针对主机列表中的某个主机或者某个组执行
-f                #指定并发数,默认为5个
-t                #指定tags运行,运行某一个或者多个tags。(前提playbook中有定义tags)
-v                #显示过程  -vv  -vvv更详细
[root@ansible PlayBook]# ansible-playbook fileName.yml --syntax-check   #playbook语法检查
3.2 主机和用户

你可以为 playbook 中的每一个 play,去选择要操作的目标机器是哪些,以哪个用户身份去完成要执行的步骤,hosts一行可以是一个主机组、主机、多个主机,中间以冒号分隔,可使用通配模式。其中remote_user表示执行的用户账号。

---
- hosts: webservers  #指定主机组,可以是一个或多个组。
  remote_user: root  ##指定远程主机执行的用户名

我们也可以在一个任务中定义自己的远程用户

---
- hosts: webservers
  remote_user: root
  tasks:
    - name: test connection
      ping:
      remote_user: yourname

也支持sudo的调用

---
- hosts: webservers
  remote_user: yourname
  sudo: yes

如果你需要在使用 sudo 时指定密码,可在运行 ansible-playbook 命令时加上选项 --ask-sudo-pass (-K)

3.3tasks列表

每个play都包含一个task列表(任务列表),一个task在目标主机执行完毕后,才会执行下一个任务,在同一个play当中,所有的主机都会收到接受到相同的指令,
每个 task 的目标在于执行一个模块(module), 通常是带有特定的参数来执行.在参数中可以使用变量
modules 具有”幂等”性,意思是如果你再一次地执行 moudle,moudle 只会执行必要的改动,只会改变需要改变的地方.所以重复多次执行 playbook 也很安全.
每一个 task 必须有一个名称 name,这样在运行 playbook 时,从其输出的任务执行信息中可以很好的辨别出是属于哪一个 task 的. 如果没有定义 name,‘action’ 的值将会用作输出信息中标记特定的 task.
下面是一种基本的task的定义
service 模块使用 key=value 格式的参数,这也是大多数 module 使用的参数格式:

tasks:
  - name: make sure apache is running  #任务名
    service: name=httpd state=running  #运行Apache

但是有两个特殊的模块shell模块和command模块,它们不是用key=value的格式,而是这样的:

tasks:
  - name: disable selinux
    command: /sbin/setenforce 0

使用shell模块和command模块我们需要考虑返回码的问题,若返回码不为0说明命令没有执行成功,那么模块执行的状态也为失败,任务可能就会终止,我们可以按如下执行来解决状态码的问题:

tasks:
  - name: run this command and ignore the result
	shell: /usr/bin/somecommand || /bin/true

或者

tasks:
  - name: run this command and ignore the result
    shell: /usr/bin/somecommand
    ignore_errors: True

4.定义变量

4.1 合法的变量名

在使用变量之前最好先知道什么是合法的变量名. 变量名可以为字母,数字以及下划线.变量始终应该以字母开头

4.2 在playbook中定义变量
- hosts: webservers
  vars:   #变量
	http_port: 80

5.变量的引用

5.1 playbook中引用变量

我们可以在playbook文件中引用变量

- hosts: webservers
  vars:
	base_dir: /usr/local/nginx
  shell: {{ base_dir }}/sbin/nignx
5.2模板文件中引用变量

我们也可以通过template模块将变量引用到文件当中,Ansible允许你使用Jinja2模板系统在playbook中引用变量
例如:
我们创建文件file.j2,内容:

mysql name is  {{ user_name }}

在playbook文件中定义变量:

- hosts: webservers
  vars:
	user_name: tom
  tasks:
	- name: copy a fille to host
  	  template: src=file.j2  dest=/root/

template常用于配置文件的推送,我们可以把一些常用的参数,例如nginx的监听地址,网站根目录,网站域名等!我们可以把这些参数都做成变量,然后在配置文件中引用,这样我们以后只需更改playbook文件中变量的值即可!增加了配置的灵活度

5.3YAML陷阱

YAML语法要求如果值以{{ foo }}开头的话我们需要将整行用双引号包起来.这是为了确认你不是想声明一个YAML字典!
错误的写法:

- hosts: app_servers
  vars:
      app_path: {{ base_path }}/22

正确的写法:

- hosts: app_servers
  vars:
       app_path: "{{ base_path }}/22"
5.4使用Facts获取的信息

在ansible中有些自带的变量,不需要用户定义,直接引用就可以
Facts通过访问远程系统获取相应的信息,比如像查看远程主机的ip地址和系统版本,那么我们可以执行:

ansible hostname -m setup

不过这样执行会返回非常多的变量数据!这里面的变量我们都可以直接引用!
例如{{ ansible_hostname }}就可以获取远程主机的主机名,{{ ansible_eth0[“ipv4”][“address”] }}获取eth0的ipv4的ip地址,当然这些变量我们也可以通过template模块,直接在模板文件中引用

5.5变量文件分割

我们有时可能会有敏感数据存放到playbook当中的情况,比如账号密码等!那么如果直接公开我们的playbook源码可能会有隐私数据泄露的情况!那么我么可以把这些敏感数据可以跟playbook进行分割!

我们可以把变量在一个外部变量文件中定义:

---
somevar: somevalue
password: magic

在playbook中直接引用这个变量文件

---
- hosts: all
  remote_user: root
  vars:
    favcolor: blue
  vars_files:
    - /vars/vars.yml

  tasks:
 	 - name: this is just a placeholder
       command: /bin/echo foo

6.Handlers: 在发生改变时执行的操作

我们可以使用handlers定义一些触发任务,这些触发任务可以在其他的任务中调用,但是执行条件是该任务有更改时才会触发这些触发任务!比如如下例子:

- name: template configuration file
  template: src=template.j2 dest=/etc/foo.conf
  notify:
     - restart memcached
     - restart apache
handlers:
    - name: restart memcached
      service:  name=memcached state=restarted
    - name: restart apache
      service: name=apache state=restarted

重启memcache和apache只有当我们使用template模块分发的配置文件有更改时才会被执行,如果配置文件没有更改则不会执行重启

Handlers 最佳的应用场景是用来重启服务,或者触发系统重启操作.除此以外很少用到了.

7.Tags

在一个playbook中,我们一般会定义很多个task,如果我们只想执行其中的某一个task或多个task时就可以使用tags标签功能了

---
hosts: webservers
remote_user: root
tasks:
  - name: make sure apache is running  #任务名
    service: name=httpd state=running  #运行Apache
    tags:
      - apache
  - name: touch file
  	file: path=/opt/hosts state=touch

之后我们可以使用ansible-playbook --tags=“apache” fileName.yml 就可以只运行playbook中指定标签的task了

8.when语句

在有些时候我们需要选择主机去执行不同的任务,比如我们在关闭防火墙的时候,Centos6和Centos7关闭的方式是不同的,所有我们需要判断主机的系统版本来执行对应的任务
在Ansible中,使用when子句很容易做到这一点,该子句包含不带双花括号的原始Jinja2表达式

tasks:
  - name: "shut down Debian flavored systems"
    command: /sbin/shutdown -t now
    when: ansible_facts['os_family'] == "Debian"
    # 注意,所有变量都可以直接在条件语句中使用,而不需要双花括号

还可以使用括号对条件进行分组:

tasks:
  - name: "shut down CentOS 6 and Debian 7 systems"
    command: /sbin/shutdown -t now
    when: (ansible_facts['distribution'] == "CentOS" and ansible_facts['distribution_major_version'] == "6") or
          (ansible_facts['distribution'] == "Debian" and ansible_facts['distribution_major_version'] == "7")

也可以将多个都必须为真的条件(逻辑“和”)指定为列表:

tasks:
  - name: "shut down CentOS 6 systems"
    command: /sbin/shutdown -t now
    when:
      - ansible_facts['distribution'] == "CentOS"
      - ansible_facts['distribution_major_version'] == "6"

你可能感兴趣的:(Ansible)