Ansible 脚本 - playbook 剧本

123 阅读6分钟

playbook

playbook是ansible用于配置,部署,和管理被控节点的剧本。通过playbook的详细描述,执行其中的tasks,可以让远端主机达到预期的状态。playbook是由一个或多个”play”组成的列表。 当对一台机器做环境初始化的时候往往需要不止做一件事情,这时使用playbook会更加适合。通过playbook你可以一次在多台机器执行多个指令。通过这种预先设计的配置保持了机器的配置统一,并很简单的执行日常任务。

ansible通过不同的模块实现相应的管理,管理的方式通过定义的清单文件(hosts)所管理的主机包括认证的方式连接的端口等。所有的功能都是通过调用不同的模块(modules)来完成不同的功能的。不管是执行单条命令还是play-book都是基于清单文件。

playbook格式

playbook由YMAL语言编写。YMAL格式是类似于JSON的文件格式,便于人理解和阅读,同时便于书写。

一个剧本里面可以有多个play,每个play只能有一个tasks,每个tasks可以有多个name。

playbooks 的组成

  1. Tasks:任务,即通过 task 调用 ansible 的模块将多个操作组织在一个playbook 中运行。

  2. Variables:变量

  3. Templates:模板

  4. Handlers:处理器,当 changed 状态条件满足时,(notify)触发执行的操作。

  5. Roles:角色

playbook的基础组件

name : 定义playbook或者task的名称(描述信息),每一个play都可以完成一个任务。

hosts : hosts用于指定要执行指定任务的主机.

user : remote_user则用于指定远程主机上的执行任务的用户

tasks : 任务列表play的主体部分是task list. task list中的各任务按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个任务后再开始第二个。

vars : 定义变量(如果不使用内部变量需要提前定义)

vars_files : 调用定义变量文件

notify : 任务执行结果如果是发生更改了的则触发定义在handler的任务执行

handlers : 用于当前关注的资源发生变化时采取一定指定的操作

playbook语法有如下特性: 

  • 以 --- (三个减号)开始,必须顶行写; 
  • 次行开始写Playbook的内容,但是一般要求写明该playbook的功能; 
  • 严格缩进,并且不能用Tab键缩进; 
  • 缩进级别必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行来实现的; 
  • K/V的值可同行写,也可换行写。同行使用 :分隔,换行写需要以 - 分隔;

示例一

1.编写httpd的playbook

vim test1.yaml
---     #yaml文件以---开头,以表明这是一个yaml文件,可省略
- name: first play     #定义一个play的名称,可省略
  gather_facts: false    #设置不进行facts信息收集,这可以加快执行速度,可省略
  hosts: dbservers    #指定要执行任务的被管理主机组,如多个主机组用冒号分隔
  remote_user: root    #指定被管理主机上执行任务的用户
  tasks:     #定义任务列表,任务列表中的各任务按次序逐个在hosts中指定的主机上执行
   - name: test connection    #自定义任务名称
     ping:     #使用 module: [options] 格式来定义一个任务
   - name: disable selinux
     command: '/sbin/setenforce 0'    #command模块和shell模块无需使用key=value格式
     ignore_errors: True     #如执行命令的返回值不为0,就会报错,tasks停止,可使用ignore_errors忽略失败的任务
   - name: disable firewalld
     service: name=firewalld state=stopped    #使用 module: options 格式来定义任务,option使用key=value格式
   - name: install httpd
     yum: name=httpd state=latest
   - name: install configuration file for httpd
     copy: src=/opt/httpd.conf dest=/etc/httpd/conf/httpd.conf    #这里需要一个事先准备好的/opt/httpd.conf文件,我们可以把端口修改一下
     notify: "restart httpd"    #如以上操作后为changed的状态时,会通过notify指定的名称触发对应名称的handlers操作
   - name: start httpd service
     service: enabled=true name=httpd state=started
  handlers:     #handlers中定义的就是任务,此处handlers中的任务使用的是service模块
   - name: restart httpd    #notify和handlers中任务的名称必须一致
     service: name=httpd state=restarted
==========================================================
##Ansible在执行完某个任务之后并不会立即去执行对应的handler,而是在当前play中所有普通任务都执行完后再去执行handler,这样的好处是可以多次触发notify,但最后只执行一次对应的handler,从而避免多次重启
==========================================================

2. 在webservers端准备httpd模板配置文件

cd /etc/httpd/conf
vim httpd.conf         #在/opt/目录下放入修改之后的配置文件
  
#42行,指定端口
Listen 8080
#95行,指定域名
ServerName www.tt.com:8080

将准备好的httpd模板配置文件发送到Ansible管理端

scp httpd.conf root@192.168.136.40:/opt

3.执行playbook剧本

ansible-playbook test1.yaml
//补充参数:
-k(–ask-pass):用来交互输入ssh密码
-K(-ask-become-pass):用来交互输入sudo密码
-u:指定用户
ansible-playbook test1.yaml --syntax-check                         #检查yaml文件的语法是否正确
ansible-playbook test1.yaml --list-task                            #检查tasks任务
ansible-playbook test1.yaml --list-hosts                           #检查生效的主机
ansible-playbook test1.yaml --start-at-task='install httpd'        #指定从某个task开始运行

示例二

定义、引用变量

- name: second play
  hosts: dbservers
  remote_user: root
  vars:                          #定义变量
    - groupname: mysql           #格式为 key: value
    - username: nginx
  tasks:
    - name: create group
      group: name={{groupname}} system=yes gid=3016         #使用 {{key}} 引用变量的值
    - name: create user
      user: name={{username}} uid=3066 group={{groupname}}
    - name: copy file
      copy: content="{{ansible_default_ipv4}}" dest=/opt/vars.txt   #在setup模块中可以获取facts变量信息
 
 
ansible-playbook test3.yaml -e "username=nginx"           #在命令行里定义变量

示例三

指定远程主机sudo切换用户

---
- hosts: webservers
  remote_user: mzs
  become: yes     #2.6版本以后的参数,之前是sudo,意思为切换用户运行
  become_user: root     #指定sudo用户为root
执行playbook时:ansible-playbook test2.yaml -K <密码>

示例四

when条件判断

在Ansible中,提供的唯一一个通用的条件判断是when指令,当when指令的值为true时,则该任务执行,否则不执行该任务

when一个比较常见的应用场景是实现跳过某个主机不执行任务或者只有满足条件的主机执行任务

vim test4.yaml
---
- hosts: all
  remote_user: root
  tasks:
    - name: shutdown host
      command: /sbin/shutdown -r now
      when: ansible_default_ipv4.address == "192.168.136.40" #when指令中的变量名不需要手动加上 {{}}
    
    when: inventory_hostname == "<主机名>"
 
ansible-playbook test4.yaml

示例五

迭代

Ansible提供了很多种循环结构,一般都命名为with_items,作用等同于 loop 循环。

vim test5.yaml
---
- name: play5
  hosts: dbservers
  gather_facts: false
  tasks:
    - name: create directories      ##创建目录。目录名使用with_items里的循环
      file:
        path: "{{item}}"              ##由于值是{{....}} ,所以为了防止被认为是字典,要加上双引号.
        state: directory
      with_items:                   #等同于 loop:
        - /tmp/test1
        - /tmp/test2
   - name: add users                ###使用循环创建用户,并添加附加组
     user: name={{item.name}} state=present groups={{item.groups}}
     with_items:
        - name: test1
          groups: wheel
        - name: test2
          groups: root
     
     with_items:
       - {name:'test1', groups:'wheel'}
       - {name:'test2', groups:'root'}
 
ansible-playbook test5.yaml