一、概述

  • playbookad-hoc 相比,是一种彻底不同的运用ansible的办法,相似与saltstack的state状况文件。ad-hoc无法耐久运用,playbook能够耐久运用。
  • playbook 是由一个或多个play组成的列表,play的主要功能在于将事前归并为一组的主机装扮成事前经过ansible中的task界说好的人物。
  • 从根本上来讲,所谓的task无非是调用ansible的一个module。将多个play组织在一个playbook中,即能够让它们联合起来按事前编列的机制完成某一使命。

参阅文档:ansible-tran.readthedocs.io/en/latest/d…

Ansible 的基础介绍和环境布置能够参阅我这篇文章:Ansible 介绍与实战操作演示

Ansible playbook 讲解与实战操作

二、playbook 中心元素

  • Hosts 履行的长途主机列表
  • Tasks 使命集
  • Varniables 内置变量或自界说变量在playbook中调用
  • Templates 模板,即运用模板语法的文件,比如装备文件等
  • Handlers 和notity结合运用,由特定条件触发的操作,满意条件方才履行,否则不履行
  • Tags 标签,指定某条使命履行,用于挑选运转playbook中的部分代码。

三、playbook 语法(yaml)

  • playbook运用yaml语法格局,后缀能够是yaml,也能够是yml
  • YAML( /jml/ )参阅了其他多种言语,包括:XML、C言语、Python、Perl以及电子邮件格局RFC2822,Clark Evans在2001年5月在首次宣布了这种言语,别的Ingy dt Net与OrenBen-Kiki也是这言语的共同规划者。
  • YAML格局是相似JSON的文件格局。YAML用于文件的装备编写,JSON多用于开发规划。

1)YAML 介绍

1、YAML 格局如下

  • 文件的榜首行应该以“—”(三个连字符)开端,标明YAML文件的开端。

  • 在同一行中,#之后的内容表明注释,相似于shell,python和ruby。

  • YAML中的列表元素以“-”最初而且跟着一个空格。后边为元素内容。

  • 同一个列表之中的元素应该坚持相同的缩进,否则会被作为过错处理。

  • play中hosts、variables、roles、tasks等对象的表明办法都是以键值中心以“:”分隔表明,而且“:”之后要加一个空格。

2、playbooks yaml装备文件解释

Hosts:运转指定使命的方针主机
remoute_user:在长途主机上履行使命的用户;
sudo_user:
tasks:使命列表
tasks的详细格局:
tasks:
  - name: TASK_NAME
    module: arguments
    notify: HANDLER_NAME
    handlers:
  - name: HANDLER_NAME
    module: arguments
##模块,模块参数:
格局如下:
    (1)action: module arguments
     (2) module: arguments
注意:shell和command模块后直接加命令,而不是key=value类的参数列表
handlers:使命,在特定条件下触发;接受到其他使命的告诉时被触发;

3、示例

---
- hosts: web
  remote_user: root
  tasks:
    - name: install nginx        ##安装模块,需要在被控主机里加上nginx的源
      yum: name=nginx state=present
    - name: copy nginx.conf    ##仿制nginx的装备文件过去,需要在本机的/tmp目录下编辑nginx.conf
      copy: src=/tmp/nginx.conf dest=/etc/nginx/nginx.conf backup=yes
      notify: reload    #当nginx.conf产生改变时,告诉给相应的handlers
      tags: reloadnginx    #打标签
    - name: start nginx service    #服务发动模块
      service: name=nginx state=started
      tags: startnginx    #打标签
  handlers:
    - name: reload
      service: name=nginx state=restarted

2)variables 变量

variables变量有四种界说办法。如下:

1、facts:能够直接调用

ansible中有setup模块,这个模块便是经过facts组件来完成的,主要是节点本身的一个体系信息,bios信息,网络,硬盘等等信息。这儿的variables也能够直接调用facts组件的facters咱们能够运用setup模块来获取,然后直接放入咱们的剧本之中调用即可。

ansible web -m setup

Ansible playbook 讲解与实战操作

常用的几个参数:

ansible_all_ipv4_addresses # ipv4的一切地址
ansible_all_ipv6_addresses # ipv6的一切地址
ansible_date_time # 获取到操控节点时刻
ansible_default_ipv4 # 默许的ipv4地址
ansible_distribution # 体系
ansible_distribution_major_version # 体系的大版别
ansible_distribution_version # 体系的版别号
ansible_domain #体系地点的域
ansible_env #体系的环境变量
ansible_hostname #体系的主机名
ansible_fqdn #体系的全名
ansible_machine #体系的架构
ansible_memory_mb #体系的内存信息
ansible_os_family # 体系的家族
ansible_pkg_mgr # 体系的包管理工具
ansible_processor_cores #体系的cpu的核数(每颗)
ansible_processor_count #体系cpu的颗数
ansible_processor_vcpus #体系cpu的总个数=cpu的颗数*CPU的核数
ansible_python # 体系上的python

搜索

ansible web -m setup -a 'filter=*processor*'

Ansible playbook 讲解与实战操作

2、用户自界说变量

自界说变量有两种办法

  • 经过命令行传入
ansible-playbook命令行中的 -e VARS,--extra-vars VARS,这样就能够直接把自界说的变量传入

运用playbook界说变量,实例如下:

---
- hosts: web
  remote_user: root
  tasks:
    - name: install {{ rpmname }}
      yum: name={{ rpmname }} state=present
    - name: copy {{ rpmname }}.conf
      copy: src=/tmp/{{ rpmname }}.conf dest=/etc/{{ rpmname }}/{{ rpmname }}.conf backup=yes
      notify: reload
      tags: reload{{ rpmname }}
    - name: start {{ rpmname }} service
      service: name={{ rpmname }} state=started
      tags: start{{ rpmname }}
  handlers:
    - name: reload
      service: name={{ rpmname }} state=restarted

运用:

ansible-playbook nginx.yml -e rpmname=keepalived
ansible-playbook nginx.yml --extra-vars rpmname=keepalived
  • 在playbook中界说变量
##在playbook中界说变量如下:
vars:
  - var1: value1
  - var2: value2

运用:

---
- hosts: web
  remote_user: root
  vars:
    - rpmname: keepalived
  tasks:
    - name: install {{ rpmname }}
      yum: name={{ rpmname }} state=present
    - name: copy {{ rpmname }}.conf
      copy: src=/tmp/{{ rpmname }}.conf dest=/etc/{{ rpmname }}/{{ rpmname }}.conf backup=yes
      notify: reload
      tags: reload{{ rpmname }}
    - name: start {{ rpmname }} service
      service: name={{ rpmname }} state=started
      tags: start{{ rpmname }}
  handlers:
    - name: reload
      service: name={{ rpmname }} state=restarted

3、经过roles传递变量

下面介绍roles会运用roles传递变量,小伙伴能够翻到下面看详解讲解。

4、 Host Inventory

能够在主机清单中界说,办法如下:

#向不同的主机传递不同的变量
IP/HOSTNAME varaiable=value var2=value2
#向组中的主机传递相同的变量
[groupname:vars]
variable=value

3)流程操控

1、用when 来表明的条件判别

- hosts: web
  remote_user: root#代表用root用户履行,默许是root,能够省略
  tasks:
  - name: createfile
    copy: content="test3" dest=/opt/p1.yml
    when: a=='3'
  - name: createfile
    copy: content="test4" dest=/opt/p1.yml
    when: a=='4'

如果a==”3″,就将“test3”,写入到web组下被管控机的/opt/p1.yml中, 如果a==”4″,就将“test4”,写入到web组下被管控机的/opt/p1.yml中。

履行

# 语法校验
ansible-playbook  --syntax-check p1.yml
#履行
ansible-playbook -e 'a="3"' p1.yml

2、标签(只履行装备文件中的一个使命)

- hosts: web
  tasks:
  - name: installnginx
    yum: name=nginx
  - name: copyfile
    copy: src=/etc/nginx/nginx.conf dest=/etc/nginx/nginx.conf
    tags: copyfile
  - name: start
    service: name=nginx static=restarted

履行

# 语法校验
ansible-playbook  --syntax-check p2.yml
#履行
ansible-playbook -t copyfile p2.yml 

3、循环 with_items

创立三个用户

- hosts: web
  tasks:
  - name: createruser
    user: name={{ item }}
    with_items:
    - shy1
    - shy2
    - shy3
  - name: creategroup
    group: name={{ item }}
    with_items:
    - group1
    - group2
    - group3 

履行

#语法校验
ansible-playbook  --syntax-check p3.yml
#履行
ansible-playbook p3.yml 

4、循环嵌套(字典)

用户shy1的属组是group1,用户shy2的属组是group2,用户shy3的属组是group3

- hosts: web
  tasks:
  - name: creategroup
    group: name={{item}}
    with_items:
    - group3
    - group4
    - group5
  - name: createuser
    user: name={{item.user}} group={{item.group}}
    with_items:
    - {'user': shy3,'group': group3}
    - {'user': shy4,'group': group4}
    - {'user': shy5,'group': group5}

履行

#语法校验
ansible-playbook  --syntax-check p4.yml
#履行
ansible-playbook p4.yml 

4)模板 templates

  • 模板是一个文本文件,嵌套有脚本(运用模板编程言语编写)
  • Jinja2是python的一种模板言语,以Django的模板言语为原本

该模板支撑:

字符串:运用单引号或双引号;
  数字:整数,浮点数;
  列表:[item1, item2, ...]
  元组:(item1, item2, ...)
  字典:{key1:value1, key2:value2, ...}
  布尔型:true/false
  算术运算:
    +, -, *, /, //, %, **
  比较操作:
    ==, !=, >, >=, <, <=
  逻辑运算:
    and, or, not
  • 通常模板都是经过引用变量来运用的

【示例】

1、界说模板

user  nginx; #设置nginx服务的体系运用用户
worker_processes  {{ ansible_processor_vcpus }}; #作业进程数
error_log  /var/log/nginx/error.log warn; #nginx的过错日志
pid        /var/run/nginx.pid; #nginx发动时分的pid
events {
    worker_connections  1024; #每个进程答应的最大连接数
}
http { #http恳求装备,一个http能够包括多个server
    #界说 Content-Type
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    #日志格局 此处main与access_log中的main对应
    #$remote_addr:客户端地址
    #$remote_user:http客户端恳求nginx认证的用户名,默许不开启认证模块,不会记录
    #$timelocal:nginx的时刻
    #$request:恳求method + 路由 + http协议版别
    #status:http reponse 状况码
    #body_bytes_sent:response body的巨细
    #$http_referer:referer头信息参数,表明上级页面
    #$http_user_agent:user-agent头信息参数,客户端信息
    #$http_x_forwarded_for:x-forwarded-for头信息参数
    log_format  main  '$http_user_agent' '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    #拜访日志,后边的main表明运用log_format中的main格局记录到access.log中
    access_log  /var/log/nginx/access.log  main;
    #nginx的一大优势,高效率文件传输
    sendfile        on;
    #tcp_nopush     on;
    #客户端与服务端的超时时刻,单位秒
    keepalive_timeout  65;
    #gzip  on;
    server { #http服务,一个server能够装备多个location
        listen       {{ nginxport }}; #服务监听端口
        server_name  localhost; #主机名、域名
        #charset koi8-r;
        #access_log  /var/log/nginx/host.access.log  main;
        location / {
            root   /usr/share/nginx/html; #页面寄存目录
            index  index.html index.htm; #默许页面
        }
        #error_page  404              /404.html;
        # 将500 502 503 504的过错页面重定向到 /50x.html
        error_page   500 502 503 504  /50x.html;
        location = /50x.html { #匹配error_page指定的页面途径
            root   /usr/share/nginx/html; #页面寄存的目录
        }
        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}
        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}
        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }
    include /etc/nginx/conf.d/*.conf;
}

2、界说yaml编列

---
- hosts: web
  remote_user: root
  vars:
    - rpmname: nginx
    - nginxport: 8088
  tasks:
    - name: install {{ rpmname }}
      yum: name={{ rpmname }} state=present
    - name: copy {{ rpmname }}.conf
      copy: src=/tmp/{{ rpmname }}.conf dest=/etc/{{ rpmname }}/{{ rpmname }}.conf backup=yes
      notify: reload
      tags: reload{{ rpmname }}
    - name: start {{ rpmname }} service
      service: name={{ rpmname }} state=started
      tags: start{{ rpmname }}
  handlers:
    - name: reload
      service: name={{ rpmname }} state=restarted

运用

##运用reloadnginx标签,从头加载剧本
ansible-playbook nginx.yml -t reloadnginx

copy与template的区别

  • copy模块不代替参数,template模块代替参数
  • template的参数几乎与copy的参数彻底相同

5)handlers(触发事情)

notify:触发
handlers:触发的动作

运用上场景:修改装备文件时

【示例】 正常状况时handlers是不会履行的

- hosts: web
  tasks:
  - name: installredis
    yum: name=redis
  - name: copyfile
    template: src=redis.conf dest=/etc/redis.conf
    tags: copyfile
    notify: restart
  - name: start
    service: name=redis state=started
  handlers:
  - name: restart
    service: name=redis

履行

ansible-playbook -t copyfile p6.yml

6)roles

1、roles介绍与优势

一般状况下将roles写在**/etc/ansible/roles**中,也能够写在其他恣意方位(写在其他方位要自己手动树立一个roles文件夹)

  • 对于以上一切办法有个缺陷便是无法完成一起布置web、database、keepalived等不同服务或许不同服务器组合不同的运用就需要写多个yaml文件,很难完成灵活的调用
  • roles用于层次性,结构化地组织playbook。roles能够依据层次成果主动装载变量文件、tasks以及handlers等。
  • 要运用roles只需要在playbook中运用include指令即可。
  • 简略来讲,roles便是经过分别将变量(vars)、文件(files)、使命(tasks)、模块(modules)以及处理器(handlers)放置于单独的目录中,而且能够便捷的include它们地一种机制。
  • 人物一般用于根据主机构建服务的场景中,但是也能够用于构建看护进程等场景中。4

2、目录结构

创立目录

mkdir -pv ./{nginx,mysql,httpd}/{files,templates,vars,tasks,handlers,meta,default}

Ansible playbook 讲解与实战操作

  • roles/

  • mysql/:mysql服务的yml文件

  • httpd/:apached服务的yml文件

  • nginx/:nginx服务的yml文件

  • files/:存储由copy或许script等模块调用的文件或许脚本;

  • tasks/:此目录中至少应该有一个名为main.yml的文件,用于界说各个task;其他文件需要由main.yml进行包括调用;

  • handlers/:此目录中至少应该有一个名为main.yml的文件,用于界说各个handler;其他文件需要由main.yml进行包括调用;

  • vars/:此目录至少应该有一个名为main,yml的文件,用于界说各个variable;其他的文件需要由main.yml进行包括调用;

  • templates/:存储由templates模块调用的模板文件;

  • meta/:此目录中至少应该有一个名为main.yml的文件,界说当时人物的特殊设定以及依赖关系,其他文件需要由main.yml进行包括调用;

  • default/:此目录至少应该有一个名为main.yml的文件,用于设定默许变量;

3、实战操作

【1】创立目录

mkdir -pv ./{nginx,mysql,httpd}/{files,templates,vars,tasks,handlers,meta,default}

【2】界说装备文件

先下载nginx rpm布置包

# 下载地址:http://nginx.org/packages/centos/7/x86_64/RPMS/
 wget http://nginx.org/packages/centos/7/x86_64/RPMS/nginx-1.18.0-1.el7.ngx.x86_64.rpm -O nginx/files/nginx-1.18.0-1.el7.ngx.x86_64.rpm
  • nginx/tasks/main.yml
- name: cp
  copy: src=nginx-1.18.0-1.el7.ngx.x86_64.rpm dest=/tmp/nginx-1.18.0-1.el7.ngx.x86_64.rpm
- name: install
  yum: name=/tmp/nginx-1.18.0-1.el7.ngx.x86_64.rpm state=latest
- name: conf
  template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
  tags: nginxconf
  notify: new conf to reload
- name: start service
  service: name=nginx state=started enabled=true
  • nginx/templates/nginx.conf.j2
user  nginx; #设置nginx服务的体系运用用户
worker_processes  {{ ansible_processor_vcpus }}; #作业进程数
error_log  /var/log/nginx/error.log warn; #nginx的过错日志
pid        /var/run/nginx.pid; #nginx发动时分的pid
events {
    worker_connections  1024; #每个进程答应的最大连接数
}
http { #http恳求装备,一个http能够包括多个server
    #界说 Content-Type
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    #日志格局 此处main与access_log中的main对应
    #$remote_addr:客户端地址
    #$remote_user:http客户端恳求nginx认证的用户名,默许不开启认证模块,不会记录
    #$timelocal:nginx的时刻
    #$request:恳求method + 路由 + http协议版别
    #status:http reponse 状况码
    #body_bytes_sent:response body的巨细
    #$http_referer:referer头信息参数,表明上级页面
    #$http_user_agent:user-agent头信息参数,客户端信息
    #$http_x_forwarded_for:x-forwarded-for头信息参数
    log_format  main  '$http_user_agent' '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    #拜访日志,后边的main表明运用log_format中的main格局记录到access.log中
    access_log  /var/log/nginx/access.log  main;
    #nginx的一大优势,高效率文件传输
    sendfile        on;
    #tcp_nopush     on;
    #客户端与服务端的超时时刻,单位秒
    keepalive_timeout  65;
    #gzip  on;
    server { #http服务,一个server能够装备多个location
        listen       {{ nginxport }}; #服务监听端口
        server_name  localhost; #主机名、域名
        #charset koi8-r;
        #access_log  /var/log/nginx/host.access.log  main;
        location / {
            root   /usr/share/nginx/html; #页面寄存目录
            index  index.html index.htm; #默许页面
        }
        #error_page  404              /404.html;
        # 将500 502 503 504的过错页面重定向到 /50x.html
        error_page   500 502 503 504  /50x.html;
        location = /50x.html { #匹配error_page指定的页面途径
            root   /usr/share/nginx/html; #页面寄存的目录
        }
        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}
        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #    root           html;
        #    fastcgi_pass   127.0.0.1:9000;
        #    fastcgi_index  index.php;
        #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
        #    include        fastcgi_params;
        #}
        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
    }
    include /etc/nginx/conf.d/*.conf;
}
  • nginx/vars/main.yml
nginxport: 9999
  • nginx/handlers/main.yml
- name: new conf to reload
  service: name=nginx state=restarted
  • 界说剧本文件(roles.yml
- hosts: web
  remote_user: root
  roles:
    - nginx

最终的目录结构如下:

Ansible playbook 讲解与实战操作
履行

ansible-playbook roles.yml

Ansible playbook 讲解与实战操作

到这儿一个完整版的roles演示示例就完成了,接下来也会真实运用ansible playbook roles运用到真实场景中,请小伙伴耐性等待,小伙伴也可关注我的大众号【大数据与云原生技术共享】,会在大众号里分类整理这些文章,看起来更方便~

Ansible playbook 讲解与实战操作