Ansible学习总结
一、简介
Ansible是一个自动化运维的工具
基于python语言编写,因此机器需要具备python环境。
通过ssh的连接方式进行自动化部署,ansible优先使用OpenSSH,在使用python模块里的paramiko作为SSH工具
二、优缺点
2.1 优点:
1.入门快速,简单上手
2.基于Python语言
3.无代理(基于ssh,无需安装客户端,如zabbix的客户端要安装agent)
4.可读性强(采用YAML格式)
2.2 缺点:
1.对Windows系统的排斥(服务端无法安装在windows)
2.运行效率较低(task任务是串行运行;多台设备同时运行一个task,有并发数限制)
三、安装
安装的是基于Python2.7的Ansible
3.1 在Ubuntu上的安装
#1.增加PPA源,并安装Ansible
sudo apt-get unpdate
sudo apt-get install software-properties-common
sudo apt-add-repository --yes --update ppa:ansible/ansible
sudo apt-get install ansible
#2.查看版本,结果无报错
ansible --version
3.2 在Centos7上的安装
#1.安装EPEL扩展软件仓库
sudo yum -y install epel-release
#2.安装Ansible
sudo yum -y install ansible
#3. 检查ansible的版本和运行环境
ansible --version
四、框架介绍
4.1 框架图
4.2 各组件功能
ansible.cfg #ansible的配置文件,包含各种Ansible全局性质的参数,可在不同项目下或者不同用户下创建一样的ansible.cfg文件,作为局部配置文件,检索顺序:局部-->全局
inventory #设备列表,当跑脚本时,需要告诉Ansible针对哪些设备或设备组
variable #变量
module #模块,通过其他语言编写而成,能实现某个特定的功能的工具,例如思科配置接口的模块,修改ip地址的模块等等
Jinja2 #模板系统,Ansible可实现批量配置网络设备
Role #角色,一套文件夹,里面定义了例如变量,具体任务task。Role里面定义的内容可以实现某些特殊功能,而你在使用不通的脚本过程中可以导入Role来实现某一个功能。而不用重复写
#以上的组件,会由以下的“客户”来使用
Ad-hoc #即插即用,简易模式,一条命令,一次使用
playbook #剧本,基于YAML文件格式书写,可以包含Ansible任意功能,无论是设备列表,变量,jinja2模板,条件循环,模块等等
五、模块
5.1 常用模块之文件操作
1.远程复制备份模块:copy
模块参数详解:
src: 指定源文件路径
dest: 目标地址(拷贝到哪里)
owner: 指定属主
group: 指定属组
mode: 指定权限,可以以数字指定比如0644
backup: 在覆盖之前将原文件备份,备份文件包含时间信息。有两个选项:yes|no
[root@ansible ~]# vim a.txt #创建一个测试文件
123123
[root@ansible ~]# ansible weball -m copy -a 'src=/root/a.txt dest=/opt owner=root group=root mode=644' -o
[root@ansible ~]# vim a.txt #追加如下内容
123123
234234
[root@ansible ~]# ansible weball -m copy -a 'src=/root/a.txt dest=/opt/ owner=root group=root mode=644 backup=yes' -o
登录被控制机器其中一台查看
[root@ansible-web1 ~]# cat /opt/a.txt
2.文件模块file
模块参数详解:
owner: 修改属主
group: 修改属组
mode: 修改权限
path: 要修改文件的路径
recurse:递归的设置文件的属性,只对目录有效
yes: 表示使用递归设置
state:
touch:创建一个新的空文件
directory:创建一个新的目录,当目录存在时不会进行修改
# 创建一个文件
[root@ansible ~]# ansible webservers1 -m file -a 'path=/tmp/88.txt mode=777 state=touch'
# 创建一个目录
[root@ansible ~]# ansible webservers1 -m file -a 'path=/tmp/99 mode=777 state=directory'
3.blockinfile模块
在文本文件中添加标记或删除标记
模块参数详解:
path: 必须参数,指定要操作的文件
block: 操作的文本
marker:标记
state:有两个可选值present和absent,表示新增block标记或删除block标记
backup: 是否在修改文件前备份文件
create:当操作的文件不存在时,是否创建文件
[root@ansible ~]# ansible all -m blockinfile -a 'path=/testdir/rc.local block="" marker="#{mark} serivce to start" '
4.lineinfile模块
在文本文件中添加行或者替换或删除行
模块参数详解:
path :必须参数,指定要操作的文件
line : 使用此参数指定文本内容
regexp :使用正则表达式匹配对应的行,当替换文本时,如果有多行文本都能被匹配,则只有最后面被匹配到的那行文本才会被替换,当删除文本时,如果有多行文本都能被匹配,这么这些行都会被删除
state:当想要删除对应的文本时,需要将state参数的值设置为absent,absent为缺席之意,表示删除,state的默认值为present
backup:是否在修改文件之前对文件进行备份
create :当要操作的文件并不存在时,是否创建对应的文件
[root@ansible-master playbooks]# ansible all -m lineinfile -a 'path=/testdir/test line="test text"'
5.find模块
远程主机中查找符合条件的文件
模块参数详解:
paths:必须参数,指定在哪个目录查找文件
recurse:是否递归查找文件
hidden:是否查找隐藏文件
file_type:文件类型(any,directory,file,link)
contains:正则表达式查找
[root@ansible-master playbooks]# ansible all -m find -a 'paths=/testdir contains=".*abc.*" '
6.replace模块
指定的正则表达式替换文件中的字符串
模块参数详解:
path:必须参数,指定要操作的文件
regexp:正则表达式
replace:最终要替换的字符串
backup:是否对源文件进行备份
[root@ansible-master playbooks]# ansible all -m replace -a 'path=/testdir/test regexp="ASM" replace=asm'
7.远程拉取fetch模块
模块参数详解:
src: 远程主机文件路径(必须为文件)
dest: 文件保存路径
[root@ansible-master playbooks]# ansible all -m fetch -a "src=/etc/hosts dest=/tmp"
192.168.70.102 | CHANGED => {
"changed": true,
"checksum": "7335999eb54c15c67566186bdfc46f64e0d5a1aa",
"dest": "/tmp/192.168.70.102/etc/hosts",
"md5sum": "54fb6627dbaa37721048e4549db3224d",
"remote_checksum": "7335999eb54c15c67566186bdfc46f64e0d5a1aa",
"remote_md5sum": null
}
192.168.70.101 | CHANGED => {
"changed": true,
"checksum": "7335999eb54c15c67566186bdfc46f64e0d5a1aa",
"dest": "/tmp/192.168.70.101/etc/hosts",
"md5sum": "54fb6627dbaa37721048e4549db3224d",
"remote_checksum": "7335999eb54c15c67566186bdfc46f64e0d5a1aa",
"remote_md5sum": null
}
5.2 常用模块之系统操作
1.用户管理user模块
添加用户并设置密码:
生成加密密码:
[root@ansible ~]# echo '777777' | openssl passwd -1 -stdin
$1$i2prOXuN$D9i18PZSb6IN5pt3lRXEM1
openssl passwd :目的是为了防止密码以明文的形式出现
-1:MD5加密算法
设置密码:
[root@ansible ~]# ansible ansible-web1 -m user -a 'name=qianfeng password="$1$XVzsJMDr$5wI4oUaQ.emxap6s.N272."'
"name= " #如:指定的用户名,要安装的软件
====================================================================
删除用户:
[root@ansible ~]# ansible ansible-web1 -m user -a "name=qianfeng state=absent" -o
absent #删除用户,但是不会删除家目录
2.软件包管理 yum模块
# 安装apache
[root@ansible ~]# ansible webservers1 -m yum -a "name=httpd state=latest" -o
state= #状态是什么,干什么
state=absent 用于remove安装包
state=latest 表示最新的
state=removed 表示卸载
# 卸载软件:
[root@ansible ~]# ansible webservers1 -m yum -a "name=httpd state=removed" -o
3.服务管理service模块
[root@ansible ~]# ansible webservers1 -m service -a "name=httpd state=started" #启动
[root@ansible ~]# ansible webservers1 -m service -a "name=httpd state=stopped" #停止
[root@ansible ~]# ansible webservers1 -m service -a "name=httpd state=restarted" #重启
[root@ansible ~]# ansible webservers1 -m service -a "name=httpd state=started enabled=yes" #开机启动
[root@ansible ~]# ansible webservers1 -m service -a "name=httpd state=started enabled=no" #开机关闭
4.收集信息模块setup
[root@ansible ~]# ansible webservers1 -m setup #收集所有信息
[root@ansible ~]# ansible webservers1 -m setup -a 'filter=ansible_all_ipv4_addresses' #只查询ipv4的地址
filter:过滤
5.cron模块
管理远程主机中的计划任务
模块参数详解:
minute:此参数用于设置计划任务中分钟设定位的值,比如,上述示例1中分钟设定位的值为5,即minute=5,当不使用此参数时,分钟设定位的值默认为”*”
hour:此参数用于设置计划任务中小时设定位的值,比如,上述示例1中小时设定位的值为1,即hour=1,当不使用此参数时,小时设定位的值默认为”*”
day:此参数用于设置计划任务中日设定位的值,当不使用此参数时,日设定位的值默认为”*”
month:此参数用于设置计划任务中月设定位的值,当不使用此参数时,月设定位的值默认为”*”
weekday:此参数用于设置计划任务中周几设定位的值,当不使用此参数时,周几设定位的值默认为”*”
special_time:在上述示例3与示例4中,计划任务的时间设定格式为@reboot或者@hourly,@reboot表示重启时执行,@hourly表示每小时执行一次,相当于设置成”0 * * * *” ,这种@开头的时间设定格式则需要使用special_time参数进行设置,special_time参数的可用值有reboot(重启后)、yearly(每年)、annually(每年,与yearly相同)、monthly(每月)、weekly(每周)、daily(每天)、hourly(每时)
注意:当上述时间单位设定参数都未指定时,计划任务的时间设定默认会被设定为”* * * * *”,这样表示每分钟都会执行一次计划任务,所以,在使用cron模块时,我们应该确定对应的时间参数设置正确。
user参:此参数用于设置当前计划任务属于哪个用户,当不使用此参数时,默认为管理员用户
job:此参数用于指定计划的任务中需要实际执行的命令或者脚本,比如上例中的”echo test”命令。
name参数:此参数用于设置计划任务的名称,计划任务的名称会在注释中显示,当不指定计划任务的名称时,ansible会默认为计划任务加入注释,注释的内容为#Ansible: None,假设指定计划任务的名称为test,那么注释的内容为#Ansible: test,在一台机器中,计划任务的名称应该具有唯一性,方便我们以后根据名称修改或删除计划任务。
state:当计划任务有名称时,我们可以根据名称修改或删除对应的任务,当删除计划任务时,需要将state的值设置为absent
disabled:当计划任务有名称时,我们可以根据名称使对应的任务”失效”(注释掉对应的任务),注意,使用此参数时,除了需要指定任务的名称,还需要同时指定任务的job以及任务的时间设定,而且任务的时间设定必须和对应任务完全相同,否则在注释任务的同时,任务的时间设定会被修改,除非你确定这样做,如果你不明白这段话的意思,可以参考下文中的示例。
backup参数:如果此参数的值设置为yes,那么当修改或者删除对应的计划任务时,会先对计划任务进行备份,然后再对计划任务进行修改或者删除,cron模块会在远程主机的/tmp目录下创建备份文件,以crontab开头并且随机加入一些字符,具体的备份文件名称会在返回信息的backup_file字段中看到,推荐将此此参数设置为yes
[root@ansible ~]# ansible all -m cron -a " name='test crontab' minute=5 hour=1 job='echo test' "
5.3 常用模块之命令相关
1.command模块
执行远程命令
模块参数详解:
chdir: 指定一个目录,执行命令
2.shell模块
远程主机上执行命令,与command模块不同的是,shell模块在远程主机中执行命令时,会经过远程主机上的/bin/sh程序处理
[root@ansible ~]# ansible all -m shell -a "chdir=/testdir echo test > test"
3.script模块
远程主机上执行ansible主机上的脚本
[root@ansible ~]# ansible all -m script -a "chdir=/opt /testdir/atest.sh"
六、 Ansible Playbook
6.1 初识playbook
编写一个最基础的ansible playbook剧本
[root@ansible-master playbooks]# cat test.yml
---
- hosts: all
remote_user: root
tasks:
- name: Ping the hosts
ping:
- name: make dir test
file: path=/testdir/test state=directory
编写完成之后可以使用以下命令检查yaml语法
[root@ansible-master playbooks]# ansible-playbook --syntax-check test.yml
playbook: test.yml
使用一下命令进行模拟执行
[root@ansible-master playbooks]# ansible-playbook --check test.yml
PLAY [all] ****************************************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************************************
ok: [192.168.70.101]
ok: [192.168.70.102]
TASK [Ping the hosts] *****************************************************************************************************************************************************************************
ok: [192.168.70.102]
ok: [192.168.70.101]
TASK [make dir test] ******************************************************************************************************************************************************************************
changed: [192.168.70.101]
changed: [192.168.70.102]
PLAY RECAP ****************************************************************************************************************************************************************************************
192.168.70.101 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.70.102 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
6.2 handlers的用法
当执行一个task的时候,需要修改完配置之后重启服务,就是可以使用handlers
[root@ansible-master playbooks]# cat handlers.yml
---
- hosts: test
remote_user: root
tasks:
- name: task1
file: path=/testdir/testfile
state=touch
notify: handler group1
handlers:
- name: handler1
listen: handler group1
file: path=/testdir/ht1
state=touch
- name: handler2
listen: handler group1
file: path=/testdir/ht2
state=touch
6.3 tags的用法
tags可以对任务进行打标签
的操作,当任务存在标签以后,就可以在执行playbook时,借助标签,指定执行哪些任务,或者指定不执行哪些任务了
[root@ansible-master playbooks]# cat tags.yml
---
- hosts: test
remote_user: root
tasks:
- name: task1
file:
path: /testdir/t1
state: touch
tags: t1
- name: task2
file: path=/testdir/t2
state=touch
tags: t2
- name: task3
file: path=/testdir/t3
state=touch
tags: t3
如上例所示,上例的play中有3个task,每个task都有对应的tags,为了方便示例,只是简单的把tags的值写成了t1、t2、t3,在实际的使用中,应该让tags的值能够见名知义,现在每个task都有了标签,假如在执行上述playbook时,只想执行task2,该怎样执行呢?可以使用如下命令
ansible-playbook --tags=t2 tags.yml
使用–tags选项指定某个标签,当指定标签后,只有标签对应的任务会被执行,其他任务都不会被执行,执行上述命令后,只有task2会执行,因为task2的标签值为t2,task1和task3都不会执行,这样就达到了只执行playbook中部分任务的目的
借助标签,除了能够指定”需要执行的任务”,还能够指定”不执行的任务”,示例命令如下。
ansible-playbook --skip-tags='t2' testtag.yml
6.3 变量
我们可以在play中使用vars关键字定义变量。示例如下:
---
- hosts: test
vars:
testvar1: testfile
remote_user: root
tasks:
- name: task1
file:
path: /testdir/{{ testvar1 }}
state: touch
在定义变量时,还能够以类似”属性”的方式定义变量,示例如下
---
- hosts: test
remote_user: root
vars:
nginx:
conf80: /etc/nginx/conf.d/80.conf
conf8080: /etc/nginx/conf.d/8080.conf
tasks:
- name: task1
file:
path: "{{nginx.conf80}}"
state: touch
- name: task2
file:
path: "{{nginx.conf8080}}"
state: touch
当我们需要引用这两个变量时,有两种语法可用
语法一:
"{{nginx.conf80}}"
语法二:
"{{nginx['conf8080']}}"
也可以使用文件定义变量,示例如下:
# cat nginx_vars.yml
nginx:
conf80: /etc/nginx/conf.d/80.conf
conf8080: /etc/nginx/conf.d/8080.conf
定义完相关变量文件后,在playbook中引入变量的文件时,使用‘‘vars_files’’,引入的文件需要以‘-’开头
---
- hosts: test
remote_user: root
vars_files:
- /testdir/ansible/nginx_vars.yml
tasks:
- name: task1
file:
path={{nginx.conf80}}
state=touch
- name: task2
file:
path={{nginx['conf8080']}}
state=touch
“vars”关键字和”vars_files”关键字可以同时使用,如下
vars:
- conf90: /etc/nginx/conf.d/90.conf
vars_files:
- /testdir/ansible/nginx_vars.yml
注册变量(将task的返回值写入变量的方法乘称作注册变量)示例如下
---
- hosts: test
remote_user: root
tasks:
- name: test shell
shell: "echo test > /var/testshellfile"
register: testvar
- name: shell module return values
debug:
var: testvar
提示用户输入信息并写入变量
---
- hosts: test
remote_user: root
vars_prompt:
- name: "your_name"
prompt: "What is your name"
- name: "your_age"
prompt: "How old are you"
tasks:
- name: output vars
debug:
msg: Your name is {{your_name}},You are {{your_age}} years old.
为提示信息设置默认值,即如果用户不输入任何信息,则将默认值赋予变量,示例playbook如下。
---
- hosts: test
remote_user: root
vars_prompt:
- name: "solution"
prompt: "Choose the solution you want \n
A: solutionA\n
B: solutionB\n
C: solutionC\n"
private: no
default: A
tasks:
- name: output vars
debug:
msg: The final solution is {{solution}}.
通过命令行传入变量
---
- hosts: test
remote_user: root
tasks:
- name: "Passing Variables On The Command Line"
debug:
msg: "{{pass_var}}"
上述示例中没有定义pass_var变量,调用palybook时可以从命令行引入该变量,方法如下
ansible-playbook cmdvar.yml --extra-vars "pass_var=cmdline pass var"
如上例所示,在调用playbook时使用 “–extra-vars” 选项可以传递对应的变量与变量值, “–extra-vars” 是长选项,对应的短选项是”-e”,我们也可以一次性传入多个变量,变量之间用空格隔开,如下
ansible-playbook cmdvar.yml -e 'pass_var="test" pass_var1="test1"'