salt是一款非常流行的开源软件,用于跨平台infra管理。常用的功能包括跨平台远程执行命令,跨平台配置管理等等。
这一节主要是介绍salt的工作原理,以及其组成模块和对应功能。有了高屋建瓴的视角,后面的章节再对各个模块进行深入讲解。
我是T型人小付,一位坚持终身学习的互联网从业者。喜欢我的博客欢迎在csdn上关注我,如果有问题欢迎在底下的评论区交流,谢谢。
salt采用server-agent通信方式,server称为salt master,agent称为salt minion。salt master负责给minion发送指令,并收集和显示指令的返回结果。因为其轻量性,一个salt master可以轻松管理数千乃至上万个minion。
salt master会同时监听4505和4506两个端口。所有的minion会主动和master的4505端口建立一个持久的连接,并在这个连接上监听master发送的命令。命令会以异步(asynchronously)的方式发送给所有的minion,所以几乎所有的minion都会同时接收到发送的命令。如果minion有特殊请求,例如发送结果给master,或者从master获取数据(例如配置信息),才会连接到4506端口。如下所示,我的实验环境有一台master和两台minion,在saltmaster上检查端口连接情况如下图所示,可见两台minion都和master的4505端口建立了连接。
root@saltmaster:/srv/salt# netstat -ntap | grep python
tcp 0 0 0.0.0.0:4505 0.0.0.0:* LISTEN 16010/python2
tcp 0 0 0.0.0.0:4506 0.0.0.0:* LISTEN 16018/python2
tcp 0 0 192.168.50.10:4505 192.168.50.11:52394 ESTABLISHED 16010/python2
tcp 0 0 192.168.50.10:4505 192.168.50.12:44442 ESTABLISHED 16010/python2
在初次连接的时候,minion会把自己的public key发送给master,以后的通信都是加密过的。
跨平台是salt最强大的能力之一。基本只要能运行python的平台就可以加入到salt里面来,不管minion是Linux,Windows,MacOS,FreeBSD,Solaris,或者云上的一个实例,甚至是一个容器实例。
为了达到这种跨平台的效果,salt对不同平台上实现相同功能的函数进行了抽象和整合,以确保在完成某个功能的时候所采用的salt命令都是一样的。对于功能相同的函数还整理成了模块,便于调用,后面我们会看到每个功能模块都是按照module.function
这样的方式去操作的。同时不仅是在发送指令,运行的结果在返回的时候也是按照统一的格式进行输出,便于后续的处理和存储。
salt的目标就是通过一个个的模板将所有的管理尽可能的自动化,所以一个简洁好用的模板格式就是必不可少的。salt采用的是YAML格式。例如,我要对所有minion采用common目录下的所有配置模板,然后对minion1额外采用nettools配置模板,就可以用下面的方式
base:
'*':
- common
'minion1':
- nettools
而这其中的nettools也是一个模板文件,例如
install_network_packages:
pkg.installed:
- pkgs:
- rsync
- lftp
- curl
这样只需要一条命令就可以按照自己的需要对所有机器进行个性化的配置,非常高效。
后面的教程会详细讲解如何使用模板文件,这里只需要有个大致印象即可
远程执行命令是salt的最常用的功能模块,也是最早建立的模块。以下面这条命令为例进行讲解
salt '*' test.rand_sleep 120
远程执行命令是通过在saltmaster上执行salt
命令来实现的,其格式如下
salt [options] '' [arguments]
上面例子中,'*'
是'
,表示所有的minion,执行的命令是test
这个module
下面的rand_sleep
这个function
,参数是120
。这里就会有两个问题:
saltmaster会在上面讲到的4505端口对所有的minion下发待执行的命令,但是往往这个命令只是给一部分minion去执行的,所以minion在收到命令以后会对照自己看是否属于要执行这个命令的目标minion,也就是这个target。如果不属于target,就忽视这个命令。
target最常用的是采用minion的名字,也可以采用目标机器的特定属性,例如OS,IP地址等等,后面会再详细的讲到。当然通配符也是必不可少的功能,*
表示任意多个字符,?
表示任意单个字符。
待执行的命令按照功能被分成了多个模块,也就是module。每一个模块包含了多个函数,也就是function。点击这里查看完整的远程命令模块列表,同时也可以去salt的github仓库查看函数的源码,远程执行的模块都在salt/salt/modules
这个目录下,每一个module是一个python文件。
例如刚才执行的那条命令源码就在salt/salt/modules/test.py
中,源码如下
def rand_sleep(max=60):
'''
Sleep for a random number of seconds, used to test long-running commands
and minions returning at differing intervals
CLI Example:
.. code-block:: bash
salt '*' test.rand_sleep 60
'''
time.sleep(random.randint(0, max))
return True
所以刚才那条命令就相当于执行了一条python语句,随机休眠0-120秒。
time.sleep(random.randint(0,120))
值得一提的是,往往一个函数有很多参数,有的时候需要指定几个需要的参数名来赋值,可以用等号来实现,例如
root@saltmaster:/srv/salt/ssh# salt minion1 network.ip_addrs interface=eth0 cidr="10.0.0.0/8"
minion1:
- 10.0.2.15
如果可以进行远程控制,那自然就可以将一系列的配置命令放在一个文件里面,对一个minion进行批量修改。例如一次性安装20个待安装的软件之类的。
没错,salt团队也是这么想的,所以在远程控制这个功能模块之后又有了配置管理功能模块。不过虽然说是两个功能模块,但是配置管理是很依赖远程控制的。
salt将这个思路进一步进行了抽象和简化,将一条条的命令抽象成了一个个的函数,同时按照功能又整合成了多个模块。这些和修改机器配置有关的模块和函数都在salt的github仓库的/salt/salt/states
目录下。
同时这个存放命令的文件,salt也规定了用YAML格式去写,便于检查和维护,并统一叫做states文件,后缀为sls。
例如,创建一个nettools.sls
文件,放入下面的内容,就是执行/salt/salt/states/pkg.py
里面的installed
函数,同时给函数的pkgs
参数传递了一个3个元素的list。
install_network_packages:
pkg.installed:
- pkgs:
- rsync
- lftp
- curl
关于配置管理,后面会有专门的一篇去详细讲解,这里有个印象即可。
系统数据在集群里面的传递主要有两个方向:saltmaster获取minion的系统数据,例如os版本,ip信息等等,以及saltmaster传递数据给minion。这两个方向分别有两个功能模块来管理,分别叫做grains和pillar。
grains是关于minion的静态信息,例如os版本,ip信息,内存硬盘大小等等。minion初次连接就会传递这些数据给saltmaster,同时周期更新或者saltmaster主动请求更新。
grains的主要作用是用在对minion的筛选上,还记得上面的远程执行命令中有一个'
吗,grains就可以用在这个上面。例如针对不同os的系统执行不同的命令。
pillar是saltmaster往下发送给minion的数据,因为经过加密,所以可以用来传递一些私密信息,例如密码等等。同时pillar的数据也不会在minion端进行本地持久化,确保安全。
上面提到了配置管理,但是修改配置的时候参数往往是很多的,而且不同的系统也会不一样,例如安装路径,监听端口,用户名等等。pillar可以让你定义这些信息,然后以变量的形式插入到states文件中去执行。
pillar文件也是采用YAML格式。
顺便值得一提的是mine这个数据传递的方向,用于在minion之间传递数据。这是个不太常见的功能,以后有机会通过实例来讲解。
这一节我们一起学习了salt的基本工作原理和常用功能模块,但是理论知识总是让人没有太深刻的感受。那么下一节我们就在本地搭建一个简易的集群来亲手体验下上面的这些功能,非常有趣。我们下一节见。