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

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

内容简介: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的内容请继续关注我的后续博文,谢谢!


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

查看所有标签

猜你喜欢:

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

We Are the Nerds

We Are the Nerds

Christine Lagorio-Chafkin / Hachette Books / 2018-10-2 / USD 18.30

Reddit hails itself as "the front page of the Internet." It's the third most-visited website in the United States--and yet, millions of Americans have no idea what it is. We Are the Nerds is an eng......一起来看看 《We Are the Nerds》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

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

Markdown 在线编辑器

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换