Ansible--playbook介绍

playbook能够理解成剧本,即一份文件能够存放多个ansible任务。后续的操做所有按照playbook中定义的动做执行java

playbook使用YAML格式
nginx

YAML有本身的书写格式,操做时必定要严格按照此格式执行,后面会详细介绍其格式web


playbook示例:redis

首先编辑yaml格式的文件,而此文件中统必定义要执行的操做:
vim  test.yaml     
- hosts: webservers   #指定操做的远程主机 
  remote_user: root   #以root身份执行如下tasks
  tasks: 
  - name: install nginx               #任务的名称,即在执行时显示的标题名称
    yum: name=nginx state=latest      #调用yum模块,与单独使用yum模块时的用法是同样的
  - name: start nginx 
    service: name=nginx enabled=true state=started  #service模块

- hosts: dbservers     #另外一组远程主机
  remote_user: root
  tasks: 
  - name: install redis 
    yum: name=redis state=latest 
  - name: install conf file
    copy: src=/root/redis.conf dest=/app/ owner=redis group=root mode=0644
  - name: start redis 
    service: name=redis state=started
#以上注意hosts与name前要有短横线打头,这是yaml的格式要求
#并且tasks和其后面的具体任务要错开,即不能顶格配置name、service等

ansible-playbook  --list-hosts test.yaml
#主机检查
ansible-playbook  --list-tasks test.yaml
#任务检查
ansible-playbook  --syntax-check test.yaml
#语法检查

存在两个问题
vim

1)只想执行test.yaml中的某一个任务怎么作tomcat

2)配置文件修改了,服务怎么重启,要知道service模块的配置中state已经配置为started了,不会再添加state为restartedbash

上述两个问题都须要执行任务可是只能将全部任务从新执行一遍,效率不高app


问题1)的解决方案:给任务加标签less

vim test.yaml
 tasks: 
  - name: install redis 
    yum: name=redis state=latest 
  - name: install conf file
    copy: src=/root/redis.conf dest=/app/ owner=redis group=root mode=0644
    tags: install    #加此标签,执行时指定此标签则只执行此任务,未加标签的任务不执行
  - name: start redis 
    service: name=redis state=started
    tags: start
#并且能够指定多个标签,多个任务也可使用同一个标签,当调一个标签时能够执行多个任务
ansible-playbook  --list-tags test.yaml 
#查看哪些hosts打了标签
ansible-playbook  -t install,start test.yaml
#指定标签执行

问题2)的解决方案:webapp

条件式触发任务,在配置文件被修改时会触发handlers机制

vim test.yaml
- hosts: dbservers
  remote_user: root
  tasks: 
  - name: install redis 
    yum: name=redis state=latest 
  - name: install conf file
    copy: src=/root/redis.conf dest=/etc/ owner=redis group=root mode=0644
    tags: install 
    notify: restart redis service   #条件通知,当此任务即要复制的文件被修改了notify就会通知handlers执行触发任务
  - name: start redis 
    service: name=redis state=started
    tags: start
  handlers:    #条件触发器,只有知足特定条件才会执行后续任务
  - name: restart redis service 
    service: name=redis state=restarted
#handlers依然调用service模块重启,这样只有配置文件修改才会触发handlers,才会执行此处的service。
#正常配置文件未改变的状况下不会触发此任务
ansible-playbook  -t install  test.yaml  
#将redis.conf的bind端口修改后,测试便可

还有一个问题须要注意,即如何根据实际状况调整参数

如redis.conf配置文件中有maxmemory字段,表示用于redis的内存容量,若是想将此容量调整为当前主机的内存容量的一半该怎么作。

要知道多个远程主机的内存容量不必定是同样的,有的是4G有的是16G如何根据主机自身的内存容量来配置呢?解决方案以下:

这个就用到了变量variables

facts变量:
ansible dbservers -m setup |  less
用户自定义变量:
    a、在playbook中定义变量,以下: 
    vim tree.yml  
- hosts: webservers
  remote_user: root
  vars:   #定义变量,其格式是 变量名+冒号+值
  - pkgname: tree
  tasks:
  - name: install {{ pkgname }} pkg   #调用变量使用花括号
    yum: name={{ pkgname }} state=latest   #在执行任务时就能够调用变量
而后测试便可
ansible-playbook  -C tree.yml  

     b、在ansible-playbook命令中指定变量,其优先级高于playbook中定义的,以下:
     接着上述步骤a进行操做
     ansible-playbook -e "pkgname=memcached" -C tree.yml 
     #在命令行中使用-e指定变量的键值,tree.yml只是本次测试使用
     
    c、经过roles传递的变量,后续介绍
    
    d、host inventory主机列表中定义的变量:
    vim /etc/ansible/hosts 
    [webservers]
    192.168.1.106 pkgname=redis
    192.168.1.107 pkgname=redis
    #在定义主机列表时定义
    若是同一组内主机变量所有相同,即向一个组传递相同变量,还可使用下述方法定义:
    [webservers:var]
    pkgname=redis

模板与变量引用:一般须要在模板中调用变量

template模块:jinja2语法格式,相似于copy模块

vim redis.yml  
- hosts: webservers
  remote_user: root
  tasks:
  - name: install redis maxmem
    template: src=/root/redis.conf dest=/tmp/ owner=redis mode=666 
#在此任务中咱们使用template模块,其提供模板功能,用法相似于copy
vim redis.conf 
maxmemory {{ ansible_memtotal_mb /2 }}mb
#ansible_memtotal_mb是ansible内置变量,能够参与多种运算
#在控制端,定义ansible内置变量并进行除法运算,即取本本机内存空间的一半
#这样即便远程多台主机的内存大小不一致,此变量仍会取内存大小的一半并将取出的最终结果定义在此配置文件中传给远程主机
ansible-playbook  redis.yml   
#template支持嵌套脚本的文本文件这是与copy模块的主要区别
#此示例能够上述提到的根据具体主机分别设置参数的问题。关键就是使用template模块并使用正确的变量

条件测试:

when语句,只有知足when条件才会执行任务

cat dfile.yml  
- hosts: webservers
  remote_user: root
  tasks:
  - name: copy file
    copy: src=/root/diff1.txt dest=/app/
    when: ansible_default_ipv4['address'] == '172.18.251.244'  #只有知足此条件才可以执行此任务
    #此条件说明当地址为127.18.251.244时执行copy模块的操做,ansible_default_ipv4是ansible的内置变量,中括号[]表示调用变量的子键
    #
  - name: copy file2
    copy: src=/root/diff2.txt dest=/app/
    when: ansible_default_ipv4['address'] == '192.168.1.107'
    #
ansible-playbook  --syntax-check dfile.yml 
#检查语法
ansible-playbook  dfile.yml

循环:迭代

须要重复执行任务,如在远程主机上安装多个程序包

cat tomcat.yml  
- hosts: dbservers
  remote_user: root
  vars:
  - jdk_version: 1.8.0   #定义变量
  tasks:
  - name: install  pkgs
    yum: name={{ item }} state=latest   #变量的调用方法是{{ }},而item是变量,其内容就是with_items中的
    with_items: 
    - nginx
    - java-{{ jdk_version }}-openjdk   #此处使用变量调用上文的内容
    - tomcat 
    - tomcat-webapps
    - tomcat-docs-webapp
    - tomcat-admin-webapps
    #以上是在一个任务中要安装的软件包
    扩展:以上是在一个任务中安装多个软件包,若是是建立多个用户、组也是相似的方法
    总结:迭代循环配合变量,迭代的关键字段是with_items,变量的调用使用{{ }}
    
ansible-playbook  tomcat.yml   #执行操做

下面思考一个问题:

若是使用循环方式安装多个软件包,而每一个软件包的版本号基本是不同的,那如何动态的在安装软件包时添加版本号,而不是事先写好在yaml文件中?

解决上述问题须要调用字典

cat tomcat.yml  
- hosts: dbservers
  remote_user: root
  tasks:
  - name: install  pkgs
    yum: name={{ item.name }}-{{ item.version }} state=latest   #item是使用循环的固定变量,此处item变量调用字典内容
    with_items:    #此处即所谓的字典,定义好软件包名称和版本号
    - { name: 'nginx', version: 1.10.2 }
    - { name: 'tomcat',version: 7.0.69 } 
#在一个任务中使用字典安装软件
ansible-playbook  -C tomcat.yml

再来看下面这个例子:循环加字典的使用
在控制端修改了两份文件:tomcat-users.xml和 server.xml
如今要是先的是将此二份文件经过copy模块复制到远程主机
cat tomcat.yml 
- hosts: dbservers
  remote_user: root
  tasks:
  - name: install config file 
    copy: src={{ item.file }} dest={{ item.conf }}
    with_items:
    - { file: '/root/server.xml',conf: '/etc/tomcat/server.xml' }
    - { file: '/root/tomcat-users.xml',conf: '/etc/tomcat/tomcat-users.xml' }
#在字典中咱们定义file和conf
ansible-playbook  tomcat.yml
#完成上述步骤,就能够到远程主机上查看指定路径的文件是否已经修改过

roles  角色:

vim /etc/ansible/ansible.cfg 
roles_path    = /etc/ansible/roles   #roles的路径

/etc/ansible/roles/nginx/   
#其中nginx就是一个角色,在nginx目录下应该具备特定的目录层级结构,如:handlers  tasks  templates  vars
cat /etc/ansible/roles/nginx/tasks/main.yml    #tasks是nginx角色的一个任务模块,main.yml是固定格式不能改变
- name: install nginx pkg
  yum: name=nginx state=latest
- name: start nginx service 
  service: name=nginx state=started enabled=true
  #此任务模块完成两个动做,安装nginx和启动nginx
  
而后配置playbook文件
cat websrv.yml 
- hosts: webservers
  remote_user: root
  roles:   #不须要像之前那样配置tasks之类的,而是直接指定角色
  - nginx 
  #对webservers的主机以root身份调用nginx角色,而nginx橘色定义了两个task任务

ansible-playbook  -C websrv.yml 
#测试

总结:建立角色nginx,配置playbook文件,而此文件只需调用角色便可,具体操做已经在角色的模块中定义好了

示例:
基于模板生成nginx配置文件
第一步定义nginx内的变量                    #定义变量,将被templates模板调用
cat /etc/ansible/roles/nginx/vars/main.yml 
nginx_server_port: 8888
nginx_server_name: www.abc.com
nginx_doc_root: /webdata
第二步配置nginx下的模板文件                #定义模板文件,调用vars变量,此模板将用于生成nginx服务的配置文件
cat /etc/ansible/roles/nginx/templates/web-conf.j2 
server {
        listen {{ nginx_server_port }};
        server_name {{ nginx_server_name }};

        location  / {
                root {{ nginx_doc_root }};
        }
}
第三步定义nginx下的任务文件                #定义多项任务,安装nginx、配置文件、建立文件、开启服务
cat /etc/ansible/roles/nginx/tasks/main.yml  
- name: install nginx pkg
  yum: name=nginx state=latest
- name: install conf file
  template: src=web-conf.j2 dest=/etc/nginx/conf.d/web.conf
- name: create datadir
  file: path={{ nginx_doc_root }} state=directory    #此目录即nginx模板文件中将使用的
- name: start nginx service 
  service: name=nginx state=started enabled=true
第四步配置playbook文件                #定义webservers组中主机以root身份调用nginx角色,而nginx角色能作什么上述三个步骤已定义
cat /root/websrv.yml 
- hosts: webservers
  remote_user: root
  roles:
  - nginx
第五步测试i
ansible-playbook   websrv.yml 
#执行完上述操做,在远程webservers主机的/etc/nginx/conf.d/web.conf文件中就会有nginx模板下web-conf.j2文件的内容
#

接着以上述实验为基础,再继续延伸

定义handlers模块

进入nginx角色目录下
cat handlers/main.yml 
- name: restart nginx service
  service: name=nginx state=restarted
而后咱们修改vars下的文件内容,如将端口修改
cat vars/main.yml 
nginx_server_port: 8888   #变量改变,templates文件就会变化,templates文件变化就会触发notify执行handlers的动做
接着在tasks下修改触发条件
cat tasks/main.yml 
- name: install conf file
  template: src=web-conf.j2 dest=/etc/nginx/conf.d/web.conf
  notify: restart nginx service   #此处notify定义的与handlers中的name对应
最后playbook文件内容不变
ansible-playbook  websrv.yml 

试想一下,若是每次修改配置文件,都要所有执行一遍playbook操做太麻烦并且也没必要要
因此咱们可使用tags标签,指定标签的任务才会执行,如:
vim tasks/main.yml 
 name: install conf file
  template: src=web-conf.j2 dest=/etc/nginx/conf.d/web.conf
  notify: restart nginx service
  tags: changed   #指定标签,这样修改配置文件后咱们只要对特定标签进行操做便可
- name: create datadir
  file: path={{ nginx_doc_root }} state=directory 
  tags: changed   #此处使用与配置文件相同标签,由于配置文件若是修改了目录此处也要跟着修改
  #完成上述操做,咱们能够修改配置文件,而后ansible下发配置便可
  ansible-playbook -t changed -C websrv.yml
  #测试

以上测试使用到模板文件、变量文件、触发器、任务管理模块 ,下面来使用静态文件复制nginx的配置文件
 
静态文件:
  编辑在角色下的files文件,做为静态文件
  vim files/nginx.conf    #随便修改写内容,如日志格式,只要能看到效果便可
  cat  tasks/main.yml    #修改tasks配置文件
- name: install config file2
  copy: src=nginx.conf dest=/etc/nginx/nginx.conf    #复制静态文件
  notify: restart nginx service    #启动触发,一旦此文件被修改就会执行handlers操做
  tags: changed    #一样的此任务也加入同一标签中
  而后执行便可
  ansible-playbook -t changed  websrv.yml


结束

相关文章
相关标签/搜索