Ansible is an open source IT automation engine that automates provisioning, configuration management, application deployment, orchestration, and many other IT processes.
运维自动化和 Ansible 简介
云计算运维工程师核心技能
相关工具:
- 代码管理(SCM):GitHub,GitLab,BitBucket,SubVersion
- 构建工具:Maven,Ant,Gradle
- 自动部署:Capistrano,CodeDeploy
- 持续集成(CI):jenkins,Travis
- 配置管理:Ansible,SaltStack,Chef,Puppet
- 容器:Docker,Podman,LXC,第三方厂商如AWS
- 编排:Kubernetes,Core,Apache Mesos
- 服务注册与发现:Zookeeper,etcd,Consul
- 脚本语言:Python,Ruby,Shell
- 日志管理:ELK,Logentries
- 系统监控:Prometheus,Zabbix,Datadog,Graphite,Ganglia,Nagios
- 性能监控:AppDynamics,New Relic,Splunk
- 压力测试:jMeter,Blaze Meter,loader.io
- 应用服务器:Tomcat,jBoss,IIS
- Web服务器:Apache,Nginx
- 数据库:MySQL,Oracle,PostgreSQL等关系型数据库;mongoDB,redis等NoSQL数据库
- 项目管理(PM):jira,Asana,Taiga,Terllo,Basecamp,Pivotal Tracker
Ansible 特性
- 模块化:调用特定的模块完成特定任务,支持自定义模块,可以使用任何编程语言编写模块
- Paramiko(python 对 ssh 的实现),PyYAML,Jinja2(模板语言)三个关键模块
- 基于Python语言实现
- 部署简单,基于 python 和 SSH(默认已安装),agentless,无需代理不依赖 PKI(无需 SSL)
- 安全,基于 OpenSSH
- 幂等性:一个任务执行 1 遍和执行 n 遍效果一样,不因重复执行带来意外情况,此特性非绝对
- 支持 playbook 编排任务,YAML 格式,编排任务,支持丰富的数据结构
- 较强大的多层解决方案 role
Ansible 架构
ANSIBLE
:组合 INVENTORY、API、MODULES、PLUGINS 的绿框,可以理解为是 ansible 命令工具,其为核心执行工具
ANSIBLE PLAYBOOKS
:任务剧本(任务集),编排定义 Ansible 任务集的配置文件,由 Ansible 顺序依次执行,通常是 JSON 格式的 YML 文件INVENTORY
:Ansible 管理主机的清单/etc/anaible/hosts
MODULES
:Ansible 执行命令的功能模块,多数为内置核心模块,也可自定义PLUGINS
:模块功能的补充,如连接类型插件、循环插件、变量插件、过滤插件等,该功能不常用API
:供第三方程序调用的应用程序编程接口
Ansible 安装和入门
Ansible 安装
1 | $ dnf info ansible |
EPEL 源的 rpm 包安装
1 | $ yum install absible |
除此以外还有编译安装,Git 方式安装,pip 方式安装等
确认安装:
1 | $ ansible --version |
Ansible 相关文件
Ansible 配置文件
/etc/ansible/ansible.cfg
:主配置文件,配置 ansible 工作特性/etc/ansible/hosts
:主机清单文件,配置 ansible 管理的主机/etc/ansible/roles/
:存放角色的目录
Ansible 主配置文件
/etc/ansible/ansible.cfg
大部分的配置内容无需进行修改
1 | [defaults] |
inventory 主机清单
ansible 的主要功用在于批量主机操作,为了便捷地使用其中的部分主机,可以在 inventory file 中将其分组命名。默认的 inventory file 为 /etc/ansible/hosts
。inventory file 可以有多个,且也可以通过 Dynamic Inventory 来动态生成
inventory 文件遵顼 INI
文件风格,中括号中的字符为组名,可以将用一个主机同时归并到多个不同的组中,其外,当目标主机使用了非默认的 SSH 端口,还可以在主机名称之后使用冒号加端口号来说明。如果主机名称遵循相似的命名模式,还可以使用列表的方式标识各主机
1 | mail.example.com |
1 | [webservers] |
如果想配置目标主机,就不需要通过 SSH 协议连接本机,只需添加 ansible_connection=local
即可
1 | [test] |
ansible_connection
不写的时候默认为 ssh,ansible_port
不写的时候默认为 22,ansible_ssh_user
不写的时候默认为当前用户,ansible_ssh_pass
不写的时候默认为 ssh 密钥
Ansible 相关工具
usr/bin/ansible
:主程序,临时命令执行工具usr/bin/ansible-doc
:查看配置文档,模块工程查看工具,相当于 manusr/bin/ansible-playbook
:定制自动化任务,编排剧本工具,相当于脚本usr/bin/ansible-pull
:远程执行命令的工具usr/bin/ansible-vault
:文件加密工具usr/bin/ansible-console
:基于 Console 界面与用户交互的执行工具usr/bin/ansible-galaxy
:下载/上传优秀代码或 Role 模块的官网平台
利用 ansible 实现管理的主要方式:
- Ad-Hoc 即利用 ansible 命令,主要用于临时命令使用场景
- Ansible-playbook 主要用于长期规划好的,大型项目的场景,需要有前期的规划过程
ansible-doc
显示模块的帮助信息
1 | ansible-doc [options] [module] |
1 | # 列出所有模块 |
ansible
此工具通过 ssh 协议,实现对远程主机的配置管理,应用部署,任务执行等功能
格式:
1 | ansible <host-pattern> [-m module_name] [-a args] |
选择说明:
1 | --version # 显示版本 |
例:
1 | $ ansible all --list-hosts |
1 | $ ansible all -m ping |
也可以只有通配符等简单的模式匹配,如:
1 | # ansible 的 Host-pattern |
ansible命令执行过程
- 加载自己的配置文件,默认
/etc/ansible/ansible.cfg
- 加载自己对应的模块文件,如:command
- 通过 ansible 将模块或命令生成对应的临时 py 文件,并将该文件传输至远程服务器的对应执行用户
$HOME/.ansible/tmp/ansible-tmp-数字/XXX.PY
文件 - 给文件 +x 执行
- 执行并返回结果
- 删除临时 py 文件,sleep 0 退出
执行状态:
- 绿色:执行成功并且不需要做改变的操作
- 黄色:执行成功并且对目标主机做变更
- 红色:执行失败
ansible-vault
用于生成加密解密 yml 文件
1 | $ ansible-vault [options] [create|decrypt|edit|encrypt|rekey|view] [vaultfile.yml] |
1 | # 加密 |
ansible-console
此工具可交互执行命令,支持 tab,ansible 2.0+ 新增
ansible-galaxy
此工具会连接 https://galaxy.ansible.com 下面对应的 roles
1 | # 列出所有已安装的 galaxy |
Ansible常用模块
Command 模块
1 | $ ansible all -m command -a 'hostname' |
Command 模块是默认模块,即使不输入 command
也是默认的。可以在 /etc/ansible/ansible.cfg
下修改默认模块
需要注意的是,Command 模块不支持各种符号,例如 $ > 等,如果需要使用这些符号,需要使用 shell 模块
Shell 模块
与 Command 模块类似,但是支持各种符号,比如 * $ > 等
1 | $ ansible all -m shell -a 'echo $HOSTNAME' |
Script 模块
在远程主机上运行 ansible 服务器上的脚本(无需执行权限)
1 | $ ansible all -m script -a "/data/test.sh" |
Copy 模块
从 ansible 服务器主控制端复制文件到远程主机
1 | # 如果目标存在,默认覆盖,此处指定先备份 |
Fetch 模块
从远程主机提取文件至 ansible 服务器主控制端,与 copy 模块相反,目前不支持目录
1 | asible all -m fetch -a "src=/data/test.sh dest=/data/scripts" |
File 模块
设置文件属性,创建软连接等
1 | # 创建空文件 |
unarchive 模块
解包解压缩
2种用法
- 将 ansible 主机上的压缩包传到远程主机后解压缩至特定目录,设置
copy=yes
,copy 参数默认为 yes,未来这个参数会被废弃 - 将远程主机上的压缩包解压缩至指定路径下,设置
copy=no
1 | $ ansible all -m unarchive -a "src=/data/foo.tar.gz dest=/var/lib/foo owner=user group=bin mode=0777 copy=yes" |
archive 模块
打包压缩保存在被管理节点
1 | $ ansible all -m archive -a "path=/data/foo dest=/tmp/foo.zip format=zip owner=user mode=0777" |
hostname 模块
管理主机名
1 | $ ansible node1 -m hostname -a "name=webserver1" |
corn 模块
计划任务
支持时间:minute,hour,day,month,weekday
1 | # 备份数据库脚本 |
1 | # 创建任务 |
$ contab -l 查看计划任务
yum 和 apt 模块
yum
管理软件包,只支持RHEL, CentOS, Fedora, Amazon Linux, Oracle Linux, Scientific Linux
,不支持Ubuntu, Debian
版本apt
模块管理Debian
相关版本的软件包
1 | # 安装 |
service 模块
管理服务
1 | # 停止服务 |
user 模块
管理用户
1 | # home 指定家目录路径 |
group 模块
管理组
1 | # 创建组 |
lineinfile 模块
ansible 在使用 sed
替换时,经常会遇到需要转义的问题,而且 ansible 在遇到特殊符号进行替换时,存在问题,无法正常进行替换,其实在 ansible 自身提供了两个模块,lineinfile 模块和 replace 模块,可以方便的进行替换
一般在 ansible 当中去修改某个文件的单行进行替换的时候需要使用 lineinfile 模块
regexp 参数:使用正则表达式匹配对应的行,当替换文本时,如果有多行文本都能被匹配,则只有最后面被匹配的那行文本才会被替换,当删除文本时,如果有多行文本都能被匹配,那么这些行都会被删除
如果想进行多行匹配进行替换需要使用 replace 模块
- 相当于
sed
,可以修改文件内容
1 | $ ansible webserver -m lineinfile -a "dest=/etc/httpd/conf/httpd.conf regexp='^Listen' line='Listen 8080'" |
replace 模块
类似于 sed
指令,主要也是基于正则进行匹配和替换,建议使用
1 | $ ansible all -m replace -a "path=/etc/fstab regexp='^(UUID.*)' replace='#\1'" |
setup 模块
setup 模块来收集主机的系统信息,这些 facts 信息可以直接以变量的形式使用,但是如果主机较多,会影响执行速度,可以使用 gather_facts: no
来禁止 ansible 收集 facts 信息
1 | $ ansible all -m setup |
Playbook
playbook 介绍
playbook 是由一个或多个 play
组成的列表,play 的主要功能在于将预定义的一组主机,装扮成事先通过 ansible 中的 task
定义好的角色
Task 实际是调用 ansible 的一个 module,将多个 play 组织在一个 playbook 中,即可以让它们联合起来,按事先编排的机制执行预定义的动作
playbook 核心组件
Hosts
:执行的远程主机列表(应用在哪些主机上)Tasks
:任务集,由多个 task 的元素组成的列表实现,每个 task 是一个字典Variables
:内置变量或自定义变量在 playbook 中调用Templates
:模板,可替换模板文件中的变量并实现一些简单逻辑的文件Handlers
和notify
:结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行tags
:指定某条任务执行,用于选择运行 playbook 中的部分代码。ansible 具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地长。此时,如果确信其没有变化,就可以通过 tags 跳过此些代码片断- ansible-playbook -t tagsname useradd.yml
roles
:角色,将 playbook 中的一些任务集合成一个角色,可以在 playbook 中调用,也可以在其他 playbook 中调用
hosts 组件
playbook 中的每一个 play 的目的都是为了让特定主机以某个指定的用户身份执行任务。hosts
用于指定要执行指定任务的主机,须事先定义在主机清单中
1 | one.example.com |
1 | - hosts: websrvs:dbsrvs |
remote_user 组件
可用于 Host 和 task 中。也可以通过指定其通过 sudo 的方式在远程主机上执行任务,其可用于 play 全局或某任务;此外,甚至可以在 sudo 时使用 sudo_user
指定 sudo 时切换的用户
1 | - hosts: websrvs |
task 列表和 action 组件
play 的主体部分是 task list,task list 中的各任务按次序逐个在 hosts 中指定的所有主机上执行,即在所有主机上完成第一个任务后,再开始第二个任务
task 的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致
每个 task 都应该有其 name,用于 playbook 的执行结果输出,建议其内容能清晰地描述任务执行步骤。如果未提供 name,则 action 的结果将用于输出
1 | action: module arguments |
运行 playbook
1 | # 运行playbook的方式 |
playbook 实战
playbook 创建 mysql 用户
1 |
|
playbook 安装 Nginx
1 |
|
playbook 安装 httpd
1 | - hosts: websrvs |
playbook 中使用 handlers 和 notify
handlers
本质是 task list,类似于 MySQL 中的触发器触发的行为,其中的 task 与前述的 task 并没有本质上的不同,主要用于当关注的资源发生变化时,才会采取一定的操作
notify
对应的 action 可用于在每个 play 的最后被触发,这样可避免多次有改变发生时每次都执行指定的操作,仅在所有的变化发生完后一次性的执行指定操作。而 notify 中列出的操作被称为 handler,即 notify 中调用 handler 中定义的操作
1 | - hosts: websrvs |
1 | - hosts: websrvs |
playbook 中使用 tags
在 playbook 文件中,可以利用 tags 组件,为特定 tasks 指定标签,当在执行 playbook 时,可以只执行特定 tags 的 tasks,而不是执行整个 playbook
1 | # httpd.yml |
1 | # 指定执行install,conf 两个标签 |
playbook 中使用变量
仅能由字母,数字和下划线组成,且只能以字母开头
1 | # 变量定义 eg. |
setup 模块中的变量
setup 模块中的变量可以直接调用
ansible setup facts
远程主机的所有变量都可直接调用 (系统自带变量),setup 模块可以实现系统中很多系统信息的显示,可以返回每个主机的系统信息包括:版本、主机名、cpu、内存等
1 | $ ansible all -m setup -a 'filter="ansible_nodename"' # 查询主机名 |
1 |
|
1 | $ ansible-playbook var1.yaml |
playbook 命令行中自定义变量
通过命令行指定变量,优先级最高
1 | # 命令行赋值 |
1 |
|
1 | $ ansible-playbook var2.yaml |
playbook 文件中自定义变量
1 |
|
1 | $ ansible-playbook var3.yaml |
使用变量文件
可以在一个独立的 playbook 文件中定义变量,在另一个 playbook 文件中引用变量文件中的变量,比 playbook 中定义的变量优先级高
1 | # var.yaml |
1 | # var4.yaml |
主机清单文件中定义变量
主机变量
1 | # vim /etc/ansible/hosts |
1 |
|
组/公共变量
在 inventory 主机清单文件中赋予指定组内所有主机上的在 playbook 中可用的变量,如果和主机变量是同名,优先级低于主机变量
1 | # vim /etc/ansible/hosts |
1 |
|
Template
模板是一个文本文件,可以做为生成文件的模板,并且模板文件中还可以嵌套 jinja
语法
jinja2 语言
Jinja2 语言,使用字面量,有下面形式
- 字符串:使用单引号或双引号
- 数字:整数,浮点数
- 列表:[item1, item2, …]
- 元组:(item1, item2, …)
- 字典:{key1:value1, key2:value2, …}
- 布尔型:true/false
- 算术运算:+, -, *, /, //, %, **
- 比较操作:==, !=, >, >=, <, <=
- 逻辑运算:and,or,not
- 流表达式:For,If,When