文章目录
一、自动化运维工具
1、不止ansible
自动化运维工具有很多
- 1、Puppet:基于 Ruby 开发,采用 C/S 架构,扩展性强,基于 SSL,远程命令执行相对较弱。
- 2、SaltStack:基于 Python 开发,采用 C/S 架构,相对 puppet 更轻量级,配置语法使用 YAML,使配置脚本更简单,需要配置客户端以及服务器端。每台被控制节点需要安装agent。
- 3、Ansible:基于 Python开发,分布式,无需客户端,轻量级,配置语法使用YAML语言,更强的远程命令执行操作。
2、凭什么是ansible
Ansible简介
ansible是新出现的自动化运维工具,基于Python开发,分布式,无需客户端,轻量级,实现了批量系统配置、批量程序部署、批量运行命令等功能,ansible是基于模块工作的,本身并没有批量部署的能力,真正具有批量部署的是ansible上所运行的模块,ansible只是提供一种框架。
Ansible特性
- 、no agents:不需要在被管控主机上安装任何客户端,更新时只需在操作机上进行一次更新即可(不用安装客户端,分布式的)。
- 、no server:无服务器端,使用时直接运行命令即可。
- 、modules in any languages:基于模块工作,可使用任意语言开发模块。
- 、yaml,not code:使用yaml语言定制剧本playbook。
- 、ssh by default:基于SSH工作。
- 、strong multi-tier solution:可实现多级指挥。
connection plugins:连接插件,负责和被监控端实现通信,默认使用SSH连接。
host inventory:主机清单,是一个配置文件里面定义监控的主机。
modules:模块,核心模块、command模块、自定义模块等。
plugins:modules功能的补充,包括连接插件,邮件插件等。
playbook:编排,定义 Ansible 多任务配置文件,非必需。
二、安装部署ansible
1、安装配置ansible主机组
在这里我们准备三台机器,分别是server(控制节点),web1(被控节点),web2(被控节点)
主机清单文件配置
#三台服务器的/etc/hosts文件中配置解析
[root@ansible-server] vim /etc/hosts
192.168.202.131 ansible-server
192.168.202.132 ansible-web1
192.168.202.133 ansible-web2
#配置秘钥对,采用公钥认证方式:控制节点需要发送ssh公钥给所有被控制节点
[root@ansible-server] ssh-keygen
[root@ansible-server] ssh-copy-id -i 192.168.202.132
#也可以把ip换成解析的ansible-web1(两台机器都要发)
除了ssh公钥认证的方式外,也可以用密码认证
[root@ansible-server] yum -y install ansible
#如果没有的话就先安装epel-release源
[root@ansible-server] ansible --version #查看版本及信息,如果报红则环境有问题安装失败
[root@ansible-server] rpm -qc ansible #查看配置文件
/etc/ansible/ansible.cfg #主配置文件
/etc/ansible/hosts #主机清单文件
/etc/ansible/ansible.cfg 主配置文件,主要设置一些ansible初始化的信息,比如日志存放路径、模块、等配置信息。
/etc/ansible/hosts 默认主机清单文件,定义管理的主机及主机组,默认路径。
[root@ansible-server] vim /etc/ansible/hosts
#单独定义主机的
ansible-web1 #单独定义一个主机
192.168.202.133 #如果未解析也可以写ip
#定义主机组批量管理的
#每个组内可以有一个到多个主机
#定义主机组用[]
[webgrp1] #组1
ansible-web1
[webgrp2] #组2
ansible-web2
#主机组内也可以包含其它组
[weball:children] #后跟children表示子组
webgrp1
webgrp2
#主机组指定变量
[weball:vars] #后跟vars设置变量
ansible_ssh_port=22
ansible_ssh_user=root
ansible_ssh_private_key_file=/root/.ssh/id_rsa
#ansible_ssh_pass=xiaobai123
#如果没有互传秘钥可以使用密码,使用密码就将ansible_ssh_private_key_file=/root/.ssh/id_rsa注释掉
#也可以自定义主机清单文件
#自定义的可以写在任意目录下
[root@ansible-server] vim /tmp/hostlist
[all]
ansible-web1
ansible-web2
[all:vars]
ansible_ssh_port=22
ansible_ssh_user=root
ansible_ssh_private_key_file=/root/.ssh/id_rsa
2、ansible内置参数
ansible常见的内置参数
参数 | 用途 |
---|---|
ansible_ssh_host | 定义hosts ssh地址 |
ansible_ssh_port | 定义hosts ssh端口 |
ansible_ssh_user | 定义hosts ssh认证用户 |
ansible_ssh_pass | 定义hosts ssh认证密码 |
ansible_sudo | 定义hosts sudo用户 |
ansible_sudo_pass | 定义hosts sudo密码 |
ansible_sudo_exe | 定义hosts sudo路径 |
ansible_connection | 定义hosts连接方式 |
anshible_ssh_private_key_file | 定义hosts私钥 |
ansible_ssh_shell_type | 定义hosts shell类型 |
ansible_python_interpreter | 定义hosts任务执行python路径 |
ansible_*_interpreter | 定义hosts其它语言解析路径 |
… | … |
查看主机组内的主机
#列出weball组里所有的主机
#如果不加参数,指定是默认主机清单文件
[root@ansible-server] ansible weball --list-hosts
hosts (2):
ansible-web1
ansible-web2
#加上-i参数后跟路径就会读取路径中配置的主机清单文件
[root@ansible-server] ansible -i /tmp/hostlist all --list-hosts
hosts (2):
ansible-web1
ansible-web2
三、Ansible的简单操作
1、基本语法
ansible的基本语法
ansible 主机名或主机组或ip或别名等 -m 模块 -a ‘命令’
-m:指定模块
-a:传递给后面的命令
注:最后可以跟-o
-o:友好显示,显示一行
[root@ansible-server] ansible weball -m ping -o #检测能否ping通
ansible-web1 | SUCCESS => {"changed": false, "ping": "pong"}
ansible-web2 | SUCCESS => {"changed": false, "ping": "pong"}
#我们在server端用ansible对ansible-web1执行的操作
[root@ansible-server] ansible ansible-web1 -m shell -a 'uptime'
ansible-web1 | SUCCESS | rc=0 >>
18:37:01 up 9:17, 3 users, load average: 0.00, 0.01, 0.05
#现在我们切换到ansible-web1上执行uptime命令
[root@ansible-web1] uptime
18:39:56 up 9:20, 2 users, load average: 0.00, 0.01, 0.05
#可以看到执行的效果是一样的,由于数据实时更新所以数据会不同
指定多台机器时用逗号分割,或者将之定义到一个主机组内
重定向输入到本地文件中
[root@ansible-server] ansible ansible-web1 -m shell -a 'df -Th' > /opt/a.txt #敲回车后不会有任何输出
#执行后我们换到ansible-web1上查看一下
[root@ansible-web1] cat /opt/a.txt
cat: /opt/a.txt: No such file or directory
#ansible-web1上并没有a.txt
#我们换回到server端
[root@ansible-server] cat /opt/a.txt
ansible-web1 | SUCCESS | rc=0 >>
Filesystem Type Size Used Avail Use% Mounted on
/dev/mapper/centos-root xfs 17G 1.2G 16G 7% /
devtmpfs devtmpfs 475M 0 475M 0% /dev
tmpfs tmpfs 487M 0 487M 0% /dev/shm
tmpfs tmpfs 487M 7.7M 479M 2% /run
tmpfs tmpfs 487M 0 487M 0% /sys/fs/cgroup
/dev/sda1 xfs 1014M 133M 882M 14% /boot
tmpfs tmpfs 98M 0 98M 0% /run/user/0
2、ansible里的常用模块
ansible是基于模块工作的,它上面有很多模块
[root@ansible-server] ansible-doc -l #查看所有模块
[root@ansible-server] ansible-doc -s yum #查看yum模块的使用信息
2.1、copy模块
#远程复制备份模块:copy
参数详解
src=:指定源文件路径
dest=:目标地址
owner=:指定属主
group=:指定属组
mode=:指定权限
backup=:如果目标地址已存在这个文件则会查看文件,文件有变化将原文件备份,无变化不做备份,备份文件包含时间信息,选项为yes|no
[root@ansible-server] vim /root/a.txt #在server端创建a.txt
xiaobai #在文件中写入xiaobai
#切换到web1上查看/opt/下有没有a.txt文件
[root@ansible-web1] cat /opt/a.txt
cat: /opt/a.txt: No such file or directory
#可以看到web1的/opt/下是没有a.txt的
[root@ansible-server] ansible webgrp1 -m copy -a 'src=/root/a.txt dest=/opt/ owner=root group=root mode='644' backup=yes' -o
ansible-web1 | SUCCESS => {"changed": true ...... "state": "file", "uid": 0}
#此时我们再切换到web1上查看
[root@ansible-web1] ll /opt/
total 4
-rw-r--r--. 1 root root 8 Mar 24 16:23 a.txt
[root@ansible-web1] cat /opt/a.txt
xiaobai
#这时候web1下已经有了a.txt文件,文件内容就是我们输入的xiaobai,属主属组为root,权限为644
#由于之前的/opt/下没有a.txt文件,所以备份开启也不备份
#我们再回到server端执行刚才的命令
[root@ansible-server] ansible webgrp1 -m copy -a 'src=/root/a.txt dest=/opt/ owner=root group=root mode='644' backup=yes' -o
ansible-web1 | SUCCESS => {"changed": false ...... "state": "file", "uid": 0}
#再次回到web1上查看有无备份文件
[root@ansible-web1] ls /opt/
a.txt
#这里我们可以看到,由于文件内容相同不进行备份
#我们先在web2的/opt/下创建一个a.txt文件
[root@ansible-web2] vim /opt/a.txt
little #在这个文件中写入little
#我们换回到server端执行命令
[root@ansible-server] ansible webgrp2 -m copy -a 'src=/root/a.txt dest=/opt/ owner=root group=root mode='644' backup=yes' -o
ansible-web2 | SUCCESS => {"backup_file": "/opt/a.txt.8548.2020-03-24@16:38:46~" ...... "state": "file", "uid": 0}
#此时我们回到web2查看
[root@ansible-web2] ls /opt/
a.txt a.txt.8548.2020-03-24@16:38:46~
#可以看到这里有两个文件,分别查看
[root@ansible-web2] cat /opt/a.txt.8548.2020-03-24\@16\:38\:46~
little
[root@ansible-web2] cat /opt/a.txt
xiaobai
#长的为原文件,原文件被备份并加上了日期时间
2.2、yum模块
#软件包管理模块:yum
参数详解
name=:安装包名
state=absent:用于卸载安装包
state=latest:表示安装最新的
state=removed:表示卸载
#state=absent和state=removed都是卸载,用哪个都可以
#先切换到web1查看有没有下载httpd服务
[root@ansible-web1] rpm -qa |grep httpd
#没有任何反馈就是没下载
#回到server端
[root@ansible-server] ansible webgrp1 -m yum -a 'name=httpd state=latest' #要等一定时间
ansible-web1 | SUCCESS => {"changed": true, "msg": "", "rc": 0, "results": ["Loaded plugins: fastestmirror
--> Running transaction check
......
Dependency Installed:
apr.x86_64 0:1.4.8-5.el7 apr-util.x86_64 0:1.5.2-6.el7
httpd-tools.x86_64 0:2.4.6-90.el7.centos mailcap.noarch 0:2.1.41-2.el7
Complete!
"]}
#安装成功,我们到web1上查看一下
[root@ansible-web1] rpm -qa |grep httpd
httpd-tools-2.4.6-90.el7.centos.x86_64
httpd-2.4.6-90.el7.centos.x86_64
#此时已经有了httpd,卸载的话用remove和absent都可以
2.3、service模块
#服务管理模块:service
参数详解
state=stopped:停止服务
state=restarted:重启服务
state=started:启动服务
enabled=yes:开机自启
enabled=no:开机关闭
[root@ansible-server] ansible webgrp1 -m service -a 'name=httpd state=started enabled=yes' -o
ansible-web1 | SUCCESS => {"changed": false, "enabled": true, "name": "httpd"
......
"WatchdogTimestampMonotonic": "32583844837", "WatchdogUSec": "0"}}
#我们切换到web1上查看
[root@ansible-web1] systemctl status httpd
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
Active: active (running) since Tue 2020-03-24 18:15:11 CST; 57s ago
2.4、file模块
#文件模块:file
参数详解
owner:修改属主
group:修改属组
mode:修改权限
path:修改文件的路径
recurse:递归设置的文件,只对目录有效,yes表示使用递归参数
state=touch:创建一个新的空文件
state=directory:创建一个新的目录,当目录存在时不会进行修改
#我们创建一个文件bai.txt属主为xiaobai
#先切换到web1
[root@xiaobai-web1] useradd xiaobai
[root@xiaobai-web1] id xiaobai
uid=1000(xiaobai) gid=1000(xiaobai) groups=1000(xiaobai)
#我们回到server端
[root@xiaobai-server] ansible webgrp1 -m file -a 'path=/tmp/bai.txt mode=777 owner=xiaobai state=touch' -o #不写属主属组的话默认为root
ansible-web1 | SUCCESS => {"changed": true ..... "state": "file", "uid": 1000}
#到web1上查看这个文件
[root@xiaobai-web1] ll /tmp
total 4
-rwxrwxrwx. 1 xiaobai root 0 Mar 24 18:36 bai.txt
#下面我们在web2上用递归修改目录属主属组
#首先我们先在web2上创建一个目录及文件查看一下
[root@xiaobai-web2] ll /xb
total 0
-rw-r--r--. 1 root root 0 Mar 24 18:43 little.txt
-rw-r--r--. 1 root root 0 Mar 24 18:43 xiaobai.txt
[root@xiaobai-web2] ll -d /xb
drwxr-xr-x. 2 root root 43 Mar 24 18:43 /xb
[root@xiaobai-web2] useradd bai
[root@xiaobai-web2] groupadd little
#创建好后我们到server端
[root@xiaobai-server] ansible webgrp2 -m file -a 'path=/xb owner=bai group=little state=directory recurse=yes' -o
ansible-web2 | SUCCESS => {"changed": true, "gid": 1001, "group": "little", "mode": "0755", "owner": "bai", "path": "/xb", "secontext": "unconfined_u:object_r:default_t:s0", "size": 43, "state": "directory", "uid": 1000}
#我们到web2上查看
[root@xiaobai-web2] ll /xb
total 0
-rw-r--r--. 1 bai little 0 Mar 24 18:43 little.txt
-rw-r--r--. 1 bai little 0 Mar 24 18:43 xiaobai.txt
[root@xiaobai-web2] ll -d /xb
drwxr-xr-x. 2 bai little 43 Mar 24 18:43 /xb
2.5、setup模块
#收集信息模块:setup
#只查询ipv4的地址
[root@xiaobai-server] ansible webgrp1 -m setup -a 'filter=ansible_all_ipv4_addresses' #只查询ipv4的地址
ansible-web1 | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"192.168.202.132"
]
},
"changed": false
}
#收集webgrp1主机组里主机的所有信息
[root@xiaobai-server] ansible webgrp1 -m setup #收集所有信息
ansible-web1 | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"192.168.202.132"
......
"module_setup": true
},
"changed": false
}
四、ansible剧本(playbook)
前面已经定义了ansible的主机组
[webgrp1]
ansible-web1
[webgrp2]
ansible-web2
接下来来了解ansible中最重要的playbok吧
核心元素:
variables #变量元素,可传递给tasks/templates使用。
tasks #任务元素,由模块定义的操作的列表,即调用模块完成任务。
templates #模板元素,使用了模板语法的文本文件。
handlers #处理器元素,通常指在某事件满足时触发的操作。
roles #角色元素。
1、简单的剧本
playbook格式:playbook由YMAL语言编写,YMAL格式是类似于JSON的文件格式,便于人理解和阅读,同时便于书写。
一个剧本里面可以有多个play,每个play只能有一个tasks,每个tasks可以有多个name
playbool的基础组件
- name:定义playbook或者task的名称(描述信息),每一个play都可以完成一个任务。
- hosts:hosts用于指定要执行指定任务的主机。
- user:remote_user则用于指定远程主机上的执行任务的用户。
- tasks:任务列表play的主体部分是task list,task list中的各任务按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个任务后再开始第二个。
- vars:定义变量(如果不使用内部变量需要提前定义)。
- vars_files:调用定义变量文件。
- notify:任务执行结果如果是发生更改了的则触发定义在handler的任务执行。
- handlers:用于当前关注的资源发生变化时采取一定指定的操作。
先创建一个YMAL格式的文件,结尾以 .yml 或 .ymal 都可以
[root@ansible-server] cd /etc/ansible/
[root@ansible-server] vim test.yml
在文件中按格式写入想要执行的操作
---
- hosts: webgrp1
user: root
tasks:
- name: playbook_test
file: state=touch path=/tmp/playbook.txt
#参数解释
hosts: 参数指定了对哪些主机进行操作
user: 参数指定了使用什么用户登录远程主机操作
tasks: 指定了一个任务
name: 参数同样是对任务的描述,在执行过程中会打印出来
写好后检测语法
[root@ansible-server] ansible-playbook --syntax-check test.yml
playbook: test.yml #这个反馈就是没有问题
#在当前目录下敲的是相对路径
[root@ansible-server] ansible-playbook test.yml #执行该剧本
'PLAY [webgrp1] *****************************************************************
......
ansible-web1 : ok=2 changed=1 unreachable=0 failed=0 '
#我们到web1机器上查看一下/tmp/下是否有playbook.txt文件
[root@ansible-web1] ll /tmp/playbook.txt
-rw-r--r--. 1 root root 0 Mar 25 17:30 /tmp/playbook.txt
1.1、触发器
上面是一个简单的剧本,下面我们来了解一下触发器
#参数详解
handlers:由特定条件触发的tasks
handlers:处理器
notify:触发器
[root@ansible-server] cd /etc/ansible/
[root@ansible-server] vim handlers.yml
触发器可以实现多级操作,剧本中开头的—也可以不写
- hosts: webgrp2
user: root
tasks:
- name: test copy
copy: src=/root/b.txt dest=/mnt
notify: test handlers
handlers:
- name: test handlers
shell: echo "abcd" >> /mnt/b.txt
#注意notify里的名字一定要和handlers里的name一样
#只有 copy 模块真正执行后,才会去调用下面的 handlers 相关的操作,追加内容。所以这种比较适合配置文件发生更改后,需要重启服务的操作。
保存并退出测试一下剧本
[root@ansible-server] ansible-playbook --syntax-check handlers.yml
playbook: handlers.yml
[root@ansible-server] ansible-playbook handlers.yml
ok: [ansible-web2]
TASK [test copy] ********************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: AnsibleFileNotFound: Could not find or access '/root/b.txt'
fatal: [ansible-web2]: FAILED! => {"changed": false, "msg": "Could not find or access '/root/b.txt'"}
to retry, use: --limit @/etc/ansible/handlers.retry
PLAY RECAP **************************************************************************
ansible-web2 : ok=1 changed=0 unreachable=0 failed=1
#这次反馈不是绿色的了,星号中间的是报错信息,我们来看一下
执行剧本之前一定要确定有我们要发的文件,没有的话就创建一个
[root@ansible-server] touch /root/b.txt
[root@ansible-server] ansible-playbook handlers.yml
'PLAY [webgrp2] **********************************************************************
......
ansible-web2 : ok=3 changed=2 unreachable=0 failed=0 '
#执行成功,我们到web2上查看
[root@ansible-web2] ll /mnt/b.txt
-rw-r--r--. 1 root root 5 Mar 25 17:49 /mnt/b.txt
[root@ansible-web2] cat /mnt/b.txt
abcd
#我们可以看到不仅文件拷贝了过去,还触发了我们的第二个指令,将abcd重定向到b.txt里
1.2、循环迭代
对迭代项的引用,固定变量名为”item”,使用with_item属性给定要迭代的元素,需要重复执行的任务。
#我们在web2上确定一下有没有安装httpd php php-mysql php-mbstring php-gd软件
[root@ansible-web2] rpm -q httpd php php-mysql php-mbstring php-gd
package httpd is not installed
package php is not installed
package php-mysql is not installed
package php-mbstring is not installed
package php-gd is not installed
#确定都没有后回到server端,有就卸载
[root@ansible-server] cd /etc/ansible/
[root@ansible-server] vim list.yml
接下来我们就用with_item属性
item相当于for循环里面的i
with_items取值,但不支持通配符
- hosts: webgrp2
remote_user: root
tasks:
- name: install packages
yum: name={{ item }} state=latest
with_items:
- httpd
- php
- php-mysql
- php-mbstring
- php-gd
检测
[root@ansible-server] ansible-playbook --syntax-check list.yml
playbook: list.yml
[root@ansible-server] ansible-playbook list.yml #这次时间会长一点
'PLAY [webgrp2] **********************************************************************
......
ansible-web2 : ok=2 changed=1 unreachable=0 failed=0 '
#我们到web2主机上
[root@ansible-web2] rpm -q httpd php php-mysql php-mbstring php-gd
httpd-2.4.6-90.el7.centos.x86_64
php-5.4.16-46.1.el7_7.x86_64
php-mysql-5.4.16-46.1.el7_7.x86_64
php-mbstring-5.4.16-46.1.el7_7.x86_64
php-gd-5.4.16-46.1.el7_7.x86_64
#可以看到都下载好了
1.3、自定义vars_files变量
变量调用语法: {{ var_name }}
我们要先创建变量目录
[root@ansible-server] mkdir /etc/ansible/vars
[root@ansible-server] cd /etc/ansible/vars/
[root@ansible-server] vim file.yml
在这个变量文件中写入
src_path: /root/test/b.txt
dest_path: /opt/test/
在server端创建/root/test/目录和/root/test/b.txt文件
[root@ansible-server] cd /etc/ansible/
[root@ansible-server] vim vars.yml
在文件中写入
- hosts: ansible-web1
user: root
vars_files:
- /etc/ansible/vars/file.yml
tasks:
- name: create directory
file: path={{ dest_path }} mode=755 state=directory
- name: copy file
copy: src={{ src_path }} dest={{ dest_path }}
#ansible-web1就是webgrp1主机组内的主机,不要忘记哦
检测
[root@ansible-server] ansible-playbook --syntax-check vars.yml
playbook: vars.yml
[root@ansible-server] ansible-playbook vars.yml
'PLAY [ansible-web1] *****************************************************************
......
ansible-web1 : ok=3 changed=1 unreachable=0 failed=0 '
#我们换到web1上查看
[root@ansible-web1] ll -d /opt/test/
drwxr-xr-x. 2 root root 19 Mar 25 18:30 /opt/test/
[root@ansible-web1] ls /opt/test/
b.txt
#我们可以看到不仅创建好了目录,文件也拷贝了过去,所以引用变量也是可以的
1.4、剧本多个play
在web1上创建一个名为mygrp的系统组,gid为2003,并且创建一个bai用户为系统用户,用户组为mygrp
在web2上下载apache并启动apache
#web1主机
[root@ansible-web1] id bai
id: bai: no such user
[root@ansible-web1] cat /etc/group |grep mygrp
#web2主机
[root@ansible-web2] rpm -q httpd
httpd-2.4.6-90.el7.centos.x86_64
[root@ansible-web2] yum -y remove httpd
#server主机
[root@ansible-server] cd /etc/ansible/
[root@ansible-server] vim play.yml
创建多个play
- hosts: webgrp1
user: root
tasks:
- name: create a group
group: name=mygrp gid=2003 system=true
- name: create a user
user: name=bai group=mygrp system=true
- hosts: webgrp2
user: root
tasks:
- name: install apache
yum: name=httpd state=latest
- name: start httpd service
service: name=httpd state=started
#group模块参数
#name参数:必须参数,用于指定组名称。
#state参数:用于指定组的状态,两个值可选,present,absent,默认为 present,设置为absent 表示删除组。
#gid参数:用于指定组的gid,不指定为随机。
#system参数:true为系统组,可选。
测试
[root@ansible-server] ansible-playbook --syntax-check play.yml
playbook: play.yml
[root@ansible-server] ansible-playbook play.yml
'PLAY [webgrp1] **********************************************************************
......
ansible-web1 : ok=3 changed=2 unreachable=0 failed=0
ansible-web2 : ok=3 changed=2 unreachable=0 failed=0 '
#web1主机
[root@ansible-web1] id bai
uid=998(bai) gid=2003(mygrp) groups=2003(mygrp)
[root@ansible-web1] cat /etc/group |grep mygrp
mygrp:x:2003:
#web2主机
[root@ansible-web2] rpm -q httpd
httpd-2.4.6-90.el7.centos.x86_64
[root@ansible-web2] systemctl status httpd
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
Active: 'active (running)' since Thu 2020-03-26 03:20:26 CST; 13min ago
1.5、when模块
先判断when条件是否成立,如果成立则继续执行当前模块的命令
[root@ansible-server] cd /etc/ansible/
[root@ansible-server] vim when.yml
- hosts: webgrp1
user: root
tasks:
- name: use when
file: state=touch path=/tmp/when.txt
- name: insert data
shell: echo 123 >> /tmp/when.txt
when: ansible_hostname == "ansible-web1" #when可以在shell上也可以在shell下
注意:when判断中的ansible-web1指的是被控节点上真正的主机名称,不是解析的名,如果被控节点的主机名不是ansible-web1则不会执行insert data的命令
测试
[root@ansible-server] ansible-playbook --syntax-check when.yml
playbook: when.yml
[root@ansible-server] ansible-playbook when.yml
'PLAY [webgrp1] **********************************************************************
......
ansible-web1 : ok=3 changed=2 unreachable=0 failed=0 '
#web1主机
[root@ansible-web1] ll /tmp/when.txt
-rw-r--r--. 1 root root 4 Mar 26 03:45 /tmp/when.txt
[root@ansible-web1] cat /tmp/when.txt
123
#可以看到我们执行成功了
1.6、剧本中定义变量
使用变量并不显示搜集主机相关信息
gather_facts参数:指定了在任务部分执行前,是否先执行setup模块获取主机相关信息,默认值为true,改成false之后在执行过程中不会搜集主机相关信息。
在文件中
五、roles角色
1、roles又是什么
roles是在ansible中playbooks的目录组织结构,模块化之后,成为roles的组织结构,易读,代码可重用,层次清晰
目录顺序
- role_name/:角色名称=目录。
- files/:存储一些可以用copy调用的静态文件。
- tasks/: 存储任务的目录,此目录中至少应该有一个名为main.yml的文件,用于定义各task。其它的文件需要由main.yml进行“包含”调用。
- handlers/:此目录中至少应该有一个名为main.yml的文件,用于定义各handler。其它的文件需要由(与notify:名字相同,方便notify通知执行下一条命令)通过main.yml进行“包含”调用。
- vars/:此目录中至少应该有一个名为main.yml的文件,用于定义各variable;其它的文件需要由main.yml进行“包含”调用。
- templates/:存储由template模块调用的模板文本。(也可以调用变量)
- site.yml:定义哪个主机应用哪个角色。
2、用roles创建一个nginx吧
[root@ansible-server] cd /etc/ansible/roles/ #role为自带目录,如果不存在可以创建
[root@ansible-server] mkdir nginx/{files,handlers,tasks,templates,vars} -p #递归创建
[root@ansible-server] touch site.yml nginx/{handlers,tasks,vars}/main.yml
[root@ansible-server] yum install -y tree #下载tree命令,结构树
[root@ansible-server] tree /etc/ansible/roles/nginx/
/etc/ansible/roles/nginx/
├── files
├── handlers
│ └── main.yml
├── tasks
│ └── main.yml
├── templates
└── vars
└── main.yml
#files目录和templates目录下还没有创建文件,先不着急
#创建nginx的测试文件
[root@ansible-server] echo 1234 > nginx/files/index.html
#安装nginx并配置模板,下载不了的先下载epel-release源
[root@ansible-server] yum install -y nginx && cp /etc/nginx/nginx.conf nginx/templates/nginx.conf.j2
#一定要将nginx的主配置文件结尾改为.j2结尾
#编写任务
[root@ansible-server] vim nginx/tasks/main.yml
任务中写入
---
- name: install epel
yum: name=epel-release state=latest
- name: install nginx
yum: name=nginx state=latest
- name: copy nginx.conf templte
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
- name: copy index.html
copy: /etc/ansible/roles/nginx/files/index.html dest=/usr/share/nginx/html/index.html
notify: start nginx
#注意这里的notify一定和nginx/handlers/main.yml的name一样
保存并退出,继续
[root@ansible-server] vim nginx/handlers/main.yml
文件中写入
---
- name: start nginx
service: name=nginx state=started
#这里的name一定要和nginx/tasks/main.yml的notify的名字一样
保存并退出,继续
vim nginx/templates/nginx.conf.j2
#以.j2结尾可以引用变量,
修改成如下内容,自定义变量
把worker_processes 后改为变量名,变量还没有定义,继续
[root@ansible-server] vim nginx/vars/main.yml #这个文件中写入变量的值
在文件中定义变量
worker_connections: 2
编写要执行的主机
[root@ansible-server] vim site.yml
文件中写入
---
- hosts: webgrp2
user: root
roles:
- nginx
保存并退出,检测
[root@ansible-server] ansible-playbook --syntax-check site.yml
playbook: site.yml
[root@ansible-server] ansible-playbook site.yml
#web2主机
[root@ansible-web2] netstat -lntp #或者ss -lntp
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 3102/nginx: master
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 926/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1007/master
tcp6 0 0 :::80 :::* LISTEN 3102/nginx: master
tcp6 0 0 :::22 :::* LISTEN 926/sshd
tcp6 0 0 ::1:25 :::* LISTEN 1007/master
[root@ansible-web2] cat /etc/nginx/nginx.conf | grep worker_processes #查看一下我们的变量
#worker_processes auto;
worker_processes 2;
#这里看到已经为2了