一、利用主机模式选择主机
- 书上这里其实就是讲主机清单里面主机和主机组的形式,这里的角度更多是从play中的hosts可指定的内容(个人觉得差不多,有点啰嗦)
1、主机模式介绍
- 主机模式:用于指定要作为play或临时命令的目标主机(其实就是指明目标主机的一种说法)
- 最简单的形式:**清单中受管主机或主机组的名称(包括ip地址)**就是指定该主机或主机组的主机模式
- 合理利用主机清单的主机模式,而不在play的任务中设置复杂的条件,会使得控制目标主机变得更加容易
2、主机模式的几种常见形式
-
受管主机
-
最基本的主机模式是单一受管主机名称列在清单中
-
事实收集在匹配主机模式后,在所有匹配的受管主机上运行
-
-
使用组指定主机
- 将对属于该组的成员的主机执行操作
- 默认存在的
all
和ungrouped
组
-
使用通配符匹配多个主机
hosts: '*'
效果同all组- 建议使用单引号,防止某些shell字符生效
hosts: '*.example.com'
匹配以.example.com
结尾
-
使用逻辑列表引用清单中多个条目
- 形式一:以
:
或,
分隔,任何属于这些组的所有主机都是目标- 示例:
hosts: lab,data*,192.168.2.2
- 示例:
- 形式二:在主机模式前加上
&
符号,表示某一主机/主机组要同时匹配&标识的主机模式才作为目标- 示例:
hosts: lab,&datacenter1
表示lab组内的主机要同时匹配datacenter1组才作为目标
- 示例:
- 形式三:在主机模式前加上
!
符号,表示某一主机/主机组要不匹配!标识的主机模式才作为目标- 示例
hosts: !test2,datacenter
表示datacenter中的主机,不匹配(除了)test2才作为目标
- 示例
- 形式一:以
二、管理动态清单
1、介绍
- 引入:使用静态清单管理小型基础架构很方便,但是对大型架构或更替很快的环境,静态清单很难随时保持最新的状态
- Ansible支持动态清单脚本,这些脚本在每当Ansible执行时从这些类型的来源检索当前的信息,使清单能够实时得到更新(执行ansible时先执行动态清单)
- 这些脚本是可以执行的程序,能够从一些外部来源收集信息,并以JSON格式输出清单
- Ansible识别方法:清单可执行即被视为动态清单,不可执行即被视为静态清单
2、贡献的脚本
- 如何获取开源的动态清单脚本
- 可以从GitHub网站获取
- 贡献的动态清单脚本以一些数据源或平台作为对象(下面是书上的原话,看看就好)
- 私有云平台,如红帽OpenStack平台。
- 公共云平台,如 Rackspace Cloud、Amazon Web Services EC2和Google Compute Engine。
- 虚拟化平台,如红帽虚拟化(oVirt)和VMware vSphere。
- 平台即服务解决方案,如OpenShift Container Platform。
- 生命周期管理工具,如Foreman(搭配红帽卫星6或独立使用)和Spacewalk(红帽卫星5的上游)。
- 主机托管提供程序,如Digital Ocean和 Linode。
3、编写动态清单程序(了解即可)
- 动态清单程序可以使用任何编程语言编写自定义程序,但必须以JSON格式返回清单信息
- 可以使用
ansible-inventory --list
以JSON格式查看清单文件 - 开发要求:
- 脚本以适当的解释器运行(例如#!/usr/bin/python)开头并且可以执行
- 在传递
--list
选项时,脚本必须显示清单中所有主机和组的JSON编码散列/字典
- 注:本节内容超出考试要求,不会让你手写动态脚本文件的
4、管理多个清单
-
Ansible支持在同一运行中使用多个清单,可指定目录(会组合该目录中包含的所有清单文件)
-
清单文件不应依赖于其他清单文件或脚本来解析,即如果静态清单文件指定某一组group1是另一组group2的子集,则也需要具有group2组的占位符条目,来确保内部一致性不受解析顺序的影响(解析顺序是按字母顺序进行解析)
[cloud-east] [servers] test.demo.example.com [servers:children] cloud-east
三、配置并行
1、使用分叉在Ansible中配置并行
-
Ansible可以同时连接到play中的所有主机以执行每项任务
- 适用于小型主机列表
- 但目标数量过大(数百台),则会给控制节点带来沉重的负担
-
Ansible所进行的最大同时连接数由Ansible配置文件中的forks参数控制,默认为5
-
通常在控制节点负载不高的情况下,将forks值调大(接近100),然后性能就会提高
2、管理滚动更新
-
引入:
- 通常当Ansible运行play时,会确保所有受管主机,在启动任何主机进行下一个任务前已经完成每个任务(所有一个任务全部完成后进入下一个任务)
- 在某些情况下,例如软件更新,不能同时停止全部的服务,可使用serial关键字
-
例如将
serial
设置为2,则play一次将运行两台受控节点,直至全部更新完示例
--- - name: Rolling update hosts: webservers serial: 2 tasks: - name: latest apache httpd package is installed yum: name: httpd state: latest notify: restart apache handlers: - name: restart apache service: name: httpd state: restarted
-
相反,如果不使用serial关键字,将同时在五台Web服务器上执行play和生成的处理程序。这可能会导致服务中断,因为Web服务将在所有Web服务器上同时重新启动
-
如果因为某些原因更新失败,则会停止整个playbook,也仅会影响两台受控节点
-
四、包含和导入文件
1、介绍
- 引入:当playbook很长或很复杂时,可以拆分为较小的文件来便于管理,这样可以提高各play/task的重用性
- Ansible的两种包含文件的方式
- 包含内容是一个动态操作。在playbook运行期间,Ansible 会在内容到达时处理所包含的内容
- 导入内容是一个静态操作。在运行开始之前,Ansible在最初解析playbook时预处理导入的内容
2、导入Playbook
import_playbook
指令允许您将包含play列表的外部文件导入playbook- 因为导入的是一个完整的playbook,所以只可以在playbook的顶层(指层级,不一定是开头)使用,而不能在play内使用
---
- name: Play 1
hosts: localhost
tasks:
- debug:
msg: Play 1
- name: Import Playbook
import_playbook: play2.yml
3、导入和包含任务
-
可以将任务文件中的任务列表导入或包含在play中(任务列表->play中)
-
导入任务文件
-
使用
import_tasks
功能将任务文件静态导入playbook中的play中,要注意插入位置决定了解析执行顺序 -
示例
--- - name: Install web server hosts: webservers tasks: - import_tasks: webserver_tasks.yml # webserver_tasks.yml文件的内容仅有正常tasks的任务列表
-
注意事项
- 使用import_tasks 功能时,导入时设置的when等条件语句将应用于导入的每个任务
- 您无法将循环用于import_tasks功能
- 如果使用变量来指定要导入的文件的名称,那么您将无法使用主机或组清单变量
-
-
包含任务文件
-
使用
include_tasks
功能将任务文件动态导入playbook中的play中,运行到达这部分play之前,不会处理其内容 -
示例
- name: Install web server hosts: webservers tasks: - include_tasks: webserver_tasks.yml
-
注意事项
- 使用include_tasks 功能时,包含时设置的when等条件语句将确定任务是否包含在 play中
- 如果运行
ansible-playbook --list-tasks
以列出playbook中的任务,则**不会显示已包含(include)**任务文件中的任务(包含文件的内容),将显示包含任务文件的任务 - 相比之下,
import_tasks
功能不会列出导入任务文件的任务(导入文件的任务),而列出已导入任务文件中的各个任务(导入文件的具体内容) - 不能使用
ansible-playbook --start-at-task
从已包含任务文件中的任务开始执行playbook - 不能使用notify语句触发已包含任务文件中的处理程序名称。可以在包含整个任务文件的主playbook中触发处理程序,在这种情况下,已包含文件中的所有任务都将运行
-
-
建议创建专门用于任务文件的目录,来保存所有任务文件
4、为外部play和任务定义变量
-
为进一步增强重用任务,使得导入的任务和play文件尽可能通用,变量可用于参数化play和任务元素,扩大任务和play的应用范围(可以理解为程序设计里面库函数设计参数)
-
下面一步步推导如何参数化
- 下例是按照web软件包并启动
- name : Install the httpd package
yum:
name: httpd
state: latest
- name: start the httpd service
service:
name: httpd
enabled: true
state: started
- 将此例中的软件包和服务参数化
- name: Install the {{ package }} package
yum:
name: "{{ package }}"
state: latest
- name: start the {{ service }} service
service:
name: "{{ service }}"
enabled: true
state: started
- 将此任务文件导入到另一个playbook中,并定义变量(Ansible使传递的变量可用于从外部文件导入的任务)
tasks:
- name: Import task file and set variables
import_tasks: task.yml
vars:
package: httpd
service: httpd
- 此技术同样可用于导入剧本
- name: Import play file and set the variable
import_playbook: play.yml
vars:
package: mariadb