ansible的剧本Playbook

1.Playbook介绍
.2.Playbook核心元素
3.Playbook 语法
4.Playbook 的运行方式

5.Playbook中元素属性

6. Playbook中变量的使用.

7.Playbook中标签的使用

8. Playbook 中模板的使用


如果把ansible的模块比喻成linux命令,那么咱的playbook就好比是shell脚本

Playbook介绍

Playbook 与 ad-hoc 相比,是一种完全不同的运用ansible的方式,类似与saltstack 的 state状态文件。ad-hoc 无法持久使用,playbook可以持久使用。playbook是由一个或多个play 组成的列表, play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible中的task定义好的角色。从根本上来讲,所谓的task无非是调用ansible 的一个module。将多个play组织在一个playbook中,即可以让它们联合起来按事先编排的机制完成某一任务

 Playbook核心元素

·Hosts执行的远程主机列表.Tasks任务集
. Variables内置变量或自定义变量在playbook中调用
. Templates模板,即使用模板语法的文件,比如配置文件等. Handlers 和notity 结合使用,由特定条件触发的操作,满
足条件方才执行,否则不执行
. tags标签,指定某条任务执行,用于选择运行playbook中
的部分代码。

 先简单创建一个Playbook吧

---
- hosts: all        ###可以替换成其他的,例如IP地址,或者hostst指定的组
  remote_user: root ###使用哪个用户进行操作

  tasks:            ###任务列表
  - name: "创建一个yum源"
    yum_repository: name=local description=local baseurl=file:///mnt enabled=1 gpgcheck=0 file=Chengzhang

  - name: "挂载镜像"
    mount: src=/dev/cdrom path=/mnt fstype=iso9660 state=mounted

  - name: "安装web服务"
    yum: name=httpd state=installed

  - name: "自定义页面"
    copy: content="Hello,World" dest=/var/www/html/index.html

  - name: "启动服务"
    systemd: name=httpd state=started enabled=yes

测试:保证文件没有问题(去掉-C后就可以运行了)

ansible-playbook 文件名.yml -C

ansible的剧本Playbook_第1张图片

 创建一个自定义变量

---
- hosts: all
  remote_user: root
  vars:             ###自己定义的变量
    http_port: 8080

  tasks:
  - name: "拷贝配置文件"
    template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf

  - name: "重启web服务"
    systemd: name=httpd state=restarted

 然后从其他地方拷贝一个conf文件进行修改

#Listen 12.34.56.78:80
#Listen 80   ####将Listen 80替换为咱们定义的变量然后保存
Listen {{ httpd_port }}

然后进行测试:

ansible的剧本Playbook_第2张图片

成功将80端口改为8080

Playbook的运行方式


通过ansible-playbook命令运行
格式: ansible-playbook ... [options]
[root@ansible PlayBook]# ansible-playbook -h
#ansible-playbook常用选项:

--check or -C             #只检测可能会发生的改变,但不真正执行操作

--list-hosts                #列出运行任务的主机

--list-tags                   #列出playbook文件中定义所有的 tags(列出标签)

--list-tasks                 #列出playbook 文件中定义的所以任务集

--limit                         #主机列表只针对主机列表中的某个主机或者某个组执行

-f                                #指定并发数,默认为5个(最多同时进行5台,如果有100台就用-f指定100)
-t                                #指定tags运行,运行某一个或者多个tags。(前提playbook中有定义tags)


一V                            #显示过程-vv-vvv更详细

 ansible的剧本Playbook_第3张图片

ansible的剧本Playbook_第4张图片ansible的剧本Playbook_第5张图片

主机与用户

在一个playbook开始时,最先定义的是要操作的主机和用户

 除了上面的定义外,还可以在某一个tasks 中定义要执行该任务的远程用户

ansible的剧本Playbook_第6张图片

 还可以定义使用sudo授权用户执行该任务

ansible的剧本Playbook_第7张图片

 Handlers(动作)与Notify(触发)

很多时候当我们某一个配置发生改变,我们需要重启服务,(比如 httpd配置文件文件发生改变了)这时候就可以用到handlers和notify 了;
(当发生改动时)notify actions会在playbook 的每一个task结束时被触发,而且即使有多个不同task通知改动的发生,notify actions 知会被触发一次;比如多个resources指出因为一个配置文件被改动,所以apache需要重启,
是重新启动的操作知会被执行一次。

 先编写一个动作文件

---
- hosts: all
  remote_user: root

  tasks:
  - name: "拷贝配置文件"
    template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf

  - name: "重启web服务"    ###到了这步之后就会跳到handlers上找restart_http
    shell: ls /root
    notify:
      - restart_http      

  - name: "创建一个名为Chengzhang的文件"      ###然后此项就会被跳过,但是下一项还是继续执行
    file: path=/root/Chengzhang state=touch

  - name: "写入文字"
    copy: content= "Hello Chengzhang" dest=/root/Chengzhang

  handlers:
    - name: restart_http   ###这个name要与notify相同,不然匹配不到
      systemd: name=httpd state=restarted

测试查看:

ansible的剧本Playbook_第8张图片

PlayBook中变量的使用

环境说明:这里配置了两个组,一个webA组和一个webB组

[root@ansible PlayBook]# cat /etc/ansible/hosts
[webA]
192.168.100.203
 
[webB]
192.168.100.204

[web:children]
webA
webB

命令行指定变量

执行playbook时候通过参数-e传入变量,这样传入的变量在整个playbook中都可以被调用属于全局变量
(当发生改动时)notify actions会在playbook 的每一个task结束时被触发,而且即使有多个不同task通知改动的发生,notify actions 知会被触发一次;比如多个resources指出因为一个配置文件被改动,所以apache需要重启,
是重新启动的操作知会被执行一次

 写一个变量文件:

---
- hosts: all
  remote_user: root

  tasks:
    - name: "安装变量上的服务"
      yum: name={{ gpg }} state=installed

 使用-e配置变量

ansible的剧本Playbook_第9张图片

 hosts文件中定义变量

在/etc/ansible/hosts文件中定义变量,可以针对每个主机定义不同的变量,也可以定义一个组的变量,然后直接在playbook中直接调用。注意,组中定义的变量没有单个主机中的优先级高。

ansible的剧本Playbook_第10张图片

 编辑playbook剧本

---
- hosts: all
  remote_user: root

  tasks:
    - name: "安装变量上的服务"
      file: name={{ webdir }} state=touch

验证:

ansible的剧本Playbook_第11张图片

 

 所以可以证明,局部变量与全局变量相同时,有先使用局部变量

playbook 文件中定义变量

编写playbook时,直接在里面定义变量,然后直接引用,可以定义多个变量;注意:如果在执行playbook时,又通过-e参数指定变量的值,那么会以-e参数指定的为准。

 创建playbook文件

---
- hosts: webA
  remote_user: root
  vars:                 #自定义变量
    pkg: nginx          #变量1
    dir: /tmp/test1     #变量2
  tasks:
    - name: "install pkg"
      file: name={{ pkg }} state=directory   #引用变量
    - name: "create new dir"
      file: name= {{ dir }} state=touch      #引用变量

执行之后就会安装nginx和创建一个/tmp/test1文件

引用setup变量(setup属于一个模块)

---
- hosts: webA
  remote_user: root

  tasks:
    - name: "create file"
      file: name= {{ ansible_fqdn }}.log state=touch      #引用setup变量

ansible的剧本Playbook_第12张图片

 独立的变量YAML文件中定义

为了方便管理将所有的变量统一放在一个独立的变量YAML文件中,playbook文件直接引用文件调用变量即可。

 单独创建一个yml文件

 

 创建palybook文件

---
- hosts: webA
  remote_user: root
  vars_files:               #引用变量文件
    - ./var.yml             #指定变量文件是本目录下的
var.yml

  tasks:
    - name: "install package"
      yum: name= {{ var1 }} #引用变量
    - name: "create file"
      file: name=/tmp/{{ var2 }}.log state=touch

 总结一下:

变量的类型:

1、主机清单
2、Yaml文件中定义vars:
3、运行ansible-playbook时用-e参数指定
4、编写变量yaml文件,在playbook 中用vars_files:调用5、用setup模块自带的变量

 

Playbook标签的使用

一个playbook 文件中,执行时如果想执行某一个任务,那么可以给每个任务集进行打标签,这样在执行的时候可以通过-t选择指定标签执行,还可以通过--skip-tags选择除了某个标签外全部执行等。

---
- hosts: webA
  remote_user: root

  tasks:
  - name: "拷贝配置文件"
    template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
    tags: httpd.conf                                               ###移动配置文件的标签
  - name: "重启web服务"
    shell: mkdir /opp
    tags: mkdir                                                    ###创建文件的标签

  - name: restart_http
    systemd: name=httpd state=restarted

 只执行指定标签的模块

ansible-playbook -t httpd.conf qq.yml

只执行不是标签的模块

ansible-playbook --skip-tage httpd.conf,make qq.yml

template之when

when 语句参考
条件测试:如果需要根据变量、facts或此前任务的执行结果来做为某task 执行与否的前提时要用到条件测试,通过when语句执行,在 lask中使用jinja2的语法格式、
when 语句:
在 task后添加when子句即可使用条件测试: when语句支持jinja2.表达式语法。

 创建案例

---
- hosts: webA
  tasks:
  - name: 输出Chengzhang
    shell: echo -n "Chengzhang"
    register: xingming          ##"如果上一条命令执行成功,就创建一个xingming"
    ignore_errors: True

  - name: 我要判断
    shell: rm -rf /opp
    when: xingming is success   ##判断xingming是不是被成功创建,成功创建就删除根下的/opp

执行之前

执行之后

 ansible的剧本Playbook_第13张图片

修改playbook文件,通过setup模块获取系统版本去判断。setup常用模块

[root@ansible PlayBook]# cat qq.yml 
# when示例
---
- hosts: all
  remote_user: root
  vars:
    - listen_port: 88
 
  tasks:
    - name: Install Httpd
      yum: name=httpd state=installed
    - name: Config System6 Httpd
      template: src=httpd6.conf.j2 dest=/etc/httpd/conf/httpd.conf
      when: ansible_distribution_major_version == "6"   # 判断系统版本,为6便执行上面的template配置6的配置文件
      notify: Restart Httpd
    - name: Config System7 Httpd
      template: src=httpd7.conf.j2 dest=/etc/httpd/conf/httpd.conf
      when: ansible_distribution_major_version == "7"   # 判断系统版本,为7便执行上面的template配置7的配置文件
      notify: Restart Httpd
    - name: Start Httpd
      service: name=httpd state=started
 
  handlers:
    - name: Restart Httpd
      service: name=httpd state=restarted

template之with_items

with_items迭代,当有需要重复性执行的任务时,可以使用迭代机制。
对迭代项的引用,固定变量名为“item”,要在task中使用with_items给定要迭代的元素列表。
列表格式:
  字符串
  字典

 示例1:通过with_items安装多个不同软件(相当于使用for命令进行循环,可以一次性安装三个服务)

[root@ansible PlayBook]# cat qq.yml 
# 示例with_items
---
- hosts: all
  remote_user: root
 
  tasks:
    - name: Install Package
      yum: name={{ item }} state=installed   # 引用item获取值
      with_items:     #定义with_items
        - httpd
        - vsftpd
        - nginx

与下方案例同等效果

---
- hosts: all
  remote_user: root
  tasks:
    - name: Install Httpd
      yum: name=httpd state=installed
    - name: Install Vsftpd
      yum: name=vsftpd state=installed
    - name: Install Nginx
      yum: name=nginx state=installed

示例2:通过嵌套子变量创建用户并加入不同的组(相当于使用for循环创建用户以及它们的组,可以批量进行)

[root@ansible PlayBook]# cat qq.yml 
# 示例with_items嵌套子变量
---
- hosts: all
  remote_user: root
 
  tasks:
    - name: Create New Group
      group: name={{ item }} state=present
      with_items: 
        - group1
        - group2
        - group3 
 
    - name: Create New User
      user: name={{ item.name }} group={{ item.group }} state=present
      with_items:
        - { name: 'user1', group: 'group1' } 
        - { name: 'user2', group: 'group2' } 
        - { name: 'user3', group: 'group3' }

执行playbook并验证

# 执行playbook
[root@ansible PlayBook]# ansible-playbook qq.yml
 
# 验证是否成功创建用户及组
[root@ansible PlayBook]# ansible all -m shell -a 'tail -3 /etc/passwd'
192.168.100.102 | CHANGED | rc=0 >>
user1:x:500:500::/home/user1:/bin/bash
user2:x:501:501::/home/user2:/bin/bash
user3:x:502:502::/home/user3:/bin/bash
 
192.168.100.105 | CHANGED | rc=0 >>
user1:x:1001:1001::/home/user1:/bin/bash
user2:x:1002:1002::/home/user2:/bin/bash
user3:x:1003:1003::/home/user3:/bin/bash
 
192.168.100.101 | CHANGED | rc=0 >>
user1:x:1002:1003::/home/user1:/bin/bash
user2:x:1003:1004::/home/user2:/bin/bash
user3:x:1004:1005::/home/user3:/bin/bash
 
192.168.100.103 | CHANGED | rc=0 >>
user1:x:1001:1001::/home/user1:/bin/bash
user2:x:1002:1002::/home/user2:/bin/bash
user3:x:1003:1003::/home/user3:/bin/bash

template之for if

通过使用for,if可以更加灵活的生成配置文件等需求,还可以在里面根据各种条件进行判断,然后生成不同的配置文件、或者服务器配置相关等。

示例1

1)编写playbook

[root@ansible PlayBook]# cat qq.yml 
# template for 示例
---
- hosts: all
  remote_user: root
  vars:
    nginx_vhost_port:
      - 81
      - 82
      - 83
 
  tasks:
    - name: Templage Nginx Config
      template: src=nginx.conf.j2 dest=/tmp/nginx_test.conf

2)模板文件编写

# 循环playbook文件中定义的变量,依次赋值给port
[root@ansible PlayBook]# cat nginx.conf.j2 
{% for port in nginx_vhost_port %}   ###使用for循环定义变量prot,从nginx_vhost_port中取值,进行循环
server{
     listen: {{ port }};
     server_name: localhost;
}
{% endfor %}

playbook的验证

[root@localhost ~]# cat /tmp/nginx_test.conf 
server{
     listen: 81;
     server_name: localhost;
}
server{
     listen: 82;
     server_name: localhost;
}
server{
     listen: 83;
     server_name: localhost;
}

示例2

1)编写playbook

[root@ansible PlayBook]# cat testfor02.yml 
# template for 示例
---
- hosts: all
  remote_user: root
  vars:
    nginx_vhosts:
      - web1:
        listen: 8081
        server_name: "web1.example.com"
        root: "/var/www/nginx/web1"
      - web2:
        listen: 8082
        server_name: "web2.example.com"
        root: "/var/www/nginx/web2"
      - web3:
        listen: 8083
        server_name: "web3.example.com"
        root: "/var/www/nginx/web3"
 
  tasks:
    - name: Templage Nginx Config
      template: src=nginx.conf.j2 dest=/tmp/nginx_vhost.conf

2)模板文件编写

[root@ansible PlayBook]# cat nginx.conf.j2 
{% for vhost in nginx_vhosts %}
server{
     listen:    {{ vhost.listen }};
     server_name:    {{ vhost.server_name }};
     root:   {{ vhost.root }}; 
}
{% endfor %}

3)执行playbook并查看生成结果

[root@ansible PlayBook]# ansible-playbook testfor02.yml
 
# 去到一个节点看下生成的结果发现自动生成了三个虚拟主机
[root@linux ~]# cat /tmp/nginx_vhost.conf 
server{
     listen:    8081;
     server_name:    web1.example.com;
     root:   /var/www/nginx/web1; 
}
server{
     listen:    8082;
     server_name:    web2.example.com;
     root:   /var/www/nginx/web2; 
}
server{
     listen:    8083;
     server_name:    web3.example.com;
     root:   /var/www/nginx/web3; 
}

示例3

在for循环中再嵌套if判断,让生成的配置文件更加灵活
1)编写playbook

[root@ansible PlayBook]# cat qq.yml 
# template for 示例
---
- hosts: all
  remote_user: root
  vars:
    nginx_vhosts:
      - web1:
        listen: 8081
        root: "/var/www/nginx/web1"
      - web2:
        server_name: "web2.example.com"
        root: "/var/www/nginx/web2"
      - web3:
        listen: 8083
        server_name: "web3.example.com"
        root: "/var/www/nginx/web3"
 
  tasks:
    - name: Templage Nginx Config
      template: src=nginx.conf.j2 dest=/tmp/nginx_vhost.conf

2)模板文件编写

# 说明:这里添加了判断,如果listen没有定义的话,默认端口使用8888,如果server_name有定义,那么生成的配置文件中才有这一项。
[root@ansible PlayBook]# cat nginx.conf.j2 
{% for vhost in nginx_vhosts %}
server{
     {% if vhost.listen is defined %}
     listen:    {{ vhost.listen }};
     {% else %}
     listen: 8888;
     {% endif %}
     {% if vhost.server_name is defined %}
     server_name:    {{ vhost.server_name }};
     {% endif %}
     root:   {{ vhost.root }}; 
}
{% endfor %}

生成结果:

[root@ansible PlayBook]# ansible-playbook qq.yml
 
# 去到一个节点看下生成的结果发现自动生成了三个虚拟主机
[root@linux ~]# cat /tmp/nginx_vhost.conf 
server{
          listen:    8081;
          root:   /var/www/nginx/web1; 
}
server{
          listen: 8888;   ###如果此项在剧本被定义了,那就使用被定义的项,如果没有被定义,默认选择8888
          server_name:    web2.example.com;
          root:   /var/www/nginx/web2; 
}
server{
          listen:    8083;
          server_name:    web3.example.com;
          root:   /var/www/nginx/web3; 
}

你可能感兴趣的:(服务器,运维)