1 概述


1. 关于saltstack

Salt是用Python编写的一个基础管理工具,能够非常快速的运行以及具有良好的扩展性来管理成千上万的服务器。Salt通过发送一个动态通讯总线来实现远程执行、配置管理等等工作。

Salt采用zeromq消息队列来进行通信,能够提供很强的拓展性、灵活性和实时性。


2. 与Puppet、Fabric等的比较

Puppet作为自动化配置管理工具,可以完成初始化和配置等一系列工作(比如,静态 IP 配置,DNS 设置,NFS/SAN 挂载,LDAP/Kerberos 登录,安全加固配置,内核参数优化,防火墙规则配置等等),等初始化完成后开始运行,运行一段时间后有一些需要自动和手动操作的任务(比如升级、重启、备份等),这时候我们使用 Fabric来批量执行这些临时任务。运维工作内容:

  • 操作系统和软件的安装、配置、初始化等——Puppet、Chef、CFEngine、Ansible、Salt

  • 自动执行任务,比如定期备份、清除日志等——Fabric、Ansible、Salt

  • 手动执行任务,比如部署应用、升级、重启、检查和校验文件系统,增加用户等——Fabric、Rake、Func、Ansible、Salt

可见,Salt(或Ansible)可以完成上述几种不同的任务。


2 安装、配置


Salt是基于主从模式的架构来实现配置管理的,在主控服务器上安装服务器端软件,即salt master,在多台需要被管理和配置的受控机器上安装客户端软件,即salt minion。在主控机器上给下属(受控)发命令,在受控机器上接受和执行上级(主控)的命令。


1. 主控端

在官网上有很多安装方式,CentOS上可使用rpm安装(yum)

首先需要添加RPM源:

rpm -ivh http://mirrors.sohu.com/fedora-epel/6/i386/epel-release-6-8.noarch.rpm


安装:

yum install salt-master -y


配置:/etc/salt/master

配置好服务端监听IP字段,此处为主控服务器的IP:

interface: 192.168.56.1


启动运行:

调试模式:salt-master -l debug

后台daemon模式:salt-master -d

service模式:service salt-master start


监听的端口:

4505(publish_port):salt消息发布系统使用的tcp端口

4506(ret_port):salt客户端与服务端通信的端口,包括文件服务器、认证等通信的执行,主要用来接受消息

需要配置好iptables等防火墙工具来确保客户端能与服务端的这两个端口通信


2. 受控端

安装:yum install salt-minion -y


配置:/etc/salt/minion

master: salt        服务端主机名

id: 客户端主机名    在服务端上显示的客户端的名字,若为空则显示受控端的hostname


运行:

调试模式:salt-minion -l debug

后台daemon模式:salt-minion -d

service模式:service salt-minion start


3. 认证

salt minion和master的认证过程:

  • minion在第一次启动时,会在/etc/salt/pki/minion下自动生成minion.pem(private key),然后将minion.pem发送给master

  • master在接收到minion的public key
    后,通过salt-key命令accept minion public key,在master的/etc/salt/pki/master/minions下会存放以minion id命名的public key,然后master就能对minion发送指令了


具体执行如下:

启动服务端:service salt-master start

启动客户端:service salt-minion start

服务端查看key:salt-key

Accepted Keys:
Unaccepted Keys:

vm1.sysu
vm2.sysu
vm3.sysu
vm4.sysu
Rejected Keys:

服务端接受key:

salt-key -A


测试:salt ‘vm1.sysu’ test.ping

vm1.sysu:
    True


查看salt更多命令和手册:salt ‘*’ sys.doc


3 salt使用


1. 几个关键词

targeting:目标匹配

salt ‘*’ test.ping

引号中配合shell正则表达式能够实现很强大的minion的过滤和匹配技术

示例:salt -C ‘webserv* and G@os:Debian or E@web-dc1-srv.*’ test.ping


nodegroup:minion分组管理

在master的配置文件中按如下格式定义:

nodegroups:

    group1:‘vm1.sysu,vm2.sysu’

    group2:‘vm3.sysu,vm4.sysu’


grains:minion基本信息管理

基本使用:

salt '*' grains.ls  查看grains分类

salt '*' grains.items  查看grains的所有信息

salt 'vm3.sysu' grains.item pythonversion 查看单个信息

在用salt进行客户端管理或编写state的时候都可以引用grains的变量


pillar:salt对敏感信息的管理,只有匹配到的节点才能获取和使用

默认位置:pillar数据定义文件存储在:/srv/pillar

入口文件:/srv/pillar/top.sls

格式:

    base:

        “targeting”:

            - $pillar            #名字为pillar.sls的文件来存放匹配到的minion的变量

查看节点的pillar数据:

salt ‘vm1.sysu’ pillar.data


2. 实时命令执行

临时的执行一些命令,比如查看多台机器的iptables情况,或者执行某个命令(重启apache)

内建命令:

cmd.run:salt '*' cmd.run "hostname"

test.ping: salt '*' test.ping


salt有非常多的内建命令,以模块的方式集成,查看salt所有内建模块:

http://docs.saltstack.com/en/latest/ref/modules/all/index.html


3. 状态管理

类似于puppet(Mcollective)的状态管理,salt通过在服务端(主控)上定义好系统配置应该有的状态,然后客户端自动完成相应的操作和配置。salt基于state对minion进行状态管理,state文件默认在/srv/salt目录下。

查看salt所有状态的模块类型:http://docs.saltstack.com/en/latest/ref/states/all/index.html


state的结构:

    $ID:     #state的名字

        $state:        #要管理的模块类型

        - states        #该模块的状态

示例:在所有受控机器上安装vim软件包,并使用自己定义的vimrc文件:/srv/salt/vim.sls

vim:

    pkg.installed


/etc/vimrc文件:

syntax enable

set textwidth=79

set shiftwidth=4

set expandtab

set softtabstop=4

set shiftround

set fileencodings=utf-8

set ending=utf8

set tenc=utf8

强制执行这个状态:

salt '*' state.sls vim


逻辑关系:

require:依赖于某个state,在运行此state之前,先运行依赖的state,可有多个依赖,类似于ansible的notify

httpd:

    pkg.installed

    file.managed:

    - name: /etc/httpd/conf/httpd.conf

    - source: salt://httpd/httpd.conf

    - require:

        - pkg: httpd


watch:当某个state变化时运行此模块

官方文档中的一个例子是:service.running state使用watch,即当一个service watch一个state之后,那么当被监视的状态发生改变时,这个服务将被重新加载或者重启,另外,salt能确保这个服务在运行状态。

ntpd:
  service.running:
    - watch:
      - file: /etc/ntp.conf
  file.managed:
    - name: /etc/ntp.conf
    - source: salt://ntp/files/ntp.conf

ps:watch除具备require功能外,还增加了关注状态的功能,另外还有与watch、require相反的watch_in和require_in


order:优先级设定,但比watch和require的优先级低;具有order指定的state比没有order指定的优先级高。

vim:

    pkg.installed:

        - order: 1        #让当前状态第一个运行,如果该状态依赖于其他状态,依赖的状态会在这个状态运行前执行。

ps:使用值last可以让某个state最后一个运行。


state与minion:临时给某个minion部署一个state,即强制执行。

salt 'vm1.sysu' state.sls 'vim'

执行该命令后可以立即看到输出结果。


highstate:给minion添加永久性的state。

状态树是位于定义在salt配置文件中的file_roots字段所指定的目录下的SLS文件的集合,状态树能被组织成SLS模块,从而形成永久性的state。

默认配置文件:/srv/salt/top.sls

语法:

base:

    ‘*’:

        - core

        - wsproxy

/srv/salt/目录结构:

.

|— core.sls

|— top.sls

|— wsproxy

    |— init.sls

    |— websocket.py

    |— websockify

应用:salt ‘vm1.sysu’ state.highstate

测试模式:salt ‘vm1.sysu’ state.highstate -v test=True


state schedule: salt的scheduling系统能够使得minion定时自动去执行一些state,而不是要等到服务端被调用时才执行。

入口文件:/srv/pillar/top.sls

base:

    '*':

        - schedule

示例:/srv/pillar/schedule.sls

schedule:

    job1:

        function: state.sls

        seconds: 3600

        args:

            - httpd

        kwargs:

            test: True

上述schedule将会排定一个命令:state.sls httpd test=True every 3600 seconds (every hour)


4. peer

peer提供了一种让某些minions去发送命令的机制,目的是允许minions能够互相传递命令。

peer的配置在master的配置文件的peer块,默认为:

peer:

    .*:            #有管理权限的minion节点,此处为所有的minions

        - .*        #可以使用的module

默认为所有的minion节点都有权限执行peer,而且能够使用所有模块。


5. runner

salt runner提供了一种灵活、快捷调用salt的方式,通过salt-run能直接运行在master上的代码,即在master上执行命令而不是远程的salt minions上。

runner代码目录配置在master的配置文件的runner_dirs字段:

runner_dirs: ['/srv/salt/_runner',]

实例测试:/srv/salt/_runner/foo.py:

def test():
    print "Hello Jay!"

运行:salt-run foo.test

Hello Jay!


6. returner

默认情况下,salt发送到minion端的命令执行后的返回值会返回到master端,通过使用salt的returner,结果数据可以被重定向到外部的数据存储区,以便用来分析和归档。returner接口能允许将结果数据发送到Redis服务器、MongoDB服务器、MySQL服务器等任何可以接收数据的系统。

使用示例:

salt '*' test.ping --return redis_return

上述命令会将ping执行后的结果发一份到redis数据库中,其中redis_return是salt的一个returner接口,类似还有mongo_return,cassandra_returnd等。

由于salt的returner需要在minion上做配置,这样子会比较麻烦,所以可以考虑自定义returner:

returner是一个包含了一个returner函数的python模块,该函数需要接收一个返回数据的参数,示例如下:/srv/salt/_returners/local_return.py

import redis

import json

def returner(ret):

    '''

    Return information to a redis server

    '''

    #Get a redis connection

    serv = redis.Redis(

                    host='redis-host',

                    port=6379

                    db='0')

    serv.sadd("%(id)s:jobs" % ret, ret['jid'])

    serv.set("%(jid)s:%(id)s" % ret, json.dumps(ret['return']))

    serv.sadd('jobs', ret['jid'])

    serv.sadd(ret['jid'], ret['id'])

同步到所有节点:salt '*' saltutil.sync_returners


7. Python client API:实现salt编程开发

示例:

import salt.client

local = salt.client.LocalClient()

ret = local.cmd('vm1.sysu', 'cmd.run', ['hostname'])

print ret

更多文档参考:http://docs.saltstack.cn/ref/clients/index.html#python-api

                                                                                                                                ——游响云停