文章目录
一、playbook介绍
playbook是ansible的配置、部署、编排语言。他们可以被描述为一个需要希望远程主机执行命令的方案,或者一组ansible模块程序运行的命令集合
二、YAML语法详解
YAML(Yet Another Markup Language)语言是一种用来表达数据序列的编程语言,他的主要特点包括:可读性强,语法简单明了,支持丰富的语言解析库,通用性强。
ansible中的配置文件都以YAML格式存在,所以必须要熟悉YAML格式来配置管理ansible。
yaml与json的转化
列表
使用"- "(减号加一个或多个空格)作为列表项,也就是json中的数组。yaml的列表在playbook中极重要,必须得搞清楚它的写法。
例如:
- zhangsan
- lisi
- wangwu
它们等价于json格式的:
[
"zhangsan",
"lisi",
"wangwu"
]
字典
使用"冒号+空格"分隔,即key: value
,作为字典的形式。它一般当作列表项的属性。
例如
alice:
hp: 34
sp: 8
level: 4
它们等价于json格式的:
{
'alice':
{
'hp':34,
'sp':8,
'level':4
}
}
列表和字典两种混合
例如
bob:
hp:
- 12
- 30
sp:
- 10
- 20
level: 4
它们等价于json格式的:
{
'bob':
{
'hp':[12,30],
'sp':[10,20],
'level':4
}
}
三、playbook的YMAL格式
---
- hosts: test
remote_user: root
tasks:
- name: install nginx
yum: name=nginx state=present
tags: install
- name: start nginx service
service: name=nginx state=start
格式:
- 文件的第一行应该以 “—” (三个连字符)开始,表明YMAL文件的开始。
- 在同一行中,#之后的内容表示注释,类似于shell,python和ruby。
- YMAL中的列表元素以”-”开头然后紧跟着一个空格,后面为元素内容。
- 同一个列表中的元素应该保持相同的缩进。否则会被当做错误处理。
- play中hosts,variables,roles,tasks等对象的表示方法都是键值中间以":“分隔表示,”:"后面还要增加一个空格。
基础组成
hosts
:运行指定任务的目标主机
remote_user
:在远程主机以哪个用户执行
tasks
:指定远端主机将要执行的一系列动作。tasks 的核心为 ansible 的模块,前面已经提到模块的用法。tasks 包含name
和要执行的模块
,name 是可选的,只是为了便于用户阅读,不过还是建议加上去,模块是必须的,同时也要给予模块相应的参数。
四、playbook核心组件
1、Tasks
Play的主体是任务列表。任务列表中的任务按照次序逐个在hosts中指定的所有主机上执行
示例
- hosts: abc
remote_user: root
tasks:
- name: disable selinux
command: '/sbin/setenforce 0' ##关闭selinux
- name: make sure apache is running
service: name=httpd state=started ##开启httpd服务
##play中只要执行命令的返回值不为0,就会报错,tasks停止
加上下面这句话 可以强制执行
ignore_errors: True ##忽略错误,强制返回成功
2、Variables
当我们需要定制一些模板时,我们需要从外部传入变量来配置playbook
示例
方法1(命令行传入参数)
[root@ansible_center tmp]# cat ~/install_nginx.yaml
- hosts: webservers
remote_user: root
tasks:
- name: install {{ pkgname }}
yum: name={{ pkgname }} state=present
tags: install
- name: start {{ pkgname }} service
service: name={{ pkgname }} state=start
#命令行传入参数
[root@ansible_center tmp]# ansible-playbook -e pkgame=nginx ~/install_nginx.yaml
方法2(playbook内部定义)
[root@ansible_center tmp]# cat ~/install_nginx.yaml
- hosts: webservers
remote_user: root
vars:
- pkgname: nginx
tasks:
- name: install {{ pkgname }}
yum: name={{ pkgname }} state=present
tags: install
- name: start {{ pkgname }} service
service: name={{ pkgname }} state=start
3、Templates
Jinja2是基于 Python的模板引擎。 Templates使用Jinjia2格式作为文件模版,进行文档内变量的替换,可以看作是一个编译过的模板文件,用来产生目标文本,传递 Python的变量给模板去替换模板中的标记。
示例
从被管理端复制一份httpd.conf到管理端
并做如下修改
vim templates/httpd.conf
Listen {{ http_port }}
ServerName {{ server_name }}
MaxClients {{ access_num }}
vi /etc/ansible/hosts
[aaa]
192.168.x.x http_port=192.168.x.x:80 access_num=100 server_name="www.aaa.com:80"
## 在hosts文件为主机配置变量
vi httpd.yml
- hosts: aaa
remote_user: root
vars:
- package: httpd
- service: httpd
tasks:
- name: install httpd package
yum: name={{ package }} state=latest ##安装最新版本的httpd
- name: install configure file
template: src=/opt/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf ##使用模板并根据变量进行配置
notify:
- restart httpd ##调用handler
- name: start httpd server
service: name={{ service }} enabled=true state=started ##开启服务
handlers:
- name: restart httpd
service: name={{ service }} state=restarted
4、Handlers
Handlers用于当关注的资源发生变化时所采取的操作。在 notify中列出的操作便称为 handler,也就是在notify中需要调用 handler中定义的操作。而 notify这个动作在每个play的最后被触发,仅在所有的变化发生完成后一次性地执行指定操作。
示例
- hosts: abc
remote_user: root
tasks:
- name: install httpd package
yum: name=httpd state=latest ##按照最新版本的httpd服务
- name: install configuration file for httpd
copy: src=/opt/httpd.conf dest=/etc/httpd/conf/httpd.conf ##配置文件
notify:
-restart httpd ##调用名字为 restart httpd 的handler
- name: start httpd service
service: enabled=true name=httpd state=started ## 开启httpd服务
handlers:
- name: restart httpd
service: name=httpd state=restarted
5、Tags
如果多次执行修改 Playbook 会涉及到一些没有变化的代码,可以使用tags让 用户选择跳过没有变化的代码。只运行Playbook中发生变化的部分代码。可以在Playbook中为某个或某些任务定义“标签”,在执行此Playbook时通过 ansible-playbook命令 使用 --tags 选项能实现仅运行指定的tasks。
示例
vi hosts.yml
- hosts: aaa
remote_user: root
tasks:
- name: Copy hosts file
copy: src=/etc/hosts dest=/etc/hosts
tags:
- only
- name: touch file
file: path=/opt/hosts state=touch
执行命令:ansible-playbook hosts.yml -t only
会只执行标签为 only的任务
事实上,不光可以为单个或多个task指定同一个tags。playbook还提供了一个特殊的tags为always。作用就是当使用always当tags的task时,无论执行哪一个tags时,定义有always的tags都会执行。
如果在上面的yaml文件中添加
- name: touch file
file: path=/opt/hosts state=touch
tags:
- always
执行命令:ansible-playbook hosts.yml -tags only
会将两个task都执行
6、Roles
Ansible为了层次化、结构化地组织 Playbook,使用了角色( roles),可以根据层次结构自动装载变量文件、 tasks以及 handlers等。只需要在 Playbook中使用 include指令即可使用 roles。简单来讲, roles就是通过分别将变量、文件、任务、模块及处理器设置于单独的目录中,便捷地使用他们。
roles内各目录含义解释
rolename/: 角色名命名的目录
—files/:用来存放由copy模块或script模块调用的文件。
—templates/:用来存放jinjia2模板,template模块会自动在此目录中寻找jinjia2模板文件。
—tasks/:此目录应当包含一个main.yml文件,用于定义此角色的任务列表。
—handlers:此目录应当包含一个main.yml文件,用于定义此角色中触发条件时执行的动作。
—vars:此目录应当包含一个main.yml文件,用于定义此角色用到的变量。
—defaults:此目录应当包含一个main.yml文件,用于为当前角色设定默认变量。
—meta:此目录应当包含一个main.yml文件,用于定义此角色的特殊设定及其依赖关系。
在每个角色命令的目录中分别创建files、handlers、tasks、templates、meta、defaults和vars目录,用不到的目录可以创建为空目录,但不可以不创建。
五、roles实战部署nginx
1、创建角色目录及相关子目录
[root@ansible_center roles]# cd /etc/ansible/roles/
[root@ansible_center roles]# mkdir -pv nginx/{files,templates,vars,handlers,meta,default,tasks}
mkdir: created directory ‘nginx’
mkdir: created directory ‘nginx/files’
mkdir: created directory ‘nginx/templates’
mkdir: created directory ‘nginx/vars’
mkdir: created directory ‘nginx/handlers’
mkdir: created directory ‘nginx/meta’
mkdir: created directory ‘nginx/default’
mkdir: created directory ‘nginx/tasks’
2、在task定义任务
[root@ansible_center roles]# cat nginx/tasks/main.yaml
- name: mkdir /data/www
file: path=/data/www state=directory
- name: create user nginx
user: name=nginx
- name: copy nginx html to remote host
copy: src=index.html dest=usr/local/nginx/html/
- name: copy nginx package to remote host
copy: src=nginx-1.12.2.tar.gz dest=/opt/nginx-1.12.2.tar.gz
tags: cppkg
- name: tar nginx
shell: cd /opt; tar -xf nginx-1.12.2.tar.gz
- name: install pkg
yum: name={{ item }} state=latest
with_items:
- openssl-devel
- pcre-devel
- gcc
- name: install nginx
shell: cd /opt/nginx-1.12.2;./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module --with-http_ssl_module --with-pcre;make&&make install
- name: copy conf file nginx.conf
template: src=nginx.conf dest=/usr/local/nginx/nginx.conf
tags: naxconf
notify: reload nginx service
3、相关文件准备
#nginx源码安装文件
[root@ansible_center roles]# cd nginx/files/
[root@ansible_center files]# wget http://nginx.org/download/nginx-1.12.2.tar.gz
#nginx首页html文件
[root@ansible_center files]# cat index.html
<h1>test page</h1>
#nginx配置模板文件
[root@ansible_center files]# cd ../templates/
[root@ansible_center templates]# cat nginx.conf
#user nobody;
worker_processes 1;
events {
worker_connections {{ con_counts }};
}
http {
include mime.types;
default_type application/octet-stream;
#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 logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name localhost;
location / {
root {{ html_dir }};
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
4、在vars中定义变量
[root@ansible_center templates]# cd /etc/ansible/roles/nginx/vars/
[root@ansible_center vars]# vim main.yaml
[root@ansible_center vars]# cat main.yaml
con_counts: "65535"
html_dir: "/data/www"
5、在handlers中定义触发器
[root@ansible_center vars]# cd /etc/ansible/roles/nginx/handlers/
[root@ansible_center handlers]# vim main.yaml
[root@ansible_center handlers]# cat main.yaml
name: reload nginx service
shell: /usr/local/nginx/sbin/nginx
6、创建nginx.yaml引导文件
[root@ansible_center handlers]# cd /etc/ansible/roles/
[root@ansible_center roles]# vim nginx.yaml
[root@ansible_center roles]# cat nginx.yaml
- host: 192.168.189.134
remote_user: root
roles:
- nginx
运行结果
ansible-playbook /etc/ansible/roles/nginx.yaml