STATES TUTORIAL - STATES使用教程
或者您也可以参考在GitHub上相同的另一份资料:States-tutorial
PART 1 - BASIC USAGE
第一部分:基本用法
本教程的目的是演示如何快速配置由Salt States管理的系统。 有关状态系统的详细信息,请参阅完整的状态参考。
本教程将引导您使用Salt配置minion以运行Apache HTTP服务器并确保服务器正在运行。
在继续之前,请先按照安装和配置文档的说明确保您已正确安装Salt。
卡住了?
SETTING UP THE SALT STATE TREE - 配置和启用Salt State Tree
States状态存储在master上的文本文件中,并通过master文件服务器按需传送到minions。 状态文件的集合即构成State Tree
。
要在Salt中开始使用集中式的状态系统,必须首先设置Salt File Server。 编辑master配置文件(file_roots
)并取消以下行的注释:
file_roots:
base:
- /srv/salt
注:如果你通过ports在FreeBSD上部署,则
file_roots
路径默认为/usr/local/etc/salt/states
。
重新启动Salt master以使变更生效:
pkill salt-master
salt-master -d
PREPARING THE TOP FILE - 准备top file文件
在master上,在上一步中取消注释的目录(默认情况下为/srv/salt)中,创建一个名为top.sls的新文件并添加以下内容:
base:
'*':
- webserver
top file文件被划分为多个不同的环境(稍后讨论)。 默认环境是base
。 在base
环境下,定义了一系列minion匹配映射关系; 现在只需简单的指定为所有主机(*)。
Targeting minions
表达式可以使用Salt使用的任何目标定位机制。minions可以通过glob、PCRE正则表达式或者grains来匹配。 例如:
base: 'os:Fedora': - match: grain - webserver
CREATE AN SLS FILE - 创建一个sls文件
在和 top file 文件同一个目录中, 创建一个名为 webserver.sls
的文件, 包含以下内容:
apache: # ID declaration
pkg: # state declaration
- installed # function declaration
第一行称为ID声明,可以是一个任意标识符。 在上面的这种情况下,它定义了要安装的包的名称。
注:Apache httpd Web服务器的软件包名称可能因操作系统或发行版而异 - 例如,在Fedora上它是httpd,但在Debian/Ubuntu上它是apache2。
第二行称为state声明,它定义了我们正在使用哪些Salt States。 在此示例中,我们使用pkg state
来确保安装了给定的包。
第三行称为Function声明,它定义了在pkg state模块中要调用的函数。
Renderers:渲染器
States sls文件可以用多种格式编写。 Salt只需要一个简单的数据结构,而不关心如何构建数据结构。 模板语言和DSL是一个简单而灵活的实现,每个人都喜欢。
构建预期的数据结构是Salt Renderers的工作,它们写起来很简单。
在本教程中,我们将在Jinja2模板中使用YAML,这是Salt的默认格式。 你可以通过在Master配置文件中编辑渲染器来更改默认值。
INSTALL THE PACKAGE - 安装软件包
接下来,让我们运行我们创建的状态文件。 在master服务器上打开终端并运行:
salt '*' state.apply
我们的Master指示所有目标minions运行state.apply。 在没有任何SLS目标的情况下执行此功能时,minion将下载top file文件并尝试匹配其中的表达式。 当minion与表达式匹配时,将为其列出的模块下载、编译和执行。
注意:上面的操作又称为“highstate”,也可以使用state.highstate函数运行。 但是,为了使用更容易理解(“highstate”不一定是直观的名称),在2015.5.0版本中添加了state.apply函数,在没有任何SLS名称的情况下调用时就会触发highstate。
state.highstate
仍然保留且可以使用,但文档(如上所示)已更新为引用state.apply
。state.apply
相当于是一个别名,在不同情况下会调用不同的state函数命令。因此在阅读文档时请记住以下内容:
- 在没有指定任何SLS文件名称的情况下调用
state.apply
的效果相当于运行state.highstate
- 在指定了SLS文件名称的情况下调用的
state.apply
将运行state.sls
命令执行完成后,minion将报告所有采取的行动和做的所有更改的摘要。
Warning
如果你创建了自定义的grain模块,则在执了第一次highstate命令之前,它们都将无法在top file文件中使用。 为了及时在minion的第一个highstate操作上提供custom grains数据,建议使用此示例以确保在minion启动时可以自动同步自定义grains数据。
SLS File Namespace
请注意,在上面的示例中,SLS文件webserver.sls简称为webserver。 在top.sls或Include声明中引用时,SLS文件的命名空间遵循一些简单的规则:
.sls
的后缀被丢弃了 (也就是说webserver.sls
变成了webserver
).- 子目录被做了更好的组织,其中:
- 每个子目录在Salt状态和命令行中用点(遵循Python导入模型)表示。 文件系统上的
webserver/dev.sls
,在Salt中称为webserver.dev
- 由于斜杠表示为点,因此SLS文件不能在名称中包含点(SLS文件后缀的点除外)。 你将无法正确匹配SLS文件
webserver_1.0.sls
,因为webserver_1.0
将与目录/webserver_1/0.sls
匹配
子目录中名为
init.sls
的文件将通过目录的路径引用。 因此,webserver/init.sls
称作webserver
。如果
webserver.sls
和webserver/init.sls
都存在,webserver/init.sls
将被忽略,webserver.sls
将被作为合法的webserver
使用。
Troubleshooting Salt
如果未看到预期的输出,以下提示可帮助缩小问题分析范围。
- Turn up logging - 打开日志输出
将日志记录设置更改为debug时,Salt可能会输出很繁琐的信息:
salt-minion -l debug
- Run the minion in the foreground - 在前台运行minion程序
通过不以守护进程模式启动minion(-d),也可以查看到minion的所有输出:
salt-minion
- 运行salt时增加默认超时值。 例如,将默认超时更改为60秒
salt -t 60
为了得到最好的效果,结合使用以上三个方法:
salt-minion -l debug # On the minion salt '*' state.apply -t 60 # On the master
NEXT STEPS
本教程重点介绍如何使用简单的Salt States配置。 第2部分将基于此示例构建,以涵盖更高级的sls语法,并将探索更多与Salt一起提供的状态。
PART 2 - MORE COMPLEX STATES AND REQUISITES
第二部分:更复杂的STATES、REQUISITES
注意:本教程章节是以第1部分中介绍的主题为基础。建议您从那里开始阅读。
在Salt States教程的前一部分中,我们介绍了安装软件包的基础知识。 我们现在将修改我们的webserver.sls
文件以满足使用要求,并使用更多的Salt状态配置方法。
CALL MULTIPLE STATES
你可以在ID声明下指定多个State声明。 例如,快速修改我们的webserver.sls
,检查如果Apache服务没有运行,则启动Apache:
apache:
pkg.installed: []
service.running:
- require:
- pkg: apache
在运行state.apply之前停止Apache并观察输出,再次运行并观察。
注意:对于那些运行Redhat OS衍生产品(Centos,AWS)的人,你需要将服务名称指定为httpd。 更多关于state service的知识参考这里。 使用上面的示例,只需在require行上方添加
"- name: httpd"
并使用相同的间距。
REQUIRE OTHER STATES
我们现在有了一个Apache的安装任务,所以让我们添加一个HTML文件来定制我们的网站。 拥有一个没有网络服务器的网站并不是很有用所以我们不希望Salt在安装和运行Apache之前部署我们的HTML文件。 在webserver/init.sls
文件的底部包含以下内容:
apache:
pkg.installed: []
service.running:
- require:
- pkg: apache
/var/www/index.html: # ID declaration
file: # state declaration
- managed # function
- source: salt://webserver/index.html # function arg
- require: # requisite declaration
- pkg: apache # requisite reference
第7行 是 ID 声明。在此示例中,它是我们要安装自定义HTML文件的位置。 (注意:Apache提供的默认位置可能与您的操作系统或发行版上的上述不同./srv/www
也可能是一个值得关注的地方。)
第8行 是state声明。 此示例使用的是Salt file state
。
第9行 是Function声明。 managed function
将从master服务器下载文件并将其安装在指定的位置。
第10行 是一个Function arg的声明,在本例中,它将source
参数传递给managed
函数。
第11行 是 Requisite的声明。
第12行 是Requisite的参数,它指向了一个state和一个ID。 在这个例子中,它引用了我们在第1部分中的示例中的ID声明。该声明告诉Salt在安装Apache服务之前不要安装HTML文件。
接下为, 创建 index.html
文件并把它保存在 webserver
目录中:
<!DOCTYPE html>
<html>
<head><title>Salt rocks</title></head>
<body>
<h1>This file brought to you by Salt</h1>
</body>
</html>
最后, 再次调用state.apply,minion将从master获取数据并执行highstate,以及从Salt的文件服务器获取我们的HTML文件:
salt '*' state.apply
检查一下Apache是否可以正确地为我们自定义的HTML网页提供服务。
require vs. watch
有两个Requisite declaration,“require”和“watch”。 并非每个state都支持“watch”。
service state
支持“watch”,并可以根据监视条件重新启动服务。例如,如果您使用Salt安装Apache虚拟主机配置文件并希望在更改该文件时重新启动Apache,则可以修改我们之前的Apache示例:
/etc/httpd/extra/httpd-vhosts.conf: file.managed: - source: salt://webserver/httpd-vhosts.conf apache: pkg.installed: [] service.running: - watch: - file: /etc/httpd/extra/httpd-vhosts.conf - require: - pkg: apache
如果您的操作系统或发行版的pkg和服务名称不同,您可以使用第3部分中说明的Name declaration单独指定每个名称。
NEXT STEPS
在第3部分中,我们将讨论如何使用includes、extends和templating来创建更完整的状态树配置。
PART 3 - TEMPLATING AND INCLUDES AND EXTENDS
第三部分:模板、包含和扩展
注意:这一章节的教程是在前面两部分主题内容的基础上进行的,建议从那里开始阅读。
本教程的这一部分将介绍sls文件的更高级模板和配置技术。
TEMPLATING SLS MODULES
在处理复杂业务逻辑时,SLS模块可能需要编程逻辑或内联执行。 这是通过模块模板实现的。 使用的默认模块模板系统是Jinja2,这可以通过更改master配置中的renderer
值来配置。
所有状态在最初读取时都通过模板系统。 要使用模板系统,只需添加一些模板标记即可。 带模板标记的sls模块的示例可能如下所示:
{% for usr in ['moe','larry','curly'] %}
{{ usr }}:
user.present
{% endfor %}
这个模板化的sls文件一旦生成将如下所示:
moe:
user.present
larry:
user.present
curly:
user.present
下面是一个更复杂的示例:
# Comments in yaml start with a hash symbol.
# Since jinja rendering occurs before yaml parsing, if you want to include jinja
# in the comments you may need to escape them using 'jinja' comments to prevent
# jinja from trying to render something which is not well-defined jinja.
# e.g.
# {# iterate over the Three Stooges using a {% for %}..{% endfor %} loop
# with the iterator variable {{ usr }} becoming the state ID. #}
{% for usr in 'moe','larry','curly' %}
{{ usr }}:
group:
- present
user:
- present
- gid_from_name: True
- require:
- group: {{ usr }}
{% endfor %}
USING GRAINS IN SLS MODULES - 在SLS模块中使用grains
通常情况下,state状态需要在不同系统上表现不同的行为。 Salt grains对象在模板上下文中可以使用。 在sls模块中使用grains:
apache:
pkg.installed:
{% if grains['os'] == 'RedHat' %}
- name: httpd
{% elif grains['os'] == 'Ubuntu' %}
- name: apache2
{% endif %}
USING ENVIRONMENT VARIABLES IN SLS MODULES - 在SLS模块中使用环境变量
你可以使用 salt['environ.get']('VARNAME')
的方式在一个Salt state中使用环境变量参数。
MYENVVAR="world" salt-call state.template test.sls
Create a file with contents from an environment variable:
file.managed:
- name: /tmp/hello
- contents: {{ salt['environ.get']('MYENVVAR') }}
带错误检测的配置方法:
{% set myenvvar = salt['environ.get']('MYENVVAR') %}
{% if myenvvar %}
Create a file with contents from an environment variable:
file.managed:
- name: /tmp/hello
- contents: {{ salt['environ.get']('MYENVVAR') }}
{% else %}
Fail - no environment passed in:
test.fail_without_changes
{% endif %}
CALLING SALT MODULES FROM TEMPLATES - 在模板中调用Salt模块的方法
由minion加载的所有Salt模块都可在模板系统中使用。 这允许在目标系统上实时收集数据。 它还允许从sls模块中轻松运行shell命令。
Salt模块函数也可以在模板上下文中以salt:
形式提供。
以下示例说明中使用名为some_group_that_exists
的单个位置参数调用文件执行模块中的group_to_gid
函数。
moe:
user.present:
- gid: {{ salt['file.group_to_gid']('some_group_that_exists') }}
考虑这种情况的一种方法可能是为gid键分配了一个等价于以下python伪代码的值:
import salt.modules.file
file.group_to_gid('some_group_that_exists')
请注意,要使上述示例起作用,在模板引擎处理状态文件之前,some_group_that_exists
必须是存在的。
下面是一个使用network.hw_addr
函数检索eth0的MAC地址的示例:
salt['network.hw_addr']('eth0')
要检查每个执行模块函数的可以使用的参数,可以检查模块参考文档。
ADVANCED SLS MODULE SYNTAX - 高级SLS模块语法
最后,我们将介绍一些非常有用的技术,用于更复杂的状态树。
INCLUDE DECLARATION
前面的示例演示了如何在多个文件中构建Salt树。 同样的,Requisites and Other Global State Arguments可以使用Include declaration跨越多个文件。 例如:
python/python-libs.sls:
python-dateutil:
pkg.installed
python/django.sls:
include:
- python.python-libs
django:
pkg.installed:
- require:
- pkg: python-dateutil
EXTEND DECLARATION
您可以使用Extend声明修改以前的声明。 例如,以下内容修改了Apache状态树,以便在更改vhosts文件时重新启动Apache:
apache/apache.sls:
apache:
pkg.installed
apache/mywebsite.sls:
include:
- apache.apache
extend:
apache:
service:
- running
- watch:
- file: /etc/httpd/extra/httpd-vhosts.conf
/etc/httpd/extra/httpd-vhosts.conf:
file.managed:
- source: salt://apache/httpd-vhosts.conf
Using extend with require or watch
extend
语句对require
或watch
的工作方式不同。 它是附加,而不是替换requiste的组件。
NAME DECLARATION
你可以使用Name声明覆盖ID声明。 例如,如果像下面这样重写,前面的示例会更易于维护:
apache/mywebsite.sls:
include:
- apache.apache
extend:
apache:
service:
- running
- watch:
- file: mywebsite
mywebsite:
file.managed:
- name: /etc/httpd/extra/httpd-vhosts.conf
- source: salt://apache/httpd-vhosts.conf
NAMES DECLARATION
更强大的是使用Names声明一次覆盖多个状态的ID声明。 这通常可以消除模板中循环的需要。 例如,本教程中的第一个示例可以在没有循环的情况下重写:
stooges:
user.present:
- names:
- moe
- larry
- curly
NEXT STEPS
在第4部分中,我们将讨论如何使用salt的file_roots来设置一个工作流,在该工作流中,状态可以从开发、QA到生产依次“升级”。
PART 4 - Set Up a Workflow by Salt states
第四部分:使用salt的file_roots来设置一个工作流,在该工作流中,状态可以从开发、QA到生产依次“升级”。
注意:这一章节的教程是在前面三部分主题内容的基础上进行的,建议从那里开始阅读。
SALT FILESERVER PATH INHERITANCE - Salt文件服务器的路径继承关系
Salt的文件服务器允许每个环境拥有多个根目录,如下例所示,它使用本地目录和通过NFS共享给salt master服务器的第二个目录:
# In the master config file (/etc/salt/master)
file_roots:
base:
- /srv/salt
- /mnt/salt-nfs/base
Salt的文件服务器会将根目录的列表合并到包含每个根的所有文件的单个虚拟环境中。 如果同一文件存在于多个根目录中的相同相对路径中,则最顶部先匹配上的“胜出”。 例如,如果/srv/salt/foo.txt
和/mnt/salt-nfs/base/foo.txt
都存在,那么salt://foo.txt
将指向/srv/salt/foo.txt
。
注意:使用多个文件服务器后端时,它们在fileserver_backend参数中列出的顺序也很重要。 如果
roots
和git
后端包含一个具有相同相对路径的文件,并且’roots’目录出现在fileserver_backend
列表中的git
之前,那么roots
中的文件将“win”,并且gitfs
中的文件将被忽略。有关Salt的模块化文件服务器如何工作的更全面的解释可以在这里找到。 我们建议阅读此内容。
ENVIRONMENT CONFIGURATION - 环境配置
一个多环境的文件服务后端配置会像下面这样:
file_roots:
base:
- /srv/salt/prod
qa:
- /srv/salt/qa
- /srv/salt/prod
dev:
- /srv/salt/dev
- /srv/salt/qa
- /srv/salt/prod
鉴于上述路径继承关系,/srv/salt/prod
中的文件将在所有环境中可用。 /srv/salt/qa
中的文件可以在qa
和dev
中使用。 最后,/srv/salt/dev
中的文件只能在dev
环境中使用。
根据定义roots的顺序,可以将新files/states放在/srv/salt/dev中,然后推送到开发主机进行测试。
然后可以将这些files/states移动到/srv/salt/qa
中的相同相对路径,它们现在可以在dev
和qa
环境中使用,允许它们被推送到QA主机并进行测试。
最后,如果移动到/srv/salt/prod
中的相同相对路径,则文件现在可在所有三种环境中使用。
REQUESTING FILES FROM SPECIFIC FILESERVER ENVIRONMENTS - 从特定的FILESERVER环境中请求文件
有关如何从特定环境请求文件的文档,请参见此处。
PRACTICAL EXAMPLE - 一个实际的例子
例如,考虑一个安装到/var/www/foobarcom
的简单网站。 以下是可用于部署网站的top.sls:
/srv/salt/prod/top.sls:
base:
'web*prod*':
- webserver.foobarcom
qa:
'web*qa*':
- webserver.foobarcom
dev:
'web*dev*':
- webserver.foobarcom
使用pillar, 为各主机指定角色:
/srv/pillar/top.sls:
base:
'web*prod*':
- webserver.prod
'web*qa*':
- webserver.qa
'web*dev*':
- webserver.dev
/srv/pillar/webserver/prod.sls:
webserver_role: prod
/srv/pillar/webserver/qa.sls:
webserver_role: qa
/srv/pillar/webserver/dev.sls:
webserver_role: dev
最后, 定义一个SLS,用于部署website。
/srv/salt/prod/webserver/foobarcom.sls:
{% if pillar.get('webserver_role', '') %}
/var/www/foobarcom:
file.recurse:
- source: salt://webserver/src/foobarcom
- env: {{ pillar['webserver_role'] }}
- user: www
- group: www
- dir_mode: 755
- file_mode: 644
{% endif %}
鉴于上述SLS,网站的源文件最初应放在/srv/salt/dev/webserver/src/foobarcom
中。
首先,让我们部署到dev
。 鉴于top file文件中的配置,可以使用state.apply
完成:
salt --pillar 'webserver_role:dev' state.apply
但是,如果不希望应用top file文件中配置的所有状态(可能在更复杂的设置中),则可以通过调用state.apply
来仅应用为foobarcom
网站定义的配置状态。 将期望的SLS目标作为参数:
salt --pillar 'webserver_role:dev' state.apply webserver.foobarcom
一旦站点通过了dev
环境中的测试,就可以将文件从/srv/salt/dev/webserver/src/foobarcom
移动到/srv/salt/qa/webserver/src/foobarcom
,并使用以下命令进行部署:
salt --pillar 'webserver_role:qa' state.apply webserver.foobarcom
最后,一旦站点在qa
中通过了测试,那么文件可以从/srv/salt/qa/webserver/src/foobarcom
移动到/srv/salt/prod/webserver/src/foobarcom
,并使用以下内容进行部署:
salt --pillar 'webserver_role:prod' state.apply webserver.foobarcom
感谢Salt的文件服务器继承功能,即使文件已经移动到/srv/salt/prod
中,它们仍然可以在qa
和dev
环境中使用相同的salt://
URI。
CONTINUE LEARNING
继续学习Salt States的最佳方法是阅读参考文档并查看现有状态树的示例。 许多预先配置的状态树可以在GitHub上saltstack-formula集合的存储库的中找到。
如果你有任何问题、建议或只是想与使用Salt的其他人聊天,我们有一个非常活跃的社区,我们很乐意听取您的意见。
此外,通过继续阅读Orchestrate Runner文档,你可以了解Salt所具备的强大的编排功能。
PART 5 - ORCHESTRATION WITH SALT
第五部分:使用Salt进行服务编排
这个部分的内容已经整合到了 Orchestrate Runner 中。