一、自动化工具介绍
1、自动化运维应用场景
- 文件传输
- 应用部署
- 配置管理
- 任务流编排
2、常用自动化运维工具
- Ansible:python,Agentless,中小型应用环境
- Saltstack:python,一般需部署agent,执行效率更高
- Puppet:ruby, 功能强大,配置复杂,重型,适合大型环境
- Fabric:python,agentless
- Chef:ruby,国内应用少
- Cfengine
- func
二、Ansible介绍
1、Ansible特性
- 1> 模块化:调用特定的模块,完成特定任务
- 2> Paramiko(python对ssh的实现),PyYAML,Jinja2(模板语言)三个关键模块
- 3> 支持自定义模块
- 4> 基于Python语言实现
- 5> 部署简单,基于python和SSH(默认已安装),agentless
- 6> 安全,基于OpenSSH
- 7> 支持playbook编排任务
- 8> 幂等性:一个任务执行1遍和执行n遍效果一样,不因重复执行带来意外情况
- 9> 无需代理不依赖PKI(无需ssl)
- 10> 可使用任何编程语言写模块
- 11> YAML格式,编排任务,支持丰富的数据结构
- 12> 较强大的多层解决方案
2、Ansible架构

Ansible的作用以及工作结构
1、ansible简介:
ansible是新出现的自动化运维工具,基于Python开发,
集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,
实现了批量系统配置、批量程序部署、批量运行命令等功能。
ansible是基于模块工作的,本身没有批量部署的能力。
真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。
主要包括:
(1)、连接插件connection plugins:负责和被监控端实现通信;
(2)、host inventory:指定操作的主机,是一个配置文件里面定义监控的主机;
(3)、各种模块核心模块、command模块、自定义模块;
(4)、借助于插件完成记录日志邮件等功能;
(5)、playbook:剧本执行多个任务时,非必需可以让节点一次性运行多个任务。
2、ansible的架构:连接其他主机默认使用ssh协议
3、Ansible工作原理

4、Ansible主要组成部分
ANSIBLE PLAYBOOKS:任务剧本(任务集),编排定义Ansible任务集的配置文件,由Ansible顺序依次执行,通常是JSON格式的YML文件
INVENTORY:Ansible管理主机的清单 /etc/anaible/hosts
MODULES: Ansible执行命令的功能模块,多数为内置核心模块,也可自定义
PLUGINS: 模块功能的补充,如连接类型插件、循环插件、变量插件、过滤插件等,该功能不常用
API: 供第三方程序调用的应用程序编程接口
ANSIBLE: 组合INVENTORY、API、MODULES、PLUGINS的绿框,可以理解为是ansible命令工具,其为核心执行工具
Ansible命令执行来源:
- 1> USER,普通用户,即SYSTEM ADMINISTRATOR
- 2> CMDB(配置管理数据库) API 调用
- 3> PUBLIC/PRIVATE CLOUD API调用 (公有私有云的API接口调用)
- 4> USER-> Ansible Playbook -> Ansibile
利用ansible实现管理的方式:
- 1> Ad-Hoc 即ansible单条命令,主要用于临时命令使用场景
- 2> Ansible-playbook 主要用于长期规划好的,大型项目的场景,需要有前期的规划过程
Ansible-playbook(剧本)执行过程
- 将已有编排好的任务集写入Ansible-Playbook
- 通过ansible-playbook命令分拆任务集至逐条ansible命令,按预定规则逐条执行
Ansible主要操作对象
- HOSTS主机
- NETWORKING网络设备
注意事项:
- 执行ansible的主机一般称为主控端,中控,master或堡垒机
- 主控端Python版本需要2.6或以上
- 被控端Python版本小于2.4需要安装python-simplejson
- 被控端如开启SELinux需要安装libselinux-python
- windows不能做为主控端
- ansible不是服务,不会一直启动,只是需要的时候启动
三、Ansible安装
1、rpm包安装
#安装epel源 yum install epel-release -y #安装 yum install ansible
2、编译安装
yum -y install python-jinja2 PyYAML python-paramiko python-babel python-crypto tar xf ansible-1.5.4.tar.gz cd ansible-1.5.4 python setup.py build python setup.py install mkdir /etc/ansible cp -r examples/* /etc/ansible
3、Git方式
git clone git://github.com/ansible/ansible.git --recursive cd ./ansible source ./hacking/env-setup
4、pip安装
yum install python-pip python-devel yum install gcc glibc-devel zibl-devel rpm-bulid openssl-devel pip install --upgrade pip pip install ansible --upgrade
确认安装:
ansible --version
四、Ansible配置
1、文件结构
配置文件
/etc/ansible/ansible.cfg 主配置文件,配置ansible工作特性(一般无需修改)
/etc/ansible/hosts 主机清单(将被管理的主机放到此文件)
/etc/ansible/roles/ 存放角色的目录
程序
/usr/bin/ansible 主程序,临时命令执行工具
/usr/bin/ansible-doc 查看配置文档,模块功能查看工具
/usr/bin/ansible-galaxy 下载/上传优秀代码或Roles模块的官网平台
/usr/bin/ansible-playbook 定制自动化任务,编排剧本工具
/usr/bin/ansible-pull 远程执行命令的工具
/usr/bin/ansible-vault 文件加密工具
/usr/bin/ansible-console 基于Console界面与用户交互的执行工具
2、主机清单inventory
Inventory 主机清单
1> ansible的主要功用在于批量主机操作,为了便捷地使用其中的部分主机,可以在inventory file中将其分组命名
2> 默认的inventory file为/etc/ansible/hosts
3> inventory file可以有多个,且也可以通过Dynamic Inventory来动态生成
/etc/ansible/hosts文件格式
inventory文件遵循INI文件风格,中括号中的字符为组名。
可以将同一个主机同时归并到多个不同的组中;
此外,当如若目标主机使用了非默认的SSH端口,还可以在主机名称之后使用冒号加端口号来标明
ntp.magedu.com 不分组,直接加
[webservers] webservers组
www1.magedu.com:2222 可以指定端口
www2.magedu.com
[dbservers]
db1.magedu.com
db2.magedu.com
db3.magedu.com
如果主机名称遵循相似的命名模式,还可以使用列表的方式标识各主机
示例:
[websrvs]
www[1:100].example.com ip: 1-100
[dbsrvs]
db-[a:f].example.com dba-dbff
3、Ansible 配置文件
Ansible 配置文件/etc/ansible/ansible.cfg (一般保持默认) vim /etc/ansible/ansible.cfg [defaults] #inventory = /etc/ansible/hosts # 主机列表配置文件 #library = /usr/share/my_modules/ # 库文件存放目录 #remote_tmp = $HOME/.ansible/tmp # 临时py命令文件存放在远程主机目录 #local_tmp = $HOME/.ansible/tmp # 本机的临时命令执行目录 #forks = 5 # 默认并发数,同时可以执行5次 #sudo_user = root # 默认sudo 用户 #ask_sudo_pass = True # 每次执行ansible命令是否询问ssh密码 #ask_pass = True # 每次执行ansible命令是否询问ssh口令 #remote_port = 22 # 远程主机的端口号(默认22) 建议优化项: host_key_checking = False # 检查对应服务器的host_key,建议取消注释 log_path=/var/log/ansible.log # 日志文件,建议取消注释 module_name = command # 默认模块
五、Ansible命令
1、Ansible系列命令
Ansible系列命令
ansible ansible-doc ansible-playbook ansible-vault ansible-console ansible-galaxy ansible-pull
ansible-doc: 显示模块帮助
ansible-doc [options] [module...]
-a 显示所有模块的文档
-l, --list 列出可用模块
-s, --snippet 显示指定模块的playbook片段(简化版,便于查找语法)
示例:
ansible-doc -l 列出所有模块
ansible-doc ping 查看指定模块帮助用法
ansible-doc -s ping 查看指定模块帮助用法
2、Ansible命令介绍
ansible通过ssh实现配置管理、应用部署、任务执行等功能,建议配置ansible端能基于密钥认证的方式联系各被管理节点
ansible <host-pattern> [-m module_name] [-a args]
ansible +被管理的主机(ALL) +模块 +参数
--version 显示版本
-m module 指定模块,默认为command
-v 详细过程 –vv -vvv更详细
--list-hosts 显示主机列表,可简写 --list
-k, --ask-pass 提示输入ssh连接密码,默认Key验证
-C, --check 检查,并不执行
-T, --timeout=TIMEOUT 执行命令的超时时间,默认10s
-u, --user=REMOTE_USER 执行远程执行的用户
-b, --become 代替旧版的sudo切换
--become-user=USERNAME 指定sudo的runas用户,默认为root
-K, --ask-become-pass 提示输入sudo时的口令
ansible all --list 列出所有主机
ping模块: 探测网络中被管理主机是否能够正常使用 走ssh协议
如果对方主机网络正常,返回pong
ansible-doc -s ping 查看ping模块的语法
检测所有主机的网络状态
1> 默认情况下连接被管理的主机是ssh基于key验证,如果没有配置key,权限将会被拒绝
因此需要指定以谁的身份连接,输入用户密码,必须保证被管理主机用户密码一致
ansible all -m ping -k
2> 或者实现基于key验证 将公钥ssh-copy-id到被管理的主机上 , 实现免密登录
ansible all -m ping
3、Ansible的主机组
ansible的Host-pattern
匹配主机的列表
All :表示所有Inventory中的所有主机
ansible all –m ping
* :通配符
ansible "*" -m ping (*表示所有主机)
ansible 192.168.1.* -m ping
ansible "*srvs" -m ping
或关系 ":"
ansible "websrvs:appsrvs" -m ping
ansible “192.168.1.10:192.168.1.20” -m ping
逻辑与 ":&"
ansible "websrvs:&dbsrvs" –m ping
在websrvs组并且在dbsrvs组中的主机
逻辑非 ":!"
ansible 'websrvs:!dbsrvs' –m ping
在websrvs组,但不在dbsrvs组中的主机
注意:此处为单引号
综合逻辑
ansible 'websrvs:dbsrvs:&appsrvs:!ftpsrvs' –m ping
在websrvs组或者在dbsrvs组,并且在appsrvs组,同时不再ftpsrvs组
websrvs U dbsrvs ∩ appsrvs ∩(!sftpsrvs)
正则表达式
ansible "websrvs:&dbsrvs" –m ping
ansible "~(web|db).*.magedu.com" –m ping
4、Ansible命令执行过程
ansible命令执行过程
1. 加载自己的配置文件 默认/etc/ansible/ansible.cfg
2. 加载自己对应的模块文件,如command
3. 通过ansible将模块或命令生成对应的临时py文件,
并将该文件传输至远程服务器的对应执行用户$HOME/.ansible/tmp/ansible-tmp-数字/XXX.PY文件
4. 给文件+x执行
5. 执行并返回结果
6. 删除临时py文件,sleep 0退出
执行状态:
绿色:执行成功并且不需要做改变的操作
黄色:执行成功并且对目标主机做变更
红色:执行失败
六、Ansible使用示例
示例
以wang用户执行ping存活检测
ansible all -m ping -u wang -k
以wang sudo至root执行ping存活检测
ansible all -m ping -u wang -k -b
以wang sudo至mage用户执行ping存活检测
ansible all -m ping -u wang -k -b --become-user=mage
以wang sudo至root用户执行ls
ansible all -m command -u wang -a 'ls /root' -b --become-user=root -k -K
ansible ping模块测试连接
ansible 192.168.38.126,192.168.38.127 -m ping -k
完整实例:
需求:
- 创建普通用户,并设置密码
- 使用普通用户通过sudo查看root家目录下面的内容
1、创建普通用户alex
[root@ansible ~]# ansible all -m shell -a "useradd alex" 192.168.52.130 | CHANGED | rc=0 >> 192.168.52.132 | CHANGED | rc=0 >> 192.168.52.131 | CHANGED | rc=0 >>
2、设置用户密码
[root@ansible ~]# ansible all -m shell -a "echo xuequn|passwd alex --stdin" 192.168.52.130 | CHANGED | rc=0 >> Changing password for user alex. passwd: all authentication tokens updated successfully. 192.168.52.132 | CHANGED | rc=0 >> Changing password for user alex. passwd: all authentication tokens updated successfully. 192.168.52.131 | CHANGED | rc=0 >> Changing password for user alex. passwd: all authentication tokens updated successfully.
3、普通用户alex查看root下的文件
[root@ansible ~]# ansible all -m shell -a "ls /root" -u alex -k SSH password: 192.168.52.130 | FAILED | rc=2 >> ls: cannot open directory /root: Permission deniednon-zero return code 192.168.52.132 | FAILED | rc=2 >> ls: cannot open directory /root: Permission deniednon-zero return code 192.168.52.131 | FAILED | rc=2 >> ls: cannot open directory /root: Permission deniednon-zero return code [root@ansible ~]#
提示没有权限!
4、sudo切换到root进行执行
[root@ansible ~]# ansible all -m shell -a "ls /root" -u alex -k -b -K
SSH password:
BECOME password[defaults to SSH password]:
192.168.52.132 | FAILED! => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"module_stderr": "Shared connection to 192.168.52.132 closed.
",
"module_stdout": "
alex is not in the sudoers file. This incident will be reported.
",
"msg": "MODULE FAILURE
See stdout/stderr for the exact error",
"rc": 1
}
192.168.52.131 | FAILED! => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"module_stderr": "Shared connection to 192.168.52.131 closed.
",
"module_stdout": "
alex is not in the sudoers file. This incident will be reported.
",
"msg": "MODULE FAILURE
See stdout/stderr for the exact error",
"rc": 1
}
192.168.52.130 | FAILED! => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"module_stderr": "Shared connection to 192.168.52.130 closed.
",
"module_stdout": "
alex is not in the sudoers file. This incident will be reported.
",
"msg": "MODULE FAILURE
See stdout/stderr for the exact error",
"rc": 1
}
提示alex用户不存在于sudoers文件中!
5、将alex用户添加至sudoers文件中,加入wheel组即可。
[root@ansible ~]# ansible all -m shell -a "usermod -a -G wheel alex" 192.168.52.130 | CHANGED | rc=0 >> 192.168.52.131 | CHANGED | rc=0 >> 192.168.52.132 | CHANGED | rc=0 >>
6、验证是否加入成功
[root@ansible ~]# ansible all -m shell -a "cat /etc/group|grep wheel" 192.168.52.130 | CHANGED | rc=0 >> wheel:x:10:alex 192.168.52.132 | CHANGED | rc=0 >> wheel:x:10:alex 192.168.52.131 | CHANGED | rc=0 >> wheel:x:10:alex
7、通过sudo切换到root用户执行查看root家目录的文件
[root@ansible ~]# ansible all -m shell -a "ls /root" -u alex -k -b -K SSH password: BECOME password[defaults to SSH password]: 192.168.52.132 | CHANGED | rc=0 >> anaconda-ks.cfg original-ks.cfg 192.168.52.130 | CHANGED | rc=0 >> anaconda-ks.cfg original-ks.cfg 192.168.52.131 | CHANGED | rc=0 >> anaconda-ks.cfg original-ks.cfg
8、删除wheel组中的alex用户
[root@ansible ~]# ansible all -m shell -a "gpasswd -d alex wheel" 192.168.52.130 | CHANGED | rc=0 >> Removing user alex from group wheel 192.168.52.131 | CHANGED | rc=0 >> Removing user alex from group wheel 192.168.52.132 | CHANGED | rc=0 >> Removing user alex from group wheel
9、再次测试alex用户是否可以通过sudo命令查看root家目录下的内容
[root@ansible ~]# ansible all -m shell -a "ls /root" -u alex -k -b -K
SSH password:
BECOME password[defaults to SSH password]:
192.168.52.131 | FAILED! => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"module_stderr": "Shared connection to 192.168.52.131 closed.
",
"module_stdout": "
alex is not in the sudoers file. This incident will be reported.
",
"msg": "MODULE FAILURE
See stdout/stderr for the exact error",
"rc": 1
}
192.168.52.132 | FAILED! => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"module_stderr": "Shared connection to 192.168.52.132 closed.
",
"module_stdout": "
alex is not in the sudoers file. This incident will be reported.
",
"msg": "MODULE FAILURE
See stdout/stderr for the exact error",
"rc": 1
}
192.168.52.130 | FAILED! => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"module_stderr": "Shared connection to 192.168.52.130 closed.
",
"module_stdout": "
alex is not in the sudoers file. This incident will be reported.
",
"msg": "MODULE FAILURE
See stdout/stderr for the exact error",
"rc": 1
}