1.使用playbook有什么好处 2.认识playbook(自动部署nginx)(自动部署docker-ce社区版) 3.YAML语法 4.playbook文件结构 5.在变更时执行操作(handlers) 6.任务控制(tags) 7.playbook文件调试 8.案例:自动部署tomcat 9.Playbook变量定义与使用 10.playbok文件复用 11.流程控制 12.jinja模版渲染配置文件

1. 使用playbook有什么好处

Ansible真正的能力在于使用playbook,也就称为剧本
当我们在某个目录下执行某个命令的时候,那么我们可以使用ansible的ad hoc的模式快速执行,而无不虚编写文件或者剧本,但是对于配置的管理和应用的部署,通常有很多的操作,单独的去写ad hoc命令麻烦很多,而且ad hoc适用于简单命令的执行,所以我们使用playbook去完成,如果ansible是工作中用到的工具,那么ploybook就是相当于你使用ansible的说明书,而你的主机就是原材料,写playbook就像写说明书一样,它是一个按顺序执行的一个过程,playbook和ad hoc完全不是一种模式,并且功能强大

Playbook的特点 易读的编排语言:它是用最主流的yaml格式去编写的来实现应用的编排,非常适合配置和应用部署,也非常适合部署复杂的任务,我们可以通过声明式的内容将复杂的工作通过playbook进行编排。

这个—syntax-check是检查playbook的语法

[root@ansible playbook-test]# ansible-playbook nginx.yaml   --syntax-check 

playbook: nginx.yaml
[root@ansible playbook-test]# vim nginx.yaml 
[root@ansible playbook-test]# cat nginx.yaml 

---
 - hosts: webservers
  vars:
    hello: Ansible
  tasks:
  - name: Add repo
    yum_repository:
      name: nginx
      description: nginx repo
      baseurl: http://nginx.org/packages/centos/7/$basearch/
      gpgcheck: no
      enabled: 
  - name: Install nginx
    yum:
      name: nginx
      state: latest
  - name: Copy nginx configuration file
    copy:
      src: ./site.conf
      dest: /etc/nginx/conf.d/site.conf
  - name: Start nginx
    service:
      name: nginx
      state: started
  - name: Create wwwroot directory
    file:
      dest: /var/www/html
      state: directory
  - name: Create test page index.html
shell: echo "hello {{hello}}" > /var/www/html/index.html
[root@ansible playbook-test]# ls
nginx.yaml  site.conf

[root@ansible playbook-test]# vim site.conf
server {
    listen 80;
    server_name devops;
    location / {
        root   /var/www/html;
index index.html; }
}

执行playbook [root@ansible playbook-test]# ansible-playbook nginx.yaml 查看进程已经启动

[root@ansible playbook-test]# ansible webservers -m shell -a "ps -ef |grep nginx"
10.4.7.22 | SUCCESS | rc=0 >>
root      10713      1  0 16:46 ?        00:00:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx     10714  10713  0 16:46 ?        00:00:00 nginx: worker process
root      10849  10848 10 16:49 pts/1    00:00:00 /bin/sh -c ps -ef |grep nginx
root      10851  10849  0 16:49 pts/1    00:00:00 grep nginx

10.4.7.21 | SUCCESS | rc=0 >>
root      10953      1  0 16:46 ?        00:00:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx     10954  10953  0 16:46 ?        00:00:00 nginx: worker process
root      11088  11087  0 16:49 pts/1    00:00:00 /bin/sh -c ps -ef |grep nginx
root      11090  11088  0 16:49 pts/1    00:00:00 grep nginx

批量部署docker-ce社区版

这里运用的模块就shell模块和service,还是很简单的。


---
- hosts: webservers
  gather_facts: no
  remote_user: root


  tasks:
  - name: install packages
    shell: yum -y install yum-utils device-mapper-persistent-data lvm2

  - name: docker packages
    shell: wget -O /etc/yum.repos.d/docker-ce.repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

  - name: install docker-ce
    shell: yum -y install docker-ce

  - name: daocloud speed up
    shell: curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://f1361db2.m.daocloud.io

  - name: systemctl start docker
    service: name=docker state=started

测试查看是否安装成功

[root@ansible ~]# ansible webservers -m shell -a "docker -v"
10.4.7.21 | SUCCESS | rc=0 >>
Docker version 19.03.5, build 633a0ea

10.4.7.22 | SUCCESS | rc=0 >>
Docker version 19.03.5, build 633a0ea

YAML语法格式 缩进表示层级关系 不支持制表符“tab” 缩进 通常开头缩进2个空格 字符后缩进1个空格,如冒号,逗号等 “---”表示YAML格式,一个文件的开头 “#”注释 在变更时执行操作(handlers)处理器 主要用于当你出来某个操作变更时,它帮你触发另一个任务

  • hosts: webservers gather_facts: no 这个会收集列表主机的信息,会很耗时间,一般就是禁用掉,这样的话就提高我们playbook的效率

自动部署tomcat 1. 安装jdk 2. 下载tomcat包 3. 解压tomcat 4. 启动

安装tomcat

---
- hosts: webservers
  gather_facts: no
  vars:
    tomcat_version: 9.0.29
    tomcat_install_dir: /usr/local

  tasks:
    - name: Install java-1.8.0-openjdk.x86_64
      shell: yum -y install java-1.8.0-openjdk.x86_64 state=present

    - name: Download tomcat
      get_url: url=http://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-9/v9.0.29/bin/apache-tomcat-9.0.29.tar.gz dest=/tmp
    - name: Unarchive tomcat-{{ tomcat_version }}.tar.gz
      unarchive:
        src: /tmp/apache-tomcat-{{ tomcat_version }}.tar.gz
        dest: "{{ tomcat_install_dir }}"
        copy: no

    - name: Start tomcat
      shell: cd {{ tomcat_install_dir }} &&
             mv apache-tomcat-{{ tomcat_version }} tomcat8 &&
             cd tomcat8/bin && nohup ./startup.sh &
[root@ansible tomcat-playbook]# ansible-playbook tomcat.yaml
[root@ansible tomcat-playbook]# ansible webservers -m shell -a "ps -ef |grep tomcat"

Playbook变量定义与使用

  1. 命令行
  2. 在inventory中定义
  3. 在playbook中定义
  4. 在role中定义
  5. 注册变量(register)
  6. 系统信息变量(facts)

命令行定义变量 列出主要的变量信息

[root@ansible tomcat-playbook]# ansible-playbook --list-tags tomcat.yaml 

playbook: tomcat.yaml

  play #1 (webservers): webservers	TAGS: []
      TASK TAGS: []
[root@ansible tomcat-playbook]# ansible-playbook --list-tasks tomcat.yaml 

playbook: tomcat.yaml

  play #1 (webservers): webservers	TAGS: []
    tasks:
      Install java-1.8.0-openjdk.x86_64	TAGS: []
      Download tomcat	TAGS: []
      Unarchive tomcat-{{ tomcat_version }}.tar.gz	TAGS: []
      Start tomcat	TAGS: []

debug模块在执行期间打印语句,并且可用于调试变量或表达式,而不必停止playbook。

[root@ansible tomcat-playbook]# vim 1.yaml

---
- hosts: webservers
  gather_facts: no
  remote_user: root

  tasks:
  - name: test var
    debug: msg="{{work_dir}}"
[root@ansible tomcat-playbook]# ansible-playbook 1.yaml -e work_dir=/usr/local

定义这个变量也有一定的要求,变量名是要以字母为开头

还有一种在inventory中定义 在/etc/ansible/hosts去定义变量,为一组主机或者多个主机传递不同的变量 也可以单独写到/etc/ansible/group_vars/webservers.yml下,它默认会读取你哪个组里面的变量,以yml的模式更方便 http_port: 8090 server_name: xiabanle


[root@ansible group_vars]# ansible webservers -a "echo {{http_port}}"
10.4.7.22 | SUCCESS | rc=0 >>
8090

10.4.7.21 | SUCCESS | rc=0 >>
8090

[root@ansible group_vars]# ansible webservers -a "echo {{server_name}}"
10.4.7.22 | SUCCESS | rc=0 >>
xiabanle

10.4.7.21 | SUCCESS | rc=0 >>
xiabanle

在playbook使用debug模块去定义变量

---
- hosts: webservers
  gather_facts: no
  remote_user: root
  vars:
    - work_dir: /usr/local
    - nginx_version: 1.16

  tasks:
  - name: Install nginx
debug: msg="{{work_dir}}/nginx/{{nginx_version}}"
[root@ansible tomcat-playbook]# ansible-playbook 1.yaml --syntax-check

playbook: 1.yaml
[root@ansible tomcat-playbook]# ansible-playbook 1.yaml

使用file模块创建文件

---
- hosts: webservers
  gather_facts: no
  remote_user: root
  vars:
    - work_dir: /opt
    - nginx_version: 1.11

  tasks:
  - name: create dir
    file: "dest={{work_dir}}/nginx/{{nginx_version}} state=directory"

注册变量—register 注册变量就是将你某个任务执行的结果保存到一个变量中,这样的话就是能动态的获取一个变量,例如执行完一个任务,返回有个状态,那么希望根据这个状态异步处理,因为之前的变量由于对应好了,很难知道这次获取的什么变量。 这里有个debug就是专门调试变量用的,这里时创建文件的同时动态定义文件的时间 一般这种就是启动两个服务,这两个服务是有依赖关系的,只有启动第一个服务,第二个才能启动起来,那这种情况下,就可以在启动服务下加一个注册变量,如果第一个服务启动的时候会有pid,或者有其他的输出然后用到定义的注册变量。

---
- hosts: webservers
  gather_facts: no
  remote_user: root
  vars:
    - work_dir: /opt

  tasks:
    - name: register var
      command: date +"%F %T"
      register: datetime

    - name: touch file
      #debug: msg={{datetime}}
      file: dest=/tmp/r_{{datetime.stdout}} state=touch

系统信息变量(fasts) 以系统变量调用主机名/主机IP并创建文件 这个可以通过set up去调用,来查看我们的ansible的接口api

[root@ansible test]# ansible webservers -m setup

---
- hosts: webservers
  gather_facts: yes
  remote_user: root

  tasks:
  - name: touch file
    file: dest=/tmp/devops_{{ansible_hostname}} state=touch

playbok文件复用 将我们的文件进行复用,可以使用playbook中的incloud_tasks和import_tasks导入进来,这样的好处就是,当我们去写一个比较大的playbook时,可以将它分解成很多小的任务,分解成小的任务之后呢,就能在其他的地方引用,第二个好处就是能组织playbook这些功能模块,如果要写一个大的剧本,可能是上百行,就不太好维护管理了,所以就有了include_tasks和import_tasks的实现来完成这些需求 Include和import的区别 都是导入文件的 Include(动态):在运行时导入  --list-tags, --list-tasks 不会显示到输出  不能使用notify触发来自include内处理程序名称(handlers)

Import*(静态) :在playbook解析时预先导入,就是在playbook之前提前把预先的就导入进来了,  不能与循环一起使用  将变量用于目标文件或角色名称时,不能使用inventory(主机/主机组等)中的变量 复用案例: 安装lnmp/lnmt 只需要将—import调用使用的的那个yaml就可以了

vim lnmp.yaml

---
 - import_playbook: nginx.yaml
 - import_playbook: mysql.yaml
 - import_playbook: php.yaml

vim nginx.yaml

---
- hosts: webservers
  gather_facts: no
  remote_user: root

  tasks:
  - name: Install nginx
    debug: msg="install nginx ... "  
[root@ansible web]# ansible-playbook lnmp.yaml   

Import导入的是playbook,而include的是导入的任务文件

[root@ansible web]# ansible-playbook test.yaml

---
- hosts: webservers
  gather_facts: no
  remote_user: root

  tasks:
  - name: task1
    debug: msg="test1"

  - name: task2
    debug: msg="test2"

但是部署的任务这个tasks,任务比较多时就可以进行分解,可以分成独立的文件,例如有两个任务,我将第一个tasks分解成一个文件,第二个分解成一个文件用include再导入进去

vim test.yaml

---
- hosts: webservers
  gather_facts: no
  remote_user: root

  tasks:
  - include_tasks: task1.yaml
  - include_tasks: task2.yaml

vim task1.yaml

---
- name: tasks1
  debug: msg="test1"
vim task2.yaml

---
- name: tasks2
  debug: msg="test2"

流程控制 循环 批量创建用户/文件/拷贝文件也可以使用

- name: create file
  file: path=/tmp/{{item}} state=touch
  with_items:
      - "1.txt"
      - "2.txt"
      - "3.txt"
      - "4.txt"
执行效果
[root@hdss7-200 test-roles]# ansible-playbook -i hosts site.yaml --tags nginx

PLAY [roles] ***************************************************************************************************

TASK [nginx : create file] *************************************************************************************
changed: [10.4.7.22] => (item=1.txt)
changed: [10.4.7.22] => (item=2.txt)
changed: [10.4.7.22] => (item=3.txt)
changed: [10.4.7.22] => (item=4.txt)

PLAY RECAP *****************************************************************************************************
10.4.7.22                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
常用循环语句:

比如拷贝文件

- name: copy html
  copy: src=/tmp/{item}} dest=/tmp
  with_items:
      - "a.html"
      - "b.html"
      - "c.html"

或者通配符,像一些拷贝一些目录的tar.gz的压缩包的时候比如比较多的时候就会用到可以使用fileglob,或者item,进行for循环,进行批量执行,简化操作步骤。

- name: copy html
  copy: src={{item}} dest=/tmp
  with_fileglob:
      - "/tmp/*.html"

模版 比如部署一个应用,nginx,etcd,这些都有自己的配置文件,就比如将nginx,虚拟主机的配置文件,渲染到我们的nginx上,就可以使用template,这个模块就专门支持jr模版 这里定义j2的模版,然后拷贝这个文件过去进行渲染

[root@hdss7-200 test-roles]# cat /tmp/nginx.conf 
{% set domain_name = domain %}
server {
   listen 80;
    server_name {{ domain_name }};
    location / {
         root /usr/share/html;

    }
}

定义的变量,进行传递

[root@hdss7-200 test-roles]# cat group_vars/roles.yaml 
domain: www.xxxxx.com

定义的任务类型

- name: vire hosts
  template: src=/tmp/nginx.conf dest=/etc/nginx/conf.d/

比如再传递端口的变量,在jinja里使用ansible的变量之间{{ }}去使用

[root@hdss7-200 test-roles]# cat /tmp/nginx.conf 
{% set domain_name = domain %}
server {
   listen {{ http_port }};
    server_name {{ domain_name }};
    location / {
         root /usr/share/html;

    }
}

我在ansible去定义这个变量

[root@hdss7-200 test-roles]# cat group_vars/roles.yaml 
domain: "www.maidi.com"
http_port: "80"

执行成功会将使用j2的模版将我们的配置文件拷贝过来,我们通过j2的模版和ansible定义变量就可以渲染很多我们的功能和需求

[root@hdss7-22 conf.d]# cat nginx.conf 
server {
   listen 80;
    server_name www.maidi.com;
    location / {
         root /usr/share/html;

    }
}