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.\r\n", "module_stdout": "\r\nalex is not in the sudoers file. This incident will be reported.\r\n", "msg": "MODULE FAILURE\nSee 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.\r\n", "module_stdout": "\r\nalex is not in the sudoers file. This incident will be reported.\r\n", "msg": "MODULE FAILURE\nSee 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.\r\n", "module_stdout": "\r\nalex is not in the sudoers file. This incident will be reported.\r\n", "msg": "MODULE FAILURE\nSee 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.\r\n", "module_stdout": "\r\nalex is not in the sudoers file. This incident will be reported.\r\n", "msg": "MODULE FAILURE\nSee 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.\r\n", "module_stdout": "\r\nalex is not in the sudoers file. This incident will be reported.\r\n", "msg": "MODULE FAILURE\nSee 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.\r\n", "module_stdout": "\r\nalex is not in the sudoers file. This incident will be reported.\r\n", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1 }