我们如何使用Salt States?

简单,简单,简单

很多最强大、最有用的工程解决方案都是基于简单原则建立起来的。Salt States 也竭尽全力做到那样:K.I.S.S.(Keep It Stupidly Simple 简单到愚蠢)

Salt 状态系统的核心是SLS,或者叫**S**aLt State 文件。SLS表示系统将会是什么样的一种状态,而且是以一种很简单的格式来包含这些数据。这经常也被叫做配置管理。

注解

这只是使用states的入门, 要深入的话请接下来阅读 pillar Pillar.

所有都是数据

在深入研究细节之前,细节将有助于理解SLS文件只是蒙上面纱的数据结构。虽然明白SLS只是一种数据结构不是理解和使用Salt States的关键,但这对巩固知识是非常有用效的。

因此,SLS文件实际上只是一些: 词典dictionaries, 列表lists, 字符串, and 数字.通过使用这些方法,使得Salt更加灵活. 多写state 文件,将更加明白需要写什么。 其结果就是系统更加容易理解,即使系统管理员和开发人员的需求不断增加。

顶级配置文件

以下部分的示例SLS 文件可以用一个叫做:strong:top.sls`的文件存在主机上。 这个文件进行了深入的描述: :doc:`这里</ref/states/top>.

默认数据格式 - YAML

缺省情况Salt把SLS数据表现为可用的最简单的系列化格式中的一种 - YAML

一个典型的SLS 文件常常看起来像这样的YAML:

注解

那些演示使用了一些通用服务和包名,不同的发行版常使用不同的包名和服务名。例如在Red Hat系统上 apache`要被替换为`httpd。Salt使用初始化脚步,系统进程名称,upstart名等名称都要基于平台的底层服务管理。在平台执行service.get_all salt 功能获取可用的服务名列表。

如何让States在多个发行版上同时工作的信息在后面指南里有。

apache:
  pkg.installed: []
  service.running:
    - require:
      - pkg: apache

这个SLS数据将保证apache包被安装了而且apache服务是处于运行状态。组件可以以一种简单的方式来解释。

第一行是这一组数据的ID,被叫做ID 声明。这个ID设置了需要被维护的东西的名字。

The second and third lines contain the state module function to be run, in the format <state_module>.<function>. The pkg.installed state module function ensures that a software package is installed via the system's native package manager. The service.running state module function ensures that a given system daemon is running.

Finally, on line five, is the word require. This is called a Requisite Statement, and it makes sure that the Apache service is only started after a successful installation of the apache package.

增加配置和用户

当建立一个类似Apache web服务器这样的服务时,许多组件需要被添加。Apache 的配置文件肯定要被管理起来,而且需要设置特定的用户和用户组。

apache:
  pkg.installed: []
  service.running:
    - watch:
      - pkg: apache
      - file: /etc/httpd/conf/httpd.conf
      - user: apache
  user.present:
    - uid: 87
    - gid: 87
    - home: /var/www/html
    - shell: /bin/nologin
    - require:
      - group: apache
  group.present:
    - gid: 87
    - require:
      - pkg: apache

/etc/httpd/conf/httpd.conf:
  file.managed:
    - source: salt://apache/httpd.conf
    - user: root
    - group: root
    - mode: 644

这个SLS数据在第一个例子的基础上扩展了很多,而且他包含了一个配置文件,一个用户,一个用户组和一个需求声明: watch.

增加更多的状态也很容易,自从在Apache ID下建立了新用户和用户组状态,用户和组将成为Apache的用户和组。``require``声明将保证是在创建用户组后再创建用户,用户组又是在Apache包安装后才创建。

紧接着,处于服务中中的“require”语句会被更改为“watch”,而且现在是监测的是3个state而不是1个。“watch”语句的功能和“require”相同。在运行“watch”之前先要确保有其他的state在运行,但是“watch”会添加额外的组件。“watch”语句会对它所监控的所有state的任何改变运行监测功能。所以如果安装包被更新了,组态文件夹更改了用户名更改了,然后state监测服务就会运行,这个服务仅仅只是重启它自身的的服务。但在组态文件夹被更改的情况下将会激发被更改的各个项目各自的重启。

超越单个SLS

当以一种可扩展的方式建立Salt States时,需要用到多个SLS文件。上面的例子是在单一的SLS文件中,不过可以用两个或多个文件组合成一个状态树State Tree。上面的例子也引用了一个有点奇怪的来源-salt://apache/httpd.conf。被引用的文件也必须是可用的。

这些SLS文件放在Salt master上一个目录中,一个SLS就是一个文件,而且被下载到minion也还是文件。

Apache的例子将像这样表现在Salt 文件服务器根路径下:

apache/init.sls
apache/httpd.conf

所以httpd.conf是apache 目录下的一个文件,而且是被直接引用的

Do not use dots in SLS file names or their directories

The initial implementation of top.sls and Include declaration followed the python import model where a slash is represented as a period. This means that a SLS file with a period in the name ( besides the suffix period) can not be referenced. For example, webserver_1.0.sls is not referenceable because webserver_1.0 would refer to the directory/file webserver_1/0.sls

The same applies for any subdirecortories, this is especially 'tricky' when git repos are created. Another command that typically can't render it's output is `state.show_sls` of a file in a path that contains a dot.

但是当使用超过单独一个SLS文件时,更多的组件可以被添加到工具箱中。看看这个SSH的例子:

ssh/init.sls:

openssh-client:
  pkg.installed

/etc/ssh/ssh_config:
  file.managed:
    - user: root
    - group: root
    - mode: 644
    - source: salt://ssh/ssh_config
    - require:
      - pkg: openssh-client

ssh/server.sls:

include:
  - ssh

openssh-server:
  pkg.installed

sshd:
  service.running:
    - require:
      - pkg: openssh-client
      - pkg: openssh-server
      - file: /etc/ssh/banner
      - file: /etc/ssh/sshd_config

/etc/ssh/sshd_config:
  file.managed:
    - user: root
    - group: root
    - mode: 644
    - source: salt://ssh/sshd_config
    - require:
      - pkg: openssh-server

/etc/ssh/banner:
  file:
    - managed
    - user: root
    - group: root
    - mode: 644
    - source: salt://ssh/banner
    - require:
      - pkg: openssh-server

注解

注意我们有两种差不多的方法表示一个文件是被Salt管理的。在上面的`/etc/ssh/sshd_config` 状态部分,我们用`file.managed`状态声明,而在 /etc/ssh/banner 状态部分,我们使用,`file`状态声明,然后加一个`managed`属性给那个状态声明。两种方式都产生一个结果;第一种方式 -- 使用 file.managed-- 只不过是一个快捷方式。

现在我们的State状态树看起来像这样:

apache/init.sls
apache/httpd.conf
ssh/init.sls
ssh/server.sls
ssh/banner
ssh/ssh_config
ssh/sshd_config

这个例子介绍了``include``声明。include声明包含另一个SLS文件,以便看到的那些组件可以被请求到,监控到或者很快看到效果 - extended。

Include声明允许stated被交叉连接。当SLS文件有一个include声明 ,它会像字面量一样包含被include的SLS文件的内容。

注意有些SLS文件被叫做init.sls,而有些不是。关于这个的更多信息可以在这里找到 States Tutorial.

扩展包含的SLS数据

有时候SLS数据需要被扩展。有可能apache服务需要监控更多的资源,在不同的环境下需要放置为不同的文件。

在这些例子中,第一个增加了一个定制的banner给ssh,第二个增加了更多的观察器给apache,为了包含mod_python

ssh/custom-server.sls:

include:
  - ssh.server

extend:
  /etc/ssh/banner:
    file:
      - source: salt://ssh/custom-banner

python/mod_python.sls:

include:
  - apache

extend:
  apache:
    service:
      - watch:
        - pkg: mod_python

mod_python:
  pkg.installed

The custom-server.sls file uses the extend statement to overwrite where the banner is being downloaded from, and therefore changing what file is being used to configure the banner.

在新的mod_python SLS中,mod_python包已经被添加了,但是更重要的apache 服务还是被通过观察mod_python 包的方式扩展进来。

对比扩展和`required`or watch

extend 语句的工作方式有别于``require``或者``watch``,它只是附加而不是替换必要的组件。

理解渲染系统

SLS数据是非常简单的(数据),他不是必须用YAML表示。Salt默认用YAML格式是因为它非常直接,而且容易学习和使用。不过只要有一个渲染器,SLS文件可以从任何你能想象到的媒介中渲染出来。

默认的渲染系统是``yaml_jinja``渲染器。``yaml_jinja``渲染器第一个传递模板给递`Jinja2`_ templating 系统,然后给YAML 分析器。这样的好处是在创建SLS文件的时候,整个编程结构都是有用的。

其他渲染器是 yaml_mako 和``yaml_wempy``,他们各自使用`Mako`_ 或`Wempy`_ 模板系统表示而不是jinja模板系统,更加值得注意的是,纯Python或``py``, pydsl & pyobjects 渲染器。``py``渲染器允许SLS文件用纯Python来写,允许在准备SLS数据时最大程度的灵活和强大,且 pydsl 渲染器提供了一个灵活、领域特定语言来以Python编写SLS数据; 而且 pyobjects 渲染器给你一个`"Pythonic"`_ 接口,用来建立状态数据。

注解

上述模板引擎不只是在SLS文件中有用。他们同样可以用在:mod:file.managed <salt.states.file.managed> 状态,进行更加动态、灵活的文件管理。使用模板管理文件的例子在这里可以找到:doc:file states </ref/states/all/salt.states.file>,以及 the MooseFS example 的下面。

了解默认值- yaml_jinja

默认渲染器- yaml_jinja,允许使用jinja模板系统。Jinja模板系统的引导可以再这里找到: http://jinja.pocoo.org/docs

渲染器工作时有一些有用的数据会传递。在基于渲染器模板引擎,三个关键组件是有用的,salt, grains, and pillar``salt``对象允许模板调用任何Salt函数,``grains``允许模板内存钱Grains数据。一些例子如下:

apache/init.sls:

apache:
  pkg.installed:
    {% if grains['os'] == 'RedHat'%}
    - name: httpd
    {% endif %}
  service.running:
    {% if grains['os'] == 'RedHat'%}
    - name: httpd
    {% endif %}
    - watch:
      - pkg: apache
      - file: /etc/httpd/conf/httpd.conf
      - user: apache
  user.present:
    - uid: 87
    - gid: 87
    - home: /var/www/html
    - shell: /bin/nologin
    - require:
      - group: apache
  group.present:
    - gid: 87
    - require:
      - pkg: apache

/etc/httpd/conf/httpd.conf:
  file.managed:
    - source: salt://apache/httpd.conf
    - user: root
    - group: root
    - mode: 644

这是个简单例子。如果``os`` grain states指明操作系统是Red Hat,Apache包和服务的名称需要是httpd。

一个更加激进的使用Jinja的方法可以在这里找到,在模块中建立一个MooseFS分布式文件系统的Chunkserver:

moosefs/chunk.sls:

include:
  - moosefs

{% for mnt in salt['cmd.run']('ls /dev/data/moose*').split() %}
/mnt/moose{{ mnt[-1] }}:
  mount.mounted:
    - device: {{ mnt }}
    - fstype: xfs
    - mkmnt: True
  file.directory:
    - user: mfs
    - group: mfs
    - require:
      - user: mfs
      - group: mfs
{% endfor %}

/etc/mfshdd.cfg:
  file.managed:
    - source: salt://moosefs/mfshdd.cfg
    - user: root
    - group: root
    - mode: 644
    - template: jinja
    - require:
      - pkg: mfs-chunkserver

/etc/mfschunkserver.cfg:
  file.managed:
    - source: salt://moosefs/mfschunkserver.cfg
    - user: root
    - group: root
    - mode: 644
    - template: jinja
    - require:
      - pkg: mfs-chunkserver

mfs-chunkserver:
  pkg.installed: []
mfschunkserver:
  service.running:
    - require:
{% for mnt in salt['cmd.run']('ls /dev/data/moose*') %}
      - mount: /mnt/moose{{ mnt[-1] }}
      - file: /mnt/moose{{ mnt[-1] }}
{% endfor %}
      - file: /etc/mfschunkserver.cfg
      - file: /etc/mfshdd.cfg
      - file: /var/lib/mfs

例子显示更多Jinja的可用的能力,多循环用来动态检测硬盘可用、而且已经被挂载,而且 salt 对象被多次使用来调用shell命令收集数据。

Introducing the Python, PyDSL, and the Pyobjects Renderers

有时候使用默认的渲染器没有足够的逻辑能力来执行所需的任务。这种情况下可以使用Python渲染器。通常多数SLS文件或使用YAML渲染器,不过SLS文件可以使另一个渲染器可以很容易地添加到树中。

这个例子展示了一个非常基础的Python SLS文件:

python/django.sls:

#!py

def run():
    '''
    Install the django package
    '''
    return {'include': ['python'],
            'django': {'pkg': ['installed']}}

这是个简单的例子,第一行是SLS组织行,告诉Salt不要用默认的渲染器,而是使用``py``渲染器。然后运行定义的功能,运行功能返回值必须是Salt友好的数据结构或从这里了解更多一个Salt:doc:HighState data structure</ref/states/highstate>.

作为一种选择,使用 :doc:`pydsl</ref/renderers/all/salt.renderers.pydsl>`渲染器,上面的例子可以被更加简洁地写为:

#!pydsl

include('python', delayed=True)
state('django').pkg.installed()

文档:doc:pyobjects</ref/renderers/all/salt.renderers.pyobjects> 渲染器提供了一个 `"Pythonic"`_对象,它是建立状态数据的基础方法。上面的例子可以被写为:

#!pyobjects

include('python')
Pkg.installed("django")

These Python examples would look like this if they were written in YAML:

include:
  - python

django:
  pkg.installed

例子显然的表明:1、使用YAML渲染器是明智的选择,2、获得更加猛烈的能力需要使用纯Python SLS。

运行和调试salt 状态。

一旦SLS内部规则准备妥当,他们将被测试以确保能工作正常。为了调用哪些规则,在命令行简单执行 salt '*' state.highstate 就可以了。如果仅仅收到以 : 结束的主机名,但是没有返回值,有可能是一个或多个SLS文件有问题。在minion上,使用 salt-call 命令: salt-call state.highstate -l debug 测试错误输出。这可以帮助解决问题。minion也可以以前台调试模式启动: salt-minion -l debug

接下来阅读

理解states的同时,接下来的推荐是熟悉 Salt's pillar 接口: