文章目录
playbook
playbook是什么
- playbook是ansible用于配置,部署和管理托管主机剧本,通过playbook的详细描述,执行其中一系列tasks,可以让远程主机达到预期状态
- 也可以说,playbook字面意思及剧本,现实中由演员按剧本表演,在ansible中由计算机进行安装,部署应用,提供对外服务,以及组织计算机处理各种各样的事情
playbook语法格式
- playbook由YAML语言编写,遵循YAML标准
- 在同一行中,#之后的内容表示注释
- 同一个列表中的元素应该保持相同的缩进
- playbook由一个或多个play组成
- play中hosts,variables,roles,tasks等对象的表示方法都是键值中间以” : “分隔表示
- YAML还有一个小的怪癖,他的文件开始行都应该是 —,这是YAML格式的一部分,表明一个文件的开始
playbook构成
- hosts:定义将要执行playbook的远程主机组
- vars; 定义playbook运行时需要使用的变量
- tasks: 定义将要在远程主机上执行的任务列表
- handlers:定义task执行完成一会需要调用的任务(执行触发性任务)
playbook执行结果
-
使用ansible-playbook运行playbook文件,输出内容为JSON格式,由不同颜色组成便于识别
——绿色代表执行成功
——黄色代表系统状态发生改变
——红色代表执行失败
playbook的编写
示例
--- #第一行,表示开始
- host: all #执行主机的集合,以逗号作为分隔符
remote_user: root #执行的账户名
tasks:
# - cmd1 #第一个命令
# - cmd2 #第二个命令
# - cmd3 #第三个集合
模块: 模块参数
例: - ping:
ansible-playbook myping.yml -f 5
#-f 并发进程数量,默认是5 ,线程一般不超过cpu的八倍数量,默认是5
-
tasks
命令的集合
每一个play包含一个task列表(任务列表)
一个task在其所对应的所有主机上执行完毕之后,下一个task才会执行
-
hosts
主机的集合
定义要执行任务的主机
实例:
给主机添加用户bai,设置默认密码123,并把bai用户添加到users组
---
- hosts: A
remote_user: root
tasks:
- name: create user bai #一级name,注释说明
user:
name: bai #模块name,看其模块的作用
group: users
- name: set passwd
shell:
echo 123 | passwd --stdin bai
练习:
1.所有主机安装Apache
2.修改配置文件的监听端口为8080
3.设置默认主页:hello world
4.启动服务
5.设置开机自启
vim http.yml
---
- name: enable server
hosts: A
become: yes
tasks:
- name: latest httpd and firewalld #安装APache和防火墙
yum:
name:
- httpd
- firewalld
state: latest #状态最新
- name: http.conf
lineinfile:
path: /etc/httpd/conf/httpd.conf
regexp: '^Listen '
insertafter: '^#Listen '
line: 'Listen 8080'
- name: index.html
copy:
src: index.html
dest: /var/www/html/index.html
owner: apache
group: apache
mode: 0644
#在当前目录下创建 index.html
#vim index.html
#hello world
#书写网页内容第二种写法
#- name: test html page is install
# copy:
#把内容写入目标文件
#content: "Welcome to the example.com ! \n"
#dest: /var/www/html/index.html
#owner: apache
#group: apache
#mode: 0644
- name: httpd enable and running #开机自启
service:
name: httpd
enabled: true
state: started
测试:
ansible-playbook http.yml
进阶版:在原来的基础上添加 防火墙允许通过HTTP服务,在使用uri模块测试
vim http.yml #.yml=.yaml
---
- name: enable server
hosts: A
become: yes
tasks:
- name: latest httpd and firewalld
yum:
name:
- httpd
- firewalld
state: latest
- name: test html page is install
copy:
#把内容写入目标文件
content: "Welcome to the example.com ! \n"
dest: /var/www/html/index.html
- name: start firewalld
service:
name: firewalld
enable: true
state: started
- name: firewalld pass httpd
firewalld:
service: http
#永久设置
permanent: true
state: enable
#临时设置允许
immediate: yes
- name: httpd enable and running
service:
name: httpd
enabled: true
state: started
- name: test install web server
hosts: localhost
become: no
tasks:
- name: connect to install web
uri:
url: A
#允许返回内容
return_content: yes
status_code: 200
#状态对比,200正常状态
高级使用
引用变量
设密码
-
解决密码明文问题
user模块的password不能直接设置密码
password是把字符串直接写入shadow,并没有改变,而Linux的shadow密码是经过加密的,所以不能直接使用
-
解决方案
变量过滤器password_hash
例:添加用户,使用user模块中password参数进行设置密码
---
- name: add user "{{ username }}"
remote_user: root
hosts: A
vars: #变量
username: zhangsan
tasks:
- name: add user "{{ username }}"
user:
name: "{{ username }}"
group: users
password: "{{'123' | password_hash('sha512')}}"
#使用jinja2过滤器设置密码
#password参数设置密码,需要自己去加密密码,明文无法登录,用户相关得基本默认设置在/etc/login.defs
#Linux得默认加密方式 sha512
测试
变量参数
- 传递参数
- -e 参数
- 参数格式必须为 JSON或者YAML
- yaml格式可以使用参数文件
- 调用 -e @args.yaml
例,添加用户lisi,设置默认密码123asd
---
- name: add user "{{ username }}"
remote_user: root
hosts: A
tasks:
- name: add user "{{ username }}"
user:
name: "{{ username }}"
我们在playbook中删除变量的定义,去执行,会出现找不到变量错误
但是我们可以定义外部变量
有两种方式
JSON:不管参数多长,我们可以写到一行中,相当于我们定义了username的变量
ansible-playbook user.yml -e '{"username": "lisi"}'
测试
YML格式
先书写一个关于变量的yml文件
vim args.yaml
---
nameuser:
wangwu
ansible-playbook user.yml -e @args.yaml
测试
错误处理:error
-
ansible-playbook对错误的处理
–默认情况判断$?,如果值不为0就停止执行
–单某些情况我们需要忽略错误继续执行
-
错误处理方法
–ignore_errors: 对错误的处理方式
–True :表示忽略错误继续执行
–false:表示遇到错误就停止执行
–默认False
–处理方式:在需要的地方下一行加入
ignore_errors: True
#第一次创建没有问题,再次执行$?为非零,playbook中止
解决方案
...
name: test
shell:
mkdir /www
ignore_errors: True
...
tags标记
-
tags:给使用的任务定义一个调用标识
-
使用格式:
–name: NAME
–module: ARGUMENTS
–tags: TAG_ID
-
playbook调用方式
-t TAGS,–tags=TAGS
-
设置tags标记
例:如果只执行某个playbook的某一段,可以使用tags打上标签(只执行标签,其他不执行)
...
- name: httpd enable and running
service:
name: httpd
enabled: true
state: started
tags: sys
...
调用这个标签
ansible-playbook conf.yml -t sys
触发器handlers
-
当关注的资源发生变化时采取的操作
-
notify这个action可用于在每个play的最后被触发,这样可以避免有多次改变发生时,每次都执行指定的操作,取而代之仅在所有的变化发生完成后一次性的执行指定操作
-
在notify中列处的操作称为handler,即notify调用handler中定义的操作
-
notify调用的是handler段的name定义的串,必须一致,否则达不到触发的效果
-
多个task触发同一个notify的时候,同一个服务只会触发一次
-
notify可以触发多个条件,在生产环境中往往涉及到某一个配置文件的改变要重启若干服务的场景,handler用在这个非常合适
-
结合vars可以写出非常普适的服务器管理脚本
...
- name: httpd enable and running
service:
name: httpd
enabled: true
state: started
notify:
- restart httpd #定义触发器的名字
handlers: #与tasks对齐
- name: restart httpd #书写触发器的内容,handlers一般在playbook末尾,只执行一次
service:
name: httpd
state: restarted
...
也可以与标签连用,在标签下书写触发器,调用标签的时候,触发触发器,比如可以在修改配置文件的下面加上重启服务的handlers
...
- name: httpd enable and running
service:
name: httpd
enabled: true
state: started
tags: sys
notify:
- restart httpd #定义触发器的名字
handlers: #与tasks对齐
- name: restart httpd #书写触发器的内容,handlers一般在playbook末尾,只执行一次
service:
name: httpd
state: restarted
...
调用这个标签
ansible-playbook conf.yml -t sys
条件判断when
有些时候需要在满足特定的条件后再触发某一项操作,或在特定的条件下终止某个行为,这个时候需要进行条件判断,when正是解决这个问题的最佳选项,远程中的系统变量facts作为when的条件,可以通过setup模块查看
when的样例:
tasks:
- name: somecommand
command: somecommand
when: expr
案例:因为各个系统安装软件的命令不一致,所以根据系统的不同选择不同的安装命令
---
- name: install vim
hosts: A
tasks:
- name: install vim in yum #如果是Redhat就使用yum安装
yum:
name: vim
state: installed
when: ansible_os_family == 'RedHat'
- name: install vim in apt #如果是Debian使用apt安装
apt:
name: vim
state: installed
when: ansible_os_family == 'Debian'
register(注册变量)
有时候我们还需要更复杂的例子,如判断前一个命令的执行结果去处理后面的操作,这时候就需要register模块来保存前一个命令的返回状态,在后面进行调用
保存上一条命令的输出对象
register样例:
- command: test command
register: result
- command: run command
when: resilt
案例:
针对运行命令结果的返回值做判定,当系统负载超过一定值的时候做特殊处理
例:当系统负载超过0.7,关闭httpd服务
---
- name: fuzai
hosts: A
remote_user: root
tasks:
- shell: uptime | awk '{printf("%.2f\n",$(NF-2))}'
register: result
- service:
name: httpd
state: stopped
when: result.stdout|float > 0.7
with_items循环(loop循环)
with_items是playbook的标准循环,可以用于迭代一个列表或者字典,通过{{ item }}获取每次迭代的值
例:创建多个用户
---
- name: useradd
hosts: A
remote_user: root
tasks:
- name: add "{{ item }}"
user:
name: "{{ item }}"
group: users
with_items: #循环的值
- aa
- bb
- cc
用loop来写
---
- name: useradd
hosts: A
remote_user: root
vars:
userss:
- aa
- bb
tasks:
- name: add "{{ item }}"
user:
name: "{{ item }}"
group: users
loop: "{{ userss }}" #循环的值,可以写入变量,在调用
循环精细化,为不同的用户设置不同的组,设置不同的密码
---
- name: useradd
hosts: A
remote_user: root
tasks:
- name: add "{{ item }}"
user:
name: "{{ item.username }}"
group: "{{ item.group }}"
password: "{{ item.password|password_hash('sha512')}}"
with_items: #循环的值
-
username: aa
group: users
password: '123456'
-
username: bb
group: bin
password: '123'
-
username: cc
group: root
password: '1'
测试:
include and roles
- include 引入一个文件
- 在编写playbook的时候随着项目越来越大,playbook越来越复杂,修改也很麻烦,这是可以把一些play、task或者handler放到其他文件中,通过include指令包含进来是一个不错的选择
roles
-
roles引入一个目录
-
roles像是加强版的include,它可以引入一个项目的文件和目录
-
一般所需的目录层级有
–vars: 变量层
–tasks:任务层
–handlers:触发条件
–files: 文件
–template: 模板
–default: 默认,优先级最低
-
加入有一个play包含一个叫“x“的role,则
--- - hosts: host_gruop #组变量 roles: - x
– x/tasks/main.yml
– x/vars/main.yml
– x/handler/main.yml
– x/… …/main.yml
– 都会自动添加进这个play
调试:debug模块
对于语法不熟悉的,playbook书写容易出错,且排错困难,下面介绍几种简单的排错调试方法
-
检测语法
ansible-playbook --syntax-check playbook.yml
-
测试运行(空运行,并不会对目标主机进行真实改动,对于一些服务,如:开启服务,在测试模式下,会出错,会检测目标主机并没有安装服务,哪怕是之前的playbook中有安装服务)
ansible-playbook -C playbook
-
显示收到影响的主机 --list-hosts
-
显示工作的task --list-tasks
-
显示将要运行的tag --list-tags
-
debug模块可以在运行是输出更为详细的信息,帮助我们排错
--- - name: fuzai hosts: A remote_user: root tasks: - shell: uptime | awk '{printf("%.2f\n",$(NF-2))}' register: result - service: name: httpd state: stopped when: result.stdout|float > 0.7 - name: show debug info debug: var=result