一、概述
Ansible是2013年推出的通用自动化工具,可用于配置管理和流程管理。Ansible使用Python编写,它使用SSH在不同的机器上执行命令,Ansible是无代理的,使用声明式YAML编写Playbook。
(1)其他开源项目
- Ansible Galaxy:用于查找、共享使用Ansible Role的在线社区
- Ansible Container:实现了构建、部署、管理容器应用的全过程
- Ansible Tower:商业项目,可视化仪表盘
(2)对管理主机的要求
- 支持Python2和Python3
(3)对目标主机的要求
- 使通常使用SSH通信,使用SFTP作为文件传输,通过修改ansible.cfg可以实现SCP文件传输
- 支持Python2或者Python3版本
(4)与其他软件对比
Ansible | Chef | Puppet | SaltStack | |
---|---|---|---|---|
开发语言 | Python | Ruby、Erlang | C++、Clojure | Python2 |
配置文件 | YAML、JSON | Ruby | Propfiletary | YAML |
数据库支持 | 不需要 | PostgreSQL | PuppetDB | 不需要 |
传输方式 | SSH | RabbitMQ | Mcollective | ZeroMQ |
发布方式 | PUSH | PULL | PULL | PUSH |
管理节点 | 无限制 | LINUX | LINUX | 无限制 |
是否需要代理 | 是 | 否 | 否 | 否 |
公有云版本 | AM | AM、AZ、PR | 否 | 否 |
公有云管理支持 | AM、AZ、OS、GCP | Fog Driver | AM、AZ、VM、GCP | Salt Cloud |
架构 | Server | C/S | C/S | C/S |
逐步部署支持 | 支持 | 支持 | 不支持 | 不支持 |
开源版UI | Semaphore | Chef Manager | Foreman | Slatpad、SlatShaker |
企业版UI | Ansible Tower | OpsCode Manager | Puppet Enterprise | SaltStack Enterprise |
企业版本 | 是 | 是 | 是 | 是 |
Ansible适用于中小型环境,SaltStack执行效率高,Puppet适合大型环境。
(5)常见文件和命令
/etc/ansible/ansible.cfg
配置文件/etc/ansible/hosts
主机清单/etc/ansible/roles
存放角色的目录/usr/bin/ansible
主程序/usr/bin/ansible-doc
查看配置文档的程序/usr/bin/ansible-galaxy
Role分享平台/usr/bin/ansible-playbook
定制自动化任务/usr/bin/ansible-ansible-pull
远程执行命令/usr/bin/ansible-vault
文件加密/usr/bin/ansible-console
基于Console界面与用户交互的工具
二、主机清单
(1)概述
主机清单的本质是个INI文件或者YAML文件,因此可以手动使用Python的INI模块configparser
解析。但是YAML文件使用不方便所以忽略。
ini文件由section和键值对或者字符串组成,每个section对应多个键值对,类似于如下形式:
[section]
key=value
string
(2)定义主机
Ansible通过主机清单管理想要管理的主机。将主机组写在sectioon位置,Ansible支持各种形式的主机定义:
[nginx-servers]
hostname
hostname:port # 指定连接端口
localhost ansible_connection=local # 指定连接类型
hostname http_port=80 maxReuqestsPerChild=808 # 定义主机变量
hostname ansible_ssh_port=22 ansible_ssh_host=192.168.3.3 # 定义SSH参数
service[0:50].example.com # 支持范围定义的方式
server[a-f].example.com
(3)执行环境
Ansible支持定义执行Playbook的时候所使用的的执行环境:
[mysql-servers]
database.example.com ansible_python_interpreter=/applications/python/bin/python3.8
192.168.3.5 ruby_module_host ansible_ruby_interpreter=/applications/ruby/bin/ruby
(4)定义变量
Ansible支持在Hosts文件中定义变量:
[nginx-servers:var] # 使用:var表示定义在nginx-servers组内可以被共享的变量
ntp_server = 192.178.3.7
proxy = 127.0.0.1:1080
由于在Hosts文件中的变量存在覆盖情况,因此变量在覆盖的时候遵循以下优先级:
- all 最低
- 父组
- 子组
- 主机 最高
当然可以使用ansible_group_priority
调整优先级,默认为1(数值越大优先级越高),相同的优先级后者优先。
(5)组合并
Ansible支持将组合并为一个新的组进行管理:
[web-services]
nginx-servers
mysql-servers
Ansible中有默认的组:
- all:所有的主机
- ungrouped:没有组的主机
三、Playbook
Playbook是由多个Play构成的,Play的主要功能在于将预定义的一组主机设置为通过Ansible中的Task描述后的角色。本质上,Task是调用Ansible的一个Module(目前Ansible自带1738个模块),将多个Play组织在一个Playbook中,就可以通过多个Play实现任务的编排。Playbook采用YAML编写,在YAML的基础上,支持Jinjia2模板引擎的解析。
通常情况下,一个YAML文件对应一个Playbook,但是也可以使用---
进行分割。
一般会将Playbook文件存放到/etc/ansible/role
目录。
(1)核心元素
- hosts:执行Playbook的远程主机列表,支持逻辑操作符
- tasks:任务集,由众多action组成,每个name对应一个action,用于描述action的意义
- varniables:变量,在YAML文件中使用变量:
{{var_name}}
,变量可以在:- Hosts文件或者Playbook中定义
- 使用ansible setup fact获取
-e
参数可以通过命令行传入参数
- templates:模板,可以替换模板文件变量并且实现简单逻辑的文件,比如根据硬件信息自动修改配置,使用jinjia2语言
- handlers:与notify结合使用,特定条件下触发的处理器,本质上handlers还是action,notify与hanlder通过name进行绑定
- tags:标签,指定某条任务执行,用于选择运行Playbook中的部分代码,Ansible本身具有幂等性,自动跳过没有变化的部分。但是有些Task在测试是否执行过的时候时间很长,因此可以配合tag使用。多个action可以共用一个tag
执行Playbook的指令:
ansible-playbook yamlfile
--check
参数可以检查Playbook脚本,-t tagname
可以指定Tag执行,-k
使用密码方式,默认是秘钥方式
在action中,大部分模块参数都是键值对形式,除了shell和command模块。
由于在执行任务的时候出错,如果希望继续执行那么可以在命令后边添加|| /bin/true
或者在action中添加ignore_errors: True
- hosts: all
remote_user: root
vars:
- filename: create-by-ansible
tasks:
- name: create new file in root home
file: name=/root/{{filename}} state=touch
notify:
- restart postfix
- check nginx status
- name: create new user
user: name=tmpuser system=yes shell=/sbin/nologin
tags: create-new-user
handlers:
- name: restart postfix
service: name=postfix state=restart
- name: check nginx status
shell: killall -0 nginx
(2)执行流程
(3)Role模块化
/etc/ansible
的目录结构:
ansible.cfg # Ansible的配置文件
hello-world.yml # Playbook文件,与roles目录同级
hosts # 配置的主机文件
roles # 存放角色的目录
└── hello-world # 一个角色
├── default # 设定默认变量时使用此目录的main.yml文件
│ └── main.yml
├── files # 存放由copy和script模块等调用的文件
├── handlers # 存放触发器对应的处理Action,通过include引入
│ └── main.yml
├── meta # 角色的特殊设定及其依赖关系,通过include引入
│ └── main.yml
├── tasks # 定义Task和Role的基本元素,通过include引入
│ └── main.yml
├── templates # 存放模板文件的目录
└── vars # 定义变量,通过include引入
└── main.yml
tasks/main.yml中通过include的编写顺序定义各个task的执行顺序:
- include: create-user.yml
- include: copy-nginx-config.yml
在Playbook中使用Role,/etc/ansible/hello-world.yml
:
- hosts: services
remote_user: root
roles:
- role: hello-world
*模板会自动搜索templates目录下的.j2文件**:
templates: nginx.conf.j2
变量的优先级是:-e
指定的变量 > Playbook变量 > 主机清单变量
(4)角色包含
-
静态包含
- 使用import_tasks模块来包含task文件
- 使用import_role模块来包含role
-
变量包含
- include_vars 在task中动态加载yaml或json文件类型中的变量
-
动态包含
循环引用3次 - include_tasks: foo.yml param={{item}} with_items: - 1 - 2 - 3 使用动态变量引入task文件 - include_tasks: "{{inventory_hostname}}.yml"
(5)Facts
-
采集目标系统的信息
ansible hostname -m setup
支持正则表达式过滤:
ansible all -m setup -a 'filter=ansible_*_mb’
-
自定义目标系统的facts
在远程主机
/etc/ansible/facts.d/
目录下创建.fact
结尾的文件,也可以是json、ini 或者返回json 格式数据的可执行文件,这些将被作为远程主机本地的facts 执行。# /etc/ansible/facts.d/helloworld.fact [helloworld] name = hello
通过
{{ ansible_local.preferences.helloworld.name }}
方式来使用该变量 -
Facts支持缓存,
/etc/ansible/ansible.cfg
- 使用文件作为缓存
fact_caching = jsonfile fact_caching_connection = /tmp/facts_cache
- 使用Redis作为缓存
gathering = smart fact_caching = redis fact_caching_timeout = 86400 fact_caching_connection = localhost:6379:0:admin
- 使用Memcached作为缓存
gathering = smart fact_caching = memcached fact_caching_timeout = 86400 fact_caching_connection = localhost:11211