Ansible--playbook

简介

在ansible中playbook是由多个play组成的列表
paly的主要功能在于将事先归并为一组的主机装扮成事先通过ansible中的task定义好的角色,从根本上讲,所谓的task无非是调用ansible的module讲多个play组织在一个playbook中,即可以让它们连同起来按事先编排好的机制运行
palybook采用的是YAML语言编写的

palybook核心元素
hosts               # 执行的远程主机列表
tasks               # 任务集
varniables          # 内置变量或者自定义变量在playbook中调用
templates           # 模板,可替换模板文件中的变量并实现一些简单的逻辑文件
handlers和notify    # 两个集合使用,由特点条件触发的操作,满足条件方才执行,否则不执行
tags                # 标签,指定某条件任务执行,用于选择运行playbook中的部分代码
                    # ansible具有幂等性,因此会自动跳过没有变化的代码,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常的长,此时,如果确信其没有变化,就可以通过tags跳过这些代码

常用元素示例

hosts元素

hosts元素
指定被控端的远程主机列表
[root@ansible ~]# vim /root/ansible/hosts.yml
---
- hosts: web
  remote_user: root
  
在hosts后面的主机列表形式可以是单个主机的主机名、IP地址、组名,或者两个组的并集、交集、差集,比如:
brian.com       # 单个主机名
192.168.192.129 # 单个IP
web             # 一个组名
web:db          # 两个组的并集
web:!db         # 两个组的差集
web:&db         # 两个组的交集

remote_user表示的是执行远程的用户,一般为root

tasks元素

tasks元素
指定要执行的任务集
[root@ansible ~]# vim /root/ansible/tasks.yml
---
- hosts: web
  remote_user: root

  tasks:
    - name: create new file
      file: name=/root/ansible/newfile state=touch
    - name: create new user
      user: name=zhujingzhi state=present system=yes shell=/sbin/onlogin

这里tasks元素里面写的就是要执行的任务
name 表示一个描述信息
file和user表示使用的模块名,后面跟着的就是使用模块操作的具体的使用方法(这里使用file模块在/root/ansible/创建了一个新的文件,使用user模块创建了一个zhujingzhi的用户)

handlers和notify元素

handlers和notify元素
notify元素,在tasks中的某段代码中定义,作为handlers的触发器(当tasks中的代码中触发到notify的元素,则会执行notify指定的handlers中的代码)
handlers元素属于和tasks同级的列表,其主要作用是定义一个任务(和tasks中的任务是一样的)等待tasks中任务触发notify后执行
[root@ansible ~]# vim /root/ansible/nginx.yml
---
- hosts: web
  remote_user: root

  tasks:
    - name: install nginx
      yum: name=nginx 
    - name: copy nginx config file
      copy: src="/etc/nginx/nginx.conf" dest="/etc/nginx/" backup=yes
      notify: 
        - restart nginx
        - check service
    - name: start nginx
      service: name=nginx state=started enabled=yes

  handlers:
    - name: restart nginx
      service: name=nginx state=restarted
    - name: check service
      shell: killall -0 nginx > /tmp/nginx.log


这里在运行的时候出现了在被管理机器上没有killall的命令的错误,解决方法(yum -y install psmisc)
killall -0 nginx 的意思就是检查nginx的进程有没有启动返回0启动,返回非0服务有问题

tags元素

tags元素
tags元素为tasks里面的任务打上一个标签,方便在执行的时候单独执行tasks里面的单独的任务和被其他调用
[root@ansible ~]# vim /root/ansible/nginx.yml
---
- hosts: web
  remote_user: root

  tasks:
    - name: install nginx
      yum: name=nginx 
      tags: installnginx
    - name: copy nginx config file
      copy: src="/etc/nginx/nginx.conf" dest="/etc/nginx/" backup=yes
      notify: 
        - restart nginx
        - check service
    - name: start nginx
      service: name=nginx state=started enabled=yes
      tags: startnginx

  handlers:
    - name: restart nginx
      service: name=nginx state=restarted
    - name: check service
      shell: killall -0 nginx > /tmp/nginx.log

可单独执行tasks里面的startnginx任务
[root@ansible ~]# ansible-playbook -t startnginx /root/ansible/nginx.yml 
也可以指定两个标签执行
[root@ansible ~]# ansible-playbook -t installnginx,startnginx /root/ansible/nginx.yml 

温馨提示:
这里多个任务也是可以使用一个标签的名字的
比如:
[root@ansible ~]# vim /root/ansible/nginx.yml
---
- hosts: web
  remote_user: root

  tasks:
    - name: install nginx
      yum: name=nginx 
      tags: nginx
    - name: copy nginx config file
      copy: src="/etc/nginx/nginx.conf" dest="/etc/nginx/" backup=yes
      notify: 
        - restart nginx
        - check service
    - name: start nginx
      service: name=nginx state=started enabled=yes
      tags: nginx

  handlers:
    - name: restart nginx
      service: name=nginx state=restarted
    - name: check service
      shell: killall -0 nginx > /tmp/nginx.log
      
使用ansible执行(加-t参数)
[root@ansible ~]# ansible-playbook -t nginx /root/ansible/nginx.yml 

vars元素

vars元素
vars元素指的是定义变量
变量名:仅能由字母、数字和下划线组成,且只能以字母开头
可以在什么地方定义变量呢?如下:
1.ansible setup facts 远程主机的所有变量都是可以被直接调用的
2.在/etc/ansible/hosts中定义
普通变量:主机组中主机单独定义,优先级高于公共变量
公共(组)变量:针对主机组中所有主机定义统一的变量
3.通过命令行指定变量,优先级最高
ansible-playbook -e varname=value
4.在playbook中定义
vars:
  - var1: value1
  - var2: value2
5.在role中定义(role是模块化的设置模式,在role中var可以定义在一个单独的文件中)

示例:
1.ansible setup查看变量
# 查看所有的远程主机上的可用变量
[root@ansible ~]# ansible all -m setup
# grep过滤查看主机名的变量
[root@ansible ~]# ansible all -m setup | grep ansible_fqdn
# setup模块的filter方法过滤查看主机名
[root@ansible ~]# ansible all -m setup -a "filter=ansible_hostname"

2.在/etc/ansible/hosts中定义
[root@ansible ~]# vim /etc/ansible/hosts
[testserver]
192.168.192.129         http_port=8080

在playbook中使用
---
- hosts: web
  remote_user: root

  tasks:
    - name: set hostname
      hostname: name=brian{{ http_port }}.python.com

详细的设置请查看:https://www.cnblogs.com/brianzhu/p/10188676.html

3.通过命令行指定变量,优先级最高
playbook的定义如下(使用{{}}双大括号定义中间是变量名):
---
- hosts: web
  remote_user: root

  tasks:
    - name: install nginx
      yum: name={{ pkname1 }} 
    - name: install nginx
      yum: name={{ pkname1 }} 
    - name: copy nginx config file
      copy: src="/etc/nginx/nginx.conf" dest="/etc/nginx/" backup=yes
    - name: start nginx
      service: name={{ pkname }} state=started enabled=yes

在命令行执行指定(使用 -e 参数指定变量变量赋值的定义格式是k=v格式)
[root@ansible ~]# ansible-playbook -e 'pkname1=nginx pkname2=vsftpd' /root/ansible/nginx.yml

4.在playbook中定义
直接是用vars元素定义变量列表
---
- hosts: web
  remote_user: root
  vars:
    - pkname1: nginx
    - pkname2: vsftpd
  tasks:
    - name: install nginx
      yum: name=nginx 
    - name: copy nginx config file
      copy: src="/etc/nginx/nginx.conf" dest="/etc/nginx/" backup=yes
    - name: start nginx
      service: name=nginx state=started enabled=yes

5.将使用的变量存放到一个文件中,在playbook里面调用
编辑变量文件
[root@ansible ~]# cat /root/ansible/vars.yml
var1: nginx
var2: nsftpd

在playbook中调用
---
- hosts: web
  remote_user: root
  vars_files:
    - vars.yml
  tasks:
    - name: install nginx
      yum: name={{ var1 }} 
    - name: install vsftpd
      yum: name={{ var2 }} 

templates元素

templates元素
主要是对配置文件进行远程主机的copy(能够实现根据不同的主机的配置修改不同的配置文件)
templates 文件也是一个文本文件,嵌套有脚本(使用模板编程语言编写)
模板文件的编程语言使用的是jinja2语言,支持下面的类型:
字符串: 使用单引号或者双引号
数字: 整数,浮点数
列表: [item1,item2,..]
元组: (item1,item2,..)
字典: {key1:value1,key2:value2,..}
布尔值: true/false

算数运算符: +,-,*,/,//,%,**
比较运算符: ==,!=,>,>=,<,<=
逻辑运算符: and,or,not
流表达式: for if when

示例:
使用nginx的打开的进程数为示例
创建模板目录
[root@ansible ~]# mkdir -p /root/ansible/templates

编辑模板文件
在ansible管理机上安装nginx,并copy nginx.conf到/root/ansible/templates中并改名为nginx.conf.j2(改名是必须的这个是模块的规定)
[root@ansible ~]# cp /etc/nginx/nginx.conf /root/ansible/templates/nginx.conf.j2

这里编辑nginx的模板文件将进程数**2
修改/root/ansible/templates/nginx.conf.j2
[root@ansible ~]# vim /root/ansible/templates/nginx.conf.j2

将 worker_processes auto;改成 worker_processes {{ ansible_processor_vcpus**2 }};
这里ansible_processor_vcpus是使用ansible setup得到的远程主机的cpu的个数


编写playbook
[root@ansible ~]# vim /root/ansible/nginxtemp.yml
---
- hosts: web
  remote_user: root

  tasks:
    - name: install nginx
      yum: name=nginx
    - name: copy templates file
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
      notify: restart nginx
    - name: start nginx
      service: name=nginx state=started enabled=yes

  handlers:
    - name: restart nginx
      service: name=nginx state=restarted

执行playbook
[root@ansible ~]# ansible-playbook /root/ansible/nginxtemp.yml

查看结果
这里我的机器是2个CPU的,刚刚在nginx模板文件中设置了worker_processes {{ ansible_processor_vcpus**2 }};所有最后开启的进程是4个
[root@ansible ~]# ansible all -m shell -a "ps aux |grep nginx"
192.168.192.129 | CHANGED | rc=0 >>
root       6127  0.0  0.1 125092  2256 ?        Ss   17:09   0:00 nginx: master process /usr/sbin/nginx
nginx      6128  0.0  0.3 129348  7080 ?        S    17:09   0:00 nginx: worker process
nginx      6129  0.0  0.3 129348  7080 ?        S    17:09   0:00 nginx: worker process
nginx      6130  0.0  0.3 129348  7080 ?        S    17:09   0:00 nginx: worker process
nginx      6131  0.0  0.3 129348  7080 ?        S    17:09   0:00 nginx: worker process


模板文件使用变量(改变nginx端口)
这里把变量定义在了/etc/ansible/hosts中为每台主机定义的(也可以使用上面提到的其他方式定义变量)

设置变量
[root@ansible ~]# vim /etc/ansible/hosts 
[web]
192.168.192.129  http_port=8080

设置模板文件
[root@ansible ~]# vim /root/ansible/templates/nginx.conf.j2
修改:
listen       {{ http_port }} default_server;
listen       [::]:{{ http_port }} default_server;

执行playbook
[root@ansible ~]# ansible-playbook /root/ansible/nginxtemp.yml

查看结果
[root@ansible ~]# ansible all -m shell -a "ss -ntl | grep 8080"
192.168.192.129 | CHANGED | rc=0 >>
LISTEN     0      128          *:8080                     *:*                  
LISTEN     0      128         :::8080                    :::*            

跳过错误继续执行

作用主要是为了解决在playbook中的tasks元素中某段代码执行出现问题是否继续往下执行的一个解决的方法(其默认是出错及停止的) 
playbook文件

---
- hosts: web
  remote_user: root

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

或者

---
- hosts: web 
  remote_user: root

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

流程控制语句

when语句

when语句
when语句表示条件的测试,如果需要根据变量、facts或者此前任务的执行结果来做为某task执行与否的前提时要用到条件测试,通过when语句就可以实现
示例:
在生产环境中系统有6的和7的共存的情况,那么配置有些配置文件在不同的操作系统上是不一样的,这时候我们就要创建两个模板文件根据不同的操作系统执行不同的配置文件copy
# 定义两个配置文件
[root@ansible ~]# cp /etc/nginx/nginx.conf /root/ansible/templates/nginx6.conf.j2
[root@ansible ~]# cp /etc/nginx/nginx.conf /root/ansible/templates/nginx7.conf.j2

编写playbook
[root@ansible ~]# vim /root/ansible/nginxtemp.yml
---
- hosts: web
  remote_user: root

  tasks:
    - name: install nginx
      yum: name=nginx
    - name: copy templates file for centos7
      template: src=nginx7.conf.j2 dest=/etc/nginx/nginx.conf
      when: ansible_distribution_major_version == '7'
      notify: restart nginx
    - name: copy templates file for centos6
      template: src=nginx6.conf.j2 dest=/etc/nginx/nginx.conf
      when: ansible_distribution_major_version == '6'
      notify: restart nginx
    - name: start nginx
      service: name=nginx state=started enabled=yes

  handlers:
    - name: restart nginx
      service: name=nginx state=restarted

with_items语句

with_items语法
with_items表示迭代,当需要执行重复性的任务的时候,就可以使用迭代机制来实现
对于迭代的引用,固定的变量名为"item"
要在tasks中使用with_items给定要迭代的元素列表
支持的列表格式:字符串、字典

示例:
同时执行创建多个文件的任务
编写playbook
[root@ansible ~]# vim /root/ansible/items.yml
---
- hosts: web
  remote_user: root

  tasks:
    - name: create file
      file: name=/root/ansible/{{ item }} state=touch
      with_items:
        - file1
        - file2
        - file3

    - name: install packages
      yum: name={{ item }}
      with_items:
        - htop
        - sl
        - hping3

迭代嵌套子变量

迭代嵌套子变量
创建多个组和用户将多个用户加入到不同的组中
编写playbook
[root@ansible ~]# vim /root/ansible/guser.yml
---
- hosts: web
  remote_user: root

  tasks:
    - name: add groups
      group: name={{ item }} state=present
      with_items:
        - g1
        - g2
        - g3

    - name: add user for goups
      user: name={{ item.name }} group={{ item.group }} state=present
      with_items:
        - { name: 'user1', group: 'g1'}
        - { name: 'user2', group: 'g2'}
        - { name: 'user3', group: 'g3'}

for语句

for语句
最后需要使用for语句生成的例子
server {
  listen: 81
}
server {
  listen: 82
}
server {
  listen: 83
}

这里需要使用模板文件和变量来配合使用生成
palybook编写
[root@ansible ~]# vim /root/ansible/testfor.yml
---
- hosts: web
  remote_user: root
  vars:
    ports:
      - 81
      - 82
      - 83

  tasks:
    - name: create for config
      template: src=/root/ansible/testfor.conf.j2 dest=/root/ansible/testfor.conf

模板文件编写
[root@ansible ~]# vim /root/ansible/testfor.conf.j2
{% for p in ports %}
server {
  listen {{ p }}
}
{% enfor %}

执行playbook
[root@ansible ~]# ansible-playbook /root/ansible/testfor.yml

查看结果
[root@ansible ~]# ansible all -m shell -a "cat /root/ansible/testfor.conf"
192.168.171.129 | CHANGED | rc=0 >>
server {
  listen: 81
}
server {
  listen: 82
}
server {
  listen: 83
}

通过模板文件来获取playbook文件中的设置好的变量并通过for语句进行多次循环(playbook中使用的变量是列表的形式),这样的方式使用起来其实是很灵活的,也可以是上面的列表的形式,也可以是使用字典的形式或者列表嵌套字典的形式
比如:
playbook文件
---
- hosts: web
  remote_user: root
  vars:
    weblist:
      - web:
        port: 81
        name: python.brian.com
        rootdir: /nginx/python
      - web2:
        port: 82
        name: php.brian.com
        rootdir: /nginx/php

  tasks:
    - name: create for config
      template: src=/root/ansible/testfor.conf.j2 dest=/root/ansible/testfor.conf

模板文件
{% for w in weblist %}
server {
  listen {{ w.port }}
  servername {{ w.name }}
  documentroot {{ w.rootdir }}
}
{% endfor %}

if语句

if语句
在for语句中使用,判断playbook中有没有设置变量,设置了生成,没有则不生成,这里只是举例子,还有其他使用的方式,比如一个变量等于大于小于多少执行什么任务等等

[root@ansible ~]# vim /root/ansible/testfor.yml
playbook文件
---
- hosts: web
  remote_user: root
  vars:
    weblist:
      - web:
        port: 81
        rootdir: /nginx/python
      - web2:
        port: 82
        name: php.brian.com
        rootdir: /nginx/php

  tasks:
    - name: create for config
      template: src=/root/ansible/testfor.conf.j2 dest=/root/ansible/testfor.conf

模板文件
[root@ansible ~]# vim /root/ansible/testfor.conf.j2
{% for w in weblist %}
server {
  listen {{ w.port }}
{% if w.name is defined %}
  servername {{ w.name }}
{% endif %}
  documentroot {{ w.rootdir }}
}
{% endfor %}

执行playbook
[root@ansible ~]# ansible-playbook  /root/ansible/testfor.yml 

查看结果
[root@ansible ~]# ansible all -m shell -a "cat /root/ansible/testfor.conf"
192.168.171.129 | CHANGED | rc=0 >>
server {
  listen 81
  documentroot /nginx/python
}
server {
  listen 82
  servername php.brian.com
  documentroot /nginx/php
}

上面的示例只是少部分的流程控制语句

温馨提示:

上面是我在生产中常用的元素,语句,这里主要是把每个元素分开来写的,其实真正的playbook是要把上面的元素语句等结合一起使用的

猜你喜欢

转载自www.cnblogs.com/brianzhu/p/10174123.html
今日推荐