1、ansible的基本命令格式
ansible
#host 必选项,表示Inventory文件中指定的主机或者主机组,可以为ip、hostname、Iventory中的group组名,还可以使用.*等通配符
#option可选项,常见可选项如下
-m name 或 --module=name : 指定执行使用的模块名
-u username 或 --user=username : 指定远程主机以什么用户执行命令
-s 或 --sudo : 相当于linux中切换到root用户执行命令
-U sudo_username 或 --sudo-user=sudo_username : 表示切换到指定的用户sudo_username执行命令
-b 或 --become : 替换旧版中的-s和--sudo命令
-become-user : 替换旧版中的--sudo-user命令
#旧版
ansible all -m ping -u hadoop #以hadoop用户执行所有主机是否ping得通
ansible all -m ping -u hadoop --sudo #以hadoop用户sudo 切换到root用户执行ping命令
ansible all -m ping -u hadoop --sudo --sudo-user master #以hadoop用户sudo 切换到master用户去执行ping命令
#新版
ansible all -m ping -u hadoop -b #切换至root用户执行ping命令
ansible all -m ping -u hadoop -b --become-user master #以hadoop用户sudo切换到master用户执行ping命令
ansible web1 -m ping #检查web1服务器组中的所有服务器是否都存活
ansible web1 -m copy -a "src=/etc/fstab dest=/tmp/fstab owner=root group=root mode = 644 backup=yes " #复制本地文件到远程
2、ansible-playbook的基本命令格式
ansible-playbook test.yml
#ansible后面跟事先编辑好的playbook.yml文件
其实可以看成将一系列ansible命令按照一定的条件组织好,形成一个命令集,存放到yml文件中,再使用ansible-playbook命令统一批量执行。
3、ansible-galaxy命令格式
#类似于github和pip功能,可以从galaxy中下载和上传roles
(1)ansible-galaxy [init|info|install|list|remove] [--help] [options]
#init:初始化本地的Roles配置,以备上传到galaxy中
#info:列出指定Roles的详细信息
#install:从galax中下载并安装指定的Roles到本地
#list: 列出本地已下载的所有Roles
#remove: 删除已经下载的Roles
(2)--help 显示init、info、install……的具体用法
ansible init --help
usage : ansible-galaxy init [options] role_name
options可选参数如下:
#-f, --force 强制覆盖本地已经存在的Role
#-h, --help 显示帮助信息
#-c, --ignore-certs 忽略SSL授权认证的错误
#-p init_path , --init-path=init_path 设置Role的下载存放地址,默认为当前目录
#--offline , 直接离线安装,不需要在线下载
#-s api_server , --server=api_server , 设置下载服务器的目标地址,默认是http://galaxy.ansible.com
#-v , --verbose , 详细信息模式
#--version , 显示版本号
(3) 案例:
ansible-galaxy --ignore-errors install azavea.git #默认保存在/etc/ansible/roles目录下
4、ansible-pull基本命令格式
ansible-pull [options] [playbook.yml]
通过ansible-pull命令与git、crontab共同使用,可以通过crontab定期拉去指定的git版本到本地,并以指定模式自动运行预先制定好的指令
*/20 * * * * root /usr/local/bin/ansible-pull -o -C 2.1.0 -d /src/www/king-gw/ -i /etc/ansible/hosts - U git://git.kingifa.com/king-gw-ansiblepull >> /var/log/ansible-pull.log 2>&1
5、ansible-doc基本命令格式
ansible-doc [options] [module...]
Ansible模块文档说明,ansible中的每一个模块(ping 就是一个模块)都有详细的介绍
ansible-doc ping #显示ping模块的详细说明
ansible-doc -l #列出所有模块
6、ansible-vault基本命令格式
ansible-vault [create|encrypt|decrypt|edit|rekey|view] [--help] [options] filename
valut:街道,拱顶,保险库 , ansible-vault主要用来加密和解密yml文件,加密后的yml文件里面就是一串乱码,必须解密后才能正常查看
ansible-vault encrypt a.yml #加密文件,
ansible-vault decrypt a.yml #解密文件
7、ansible-console
通过该命令可以直接进入ansible的交互式命令行终端模式,类似于shell命令行,常用于集中处理一批临时命令,复杂程度低于使用ansible-playbooks
提示符:root@all (4)[f:5] #当前用户名@当前所在Inventory中定义的组 组中主机(ip地址)的数量 f:5 表示fork线程数为5
cd web1 #可以切换地址组,
forks 2 #设置线程数
list #列出组中的所有主机ip地址
8、Inventory文件的配置
Inventory文件是用来管理主机的配置文件,其中记录了很多不同组,每个组中我们可以添加不同的主机IP地址,通过该文件我们就可以批量化地管理多台主机了
Inventory文件默认存放路径为/etc/ansible/hosts中,在使用ansible命令是可以通过参数-i 或者 --inventory-file来读取指定的inventory文件
ansible -i /etc/ansible/hosts webs -m ping -u hadoop # 读取指定的Inventory文件
如果系统中只有一个Inventory文件,我们就不需要特别指定,会默认去/etc/ansible/hosts目录中读取。
另外一台主机可以同时属于多个不同的组
(1) 定义主机和组
[websevers] # 定义一个组
192.168.1.80 #组内可以为ip地址,也可以为主机名
web1.magedu.com
web2.mageud.com:2222 #如果目标主机的ssh端口不是默认的22,就需要在主机名或ip地址后面指定SSH端口号
web[10:20].magedu.com #[10:20]通配符代表从10~20之间的所有数字, 这一行包含了11台主机
web[a:f].mageud.com #[a:f]代表从a~f中所有的字母,这一行包含了6台主机
(2)定义主机变量
为单个主机服务器添加特有的配置,直接在对应的主机后面,添加变量
[webservers]
weba.magedu.com http_port=808 maxRequestPerChild=801 #表示这台主机上的http服务的端口不是默认的8080,而是808 ,以及最大链接数为801个
(3)定义组变量
为某一个组中所有的主机赋予统一变量
[webservers]
weba.magedu.com
webb.magedu.com
webc.magedu.com
[webservers:vars] #给webservers组定义主变量
ntp_server=ntp.magedu.com #将webservers组中的所有主机ntp_sserver的值为ntp.magedu.com
nfs_server=nfs.magedu.com #将webservers组中的所有主机nfs_sserver的值为nfs.magedu.com
(4) 组中还可以嵌套组
Inventory中,组还可以包含其他组,并且也可以向组中的主机指定变量。
(5)多重变量定义
变量除了可以在Inventory中定义,还以独立于Inventory文件之外单独到存在yaml格式的配置文件中。
9、正则表达式
在使用ansible命令,指定作用组或者单个主机时可以使用正则表达式
ansible webservers -m service -a "name=httpd status=restarted" #重启webservers组中所有主机的httpd服务
ansible all -m ping #检查所有主机是否存活
ansible "*" -m ping #all和*号的功能相同,但是*需要用""号引起来
ansible 192.168.1.* -m ping #检查192.168.1.0/24网络的所有主机是否存活
ansible web1:web2 -m ping #同时检查web1和web2两个组的所有主机是否存活,并集,同时对多个主机或多个组执行命令,用":"冒号分割
ansible web1:!web2 -m ping #表示表示在web1组中但是不在web2中的所有主机执行命令, 差集
ansible web1:&web2 -m ping #即在web1组也在web2组中的主机,交集
ansbile *.magedu.com -m ping #对所有以.magedu.com结尾的主机执行命令
ansible one*.com:webservers -m ping #对所有以one开头以com结尾的主机,与webservers组取并集
ansible webservers[0:1] -m ping #根据下标取组中对应的主机
ansible webservers[-1] -m ping #取组中倒数第一个主机
ansible webservers[1:] -m ping #取组中第2个到到最后一个主机
ansible "~(beta|web|green)\.example\.(com|org)" -m ping #支持正则表达式,正则表达式以~开头
ansible "~192\.168\.[0-9]{\2}.[0-9]\2{,}" -m ping #检测Inventory中所有以192.168开头的服务器是否存活
10、ansible命令详解Ad-Hoc命令集
ansible命令执行的完整流程:
ansible webservers -s -m command -a "hostname" -vvv #以root用户在每台主机上执行hostname命令,返回webservers组中的每台主机的名字,并显示详细的执行过程。
(1)首先当前主机与远程主机建立SSH链接,
(2)然后在远程主机的$HOME/.ansible/tmp/目录下建立临时文件夹用来存放远程执行脚本,
(3)将/tmp/目录下的临时脚本移动到$HOME/.ansible/tmp/ansible-tmp-数字/command Python脚本中,
(4)切换成root用户,执行python脚本,并返回结果
(4)然后再删除临时目录$HOME/.ansible/tmp/ansible-tmp-数字 。
(2)ansible 10.21.40.61 -B 5 -P 2 -T 2 -m command -a "sleep 20" -u root
对服务器10.21.40.61以root用户执行sleep 20 ,执行最大连接超时时长为2s,设置为后台模式执行命令,没隔2s输出一次进度,如果5s还没有执行完毕就终止改任务
ansible命令的其他options可选项
-B num ,--backgroud=num 后台执行命令,超过num秒任务没有执行完毕就自动终止
-P num ,--poll=num 定期返回后台任务的进度,每隔num秒返回一次任务进度
-T sec ,--timeout=sec 指定远程链接最长超时时间
-u name,--user=name 指定远程主机以name用户执行命令
-k , --ask-pass SSH 认证密码
-K , --ask-sudo-pass sudo 用户密码 (--sudo时使用)
-s , --sudo 切换成root用户执行命令
-a "arguments", --args "arguments" 执行命令command模块的参数
-m name , --module-name=name 指定执行使用的模块
-t directory , -tree=directory 输出信息至directory目录下,结果文件以远程主机的主机名命名
-f num , --forks=num 指定ansible命令执行的并发线程数,默认为5
-l subset ,--limit=subset 限定运行命令的主机,只有limit指定的主机才会执行命令
(3)ansible web1 -m command -a "df -lh"
ansible web1 -a "df -lh" #默认使用command模块,查看web1组中的所有主机的磁盘使用情况
ansible web1 -m shell -a "free -m" #使用shell模块批量查看web1组中所有主机内存使用情况
ansible apps -m yum -a "name=redhat-lsb state=present" #为apps组中所有主机安装redhat-lsb 用来查看每台主机的系统版本号
ansible apps -m command -a "lsb-release -a"
ansible apps -m yum -a "name=ntp state=present" #为appls组中所有主机按照ntp服务并设置为开机自启动
ansible apps -m command -a "name=ntpd state=started enable=yes"
11、Ad-Hoc组管理和特点主机变更
架构规划:前端Proxy 、 Web servers 和后端的数据库DB。
[proxy]
192.168.37.159
[app]
192.168.37.130
192.168.37.160
[nosql]
192.168.37.142
[db]
192.168.37.142
(0)构建简单的web服务架构
proxy组:安装Nginx服务用来转发用户的各种请求到后端的WebServers响应
app组: 安装Nginx+PHP+Django服务,用来响应用户的request请求
nosql组:安装redis服务,用来缓冲查询数据库的压力
db组: 安装MariaDB服务,查询数据库返回结果
(1)首先给proxy组安装Nginx服务,并检查服务是否安装成功
ansible proxy -m yum -a "name=nginx state=present" #state=present表示新建
ansible proxy -m command -a "nginx -v"
(2)然后Web Servers组安庄Nginx、PHP、Django服务
ansible app -m yum -a "name=nginx state=present" #安装nginx、php服务
ansible app -m yum -a "name=php state=present"
ansible app -m yum -a "name=MySQL-python state=present" #安装MySql-python 和Python-setuptools依赖包
ansible app -m yum -a "name=python-setuptools state=present"
ansible app -m pip -a "name=django start=present" #使用pip安装django服务,django依赖Python 2.7.0+版本
ansible app -m command -a "python -c 'import django; print django.get_version()'" #检查django是否安装成功
(3)最后配置后端Nosql和Database服务
ansible nosql -m yum -a "name=redis state=present"
ansible nosql -m command -a "redic-cli --version"
安装MariaDB(继Mysql后又一大流行数据库)
添加yum源,修改/etc/yum.repos.d/mariadb.repo添加内容
[mariadb]
name=MariaDB
baseurl=http://yum.mariadb.org/10.1/centos6-x86
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1
ansible db -m yum -a "name=MariaDB-Server state=present" #安装MariaDB-Server服务
ansible db -m yum -a "name=MariaDB-client state=present" #安装MariaDB-Client服务
ansible db -m command -a "iptables -A INPUT -s 192.168.37.0/24 -p tcp -m tcp --dport 3306 -j ACCEPT" #开启防火墙3306端口
(4)Ad-Hoc限定主机执行命令
ansible app -m command -a "service ntpd start " --limit "192.168.37.158" #只启动app组中192.168.37.158这台服务器的ntpd服务
ansible 192.168.37.158 -m command -a "service ntpd start"
ansible "192.168.37.158:192.168.37.161" -m command -a "service ntpd start" #指定多台主机执行命令,用冒号分割,需要用引号将所有地址引起来
ansible 192.168.37.* -m command -a "service ntpd start" #指定多台主机变更
12、ansible管理系统用户
(1)linux用户管理
批量新增用户;新增用户dba , 使用bash shell, 附加组为admins,dbagroup ,家目录为/home/dba/
ansible db -m user -a "name=dba shell=/bin/bash groups=admins,dbagroup append=yes home=/home/dba/ state=present"
user模块的属性
name 用户名
shell 设置用户shell
groups 设置用户附加组群,使用逗号分隔多个群组,如果参数为空,即groups="" ,则删除用户所有附加组
append 当为yes表示增量添加group,即用户附加组群变多了,当为no时全量变更,抛弃原来的组群,只设置为groups属性中的组
state 为present时新建用户 , 为absent时删除用户
remove 结合state=absent使用,删除用户相当于userdel --remove
home 设置用户的家目录
expires 设置用户过期时间
password 设置用户密码,后面跟的密码必须是加密过后的密码
update_pssword 当为always:只有密码不同才会更新密码,当为on_create 只为新用户设置密码
(2)修改用户属组,将用户dba的所属组质变为dbagroup,删除admins组权限
ansible db -m user -a "name=bda groups=dbagroup append=no"
(3)修改用户属性,将用户dba的过期时间设置为2016/6/1 18:00:00,UNIXTIME=1464775200
ansible db -m user -a "name=dba expires=1464775200"
(4)删除用户,将用户dba删除
ansible db -m user -a "name=dba remove=yes state=absent"
(5)变更用户密码:设置用户tom的密码为redhat123
ansible db -m user -a "name=tom shell=/bin/bash password=EKEVWEJRO123 update_pssword=always"
(6)通过使用mysql_user模块为mysql数据库增加用户xiao,初始密码为xiao123
ansible db -m mysql_user -a "login_host=localhost login_password=root123 login_user=root name=xiao password="xiao123" priv=zabbox.*:ALL state=present"
13、Playbook基础语法
(1)playbook的正式内容:
注:缩进空格和tab不能混用,k/v的值可以同行写也可以换行写,同行使用":"隔开,换行写需要以"-"分隔,一个name对应一个task
创建一个名为hello.yml的文件
--- #必须以三个减号作为首行
- hosts: webservers #定义第一个play1,并指定要执行命令的远程主机组或者单个主机
vars: #定义了两个变量,后期可以调用
http_port: 80
max_client: 200
remote_user: root #设置远程主机以root用户执行命令
tasks: #定义一系列接下来要执行的任务,任务列表
- name: ensure the apache server is the latest version #任务1:确保apache服务器的本班时最新的
yum: name=httpd state=latest # 使用yum模块执行任务,后面是yum模块的参数
- name: write the apache config file #任务2:编辑apache服务器的配置文件
template: src=/srv/httpd.j2 dest=/etc/httpd.conf # 使用template模块
- name: ensure apache is running #任务3:启动apache服务
service: name=httpd state=started # 使service模块启动httpd服务
notify: restart apache #调用并执行定义好的handler中的task
handlers: #定义一个handlers,且本质也是一个task的列表,可以通过notify和任务名来调用集合中的某个task,notiy的task才会执行,没有notify的task不会执行
- name: restart apache server
service: name=httpd state=restart
- name: stop apache server
service: name=httpd state=stop
- hosts: app #定义第二个paly2, 针对app主机组,一个playbook可以包含多个play
remote_user: root
tasks:
- name:"安装apache server"
command: yum install --quite -y httpd httpd-devel
- name: "复制文件"
command:cp /tmp/httpd.conf /etc/httpd/conf/httpd.conf
command: cp /tmp/httpd-vhosts.conf /etc/httpd/conf/httpd-vhosts.conf
- name: "启动Apache,并设置为开机自启动"
command: service httpd start
command: chkconfig httpd on
执行hello.yml文件:
ansible-playbook hello.yml
(2)playbook循环语句:
---
- hosts: all
sudo: yes #远程主机以root用户执行命令
tasks:
- name: "安装Apache server"
yum: name={{item}} state=present
with_items: #wtih_items要与模块名yum左对齐
- httpd
- httpd-devel
- name:"复制配置文件"
copy: src={{item.src}} dest={{item.dest}} owner=root group=root mode=644
with_items: #该命令是将当前主机上的文件远程拷贝到其他机器的指定路径下
- {src:"/tmp/httpd.conf", dest:"/etc/httpd/conf/httpd.conf"} #src表示ansible所在本地服务器上的路径, dest为远程主机的路径
- {src:"/etc/httpd-vhosts.conf", dest:"/etc/httpd/conf/httpd-vhosts.conf"}
- name: "检查Apache运行状态,并设置开机自启动"
service: name=httpd state=started enable=yes
(3)ansible-playbook常用的参数 [options]
--limit 用来限定哪些主机会执行playbook中的命令
--list-hosts 返回在执行playbook时,哪些主机将会受到影响
--remote_user 用来执行远程主机以什么用户执行命令
--ask-sudo-pass 用来传递sudo密码到远程主机,来保证sudo命令可以正常运行,使用--ask-sudo-pass(-K)选项交互式输入sudo密码
--sudo 可以强制所有play都使用sudo用户执行
--sudo-user 可以指定sudo可以执行那个用户的权限
--check 在运行playbook之前,使用该命令--check(-C)来检测playbook都会改变哪些内容,显示的结果跟真正执行时一模一样,但不会真的对被管理的服务器产生实际影响。
--force-handlers 当playbook中某一个task执行时出现了错误,那么ansible会停止所有任务,而且handlers也不会被触发,如果们需要不管是否出现问题都要触发handlers,那么就可以用该选项来强制触发handlers
(4)playbook定义变量,设置Handlers
在playbook中可以创建一个变量文件vars.yml来存放所有需要的变量。
不仅变量可以定义在文件中,Handler、Tasks也可以独立定义在文件中.
---
- hosts: all
vars_files: vars.yml #通过vars_files关键字来引用文件中的变量
pre_task和post_task用来指定在主任务运行之前和之后要运行的任务
例如:在安装其他服务之前,我们需要确保apt缓存始终是最新的,因此我们通过apt模块来更新apt缓存,同时设置有效期为3600s
pre_tasks:
- name: update apt cache if needed
apt: update_cache=yes cache_valid_time=3600
(5)输出打印一行信息:
********************************************
ansible all -m debug -a "msg='hello world'"
ansible all -m debug -a msg=hello -u root
playbook模式
- name: 打印出环境变量
debug: msg=" The variable is {{JAVA_HOME}}"
********************************************
(6)在文件中独立定义变量时,首行时三个减号,变量定义定格写,不需要缩进,
创建vars.yml 文件用来存放变量
---
name: xiaowei
age:12
sex: male
在playbook中通过vars_files: vars.yml 来引用里面的变量
创建hello.yml文件
---
- hosts: all
vars_files: vars.yml
tasks:
- name : 打印信息
debug: msg=" the name is {{name}}, age is {{age}}"
ansible-playbook hello.yml
(7)在Inventory文件中定义变量
Inventory文件默认路径为/etc/ansible/hosts, 可以在主机名的后面或者是组名的下方定义变量,如下:
[shanghai] #为某一台主机单独指定变量
app1.example.com proxy_state=present
app2.example.com proxy_state=present
[shanghai:vars] #为整个主机组指定变量
dns_hosts=static.example.com
version=2.1.0
(8)定义变量的另一种方式
由于ansible在执行命令的时候回默认去/etc/ansible/host_vars/和/etc/ansible/group_vars目录下去读取变量
因此可以在这两个目录下创建于host主机同名的变量定义文件,或者创建与组同名的变量定义文件
如果我们需要给主机app1.example.com定义变量文件,那么就可以到/etc/ansible/host_vars/目录下创建一个名为app1.example.com的文件
在里面以YAML格式定义变量
如果要给shanghai整个组定义变量文件,那么就可以到/etc/ansible/group_vars/目录下创建一个shanghai的空白文件,
在里面以YAML格式定义变量:
---
foo: bar
name: xiaowei
(9)Facts,收集系统信息
在运行任何一个playbook之前,ansible都会去收集playbook指定的主机的信息,这些信息包括:
远程主机CPU信息、IP地址、磁盘空间、网络接口、操作系统信息
这些信息对于运行playbook至关重要,我们可以根据这些信息决定是否要运行playbook,我们也可以将这些信息写入到配置文件中
ansible localhost -m setup >> setup.txt #用setup模块获取对应主机上的所有可用的Facts信息
结果:
localhost | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"192.168.122.128"
],
"ansible_all_ipv6_addresses": [
"fe80::20c:29ff:feff:7eb7"
],
"ansible_apparmor": {
"status": "disabled"
},
"ansible_architecture": "x86_64",
"ansible_bios_date": "05/19/2017",
"ansible_bios_version": "6.00",
"ansible_cmdline": {
"BOOT_IMAGE": "/vmlinuz-3.10.0-123.el7.x86_64",
"LANG": "en_US.UTF-8",
"crashkernel": "auto",
"quiet": true,
"rhgb": true,
"ro": true,
"root": "UUID=b6943379-8c8a-4dbe-af80-b3f2af2d6fa9",
"vconsole.font": "latarcyrheb-sun16",
"vconsole.keymap": "us"
}
常用的Facts变量有: ansible_os_family、ansible_hostname、ansible_memtotal_mb……
14、流程控制if、then、when
(1)flie模块:主要用来
path参数 :必须参数,用于指定要操作的文件或目录,在之前版本的ansible中,使用dest参数或者name参数指定要操作的文件或目录,为了兼容之前的版本,使用dest或name也可以。
state参数 :设置path=/testdir/a/b,但是ansible不知道这个路径是代表一个文件还是一个目录,所以要通过state来指定,state=directory(创建目录)、touch(创建文件)、link(创建软连接)、hard(创建硬链接)、absent(删除文件或目录)
src参数 :当state设置为link或者hard时,表示我们想要创建一个软链或者硬链,所以,我们必须指明软链或硬链链接的哪个文件,通过src参数即可指定链接源。
force参数 : 当state=link的时候,可配合此参数强制创建链接文件,当force=yes时,表示强制创建链接文件。不过强制创建链接文件分为三种情况。情况一:当要创建的链接文件指向的源文件并不存在时,使用此参数,可以先强制创建出链接文件。情况二:当要创建链接文件的目录中已经存在与链接文件同名的文件时,将force设置为yes,会将同名文件覆盖为链接文件,相当于删除同名文件,创建链接文件。情况三:当要创建链接文件的目录中已经存在与链接文件同名的文件,并且链接文件指向的源文件也不存在,这时会强制替换同名文件为链接文件。
owner参数 :用于指定被操作文件的属主,属主对应的用户必须在远程主机中存在,否则会报错。
group参数 :用于指定被操作文件的属组,属组对应的组必须在远程主机中存在,否则会报错。
mode参数 :用于指定被操作文件的权限,比如,如果想要将文件权限设置为”rw-r-x---“,则可以使用mode=650进行设置,或者使用mode=0650,效果也是相同的。如果想要设置特殊权限,比如为二进制文件设置suid,则可以使用mode=4700。
recurse参数 :当要操作的文件为目录,将recurse设置为yes,可以递归的修改目录中文件的属性
- name: 创建文件
file: path=/home/hadoop/words.txt state=touch owner=hadoop group=hadoop mode=0650
(2)when条件判断
ansible在进行条件判断时会使用到一些Jinja2的语法、以及Python的一些内置函数
很多任务只有在特定条件下执行,这就需要用到when条件表达式了
还以通过注册器保存命令运行的结果,并对其进行判断
---
- hosts: all
tasks:
- name: 只为数据库服务器安装mysql
yum: name=mysql-server state=present
when: ({{is_db_server}} is defined) and {{is_db_server}} #只在一个服务器上设置一个is_db_server的布尔值变量,用来表示这是一台数据库服务器
- name: 当软件主版本号为4才更新软件
yum: name=redis state=present
when: {{redis_version}}.split(".")[0]=='4'
- name: 查看一个应用的运行状态,
command: appname --state
register: appstate_result #定义一个注册变量,将该task的任务执行的结果放到这个注册变量appstate_result中
- name: 根据上app软件运行的状态,决定是否要执行本task
command: do something else as you like
when: "ready" in appstate_result.stdout #只有当上一个task的执行结果中包含有ready时才会执行当前命令
- name: 如果当前PHP的版本号为7.0,就执行PHP降级任务
shell: php --version
register: php_version_result
- name: PHP降级
shell: yum -y downgrade php*
when: '7.0' in php_version_result.stdout
- name: 如果远程主机中没有host文件,就远程拷贝一个过去
stat: path=/etc/hosts
register: host_file_result
- name: 拷贝host文件
copy: src=/path/to/local/hosts_file dest=/path/to/remote/hosts_file
when: host_file_result.stat.exists =- false
(3)changed_when 、failed_when条件判断
#使用PHP composer来安装项目依赖,无论是否安装或升级的某些软件,ansible任务返回的结果都会是changed,表示主机已经改变。
#所以我们需要通过changed_when语句来设置,只有当软件被安装成功了或升级成功了,任务才会返回changed
---
- hosts: all
tasks:
- name: isntasll dependencies via composer
cammand: /user/local/bin/composer global require phpunit/phpunit --prefer-dist
register: composer_result
changed_when: "Nothing to install or update" not in composer_result.stdout #只有当满足这个条件时,才通知Ansible显示主机Changed
- name: 通过CLI导入Jenkins任务
shell: java -jar /opt/jenkins-cli.jar -s htttp://localhost:8080/create-job "my job"
register: import_result
failed_when: import_result and "already exsits" not in import_result #只有当满足这个条件时,才通知Ansible显示任务执行失败
- name: 忽略错误
command: do something as will
ignore_errors: true #不管这个任务是否会报错,都算它执行成功
(4)delegate_to 任务委托
在执行任务的时候,如果对于某一个task,我们只想它在某一台服务器上运行,而不是所有的服务器都运行,这时候就需要用到delegate_to了
---
- hosts: webservers
tasks:
- name: remove server form load balancer
command: remove-from-lb
delegate_to: 127.0.0.1 #只在本地主机上执行这个task,其他主机上都不执行
- name: remove server form load balancer
local_action: command remove-from-lb # local_action 与 delegate_to等价
(5) wait_for 任务暂停
---
- hosts: all
task:
- name: wait for webserver to start #等待web1服务器的80端口打开后,才执行本task
local_action:
module: wait_for
host: web1
port: 80
delay: 10
timeout: 300
state: started
该任务会每个10s检查一下web1服务器上的80端口是否开启,如果超过300s还没有开启就返回失败信息
(6)tags标签
可以给某一个task、某一个role、某一个play、或者整个playbook都打上标签,然后再执行的时候,使用--tags选项来指定执行哪些task,用--skip-tags来指定不执行哪些tasks
ansible-playbook hello.yml --tags "helloworld"
ansible-playbook hello.yml --skip-tags "helloworld"
案例:
---
- hosts: all
tags: hello
roles:
- role: tomcat
- tags: [tomcat , app] #第一种添加tags的方式,用一个列表将所有tags包含在里面
tasks:
- name: notif on completion
local_action:
module: osx_say
msg: hi,nihao
voice: zarvox
tags: #第二种添加tags的方式,换行用"-"分隔tags
- notification
- say
(7)block块
block块将一系列的task形成一个整体,可以对这个整体执行异常处理语句
---
- hosts: all
tasks:
# install and configure apache on redhat/centos hosts
- block: #把三个task合并成一个整体,如果操作系统是redhat,就执行这些task,而不用逐个判断
- yum: name=httpd state=present
- template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
- service: name=httpd state=started enable=yes
when: {{ansible_os_family}} == "Redhat"
sudo: yes
# install and configure apache on debian/ubuntu hosts
- block:
- apt: name=apache2 state=present
- template: src=htttpd.conf.j2 dest=/etc/apache2/apache.conf
- service: name=apache2 state=started enable=yes
when: {{ansible_os_family}} == "Debian"
sudo: yes
block块中异常处理:
tasks:
- block:
- name: shell script to connect the app to a monitoring service
script: monitoring-connect.sh
rescue:
- name: 只有脚本运行出错时,才执行rescue中的语句
debug: msg="there was a error in this block"
always:
- name: 无论脚本执行结果如何,都要执行always中的语句
debug: msg="this always executes"
#当块中的任意代码出了问题就会执行rescue中的语句,相当于java中的try catch语句,而always相当于finally语句
15、Playbook的高级技巧使用
(1)copy模块的使用:
copy模块实现复制本地文件到远程主机,copy模块包含如下选项:
backup: 在覆盖之前将原文件备份,备份文件包含时间信息。有两个选项:yes|no
content: 用于替代"src",可以直接设定指定文件的值
dest: 必选项。要将源文件复制到的远程主机的绝对路径,如果源文件是一个目录,那么该路径也必须是个目录
directory_mode:递归的设定目录的权限,默认为系统默认权限
force: 如果目标主机包含该文件,但内容不同,如果设置为yes,则强制覆盖,如果为no,则只有当目标主机的目标位置不存在该文件时,才复制。默认为yes
others: 所有的file模块里的选项都可以在这里使用
src: 要复制到远程主机的文件在本地的地址,可以是绝对路径,也可以是相对路径。如果路径是一个目录,它将递归复制。在这种情况下,如果路径使用"/"来结尾,则只复制目录里的内容,如果没有使用"/"来结尾,则包含目录在内的整个内容全部复制,类似于rsync。
ansible web1 -m copy -a "src=/etc/ansible/script.sh dest=/tmp/ owner=appuser group=appuser mode=0755"
###复制本地脚本到远程主机server6下并定义用户和组以及权限755
(2)include用法:
创建一个 install_MysqlAndPhp.yml文件 ,用来存放公共执行模块
install_MysqlAndPhp.yml:
--- # 这个yml文件可以看做是一个task任务列表,专门用来安装msyql和php
- yum: name=mysql state=present
- yum: name=php-fpm state=present
再创建一个install_lamp.yml文件,通过include语句来调用install_MysqlAndPhp.yml文件中的内容
---
- host: all
remote_user: root
gather_facts: no
tasks: # 在tasks关键字中使用include,
- include: install_MysqlAndPhp.yml # include语句可以看做是一个task,所以与任务install_httpd左对齐
- name: install_httpd
yum: name=httpd state=present
在handlers关键字中使用include
创建test_include.yml文件
---
- hosts: all
remote_user: root
gather_facts: no
tasks:
- name: create_file
file: path=/opt/tmp state=touch
notify: test_include_module #handlers中的任务,要被tasks中的任务调用,所以notify语句要与file模块左对齐,由create_file这个task去notify在handlers中的test_include_moudle这个任务
handlers: # handlers 也可以看做是一种任务列表,所以与tasks左对齐
- name: test_include_module
include: include.yml #在handlers关键字中调用include语句
创建include.yml
---
- debug: msg="hello world"
- debug: msg="hello world2"
- debug: msg="hello world3"
(3)Roles角色:
roles的默认目录可以在/etc/ansible/ansible.cfg配置文件中找到
roles_path = /etc/ansible/roles/
roles目录下用来存放各个角色,每一个角色对应个子文件夹,
而每个角色文件夹中又包含:files、templates、tasks、handlers、vars、defaults、meta (7个子文件夹)
files/ :存放由copy或script模块等调用的文件;
templates/ :template模块查找所需要模板文件的目录;
tasks/ :至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含,所有包含在其中的任务将会被执行;
handlers/ :至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含,所有包含在其中的handlers将会被执行;
vars/ :至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含,所有包含在其中的变量将在roles中生效;
meta/ :至少应该包含一个名为main.yml的文件,定义当前角色的特殊设定及其依赖关系;其它的文件需要在此文件中通过include进行包含;注意,角色和角色之间有依赖关系,如安装NT,先装nginx后装tomcat,一般不需定义,执行我们自己定义好安装顺序即可
default/ :设定默认变量时使用此目录中的main.yml文件;
(4)案例:目录结构如下:
myfile.yml
myapache.yml
roles
|---- apache
| |---- handlers
| | |---- main.yml
| |---- tasks
| |---- main.yml
| |---- restart.yml
|---- example
|---- files
| |---- Magedu.ppt
| |---- Stanley.ppt
|
|---- tasks
|---- main.yml
|---- file.yml
在roles目录下有两个子目录:apache和example分别对于两个role
案例一:更新webservers组中的httpd服务的配置文件,然后重启服务
1)编辑/roles/apache/handlers/main.yml:
---
- name: restart_apache
service: name=apache state=start
2)编辑/roles/apache/tasks/restart.yml
---
- name: transfer apache config file
file: src=httpd.conf dest=/opt/apache/httpd.conf #更新httpd服务的配置文件,然后再重启httpd服务
notify: restart_apache #调用handlers中写好的重启apache httpd服务的任务
3)编辑/roles/apache/tasks/main.yml
---
- include: restart.yml
4)编辑与roles目录统计的myapahce.yml
---
- hosts: webservers
remote_user: root
roles:
- role: apache #所有task、handlers全部都被分解到roles下各个目录的文件中
5)执行apache.yml文件
ansible-playbook myapahce.yml
案例二:files文件传输
1)编辑与roles目录同级的myfile.yml文件
---
- hosts: 192.168.122.128
remote_user: root
gather_facts: no
roles:
- role: example
2)编辑roles/example/task/file.yml
---
- name: file change example
copy: path={{item.src}} dest={{item.dest}} owner=hadoop group=hadoop
with_items:
- src:Magedu.ppt #由于Magedu.ppt和Stanley.ppt这两个文件存放在roles/files目录,因此传输时只需要指定相对files目录的路径既可,规范用户了存放文件的位置。
dest:/opt/tmp/magedu.ppt
- src:Stanley.ppt
dest:/opt/tmp/Stanley.ppt
3)编辑roles/example/task/main.yml
---
- include file.yml
4)执行与roles同级file.yml
ansible-playbook myfile.yml #注:这个被执行myfile.yml文件的名字是什么,位置在哪里可以任意指定