在配置管理系统中,从中心服务器向客户端推送文件是基本需求。SaltStack使用内建的ZeroMQ服务器作为文件服务器。文件服务器主要用于在state系统中将SLS文件推送到客户端,当然也可以用于其他文件的传输。
运维工作中,经常会有文件同步的情况。我在日常工作中,由于权限限制,只能自己写程序分发文件。我使用的是Python+paramiko+threading+Queue,paramiko用于远程执行命令或者分发文件,threading+Queue实现并发分发文件(如果是串行的话,效率十分低下)。最近研究SaltStack时,发现有两种方法可以做到文件分发,第一只是使用SaltStack命令:salt-cp;第二种是使用SaltStack提供的:Salt文件服务器,这两种方法都可以实现文件分发的功能。
一、 salt-cp
1. salt-cp简述
salt-cp命令用于复制一个文件到多个minion系统中。指定minion可以使用通配符、正则表达式、Grains等方法
salt-cp '*' [ options ] SOURCE DEST
salt-cp -E '.*' [ options ] SOURCE DEST
salt-cp -G 'os:CentOS*' [ options ] SOURCE DEST
minion匹配
-E 目标选择;表示以正则表达式匹配minion
-G 目标选择表示使用minion上的Salt Graings系统的返回值来匹配特定minion
-L 目标minion别解析成用逗号分隔的列表
2. salt-cp 用例
- 将irq.py 文件 发送到 OS为CentOS的minion的 /usr/local目录下
salt-cp -G 'os:centos' irq.py /usr/local/
返回值:{'192.168.1.223': {'/usr/local/irq.py': True}} 表示成功
- 将salt.doc文件发送到所有的minion的/usr/local目录下
salt-cp '*' salt.doc /usr/local/
返回值:{'192.168.1.223': {'/usr/local/salt.doc': True}} 表示成功
salt-cp -L '192.168.1.223' install.log /usr/local/
返回{'192.168.1.223': {'/usr/local/install.log': True}} 表示成功
二、Salt 文件服务器
Salt内置了一个简单的文件服务器用于分发文件给Salt minions。
1. 文件服务器的base环境
由于文件服务器是为Salt state system工作的,所以文件服务器也是支持环境的概念的。
Salt文件服务器/etc/salt/master配置文件中的flie_roots选项管理。Salt文件服务器的默认环境为为base环境,base环境必须定义,因为当环境没有明确指定时,文件下载就是从base环境中去找的。其配置如下:
file_roots:
base:
- /srv/salt/base
- /srv/salt/failover
/srv/salt/base和/srv/salt/failover这些目录是不存在,需要手动创建。这里还需要说明的是下载文件时的搜索顺序。文件服务器在给minions传输文件时,是有搜索顺序的。这里用上述配置说明:如果文件URL为:salt://httpd/httpd.conf。那么传输文件时,首先搜索/srv/salt/base/httpd/httpd.conf,如果找到了,则下载;否则就使用/srv/salt/failover/httpd/httpd.conf
2. 文件服务器多环境配置
多环境配置也是更改master配置达成,如下:
file_roots:
base:
- /srv/salt/base
dev:
- /srv/salt/dev
- /srv/salt/base
prod:
- /srv/salt/prod
- /srv/salt/base
在这个配置中,处了base环境外。还有dev环境和prod环境。配置文件修改后,需要重启master才能生效。
3. cp模块
cp模块被用于用于Salt state system、salt-cp命令(如上所述)以及可用于Salt文件服务器。
3.1 cp.get_fle
cp.get_file用于minion从master下载一个文件,语法:
- 文件在base环境下
salt '*' cp.get_file salt://testfile /root/testfile
该命令表示minion从master端下载文件并拷贝到到/root/testfile文件中。注意:salt://表示的base环境。因此,testfille是位于base环境下——即/srv/salt/base目录中。
- 文件在base环境的多级目录下
salt '*' cp.get_file salt://httpd/httpd.conf /root/httpd.conf
salt://httpd/httpd.conf表示** /srv/salt/base/httpd/httpf.conf**
- 实例
[root@master httpd]# salt '*' cp.get_file salt://httpd/httpd.conf /root
192.168.1.223:
The minion function caused an exception: Traceback (most recent call last):
File "/usr/lib/python2.6/site-packages/salt/minion.py", line 1412, in _thread_return
return_data = executor.execute()
File "/usr/lib/python2.6/site-packages/salt/executors/direct_call.py", line 28, in execute
return self.func(*self.args, **self.kwargs)
File "/usr/lib/python2.6/site-packages/salt/modules/cp.py", line 227, in get_file
gzip)
File "/usr/lib/python2.6/site-packages/salt/fileclient.py", line 1112, in get_file
fn_ = salt.utils.fopen(dest, 'wb+')
File "/usr/lib/python2.6/site-packages/salt/utils/__init__.py", line 1288, in fopen
fhandle = open(*args, **kwargs)
IOError: [Errno 21] Is a directory: '/root'
[root@master httpd]# salt '*' cp.get_file salt://httpd/httpd.conf /root/httpd.conf
192.168.1.223:
/root/httpd.conf
这里注意下,根据报错可以发现:目标路径必须是一个文件,而不是目录。这点有区别去salt-cp命令。
-
cp.get_file gzip格式
对于大文件传输,cp.get_file支持gzip压缩格式。因为gzip是CPU密集型的工具,因此cp.get_file开启gzip是适用于高压缩率的情况下,如JSON或者YAML文件。
语法:
salt '*' cp.get_file salt://httpd/httpd.conf /root/httpd.conf gzip=5
gzip后的数字表示压缩比,范围在1-9之间,1表示最小压缩比,9为最大压缩比。换句话说,gzip=1情况下, 消耗的CPU小;gzip=9时,消耗的CPU则更多。
-
cp.get_file makedirs=True
注意,也就是时候,cp.get_file过程中,如果目录不存在,cp.get_file是不会主动创建目录的,如果要做到这点,可以使用makedirs=True 参数。测试如下:
[root@master httpd]# salt '*' cp.get_file salt://httpd/httpd.conf /root/test/httpd.conf
192.168.1.223:
False
[root@master httpd]# salt '*' cp.get_file salt://httpd/httpd.conf /root/test/httpd.conf makedirs=True
192.168.1.223:
/root/test/httpd.conf
3.2 cp.get_dir
顾名思义,cp.get_dir就是下载目录,用法基本同cp.get_file一直。直接举个例子吧
- 将master端的httpd目录下载到minion端的/root目录下
[root@master ~]# salt '*' cp.get_dir salt://httpd /root
192.168.1.223:
- /root/httpd/httpd.conf
3.3 cp.push
cp.push 模块允许minion上传文件到master端。注意事项:
- cp.push功能默认不开启,需要修改配置文件中的file_recv 环境,默认为False
- 上传的文件存放在master端的 /var/cache/salt/master/minions/<minion_id>/files/ 目录下
修改master配置文件并重启。
file_recv: True
以上传httpd.conf为例
[root@logan ~]# salt '192.168.159.241' cp.push /etc/httpd/conf/httpd.conf
192.168.159.241:
True
# 查看文件
[root@logan conf]# pwd
/var/cache/salt/master/minions/192.168.159.241/files/etc/httpd/conf
[root@logan conf]# ls
httpd.conf
三、利用Salt API分发文件
In [10]: import salt.client
In [11]: local = salt.client.LocalClient()
In [12]: local.cmd('*', 'cp.get_file', ['salt://httpd/httpd.conf', '/root/aaaaaaa'])
Out[12]: {'192.168.1.223': '/root/aaaaaaa'}
最近在写运维管理平台时,要做一个文件分发的功能,因此就用到了Salt的文件服务器以及cp模块来做,再调用下Salt开放的API,达到的效果也是十分理想的。当然,前提是要把文件准备在特定的目录下,这点只要自己做一个规范,也是很好管理的。
网友评论