1. ansible 批量操作和配置管理:
在本篇博文中,主要讲解如下几个知识点和实践经验,供大家参考:
1. ansible 简介:
2. ansible 常用模块的使用:
3. ansible playbook的使用:
1. ansible 简介:
1.1 Ansible简介:
ansible是一个基于python开发的轻量级自动化运维管理工具,可以用来批量执行命令,安装程序,支持playbook编排。它通过ssh协议来连接主机,去中心化,相对比puppet和saltstack无需安装客户即可实现文件传输、命令执行、应用部署、配置管理、任务编排等,显得更为简单与轻量。ansible只是提供一种框架,其基于模块工作的,本身没有批量部署。
1.2 Ansible核心组件:
1. 连接插件connection plugins:负责和被监控端实现通信;
2. host inventory:指定操作的主机,是一个配置文件里面定义监控的主机;
3. 各种模块核心模块、command模块、自定义模块;
4. 借助于插件完成记录日志邮件等功能;
5. playbook:剧本执行多个任务时,非必需可以让节点一次性运行多个任务。
1.3 Ansible特性:
1. no agents:不需要在被管控主机上安装任何客户端;
2. no server:无服务器端,使用时直接运行命令即可;
3. modules in any languages:基于模块工作,可使用任意语言开发模块;
4. yaml,not code:使用yaml语言定制剧本playbook;
5. ssh by default:基于SSH工作;
6. strong multi-tier solution:可实现多级指挥;
1.4 Ansible安装:
安装ansible server的条件,第一是LInux系统,第二是需要安装python2.7以上的版本,安装epel仓库源
yum install epel-release -y
yum install ansible -y
[root@rainbondmanager yum.repos.d]# ansible --version
ansible 2.8.1
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, Oct 30 2018, 23:45:53) [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)]
[root@rainbondmanager yum.repos.d]#
# 查看ansible的版本
# 在ansible server和 ansible client上面执行:
ssh-keygen -t rsa -P "" -f /root/.ssh/id_rsa
# 然后再在ansible server上面执行拷贝公钥文件到ansible client机器的/root/.ssh/authorized_keys文件
ssh-copy-id -i /root/.ssh/id_rsa 10.93.32.130
ssh-copy-id -i /root/.ssh/id_rsa 10.93.32.131
#ansible主要的配置文件和执行文件如下:
/etc/ansible/ansible.cfg
# ansible的主配置文件 这个文件主要定义了roles_path路径,主机清单路径,连接清单中的主机方式等配置,这些大部的默认配置已经足够我们平时使用,如需要特别配置可以自行去修改;
/etc/ansible/hosts
# 这个配置文件就是默认主机清单配置文件,可通过ansible.cfg重新定义的;
ansible #主执行程序,一般用于命令行下执行
ansible-playbook #执行playbook中的任务
ansible-doc #获取各模块的帮助信息
# 配置的/etc/ansible/hosts文件内容如下:
[websrvs]
10.83.32.130
10.83.32.131
2. ansible 常用命令模块:
ansible有很多模块可以使用,我们这里只介绍一些常用的模块,首先来看一下ansible的命令行格式:
ansible
HOST-PATTERN #匹配主机模式,如all表示所有主机
-m MOD_NAME #模块名 如:ping
-a MOD_ARGS #模块执行的参数
-f FORKS #生成几个子进行程执行
-C #(不执行,模拟跑)
-u Username #某主机的用户名
-c CONNection #连接方式(default smart)
ansible模块比较多,可以通过ansible-doc --help 显示帮助信息
ansible doc -l 获取所有当前版本下的可用模块及简要信息
ansible-doc -s 模块名 获取指定模块帮助信息说明``
2.1 COPY模块:从本地copy文件分发到目录主机路径
参数说明:
src= 源文件路径
dest= 目标路径
注意src= 路径后面带/ 表示带里面的所有内容复制到目标目录下,不带/是目录递归复制过去
content= 自行填充的文件内容
owner 属主
group 属组
mode权限
ansible all -m copy -a "src=/data/ncp/pom.xml dest=/tmp/pom.xml mode=600"
ansible all -m copy -a "content='hello ansible\n' dest=/tmp/hello.txt" #通过输入文件的内容来生成文件
ansible all -m shell -a "cat /tmp/hello.txt" #查看远程主机上的文件
2.2 fetch模块:从远程主机拉取文件到本地
[root@rainbondmanager ncp]# ansible all -m fetch -a "src=/tmp/hello.txt dest=/tmp"
10.83.32.131 | CHANGED => {
"changed": true,
"checksum": "df800445bb74b4abb144b3f9bf03f90aa9618f4c",
"dest": "/tmp/10.83.32.131/tmp/hello.txt",
"md5sum": "f61d358bbdd6a9bd2e93322023a4e29d",
"remote_checksum": "df800445bb74b4abb144b3f9bf03f90aa9618f4c",
"remote_md5sum": null
}
10.83.32.130 | CHANGED => {
"changed": true,
"checksum": "df800445bb74b4abb144b3f9bf03f90aa9618f4c",
"dest": "/tmp/10.83.32.130/tmp/hello.txt",
"md5sum": "f61d358bbdd6a9bd2e93322023a4e29d",
"remote_checksum": "df800445bb74b4abb144b3f9bf03f90aa9618f4c",
"remote_md5sum": null
}
[root@rainbondmanager ncp]# ls /tmp/10.83.32.131/tmp/hello.txt
/tmp/10.83.32.131/tmp/hello.txt
[root@rainbondmanager ncp]#
#说明:fetch使用很简单,src和dest,dest只要指定一个接收目录,默认会在后面加上远程主机及src的路径
2.3 command模块: 在远程主机上执行命令,属于裸执行,非键值对显示;不进行shell解析;
[root@rainbondmanager ncp]# ansible all -m command -a "ifconfig"
10.83.32.131 | CHANGED | rc=0 >>
ens192: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.83.32.131 netmask 255.255.255.0 broadcast 10.83.32.255
inet6 fe80::e40:453c:4d1:d859 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:62:5a:6a txqueuelen 1000 (Ethernet)
RX packets 4703751 bytes 322962815 (308.0 MiB)
RX errors 0 dropped 7 overruns 0 frame 0
TX packets 22169 bytes 1642865 (1.5 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
10.83.32.130 | CHANGED | rc=0 >>
ens192: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.83.32.130 netmask 255.255.255.0 broadcast 10.83.32.255
inet6 fe80::ae8b:7313:3f36:ca25 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:0e:2f:ab txqueuelen 1000 (Ethernet)
RX packets 4703839 bytes 322848456 (307.8 MiB)
RX errors 0 dropped 17 overruns 0 frame 0
TX packets 22942 bytes 1621244 (1.5 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@rainbondmanager ncp]# ansible all -m command -a "ifconfig|grep ens192"
10.83.32.130 | FAILED | rc=2 >>
[Errno 2] No such file or directory
10.83.32.131 | FAILED | rc=2 >>
[Errno 2] No such file or directory
# 由于commnad只能执行裸命令(即系统环境中有支持的命令),至于管道之类的功能不支持,
shell模块可以做到
2.4 shell模块: 可以使用复杂的管道命令
[root@rainbondmanager ncp]# ansible all -m shell -a "ifconfig|grep ens192"
10.83.32.130 | CHANGED | rc=0 >>
ens192: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
10.83.32.131 | CHANGED | rc=0 >>
ens192: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
[root@rainbondmanager ncp]#
2.5 file模块: 设置文件属性,创建目录等
常用参数:
path目标路径
state directory为目录,link为软件链接
group 目录属组
owner 属主等,其他参数通过ansible-doc -s file 获取
# 创建目录
[root@rainbondmanager ncp]# ansible all -m file -a "path=/var/tmp/hello.dir state=directory"
10.83.32.130 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"path": "/var/tmp/hello.dir",
"secontext": "unconfined_u:object_r:user_tmp_t:s0",
"size": 6,
"state": "directory",
"uid": 0
}
10.83.32.131 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"path": "/var/tmp/hello.dir",
"secontext": "unconfined_u:object_r:user_tmp_t:s0",
"size": 6,
"state": "directory",
"uid": 0
}
[root@rainbondmanager ncp]# ansible all -m shell -a "ls -l /var/tmp/hello.dir"
10.83.32.131 | CHANGED | rc=0 >>
total 0
10.83.32.130 | CHANGED | rc=0 >>
total 0
[root@rainbondmanager ncp]#
# 配置软链接
[root@rainbondmanager ncp]# ansible all -m file -a "src=/etc/fstab path=/var/tmp/fstab.link state=link"
10.83.32.131 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"dest": "/var/tmp/fstab.link",
"gid": 0,
"group": "root",
"mode": "0777",
"owner": "root",
"secontext": "unconfined_u:object_r:user_tmp_t:s0",
"size": 10,
"src": "/etc/fstab",
"state": "link",
"uid": 0
}
10.83.32.130 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"dest": "/var/tmp/fstab.link",
"gid": 0,
"group": "root",
"mode": "0777",
"owner": "root",
"secontext": "unconfined_u:object_r:user_tmp_t:s0",
"size": 10,
"src": "/etc/fstab",
"state": "link",
"uid": 0
}
[root@rainbondmanager ncp]# ansible all -m shell -a "ls -l /var/tmp/fstab.link"
10.83.32.131 | CHANGED | rc=0 >>
lrwxrwxrwx. 1 root root 10 Jul 23 04:29 /var/tmp/fstab.link -> /etc/fstab
10.83.32.130 | CHANGED | rc=0 >>
lrwxrwxrwx. 1 root root 10 Jul 23 04:29 /var/tmp/fstab.link -> /etc/fstab
2.6 cron模块:设置定时任务
通过cron模块对目标主机生成计划任务
常用参数:
除了分(minute)时(hour)日(day)月(month)周(week)外
name: 本次计划任务的名称
state: present 生成(默认) |absent 删除 (基于name)
示例:对各主机添加每隔3分钟从time.windows.com同步时间
[root@rainbondmanager ~]# ansible all -m cron -a "minute=*/3 job='/usr/sbin/update time.windows.com &>/dev/null' name=update_time" #增加crontab任务,指定每3分钟同步时间
10.83.32.130 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"envs": [],
"jobs": [
"update_time"
]
}
10.83.32.131 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"envs": [],
"jobs": [
"update_time"
]
}
[root@rainbondmanager ~]# ansible all -m shell -a "crontab -l"
10.83.32.131 | CHANGED | rc=0 >>
#Ansible: update_time
*/3 * * * * /usr/sbin/update time.windows.com &>/dev/null
10.83.32.130 | CHANGED | rc=0 >>
#Ansible: update_time
*/3 * * * * /usr/sbin/update time.windows.com &>/dev/null
示例2:删除计划任务
[root@rainbondmanager ~]# ansible all -m cron -a "name=update_time state=absent" #删除crontab任务
10.83.32.131 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"envs": [],
"jobs": []
}
10.83.32.130 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"envs": [],
"jobs": []
}
[root@rainbondmanager ~]# ansible all -m shell -a "crontab -l"
10.83.32.131 | CHANGED | rc=0 >>
10.83.32.130 | CHANGED | rc=0 >>
2.7 yum模块:yum安装软件包的模块
常用参数说明:
enablerepo,disablerepo表示启用与禁用某repo库
name 安装包名
state (present' orinstalled', latest')表示安装, (absent' or `removed') 表示删除
示例:通过安装epel扩展源并安装nginx
ansible all -m yum -a "name=epel-release state=installed"
ansible all -m yum -a "name=nginx state=installed"
2.8 service模块:服务管理模块
服务管理模块
常用参数:
name:服务名
state:服务状态
enabled: 是否开机启动 true|false
runlevel: 启动级别 (systemed方式忽略)
ansible all -m service -a "name=nginx state=started enabled=true"
#把刚才安装的nginx软件设置成开机启动,并且启动此服务
iptables -I INPUT -p tcp --dport 80 -j ACCEPT
#由于目标机器有安装防火墙软件,需要增加防火墙开放策略
2.9 script模块:把本地的脚本传到远端执行
# 在ansible服务器上面创建一个test.sh的脚本
[root@rainbondmanager ~]# cat test.sh
#!/bin/bash
ipaddr=$(ip addr|grep ens192|grep inet|awk '{print $2}'|awk -F "/" '{print $1}')
echo "This host ip address is ${ipaddr}" >> /tmp/ip.txt
ansible all -m script -a "/root/test.sh"
今天就先写到这里了,针对ansible的使用我还会再出几篇博文,包括后续的ansible-playbook的定义,roles分层目录的管理等,大家可以持续关注;