一、playbook基础
1.1 ansible七种武器
1.1.1 ad-doc
– ansible 命令,用于执行临时性的工作.
1.1.2 ansible-doc
– ansible-doc 是 Ansible模块文档说明,针对每个模块
都有详细的用法说明及应用案例介绍,功能和Linux系
统man命令类似,必须掌握
1.1.3 ansible-console
– ansible-console 是 Ansible 为用户提供的一款交互
式工具,用户可以在 ansible-console 虚拟出来的终
端上像 Shell 一样使用 Ansible 内置的各种命令,
这为习惯于使用 Shell 交互方式的用户提供了良好的
使用体验。
1.1.4 ansible-galaxy
– ansible-galaxy 从 github 上下载管理 Roles 的一款
工具,与 python 的 pip 类似。
1.1.5 ansible-playbook
– ansible-playbook 是日常应用中使用频率最高的命令,
其工作机制是:通过读取预先编写好的 playbook 文
件实现批量管理。要实现的功能与命令 ansible 一样,
可以理解为按一定条件组成的 ansible 任务集。
1.1.6 ansible-vault
– ansible-vault 主要用于配置文件加密,如编写的
Playbook 配置文件中包含敏感信息,不希望其他人随
意查看, ansible-vault 可加密/解密这个配置文件
1.1.7 ansible-pull
– Ansible 有两种工作模式 pull/push ,默认使用 push
模式工作,pull 模式和通常使用的 push 模式工作机
理刚好相反
– 适用场景:有数量巨大的机器需要配置,即使使用高并发线程依旧要花费很多时间,
通常在配置大批量机器的场景下会使用
1.2 json简介
1.2.1 什么是 json
– json 是 JavaScript 对象表示法,它是一种基于文本,
独立于语言的轻量级数据交换格式。
– JSON中的分隔符限于单引号 ' 、小括号 ()、中括号
[ ]、大括号 { } 、冒号 : 和逗号 ,
1.2.2 json 特性
1. JSON 是纯文本
2.JSON 具有层级结构(值中存在值)
3.JSON 可通过 JavaScript 进行解析
1.2.3 json 语法规则
1.数据在名称/值对中
2.数据由逗号分隔
3.大括号保存对象
4.中括号保存数组
1.2.4 json的书写格式
1.JSON基本格式
– "键":"值"
“帅哥”:“李俊”
2. json 数组格式
{ "爱好":
["篮球", "台球", "旅游","撩妹"]
}
3.复合复杂类型
{ "dogs":
[ {"name":"laifu","color":"black"},
{"name":"ahuang","color":"yellow"},
{"name":"jiawang","color":"red"}
]
}
1.3 yaml简介
1.3.1 什么是yaml
yaml是一个可读性高,用来表达数据序列的格式
1.3.2 yaml 基础语法
– YAML的结构通过空格来展示
– 数组使用"- "来表示
– 键值对使用": "来表示
– YAML使用一个固定的缩进风格表示数据层级结构关系
– 一般每个缩进级别由两个以上空格组成
– # 表示注释
• 注意:
– 不要使用tab,缩进是容易出错的地方之一
– 同一层级缩进必须对齐
1.3.3 YAML的键值表示方法
1 采用冒号分隔
2 : 后面必须有一个空格
3. YAML键值对例子
“帅哥”: "李俊"
或
“帅哥”:
"李俊"
4.复杂YAML的键值对嵌套
“dogs”:
"name":"laifu"
或
“dogs”:
"name":
"laifu"
5.数组
["篮球", "台球", "旅游","撩妹"]
6.YAML 数组表示方法
– 使用一个短横杠加一个空格
– YAML 数组例子
- "篮球"
- "台球"
- "旅游"
- "撩妹"
7. 哈希数组复合表达式
"爱好":
- "篮球"
- "台球"
- "旅游"
- "撩妹"
1.4 jinja2模版简介
1.4.1 什么是jinja2
– Jinja2是基于python的模板引擎,包含 变量 和 表达
式两部分,这两者在模板求值的时候会被替换为值。
模板中还有标签,控制模板的逻辑。
– playbook 的模板使用 python 的 jinja2 模块来处理的
1.4.2 jinja2 模版基本语法
– 模板的表达式都是包含在分隔符 "{{ }}" 内的;
– 控制语句都是包含在分隔符 "{% %}" 内的;
– 另外,模板也支持注释,都是包含在分隔符 "{# #}"
内,支持块注释。
1.5 playbook
1.5.1 什么是playbook
– playbook 是 ansible 用于配置,部署,和管理托管主
机的剧本。通过 playbook 的详细描述,执行其中的一系
列 tasks,可以让远端主机达到预期的状态。
1.5.2 playbook语法
– playbook由 YAML 语言编写,遵循 YAML 标准
– 在同一行中,#之后的内容表示注释
– 同一个列表中的元素应该保持相同的缩进
– playbook 由一个或多个 play 组成
– play 中 hosts,variables,roles,tasks 等对象的表示
方法都是键值中间以 ": " 分隔表示
– 所有的 YAML 文件开始行都应该是 ---. 这是 YAML 格式的一部分,
表明一个文件的开始
1.5.3 playbook 构成
– Target: 定义将要执行 playbook 的远程主机组
– Variable: 定义 playbook 运行时需要使用的变量
– Tasks: 定义将要在远程主机上执行的任务列表
– Handler: 定义 task 执行完成以后需要调用的任务
1.5.4 Playbook执行结果
– 使用 ansible-playbook 运行playbook文件,得到输
出内容为 JSON 格式。并且由不同颜色组成,便于识
别。一般而言
– 绿色代表执行成功
– ***代表系统代表系统状态发生改变
– 红色代表执行失败
1.5.5 第一个playbook
1.ping所有主机的playbook
--- # 第一行,表示开始
- hosts: all
remote_user: root
tasks:
- ping:
~ ] #ansible-playbook myping.yml -f 5 # -f 并发进程数量,默认是 5
2.playbook参数说明:
2.1. hosts 行的内容是一个或多个组或主机的 patterns,以
逗号为分隔符
2.2 remote_user 就是账户名
2.3 tasks
– 每一个 play 包含了一个 task 列表(任务列表).
– 一个 task 在其所对应的所有主机上(通过 host
pattern 匹配的所有主机)执行完毕之后,下一个 task
才会执行.
1.5.6 编写playbook
• 编写 playbook 实现以下效果
– 安装 apache
– 修改 apache 监听的端口为 8080
– 为 apache 增加 ServerName 配置
– 设置默认主页 hello world
– 启动服务
– 设置开机自启动
注:要使用ansible-doc 模块名 查看帮助文档;
---
- hosts: web
remote_user: root
tasks:
- name: install the latest version of Apache
yum:
name: httpd
state: installed
- lineinfile:
path: /etc/httpd/conf/httpd.conf
regexp: '^Listen '
line: 'Listen 8080'
- lineinfile:
path: /etc/httpd/conf/httpd.conf
regexp: '^#ServerName'
line: 'ServerName localhost'
- copy:
src: /root/index.html
dest: /var/www/html/index.html
owner: apache
group: apache
mode: 0644
- service:
name: httpd
state: started
enabled: yes
二、playbook进阶
2.1 语法进阶
2.1.1 变量
– 给所有主机添加用户 xiaolv,设置默认密码 123456
– 要求第一次登录修改密码(使用变量)
---
- hosts: cache
remote_user: root
vars:
username: xiaolv
tasks:
- name: create user
shell: adduser {{username}}
- shell: echo 123456 |passwd --stdin {{username}}
- shell: chage -d 0 {{username}}
附:user 模块的 password 设置的密码无法登录系统
1.经过测试发现,password 是把字符串直接写入
shadow,并没有改变,而 Linux 的 shadow 密码是
经过加密的,所以不能使用
2.解决方案:
– 变量过滤器 password_hash
– {{ 'urpassword' | password_hash('sha512')}}
- name: name={{username}} password={{'123456' |password_hash('sha512')}}
2.1.2 error
1.ansible-playbook 对错误的处理
– 默认情况判断 $?,如果 值 不为 0 就停止执行
– 但某些情况我们需要忽略错误继续执行
需求:给所有web主机添加用户 xiaolv,如果存在就设置默认密码 123456
如果不存在就添加xiaolv用户并设置密码为123456
---
- hosts: web
remote_user: root
vars:
username: "zhang3"
tasks:
- shell: adduser "{{username}}"
ignore_errors: True #忽略错误
- shell: echo 123123 |passwd --stdin "{{username}}"
- shell: chage -d 0 "{{username}}"
2.1.3 handlers
1.多个 task 触发同一个 notify 的时候,同一个服务只会触发一次
等所有的task执行完成后,handlers才会被触发。
2.notify 可以触发多个条件,在生产环境中往往涉及到
某一个配置文件的改变要重启若干服务的场景,
handler 用到这里非常适合.
3. 结合 vars 可以写出非常普适的服务管理脚本
---
- hosts: cache
remote_user: root
tasks:
- name: install the latest version of Apache
yum:
name: httpd
state: installed
notify:
- boot start
- restart httpd
- lineinfile:
path: /etc/httpd/conf/httpd.conf
regexp: '^Listen '
insertafter: '^#Listen '
line: 'Listen 8080'
notify:
- restart httpd
- lineinfile:
path: /etc/httpd/conf/httpd.conf
regexp: '^#ServerName'
line: 'ServerName localhost'
notify:
- restart httpd
- copy:
src: index.html
dest: /var/www/html/index.html
owner: apache
group: apache
mode: 0644
handlers:
- name: restart httpd
service:
name: httpd
state: restarted
- name: boot start
service:
name: httpd
enabled: yes
2.1.4 when
1.when的使用场景
• 某些时候我们可能需要在满足特定的条件后在触发某
一项操作,或在特定的条件下终止某个行为,这个时
候我们就需要进行条件判断,when 正是解决这个问
题的最佳选择,远程中的系统变量 facts 变量作为
when 的条件,这些 facts 我们可以通过 setup 模块
查看
2.根据系统使用不同的安装命令
---
- name: Install VIM
hosts: all
tasks:
- name: Install VIM via yum
yum: name=vim-enhanced state=installed
when: ansible_os_family == "RedHat"
- name: Install VIM via apt
apt: name=vim state=installed
when: ansible_os_family == "Debian"
2.1.5 register
register 模块保存前一个命令的返回状态,在后面进行调用。
1.变量注册
– 例如我们需要判断 lijun 这个用户是否存在
– 如果存在我就修改密码,如果不存在就跳过
tasks:
- shell: id {{username}}
register: result
- name: change "{{username}}" password
user: password={{'12345678'|password_hash('sha512')}} name={{username}}
when: result
2.变量注册进阶
– 我们还可以针对运行命令结果的返回值做判定
– 当系统负载超过一定值的时候做特殊处理
把负载高的web服务器停止
---
- hosts: web
remote_user: root
tasks:
- shell: uptime |awk '{printf("%.2f",$(NF-2))}'
register: result
- service: name=httpd state=stopped
when: result.stdout|float > 0.7
追加 debug 调试信息
- name: Show debug info
debug: var=ooxx
测试命令 awk 'BEGIN{while(1){}}'
2.1.6 with_items
1.with_items列表循环
with_items 是 playbook 标准循环,最常用到的就
是它,with_items 可以用于迭代一个列表或字典,
通过{{ item }}获取每次迭代的值
2.循环添加多用户
---
- hosts: db2
remote_user: root
tasks:
- name: create user
user:
name: "{{item.name}}"
password: "{{item.pwd|password_hash('sha512')}}"
group: "{{item.group}}"
with_items:
- { name: "user1", pwd: "aa", group: "users" }
- { name: "user2", pwd: "bb", group: "mail" }
- { name: "user3", pwd: "cc", group: "wheel" }
- { name: "user4", pwd: "dd", group: "root" }
2.1.7 with_nested
1.嵌套循环
---
- hosts: cache
remote_user: root
vars:
un: [a, b, c]
id: [1, 2, 3]
tasks:
- name: add users
shell: echo {{item}}
with_nested:
- "{{un}}"
- "{{id}}"
2.1.8 tags
1. tags:给指定的任务定义一个调用标识;
2.使用格式:
– name: NAME
– module: arguments
– tags: TAG_ID
3. playbook 调用方式
– -t TAGS, --tags=TAGS
– --skip-tags=SKIP_TAGS
– --start-at-task=START_AT
4.tags样例:
vars:
soft: httpd
tasks:
- name: install {{soft}}
yum: name={{soft}}
- name: config httpd.conf
copy: src=/root/playbook/httpd.conf
dest=/etc/httpd/conf/httpd.conf
- name: config services
service: enabled=yes state=restarted name={{soft}}
tags: restartweb
• 调用方式
ansible-playbook i.yml --tags=restartweb
2.1.9 include and roles
1. 我们在编写 playbook 的时候随着项目越来越大,
playbook 也越来越复杂,修改起来也越来越麻烦。
这时候可以把一些 play、task 或 handler 放到其他
文件中,然后通过include指令包含进来是一个不错
的选择
tasks:
- include: tasks/setup.yml
- include: tasks/users.yml user=plj #users.yml 中可以通过
{{ user }}来使用这些变量
handlers:
- include: handlers/handlers.ymlinclude and roles
2. roles 像是加强版的 include,他可以引入一个项目
的文件和目录
2.1 一般所需的目录层级有
– vars 变量层
– tasks 任务层
– handlers 触发条件
– files 文件
– template 模板
– default 默认,优先级最低
2.2 假如有一个play包含了一个叫 "x" 的role,则
---
- hosts: host_group
roles:
- x
– x/tasks/main.yml
– x/vars/main.yml
– x/handler/main.yml
– x/... .../main.yml
– 都会自动添加进这个 play
2.2 调试
1.playbook 书写起来容易出错,且排错困难,这里介绍几种简单的排错
调试方法
– 检测语法
ansible-playbook --syntax-check playbook.yaml
– 测试运行
ansible-playbook -C playbook.yaml
– 显示收到影响到主机 --list-hosts
– 显示工作的 task --list-tasks
– 显示将要运行的 tag --list-tags
2.debug 模块可以在运行时输出更为详细的信息,来
帮助我们排错,debug 使用样例:
---
- hosts: 192.168.1.16
remote_user: root
tasks:
- shell: uptime |awk '{printf("%f\n",$(NF-2))}'
register: result
- shell: touch /tmp/isreboot
when: result.stdout|float > 0.5
- name: Show debug info
debug: var=result