Ansible 是近年越来越火的一款运维自动化工具,是基于python语言开发的。底层基于ssh。
其主要功能是帮忙运维实现 IT 工作的自动化、降低人为操作失误,提升运维工作效率
常用于软件批量部署自动化、批量配置自动化、批量管理自动化、持续集成等。
saltstack
puppet
1.host inventory 主机清单
定义客户机 ---需要去控制的客户机,可以对客户机进行分组:如web组、db组、redis组、flask组、django组等
2.playbook 剧本,配置文档
写明了ansible需要哪些客户机做哪些事情
3.module 模块
每个模块实现相应的功能 安装软件、复制文件、服务管理(启动、停止、重启)、执行linux命令等
4.plugins 插件
依附于ansible的一个小软件,实现某个小功能。
Ansible 系统由控制主机对被管节点的操作方式可分为两类,即adhoc和playbook:
ad-hoc模式(点对点模式)
使用单个模块,支持批量执行单条命令。
ad-hoc 命令是一种可以快速输入的命令,而且不需要保存起来的命令
就相当于bash中的一句话shell。
playbook模式(剧本模式)
是Ansible主要管理方式,也是Ansible功能强大的关键所在。
playbook通过多个task集合完成一类功能,如Web服务的安装部署、数据库服务器的批量备份等。
可以简单地把playbook理解为通过组合多条ad-hoc操作的配置文件。
语法检测:
--syntax-check
-C
效果一样
[root@ansible playbooks]# ansible-playbook --syntax-check redis.yaml
[root@ansible playbooks]# ansible-playbook -C redis_v1.yaml
copy:从本机到远程,实现文件的分发,推送
参数说明:
src= 源文件路径
dest= 目标路径
注意src= 路径后面带/ 表示带里面的所有内容复制到目标目录下,不带/是目录递归复制过去
content= 自行填充的文件内容
owner 属主
group 属组
mode权限
fetch:从远程主机拉取文件到本机
[root@ansible ~]# ansible all -m fetch -a "src=/tmp/hi.txt dest=/tmp"
command:裸执行linux命令,不能识别管道
shell:执行linux命令,可以识别管道
service:配置相关服务
ansible webdaozhu -m service -a "name=nignx state=stopped enabled=true"
state的几种状态:
reloaded --优雅的重启
restarted ---重启
started --启动
stopped --停止
enabled =true 设置开机启动
yum:—安装卸载软件
常用参数说明:
enablerepo,disablerepo表示启用与禁用某repo库
name 安装包名
state (present' orinstalled', latest')表示安装, (absent' or `removed') 表示删除
eg:通过安装epel扩展源并安装nginx
[root@ansible ~]# ansible all -m yum -a "name=epel-release state=installed
[root@ansible ~]# ansible all -m yum -a "name=nginx state=installed"
script模块 = shell +copy
把本地的脚本传到远端执行;前提是到远端可以执行
ansible all -m script -a "/root/test.sh"
cron —设置计划任务
minute
hour
day
month
weekday
eg: ansible all -m cron -a "minute=0 hour=8-18 month=5 weekday=1-5 job='bash /root/iptables.sh' name=runiptables2"
删除计划任务
ansible all -m cron -a "name=update_time state=absent"
file --文件相关操作
设置文件属性(创建文件)
常用参数:
path目标路径
state directory为目录,link为软件链接
group 目录属组
owner 属主
等等,其他参数通过ansible-doc -s file 获取
示例:
创建目录
[root@ansible ~]# ansible all -m file -a "path=/var/tmp/hello.dir state=directory"
创建软件链接
ansible all -m file -a "src=/tmp/hi.txt path=/var/tmp/hi.link state=link"
HOST-PATTERN #匹配主机模式,如all表示所有主机
-m MOD_NAME #模块名 如:ping
-a MOD_ARGS #模块执行的参数
-f FORKS #生成几个子进行程执行
-C #(不执行,模拟跑)
-u Username #某主机的用户名
-c CONNection #连接方式(default smart)
完整示例:
[root@ansible ~]# ansible all -m shell -a "ifconfig|grep enp0s3"
安装在哪: ansible安装在linux里的管理节点上,被管理的机器不需要安装,但被管理的节点需要有ssh 服务,centos7/8 默认有安装openssh 可以提供ssh服务
如何安装: yum install ansible -y
ansible可以管理windows机器,但默认需要安装一些软件
在xshell 里 ---点工具---新建用户密钥生成向导---选择ecdsa类型的密钥--密钥长度默认---自定义密钥名称---密钥栏设为空(免密登录)---保存公钥文件到桌面----将公钥文件传到linux里,并将其放到/etc/.ssh/authorized_keys文件里(cat id_ecdsa_256_sc.pub >> authorized_keys)
实验环境:
3台虚拟机(centos7为例)
主机名:ansible ip:192.168.0.211
主机名:node1-web ip :192.168.0.172
主机名:node2-db ip :1921.68.0.173
实验步骤:
1,更改主机名
#临时修改主机名
[root@localhost ~]# hostname ansible
[root@localhost ~]# su - root
上一次登录:六 10月 17 15:22:31 CST 2020从 192.168.0.28pts/1 上
#永久修改主机名
[root@ansible ~]# vim /etc/hostname
[root@ansible ~]# cat /etc/hostname
ansible
#临时修改主机名
[root@server ~]# hostname node1-web
[root@server ~]# su - root
上一次登录:六 10月 17 15:00:05 CST 2020从 192.168.0.28pts/0 上
#永久修改主机名
[root@node1-web ~]# vim /etc/hostname
[root@node1-web ~]# cat /etc/hostname
node1-web
#临时修改主机名
[root@client ~]# hostname node2-db
[root@client ~]# su - root
上一次登录:六 10月 17 15:00:58 CST 2020从 192.168.0.28pts/0 上
#永久修改主机名
[root@node2-db ~]# vim /etc/hostname
[root@node2-db ~]# cat /etc/hostname
node2-db
2,先建立免密通道
[root@ansible ~]# ps aux|grep sshd
root 7048 0.0 0.4 112756 4312 ? Ss 15:04 0:00 /usr/sbin/sshd -D
root 7760 0.0 0.5 158760 5580 ? Ss 15:22 0:00 sshd: root@pts/1
root 17654 0.0 0.0 112724 988 pts/1 S+ 18:26 0:00 grep --color=auto sshd
[root@ansible ~]# cd /etc/ssh
[root@ansible ssh]# ls
moduli ssh_host_ecdsa_key ssh_host_ed25519_key.pub
ssh_config ssh_host_ecdsa_key.pub ssh_host_rsa_key
sshd_config ssh_host_ed25519_key ssh_host_rsa_key.pub
在ansible主机上生成ecdsa类型的密钥
[root@ansible ssh]# ssh-keygen -t ecdsa
Generating public/private ecdsa key pair.
Enter file in which to save the key (/root/.ssh/id_ecdsa):
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_ecdsa.
Your public key has been saved in /root/.ssh/id_ecdsa.pub.
The key fingerprint is:
SHA256:fH71sWdKHCMtVk3GPoSwK8UcpfCSc6vIIASI8LEZAXE root@ansible
The key's randomart image is:
+---[ECDSA 256]---+
|B+E. . oo...o|
|oo.= * +. =.|
| +. + O o..|
| . . = oo ..|
| . . S..o+ =..|
| . o .oo. = +o|
| o .. . o.+|
| . . o.|
| . |
+----[SHA256]-----+
[root@ansible ssh]# cd /root/.ssh/
[root@ansible .ssh]# ll
总用量 8
-rw-------. 1 root root 227 10月 17 18:31 id_ecdsa --私钥
-rw-r--r--. 1 root root 174 10月 17 18:31 id_ecdsa.pub --公钥
将公钥上传到被控制的服务器node1-web和node2-db上
#上传密钥至node1-web
[root@ansible .ssh]# ssh-copy-id -p22 -i id_ecdsa.pub [email protected]
/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "id_ecdsa.pub"
The authenticity of host '192.168.0.172 (192.168.0.172)' can't be established.
ECDSA key fingerprint is SHA256:RAFPf4IJfMT3AiTfKGqSw7oXSV6ij02Un3NfA0IIozY.
ECDSA key fingerprint is MD5:af:a3:30:a0:52:3b:a8:e6:df:e4:94:68:ca:bc:e9:42.
Are you sure you want to continue connecting (yes/no)? yes
/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
[email protected]'s password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh -p '22' '[email protected]'"
and check to make sure that only the key(s) you wanted were added.
#上传密钥至node2-db
[root@ansible .ssh]# ssh-copy-id -p22 -i id_ecdsa.pub [email protected]
/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "id_ecdsa.pub"
The authenticity of host '192.168.0.173 (192.168.0.173)' can't be established.
ECDSA key fingerprint is SHA256:RAFPf4IJfMT3AiTfKGqSw7oXSV6ij02Un3NfA0IIozY.
ECDSA key fingerprint is MD5:af:a3:30:a0:52:3b:a8:e6:df:e4:94:68:ca:bc:e9:42.
Are you sure you want to continue connecting (yes/no)? yes
/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
[email protected]'s password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh -p '22' '[email protected]'"
and check to make sure that only the key(s) you wanted were added.
在ansible主机上验证一下是否可以免密登录
[root@node1-web .ssh]# ssh '[email protected]'
Last login: Sat Oct 17 18:49:43 2020 from 192.168.0.172
[root@node2-db ~]#
[root@node1-web .ssh]# ssh '[email protected]'
Last login: Sat Oct 17 18:55:24 2020 from node1-web
[root@node1-web ~]#
查看主机清单–hosts文件
[root@ansible ~]# cd /etc/ansible
[root@ansible ansible]# ls
ansible.cfg hosts roles
[root@ansible ansible]# vim hosts
[root@ansible ansible]# cat hosts
# This is the default ansible 'hosts' file.
#
# It should live in /etc/ansible/hosts
#
# - Comments begin with the '#' character
# - Blank lines are ignored
# - Groups of hosts are delimited by [header] elements
# - You can enter hostnames or ip addresses
# - A hostname/ip can be a member of multiple groups
# Ex 1: Ungrouped hosts, specify before any group headers.
## green.example.com
## blue.example.com
## 192.168.100.1
## 192.168.100.10
# Ex 2: A collection of hosts belonging to the 'webservers' group
[web]
192.168.0.172
[db]
192.168.0.173
## [webservers]
## alpha.example.org
## beta.example.org
## 192.168.1.100
## 192.168.1.110
ansible 的简单使用
在ansible主机上使用某个模块,去所有主机上执行命令
[root@ansible ansible]# ansible all -m shell -a "ip add"
192.168.0.172 | CHANGED | rc=0 >>
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:91:4f:94 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.172/24 brd 192.168.0.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe91:4f94/64 scope link
valid_lft forever preferred_lft forever
192.168.0.173 | CHANGED | rc=0 >>
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:3f:f2:d9 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.173/24 brd 192.168.0.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe3f:f2d9/64 scope link
valid_lft forever preferred_lft forever
warning:新建文件夹用file模块比shell更好
[root@ansible ansible]# ansible all -m shell -a "mkdir /sc/lele -p"
[WARNING]: Consider using the file module with state=directory rather than
running 'mkdir'. If you need to use command because file is insufficient you
can add 'warn: false' to this command task or set 'command_warnings=False' in
ansible.cfg to get rid of this message.
192.168.0.172 | CHANGED | rc=0 >>
192.168.0.173 | CHANGED | rc=0 >>
指定主机组进行操作
[root@ansible ansible]# ansible db -m shell -a "mkdir /sc/lele/db -p"
[WARNING]: Consider using the file module with state=directory rather than
running 'mkdir'. If you need to use command because file is insufficient you
can add 'warn: false' to this command task or set 'command_warnings=False' in
ansible.cfg to get rid of this message.
192.168.0.173 | CHANGED | rc=0 >>
[root@ansible ansible]# ansible web -m shell -a "mkdir /sc/lele/web -p"
[WARNING]: Consider using the file module with state=directory rather than
running 'mkdir'. If you need to use command because file is insufficient you
can add 'warn: false' to this command task or set 'command_warnings=False' in
ansible.cfg to get rid of this message.
192.168.0.172 | CHANGED | rc=0 >>
ansible的常用命令
ansible-doc 查看某个模块的用法,相当于help,man,按q退出
[root@ansible ansible]# ansible-doc shell
> SHELL (/usr/lib/python2.7/site-packages/ansible/modules/c
The `shell' module takes the command name followed by
of space-delimited arguments. Either a free form comma
`cmd' parameter is required, see the examples. It is a
exactly like the [command] module but runs the command
a shell (`/bin/sh') on the remote node. For Windows ta
use the [win_shell] module instead.
* This module is maintained by The Ansible Core Team
* note: This module has a corresponding action plugin.
OPTIONS (= is mandatory):
- chdir
Change into this directory before running the command.
[Default: (null)]
type: path
version_added: 0.6
- cmd
The command to run followed by optional arguments.
[Default: (null)]
type: str
- creates
A filename, when it already exists, this step will *no
run.
[Default: (null)]
type: path
- executable
:
查看ansible有哪些模块,可以去官网查看具体内容
[root@ansible ansible]# ansible-doc -l
fortios_router_community_list
azure_rm_devtestlab_info
ecs_taskdefinition
avi_alertscriptconfig
tower_receive
netapp_e_iscsi_target
azure_rm_acs
fortios_log_syslogd2_filter
junos_rpc
na_elementsw_vlan
pn_ospf
pn_snmp_vacm
cp_mgmt_service_sctp
onyx_ospf
icx_command
cs_snapshot_policy
nxos_install_os
cnos_static_route
win_eventlog
vmware_category
vmware_host_feature_info
avi_cluster
na_ontap_user
......
:
常用模块:
copy
shell 执行shell命令
script 跑脚本
fetch 从远程主机拉取模块到本地
cron 创建计划任务
:
[root@ansible ansible]# mkdir /lianxi
[root@ansible ansible]# cd /lianxi
[root@ansible lianxi]# ls
[root@ansible lianxi]# vim feng.sh
[root@ansible lianxi]# cat feng.sh
#!/bin/bash
touch /root/feng{
1..10}.txt
在所有主机上新建用户
[root@ansible lianxi]# ansible all -m user -a "name=sczwx"
192.168.0.172 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"comment": "",
"create_home": true,
"group": 1001,
"home": "/home/sczwx",
"name": "sczwx",
"shell": "/bin/bash",
"state": "present",
"system": false,
"uid": 1001
}
192.168.0.173 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"comment": "",
"create_home": true,
"group": 1001,
"home": "/home/sczwx",
"name": "sczwx",
"shell": "/bin/bash",
"state": "present",
"system": false,
"uid": 1001
}
将ansible主机上的文件传送到各个主机上,并规定该文件的权限,属主和属组
[root@ansible lianxi]# ansible all -m copy -a "src=/lianxi/feng.sh dest=/root mode=777 owner=sczwx group=sczwx"
192.168.0.172 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"checksum": "22ae77faaa8e67b7d9b087fa7ffe6336cd6d46e3",
"dest": "/root/feng.sh",
"gid": 1001,
"group": "sczwx",
"md5sum": "a8142c12949d65cce2ed3add4e943d3a",
"mode": "0777",
"owner": "sczwx",
"secontext": "system_u:object_r:admin_home_t:s0",
"size": 41,
"src": "/root/.ansible/tmp/ansible-tmp-1602987387.13-18854-27236434212338/source",
"state": "file",
"uid": 1001
}
192.168.0.173 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"checksum": "22ae77faaa8e67b7d9b087fa7ffe6336cd6d46e3",
"dest": "/root/feng.sh",
"gid": 1001,
"group": "sczwx",
"md5sum": "a8142c12949d65cce2ed3add4e943d3a",
"mode": "0777",
"owner": "sczwx",
"secontext": "system_u:object_r:admin_home_t:s0",
"size": 41,
"src": "/root/.ansible/tmp/ansible-tmp-1602987387.13-18855-2677683065084/source",
"state": "file",
"uid": 1001
}
[root@ansible lianxi]#
将远程主机上的文件拉取到本地
[root@ansible lianxi]# ansible all -m fetch -a "src=/etc/passwd dest=/lianxi"
192.168.0.173 | CHANGED => {
"changed": true,
"checksum": "489f53603354949cde551f0805c37c7479e46b38",
"dest": "/lianxi/192.168.0.173/etc/passwd",
"md5sum": "8ef55b8ac28514959588d15a36534579",
"remote_checksum": "489f53603354949cde551f0805c37c7479e46b38",
"remote_md5sum": null
}
192.168.0.172 | CHANGED => {
"changed": true,
"checksum": "09134eb68efd7842beef48cee20514073cb0c51f",
"dest": "/lianxi/192.168.0.172/etc/passwd",
"md5sum": "5fa4efa58243dfe1b7c66939dbe5f1c1",
"remote_checksum": "09134eb68efd7842beef48cee20514073cb0c51f",
"remote_md5sum": null
}
[root@ansible lianxi]# tree
.
├── 192.168.0.172
│ └── etc
│ └── passwd
├── 192.168.0.173
│ └── etc
│ └── passwd
└── feng.sh
4 directories, 3 files
command和shell模块的区别
command和shell都可以执行linux命令,但command模块不能识别管道符号,即只能执行单一命令,不能识别组合命令,裸执行
file 模块 新建文件/文件夹
— state:touch 空文件 | directory 目录 |link 软链接文件| hard 硬链接 | absent 删除文件和文件夹
#新建文件夹
[root@ansible lianxi]# ansible all -m file -a "path=/gus state=directory"
192.168.0.172 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"path": "/gus",
"secontext": "unconfined_u:object_r:default_t:s0",
"size": 6,
"state": "directory",
"uid": 0
}
192.168.0.173 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"path": "/gus",
"secontext": "unconfined_u:object_r:default_t:s0",
"size": 6,
"state": "directory",
"uid": 0
}
#新建文件
[root@ansible lianxi]# ansible all -m file -a "path=/gus/lele.txt state=touch"
192.168.0.173 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"dest": "/gus/lele.txt",
"gid": 0,
"group": "root",
"mode": "0644",
"owner": "root",
"secontext": "unconfined_u:object_r:default_t:s0",
"size": 0,
"state": "file",
"uid": 0
}
192.168.0.172 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"dest": "/gus/lele.txt",
"gid": 0,
"group": "root",
"mode": "0644",
"owner": "root",
"secontext": "unconfined_u:object_r:default_t:s0",
"size": 0,
"state": "file",
"uid": 0
}
#新建链接文件
[root@ansible lianxi]# ansible all -m file -a "path=/gus/lele.txt state=touch"
192.168.0.173 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"dest": "/gus/lele.txt",
"gid": 0,
"group": "root",
"mode": "0644",
"owner": "root",
"secontext": "unconfined_u:object_r:default_t:s0",
"size": 0,
"state": "file",
"uid": 0
}
192.168.0.172 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"dest": "/gus/lele.txt",
"gid": 0,
"group": "root",
"mode": "0644",
"owner": "root",
"secontext": "unconfined_u:object_r:default_t:s0",
"size": 0,
"state": "file",
"uid": 0
}
[root@ansible lianxi]# ansible all -m file -a "src=/gus/lele.txt path=/gus/yanle state=link"
192.168.0.172 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"dest": "/gus/yanle",
"gid": 0,
"group": "root",
"mode": "0777",
"owner": "root",
"secontext": "unconfined_u:object_r:default_t:s0",
"size": 13,
"src": "/gus/lele.txt",
"state": "link",
"uid": 0
}
192.168.0.173 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"dest": "/gus/yanle",
"gid": 0,
"group": "root",
"mode": "0777",
"owner": "root",
"secontext": "unconfined_u:object_r:default_t:s0",
"size": 13,
"src": "/gus/lele.txt",
"state": "link",
"uid": 0
}
#删除文件
[root@ansible lianxi]# ansible all -m file -a "path=/gus/lele.txt state=absent"
192.168.0.172 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"path": "/gus/lele.txt",
"state": "absent"
}
192.168.0.173 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"path": "/gus/lele.txt",
"state": "absent"
}
计划任务模块 cron
五个时间段 从左到右 分别为
minute (0-59)
hour(0-23)
day of month(1-31)
month(1-12)
day of week(0-6)
[root@ansible lianxi]# ansible all -m cron -a "minute=*/3 job='date >>/gushuai/date.txt' name=gus_date"
192.168.0.172 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"envs": [],
"jobs": [
"gus_date"
]
}
192.168.0.173 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"envs": [],
"jobs": [
"gus_date"
]
}
#查看一下
[root@node2-db ~]# crontab -l
#Ansible: gus_date
*/3 * * * * date >>/gushuai/date.txt
[root@node1-web ~]# crontab -l
#Ansible: gus_date
*/3 * * * * date >>/gushuai/date.txt
您在 /var/spool/mail/root 中有邮件
由于名字一样,所以会把原来的替换掉
[root@ansible lianxi]# ansible all -m cron -a "minute=*/30 hour=1 day=15 month=10 job='bash /gus/gu.sh' name=gus_date"
192.168.0.172 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"envs": [],
"jobs": [
"gus_date"
]
}
192.168.0.173 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"envs": [],
"jobs": [
"gus_date"
]
}
[root@node1-web ~]# crontab -l
#Ansible: gus_date
*/30 1 15 10 * bash /gus/gu.sh
[root@node2-db ~]# crontab -l
#Ansible: gus_date
*/30 1 15 10 * bash /gus/gu.sh
删除计划任务
[root@ansible lianxi]# ansible all -m cron -a "name=gus_date state=absent"
192.168.0.172 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"envs": [],
"jobs": []
}
192.168.0.173 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"envs": [],
"jobs": []
}
小练习:在ansible 机器上写好脚本;把脚本推到node服务器上;创建计划任务
[root@ansible lianxi]# cat backup_log.sh
#!/bin/bash
#年-月-日形式显示
ctime=$(date +%F%H%M%S)
mkdir -p /backup
tar czf /backup/${ctime}-log.tar.gz /var/log
[root@ansible lianxi]# ansible all -m copy -a "src=/lianxi/backup_log.sh dest=/gus"
192.168.0.173 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"checksum": "8f60eabd3608114ebdeb0668eaf3ada43be7cb67",
"dest": "/gus/backup_log.sh",
"gid": 0,
"group": "root",
"mode": "0644",
"owner": "root",
"path": "/gus/backup_log.sh",
"secontext": "system_u:object_r:default_t:s0",
"size": 120,
"state": "file",
"uid": 0
}
192.168.0.172 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"checksum": "8f60eabd3608114ebdeb0668eaf3ada43be7cb67",
"dest": "/gus/backup_log.sh",
"gid": 0,
"group": "root",
"mode": "0644",
"owner": "root",
"path": "/gus/backup_log.sh",
"secontext": "system_u:object_r:default_t:s0",
"size": 120,
"state": "file",
"uid": 0
}
[root@ansible lianxi]#
[root@ansible lianxi]# ansible all -m cron -a "minute=30 hour=2 job='bash /gus/backup_log.sh' name=backup_cron"
192.168.0.173 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"envs": [],
"jobs": [
"backup_cron"
]
}
192.168.0.172 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"envs": [],
"jobs": [
"backup_cron"
]
}
[root@node2-db gus]# crontab -l
#Ansible: backup_cron
30 2 * * * bash /gus/backup_log.sh
yum 模块 ----安装软件
常用参数
name :安装的软件包名
state :present installed lastest 表示安装 absent/removed 表示删除
[root@ansible lianxi]# ansible all -m yum -a "name=tree state=installed"
192.168.0.173 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"changes": {
"installed": [
"tree"
]
},
"msg": "",
"rc": 0,
"results": [
"Loaded plugins: fastestmirror\nLoading mirror speeds from cached hostfile\n * base: mirrors.tuna.tsinghua.edu.cn\n * extras: mirrors.tuna.tsinghua.edu.cn\n * updates: mirrors.tuna.tsinghua.edu.cn\nResolving Dependencies\n--> Running transaction check\n---> Package tree.x86_64 0:1.6.0-10.el7 will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package Arch Version Repository Size\n================================================================================\nInstalling:\n tree x86_64 1.6.0-10.el7 base 46 k\n\nTransaction Summary\n================================================================================\nInstall 1 Package\n\nTotal download size: 46 k\nInstalled size: 87 k\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n Installing : tree-1.6.0-10.el7.x86_64 1/1 \n Verifying : tree-1.6.0-10.el7.x86_64 1/1 \n\nInstalled:\n tree.x86_64 0:1.6.0-10.el7 \n\nComplete!\n"
]
}
192.168.0.172 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"changes": {
"installed": [
"tree"
]
},
"msg": "",
"rc": 0,
"results": [
"Loaded plugins: fastestmirror\nLoading mirror speeds from cached hostfile\n * base: mirrors.163.com\n * epel: d2lzkl7pfhq30w.cloudfront.net\n * extras: mirrors.tuna.tsinghua.edu.cn\n * updates: mirrors.163.com\nResolving Dependencies\n--> Running transaction check\n---> Package tree.x86_64 0:1.6.0-10.el7 will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package Arch Version Repository Size\n================================================================================\nInstalling:\n tree x86_64 1.6.0-10.el7 base 46 k\n\nTransaction Summary\n================================================================================\nInstall 1 Package\n\nTotal download size: 46 k\nInstalled size: 87 k\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n Installing : tree-1.6.0-10.el7.x86_64 1/1 \n Verifying : tree-1.6.0-10.el7.x86_64 1/1 \n\nInstalled:\n tree.x86_64 0:1.6.0-10.el7 \n\nComplete!\n"
]
}
[root@node2-db gus]# tree
.
├── backup_log.sh
└── yanle -> /gus/lele.txt
0 directories, 2 files
[root@node2-db gus]#
多进程删除软件
-f n --启动n个进程去执行
[root@ansible lianxi]# ansible all -f 2 -m yum -a "name=tree state=removed"
192.168.0.172 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"changes": {
"removed": [
"tree"
]
},
"msg": "",
"rc": 0,
"results": [
"已加载插件:fastestmirror\n正在解决依赖关系\n--> 正在检查事务\n---> 软件包 tree.x86_64.0.1.6.0-10.el7 将被 删除\n--> 解决依赖关系完成\n\n依赖关系解决\n\n================================================================================\n Package 架构 版本 源 大小\n================================================================================\n正在删除:\n tree x86_64 1.6.0-10.el7 @base 87 k\n\n事务概要\n================================================================================\n移除 1 软件包\n\n安装大小:87 k\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n 正在删除 : tree-1.6.0-10.el7.x86_64 1/1 \n 验证中 : tree-1.6.0-10.el7.x86_64 1/1 \n\n删除:\n tree.x86_64 0:1.6.0-10.el7 \n\n完毕!\n"
]
}
192.168.0.173 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"changes": {
"removed": [
"tree"
]
},
"msg": "",
"rc": 0,
"results": [
"已加载插件:fastestmirror\n正在解决依赖关系\n--> 正在检查事务\n---> 软件包 tree.x86_64.0.1.6.0-10.el7 将被 删除\n--> 解决依赖关系完成\n\n依赖关系解决\n\n================================================================================\n Package 架构 版本 源 大小\n================================================================================\n正在删除:\n tree x86_64 1.6.0-10.el7 @base 87 k\n\n事务概要\n================================================================================\n移除 1 软件包\n\n安装大小:87 k\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n 正在删除 : tree-1.6.0-10.el7.x86_64 1/1 \n 验证中 : tree-1.6.0-10.el7.x86_64 1/1 \n\n删除:\n tree.x86_64 0:1.6.0-10.el7 \n\n完毕!\n"
]
}
service 模块
服务管理模块
常用参数
name 服务名
state 服务的状态
enabled 是否开机启动 true|false
runlevel 启动级别
安装ftp
[root@ansible lianxi]# ansible all -f 2 -m yum -a "name=vsftpd state=installed"
192.168.0.173 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"changes": {
"installed": [
"vsftpd"
]
},
"msg": "",
"rc": 0,
"results": [
"Loaded plugins: fastestmirror\nLoading mirror speeds from cached hostfile\n * base: mirrors.tuna.tsinghua.edu.cn\n * extras: mirrors.tuna.tsinghua.edu.cn\n * updates: mirrors.tuna.tsinghua.edu.cn\nResolving Dependencies\n--> Running transaction check\n---> Package vsftpd.x86_64 0:3.0.2-27.el7 will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package Arch Version Repository Size\n================================================================================\nInstalling:\n vsftpd x86_64 3.0.2-27.el7 base 172 k\n\nTransaction Summary\n================================================================================\nInstall 1 Package\n\nTotal download size: 172 k\nInstalled size: 353 k\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n Installing : vsftpd-3.0.2-27.el7.x86_64 1/1 \n Verifying : vsftpd-3.0.2-27.el7.x86_64 1/1 \n\nInstalled:\n vsftpd.x86_64 0:3.0.2-27.el7 \n\nComplete!\n"
]
}
192.168.0.172 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"changes": {
"installed": [
"vsftpd"
]
},
"msg": "",
"rc": 0,
"results": [
"Loaded plugins: fastestmirror\nLoading mirror speeds from cached hostfile\n * base: mirrors.163.com\n * epel: d2lzkl7pfhq30w.cloudfront.net\n * extras: mirrors.tuna.tsinghua.edu.cn\n * updates: mirrors.163.com\nResolving Dependencies\n--> Running transaction check\n---> Package vsftpd.x86_64 0:3.0.2-27.el7 will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package Arch Version Repository Size\n================================================================================\nInstalling:\n vsftpd x86_64 3.0.2-27.el7 base 172 k\n\nTransaction Summary\n================================================================================\nInstall 1 Package\n\nTotal download size: 172 k\nInstalled size: 353 k\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n Installing : vsftpd-3.0.2-27.el7.x86_64 1/1 \n Verifying : vsftpd-3.0.2-27.el7.x86_64 1/1 \n\nInstalled:\n vsftpd.x86_64 0:3.0.2-27.el7 \n\nComplete!\n"
]
}
[root@ansible lianxi]#
起服务
[root@ansible lianxi]# ansible all -m service -a "name=vsftpd state=started enabled=true"
192.168.0.172 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"enabled": true,
"name": "vsftpd",
"state": "started",
"status": {
"ActiveEnterTimestampMonotonic": "0",
"ActiveExitTimestampMonotonic": "0",
"ActiveState": "inactive",
"After": "systemd-journald.socket basic.target system.slice network.target",
"AllowIsolate": "no",
"AmbientCapabilities": "0",
"AssertResult": "no",
"AssertTimestampMonotonic": "0",
"Before": "shutdown.target",
"BlockIOAccounting": "no",
"BlockIOWeight": "18446744073709551615",
"CPUAccounting": "no",
"CPUQuotaPerSecUSec": "infinity",
"CPUSchedulingPolicy": "0",
"CPUSchedulingPriority": "0",
"CPUSchedulingResetOnFork": "no",
"CPUShares": "18446744073709551615",
"CanIsolate": "no",
"CanReload": "no",
"CanStart": "yes",
"CanStop": "yes",
"CapabilityBoundingSet": "18446744073709551615",
......
script模块
把本地的脚本传到远端执行,前提是到远端可以执行;=copy+shell
[root@ansible lianxi]# ansible all -m script -a "/lianxi/backup_log.sh"
192.168.0.172 | CHANGED => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to 192.168.0.172 closed.\r\n",
"stderr_lines": [
"Shared connection to 192.168.0.172 closed."
],
"stdout": "tar: 从成员名中删除开头的“/”\r\n",
"stdout_lines": [
"tar: 从成员名中删除开头的“/”"
]
}
192.168.0.173 | CHANGED => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to 192.168.0.173 closed.\r\n",
"stderr_lines": [
"Shared connection to 192.168.0.173 closed."
],
"stdout": "tar: 从成员名中删除开头的“/”\r\n",
"stdout_lines": [
"tar: 从成员名中删除开头的“/”"
]
}
[root@node2-db backup]# ls
2020-10-18131404-log.tar.gz
playbook是ansible的配置,部署,和编排的语言,playbook相当于一个指导手册
playbook 是基于YAML 语言格式配置的
playbook的核心元素
hosts playbook 配置文件作用的主机
tasks 任务列表
variables : 变量
templates 包含模板语法的文本文件
handlers 由特定条件触发的任务,异常捕获
roles 用于层次性,结构化的组织playbook, roles能够根据层次型结构自动装载变量文件,tasks以及handlers等
playbook运行方式
ansible-playbook --check 只检测可能会发生的改变,但不真执行操作
ansible-playbook --list-hosts 列出运行任务的主机
ansible-playbook --syntax-check playbook.yaml 语法检测
ansible-playbook -t TAGS_NAME playbook.yaml 只执行TAGS_NAME任务
实操
[root@ansible lianxi]# vim first_redis.yaml
[root@ansible lianxi]# cat first_redis.yaml
- hosts: all
remote_user: root
tasks:
- name: install redis
yum: name=redis state=installed
- name: start redis
service: name=redis state=started
- name: install tree
yum: name=tree state=installed
#语法检测
[root@ansible lianxi]# ansible-playbook --syntax-check first_redis.yaml
playbook: first_redis.yaml
[root@ansible lianxi]#
#查看playbook会在哪些机器上执行
[root@ansible lianxi]# ansible-playbook --list-hosts first_redis.yaml
playbook: first_redis.yaml
play #1 (all): all TAGS: []
pattern: [u'all']
hosts (2):
192.168.0.172
192.168.0.173
执行playbook
[root@ansible lianxi]# ansible-playbook first_redis.yaml
PLAY [all] *********************************************************************
TASK [Gathering Facts] *********************************************************
ok: [192.168.0.172]
ok: [192.168.0.173]
TASK [install redis] ***********************************************************
fatal: [192.168.0.173]: FAILED! => {
"changed": false, "msg": "No package matching 'redis' found available, installed or updated", "rc": 126, "results": ["No package matching 'redis' found available, installed or updated"]}
changed: [192.168.0.172]
TASK [start redis] *************************************************************
changed: [192.168.0.172]
TASK [install tree] ************************************************************
changed: [192.168.0.172]
PLAY RECAP *********************************************************************
192.168.0.172 : ok=4 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.0.173 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
可以看到,有一台机器上执行失败了,原因是因为该机器上未安装epel 源
[root@node2-db backup]# yum install redis
已加载插件:fastestmirror
Loading mirror speeds from cached hostfile
* base: mirrors.tuna.tsinghua.edu.cn
* extras: mirrors.tuna.tsinghua.edu.cn
* updates: mirrors.tuna.tsinghua.edu.cn
没有可用软件包 redis。
错误:无须任何处理
vars 变量的定义和使用
vars:
scredis:/lianxi/redis.conf ----定义变量
tasks:
…
copy:src={ {scredis}} dest=/etc/redis.conf owner=redis —引用变量
notify:restart redis ----通知,异常捕获,相当于python里的raise,常与handler连用,
handler : 处理异常
template 模板
和copy模板差不多,都可以实现将文件从管理节点上传到服务器节点,但是template 模块可以在模板文件里使用变量,因为template背后有jinjia2语法的支持,变量可以用自定义变量也可以用内置变量
yaml文件:template:src={ {scredis}} dest=/etc/redis.conf
模板文件:Redis.conf --bind { {ansible_facts[“ansible_all_ipv4_addresses”] [0] }}
roles --角色
https://www.cnblogs.com/yanjieli/p/10980057.html