ansible
- 一、ansible概述
- 二、Ansible的配置
- 三、ansible-playbook的编写
- 四、playbook中handlers的作用
- 五、ansible变量的作用
- 六、ansible template的作用
- 七、ansible Roles介绍
- 八、playbook配置web--nfs--rsync架构环境
一、ansible概述
Ansible是基于Python开发的轻量级自动化运维工具,有着其他自动化运维工具如puppet、cfengine、chef、func、fabric的优点,并且不需要单独安装客户端以及启动服务,只需要通过SSH就可以快速的对大量客户端实现批量系统配置、程序部署、批量运行命令等。
Ansible官方文档1.常用的运维工具
ssh
puppet(ruby)
ansible(无客户端,中小规模)(python)
saltstack(master-minion)(python)大规模
2.Ansible的作用
(1)批量部署
(2)服务安装
(3)日常备份
3.Ansible的特性
(1)无客户端软件,通过ssh远程管理
(2)安装后不需要启动服务
(3)依赖大量的Python模块扩展功能
(4)配置文件:/etc/ansible/ansible.cfg
4.Ansible基础架构
(1)连接插件(connecter plugins):用来连接主机,连接被管理端。
(2)核心模块(core modules):连接主机,实现操作,依赖于具体模块来执行。
(3)自定义模块:用户自己开发的功能模块。
(4)剧本(playbook):将多个任务组合成一个剧本,由ansible自动批量执行。
(5)主机清单(host inventory):定义ansible管理的客户端主机范围。
5.Ansible的命令格式
ansible 主机清单名 -m 调用的模块 -a 动作命令
二、Ansible的配置
环境准备
(1)准备四台虚拟机
ansible:192.168.229.169
web:192.168.229.170
nfs:192.168.229.160
rsync:192.168.229.171
(2)关闭四台虚拟机的防火墙和selinux
[root@ansible ~]# systemctl stop firewalld
[root@ansible ~]# systemctl disable firewalld
[root@ansible ~]# setenforce 0
1.两种方法安装ansible
方法一(推荐)
(1)配置epel源:
[root@ansible ~]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
[root@ansible ~]# wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
[root@ansible ~]# yum -y install ansible
[root@ansible ~]# ansible --version #查看版本
ansible 2.9.15
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/site-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.5 (default, Aug 7 2019, 00:51:29) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]
方法二
还可以通过python pip工具安装,不过需要先编译安装好python3,并且Ansible的命令也都会放在Python的目录中,需要做软连接。
/usr/local/python3/bin/pip3 install ansible==2.7
ln -s /usr/local/python3/bin/ansible /usr/local/bin
注:ansible有两个主要的配置路径
/etc/ansible/hosts:主机列表清单,也叫Inventory。
所有被管理的主机都需要定义在该文件中。
如果不想使用默认清单的话可以用-i选项指定自定义的清单文件,防止多人混合使用一个主机清单。
如果没有定义在主机列表文件中,执行命令会提示“No hosts matched”。
/etc/ansible/ansible.cfg:Ansible服务主配置文件,比如并发数控制等在此文件定义。
inventory内置参数
参数 | 用途 | 例子 |
ansible_ssh_host | 定义hosts ssh地址 | ansible_ssh_host=192.168.1.1 |
ansible_ssh_port | 定义hosts ssh端口 | ansible_ssh_port=3000 |
ansible_ssh_user | 定义hosts ssh认证用户 | ansible_ssh_user=user |
ansible_ssh_pass | 定义hosts ssh认证密码 | ansible_ssh_pass=pass |
ansible_sudo | 定义hosts sudo用户 | ansible_sudo=www |
ansible_sudo_pass | 定义hosts sudo密码 | ansible_sudo_pass=pass |
ansible_sudo_exe | 定义hosts sudo路径 | ansible_sudo_exe=/usr/bin/sudo |
ansible_connection | 定义hosts连接方式 | ansible_connection=local |
ansible_ssh_private_key_file | 定义hosts私钥 | ansible_ssh_private_key_file=/root/key |
ansible_ssh_shell_type | 定义hosts shell类型 | ansible_ssh_shell_type=bash |
ansible_python_interpreter | 定义hosts任务执行Python路径 | ansible_python_interpreter=/usr/bin/python2.6 |
ansible_*_interpreter | 定义hosts其他语言解析器 | ansible_*_interpreter=/usr/bin/ruby |
2.修改/etc/hosts文件并配置清单
[root@ansible ~]# vim /etc/hosts
添加
192.168.229.169 ansible
192.168.229.160 nfs1
192.168.229.170 web1
192.168.229.171 rsync1
[root@ansible ~]# vim /etc/ansible/hosts
末尾添加:
[web]
192.168.229.170
[nfs]
192.168.229.160
[rsync]
192.168.229.171
[benet:children]
web
nfs
rsync
3.在ansible上配置ssh秘钥对访问
[root@ansible ~]# ssh-keygen -t rsa
[root@ansible ~]# ssh-copy-id root@192.168.229.160
[root@ansible ~]# ssh-copy-id root@192.168.229.170
[root@ansible ~]# ssh-copy-id root@192.168.229.171
4.ansible常用命令
Ad-Hoc其实就是通过命令行的形式让Ansible进行工作,这个命令行就是ansible命令,更为复杂的方式还有Playbook和Roles。
ansible命令行语法格式:
ansible <host-pattern> [-f forks] [-m module_name] [-a args]
参数解释
<host-pattern>:该选项指定ansible命令对哪些主机生效,可以使用主机列表中的地址或者组名,all代表所有主机;
[-f forks]:并发数,可以理解为ansible一次性要让多少个主机执行任务,配置文件中默认为5;
[-m module_name]:使用的模块名;
[-a args]:每个模块特有的参数,可以用ansible-doc -s 模块名来查看模块对应参数
-b:老版本中的sudo指令,将在远端主机切换到root执行操作,这个root用户是在ansible配置中定义的;
-K:sudo时需要输入的密码
ansible命令行示例
ansible 192.168.1.100 -m ping #指定某台主机
ansible all -m ping #指定所有主机
ansible 192.168.1.100:192.168.1.50 -m ping #一次指定多台主机
ansible all:\!192.168.1.100 -m ping #排除某台主机
ansible web -m ping -u dba -k #使用dba用户对web组进行操作
ansible web -m command -a 'cat /etc/passwd' -u dba -k -b -K #使用dba用户连接web组,然后sudo到root用户查看passwd文件
Ansible常用模块介绍
command模块:默认模块。让远端主机执行指定的命令,但不支持管道或者重定向。
ansible 192.168.44.130 -a 'date'
cron模块:设置定时任务,其中有个state选项包含present、absent两个参数,分别代表增加和移除。
ansible webserver -m cron -a 'minute="*/10" job="/bin/echo test" name="test cron job"'
ansible webserver -m cron -a 'hour="*/1" job="/usr/sbin/ntpdate 10.254.1.10" name="crontab from ansible" state=present'
user模块:管理用户,还有一个group模块用于管理组。
ansible webserver -m user -a "name=mysql system=yes"
file模块:设置文件的属性,如所属主、文件权限等。
ansible all -m file -a 'owner=mysql group=mysql mode=644 path=/tmp/test'
ansible all -m file -a 'path=/etc/passwd.link src=/etc/passwd state=link'
#path:指定要设置的文件所在路径,可使用name或dest替换。
#state:指明文件的格式,touch=创建新的文件;absent=删除文件,link=创建软连接文件;directory=创建目录。
创建文件的软连接时,src指明源文件,path指明连接文件路径。
ping模块:测试远端主机是否能连接
ansible all -m ping
service模块:控制服务运行状态
ansible webserver -m service -a 'enabled=true name=httpd state=started'
#enabled:是否开机自启动,取值为true或者false。
#name:服务名称
#state:状态,取值有started,stopped,restarted
shell模块:和command模块一样是用来运行命令,当命令中有变量或者管道符时要用shell模块,特殊符号需要转义,比如\$。
ansible all -m shell -a "echo test | passwd --stdin user1"
script模块:将本地的脚本复制到远端主机并执行,需要把脚本放在当前目录中并使用相对路径来指定。
ansible all -m script -a 'test.sh'
yum模块:安装程序包,远端主机需要先配置好正确的yum源
ansible -m yum -a 'name=httpd state=present'
#name:指明要安装的程序包,可以带版本号,否则默认最新版本,多个安装包用逗号分隔。
#state:present代表安装,也是默认操作;absent是卸载;latest最新版本安装
setup模块:收集被管理主机的信息,包含系统版本、IP地址、CPU核心数。
在Ansible高级操作中可以通过该模块先收集信息,然后根据不同主机的不同信息做响应操作,类似Zabbix中的低级别发现自动获取磁盘信息一样。
copy模块:实现文件复制
ansible all -m copy -a 'src=/etc/fstab dest=/etc/fstab owner=root mode=640'
ansible all -m copy -a 'content="hello world" dest=/etc/fstab owner=root mode=640 backup=yes'
通过ansible-doc -s modulename显示指定模块的详细用法。
ansible-doc -s yum
常用功能如下
安装软件、修改配置、创建程序用户和组、创建目录,修改归属和权限、启动服务、挂载、测试。
调用模块颜色提示
黄色:更改成功
绿色:没有更改,已经执行过了
红色:错误
紫色:警告
命令如下
(1)列出所有模块
[root@ansible ~]# ansible-doc --list
(2)command:仅支持简单语法命令,但语句中不能包含管道符等复杂元素。
[root@ansible ~]# ansible web -m command -a "hostname"
[root@ansible ~]# ansible web -m command -a "useradd zhangsan"
(3)shell:command升级版,支持复杂语句,但不支持别名。
[root@ansible ~]# ansible web -m shell -a "echo 123 | passwd --stdin zhangsan"
(4)yum
[root@ansible ~]# ansible web -m yum -a "name=httpd state=installed"
注释:
name:安装的软件包名,多个软件","分开
state:服务状态
installed,present #安装软件包
removed,absent #卸载软件包
latest #安装最新软件包
(5)copy
把ansible虚拟机上的/etc/hosts文件,然后通过ansible发送给其他主机
[root@ansible ~]# ansible benet -m copy -a "src=/etc/hosts dest=/etc/hosts backup=yes"
参数介绍
参数 | 说明 |
src | 源文件路径 |
dest | 目标文件路径 |
backup | 覆盖到目标文件前,是否提前备份 |
content | 添加文件内容 |
group | 指定属组 |
owner | 指定属主 |
mode | 指定权限 |
5.在ansible上远程配置rsync服务
(1)修改rsync配置文件,并传到rsync服务器,最小化安装需要安装rsync服务
[root@ansible ~]# yum -y install rsync
[root@ansible ~]# cd /etc/ansible/
[root@ansible ansible]# mkdir conf
[root@ansible ansible]# cd conf
[root@ansible conf]# cp /etc/rsyncd.conf ./
[root@ansible conf]# vim rsyncd.conf
修改为:
uid = root
gid = root
port 873
address = 192.168.229.171
hosts allow = 192.168.229.0/24
max connections = 4
pid file = /var/run/rsyncd.pid
timeout = 900
dont compress = *.gz *.tgz *.zip *.z *.Z *.rpm *.deb *.bz2
[backup]
path = /backup
read only = no
auth users = rsync_backup
secrets file = /etc/rsync.password
[root@ansible conf]# ansible rsync -m yum -a "name=rsync state=installed"
[root@ansible conf]# ansible rsync -m copy -a "src=rsyncd.conf dest=/etc/rsyncd.conf backup=yes"
(2)启动rsync服务
[root@ansible conf]# ansible rsync -m shell -a "rsync --daemon"
(3)创建目录,并赋权,更改属主属组
[root@ansible conf]# ansible rsync -m file -a "path=/backup owner=root group=root recurse=yes mode=777"
(4)配置rsync服务器的密码文件
[root@ansible conf]# ansible rsync -m copy -a "content='rsync_backup:1' dest=/etc/rsync.password owner=root group=root mode=600"
[root@ansible conf]# ansible rsync -m shell -a "ls -l /etc/rsync.password"
[root@ansible conf]# ansible rsync -m shell -a "cat /etc/rsync.password"
(5)配置所有服务器的rsync连接密码文件
[root@ansible conf]# ansible benet -m copy -a "content='1' dest=/etc/server.pass owner=root group=root mode=600"
(6)测试:备份web的httpd.conf配置文件
[root@ansible conf]# ansible web -m yum -a "name=rsync state=installed"
[root@ansible conf]# ansible web -m shell -a "rsync -avz --password-file=/etc/server.pass /etc/httpd/conf/httpd.conf rsync_backup@rsync::backup"
6.service
[root@ansible conf]# ansible web -m service -a "name=httpd state=started enabled=yes"
注释:
name #指定服务名
state #指定服务运行状态
started #开启服务
stopped #关闭服务
reloaded #重载服务
restarted #重启服务
enabled #是否开机自启
6.group
(1)在所有清单主机上创建组www,gid 666
[root@ansible conf]# ansible all -m group -a "name=www gid=666"
(2)在所有清单主机删除组www
[root@ansible conf]# ansible all -m group -a "name=www gid=666 state=absent"
7.user
[root@ansible conf]# ansible all -m user -a "name=www"
[root@ansible conf]# ansible web -m shell -a "echo 123 | passwd --stdin www"
8.file
创建目录,并赋权,更改属主属组
recurse:递归设置文件的属性,只对目录有效。
[root@ansible conf]# ansible rsync -m file -a "path=/backup owner=root group=root recurse=yes mode=777"
创建文件
[root@ansible conf]# ansible rsync -m file -a "path=/test.txt owner=root group=root state=touch mode=777"
9.mount
[root@ansible conf]# yum -y install nfs-utils rpcbind
[root@ansible conf]# systemctl start nfs
[root@ansible conf]# systemctl start rpcbind
[root@ansible conf]# ansible all -m yum -a "name=nfs-utils state=installed"
[root@ansible conf]# ansible all -m yum -a "name=rpcbind state=installed"
[root@ansible conf]# ansible nfs -m file -a "path=/nfs owner=root group=root recurse=yes mode=777"
[root@ansible conf]# vim exports
/nfs 192.168.229.0/24(rw,sync,no_root_squash)
[root@ansible conf]# ansible nfs -m copy -a "src=exports dest=/etc/exports"
[root@ansible conf]# ansible all -m service -a "name=nfs state=started"
[root@ansible conf]# ansible all -m service -a "name=rpcbind state=started"
[root@ansible conf]# showmount -e nfs
Export list for nfs:
/nfs 192.168.229.0/24
挂载nfs目录到web下的/var/www/html
[root@ansible conf]# ansible web -m mount -a "src=192.168.229.160:/nfs path=/var/www/html fstype=nfs state=mounted"
注释:
state #挂载状态
mounted #挂载
unmounted #卸载
10.script
在ansible上编写任意测试脚本
[root@ansible conf]# ansible web -m script -a "/root/test.sh"
三、ansible-playbook的编写
1.ansible-playbook简介
如果基于AD-Hoc去执行多任务(如安装Nginx、修改配置文件、启动服务),需要先使用yum或command模块安装程序,再使用copy模块复制配置文件,最后使用service模块启动服务。为了解决这种多任务的情况,可以使用Ansible的playbook功能。
2.ansible-playbook构成
Inventory:主机列表,表示剧本中的任务要应用在哪些主机上;
Tasks:具体任务,即调用哪些模块完成操作,可以配置多个任务;
Variables:变量,包含内置变量和自定义变量;
Templates:模板,即使用模板语法来灵活变更配置文件;
Handlers与notify:触发器,由某事件触发执行的操作,比如修改配置文件后自动重启服务;
3.playbook的语法要求
(1)playbook本质是包含了一个或多个play的YAML配置文件,通常以.yaml或者.yml结尾;
(2)在单一的playbook文件中,使用连续的三个中横线(---)作为每个play的区分;
(3)缩进必须统一,不能空格和tab混合使用,缩进级别需要一致,同样的缩进代表同样的级别;
(4)冒号:冒号后面需要空格,除非以冒号结尾;
(5)短横杠:列表项,后面跟空格;
(6)缩进两个字符,默认的tab键是四个字符,所以要使用tab键,需要修改.vimrc;
[root@ansible ~]# vim /root/.vimrc
set tabstop=2
4.ansible-playbook示例说明
[root@ansible ~]# cat playbook01.yml
--- #固定格式
- hosts: 192.168.1.1 #定义需要执行的主机或主机组
remote_user: root #远程用户
vars: #定义变量
http_port: 8088 #变量
tasks: #定义一个任务
- name: create new file #定义任务的名称
file: name=/tmp/playtest.txt state=touch #调用模块,具体要做的事情
- name: install package
yum: name=httpd
- name: config httpd
template: src=./httpd.conf dest=/etc/httpd/conf/httpd.conf
notify: #触发器,当条件触发后需要做的操作,配合handlers使用
- restart apache #需要引用的handlers的名字
- name: copy index.html
copy: src=/var/www/html/index.html dest=/var/www/html/index.html
- name: start httpd
service: name=httpd state=started
handlers: #notify定义的触发执行相应的处理动作
- name: restart apache #要与notify定义的内容相同
service: name=httpd state=restarted #触发要执行的动作
参数解释:
hosts:指定远程主机(多个主机用逗号分隔)或主机组
remote_user:指定执行任务的用户(也可单独给每个task定义),通常是root用户,也可指定非root用户使用sudo方式执行任务
---
- hosts: 192.168.1.31
remote_user: root #定义全局用户
tasks:
- name: run df -h
remote_user: test #单独为task定义用户
shell: name=df -h
sudo(可省略):如果设置为yes,那么sudo_user指定的用户在执行任务时会获得root权限;
sudo_user(可省略):指定需要使用sudo执行操作的用户;
tasks:
- name: run df -h
sudo_user: test
sudo: yes
shell: name=df -h
connection(可省略):通过什么方式连接到远程主机,默认为SSH;
gather_facts(可省略):如果明确不需要通过setup模块来获取远程主机facts信息,可以使用这个选项;
5.ansible-playbook命令示例与常用选项
语法结构
bashansible-playbook + 选项 + 文件路径
命令示例
ansible-playbook -t tag_name httpd.yml
ansible-playbook playbookname.yml --list-task
选项
--check | -C:只检测可能会发生的改变,但不真正执行操作;
--list-hosts:列出运行任务的主机;
--list-tags:列出playbook文件中定义的所有tags;
--list-tasks:列出playbook文件中定义的所有任务;
--syntax-check:语法检查
--limit:主机列表,只针对主机列表中的某个主机或者某个组执行;
-f:指定并发数,默认为5个;
-t:指定tags运行,运行某一个或者多个tags,前提是playbook中有定义tags;
命令结果说明
ok:已经达到任务要求,无需再次处理;
changed:经过了ansible的处理,再次执行则会发现这些信息也变成了ok;
PLAY RECAP:一个汇总报告;
6.使用ansible-vault加密playbook
ansible-vault encrypt hello.yml #加密playbook,加密后的文件无法直接执行和查看;
ansible-vault view hello.yml #查看加密后的文件;
ansible-vault edit hello.yml #查看加密后的文件;
ansible-vault decrypt hello.yml #解密playbook;
7.测试案例
通过playbook安装httpd,并修改端口号为8080;
前提:安装httpd,移动httpd.conf到ansible_playbook下的conf目录,修改端口为8080;
[root@ansible ~]# yum -y install httpd
[root@ansible ~]# vim /etc/httpd/conf/httpd.conf
定位:
Listen 80改为Listen 8080
#ServerName www.example.com:80去掉#
[root@ansible ~]# mkdir -p /etc/ansible/ansible_playbook/{conf,file,scripts,tools}
[root@ansible ~]# cd /etc/ansible/ansible_playbook/conf
[root@ansible conf]# mv /etc/httpd/conf/httpd.conf ./
[root@ansible conf]# cd ..
[root@ansible ansible_playbook]# vim httpd.yaml
- hosts: web
tasks:
- name: install httpd
yum: name=httpd state=latest
- name: httpd config
copy: src=./conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify: restart httpd
- name: start httpd
service: name=httpd state=started
handlers:
- name: restart httpd
service: name=httpd state=restarted
测试预执行yaml
[root@ansible ansible_playbook]# ansible-playbook -C httpd.yaml
执行yaml
[root@ansible ansible_playbook]# ansible-playbook httpd.yaml
四、playbook中handlers的作用
1.handlers的作用
handlers是一种触发器,它可以对task进行监控,如果task所指定的任务状态发生变化,则进行notify通知,然后触发额外的一系列操作。
看一个示例来帮助理解:
[root@ansible ansible_playbook]# cat apache.yml
- hosts: webservers
remote_user: root
tasks:
- name: install apache
yum: name=httpd state=latest
- name: install configure file for httpd
copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
- name: start httpd service
service: enabled=true name=httpd state=started
上面的YAML文件存在三个task任务,分别是安装httpd、复制配置文件到远端主机、启动httpd服务。但是当第二个task中的配置文件发生了改变后再次执行playbook的话,会发现新的配置文件虽然会正确的复制到远端主机去,但是却没有重启httpd服务。因为Ansible在执行playbook时发现第三个任务与现在状态是一致的,就不会再次执行任务。为了解决这种问题,就需要使用ansible的handlers功能。handlers是用于监控一个任务的执行状态,如果一个tasks任务最后是changed状态则会触发handlers指定的操作。
2.如何配置handlers
ansible中通过notify这个模块来实现handlers,将示例1修改后:
[root@ansible ansible_playbook]# cat apache.yml
- hosts: webservers
remote_user: root
tasks:
- name: install apache
yum: name=httpd state=latest
- name: install configure file for httpd
copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify:
- restart httpd #通知restart httpd这个触发器
- check httpd #可以定义多个触发器
- name: start httpd service
service: enabled=true name=httpd state=started
handlers: #定义触发器,和tasks同级
- name: restart httpd #触发器名字,被notify引用,两边要一致
service: name=httpd state=restart
- name: check httpd
shell: netstat -ntulp | grep 80
当httpd.conf的源文件发生修改后,只需重新执行playbook就会自动重启httpd服务,因为配置文件状态是changed而非ok。
五、ansible变量的作用
在Ansible中支持设置主机变量、组变量,变量支持嵌套使用,定义好了的变量可以在playbook中引用。由于Ansible是在每个主机上单独运行命令,所以不同的主机去调用同样的变量,也可以取到不同的值,这样进行一些配置就更灵活合理。
1.Ansible变量定义与调用
方法1:在/etc/ansible/hosts文件中定义变量
#定义变量
[root@ansible ansible_playbook]# vim /etc/ansible/hosts
[apache]
192.168.1.1 webdir=/opt/test #定义单个主机的变量
192.168.1.2
[apache:vars] #定义整个组的统一变量
webdir=/web/test
[nginx] 192.168.1.3[1:2]
[nginx:vars]
webdir=/opt/web
#playbook调用变量
[root@ansible ansible_playbook]# cat variables.yml
---
- hosts: all
remote_user: root
tasks:
- name: create webdir
file: name={{ webdir }} state=directory #引用变量
[root@ansible PlayBook]# ansible-playbook variables.yml
方法2:在playbook中定义和调用变量
[root@ansible ansible_playbook]# cat apache.yml
- hosts: webservers
remote_user: root
vars: #开始声明变量
- package: httpd #变量名与变量值
- service: httpd
tasks:
- name: install apache
yum: name={{ package }} state=latest #要引用的变量用"{{ }}"
- name: install configure file for httpd
copy: src=/root/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
- name: start httpd service
service: enabled=true name={{ service }} state=started
方法3:使用ansible-playbook -e选项定义变量,命令行变量优先级高于配置文件中的变量。
[root@ansible ansible_playbook]# cat app.yml
---
- hosts: all
remote_user: root
tasks:
- name: install httpd
yum: name="{{ package }}" #配置文件声明需要引用的变量名
[root@ansible ansible_playbook]# ansible-playbook -e 'package=httpd' app.yml #通过-e给变量赋值,在app.yml文件全局生效
方法4:调用setup模块获取变量
setup模块主要用于获取主机信息并保存在变量中,如IPv4、IPv6、MAC地址、磁盘分区等。该模块获取到的变量是可以直接调用的,无需定义。
[root@ansible ansible_playbook]# ansible webserver -m setup
每个引号内的就是默认变量名,使用双花括号可以直接引用。对于一些包含多个层级的变量(比如磁盘分区会存在sda、sdb、sdc…),可以通过从上级书写的形式,比如{{ansible_devices.sda.partitions.sda.size}}
- hosts: webservers
remote_user: root
tasks:
- name: copy file
copy: content='{{ ansible_default_ipv4.address }}' dest=/tmp/vars.ans
方法5:使用独立的YAML文件定义变量
为了方便管理将所有的变量统一放在一个独立的变量YAML文件中,playbook文件直接引用文件调用变量即可。
#定义存放变量的文件
[root@ansible ansible_playbook]# cat var.yml
var1: vsftpd
var2: httpd
#编写playbook
[root@ansible ansible_playbook]# cat variables.yml
---
- hosts: all
remote_user: root
vars_files: #引用变量文件
- ./var.yml #指定变量文件的path(这里可以是绝对路径,也可以是相对路径)
tasks:
- name: install package
yum: name={{ var1 }} #引用变量
- name: create file
file: name=/tmp/{{ var2 }}.log state=touch #引用变量
[root@ansible ansible_playbook]# ansible-playbook variables.yml
六、ansible template的作用
1.template的作用简介
在实际的工作中由于每台服务器的环境配置都可能不同,但是往往很多服务的配置文件都需要根据服务器环境进行不同的配置,比如Nginx最大进程数、Redis最大内存等。为了解决这个问题可以使用Ansible的template模块,该模块和copy模块作用基本一样,都是把管理端的文件复制到客户端主机上,但是区别在于template模块可以通过变量来获取配置值,支持多种判断、循环、逻辑运算等,而copy只能原封不动的把文件内容复制过去。需要注意的是template只能在playbook中运行,不能使用命令行方式。
2.template使用方法
(1)多数情况下都会建立一个templates目录并和playbook同级,这样playbook可以直接引用和寻找这个模板文件,如果在别的路径需要单独指定。模板文件后缀名为.j2
[root@ansible ansible_playbook]# mkdir templates
[root@ansible ansible_playbook]# cp /etc/conf/httpd.conf templates/httpd.conf.j2 #复制一个原始配置文件进行修改
(2)创建playbook并使用template模板
[root@ansible ansible_playbook]# cat test.yml
---
- hosts: all
remote_user: root
vars:
- listen_port: 88 #定义变量
tasks:
- name: Install Httpd
yum: name=httpd state=installed
- name: Config Httpd
template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf #使用模板
notify: Restart Httpd
- name: Start Httpd
service: name=httpd state=started
handlers:
- name: Restart Httpd
service: name=httpd state=restarted
(3)修改模板文件,配置文件中需要针对端口做不同设置,找到listen一项做以下修改。
[root@ansible ansible_playbook]# vim templates/httpd.conf.j2
Listen {{ listen_port }} #这里的端口用变量替代
(4)由于调用了listen_port这个变量,所以需要在主机列表文件中给每个主机定义这样一个变量(也可以将变量写在playbook中)。
[root@ansible ansible_playbook]# vim /etc/ansible/hosts
192.168.100.110 listen_port=80
192.168.100.120 listen_port=8080
192.168.100.130 listen_port=808
192.168.100.140 listen_port=8000
(5)运行ansible-playbook test.yml即可
3.ansible with循环
在ansible中使用with_items进行循环迭代,适用于需要重复执行的任务。对需要进行循环时,使用固定变量名{{ item }},然后在task中使用with_items给定要迭代的元素列表。
示例1:通过with_items安装多个软件
[root@ansible ansible_playbook]# vim /etc/ansible/with.yml
---
- hosts: 192.168.1.100
remote_user: root
tasks:
- name: Install Package
yum: name={{ item }} state=installed #引用item获取值
with_items: #定义with_items
- redis
- nginx
[root@ansible ansible_playbook]# ansible-playbook while.yml
4.ansible when条件判断
示例1:判断客户端系统判断,然后选择对应的配置文件。
[root@ansible ansible_playbook]# vim /etc/ansible/when.yml #加入如下内容
- hosts: dbservers
user: root
vars:
- http_port: 8080
tasks:
- name: install nginx
yum: name=nginx
- name: copy conf for centos7
template: src=nginx.conf7.j2 dest=/etc/nginx/nginx.conf
when: ansible_distribution_major_version == "7" #这里的变量是取facts信息
notify: restart service
- name: copy conf for centos6
template: src=nginx.conf6.j2 dest=/etc/nginx/nginx.conf
when: ansible_distribution_major_version == "6"
notify: restart service
- name: start service
service: name=nginx state=started enabled=yes
handlers:
- name: restart service
service: name=nginx state=restarted
示例2:当远程主机FQDN名为test时,给该主机添加一个用户user10。
[root@ansible ansible_playbook]# vim test.yml
- hosts: all
remote_user: root
vars:
- username: user10
tasks:
- name: create {{ username }} user
user: name={{ username }}
when: ansible_fqdn == "test"
七、ansible Roles介绍
1.roles的作用简介
ansible的roles功能也叫做角色,它是一种让多个playbook协同工作的实现方法。roles将playbook中的vars变量、handlers、tasks任务、模块及处理器都进行了拆分,分别放置于各自目录然后进行引用的一种机制。通常一些复杂场景才会使用roles,让代码复用度更高。比如上架50台服务器,其中20台是数据库服务器,另外30台是Web服务器,那么就可以建立2个roles来各自负责对应的机器。
2.通过ansible-galaxy快速了解roles
(1)该命令可以连接galaxy.ansible.com下载已经编排好的roles
[root@ansible ansible_playbook]# ansible-galaxy list #列出已经安装的galaxy
[root@ansible ansible_playbook]# ansible-galaxy install geerlingguy.redis #安装一个galaxy角色
[root@ansible ansible_playbook]# ansible-galaxy remove geerlingguy.redis #删除一个galaxy角色
(2)安装好一个roles后可以看到在相应的目录中会生成一个以角色名命名的目录,并且还有许多子目录和yml文件,这些都是构成roles的成员。复制一份角色目录就会被ansible自动识别成一个新的角色。
[root@ansible ansible_playbook]# ansible-galaxy install geerlingguy.redis
3.手动创建ansible roles
(1)创建roles目录,保持和playbook同级,然后在roles目录中创建以角色命名的目录,如nginx、mysql
[root@ansible ansible_playbook]# mkdir roles/{nginx,mysql}
(2)在每个角色目录中分别创建files、handlers、tasks(必须)、templates、vars等目录(参考galaxy所创建的目录)
[root@ansible ansible_playbook]# mkdir roles/nginx/{handlers,tasks,template,vars,files}
(3)roles各子目录作用
roles/$project/:project是真实项目名称,如nginx或mysql;
files/:存放由copy或script等模块调用的文件,如网页文件。使用copy模块时会自动从该目录找文件;
template/:template模块会自动在此目录中寻找j2模板文件,使用template模块就会自动从该目录找文件;
tasks/:该目录必须存在,定义task基本元素,该目录中需要包含一个main.yml文件,其它文件需要在此main.yml中通过include进行包含;
handlers/:应包含一个main.yml文件用于定义此角色用到的各handlers,没有handlers的话不用创建;
vars/:应包含一个main.yml文件用于定义此角色用到的变量,没有变量的话不用创建;
4.ansible roles创建httpd服务示例
(1)为roles创建目录
[root@ansible ansible_playbook]# cd /etc/ansible/roles/
[root@ansible ansible_playbook]# mkdir -p httpd/{handlers,tasks,templates,vars}
[root@ansible ansible_playbook]# cd httpd/
tree .
.
├── handlers
├── tasks
├── templates
└── vars
(2)创建变量文件
[root@ansible ansible_playbook]# vim vars/main.yml
PORT: 80 #指定httpd监听的端口
(3)为httpd创建配置文件的template
# copy一个本地的配置文件,方便修改
[root@ansible ansible_playbook]# cp /etc/httpd/conf/httpd.conf templates/httpd.conf.j2
[root@ansible ansible_playbook]# vim templates/httpd.conf.j2
Listen {{ PORT }} #引用变量
(4)建立tasks文件,写明需要执行的任务
# 创建组的task
[root@ansible ansible_playbook]# vim tasks/group.yml
- name: Create a Startup Group #name会在执行过程中显示
group: name=www gid=60 system=yes
# 创建用户的task
[root@ansible ansible_playbook]# vim tasks/user.yml
- name: Create Startup Users
user: name=www uid=60 system=yes shell=/sbin/nologin
# 安装软件的task
[root@ansible ansible_playbook]# vim tasks/install.yml
- name: Install Package Httpd
yum: name=httpd state=installed
# 配置软件的task
[root@ansible ansible_playbook]# vim tasks/config.yml
- name: Copy Httpd Template File
template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
notify: Restart Httpd
# 启动软件的task
[root@ansible ansible_playbook]# vim tasks/start.yml
- name: Start Httpd Service
service: name=httpd state=started enabled=yes
# 编写main.yml引用所有task
[root@ansible ansible_playbook]# vim tasks/main.yml
- include: group.yml
- include: user.yml
- include: install.yml
- include: config.yml
- include: start.ym
(5)建立handlers文件
[root@ansible ansible_playbook]# vim handlers/main.yml
- name: Restart Httpd
service: name=httpd state=restarted #名字需要和task中的notify保持一致
(6)建立playbook用于调用角色,这个playbook文件需要和roles目录平级
[root@ansible ansible_playbook]# vim httpd_roles.yml
---
- hosts: all
remote_user: root
roles:
- role: httpd #指定角色名称
[root@ansible ansible_playbook]# ansible-playbook -C httpd_roles.yml #正式运行前可以先-C测试一次
(7)roles最终目录结构
八、playbook配置web–nfs–rsync架构环境
全局环境:修改各主机名:ansible、web、nfs、rsync
1.服务器配置
前提:
ifdown ens33;ifup ens33
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
vim /etc/hosts
192.168.229.169 ansible
192.168.229.170 web
192.168.229.160 nfs
192.168.229.171 rsync
(1)安装ansible
[root@ansible ~]# yum -y install epel-release
[root@ansible ~]# yum -y install ansible
(2)ssh公钥
[root@ansible ~]# ssh-keygen -t rsa
[root@ansible ~]# ssh-copy-id root@web #web服务器
[root@ansible ~]# ssh-copy-id root@nfs #nfs服务器
[root@ansible ~]# ssh-copy-id root@rsync #rsync服务器
(3)复制/etc/hosts到被管理端
[root@ansible ~]# scp /etc/hosts root@web:/etc
[root@ansible ~]# scp /etc/hosts root@nfs:/etc
[root@ansible ~]# scp /etc/hosts root@rsync:/etc
(4)创建ansible目录
[root@ansible ~]# mkdir -p /etc/ansible/ansible_playbook/{conf,file,scripts,tools}
(5)创建ansible清单
[root@ansible ~]# vim /etc/ansible/hosts
[web]
web
[nfs]
nfs
[rsync]
rsync
2.基础环境部署
(1)网络环境(关闭firewall selinux)
(2)epel仓库
(3)安装rsync,nfs-utils
(4)创建组
(5)创建用户
(6)创建目录,并修改权限
(7)推送脚本
(8)推送rsync客户端密码文件,修改权限
(9)计划任务
[root@ansible ansible_playbook]# vim base.yaml
- hosts: all
tasks:
- name: clear repos.d
file: path=/etc/yum.repos.d/ state=absent
- name: create repos.d
file: path=/etc/yum.repos.d/ state=directory
- name: install base repo
get_url: url=http://mirrors.aliyun.com/repo/Centos-7.repo dest=/etc/yum.repos.d/CentOS-Base.repo
- name: install epel repo
get_url: url=http://mirrors.aliyun.com/repo/epel-7.repo dest=/etc/yum.repos.d/epel.repo
- name: install rsync nfs-utils
yum: name=rsync,nfs-utils state=installed
- name: create group www
group: name=www gid=666
- name: create user www
user: name=www uid=666 create_home=no shell=/sbin/nologin
- name: create rsync client password
copy: content='1' dest=/etc/rsync.pass mode=600
- name: create scripts directory
file: path=/server/scripts/ recurse=yes state=directory
- name: push scripts
copy: src=./scripts/rsync_backup.sh dest=/server/scripts
- name: crontab
cron: name="backup scripts" hour=01 minute=00 job="/usr/bin/bash /server/scripts/rsync_backup.sh &> /dev/null"
其中脚本rsync_backup.sh如下:
[root@ansible ansible_playbook]# cd scripts/
[root@ansible scripts]# vim rsync_backup.sh
#!/usr/bin/bash
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
#1.定义变量
Host=$(hostname)
Addr=$(ifconfig ens33|awk 'NR==2{print $2}')
Date=$(date +%F)
Dest=${Host}_${Addr}_${Date}
Path=/backup
#2.创建备份目录
[ -d $Path/$Dest ] || mkdir -p $Path/$Dest
#3.备份对应的文件
cd / && \
[ -f $Path/$Dest/system.tar.gz ] || tar czf $Path/$Dest/system.tar.gz etc/fstab etc/rsyncd.conf && \
[ -f $Path/$Dest/log.tar.gz ] || tar czf $Path/$Dest/log.tar.gz var/log/messages var/log/secure && \
#4.携带md5验证信息
[ -f $Path/$Dest/flag ] || md5sum $Path/$Dest/*.tar.gz >$Path/$Dest/flag_${Date}
#5.推送本地数据至备份服务器
export RSYNC_PASSWORD=1
rsync -avz $Path/ rsync_backup@rsync1::backup
#6.本地保留最近7天的数据
find $Path/ -type d -mtime +7|xargs rm -rf
[root@ansible scripts]# chmod +x rsync_backup.sh
测试base.yaml
[root@ansible scripts]# cd ..
[root@ansible ansible_playbook]# ansible-playbook -C base.yaml
3.rsync配置
(1)安装rsync
(2)配置
(3)启动
(4)脚本
(5)计划任务
[root@ansible ansible_playbook]# vim rsync.yaml
- hosts: rsync
tasks:
- name: install rsync
yum: name=rsync,mailx state=installed
- name: config rsync
copy: src=/etc/ansible/ansible_playbook/conf/rsyncd.conf dest=/etc/rsyncd.conf
notify: restart rsync
- name: create rsync local user
copy: content='rsync_backup:1' dest=/etc/rsync.password mode=600
- name: create data
file: path=/data state=directory recurse=yes owner=www group=www mode=755
- name: create backup
file: path=/backup state=directory recurse=yes owner=www group=www mode=755
- name: start rsync
service: name=rsyncd state=started enabled=yes
- name: push check scripts
copy: src=./scripts/rsync_check.sh dest=/server/scripts/
- name: crond check scripts
cron: name="check scripts" hour=05 minute=00 job="/usr/bin/bash /server/scripts/rsync_check.sh &> /dev/null"
handlers:
- name: restart rsync
service: name=rsyncd state=restarted
其中脚本rsync_check.sh如下
[root@ansible ansible_playbook]# cd scripts/
[root@ansible scripts]# vim rsync_check.sh
#!/usr/bin/bash
#1.定义全局的变量
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
#2.定义局部变量
Path=/backup
Date=$(date +%F)
#3.查看flag文件,将校验的结果保存至result_时间
find $Path/*_${Date} -type f -name "flag$Date" >$Path/result_${Date}
#4.将校验的结果发送邮件给管理员
mail -s "Rsync Backup $Date" 1793594335@qq.com <$Path/result_${Date}
#5.删除超过7天的校验结果文件, 删除超过180天的备份数据文件
find $Path/ -type f -name "result*" -mtime +7|xargs rm -f
find $Path/ -type d -mtime +180|xargs rm -rf
[root@ansible scripts]# chmod +x rsync_check.sh
将rsyncd.conf配置文件移动到ansible_playbook/conf下并测试rsync.yaml
[root@ansible scripts]# cd ..
[root@ansible ansible_playbook]# vim conf/rsyncd.conf
uid = root
gid = root
port 873
address = 192.168.229.171
hosts allow = 192.168.229.0/24
max connections = 4
pid file = /var/run/rsyncd.pid
timeout = 900
dont compress = *.gz *.tgz *.zip *.z *.Z *.rpm *.deb *.bz2
[backup]
path = /backup
read only = no
auth users = rsync_backup
secrets file = /etc/rsync.password
[root@ansible ansible_playbook]# ansible-playbook -C rsync.yaml
4.nfs部署
(1)安装nfs-utils
(2)配置
(3)启动
[root@ansible ansible_playbook]# vim nfs.yaml
- hosts: nfs
tasks:
- name: install nfs
yum: name=nfs-utils state=installed
- name: config nfs
copy: src=./conf/exports dest=/etc/exports
notify: restart nfs
- name: create data
file: path=/data state=directory recurse=yes owner=www group=www mode=755
- name: start nfs
service: name=nfs state=started enabled=yes
handlers:
- name: restart nfs
service: name=nfs state=restarted
测试nfs.yaml
[root@ansible ansible_playbook]# vim conf/exports
/data 192.168.229.0/24(rw,sync,no_root_squash)
[root@ansible ansible_playbook]# ansible-playbook -C nfs.yaml
5.sersync部署
(1)在ansible服务器先下载sersync
(2)解压到/etc/ansible/ansible_playbook/并修改配置文件
[root@ansible ansible_playbook]# cd tools/
[root@ansible tools]# ls
sersync2.5.4_64bit_binary_stable_final.tar.gz
[root@ansible tools]# tar zxf sersync2.5.4_64bit_binary_stable_final.tar.gz
[root@ansible tools]# ls
GNU-Linux-x86 sersync2.5.4_64bit_binary_stable_final.tar.gz
[root@ansible tools]# cd GNU-Linux-x86/
[root@ansible GNU-Linux-x86]# ls
confxml.xml sersync2
[root@ansible sersync]# vim confxml.xml
定位 <localpath watch="/opt/tongbu">
<remote ip="127.0.0.1" name="tongbu1"/>
修改为:
<localpath watch="/data">
<remote ip="192.168.229.160" name="/data"/>
(3)推送到nfs
(4)启动sersync
[root@ansible GNU-Linux-x86]# cd ..
[root@ansible tools]# mv GNU-Linux-x86/ sersync
[root@ansible tools]# cd ..
[root@ansible ansible_playbook]# vim sersync.yaml
- hosts: nfs
tasks:
- name: scp sersync
copy: src=./tools/sersync/ dest=/usr/local/sersync owner=www group=www mode=755
- name: start sersync
shell: pgrep sersync;
[ $? -eq 0 ] || /usr/local/sersync/sersync2 -dro /usr/local/sersync/confxml.xml
测试sersync.yaml
[root@ansible ansible_playbook]# ansible-playbook -C sersync.yaml
6.web部署
(1)本地安装httpd
(2)修改配置文件,复制到/etc/ansible/ansible_playbook/conf
(3)挂载
(4)启动
[root@ansible ansible_playbook]# vim web.yaml
- hosts: web
tasks:
- name: mount nfs
mount: src=nfs:/data path=/data fstype=nfs state=mounted
- name: install httpd
yum: name=httpd state=installed
- name: config httpd
copy: src=./conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
notify: restart httpd
- name: start httpd
service: name=httpd state=started enabled=yes
handlers:
- name: restart httpd
service: name=httpd state=restarted
测试web.yaml
[root@ansible ansible_playbook]# yum -y install httpd
[root@ansible ansible_playbook]# cp /etc/httpd/conf/httpd.conf ./conf/
[root@ansible ansible_playbook]# ansible-playbook -C web.yaml
7.main.yaml
[root@ansible ansible_playbook]# vim main.yaml
- import_playbook: base.yaml
- import_playbook: rsync.yaml
- import_playbook: nfs.yaml
- import_playbook: sersync.yaml
- import_playbook: web.yaml
预检测
[root@ansible ansible_playbook]# ansible-playbook -C main.yaml
执行
[root@ansible ansible_playbook]# ansible-playbook main.yaml