playbook是Ansible的配置、部署和编排的语言。Playbook可以定制配置,他们可以按照你指定的操作步骤有序执行,支持同步和异步方式。形象点的说就是:如果ansible的各模块(能实现各种功能)是车间里的各工具;
playbook就是指导手册,目标远程主机就是库存和原料对象。
playbook可作为一个适合部署复杂应用程序的基础PlayBook是由一个或多个“play”组成的列表,在play中的内容被我们称之为tasks,也叫任务,也就是说多个tasks组成了一个play,task调用Ansible的各种模块(module)。将多个play组织在一个playbook剧本中,组成一个完整的流程控制集合,完成一个复杂的工作。
1.2yaml语言Playbook采用YAML语言编写,每一个Ansible的Playbook都是一个YAML格式的文件,因此要学习编写剧本(playbook),我们先来了解YAML语法的基本用法。
1.2.1yaml有如下几个基本规则1、yaml文件以---开头,以表明这是一个yaml文件,就像xml文件在开头使用宣称它是xml文件一样。但即使没有使用---开头,也不会有什么影响。
2、yaml中使用"#"作为注释符。
3、大小写敏感
4、使用缩进表示层级关系:YAML使用一个固定的缩进风格表示层级结构,同样的缩进代表同样的级别。缩进时不允许使用Tab键,只允许使用空格。
注:缩进的空格数目没有限制,但要求同一层级左对齐。判断是否是同一级别是通过缩进结合换行来实现的。
5、冒号,以冒号结尾的除外,其他所有冒号后面必须有空格。
6、短横线,表示列表项,使用一个短横杠加一个空格。多个项使用同样的缩进级别作为同一列表。
7、关于布尔值的书写格式,即true/false的表达方式。其实playbook中的布尔值类型非常灵活,可分为两种情况:
模块的参数:这时布尔值作为字符串被ansible解析。接受yes/on/1/true/no/off/0/false。例如上面示例中的update_cache=yes。
非模块的参数:这时布尔值被yaml解释器解析,完全遵循yaml语法。接受不区分大小写的true/yes/on/y/false/no/off/n。例如gather_facts: True。
建议遵循ansible的官方规范,模块的布尔参数采用yes/no,非模块的布尔参数采用True/False。
8、YAML文件扩展名通常为yml或yaml
1.2.3yaml语法对于Ansible, 每一个YAML文件都是从一个列表(列表list,又称为序列 sequence)开始。列表中的每一项都是一个键值对,通常它们被称为一个 “哈希” 或 “字典”或映射。所以, 我们需要知道如何在YAML中编写列表和字典。
列表中的所有成员都开始于相同的缩进级别, 并且使用一个 "- " 作为开头(一个减号和一个空格)。
具体在ansible playbook中,列表所描述的是局部环境,它不一定要有名称,只要使用"- ",它就表示圈定一个范围,范围内的项都属于该列表
一个字典是由一个简单的 键: 值 的形式组成(这个冒号后面必须是一个空格),它一般当作列表项的属性。
k/v的值可同行写也可换行写。同行使用:分隔
v可是个字符串,也可是另一个列表
YAML列表与字典是可以自由组合在一起的,它们之间可以相互嵌套,通过非常灵活的组合,可以帮助我们描述更加复杂的对象属性。
此外, Ansible使用“{{ var }}”来引用变量.。如果一个值以 “{” 开头, YAML 将认为它是一个字典, 所以我们必须引用它, 像这样foo: "{{ var }}"。
下面我们来看一个playbook的例子
在编写剧本之前,我们先来回顾两个简单的ad-hoc命令,比如如下两条命令:
[root@cong11 ~]# ansible web_servers -m ping
[root@cong11 ~]# ansible web_servers -m file -a "path=/tmp/test211 state=directory"
上述命令表示使用ping模块去ping主机组web_servers中的主机,然后再用file模块在主机组web_servers的主机上创建目录,那么,如果把上述命令转换成playbook的表现形式,该如何书写呢?示例如下
---
- hosts: web_servers
remote_user: root
tasks:
- name: ping the host
ping:
- name: make directory test
file:
path: /data/testfile
state: directory
好了,aa.yml已经编写完成了,但是,我们还没有运行这个剧本,运行剧本需要使用'ansible-playbook'命令,示例如下
[root@cong11 ~]# ansible-playbook /root/aa.yml
1.3playbook核心元素及常用参数PLAY [web_servers] **************************************************************
TASK [Gathering Facts] **********************************************************
ok: [nginx02]
ok: [nginx01]TASK [ping the host] ************************************************************
ok: [nginx02]
ok: [nginx01]TASK [make directory test] ******************************************************
changed: [nginx01]
changed: [nginx02]PLAY RECAP **********************************************************************
nginx01 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
nginx02 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
1、PlayBook核心元素包括
target:定义PlayBook的远程主机组
variables:定义PlayBook使用的变量
tasks:定义远程主机上执行的任务列表
handlers:处理器,当某条件满足时,触发执行的操作。例如修改配置文件之后,启动跟handlers任务重启相关联的服务
roles :角色,用于层次性、结构化地组织playbook。roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。
2、target常用参数详解
hosts:运行指定任务的目标主机,可以是一个主机组、主机、多个主机,中间以冒号分隔,也可以用all参数表示所有主机。
remote_user:指定远程主机上的执行任务的用户。
gather_facks:获取远程主机facts基础信息
3、variable常用参数详解
vars:在yaml文件中定义变量赋值。定义格式,变量名:变量值
vars_files:指定变量文件,在文件中定义变量
4、tasks常用参数详解
name:任务显示名称也是屏幕显示信息
module_name: module_args: 需要使用的模块名字: 模块参数
关于task说明:
1、Play的主体部分是task列表,task列表中的各任务按次序逐个在hosts中指定的主机上执行,即在所有主机上完成第一个任务后再开始第二个任务。
2、在运行playbook时(从上到下执行),如果一个host执行task失败,整个tasks都会回滚,请修正playbook 中的错误,然后重新执行即可。
3、每一个task必须有一个名称name,这样在运行playbook时,从其输出的任务执行信息中可以很好的辨别出是属于哪一个task的。 如果没有定义name,‘action’的值将会用作输出信息中标记特定的task。
4、定义一个task,常见的格式:” module_name: module_args” 例如:yum: name=httpd state=absent update_cache=yes
5、ansible的自带模块中,command模块和shell模块无需使用key=value格式
5、handler: 常用参数详解
notify: “notify”这个action可用于在每个play的最后被触发,这样可以避免多次有改变发生时每次都执行指定的操作,取而代之,仅在所有的变化发生完成后一次性地执行指定操作。
handler: 也是task的列表。在notify中列出的操作称为handler,也即notify中调用handler中定义的操作。
1.4playbook运行方式1、ansible-playbook --check playbook.yaml #只检测可能会发生的改变,但不真执行操作
2、ansible-playbook --list-hosts playbook.yaml #列出运行任务的主机
3、ansible-playbook --syntax-check playbook.yaml #检查yaml文件的语法是否正确
4、ansible-playbook -t TAGS_NAME playbook.yaml #表示跳过标签前的步骤,直接从标签位置开始。-t选项执行指定的tag标签任务
5、ansible-playbook playbook.yaml #运行
1.5playbook操作 1.5.1yum安装LNMP 环境首先,我们可以在ansible服务器上安装LNMP环境,然后,再将配置文件通过ansible拷贝到远程主机
1.5.2安装nginx软件[root@cong11 ~]# yum -y install nginx #通过aliyun和epel源
[root@cong11 ~]# systemctl start nginx
测试访问nginx的默认测试页:http://192.168.1.11
1.5.3安装MySQL[root@cong11 ~]# yum install -y mariadb-server mariadb
[root@cong11 ~]# mkdir -p /data/mysql/data #创建数据库保存目录
[root@cong11 ~]# chown -R mysql:mysql /data/mysql/ #修改权限
[root@cong11 ~]# vim /etc/my.cnf #修改数据保存目录
[mysqld]
datadir=/data/mysql/data #修改此行,其他参数保持默认即可
[root@cong11 ~]# systemctl start mariadb
1.5.3安装PHP和php-mysql模块和php-fpm模块
[root@cong11 ~]# yum install -y php php-mysql php-fpm
[root@cong11 ~]# systemctl start php-fpm
1.5.4提供php的测试页[root@cong11 ~]# vim /usr/share/nginx/html/index.php
phpinfo();
?>
[root@cong11 ~]# vim /etc/nginx/nginx.conf #在server{}中添加标红部分的内容
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
index index.php index.html;
include /etc/nginx/default.d/*.conf;
location / {
}
location ~ .*.(php|php5)?$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
重新启动nginx服务
[root@cong11 ~]# systemctl restart ngin
测试LNMP
http://192.168.1.11/
确保已经出现上面的测试页,而且,要看到MySQL已经被整合进来了,才能进行下一步操作
1.5.4 roles角色Roles 角色:以特定的层级目录结构进行组织的tasks、variables、handlers、templates、files等;相当于函数的调用把各个事件切割成片段来执行
1.6基于角色的方式部署LNMP 1.6.1配置playbook创建LNMP构建的任务[root@cong11 ~]# mkdir -p /ansible/lnmp/roles/{prepare,nginx,mysql,php}/{tasks,files,templates,vars,meta,handlers}
[root@cong11 ~]# touch /ansible/lnmp/ansible.cfg
[root@cong11 ~]# touch /ansible/lnmp/hosts
[root@cong11 ~]# touch /ansible/lnmp/site.yml
[root@cong11 ~]# touch /ansible/lnmp/webserver.yml
1.6.2配置被管理主机
开始编辑各自的文件,首先是hosts文件
1.6.3设置ssh免密连接
注:设置过请跳过
[root@cong11 ~]# ssh-keygen
[root@cong11 ~]# ssh-copy-id root@192.168.1.12
[root@cong11 ~]# ssh-copy-id root@192.168.1.13
1.6.4定义hosts文件
[root@cong11 ~]# vim /ansible/lnmp/hosts
[nginx]
nginx01 ansible_ssh_host=192.168.1.12 ansible_ssh_port=22 ansible_ssh_user=root
nginx02 ansible_ssh_host=192.168.1.13 ansible_ssh_port=22 ansible_ssh_user=root[mysql]
mysql01 ansible_ssh_host=192.168.1.12 ansible_ssh_port=22 ansible_ssh_user=root[php]
php01 ansible_ssh_host=192.168.1.12 ansible_ssh_port=22 ansible_ssh_user=root
php02 ansible_ssh_host=192.168.1.13 ansible_ssh_port=22 ansible_ssh_user=root[lnmp:children]
nginx
mysql
php
如果想使用/ansible/lnmp/路径下的hosts文件,需要修改ansible.cfg配置文件,修改成这样:
[root@cong11 ~]# cat /ansible/lnmp/ansible.cfg
[defaults]
host_key_checking = True
inventory = ./hosts
1.6.4 配置site.yml
[root@cong11 lnmp]# cat site.yml
1.6.5配置webserver.yml,构建prepare角色---
- import_playbook: webserver.yml
我们要完成lnmp项目的第一个role,也就是prepare角色(prepare角色主要任务是:远程主机配置yum源,关闭防火墙,关闭selinux),webserver.yml文件内容如下
[root@cong11 lnmp]# vim webserver.yml
tasks目录当中文件说明,main.yml,任务的入口文件,执行任务时从此文件开始执行,yum.yml、firewalld.yml、selinux.yml完成对应功能的目录
[root@cong11 tasks]# vim main.yml
[root@cong11 tasks]# vim yum.yml
[root@cong11 lnmp]# vim roles/prepare/tasks/firewalld.yml
[root@cong11 lnmp]# vim roles/prepare/tasks/selinux.yml
生成selinux配置文件的模板,并修改模板文件,永久禁用selinux
[root@cong11 lnmp]# cp /etc/selinux/config /ansible/lnmp/roles/prepare/templates/config.j2 /
[root@cong11 lnmp]# vim /ansible/lnmp/roles/prepare/templates/config.j2
SELINUX=disabled #将enforcing改为disabled
测试结果,需要再次注意,执行ansible-playbook时,需要到ansible项目的根目录下执行
[root@cong11 ~]# cd /ansible/lnmp/
[root@cong11 lnmp]# ansible-playbook site.yml
[root@cong11 lnmp]# ansible-playbook site.yml
1.6.6构建nginx角色PLAY [prepare system] ***********************************************************************
TASK [Gathering Facts] **********************************************************************
ok: [nginx02]
ok: [php02]
ok: [php01]
ok: [mysql01]
ok: [nginx01]TASK [prepare : delete repo for system] *****************************************************
[WARNING]: Consider using the file module with state=absent rather than running 'rm'. If
you need to use command because file is insufficient you can add 'warn: false' to this
command task or set 'command_warnings=False' in ansible.cfg to get rid of this message.
changed: [php02]
changed: [nginx01]
changed: [nginx02]
changed: [php01]
changed: [mysql01]TASK [prepare : get repo centos6 for aliyun] ************************************************
skipping: [nginx01]
skipping: [nginx02]
skipping: [mysql01]
skipping: [php01]
skipping: [php02]TASK [prepare : get repo centos7 for aliyun] ************************************************
ok: [mysql01]
ok: [nginx01]
changed: [php01]
changed: [php02]
ok: [nginx02]TASK [prepare : get elep repo centos6 for aliyun] *******************************************
skipping: [nginx01]
skipping: [nginx02]
skipping: [mysql01]
skipping: [php01]
skipping: [php02]TASK [prepare : get elep repo centos7 aliyun] **********************************************
changed: [nginx01]
ok: [php01]
ok: [mysql01]
changed: [php02]
ok: [nginx02]TASK [prepare : close firewalld] ************************************************************
ok: [nginx01]
ok: [php01]
ok: [mysql01]
ok: [php02]
ok: [nginx02]TASK [prepare : forever close selinux] ******************************************************
ok: [nginx01]
ok: [nginx02]
ok: [php01]
ok: [mysql01]
ok: [php02]TASK [prepare : current close selinux] ******************************************************
changed: [nginx01]
changed: [nginx02]
changed: [mysql01]
changed: [php01]
changed: [php02]PLAY RECAP **********************************************************************************
mysql01 : ok=7 changed=2 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
nginx01 : ok=7 changed=3 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
nginx02 : ok=7 changed=2 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
php01 : ok=7 changed=3 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
php02 : ok=7 changed=4 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
Nginx角色说明,在nginx目录中除了和prepare目录中一样,具备的tasks和templates以外,还多一个目录叫做handlers,该目录使用来执行notify,handler功能的,后续说明该功能。另外还会用到files和vars目录。
1.6.7配置nginx的tasks
main.yml文件内容如下:
install.yml文件内容如下
config.yml文件内容如下
webpage.yml文件内容如下
1.6.8复制相应的文件和模块到对应目录下[root@cong11 ~]# vim /ansible/lnmp/roles/nginx/files/testdb.php
$link=mysql_connect('192.168.1.12','zhangsan','123456');
if ($link)echo "connection success......";
mysql_close();
?>
[root@cong11 ~]# cp /usr/share/nginx/html/index.php /ansible/lnmp/roles/nginx/files/
[root@cong11 ~]# cp /etc/nginx/nginx.conf /ansible/lnmp/roles/nginx/templates/nginx.conf.j2
[root@cong11 ~]# vim /ansible/lnmp/roles/nginx/templates/nginx.conf.j2
1.6.10 构建nginx的handlers目录和vars下的main.yml文件
[root@cong11 ~]# vim /ansible/lnmp/roles/nginx/handlers/main.yml
[root@cong11 ~]# vim /ansible/lnmp/webserver.yml
然后测试
[root@cong11 lnmp]# cd /ansible/lnmp/
[root@cong11 lnmp]# ansible-playbook site.yml -t nginx
PLAY [prepare system] ***********************************************************************
PLAY [Install and config nginx] *************************************************************
TASK [Gathering Facts] **********************************************************************
ok: [nginx02]
ok: [nginx01]TASK [install nginx] ************************************************************************
changed: [nginx02]
changed: [nginx01]TASK [config nginx] *************************************************************************
changed: [nginx01]
changed: [nginx02]TASK [start nginx] **************************************************************************
changed: [nginx02]
changed: [nginx01]TASK [nginx : provide web page] *************************************************************
changed: [nginx01]
changed: [nginx02]RUNNING HANDLER [restart nginx] *************************************************************
changed: [nginx01]
changed: [nginx02]PLAY RECAP **********************************************************************************
nginx01 : ok=6 changed=5 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
nginx02 : ok=6 changed=5 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
测试访问192.168.1.12和192.168.1.13的测试页
1.7 构建PHP角色构建php任务,这里我们只用到了tasks,templates和handlers目录,tasks当中的内容查看。
1.7.1配置php的sasks
main.yml文件内容
install.yml文件内容:
config.yml文件内容:
1.7.1 复制相应的文件和模板到对应目录 [root@cong11 tasks]# cp /etc/php.ini /ansible/lnmp/roles/php/templates/php.ini.j2
[root@cong11 tasks]# cp /etc/php-fpm.conf /ansible/lnmp/roles/php/templates/php-fpm.conf.j2
[root@cong11 tasks]# cp /etc/php-fpm.d/www.conf /ansible/lnmp/roles/php/templates/www.conf.j2
[root@cong11 tasks]# vim /ansible/lnmp/webserver.yml
然后执行测试
[root@cong11 ~]# cd /ansible/lnmp/
[root@cong11 lnmp]# ansible-playbook site.yml -t php
PLAY [prepare system] ***********************************************************************
PLAY [Install and config nginx] *************************************************************
PLAY [Install and config php] ***************************************************************
TASK [Gathering Facts] **********************************************************************
ok: [php02]
ok: [php01]TASK [install php php-mysql php-fpm] ********************************************************
[DEPRECATION WARNING]: Invoking "yum" only once while using a loop via squash_actions is
deprecated. Instead of using a loop to supply multiple items and specifying `name: "{{ item
}}"`, please use `name: ['php', 'php-mysql', 'php-fpm']` and remove the loop. This feature
will be removed in version 2.11. Deprecation warnings can be disabled by setting
deprecation_warnings=False in ansible.cfg.
[DEPRECATION WARNING]: Invoking "yum" only once while using a loop via squash_actions is
deprecated. Instead of using a loop to supply multiple items and specifying `name: "{{ item
}}"`, please use `name: ['php', 'php-mysql', 'php-fpm']` and remove the loop. This feature
will be removed in version 2.11. Deprecation warnings can be disabled by setting
deprecation_warnings=False in ansible.cfg.
ok: [php01] => (item=[u'php', u'php-mysql', u'php-fpm'])
ok: [php02] => (item=[u'php', u'php-mysql', u'php-fpm'])TASK [config php] ***************************************************************************
ok: [php02]
ok: [php01]TASK [config php-fpm] ***********************************************************************
ok: [php01] => (item={u'dest': u'/etc/php-fpm.conf', u'src': u'php-fpm.conf.j2', u'mode': u'0644'})
ok: [php02] => (item={u'dest': u'/etc/php-fpm.conf', u'src': u'php-fpm.conf.j2', u'mode': u'0644'})
ok: [php01] => (item={u'dest': u'/etc/php-fpm.d/www.conf', u'src': u'www.conf.j2', u'mode': u'0644'})
ok: [php02] => (item={u'dest': u'/etc/php-fpm.d/www.conf', u'src': u'www.conf.j2', u'mode': u'0644'})TASK [start php-fpm] ************************************************************************
changed: [php01]
changed: [php02]PLAY RECAP **********************************************************************************
php01 : ok=5 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
php02 : ok=5 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
针对上面警告的解决方法
测试访问192.168.1.12和192.168.1.13的测试页
1.8 构建mysql角色构建mysql任务,这里我们只用到了tasks,templates和handlers目录,tasks当中的内容查看
1.8.1配置mysql的tasks
main.yml文件内容
install.yml文件内容
config.yml文件内容
1.8.1复制相应的文件和模板到对应目录下
[root@cong11 ~]# cp /etc/my.cnf /ansible/lnmp/roles/mysql/templates/my.cnf.j2
[root@cong11 ~]# vim /ansible/lnmp/roles/mysql/templates/my.cnf.j2
[root@cong11 ~]# vim /ansible/lnmp/webserver.yml
接下来测试
[root@cong11 lnmp]# cd /ansible/lnmp/
[root@cong11 lnmp]# ansible-playbook site.yml -t mysql
PLAY [prepare system] **********************************************************
PLAY [Install and config nginx] ************************************************
PLAY [Install and config php] **************************************************
PLAY [Install and config mysql] ************************************************
TASK [Gathering Facts] *********************************************************
ok: [mysql01]TASK [mysql : install mariadb] *************************************************
ok: [mysql01]TASK [mysql : create data directory] *******************************************
ok: [mysql01]TASK [copy mysql config] *******************************************************
ok: [mysql01]TASK [start mysql] *************************************************************
ok: [mysql01]TASK [mysql : create a database] ***********************************************
ok: [mysql01]TASK [mysql : create a user] ***************************************************
[WARNING]: Module did not set no_log for update_password
ok: [mysql01]TASK [mysql : create ai user] **************************************************
ok: [mysql01]PLAY RECAP *********************************************************************
mysql01 : ok=8 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
到192.168.1.12(数据库主机)上查看执行结果
访问之前复制到远程主机的testdb.php测试页
至此通过ansible playbook部署lnmp就完成了.



