写点什么

SaltStack: 能够灵活且可扩展的配置管理

2014 年 7 月 09 日

配置管理作为基础使现代基础设施成为可能。在任何运维团队的工具箱中,都需要那些实现配置管理的工具,甚至对于很多开发团队也是如此。尽管所有的工具旨在解决同样的基本问题集,但它们遵循了不同的看法,并表现出不同的特点。问题在于如何选出适合各个组织具体情况的最佳工具。

本文作为该系列的一部分,旨在介绍当前市场上存在的部分配置工具,以及各个工具背后的原理,和使它们彼此脱颖而出的原因。您可以在这里订阅此系列新文章的提醒。

协会当前状态

几个月前,在蒙特利尔Python 和DevOps 用户组的联合会议上,我做了以下报告:可用于配置管理的多种可选工具项。不论是自己开发,还是从开源中获取,亦或是商业购买来的,大多数系统管理员、开发人员和IT 运维专家都用到一些工具用于自动化基础设施和配置所有方面以确保各技术完成我们所期待的工作。在该报告中,我试图为那些最流行的选项提供客观的看法。但这也取决于你的咨询对象及其思维方式,还有他们的管理对象,几乎每个人都有自己的偏好。

在以往的计算日子里,一般公司只需维护少量服务器,IT 人员通过频繁地手动调整及重新调整这些服务器就可以保证其LOLcats 网站正常平稳地运行。

但自此之后很多情况都发生了变化,尤其最近这几年变化特别大。现在大型数据中心和向外拓展的服务器集群占据了主导地位,手动管理各个服务器已不再可能。各种配置管理工具不断涌现,尽管如此,即使是在过去十年里设计的一些工具也不能适应目前这种规模等级的发展。

SaltStack 因此应运而生。尽管也有一些爱好将 SaltStack master 运用在 Raspberry Pi,或利用它管理几台在自己地下室的服务器所组成的家庭网络,但 SaltStack 的真正目标是速度和规模。这就是为什么 LinkIn、WikiMedia 和 Google 都利用它来管理由数以万计服务器构成的大型基础架构。市场需要的并非是另外一个配置管理工具,它需要的是能适合现代 Web 大规模基础设施的配置管理工具。这篇文章中,我将重点放在使用 SaltStack 来进行配置管理上。

首先是一个快速远程执行平台

最初 SaltStack 被设计为一个特别快速、具有可拓展性和强大的远程执行引擎,目的是为了有效控制分布式基础架构、代码和数据。随后,在远程执行引擎上层构建了配置管理,并使用了相同的内核功能。

“SaltStack 能做到这点”是 Salt 社区最常见的评论。对于 Salt 用户来说,SaltStack 就是数据中心的瑞士军刀。持续却轻量级的 SaltStack master/minion 拓扑为所有环境带来了广泛的控制和功能性,而所有这些都是来自单一平台,不带有第三方依赖。

Salt master 是管理 Salt minions 的守护进程。同样 Salt minions 也是守护进程,运行于受控系统上,用于接收来自 Salt master 的命令。按 SaltStack 的设计,每个 master 能处理一万个 minion 进程,但这也只是保守估计。这一规模可以通过异步、并行指令、对实时管理的控制以及与任何数据中心系统的沟通来实现。

对于不需要实时控制或极端速度及规模的轻量级用例,SaltStack 同样也提供了 Salt SSH“无代理”模式的系统管理。

此外,远程执行和配置管理结合在一起会更好。因为彼此都需要对方在某一时刻开始为其提供真正的基础设施自动化和控制。SaltStack 平台为类似持续代码部署或自动拓展资源等事件驱动行为提供了 Salt Reactor 系统。

想要基本理解 SaltStack 事件系统则需要先理解 SaltStack reactor 系统。事件系统是本地 ZeroMQ PUB 接口,用于触发 SaltStack 事件。该事件总线是个开放系统,用于给 SaltStack 和其它系统发送针对各个操作的提示信息。该事件系统所触发的事件带有十分特定的标准。所有事件都带有标签。该事件标签允许对事件进行快速的顶层过滤。除了标签,所有事件还拥有数据结构。该数据结构是一个包含该事件信息的目录。

SaltStack reactor 系统处理 SaltStack 事件,并基于逻辑引擎执行命令,从而允许事件触发行为。SaltStack 能处理和响应来自本身和其它类似 Jenkins 等系统的事件。

近期 Hearbleed 漏洞就是个很好的例子,它展示了我们的客户如何通过使用 SaltStack 控制基础架构的所有点点滴滴。SaltStack 以毫秒速度跨越整个大型基础架构,被用于诊断和修复 Heartbleed 。比如:来自 WebPlatform.org 和 WikiMedia 的这些推文强调了 SaltStack 在作出这些修正时的简单性:

在多台服务器上打 OpenSSL 的漏洞补丁包?只要输入 salt ‘*’pkg.install openssl。是的,就这么简单!Salt Stack 真的是太棒了。

- Renoir Boulanger (@renoirb) 2014 年 4 月 8 号

多亏了#SaltStack ,Wikimedia 的 heartbleed 补丁包安装的相当快速且容易。

- Ryan Lane(@SquidDLane) 2014 年 4 月 8 号

以下 SaltStack 命令使得评估和修复 Heartbleed 漏洞成为可能:

Salt \*pkg.install openssl refresh=True; salt \*service.restart nginx; #devops #saltstack #heartbleed

- Dan Garthwaite(@DanGarthwaite) 2014 年 4 月 8 号

IMO,1000% 值得,最新的 @SaltStackInc 仅远程执行功能就值得拥有。命令行检测 40 台服务器上的 OpenSSL 就只要 0.2 秒!

- John Albietz(@inthecloud247) 2014 年 4 月 10 号

基础设施即数据,而非代码

通过实施“基础设施即数据”方法,SaltStack 的配置管理学习和采用曲线已降低。在不牺牲任何功能和性能的情况下,该方法相对传统“基础设施即代码”方法大大降低了复杂度。“基础架构即代码”通常要求用户能够理解复杂的机器代码语言或领域特定语言。而 SaltStack 方法可人工阅读,当然也能轻松地被机器解读。

尽管 SaltStack 是用 Python 语言编写,但其配置管理是语言无关的,且使用了简单、人类可读的 YAML 文件和 Jinja 模板。

DevOps 和可扩展的 WebIT 要求速度、敏捷性和通信。学习曲线越短,其竞争优势就越大。尽管在“基础设施即代码”上投资显著,但其实并不需要,因为它阻碍了创新和部署,本来部署就应以快速为原则尽可能快地将服务器及其上面运行的软件调整到稳定、可重用和生产就绪的状态。何必坐着航天飞机到街角市场,明明走路或骑自行车更容易?

极具灵活性

SaltStack 由多个不同模块层组成的,全部都利用了相同的快速通信总线,这允许了其与尽可能多的服务器进行并行通信以通知服务器应该做什么。这些命令、例行程序和功能所组成的层为整个计算基础架构和所有数据中心内容提供了广泛的控制。我们的很多用户都通过 SaltStack 通知 Puppet manifest 应该做什么,因为 SaltStack 可以用于管理软件、云或虚拟化的其它任意部分。

在过去几年里对于选择声明式还是命令式方式来配置管理,一直存有纷争。而我们,则“往该纷争中插了个叉子”。SaltStack 不仅可使用声明式配置管理,也可以用于命令式。至于怎么用,就取决于你怎么想,以及你的系统如何被管理。

SaltStack 配置管理可以以命令式方式执行,所有事务将按给定顺序执行。也可以以声明式方式执行,系统决定如何执行对象间匹配有关联的各事务。

命令式排序是有限的,普遍被认为比较容易编写。声明式排序则强大很多,也更灵活,但往往比较难写。

SaltStack 的创建就是为了最好地使用这两种配置方式。状态以有限顺序评估,保证了所有状态总是按同样的顺序执行,而状态运行时确是声明式的,使得 Salt 能完全意识到关联。Salt 总是以有限方式执行状态,这意味着不论运行系统怎样,它们都将以相同的顺序执行。尽管如此,SaltStack 近期添加了状态自动排序这一选项,使得状态能按其在Salt 状态文件中所定义的顺序被评估。

评估顺序允许我们简单地获知状态将以什么顺序执行,但值得注意的是,在必要时系统会覆盖文件中定义的排序。下面将要描述的排序选项也可以覆盖Salt 状态文件中所定义的状态顺序。

当SaltStack 提供 hook (比如:“on fail”或“on change”)到声明式路径中时,其架构所蕴含的能量允许往配置管理运行过程中插入例行程序,这样即使第一次失败了,也可能在换种方式尝试后成功。SaltStack 的先决条件就是其中一个例子。先决条件只有当系统中将来有其他事情发生时才会对系统产生该事件。它是个幂等方式内嵌预测分析。它会问这个问题:“我是否即将要部署代码了?确定?那就把服务器从负载平衡器上卸下来,或者将 Apache 关闭吧。但所有这些操作只有当我对系统有所修改时发生。”或者 SaltStack“fail hard”标识会进一步为命令式配置管理提供能量:相对于放弃例行程序,它会通知流程关于事情部署的情况。

使用 SaltStack 在 Red Hat 上安装 LAMP Stack

一个简单的 SaltStack 配置管理场景是安装 LAMP stack。尽管在 GitHub 上有关于更完整采用 SaltStack 方案的组织实例( https://github.com/saltstack-formulas ),但本例应能充分地展示了基本的方案,它是某一指定资源配置管理的预编写 Salt 状态。SaltStack 方案和状态可以用于类似、:安装软件包、配置和启动一个服务、设置用户或权限以及其他常见任务。

由于该例子是为基于 Linux 的 Red Hat 环境设计的,其中包含了 Python 2.6 为现有基础安装的一部分,其 Linux 和 Python 部分已经完成了。所有需要做的就是配置一个 Web 应用程序并使用 Apache Web 服务器和 MySQL 数据库服务器。

开始前,我们要确保 /srv/salt/ 目录存在于服务器中。

因为 Web 应用程序需要在使用前安装数据库服务器,我们将首先定义数据库服务器。

复制代码
# /srv/salt/mysql.sls
mysql:
pkg.installed:
- name: mysql-server
service.running:
- enable: True
- require:
- pkg: mysql-server

由于该例子除了声明外,并不包含其它任何文件。我们可以简单地将其保存为:/srv/salt/mysql.sls。但是 Apache 的安装比较复杂,因为它包含了一个配置文件。该文件通过使用 file.managed 功能被拷贝到 web 服务器上,支持了像 templating 这样加强的功能。为了适应这种情况,我们通过在 /srv/salt/ 目录下创建 apache/ 子目录,并创建以下文件:

复制代码
# /srv/salt/apache/init.sls
httpd:
pkg.installed:
- name: httpd
- file: httpd
service.running:
- enable: True
- require:
- pkg: httpd
file.managed:
- name: /etc/conf/httpd/httpd.conf
- source: salt://httpd/httpd.conf
- require:
- pkg: httpd

由于更多的文件将添加到该方案中,我们创建另外一个目录来保存它们。该目录在包含一个 init.sls 文件的同时,也包含被管理的 httpd.conf 文件副本。这些文件现在会与 top.sls 文件绑定在一起。

复制代码
# /srv/salt/top.sls
base:
web*:
- apache
db*:
- mysql

该文件就像胶水一样将这些状态连接在一起,定义了每个服务器上所应用的状态。需要注意的是该文件并没有涉及任何具体路径。因为 top.sls 定义了这类信息,因此 SaltStack 会到 top.sls 目录下查找。当 SaltStack 在 top.sls 中找到所需名称,接下来它会查找与其名称相对应的.sls 文件(比如:mysql.sls)或者目录,该目录包含一个 init.sls 文件(比如:apache/init.sls)。

该定义确保了所有名字以“web”为开头的服务器(比如:web01,甚至是 web01.example.com)都会有指定的 Apache 状态,还有任何名字以“db”开头的服务器(比如:db01 或 db01.example.com)都会有指定的 MySQL 状态。

将这些状态应用到所有服务器上,我们需要开始运行一个 highstate 命令:

复制代码
salt ‘*’ state.highstate

Highstate 是状态数据的结合(程序包、服务和文件等),它将应用到目的系统中。

然而,它也提出了另一个挑战。正如我上面所说的,这些 web 服务器如果没有可工作的数据库服务器的话,基本上是派不上什么用场。该场景在两者都存在的情况下可以正常工作,我们只要往组合中添加服务器就可以了。但对于一个干净的环境,没有任何服务器的情况该怎么办?

这时候就该轮到 SaltStack 流程引擎上场了。可以通过定义状态执行顺序来定义机器部署顺序:

复制代码
# /srv/salt/myorchestration.sls
db_setup:
salt.state:
- tgt: ‘db*’
- highstate: True
web_setup:
salt.state:
- tgt: ‘web*’
- highstate: True
- require:
- salt: db_setup

这个文件定义了我们之前定义的 web 状态只有在我们所定义的数据库状态执行完后才能执行。启动该状态,可以执行:

复制代码
salt-run state.orchestrate myorchestration

注意:在 salt 0.17.x 里,该命令为:

复制代码
salt-run state.sls myorchestration

寻址配置漂移

上述场景对初始配置一组服务器是可行的。如果按计划执行的话,它会通过配置漂移缓解问题:如果服务器上 httpd.conf 文件被修改了,SaltStack 会将其放置回它需要在的地方,然后汇报给用户都要做那些修改,以回到正确的状态。但程序包的版本怎么办呢?

当 pkg.installed 状态被声明后,SaltStack 会检测底层包管理器来查看该程序包是否已经安装。如果是,那么该状态就已经实现了,不需要任何进一步行为。然而,如果该程序包还没被安装的话,SaltStack 也会通知包管理器安装该程序包,通常会检测该程序包 (依具体环境而异) 的最新可用版本,然后安装。

但随着时间的推移,这会造成一些服务器上的程序包所带版本不一样,由此产生的问题也将难以定位。其解决方案就是使用 pkg.lastes 状态取而代之,这样可以一直保证所有服务器上运行的程序包版本都是最新的。

复制代码
httpd:
pkg.latest:
- name: httpd

尽管如此,这也可能产生问题。只要有新版本出来,所有服务器都会试图下载安装。如果你没有预料到会有新版本,且还没有时间执行内部测试的话,这会造成很严重的问题。所以最好还是锁定某一特定版本的程序包比较好:

复制代码
httpd:
pkg.installed:
- name: httpd
- version: 2.2.15

这保证了只有在状态声明中明确更新时,安装包才会被升级。

SaltStack**** 测试模式

另外一个重要特性是提前知道即将发生的变化。这点简单到只要往 highstate 命令添加一个选项就可以:

复制代码
salt ‘*’ state.highstate test=True

当运行于测试模式时,那些已各就各位的状态将显示为绿色,而那些还未执行的状态将显示为黄色。很多用户觉得在实际执行前,能够看到所需执行的变化特别重要。

当然,测试模式也可以用在业务流程引擎中:

复制代码
salt-run state.orchestrate myorchestration test=True

该命令会按 myorchestration.sls 文件中定义的顺序评估 highstate;与此同时,如果命令在测试模式以外运行的话,也会以相同的方式显示将做出的修改。

总结

SaltStack 在配置管理上有明显的重点突破,但我们也不敢打包票。SaltStack 学习和运行起来都很简单,我们的社区也非常有活力和帮助,可以一路帮助那些自己动手的人;对于需要帮助的公司,SaltStack Enterprise 提供了相应的 SaltStack 服务和支持团队。

关于作者

Joseph Hall已经是个老手了,他曾从事过技术支持、QA 工程师、web 程序员、Linux 讲师、系统管理员、主管和云计算工程师。与此同时,他还是个训练有素的厨师和调酒师。他是第二个往 Salt 项目中提交代码的人,目前他是 SaltStack 的一名核心开发人员,致力于领导 Salt 的云开发。

配置管理作为基础使现代基础设施成为可能。在任何运维团队的工具箱中,都需要那些实现配置管理的工具,甚至对于很多开发团队也是如此。尽管所有的工具旨在解决同样的基本问题集,但它们遵循了不同的看法,并表现出不同的特点。问题在于如何选出适合各个组织具体情况的最佳工具。

本文作为这一系列的一部分,旨在介绍当前市场上存在的部分配置工具,以及各个工具背后的原理,和使它们彼此脱颖而出的原因。您可以在这里订阅该系列新文章的提醒。

查看英文原文: SaltStack for Flexible and Scalable Configuration Management

2014 年 7 月 09 日 20:289847
用户头像

发布了 39 篇内容, 共 10.6 次阅读, 收获喜欢 2 次。

关注

评论

发布
暂无评论
发现更多内容

架构师训练营第二周

M.

TarsCpp 组件之 MySQL 操作

TARS基金会

c++ MySQL 数据库 微服务 TARS

架构师训练营第二周作业

lakers

极客大学架构师训练营

有状态软件如何在k8s上快速扩容甚至自动扩容

东风微鸣

Kubernetes DevOps openshift

老板下了死命令,要把日志系统切换到Logback

沉默王二

Java logback 日志系统

如何构建一个通用的垂直爬虫平台?

Kaito

Python 爬虫 代理

「架构师训练营第 1 期」第六周作业

张国荣

美国半导体十年计划中的NO.1,模拟硬件究竟有什么价值?

脑极体

【面经】面试官:讲讲类的加载、链接和初始化?

冰河

架构 JVM 类加载 优化 性能调试

如何搭建一个爬虫代理服务?

Kaito

爬虫 代理

Scrapy 源码剖析(四)Scrapy如何完成抓取任务?

Kaito

Python 爬虫 Scrapy 源码剖析

甲方日常42

句子

工作 随笔杂谈 日常

Java9新特性-上篇

hepingfly

Java Java新特性

Scrapy 源码剖析(三)Scrapy有哪些核心组件?

Kaito

Python 爬虫 Scrapy 源码剖析

元模型驱动(一)构建元模型ーGME入门

KaYa

DDD Kaya MDA GME MDD

队列实现栈的3种方法,全都击败了100%的用户!

王磊

Java 算法和数据结构

元模型驱动(三):构建我们自己的元模型-KAYA

KaYa

DDD Kaya MDA MDD 元建模

架构师训练营第 1 期 -- 第六周学习总结

发酵的死神

极客大学架构师训练营

SpringCloud-初步介绍

hepingfly

微服务 springboot SpringCloud

当AI入职FBI,克格勃直呼内行

脑极体

Scrapy 源码剖析(二)Scrapy是如何运行起来的?

Kaito

Python 爬虫 Scrapy 源码剖析

TarsCpp 组件 之 智能指针详解

TARS基金会

c++ 微服务 智能指针 TARS

架构师训练营第二周总结

lakers

极客大学架构师训练营

【架构师训练营 1 期】第六周作业

诺乐

元模型驱动(二)构建元模型ーGME构建分层模型

KaYa

DDD Kaya MDA GME MDD

CICD实战——服务自动测试

TARS基金会

微服务 单元测试 CI/CD

嵌入式面试之《Linux系统编程100问》

哒宰的自我修养

Linux 线程 网络编程 进程

架构师训练营第 1 期 -- 第六周作业

发酵的死神

极客大学架构师训练营

目标检测学习-比赛路线

Dreamer

Scrapy源码剖析(一)架构概览

Kaito

Python 爬虫 Scrapy 源码剖析

架构师训练营第 1 期 第 6 周作业

李循律

极客大学架构师训练营

InfoQ 极客传媒开发者生态共创计划线上发布会

InfoQ 极客传媒开发者生态共创计划线上发布会

SaltStack: 能够灵活且可扩展的配置管理-InfoQ