Ansible
内容:
1.软件发布环境机制优势对比
2.Linux上的Ansible应用
Ansible的相关的文档:
非常实用的中文版功能查询手册,Ansible的中文权威指南:ansible中文指南
Github上的ansible-galaxy示例:ansible-galaxy
本文只列出一些常用的功能,更多功能以后遇到再进行更新
其他相关运维管理工具使用方法:
pssh的使用方法参照链接文章:PSSH
saltstack介绍及使用参照链接文章:Saltstack
puppet介绍及使用参照链接文章:puppet
本文主要讲解Ansible在linux服务器上的管理
windows下的ansible使用方法链接:ansible-windows
当下有许多的运维自动化工具( 配置管理 ),例如:Ansible、SaltStack、Puppet、Fabric
常用自动化运维工具
PSSH:适用于主机数量很少的环境(基础ssh的key验证)
Ansible:python,Agentless,中小型应用环境(自带代理功能)
Saltstack:python,一般需部署agent,执行效率更高
Puppet:ruby, 功能强大,配置复杂,重型,适合大型环境
Fabric:python,agentless
发布更新环境
灰度发布:又叫金丝雀发布(核心概念:一次只发布一部分主机)
比如:共100台生产服务器,先发布其中的10台服务器,这10台服务器就是灰度服务器
而软件更新实际上是将旧版本或者新版本创建一个软链接指向软件的工具路径
如:
软件路径为:/data/app
正在用的软件版本V1.0:/data/app1.0
更新的软件版本V2.0:/data/app2.0
则需要把删除原来的软链接:/data/app1.0--->/data/app
创建新的软链接:/data/app2.0--->/data/app
10台机器升级软件版本后,先上线进行,然后再逐渐把剩余的90台主机升级上线
发布步骤:
1.准备好部署各个阶段的工件,包括:构建工件,测试脚本,配置文件和部署清单文件。
2.从负载均衡列表中移除掉「金丝雀」服务器。
3.升级「金丝雀」应用(排掉原有流量并进行部署)。
4.对应用进行自动化测试。
5.将「金丝雀」服务器重新添加到负载均衡列表中(连通性和健康检查)。
6.如果「金丝雀」在线使用测试成功,升级剩余的其他服务器(否则就回滚)。
A/B Testing
A/B测试是用来测试应用功能表现的方法,例如可用性、受欢迎程度、可见性等等。 A/B 测试通常用在应用的前端上,不过当然需要后端来支持。
优势与不足:
优势:用户体验影响小,灰度发布过程出现问题只影响少量用户
不足:发布自动化程度不够,发布期间可引发服务中断
预发布验证:
新版本的代码先发布到服务器,和线上环境配置相同,只是未接入调度器
灰度发布:
可以基于主机,用户或者业务,又细分为地区,VIP和普通用户
蓝绿发布:核心:主备两套环境
定义:不停老版本,升级备环境版本然后进行测试。确认OK后将流量切到新版本,然后老版本同 时也升级到新版本
主:绿色环境-活动环境:负责对外提供服务,版本:v1.0
备:绿色环境-非活动环境:版本:v2.0
工作机制:
先把备环境升级v1.0--->v2.0版本,然后上线
把主环境的v1.0版本下线,已经升级的备环境进行替换
特点:
蓝绿部署无需停机,并且风险较小.
注意事项:
1.需要提前考虑数据库与应用部署同步迁移/回滚的问题
2.蓝绿部署需要有基础设施支持
3.在非隔离基础架构( VM 、 Docker 等)上执行蓝绿部署,蓝色环境
和绿色环境有被摧毁的风险.
优势与不足:
优势:升级切换和回退速度非常快
不足:需要有2套基础设施,v2.0版本有问题,则对用户体验有直接影响
滚动发布:在灰度发布的基础上进行进一步优化
定义:
一般是取出一个或者多个服务器停止服务,执行更新,并重新将其投入使用。周而复始,直到集群中所有的实例都更新成新版本,是自动化程度较高的发布方式.
特点:
1.这种部署方式相对于蓝绿部署,更加节约资源——它不需要运行两个集群、两倍的实例数. 可以部分部署,例如每次只取出集群的20%进行升级。
2.滚动式发布需要比较复杂的发布工具和智能LB,支持平滑的版本替换和流量拉入拉出
优势和不足:
优势:用户体验影响小,体验较平滑
不足:发布和回退时间比较缓慢。
发布工具比较复杂,LB需要平滑的流量摘除和拉入能力
滚动发布目前成熟型技术组织所采用的主流发布方式
Ansible
ansible特性:-最多管理500台主机,更多效率会降低
1.模块化:调用特定的模块,完成特定任务 -类似linux中的小命令
2.有Paramiko,PyYAML,Jinja2(模板语言)三个关键模块
3.支持自定义模块
4.基于Python语言实现
5.部署简单,基于python和SSH(默认已安装),agentless(没有自己的代理服务)
6.安全,基于OpenSSH
7.支持playbook编排任务 -类似于脚本功能,多个脚本的集合成为Roles
8.幂等性: 一个任务执行1遍和执行n遍效果一样,不因重复执行带来意外情况
9.无需代理不依赖PKI(无需ssl)
10.可使用任何编程语言写模块
11.YAML格式,编排任务,支持丰富的数据结构
12.较强大的多层解决方案
Ansible的主要功能简介:
1.ansible基本命令使用
2.ansible常用模块详解,介绍ansible单个命令的使用
3.YAML语法介绍
4.ansible playbook基础:剧本初体验,类似于写脚本
5.playbook中的变量:tags,handlers使用
6.plsybook模板:templates
7.playbook的条件判断:when
8.playbook的字典:with_items
9.Ansible Roles -多个playbook的组合,类似于多个脚本的集合
如果执行playbook时有错误信息,则会在playbook的同目录下生成一个*.retry的文件记录会记录执行时的错误IP地址,可以查看具体是什么原因产生的错误。
ansible命令执行过程(可以参照下面的playbook的执行流程图)
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退出
执行状态:(颜色定义在/etc/ansible/ansible.cfg中)
绿色:执行成功并且不需要做改变的操作
黄色:执行成功并且对目标主机做变更
红色:执行失败
CMDB作用介绍:
CMDB:Configuration Management Database 配置管理数据库
将服务器的配置,网络配置写到数据库里
CMDB即配置管理数据库,通过识别、控制、维护,检查企业的IT资源,从而高效控制与管理不
断变化的IT基础架构与IT服务,并为其它流程,例如事故管理、问题管理、变更管理、发布管
理等流程提供准确的配置信息.
了解更多CMDB可参照文章:CMDB
1.ansible基本命令使用
ansible软件安装:多种安装方法
1.基于epel源安装:
yum install ansible,非服务,只是一个管理工具
2.编译安装:
3.Github方式安装:可以同步安装
4.pip安装:pip是安装Python包的管理器,类似yum
ansible的重要&主要文件
配置文件:
/etc/ansible/ansible.cfg 配置ansible的工作特性
/etc/ansible/hosts 主机清单
/etc/ansible/roles 存放的角色目录
程序文件:
/usr/bin/ansible ansible的可执行命令-->2.7的软链接,都是软链接的思想
/usr/bin/ansible-doc 查看配置文档,模块功能查看工具,man帮助
/usr/bin/ansible-galaxy 下载/上传优秀代码或Roles模块的官网平台
/usr/bin/ansible-playbook 管理执行编排的playbook剧本任务
/usr/bin/ansible-vault 文件加密工具
/usr/bin/ansible-console 基于Console界面与用户交互的执行工具
ansible主机清单配置:/etc/ansible/hosts,第一步(下文中介绍主机清单的多种表示方法)
支持不分组,分组,等方式
如:
192.168.34.100
[webservers]
192.168.34.101
192.168.34.102
[dbservers]
192.168.34.[1:6]7 (17,27..67)
db[01:100].cenntos.com
ansible配置文件:/etc/ansible/ansible.cfg (一般保持默认)
配置文件只提供默认值,但可以通过playbook的设置进行覆盖
配置文件可以放在/etc/ansible/ansible.cfg中
也可以放到一个工作目录下命名为.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 - 默认并发数
sudo_user = root - 默认sudo 用户
ask_sudo_pass = True -每次执行ansible命令是否询问ssh密码
ask_pass = True
remote_port = 22
host_key_checking = False -检查对应服务器的host_key,建议取消注释
log_path=/var/log/ansible.log -建议启用日志文件,利于排错
[color] 定义ansible命令的执行结果颜色的
配置文件说明和建议修改的项:
local_tmp和remote_tmp:
本地临时文件和远程临时文件:把playbook转化成python程序,先放在本地
家目录的.ansible/tmp下,然后再通过ssh协议复制到远程主机的.ansible/tmp下,执行完毕后自动删除.
host_key_checking = False -检查对应服务器的host_key,建议取消注释
log_path=/var/log/ansible.log -建议启用日志文件,利于排错
module_name = command -默认使用的命令模块,可以修改成shell
建议修改为:module_name = shell
2.ansible常用模块详解,介绍ansible单个命令的使用
ansible模块的使用查询方法
ansible-doc: 显示模块帮助
ansible-doc [options] [module...]
-a 显示所有模块的文档
-l, --list 列出可用模块
-s, --snippet显示指定模块的playbook片段
示例:
ansible-doc –l 列出所有功能模块
ansible-doc ping 查看ansible中的ping用法
ansible-doc -s shell 查看shell模块的使用方法
ansible的常用基本选项
ansible通过ssh实现配置管理、应用部署、任务执行等功能,建议配置ansible
端能基于密钥认证的方式联系各被管理节点
ansible语法:
ansible <host-pattern> [-m module_name] [-a args]
--version 显示版本
-m module 指定模块,默认为command,主要使用选项
-v 详细过程 –vv -vvv更详细
--list-hosts 显示主机列表,可简写 --list
-k, --ask-pass 提示输入ssh连接密码,默认Key验证
-K, --ask-become-pass 提示输入sudo时的口令
-C, --check 检查,并不执行
-T, --timeout=TIMEOUT 执行命令的超时时间,默认10s
-u, --user=REMOTE_USER 执行远程执行的用户
-b, --become 代替旧版的sudo 切换
ansible的主机清单表示方法:Host-pattern
1.All :表示所有Inventory中的所有主机
如:ansible all -m ping
ansible all --list-hosts列出所有主机清单
ansible "dbservers" --list-hosts列出db组中的所有主机IP
2.* :通配符
如:ansible "*" = ansible all
ansible 192.168.34.* 表示34网段的所有IP
3.或的关系
如:ansible "websrvs:appsrvs" 对两个组的主机执行操作
ansible "192.168.1.10:192.168.1.20"对两个主机执行操作
4.与的关系(且)
如:ansible "websrvs:&dbsrvs"既在websrvs组并且在dbsrvs组中的主机
5.非,取反
如:ansible 'websrvs:!dbsrvs'
在websrvs组,但不在dbsrvs组中的主机;注意:此处为单引号
6.正则表达式
如:ansible "~(web|db).*\.centos\.com"
ansible的常见模块(第二步:具有很多模块,先列出比较常见且重要的,遇到再更新新的模块)
ansible-doc +模块名 可以查看具体使用方法:显示都有哪些选项
1.Command:在远程主机执行命令,默认模块,可忽略-m选项
可以在ansible.cfg中修改默认模块项
支持:chdir(切换目录)
command模块不支持 $ < > | ; & 等,可以用shell模块实现
使用示例:
ansible all -a 'rm -f /data/f1' 删除远程所有主机下f1文件,类似pssh
ansible all -a 'useradd test' 所有主机上创建test用户
2.Shell:和command相似,用shell执行命令,执行时要加-m shell选项
支持功能:支持$ < > | ; & 等
chdir 执行前,先切换到该文件夹
示例:ansible appsrvs -m shell -a 'echo $HOSTNAME'
显示appsrvs组的主机名
ansible all -m shell -a 'chdir=/data rm -rf *'
先切换到/data目录下,再执行删除命令
3.Script: 批量运行脚本
可以现在管理机上先把复杂命令写成脚本,再通过script去批量管理
功能:creates:远程主机的文件存在,则不运行
removes:远程主机的文件不存在,则也不运行==即文件存在,则执行命令
示例:ansible all -m script -a "/data/test.sh"
ansible all -a "creats=/etc/fstab rm -rf /data/*命令"
因为fstab文件存在,则不执行rm -rf /data/*命令
ansible all -a "removes=/etc/fstab rm -rf /data/*"
因为fstab文件存在,则执行rm -rf /data/*命令
4.Copy:从服务器复制文件到目标主机
src,dest,mode,owner,content,backup,mode
示例:1.nsible all -m copy -a 'src=/etc/fstab dest=/data/fstab2 backup=yes owner=test' 将fstab拷贝到主机被改名为fstab2,如果存在先备份,所有者改为test用户
2.ansible all -m copy -a 'content="selinux1\nselinux2" dest=/data/selinux1'
根据自己写的字符串生成文件
5.Fetch:从目标主机抓取文件至服务器端,copy相反,目录可先tar再抓取
src,dest(抓取到本机目录)
示例:ansible all -m fetch -a 'src=/data/fstab2 dest=/data/'
将远程主机fstab2文件抓取到本机/data下
如果抓取的是目录,先打包再抓取
打包:ansible all -a 'tar cf /root/data.tar /data'
抓取:ansible all -m fetch -a 'src=/data/fstab2 dest=/data/'
6.File:设置文件属性,创建/删除文件
src(创建链接文件),path=dest,state:(touch,absent,link,direcotory)
示例:创建文件:ansible all -m file -a 'dest=/data/f10 state=touch'
创建文件夹:ansible all -m file -a 'dest=/data/haha state=directory'
删除文件夹/目录:ansible all -m file -a 'dest=/data/haha state=absent'
7.Hostname:管理主机名
可以通过后面的变量来实现
a.先在hosts后定义hostname变量名
[centos6]
192.168.34.106 hostname=mini6-2
192.168.34.101 hostname=node6-1
[centos7]
192.168.34.107 hostname=mini7-1
b.再通过hostname模块批量修改
ansible all -m hostname -a 'name={{hostname}}'
8.Cron:计划任务
支持:minute,hour,day,month,weekday
示例:ansible all -m cron -a 'minute=*/5 job="/usr/sbin/ntpdate
172.18.0.1 &>/dev/null" name=Synctime' 创建计划任务
ansible srv -m cron -a 'name=Synctime state=absent' 删除指定的计划任务名
ansible srv -m cron -a 'name=Synctime disable=true' 禁用指定的计划任务名
9.Yum:管理包
支持:name,state=(started stopped reloaded restarted),absent
更新缓存:update_cache=yes,
示例:ansible all -m yum -a 'name=httpd,samba,vsftpd'安装多个包
ansible all -m yum -a 'name=httpd,samba,vsftpd state=absent'删除包
10.Service:管理服务(同一systemctl&service)
name,state(stopped,started,reloaded,restarted) enable(设置开启启动)
示例:ansible srv -m service -a 'name=httpd state=stopped' 停止服务
ansible srv –m service –a 'name=httpd state=reloaded' 重新加载服务
ansible srv -m service -a 'name=httpd state=restarted' 重启服务
ansible srv -m service -a 'name=httpd enable=yes' 设置开机启动
11.User:管理用户
name,comment(描述),group(主组),groups(附加组),uid,home,shell,system(系统用户) (absent,remove删除用户及家目录)
示例:ansible all -m user -a 'name=user1 uid=234 home=/data/user1 system=yes group=root groups=bin shell=/sbin/nologin comment'
创建用户,指定uid,家目录,主组,附加组,shell类型,指定为系统用户
ansible all -m user -a 'name=user1 state=absent remove=yes'删除用户及家目录
12.Group:管理组
支持:group,name,gid,system,state=(absent)
示例:ansible srv -m group -a 'name=testgroup system=yes' 创建系统组
ansible srv -m group -a 'name=testgroup state=absent' 删除组
ansible系列的一些模块(用的不多)
简单介绍与了解:
ansible-galaxy 互联网上的角色分享
ansible-pull
推送命令至远程,效率无限提升,对运维要求较高
Ansible-vault管理yaml文件
功能:管理加密解密yml文件
ansible-vault [create|decrypt|edit|encrypt|rekey|view]
ansible-vault encrypt hello.yml 加密
ansible-vault decrypt hello.yml 解密
ansible-vault view hello.yml 查看
ansible-vault edit hello.yml 编辑加密文件
ansible-vault rekey hello.yml 修改口令
ansible-vault create new.yml 创建新文件
Ansible-console
ansible重要知识之playbook(上面的各种模块的组合)
YAML语言(编写playbook的专门语言)
YAML语法:
在单一档案中,可用连续三个连字号(——)区分多个档案。另外,还有选择性的连续三
个点号( ... )用来表示档案结尾
次行开始正常写Playbook的内容,一般建议写明该Playbook的功能
使用#号注释代码
缩进必须是统一的,不能空格和tab混用
缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过
缩进结合换行来实现的
YAML文件内容是区别大小写的,k/v的值均需大小写敏感
k/v的值可同行写也可换行写。同行使用:分隔
v可是个字符串,也可是另一个列表
一个完整的代码块功能需最少元素需包括 name: task
一个name只能包括一个task
YAML文件扩展名通常为yml或yaml
List:列表,其所有元素均使用“-”打头
Dictionary:字典,通常由多个key与value构成
Playbook中的核心元素:
1.Hosts 执行的远程主机列表
2.remote_user: 可用于Host和task中。也可以通过指定其通过sudo的方式在远
程主机上执行任务,其可用于play全局或某任务;此外,甚至可以在sudo时使
用sudo_user指定sudo时切换的用户
3.Tasks 任务集
4.Varniables 内置变量或自定义变量在playbook中调用
5.Templates 模板,可替换模板文件中的变量并实现一些简单逻辑的文件
6.Handlers 和notity结合使用,由特定条件触发的操作,满足条件方才执行,否
则不执行
7.tags 标签 指定某条任务执行,用于选择运行playbook中的部分代码。ansible
具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其
确实没有发生变化的时间依然会非常地长。此时,如果确信其没有变化,就可
以通过tags跳过此些代码片断
8.handlers和notify
运行playbook
运行playbook的方式
ansible-playbook <filename.yml> ... [options]
常见选项
-C|--check 只检测可能会发生的改变,但不真正执行操作,建议执行前先检测
--list-hosts 列出运行任务的主机
--limit 主机列表 只针对主机列表中的主机执行
-v 显示过程 -vv -vvv 更详细
备注:
执行前建议 ansible-plsybook -C install_httpd.yml检查语法错误
ansible-playbook install_httpd.yml --list-hosts可以查看对哪些主机执行
执行playbook时,更改正确的是绿色的,更改的显示黄色的,错误信息显示红色,可以根据颜色变化判断是否更改,或者是否更改成功了。
示例:以下实验均在centos7管理centos7集群,因为6&7配置文件不同,均在7上实验
将centos7的httpd.conf复制到centos7主机,6上的配置文件不同
示例1:写一个安装启动httpd的playbook:install_httpd.yml
包括创建用户,安装httpd包,开启服务,并设置开机启动
- hosts: all
remote_user: root
tasks:
- name: creat user
user: name=httpd shell=/sbin/nologin uid=1234 home=/data/httpd
- name: copy config
copy: src=/data/httpd.conf dest=/etc/httpd/conf/httpd.conf
- name: install package
yum: name=httpd
- name: service
service: name=httpd state=started enabled=yes
备注:
执行完通过以下命令判断每个任务都否都执行成功了
1.ansible all -a 'getent passwd httpd'
2.ansible all -a 'rpm -q httpd'
3..ansible all -a 'ss -ntlp|grep 80'
示例2:写一个删除上面的playbook:remove_httpd.yml
包括:删除用户,卸载httpd包
- hosts: all
remote_user: root
tasks:
- name: del user
user: name=httpd state=absent remove=yes
- name: remove package
yum: name=httpd state=absent
备注:
如果只删除特定主机的httpd,而不是全部,需要加--limit选项
ansible-playbook --limit 192.168.34.105 remove_httpd.yml
只限制在192.168.34.105的主机执行
上面的playbook只是实现了简单的安装配置功能,但是不能根据在更改配置文件后,再次执行,因为服务设置是start,不合理,所以要用到下面触发条件,来达到更改控制的目的。
handlers和notify结合使用触发条件:当达到某个条件时,触发执行对应的task任务。
Handlers:
是task列表,这些task与前述的task并没有本质上的不同,用于当关注的资源发生
变化时,才会采取一定的操作
Notify:
此action可用于在每个play的最后被触发,这样可避免多次有改变发生
时每次都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作。
在notify中列出的操作称为handler,也即notify中调用handler中定义的操作
示例:
示例3:将memcached的配置文件的端口更改后再复制到各主机上,服务需要重启,则用到了handlers和notify功能 (端口11211改成11200)
- hosts: all
remote_user: root
tasks:
- name: creat user
user: name=memcached shell=/sbin/nologin uid=2345
- name: install package
yum: name=memcached
- name: copy config
copy: src=/data/memcached dest=/etc/sysconfig/memcached
notify: restart service 和handlers名称一致
- name: service
service: name=memcached state=started enabled=yes
handlers:
- name: restart service 和notify名称一致
service: name=memcached state=restarted
备注:停止并删除用户和安装包
ansible all -a 'service memcached stop'
ansible all -a 'ss -ntl'
ansible all -a 'rpm -q memcached'
ansible all -a 'getent passwd memcached'
可以多个notify对应一个handlers,也可以多个motify对应多个handlers
示例4:多个notify对应一个handlers
- hosts: websrvs
remote_user: root
tasks:
- name: Install httpd
yum: name=httpd state=present
- name: Install configure file
copy: src=files/httpd.conf dest=/etc/httpd/conf/
notify: restart httpd 第一个notify
- name: ensure apache is running
service: name=httpd state=started enabled=yes
notify: restart httpd 第二个notify
handlers:
- name: restart httpd 对应一个handlers
service: name=httpd status=restarted
示例5:多个notify对应多个handlers
- hosts: websrvs
remote_user: root
tasks:
- name: config
copy: src=/root/config.txt dest=/etc/nginx/nginx.conf
notify:
- Restart Nginx
- Check Nginx Process 多个notify的写法
handlers:
- name: Restart Nginx 对应写多个handlers
service: name=nginx state=restarted enabled=yes
- name: Check Nginx process
shell: killall -0 nginx > /tmp/nginx.log
tags的用法:作用:挑选某一段的task来执行
将安装memcached的yml,在拷贝的动作后加一个标签,执行时指定标签运行
然后执行:ansible-plsybook -t ceshi install_memcached.yml
只会触发拷贝文件和handlers的动作
---
#test yaml file
- hosts: all
remote_user: root
tasks:
- name: creat user
user: name=memcached shell=/sbin/nologin uid=2345
- name: install package
yum: name=memcached
- name: copy config
copy: src=/data/memcached dest=/etc/sysconfig/memcached
notify: restart service 和handlers名称一致
tags: ceshi 对拷贝动作加一个标签
- name: service
service: name=memcached state=started enabled=yes
handlers:
- name: restart service 和notify名称一致
service: name=memcached state=restarted
Playbook中变量使用:可以多出定义,但是存在优先级
优先级的顺序为:-e var > yaml中的var > hosts中的普通变量 > hosts公共变量
变量名:仅能由字母、数字和下划线组成,且只能以字母开头
变量来源:
1 ansible setup facts 远程主机的所有变量都可直接调用
setup是一个模块,收集所有主机的各种信息,如果要用变量,需要先在里面找出对应的
代码块,然后用代码块当变量
比如:ansible all -m setup | grep "version" 过滤和版本有关的
ansible all -m setup | grep "name" 过滤和主机名有关的
2 在/etc/ansible/hosts中定义
普通变量:主机组中主机单独定义,优先级高于公共变量
公共(组)变量:针对主机组中所有主机定义统一变量
3 通过命令行指定变量,优先级最高
可以对单个变量赋值:ansible-playbook –e varname=value
也可以对多个变量赋值:ansible-playbook –e "var1=1 var2=2"
4 在playbook中定义
vars:
- var1: value1
- var2: value2
5 在独立的变量YAML文件中定义,即roles下的var目录下的var.yml文件
很适合在roles中进行单独定义
6 在role中定义(下文中有介绍)
从setup模块中查找到的有用的变量;可以通过判断变量的值,然后执行不同的操作,类似于shell中,先判断version==7?然后再执行不同的命令
先列出setup中几个有用的变量,然后在plsybook中执行不同操作
ansible_fqdn 主机名的变量
ansible_hostname 主机名
ansible_distribution_major_version: "6" 版本名变量
ansible_processor_vcpus 虚拟cpu个数变量
ansible_memtotal_mb 内存的变量
示例:
ansible all -m setup -a "filter=ansible_memtotal_mb"
用此命令来查看系统内变量的值
调用不同变量来源的示例:得出变量的优先级顺序
示例1:调用setup中的ansible_hostname主机名变量,来生成对应文件 var.yml
- hosts: all
remote_user: root
tasks:
- name: touch file
file: name=/data/{{ ansible_hostname }}.log state=touch
示例2:将变量定义在/etc/ansible/hosts中(濮普通变量和公共变量),然后调用变量
/etc/ansible/hosts:中定义的变量:
[websrvs]
192.168.34.105 port1=80
192.168.34.106 port1=90 -普通变量
[websrvs:vars] -公共组变量
mark="-"
[appsrvs]
192.168.34.101 port1=100
[appsrvs:vars]
mark="="
vars.yml中书写格式:
- hosts: all
remote_user: root
tasks:
- name: touch file
file: name=/data/app{{mark}}{{ port1 }}.log state=touch
最后生成的文件为:
app=100.log,app-80.logapp-90.log
示例3:在示例1的基础上,再通过命令行中定义变量:
在外部定义ansible_hostname="hahaha",对比示例1的执行结果:
ansible-playbook -e ansible_hostname="hahaha" vars.yml
可以看出,最后新建的文件名为hahaha.log
示例4:在playbook中定义变量
- hosts: all
remote_user: root
vars:
- port1: 200
- mark: +++
tasks:
- name: touch file
file: name=/data/app{{mark}}{{ port1 }}.log state=touch
生成的文件:
app+++200.log
示例5:先写在var.yml中定义变量,
1.先准备cat vars.yml:文件内容格式
var1: httpd
var2: nginx
2.在cat var.yml,中调用准备好的vars.yml文件这种方式适用于在roles中单独定义
- hosts: web
remote_user: root
vars_files:
- vars.yml
tasks:
- name: create httpd log
file: name=/app/{{ var1 }}.log state=touch
- name: create nginx log
file: name=/app/{{ var2 }}.log state=touch
模板templates,作用:
文本文件,嵌套有脚本(使用模板编程语言编写)
Jinja2语言,使用字面量,有下面形式
字符串:使用单引号或双引号
数字:整数,浮点数
列表:[item1, item2, ...]
元组:(item1, item2, ...)
字典:{key1:value1, key2:value2, ...}
布尔型:true/false
算术运算:+, -, *, /, //, %, **
比较操作:==, !=, >, >=, <, <=
逻辑运算:and, or, not
流表达式:For If When
templates功能:根据模块文件动态生成对应的配置文件
templates文件必须存放于templates目录下,且命名为 .j2 结尾,而*.yml是和templates同一层目录。
yaml/yml 文件需和templates目录平级,目录结构如下:
./
├── temnginx.yml
└── templates
└── nginx.conf.j2
示例1:通过templates模板配置文件nginx,安装nginx
1.先生成nginx.conf.j2模板
cp /etc/nginx/nginx.conf templates/nginx.conf.j2
2.创建playbook
- hosts: all
remote_user: root
tasks:
- name: inastll nginx
yum: name=nginx
- name: template
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
notify: service
- name: start service
service: name=nginx state=started
handlers:
- name: service
service: name=nginx state=restarted
when配合templates实现根据不同版本执行不同的功能
条件测试:
如果需要根据变量、facts或此前任务的执行结果来做为某task执行与
否的前提时要用到条件测试,通过when语句实现,在task中使用,jinja2的语法
格式
when语句
在task后添加when子句即可使用条件测试;when语句支持Jinja2表达式语法
示例:
tasks:
- name: "shutdown RedHat flavored systems"
command: /sbin/shutdown -h now
when: ansible_os_family == "RedHat" 非赋值,而是比较是否为某个值
示例2:通过templates模板根据不同的centos版本,安装不同的httpd,就用到了when功能
步骤:涉及到多个notify对应一个handlers,定义端口变量
1.hosts文件配置:修改了4台主机httpd的端口
[centos6]
192.168.34.105 http_port=86
192.168.34.106 http_port=87
192.168.34.101 http_port=88
[centos7]
192.168.34.107 http_port=89
2.将centos6¢os7的httpd配置文件复制到templates/并改名为*.j2文件
httpd_6.conf.j2
httpd_7.conf.j2
3.将端口都自定义:修改httpd_6.conf.j2和httpd_7.conf.j2的
Listen {{http_port}} 调用hosts列表中的端口变量
4.plsybook如下:
---
- hosts: all
remote_user: root
tasks:
- name: install httpd
yum: name=httpd
- name: templates 6
template: src=httpd_6.conf.j2 dest=/etc/httpd/conf/httpd.conf
notify: restart service
when: ansible_distribution_major_version == "6"
- name: templates 7
template: src=httpd_7.conf.j2 dest=/etc/httpd/conf/httpd.conf
when: ansible_distribution_major_version == "7"
notify: restart service
- name: service
service: name=httpd state=started
handlers:
- name: restart service
service: name=httpd state=restarted
迭代:with_items,类似于shell中的for循环
迭代:当有需要重复性执行的任务时,可以使用迭代机制
对迭代项的引用,固定变量名为”item“
要在task中使用with_items给定要迭代的元素列表
列表格式:
字符串
字典 字典构成一个键值对{key:vavul},如示例3
迭代的示例:
示例1:比如创建user1.user2.user3个用户
- hosts: all
remote_user: root
tasks:
- name: touch users
user: name={{item}}
with_items:
- haha1
- haha2
- haha3
示例2:拷贝3个文件,file1 file2 file3
- hosts: all
remote_user: root
tasks:
- name: copy files
copy: src=/data/playbook/{{item}} dest=/data/
with_items:
- file1
- file2
- file3
迭代嵌套子变量:涉及到多个键值对的表达方式
示例3:创建3个组,再创建3个用户,指定加入一一对应的组
- hosts: all
remote_user: root
tasks:
- name: creat groups
group: name={{item}}
with_items:
- group1
- group2
- group3
- name: creat users
user: name={{item.name}} group={{item.group}}
with_items:
- { name: 'haha1', group: 'group1' }
- { name: 'haha2', group: 'group2' }
- { name: 'haha3', group: 'group3' }
备注:注意创建用户时,键值对的表达和使用方法
上面的执行结果是:先用单个迭代创建多个组,再通过多个键值对创建用户和组的一一对应关系:即:haha1属于group1;haha2属于group2;haha3属于group3;
Playbook中template结合for循环生成具有重复性的代码段
语法:
for的写法:
{% for vhost in nginx_vhosts %}
server {
listen {{ vhost.listen | default('80 default_server') }}
Playbook中template结合for循环生成具有重复性的代码段
if的写法和表达的意思:如果键值对中的vhost.server_name被定义了,则使用
如果没定义,则不执行接下来的代码:示例2
{% if vhost.server_name is defined %}
server_name {{ vhost.server_name }};
{% endif %}
{% if vhost.root is defined %}
root {{ vhost.root }};
{% endif %}
for和if的示例,帮助理解其要执行语句的含义
示例2:生成listen加不同端口的和fqdn文件,由多个键值对组成
先创建for.j2文件:
{% for i in ports %}
server{
listen {{i.listen}}
name {{i.name}}
root {{i.root}}
}
{% endfor %}
创建playbook:再其中调用for.j2文件
- hosts: all
remote_user: root
vars:
ports:
- web1:
listen: 81
name: www.baidu.com
root: /data/web1
- web2:
listen: 82
name: www.baidu1.com
root: /data/web2
tasks:
- name: test for
template: src=for.j2 dest=/data/for1.conf
效果为:
server{
listen 81
name www.baidu.com
root /data/web1
}
server{
listen 82
name www.baidu1.com
root /data/web2
}
示例2:template配合if的涵义:
在示例1中的playbook中,把name注释掉,即不定义name的值
- web1:
listen: 81
# name: www.baidu.com
root: /data/web1
然后playbook:再调用for.j2文件
{% for i in ports %}
server{
listen {{i.listen}}
{% if i.name is defined%} 表示:如果i.name的值定义了,就用,没定义不用
name {{i.name}}
{% endif %}
root {{i.root}}
}
{% endfor %}
结果:则web1没有name的值,即可以理解if的用法
server{
listen 81
root /data/web1 少了web1的name的值
}
server{
listen 82
name www.baidu1.com
root /data/web2
}
Roles:什么是roles,为什么要用roles?什么场景适合于roles?roles的结构?
ansible重要内容之Roles;playbook的集合和拆分
ansilbe自1.2版本引入的新特性,用于层次性、结构化地组织playbook。roles
能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需
要在playbook中使用include指令即可。简单来讲,roles就是通过分别将变量、
文件、任务、模板及处理器放置于单独的目录中,并可以便捷地include它们的一
种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程
等场景中
复杂场景:建议使用roles,代码复用度高
变更指定主机或主机组
如命名不规范维护和传承成本大
某些功能需多个Playbook,通过Includes即可实现
roles的意义和适用场景:
角色(roles):角色集合
适用场景:如系统内有多台数据库服务器,httpd服务器,nginx服务器,可以事先把
同一类的服务器所需的软件,数据库等写成各自的角色roles,然后就可以批量部署了,
当需要临时增加扩容一台服务器时,就可以使用事先编排好的role来对一台或多台服务器进行部署,从而提高了安装部署的效率。
如系统内会存在如下的各类服务,可以先编排好角色
roles/
├── httpd/
├── memcached/
├── mysql/
└── nginx/
roles的目录结构(一般分成以下目录进行存放一类的文件)
Roles各目录作用:
/roles/project/ :项目名称,有以下子目录
如创建http,memcached,nginx等目录
files/ :存放由copy或script模块等调用的文件
保存需要拷贝的配置文件
templates/:template模块查找所需要模板文件的目录
保存通过template的jinja2模板调用的配置文件
tasks/:定义task,role的基本元素,至少应该包含一个名为main.yml的文件;
其它的文件需要在此文件中通过include进行包含
handlers/:至少应该包含一个名为main.yml的文件;其它的文件需要在此
文件中通过include进行包含
vars/:定义变量,至少应该包含一个名为main.yml的文件;其它的文件需要
在此文件中通过include进行包含,可以单独定义变量的目录
meta/:定义当前角色的特殊设定及其依赖关系,至少应该包含一个名为
main.yml的文件,其它文件需在此文件中通过include进行包含
tasks目录下,组合任务顺序的文件
default/:设定默认变量时使用此目录中的main.yml文件
roles playbook的tags的标签的作用:通过标签可以更灵活的调用playbook的角色.
- hosts: all
remote_user: root
roles:
- {role: httpd,tags: ['httpd','web']}
- {role: memcached,tags: ['memcached','web']}
- {role: nginx,tags: ['nginx','web1']}
playbook调用角色:介绍前文提到的变量来源第六条:来自于roles的变量
方法一:把需要调用的角色写在一个playbook里
- hosts: all
remote_user: root
roles:
- role: httpd
- role: memcached
- role: nginx
弊端:如果要执行次playbook,三个角色都会执行一遍,不灵活
方法二;可以把变量在角色中定义
传递变量给角色
- hosts:
remote_user:
roles:
- mysql
- { role: nginx, username: nginx }
键role用于指定角色名称
后续的k/v用于传递变量给角色
调用角色方法3:还可基于条件测试实现角色调用
方法三:还可基于条件测试实现角色调用
roles:
- { role: nginx, username: nginx, when: ansible_distribution_major_version == ‘7’ }
roles示例:
以httpd&nginxmemcached三个role为例,下面为整个roles的目录结构和调用角色的playbook:role_playbook.yml
roles的目录结构下的httpd&nginx&memcached
roles
├── httpd
│ ├── files
│ │ ├── index_6.html
│ │ └── index_7.html
│ ├── handlers
│ │ └── main.yml
│ ├── tasks
│ │ ├── copyhtml_6.yml
│ │ ├── copyhtml_7.yml
│ │ ├── group.yml
│ │ ├── main.yml
│ │ ├── package.yml
│ │ ├── service.yml
│ │ ├── tempconfig_6.yml
│ │ ├── tempconfig_7.yml
│ │ └── user.yml
│ ├── templates
│ │ ├── httpd_6.conf.j2
│ │ └── httpd_7.conf.j2
│ └── vars
├── memcached
│ ├── files
│ ├── handlers
│ │ └── main.yml
│ ├── tasks
│ │ ├── group.yml
│ │ ├── main.yml
│ │ ├── package.yml
│ │ ├── service.yml
│ │ ├── tempconfig.yml
│ │ └── user.yml
│ ├── templates
│ │ └── memcached.j2
│ └── vars
└── nginx
├── files
│ ├── index_6.html
│ └── index_7.html
├── handlers
│ └── main.yml
├── tasks
│ ├── copyhtml_6.yml
│ ├── copyhtml_7.yml
│ ├── group.yml
│ ├── main.yml
│ ├── package.yml
│ ├── service.yml
│ ├── tempconfig.yml
│ └── user.yml
├── templates
│ └── nginx.conf.j2
└── vars
└── main.yml
调用角色的playbook: roles.yml
可以通过加变量和标签和条件测试调用更灵活的调用各种角色)
vim /data/roles.yml
- hosts: all
remote_user: root
roles:
- {role: httpd,tags: ['httpd','web'],when: ansible_distribution_major_version == "6“}
- {role: memcached,tags: ['memcached','web']}
- {role: nginx,tags: ['nginx','web1']}
比如:
1.ansible-playbook -C -t httpd roles.yml 选择测试安装httpd,检查语法
2.ansible-playbook -t httpd roles.yml 只选择安装httpd
3.ansible-playbook -t nginx roles.yml 只选择安装nginx
4.ansible-playbook -t web roles.yml 安装httpd和memcached
5.ansible-playbook -t web1 roles.yml 只选择安装nginx
下图为每个role的各个文件内容:
图一:参照roles的httpd的目录各个文件内容
图二:参照roles的nginx的目录各个文件内容
涉及到跨角色调用配置文件,避免产生多余的垃圾文件:截图上也有
跨角色调用配置文件写法:
- name: copy index6
copy: src=roles/httpd/files/index_6.html dest=/usr/share/nginx/html/index.html