通过ansible批量管理Linux服务器:配置Inventory和批量执行命令

栏目: 服务器 · 发布时间: 6年前

内容简介:ansible是一款比较新的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。主要包括:(1)、连接插件connection plugins:负责和被监控端实现通信;

ansible是一款比较新的自动化运维工具,基于 Python 开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。

ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。主要包括:

(1)、连接插件connection plugins:负责和被监控端实现通信;

(2)、host inventory:指定操作的主机,是一个配置文件里面定义监控的主机;

(3)、各种模块:核心模块、command模块、自定义模块;

(4)、借助于插件完成记录日志邮件等功能;

(5)、playbook:剧本执行多个任务时,非必需可以让节点一次性运行多个任务。

ansible的安装部署我这里就不讲了,可以参考官方文档。这里我将分成三个部分进行讲解:1、配置Inventory,2、批量执行命令,3、playbook作业。

系统环境:

服务器 IP地址 操作系统 所需软件
ansible主机 192.168.2.203 Centos 7 64位 ansible
远程机器1 192.168.2.205 Centos 7 64位 httpd
远程机器2 192.168.2.208 Centos 7 64位 httpd

一、ansible常用的五个命令

1、ansible

ansible是指令核心部分,其主要用于执行ad-hoc命令,即单条命令。命令格式:ansible <host-pattern> [options],默认不指定模块时,使用的是command模块。

示例:查看主机的date信息

ansible 192.168.2.205 -a "date"

2、ansible-doc

该指令用于查看模块信息,常用参数有两个-l和-s,-l是查看ansible已安装的所有模块。

示例:查看cron模块的信息

ansible-doc -s cron

3、ansible-galaxy

该指令用于从https://galaxy.ansible.com/ 站点下载第三方扩展模块,相当于yum、pip、easy_install等命令。

示例:安装一个第三方扩展模块

ansible-galaxy install &lt;模块名&gt;

实际应用中也可以指定txt或yml文件进行多个组件的下载安装,具体使用方法请参见官方文档。

4、ansible-config

查看、编辑和管理ansible的配置文件

示例:只显示已更改的配置

ansible-config dump --only-changed

5、ansible-playbook

这个指令很重要,通过读取playbook作业文件,在节点主机上执行,相当于执行一个 shell 脚本的功能,ansible自动化不可或缺的,也是我后面要重点讲的内容。

二、创建ssh key授权

ansible是通过ssh方式管理远程服务器的,所以首先需要先打通ssh通道。我们在管理大批量服务器时,为了避免远程操作时重复输入密码,最好使用sshd服务的安全密钥验证方式。

通过ssh-keygen来管理密钥,即使在创建密钥时设置了密码,执行过ssh-add之后,会创建一个新的会话,以后的每次连接都无须输入密钥密码了。建议使用ssh key授权方式,并且不要设置密钥密码,这样可以更好地实现自动化。

ssh-keygen   # 创建公钥和私钥文件
ssh-copy-id 192.168.2.205   # 将公钥文件copy到远程主机上
ssh-copy-id 192.168.2.208
ssh-agent bash   # 通过ssh-agent来管理密钥
ssh-add ~/.ssh/id_rsa  # 将私钥交给ssh-agent管理,避免每次连接都需要输入密钥密码

三、配置Inventory文件

默认的Inventory文件是/etc/ansible/hosts,格式与windows的ini配置文件类似

1、按IP地址来配置

例如:我现在有2台主机,IP地址分别为192.168.2.205和192.168.2.208,并且两台主机都是web服务器,那么可以定义一个web_server组,如下:

[web_server]
192.168.2.205
192.168.2.208

如果修改了ssh端口号的话,可以按如下方式来定义:

[web_server]
192.168.2.205:5210
192.168.2.208:5210

如果我有一台主机IP为192.168.2.203不属于任何组,可以按如下方式来定义:

192.168.2.203

[web_server]
192.168.2.205
192.168.2.208

给主机设置一个别名,在这个例子中,通过“webserver1”别名,会连接192.168.2.205。

Webserver1 ansible_ssh_port=5210 ansible_ssh_host=192.168.2.205
Webserver2 ansible_ssh_port=5210 ansible_ssh_host=192.168.2.208

可以单独设置连接用户名和连接类型:

[web_server]
192.168.2.203       ansible_connection=local
192.168.2.205:5210   ansible_connection=ssh   ansible_ssh_user=xuad
192.168.2.208:5210   ansible_connection=ssh   ansible_ssh_user=andyxu

2、按主机名配置

按主机名配置和按IP地址配置一样,只需把IP改成主机名即可,例如:

[web_server]
web1.com
web2.com

[db_server]
db1.com:5210
db2.com:5210

[targets]
ansible.com       ansible_connection=local
other1:5210   ansible_connection=ssh   ansible_ssh_user=xuad
Other2:5210   ansible_connection=ssh   ansible_ssh_user=andyxu

例如有一组db服务器,分别为db1.xuad.com到db50.xuad.com,共50台db服务器

[db_server]
db[1:50].xuad.com:5210

如果是dba.xuad.com到dbf.xuad.com,共6台db服务器

[db_server]
db[a:f].xuad.com:5210

3、给主机设置变量

分配变量给主机很简单,这些变量定义后可在playbooks中使用。

[web_server]
web1.com  http_port=80  pathname=/etc/httpd/
web2.com  http_port=8081  pathname=/etc/nginx/

4、给组分配变量

下面例子是给web_server组定义两个变量,http_port和pathname。

[web_server]
web1.com
web2.com

[web_server:vars]
http_port=80
pathname=/etc/httpd/

5、把一个组作为另一个组的子成员

下面例子是把web_server和db_server两个组分配给some_server组,作为some_server组的子组,并分配变量给some_server组使用,再把some_server组分配给user_server组,作为user_server组的子组。

[web_server]
192.168.2.205
192.168.2.208

[db_server]
db1.com:5210
db2.com:5210

[some_server:children]
web_server
db_server

[some_server:vars]
http_port=80
nginx_port=8080
pathname=/etc/ansible/
xuad=foo.xuad.com

[user_server:children]
some_server
other_server
Northserver

6、分文件定义主机和组变量

假设有一台主机为192.168.2.205,属于web_server组,现在分别给web_server组和192.168.2.205主机定义变量,那么hosts文件增加如下内容:

/etc/ansible/group_vars/web_server
/etc/ansible/host_vars/192.168.2.205

创建group_vars和host_vars目录

mkdir /etc/ansible/group_vars
mkdir /etc/ansible/host_vars

然后编辑web_server文件,可按如下内容定义变量,注意:号后面有个空格。

vim /etc/ansible/group_vars/web_server

http_port: 80
http_path: /data/httpd/
ntp_server: ntp.xuad.com
db_server: db1.com

再编辑192.168.2.205文件,可按如下内容定义变量

vim /etc/ansible/host_vars/192.168.2.205

nginx_port: 8081
nginx_path: /data/nginx/
db_server: db2.com

还有更进一步的运用,可以为一个主机或者一个组创建一个目录,目录名就是主机名或组名,目录中可以创建多个文件,文件中的变量都会被读取为主机或组的变量,host文件内容如下:

/etc/ansible/group_vars/web_server/192.168.2.205
/etc/ansible/group_vars/db_server/db1.com

Inventory文件的参数可以查看ansible官方文档,下面我们来看官方文档的一个主机文件的例子,并说明每行都是什么意思。

#给some_host主机定义了ssh连接的端口号和用户名
some_host         ansible_ssh_port=2222     ansible_ssh_user=manager
#连接aws_host主机时将通过以下定义的私钥文件进行验证
aws_host          ansible_ssh_private_key_file=/home/example/.ssh/aws.pem
#给freebasd_host主机指定了python的路径
freebsd_host      ansible_python_interpreter=/usr/local/bin/python
#给ruby_module_host主机指定了 ruby 运行的路径
ruby_module_host  ansible_ruby_interpreter=/usr/bin/ruby.1.9.3

ansible还可以从外部获取Inventory配置信息,获取途径有以下几种:

1、从云端拉取inventory

2、从LDAP获取配置

3、从cobbler获取配置

4、从CMDB获取配置

从外部获取inventory配置的方法我这里就不讲了,有兴趣的可以查看官方文档。

四、ansible批量执行命令

首先在inventory的配置文件/etc/ansible/hosts里定义一个主机组,内容如下:

vim /etc/ansible/hosts

通过ansible批量管理 <a href='https://www.codercto.com/topics/18170.html'>Linux</a> 服务器:配置Inventory和批量执行命令

(1)我们先来ping一下,看下两台主机的连通情况

ansible web_server -m ping
通过ansible批量管理Linux服务器:配置Inventory和批量执行命令

(2)查看web_server组下有哪些主机

ansible web_server --list
通过ansible批量管理Linux服务器:配置Inventory和批量执行命令

(3)查看一台主机的内存使用情况

命令格式:ansible <主机或主机组> -a “shell命令”

注:执行一条命令使用-a参数,后面跟shell命令

ansible 192.168.2.205 -a "free -h"

(4)在web_server组批量创建一个普通用户

ansible web_server -a "useradd andy"

(5)重启所有主机的httpd服务

命令格式:ansible <主机组> -m <模块名称> -a <指定执行参数>

注:使用all参数就是对hosts文件里配置的所有主机执行命令

ansible all -m service -a "name=httpd state=restarted"

也可以使用ansible all -a "systemctl status httpd"语句,结果是一样的,但输出信息不同,可自行测试看看。

(6)查看多个组下各主机指定用户的UID和GID

命令格式:ansible <主机组1>:<主机组2>:<主机组3> -a "shell命令"

ansible http1:http2 -a "id andy"
通过ansible批量管理Linux服务器:配置Inventory和批量执行命令

(7)排除一个特定组,在web_server组下的不属于http1组的主机的/tmp目录下新建一个文件

命令格式:ansible '<主机组1>:!<主机组2>' -a "shell命令"

注:执行命令的主机属于webserver组,但不属于http1组

ansible 'web_server:!http1' -a "touch /tmp/test.txt"
通过ansible批量管理Linux服务器:配置Inventory和批量执行命令

此时ansible会给出一个警告信息,意思是说ansible已经内置有file模块,建议使用file模块创建文件,如果想取消警告信息,可以修改配置文件ansible.cfg,把command_warnings参数改成False,就不会再给出警告信息了。其实创建文件可以使用下面这条命令,结果是一样的,关于模块的使用后面会讲到。

ansible 'web_server:!http1' -m file -a "dest=/tmp/test.txt state=touch"

(8)指定两个组的交集,查看属于web_server组又属于http1组的主机的负载情况

注:!表示属于前面的组但不属于后面的组;&表示即属于前面的组也属于后面的组。

ansible 'web_server:&http1' -a "uptime"
通过ansible批量管理Linux服务器:配置Inventory和批量执行命令

(9)在即属于web_server组又属于http2组但不属于http1组的主机删除/tmp/test.txt文件内容

ansible 'web_server:!http1:&http2' -a "rm -f /tmp/test.txt"

(10)通配符使用,查看以http开头的所有组的主机的字符编码

ansible http* -a "cat /etc/locale.conf"

(11)查看以http开头的所有组和web_server组的所有主机的磁盘使用情况

ansible http*:web_server -a "df -h"

(12)查看web_server组的第一台主机的hostname

ansible web_server[0] -a "hostname"

(13)查看web_server组的前5台主机的当前日期和时间

ansible web_server[0:4] -a "date '+%Y-%m-%d %H:%M:%S'"

(14)正则表达式使用,查看以web或者http开头的组的主机的httpd服务的进程PID

ansible '~(web|http)*' -a "pidof httpd"

(15)其它正则表达式例子

ansible '~(web|http)2' -a "pidof sshd"  # web2或者http2主机或者组
ansible '~(^web)*' -a "pidof sshd"  # 以web开头的主机或者组
ansible '~(web|db).*\.example\.com' -a "pidof sshd"  # web.*.example.com或者db.*.example.com主机或者组

(16)如果不想使用ssh-agent,想通过密码验证的方式使用ssh,可以在执行ansible命令时使用--ask-pass或-k参数。

ansible web_server -a "shell命令" --ask-pass
ansible web_server -a "shell命令" -k

(17)批量重启服务器,加-f 10选项可以fork出10个子进程(bash),以并行的方式执行reboot命令,即每次重启10个

ansible web_server -a "/sbin/reboot" -f 10

(18)在执行ansible命令时,默认是以当前用户的身份去执行,如果想以指定的用户执行命令,需添加-u username选项

ansible web_server -a "shell命令" -u username  # ssh安全密钥验证方式
ansible web_server -a "shell命令" -u username -k  # ssh账号密码验证方式

(19)以sudo去执行命令

如果设置了sudo不需要输入密码的话,可不加--ask-sudo-pass;如果sudo需要输入密码的话,必须加--ask-sudo-pass参数。建议设置成sudo不需要输入密码,这样更容易实现自动化。

ansible web_server -a "shell命令" -u username --sudo
ansible web_server -a "shell命令" -u username --sudo --ask-sudo-pass

(20)也可以通过-sudo-user或-U选项,使用sudo切换到其它用户,而不是root用户

ansible web_server -a "shell命令" -u username -U otheruser [--ask-sudo-pass]

ansible有许多模块,默认是“command”,也就是命令模块,我们前面执行的那些语句都是以command模块执行的,下面来看一个例子。

(21)统计无法登陆系统的用户数量,即nologin用户数

ansible web_server -a "grep '/sbin/nologin' /etc/passwd | wc -l"

发现执行后会报错,无法得到我们想要的结果

通过ansible批量管理Linux服务器:配置Inventory和批量执行命令

这是因为command模块不支持shell命令的变量、管道符等,如果你想使用shell相关的这些东西,可以使用shell模块,用-m参数指定要运行的模块即可。

ansible web_server -m shell -a "grep '/sbin/nologin' /etc/passwd | wc -l"
通过ansible批量管理Linux服务器:配置Inventory和批量执行命令

(22)查看模块的帮助信息

ansible-doc shell

(23)查看web_server组各主机的ip地址

ansible web_server -m shell -a "/sbin/ifconfig | grep 'inet ' | awk '{print \$2}' | sed -e '/127\.0\.0\.1/d'"

注:shell模块使用awk命令时需要使用转义符*

(24)查看web_server组各主机的PATH变量内容

ansible web_server -m shell -a 'echo $PATH'
注意:如果使用双引号"echo $PATH",会求出PATH变量在当前系统的值,这就牵扯到shell引号的规则了。*

在下图中我们明显看到双引号和单引号执行的结果是不一样的,单引号是远程机器的结果,而双引号实际是ansible本地机器的结果。

通过ansible批量管理Linux服务器:配置Inventory和批量执行命令

(25)Ansible能够以并行的方式同时scp大量的文件到多台机器,将本地hosts文件copy到web_server组的所有主机的/tmp目录下

命令格式:ansible <主机或主机组> -m copy -a "src=<本地目录或文件> dest=<远程目录或文件>"

ansible web_server -m copy -a "src=/etc/hosts dest=/tmp/"
通过ansible批量管理Linux服务器:配置Inventory和批量执行命令

(26)使用file模块修改文件的属主和权限,这里可以替换为copy模块,是等效的

命令格式:ansible <主机或主机组> -m file -a "dest=<远程目录或文件> mode=<权限> owner=<所属用户> group=<所属用户组>"

ansible web_server -m file -a "dest=/tmp/hosts mode=600"
ansible web_server -m file -a "dest=/tmp/hosts mode=600 owner=xuad group=xuad"
ansible web_server -a "ls -lh /tmp/hosts"
通过ansible批量管理Linux服务器:配置Inventory和批量执行命令

(27)使用file模块创建目录,与执行mkdir -p效果类似

ansible web_server -m file -a "dest=/tmp/test mode=755 owner=xuad group=xuad state=directory"

(28)使用file模块创建文件,与执行touch效果类似

ansible web_server -m file -a "dest=/tmp/test.txt mode=755 owner=xuad group=xuad state=touch"

(29)使用file模块创建一个软链接文件

ansible web_server -m file -a "src=/root/test.txt dest=/tmp/test.txt state=link"

(30)删除目录(递归删除)和删除文件,absent表示删除

ansible web_server -m file -a "dest=/tmp/test state=absent"
ansible web_server -m file -a "dest=/tmp/test.txt state=absent"

Ansible提供对yum和apt的支持,下面是关于yum的示例

(31)确认一个软件包已经安装,但不去升级它

ansible web_server -m yum -a "name=wget state=present"
通过ansible批量管理Linux服务器:配置Inventory和批量执行命令

(32)将一个软件包升级到最新版本

ansible web_server -m yum -a "name=wget state=latest"
通过ansible批量管理Linux服务器:配置Inventory和批量执行命令

(33)卸载一个软件包,将wget卸载

ansible web_server -m yum -a "name=wget state=removed"
通过ansible批量管理Linux服务器:配置Inventory和批量执行命令

(34)确认一个软件包没有安装,确认wget已经不在了

ansible web_server -m yum -a "name=wget state=absent"
通过ansible批量管理Linux服务器:配置Inventory和批量执行命令

(35)安装一个软件包,通过yum方式安装wget

ansible web_server -m yum -a "name=wget state=installed"
通过ansible批量管理Linux服务器:配置Inventory和批量执行命令

(36)删除一个用户,删除andy用户

ansible web_server -m user -a "name=andy state=absent"

(37)确认一个用户是否存在,不存在则创建此用户

ansible web_server -m user -a "name=andy state=present"

(38)创建一个新用户,并指定用户组和家目录

ansible web_server -m user -a "name=andy groups=xuad home=/home/andy1"

(39)创建一个新用户,并设置密码

ansible web_server -m user -a 'name=andy password="&lt;crypted password here&gt;"'

注:<crypted password here>是经过sha-512加密算法加密后的值,需要安装passlib,密码值要用双引号括起来,外面用单引号

通过以下方式生成sha-512算法密码

pip install passlib
python -c "from passlib.hash import sha512_crypt; import getpass; print sha512_crypt.encrypt(getpass.getpass())"

(40)我们有时需要用git下载一个软件项目,可以使用git模块

ansible web_server -m git -a "repo=foo.example.org/repo.git dest=/srv/myapp version=HEAD"

(41)服务的启动、重启、停止,enabled=yes表示加入开机启动

ansible web_server -m service -a "name=httpd state=started"
ansible web_server -m service -a "name=httpd enabled=yes state=started"
ansible web_server -m service -a "name=httpd state=restarted"
ansible web_server -m service -a "name=httpd state=stopped"

长时间运行的操作可以放到后台执行,需要加--do-stuff参数,ansible会检查任务的状态,在主机上执行的同一个任务会分配同一个job id。

(42)后台执行命令,最多运行3600秒,-B 表示后台执行的最长时间

ansible all -B 3600 -a "/usr/bin/long_running_operation --do-stuff"

(43)检查任务运行的状态,使用async_status模块,上面执行后台命令后会返回一个job id,将这个id传给async_status模块

ansible all -m async_status -a "jid=488359623657.1326"

(44)后台执行命令,最多运行1800秒,即30分钟,-P表示每60秒检查一次状态,默认15秒

ansible all -B 1800 -P 60 -a "/usr/bin/long_running_operation --do-stuff"

(45)查看一台主机的系统信息

ansible 192.168.2.205 -m setup

注:这些系统信息变量可以直接在playbook里面调用

(46)查看一台主机的日期和时间信息

ansible 192.168.2.205 -m setup -a 'filter=ansible_date_time'

(47)查看一台主机的内存相关信息

ansible 192.168.2.205 -m setup -a 'filter=ansible_*_mb'

(48)查看一台主机的网卡信息

ansible 192.168.2.205 -m setup -a 'filter=ansible_ens3[0-5]'

(49)计划任务模块cron,每6个小时同步一次时间

ansible web_server -m cron -a 'name="modify ntp server" minute=0 hour="*/6" job="/usr/sbin/ntpdate ntp.xuadup.net"'
通过ansible批量管理Linux服务器:配置Inventory和批量执行命令

ansible的cron模块实际上就是在远程主机上创建了一条crontab(自动计划任务),我们到远程主机上执行crontab -e看一下

通过ansible批量管理Linux服务器:配置Inventory和批量执行命令

(50)系统重启后自动执行一个脚本

ansible web_server -m cron -a 'name="a job for reboot" special_time=reboot job="/root/xuad.sh"'

(51)删除一个计划任务

ansible web_server -m cron -a 'name="a job for reboot" state=absent'

(52)挂载分区

ansible web_server -m mount -a 'name=/data src=/dev/sdb1 fstype=ext4 opts=rw state=mounted'

(53)卸载分区

ansible web_server -m mount -a 'name=/data state=unmounted'

(54)确保一个分区是挂载状态,如果不是则挂载

ansible web_server -m mount -a 'name=/data src=/dev/sdb1 fstype=ext4 state=present'

关于playbook的内容请继续关注我的后续博文,谢谢!


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

卓有成效的程序员

卓有成效的程序员

Neal Ford / 熊节 / 机械工业出版社 / 2009-3 / 45.00元

《卓有成效的程序员》就是讲述如何在开发软件的过程中变得更加高效。同时,《卓有成效的程序员》的讲述将会跨语言和操作系统:很多技巧的讲述都会伴随多种程序语言的例子,并且会跨越三种主要的操作系统,Windows(多个版本),Mac OS X以及 *-nix (Unix或者Linux)。 《卓有成效的程序员》讨论的是程序员个体的生产力,而不是团队的生产力问题,所以它不会涉及方法论(好吧,可能总会在......一起来看看 《卓有成效的程序员》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具