0%

SaltStack 基础知识

SaltStack 具备配置管理、远程执行、监控等功能,一般可以理解为简化版的 puppet 和加强版的 Func。

SaltStack简介与特性

简介

SaltStack是一种基于 C/S 架构的服务器基础架构集中化管理平台,管理端称为 Master,客户端称为 Mionion。SaltStack 具备 配置管理、远程执行、监控等功能,一般可以理解为简化版的 puppet 和加强版的 Func。

SaltStack 本身是基于 Python 语言开发实现,结合了轻量级的消息队列软件 ZeroMQ 与 Python 第三方模块 (Pyzmq、PyCrypto、Pyjinjia2、pythonmsgpack 和 PYYAM L等)构建。

通过部署 SaltStack 环境,可以在成千上万台服务器上做到批量执行命令,根据不同的企业特性进行配置集中化管理、分发文件、采集系统数据及软件包的 安装与管理等。

特性

  1. 部署简单、方便;
  2. 支持大部分 Uniux/linux 及 Windows 环境;
  3. 主从集中化管理;
  4. 配置简单、功能强大、扩展性强;
  5. 主控端(master)和被控端(minion)基于证书认证,安全可靠;
  6. 支持 API 及自定义模块,可通过 Python 轻松扩展。

工作原理

SaltStack 采用 C/S 结构来对服务器操作管理及配置管理。

SaltStack 客户端(minion)在启动时,会自动生成一套密钥,包括私钥和公钥。之后将公钥发送到服务器端,服务器端验证并接受公钥,以此来建立可靠且 加密的通信连接。同时通过消息队列 ZeroMQ 在客户端与服务端之间建立消息发布链接。具体通信原理图。如下:

专业术语说明:

  • Minion: SaltStack 需要管理的客户端,会主动去连接 Master 端,并从 Master 端得到资源状态信息,同步资源管理信息。
  • Master: 作为控制中心运行在主机服务器上,负责 Salt 命令运行和资源状态的管理。
  • ZeroMQ: 是一款开元的消息队列软件,用于在 Minion 端与 Master 端建立系统通信桥里那个。(新版本的 salt 开发了 REAT 自己的通信协议。 可以在官网了解。)
  • Daemon: 是运行与每一个成员内的守护进程,承担着发布消息及通信端口监听的功能。

原理图说明:

  • Minion 是 SaltStac k需要管理的客户端安装组件,会主动去连接 Master 端,并从 Master 端得到资源状态信息,同步资源管理信息。
  • Master 作为控制中心运行在主机服务器上,负责 Salt 命令运行和资源状态的管理。
  • Master 上执行某条指令通过队列下发到各个 Minions 去执行,并返回结果。

SaltStack的架构设计

根据项目的实际情况绘制了部署架构图,并在文中对架构图进行了详细说明。

  SaltStack 的所有被管理客户端节点(如图的 DB 和 Web),都是通过密钥进行加密通信,使用端口是 4506。客户端与服务器端的内容传输, 是通过消息队列完成,使用端口为 4505。Master 可以发送任何指令在 Minion 上执行,salt 有很多可执行模块,比如说 CMD 模块,在安装 minion 的 时候已经自带了。它们通常位于 python 库中,locate salt | grep /usr/ 可以看到salt自带的所有东西。

为了更好的理解架构,以下将展示主要的命令发布过程:

  1. SaltStack 的 Master 与 Minion 之间通过 ZeroMQ 进行消息传递,使用了 ZeroMQ 的发布订阅模式,连接方式包括了 Tcp 和 IPc。
  2. Salt 命令,将 cmd.run ls 命令从 salt.client.LocalClient.cmd_cli 发布到 master,获取一个 jobid,根据值获取命令执行结果。
  3. Master 接收到命令后,将要执行的命令发送到客户端 minion。
  4. Minion 从消息总栈上接收到要处理的命令,交给 minion._handle_aes 处理。
  5. Minion._handle_aes 发起一个本地线程调用 cmdmod 执行 ls 命令。线程执行完 ls 后,调用 Minion._return_pub方法, 将执行结果通过消息总线返回给 master。
  6. master 接收到客户端返回的结果,调用 master.handle_aes 方法将结果写到文件中。
  7. Salt.client.LocalClient.cmd_cli 通过轮询获取 jobid 执行结果,将结果输出到终端。

SaltStack的安装与配置

安装

1
2
3
4
5
6
7
8
9
# 安装 epel(Salt需要 epel 源支持,所有安装前需要先安装 epel 源包。)
# Centos 6
rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
# 更多下载请看
# https://repo.saltstack.com/
# 安装 salt-master
yum -y install salt-master
# 安装 salt-minion
yum -y install salt-minion

配置

  • master

    1
    vim /etc/salt/master
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    # salt运行的用户,影响到salt的执行权限
    user: root
    # salt的运行线程,开的线程越多一般处理的速度越快,但一般不要超过CPU的个数 worker_threads: 10
    # master的管理端口
    publish_port: 4505
    # master跟minion的通讯端口,用于文件服务,认证,接受返回结果等 ret_port: 4506
    # 如果这个master运行的slat-syndic连接到了一个更高层级的master,那么这个参数需要配置成连接到的这个高层级master的监听端口
    syndic_master_port: 4506
    # 指定pid文件位置
    pidfile: /var/run/salt-master.pid
    # saltstack可以控制的文件系统的开始位置 root_dir: /
    # 日志文件地址
    log_file: /var/log/slat_master.log
    # 分组设置
    nodegroups:
    group_all: '*'
    # salt state执行时候的根目录 file_roots: base:
    - /etc/salt/
    # 设置pillar的根目录 pillar_roots: base:
    - /srv/pillar
  • minion

    1
    vim /etc/salt/minion
    1
    2
    master: master # 这里的 master是指在 /etc/hosts 文件中所定义的 master 主机名或者 IP 地址
    id: slave # 这里的 slave 指的是 slave 的名称

启动

  • salt-mater salt-minion
    1
    2
    3
    4
    5
    6
    # centos6
    service salt-minion start # 启动minion
    service salt-master start # 启动master
    # centos7
    systemctl start salt-master # 启动master
    systemctl start salt-minion # 启动minion

minion 认证

  • 认证方式
    1
    2
    3
    4
    5
    6
    7
    # 建议手动接收 key
    salt-key # 证书管理
    salt-key -L # 查看所有minion-key
    salt-key -a # 接受某个minion-key
    salt-key -A # 接受所有minion-key
    salt-key -d # 删除某个minion-key
    salt-key -D # 删除所有minion-key

Target minion

saltstack minion 匹配方式

  • Glob
    salt 默认的 target 类型,使用 shell 的通配符来指定一个多个 Minion ID)通过 api 或其他用户接口使用 salt 时,通配符*通常不需要引号 和逃逸字符\保护。

    1
    salt \* test.ping # salt '*' test.ping
  • pcre
    兼容正则表达式
    选项:-E (--pcre

    1
    salt -E '^[m|M]in.[e|o|u]n$' test.ping
  • Subnet
    通过指定一个 IPv4 地址或一个 CidR 的 Ipv4 子网
    选项:-S (--ipcidr

    1
    2
    salt -S 192.168.126.129 test.ping 
    salt -S 192.168.0.0/16 test.ping
  • Grains
    salt 可以通过操作系统,CPU 架构及自定义信息等机器特征进行 target Minion
    选项:-G (--grain)
    由于 Grain 是键值对,所以键名及值都必须指定,通过冒号(:)进行分割

    1
    2
    salt -G 'os:Centos' test.ping 
    salt -G 'os_family:Centos' test.ping

    一些 Grain 是多级字典,可以通过冒号(:)进行分割字典中的每一集键名:

    1
    salt -G 'ip_interfaces:eth0:192.168.11.38'

    如果 Grain 含有冒号,同样需要指定,尽管可能看上去很奇怪,例如匹配本地 IPv6 地址(::1)

    1
    salt -G 'ipv6:1'

    Grain PCRE
    选项: --grain-pcre
    通过 Grain 来匹配很高效,但如果想进行更复杂的 grain 匹配,可以使用 grain pcre 进行匹配:

    1
    salt --grain-pcre 'os:red(hat|flag)' test.ping
  • pillar
    salt 支持通过 pillar 数据进行匹配
    选项: -I (--pillar

    1
    salt -I 'my_val:my_val' test.ping
  • compuond-混合
    选项: -C (--compound
    混合 target 允许用户在一个 shell 命令中指定多种 target 类型。默认使用 glob,想指定其他 target 类型,则需要在前面追加上类型简写@ 符号。

    简写 target
    G Grain
    E PCRE Minion ID
    P Grain PCERE
    L 列表(list)
    I Pillar
    S 子网/ip 地址
    R SECO范围
    1
    salt -C 'web* or G@os:Arch' test.ping
  • Nodegroup-节点组 选项: -N (--nodegroup
    节点组需要事先定义(/etc/salt/master),配置方法如下:

    1
    2
    nodegroups:
    node: 'L@foo.slave.com' #组名为node
    1
    salt -N node test.ping

SaltStack模块

指定 target 后,接下来需要声明并运行的方法。

方法包含两部分,通过点(.)来分隔:

1
<模块名>.<方法> 

在 salt 命令中,模块方法紧随 target,但也可以在后给方法加任何参数:

1
salt <target> <模块名>.<方法> [参数...]

SaltStack核心模块

  • test.ping
    用于监测 Minion 是否可响应。还要一些其他类似的方法,如 test.arg、test.kwarg、 test.arg_type 及 test.arg_repr
  • test.echo
    让 Minion 显示出传递给自己的字符串
  • test.sleep
    需要 Minion 先 sleep 若干秒后再返回 True,常用于测试或验证任务系统。test.rand_sleep 方法也非常实用, 常用于在大规模 minion 中进行分发并检查返回结果的测试场景。
  • test.version
    Minion 可能运行着不同的 salt 版本,需要获取 salt 的具体版本,这是简单的获取方法,会返回每个 Minion 的 Salt 版本。 如果想获取系统其它软件包的版本,可以使用 pkg.version。需要在配置文件中配置软件包路径。
  • pkg.install
    每一种包管理器都支持安装软件包功能。该方法只需要指定一个软件包名,或者指定一组软件包,甚至可以指定具体的版本。当使用执行模块式, 可能只需要指定软件包名就够了,但在 State 模块中,高级的用法会更重要。
  • pkg.remove
    与 pkg.install 方法搭配使用,用于指定卸载软件包。它允许用 python 的列表来一次性卸载若干软件包。如果在命令行中,则可以使用 JSON 字符串。
  • file.replace
    sed 命令是一个 UNIX 系统中常用的管理员工具,常用于处理包括编辑文件中的特定行、搜索和替换等任务。file.replace 类似的作用。
  • 其他文件类操作方法
    file.chown file.chgrp file.get_mode file.set_mode file.link file.symlink file.rename file.copy file.move file.remove file.mkdir file.makedirs file.mknod 等
  • 用户及用户组管理方法
    salt 中也包含大多数 unix 中用于管理用户及用户组的工具,如: user.add user.delete user.info group.add group.delete group.info user.chuid user.chgid user.chshell user.chhome user.chgoups 等 sys.doc
    可以使用 sys.doc 方法来查看 minion 端的自述文档。如果没有参数,则将在一个 minion 中显示所有方法的文档内容。
    如果指定了模块名字, 将显示该模块中所有方法的文档内容。如果也指定了方法的名字,则只显示该方法的文档内容。常用于查询在一个有效的模块中如何 使用这些方法。
    1
    salt \* sys.doc cmd[命令模块] # 可以得到帮助文档

SLS 文件树

salt 中的一些子系统需要使用 sls 文件树,最常见的是用于 salt state 的 /srv/salt,其次是 Pillar 系统的 /srv/pillar, 它们之间的文件格式不同,但目录结构相同。

sls 文件

sls 指代 salt state,在 salt 中首先会用到这种类型文件的结构。默认使用 YAML 格式。salt 和数据息息相关。YAML 是 Python 中指代字典类型数 据结构的序列化格式。sls 文件为键值对组。

在 sls 文件中每个小结(stanza)的 key 称为 ID。如果小结内没有显示声明 name 属性没那么 ID 会作为 name。ID 必须全局唯一。

使用 Top 文件将配置绑定在一起

state 和 pillar 系统中,都有一个名为 top.sls 的文件,用于将 sls 文件拉在一起并制定在那个环境下应该为 minion 提供哪些 sls 文件。

top.sls 文件中的每个 key 都定义一个环境,一般情况下,定义一个叫 base 的环境,此环境包含基础设施中所有的 minion,定义其他环境 只包含 minion 的子集。每个环境中包含一组 sls 文件。

1
2
3
4
5
6
7
8
9
10
base:
'*':
common
vim
qa:
'*_qa':
jenkins
web:
'web_*':
apache2

在这个 top.sls 中,声明了 3 个环境,分别是 base、qa 和 web。base 环境指定所有 minion 执行 common 和 vim state。qa 环境指定所有以 qa 结尾 ID 的 minion 执行 jenkins state。web 环境指定所有以 web 开头 ID 的 minion 执行 apache2 state。

sls 目录组织

sls 文件的名字可以是 sls 文件本身的文件名(如 apache2.sls)也可以是 init.sls 文件在内的目录名(/apache2/init.sls)使用 state 进行 配置管理 /srv/salt 目录下的文件用于定义 salt state。这是配置管理格式,用来强制 minion 处于某一状态,


Grain、Pillar 及模板基础

Grain 和 Pillar 提供了一种允许在 Minion 中使用用户自定义变量的方案。

Grain 定义在指定的 Minion 上,而 Pillar 则指定在 master 上。它们都可以通过静态(statically)或动态(dynamically)的方式进行定义, 但是 Grain 常用语提供不常修改的数据,而 Pillar 更倾向于动态数据。

使用 Grain 来获取 Minion 特征数据

Grain 用于描述 minion 的静态要素,执行模块能够用来判断如何执行。例如,当 os_family 的 Grain 数据为 Debain 时,则会使用 apt 工具组件 来进行软件包管理,为 redhat 时使用 yum 来进行软件包管理。可以通过 grains.items 方法来查看 minion 都有哪些 grain 数据:

1
salt \* grains.items

查看某个特定的 Grain,可以将对应的名字作为参数传递给 grains.item

1
salt \* grains.item os_family

同样可以自定义 Grain,在 minion 的配置文件(/etc/salt/minion)中定义静态的 Grain 数据。但不建议使用

1
2
3
grains:
foo: bar
baz: qux

最好是在(/etc/salt/grains)中配置;有两个好处:

  • Grain 独立存储,易于在本地查找;
  • Grain 能够通过 Grain 执行模块进行修改。

第二点非常重要 minion 的配置文件设计允许用户级注释,而 Grain 文件设计用于 salt 按需进行重写。手动编辑 Grain 文件, 但不要期望能够在内容中保留注释。Grain 文件和在 Minion 文件中的 Grain 配置基本一样

1
2
3
grains:
foo: bar
baz: qux

需要在 Grain 文件中添加或修改 Grain 时,可以使用 grains.setval 方法

1
salt \* grains.setval mygrain 'this is the content of mygrain'

Grain 的值支持多种类型。大多数 Grain 只包含字符串,也可能包含列表:

1
2
3
my_items:
item1
item2

对列表添加项目(item)时,可以使用grains.append方法

1
salt \* grains.append my_item item3

需要移除一个Grain,可以使用 grains.delval 方法

1
salt \* grains.delval my_items

使用 Pillar 使变量集中化

  pillar 在 master 上定义,存在于一个集中化的路径,默认路径为(/srv/pillar)。由于该区域存放的是用于众多 minion 的信息, 因此需要一种 target 方式来区分 minion。正因如此,使用了 sls 文件。 Pillar 的 top.sls 文件在配置和功能上和 state 的 top.sls 文件一致:首先声明一个环境,然后是一个 target,最后是该 target 需要使用 的 SLS 文件列表

1
2
3
base:
'*':
bash

Pillar 只用于提供静态的数据存储。以键值对(key/value pair)的方式进行定义,有时会包含一定的层级

1
2
3
4
5
6
7
8
9
10
skel_dir: /etc/skel
role: web
web_content:
images:
jpg
png
gif
scripts:
css
js

和 state 的 sls 文件相似,pillar 的 sls 文件可以通过 include 来引用其他 pillar sls 文件。

1
2
include:
users

需要查看所有 Pillar 数据,可以使用 pillar.items 方法

1
salt \* pillar.items

如果 master 配置文件中包含一些敏感数据,可以在 master 的配置文件中添加信息

1
pillar_opts: False

除了 master 配置数据外,pillar 数据只能被特定的 target minion 看到。默认情况下,minion 不被允许访问其他 minion 的 pillar。 salt 中允许 minion 使用 Peer 系统来执行 master 命令。


通过模板动态管理文件

salt 可以使用模板,结合 grain 和 pillar 数据,使 state 系统变得更动态。支持的模块(2015.5版本)

  • jinja
  • mako
  • wempy
  • cheetah
  • genshi

通过 salt 的渲染器系统(rendering system)使用这些引擎。以上列表只包含了典型的用做模板的渲染器,用于创建配置文件,或与其类似的东西。 还有一些其他渲染器,用于描述数据结构:

  • yaml
  • yamlex
  • json
  • msgpack
  • py
  • pyobjects
  • pydsl

最后,下面的这个渲染器能够在传递给其他渲染器之前,先解密存储在 master 上的 gpg 数据

  • gpg

默认情况下,state 的 sls 文件会首先使用 jinja 进行渲染,然后再使用 yaml 渲染。有两种方法可以将 sls 文件渲染器调整为其他。

首先,如果只有一个 sls 文件不同方式渲染,可以在该文件的第一行中包含 shabang 行来指定渲染器:

1
#!/usr/bin/env python

shabang 可以以管道符号分隔指定多个渲染器,根据使用的顺序排序。也称为渲染器管道(render pipe)。如果想用 mako 和 json 来替代默认 的 jinja 和 yaml, 可以进行如下配置:

1
#!/usr/bin/env mako | json

如果需要更改系统默认值,需要在 master 配置文件中调整 renderer 选项。默认值是:

1
renderer: yaml_jinja

也可以在minion上使用 fle.managed State 创建文件时指定模块引擎:

1
2
3
4
5
6
apache2_conf:
file:
managed
name: /etc/apache2/apache2.conf
source: salt://apache2/apache2.conf
template: jinja

Jinja 快速入门

由于 jinja 是 salt中 最常用的模块引擎。
变量可以通过闭合的双大括号来引用。如有一个叫做 user 的 Grain,可以通过以下方法访问:

1
The user {{ grains['user'] }} is referred to here.

也可以使用同样的方式访问 pillar:

1
The usr {{ pillar['user'] }} is referred to here.

如果 pillar 或 grain 中并没有设置 user,模块不会被渲染。更安全的方法是使用内置的 salt 交叉调用执行模块:

1
2
The user {{ salt['grains.get']('user','larry') }} is referred to here.
The user {{ salt['pillar.get']('user','larry') }} is referred to here.

如果没有设置 user,默认使用 larry 这个值。
可以通过搜索 grain 和 pillar 让模块变得更动态。使用 config.get 方法,salt 会首先搜索 minion 配置文件中的值,如果没有找到, 则会检查 grain; 如果没有则搜索 pillar。如果还是找不到,会搜索 master 配置。如果都没找到,会使用提供的默认值

1
The user {{ salt['config.get']('user','larry') }} is referred to here.

代码块通过闭合的大括号和百分号进行表示,如想在模块中设置一个局部变量(即无法通过 config.get 获取到的),可以使用 set 关键字:

1
{% set myvar = 'My Value' %}

由于 jinja 基于 python,因此大多数 python 数据类型都是可用的。如列表(list)和字典(dictionary):

1
2
{% set mylist = ['apples', 'oranges', 'bananas'] %}
{% set mydict = {'favorite pie': 'key lime', 'favorite cake':'saccher torter'} %}

常用模块示例

  • status(查看系统信息)
1
2
3
4
5
salt \* status.loadavg   # 查看系统负载情况
salt \* status.cpuinfo # 查看 CPU 信息
salt \* status.diskstats # 查看磁盘信息
salt \* status.meminfo # 查看内存信息
salt \* status.w # w 命令返回信息
  • 查看所有 module 列表
1
salt slave.com sys.list_modules
  • 查看指定 module 的所有 function
1
salt slave.com sys.list_functions cmd
  • 查看指定 module 指定方法的帮助文档
1
salt slave.com sys.doc cmd.run

随着 Salt 的不断迭代,会有更多的模块产生,同时部分模块可能会无法使用,请根据使用的 salt 版本查询相关的模块信息。建议在稳定运行前提下, 尽量使用新版本,避免重复造车。


Grains

static bits of information that a minion collects about the system wehn te minion first starts. the grains interface is made available to salt modules and components so that the right salt minion commands are automatically avavilable on the right systems.

  大致意思就是说 grains 是 minion 第一次启动的时候采集的静态数据,可以用在 salt 的模块和其他组件中。例如, 当 os_family 的 grain 数据为 centos 时,则会使用 yum 工具组件来进行软件包管理。grains 会在 minion 进程启动时加载,并缓存在内存中。

1
2
3
salt slave.com pkg.install httpd 
salt \* cmd.run "cat /etc/passwd | tail ‐n 8"
salt slave.com cmd.run "ifconfig eth0"

无须每次操作都重新检索系统来获取 grain,极大的提高了 minion 的性能。

简单的实例

1
salt slave.com grains.items

查看具体每一项信息

1
2
3
salt \* grains.item osfullname
salt \* grains.item nodename
salt \* grains.item ip4_interfaces:eth0

应用场景

  Grains 的特性–每次启动汇报、静态决定了它没有 pillar 灵活,pillar 是随时可变的,只要在 master 端修改了一般都会立刻生效的。 所以 grains 更适合做一些静态的属性值的采集,例如设备的角色(role),磁盘个数(disk_num),操作系统版本等诸如此类非常固定的属性。 简单总结起来 grains 的用途如下:

  • grains可以在state系统应用中,用户配置管理模块。
  • grains可以在target中使用,用来匹配minion比如os,用-G
  • grains可以用于信息查询,grains保存着收集到的客户端的信息。

那么我们就可以得到一个大致的判断,如果你想定义的属性值是经常变化的,那采用 pillar,如果是很固定的、不变的那请用 grains。