Ansible
Ansible基础
概述
Ansible首次发布于2012年,作者Michael DeHaan
于2015年被RedHat收购
Ansible是一种自动化运维工具,基于Python开发
批量系统部署
批量程序部署
批量运行命令等功能
Ansible特色
- 基于SSH架构
- 模块丰富
- 社区活跃
- 支持自定义模块
- 支持异构IT架构
- 部署简单,容易上手
Ansible环境部署
配置SSH密钥
- 所有节点做相同操作
1 | [root@ansible ~]# cat /etc/hosts |
部署软件
控制节点
要求Python2.6及以上
Python模块:paramiko、PyYAML、JinJa2······
1 | [root@ansible ~]# tar xf ansible.tar.gz -C /opt/ |
被控节点
Ansible默认通过SSH协议管理机器
被管理主机要开启SSH服务,并允许控制主机登录
被管理主机需要安装Python
Ansible基本配置
配置文件
主配置文件ansible.cfg
参考/etc/ansible/ansible.cfg
ansible配置文件查找顺序
首先检测ANSIBLE_CONFIG变量定义的配置文件
其次检查当前目录下的ansible.cfg文件
再次检查当前用户家目录下ansible.cfg文件
最后检查/etc/ansible/ansible.cfg文件
主配置文件
- 参考/etc/ansible/ansible.cfg
1 | [root@ansible ~]# mkdir ansible |
inventory主机清单文件
将被管理端主机写入一个主机列表文件
参考/etc/ansible/hosts
1 | [root@ansible ansible]# vim hosts |
测试
- 测试Ansible环境与配置是否正常
1 | [root@ansible ~]# cd ansible/ #ansible命令需要再ansible目录下 |
ad-hoc命令行
命令行语法格式
Ansible ad-hoc是一种通过命令行批量管理的方式
格式:
ansible 主机集合 -m 模块名 -a "参数"
其他选项: -k 使用密码远程、-i 指定主机列表文件
模块就是脚本(多数为Python脚本)
多数脚本都支持参数
默认模块为command
1 | [root@ansible ansible]# ansible node-1 -m command -a "uptime" |
获取帮助
Ansible总共有哪些模块
每个模块支持哪些参数
1 | [root@ansible ansible]# ansible-doc -l #列出所有模块 |
Ansible常用模块
shell模块
command和shell模块的区别
- command模块的命令不启动shell,直接通过ssh执行命令
- command不支持bash的特性,如
管道和重定向
等功能 - 所有需要调用shell的功能都无法使用
1 | [root@ansible ansible]# ansible test -m command -a "ps | wc -l" #报错 |
shell模块会启动shell执行命令
- 不可以使用shell模块执行交互命令,如vim、top等
1 | [root@ansible ansible]# ansible test -m shell -a "ps | wc -l" |
shell模块支持判断(creates)
- creates 文件名:文件存在不执行shell命令
1 | [root@ansible ansible]# ansible test -m shell -a "ssh-keygen -f ~/.ssh/id_rsa -N '' creates=~/.ssh/id_rsa" |
script模块
如果命令复杂
- script允许在本地写脚本,拷贝到被管理主机并执行
- 脚本不是shell脚本(如python,perl等),可以没有-x
1 | [root@ansible ansible]# cat test.sh |
file模块
file模块可以创建文件、目录、连接;修改权限与属性等
幂等性:任意执行所产生的影响均与第一次执行的影响相同
1 | #新建文件 |
copy模块
将文件拷贝到远程主机
- backup=yes如果目标主机有相同文件,则先备份
1 | [root@ansible ansible]# echo "AAA" > a3.txt |
fetch模块
与copy类似,但是作用相反
- 可以将其他主机的文件拷贝到本地
1 | [root@ansible ansible]# ansible test -m fetch -a "src=/etc/hostname dest=./" |
lineinfile模块
- 修改单个文件的单行内容时可以使用lineinfile模块
1 | #在/etc/issue文件中添加一行内容,默认添加在最后 |
replace模块
- lineinfile会替换一整行,replace可以替换关键字
1 | #将/etc/issue文件全文所有的Kernel替换为Ocean |
user模块
- user模块可以实现Linux系统账户系统
1 | #远程test组中所有主机并创建系统账户tuser1 |
yum_repository模块
- 使用yum_repository模块可以创建或修改yum源配置文件
1 | [root@ansible ansible]# ansible test -m yum_repository -a "name=myyum description=hello baseurl=file:///opt/centos gpgcheck=0" |
yum模块
- 使用yum模块可以安装、卸载、升级软件包
- state:present(安装)absent(卸载)latest(升级)
1 | [root@ansible ansible]# ansible test -m yum -a "name=unzip state=present" |
service模块
- service为服务管理模块(启动、关闭、重启等)
- state:started(启动)stopped(关闭)restarted(重启)
- enabled:yes设置开机自启
1 | [root@ansible ansible]# ansible test -m yum -a "name=httpd state=present" |
逻辑卷相关模块
lvg模块
- 创建、删除卷组(VG),修改卷组大小
- state:present(创建)absent(修改)
1 | [root@ansible ansible]# ansible test -m yum -a "name=lvm2" |
lvol模块
- 创建、删除逻辑卷(lv),修改逻辑卷大小
- state:present(创建)absent(修改)
1 | #使用myvg卷组创建名为mylv的逻辑卷 |
sudo提权
sudo
- superuser or another do
- 以管理员或其他人的身份执行命令
基本流程
- 管理员需要先授权(修改/etc/sudoers文件)
- 普通用户以sudo形式执行命令
- 可以通过sudo -l查看授权情况
sudoers语法
修改/etc/sudoers的方法
- visudo(带语法检查,默认没有颜色提示)
- vim /etc/sudoers(不带语法检查,默认有颜色提示)
授权格式
- 用户或组 主机列表=(提权身份) [NOPASSWD]:命令列表
- 命令需要写
绝对路径
配置sudo提权
- 为所有被管理主机创建系统账户
1 | [root@ansible ansible]# ansible all -m user -a "name=alice password={{'000000'|password_hash('sha512')}}" |
- 在所有被管理主机配置sudo,让alice可以执行
任何命令
- 使用NOPASSWD开启无密码验证
1 | [root@ansible ansible]# ansible all -m lineinfile -a "path=/etc/sudoers line='alice ALL=(ALL) NOPASSWD:ALL'" |
Ansible进阶配置
主配置文件
修改~/ansible/ansible.cfg
修改sudo相关配置(参考/etc/ansible/ansible.cfg)
1 | [defaults] |
配置SSH密钥
- 使用alice远程被管理主机,需要提前配置SSH密钥
1 | [root@ansible ansible]# for i in node-1 node-2 |
主机清单文件
inventory配置
- 如果个别主机账户不同该如何处理
- 如果有些主机需要使用密码该如何
- 有些主机的SSH端口不是22该如何
- 修改主机清单文件,添加变量(多个变量空格分开)
1 | [test] |
Ansible Playbook
Playbook概述
Ansible ad-hoc可以通过命令行形式远程管理其他主机
适合执行一些临时性简单任务
Ansible playbook中文名称叫剧本
将经常需要执行的任务写入一个文件(剧本)
剧本中可以包含多个任务
剧本写后,我们随时调用剧本,执行相关的任务命令
YAML简介
- 是一个可读性高、用来表达数据序列的格式语言
- YAML:YAML Aint't a Markup Language
- YAML以数据为中心,重点描述数据的关系和结构
YAML格式
- “#”代表注释,一般第一行为三个横杠
键值对使用":"表示,数组使用"-"表示
- 缩进必须由两个或以上空格组成
- 相同层级的缩进
必须对齐
- 全文
不可以使用tab键
- 区分大小写、扩展名为yaml或yml
- 跨行数据需要使用>或者|(|会保留换行符)
YAML格式的键值对数据
- key和value之间使用”:”分隔
- “:”后面必须有空格
- 缩进代表层级关系
1 | "key": "value" |
YAML格式的数组数据
- 使用短横杠和空格表示一行表示数据
1 | "key": |
Playbook语法格式
playbook采用YAML格式编写
playbook文件中由一个或多个play组成
每个play中可以包含:
hosts(主机)、tasks(任务)
variables(变量)、roles(角色)、handlers等元素
使用ansible-playbook命令运行playbook剧本
1 | [root@ansible ansible]# vim test.yml |
- hosts由一个或多个组或主机组成,逗号分割
- tasks由一个或多个任务组成,多个任务按顺序执行
- 可以使用-f选项自定义并发量
1 | [root@ansible ansible]# vim test.yml |
- 一个playbook中可以有多个play
1 | [root@ansible ansible]# vim test.yml |
Ansible Playbook应用案例
用户
- 编写playbook创建系统账户、账户属性、设置密码
- 花括号外面必须有双引号
1 | [root@ansible ansible]# vim user_john.yml |
- 删除用户
1 | [root@ansible ansible]# vim user_john.yml |
逻辑卷
- 使用vdb创建卷组和逻辑卷
1 | [root@ansible ansible]# vim lvm.yml |
软件管理
- 安装软件、升级软件、安装组包
1 | [root@ansible ansible]# vim pacakege.yml |
特殊模块
setup模块
- ansible_facts用于采集被管理设备的系统信息
- 所有收集的信息都被保存在变量中
- 每次执行playbook默认第一个任务就是Gathering Facts
- 使用setup模块可以查看收集到的facts信息
1 | [root@ansible ansible]# ansible test -m setup |
- 找出相应facts信息(父子关系时使用
.
分割)
1 | [root@ansible ansible]# ansible test -m setup -a "filter=ansible_mem*" |
debug模块
- debug模块可以显示变量的值,可以辅助排错
- debug模块有两个参数,mas(引用变量需要双大括号)var(引用不需要双大括号)
1 | [root@ansible ansible]# vim debug.yml |
firewalld模块
- 使用firewalld模块可以配置防火墙策略
1 | [root@ansible ansible]# vim firewalld.yml |
template模块
copy模块可以将一个文件拷贝给远程主机
但是如果希望每个拷贝的文件内容都不一样
如何给所有web主机拷贝index.html内容是各自的IP地址
Ansible可以利用Jinja2模板引擎读取变量
之前在playbook中调用变量,也是Jinja2的功能
Jinja2模块的表达式包含在分隔符双大括号内
1 | #给所有主机拷贝首页,每个主机内容不同 |
- 也可自定义变量
1 | [root@ansible ansible]# vim template/source.j2 |
Ansible定义变量
变量定义优先级排序
- inventory变量
- Host Facts变量
- Playbook变量
- 变量文件
- 当以
双大括号
开头时要用引号
定义变量
inventory变量
- 在主机清单配置文件中定义变量
1 | [root@ansible ansible]# vim hosts |
Host Facts变量
- 可以直接调用ansible收集的系统信息
1 | [root@ansible ansible]# vim facts_var.yml |
Playbook变量
- 使用vars关键词可以在playbook内定义变量
1 | [root@ansible ansible]# vim playbook_var.yml |
用vars_files调用变量文件
- 单独定义个变量文件,在playbook中用vars_files调用文件
1 | [root@ansible ansible]# vim variables.yml |
使用-e参数定义变量
- 执行ansible-playbook命令时使用-e参数定义变量
1 | [root@ansible ansible]# vim command_var.yml |
Ansible高级语法
error处理机制
- 默认ansible在遇到error会立刻停止playbook
- 使用ignore_errors可以忽略错误,继续后续的任务
1 | [root@ansible ansible]# vim error.yml |
handlers
当某个任务需要依赖其他任务怎么办
- 可以通过handlers定义一组任务
- 仅当某个任务触发(notify)handlers时才执行相应的任务
- 如果有多个notify触发执行handlers任务,也仅执行一次
仅当任务的执行状态为changed时handlers任务才执行
- handlers任务在所有其他任务都执行后才执行
1 | [root@ansible ansible]# vim handlers.yml |
when条件判断
when可以定义判断条件,条件为真时才执行某个任务
常见条件操作入下:
==、!=、>、>=、<、<=
多个条件可以使用and或or分割
when表达式调用变量不要使用
双大括号
远程主机剩余内存不足700M则关闭NetworkManager服务
1 | [root@ansible ansible]# vim when1.yml |
判断操作系统是Centos7则创建测试文件
1 | [root@ansible ansible]# vim when2.yml |
block认为块
- 使用block可以将多个任务合并为一个组
1 | [root@ansible ansible]# vim block1.yml |
- rescue定义block任务执行失败时要执行的其他任务
- always定义无论block任务是否成功,都要执行的任务
1 | [root@ansible ansible]# vim block2.yml |
loop循环
- 很多任何在使用相同的模块,使用loop避免重复
1 | [root@ansible ansible]# vim loop.yml |
- 把多个变量写入文件,也可以用loop调用
1 | nginx: |
Ansible Vault
加密敏感数据
ansible有时需要访问一些敏感数据,如密码、key等
使用ansible-vault可以加密和解密数据
encrypt(加密)、decrypt(解密)、view(查看)
1 | [root@ansible ansible]# echo 123456 > data.txt |
修改密码
- ansible-vault rekey可以修改加密的密码
1 | [root@ansible ansible]# ansible-vault encrypt data.txt |
密码文件
- 加密、解密每次都输入密码很麻烦,可以将密码写入文件
1 | [root@ansible ansible]# echo "hello world" > data.txt |
Ansible Roles
Ansible Roles基础
基本概念
在实际生产环境中,为了实现不同的功能,我们会编写大量的playbook文件
而且,每个playbook还可能会调用其他文件(如变量文件)
对于海量的、无规律的文件,管理起来很痛苦
Roles是管理ansible文件的
一种规范
(目录结构)Roles会按照标准的规范,自动到特定的目录和文件中读取数据
Roles规范的目录结构
1 | roles/user.example |
- default/main.yml:定义变量的缺省值,优先级较低
- files目录:存储静态文件的目录
- handlers/main.yml:定义handlers
- meta/main.yml:写作者、版本等描述信息
- REASME.md:整个角色(role)的描述信息
- tasks/main.yml:定义任务的地方
- template目录:存放动态数据文件的地方(模板文件)
- vars/main.yml:定义变量,优先级高
Ansible Roles应用
创建Role
- ansible-galaxy命令可以创建、管理自己的roles
1 | [root@ansible ansible]# mkdir roles |
修改Role
- 定义模板文件
1 | [root@ansible ansible]# vim roles/user.example/templates/issue.j2 |
- 定义变量文件
1 | [root@ansible ansible]# vim roles/user.example/vars/main.yml |
修改任务文件,任务文件中不需要tasks关键词
role的各个文件之间相互之间不需要写路径
1 | [root@ansible ansible]# vim roles/user.example/tasks/main.yml |
在Playbook中调用Role
- 方法一:在role相同的目录下创建一个playbook调用
- 方法二:在ansible.cfg设置roles_path=路径
1 | [root@ansible ansible]# vim ansible.cfg |
- 编写playbook文件,通过roles关键词调用role
1 | [root@ansible ansible]# vim issue.yml |
Ansible Galaxy
Ansible Galaxy是官方提供的一个共享roles的平台
公共Roles仓库(https://galaxy.ansible.com)
1 | #联网搜索roles |
下载Roles方法
使用ansible-galaxy install 或者编写requirements.yml
1 | [root@ansible ansible]# vim roles/requirements.yml |