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变量定义与使用
- 命令行
- 在inventory中定义
- 在playbook中定义
- 在role中定义
- 注册变量(register)
- 系统信息变量(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;
}
}