我从测试 200 行基础设施代码中学到了什么

我从测试 200 行基础设施代码中学到了什么

方法 交流电 (基础设施即代码)不仅包含存储在存储库中的代码,还包含围绕该代码的人员和流程。 是否可以重用从软件开发到基础设施管理和描述的方法? 在阅读本文时记住这个想法是个好主意。

中文版

这是我的抄本 演出DevOps大会 2019-05-28.

幻灯片和视频

作为 bash 历史的基础设施

我从测试 200 行基础设施代码中学到了什么

假设你来到一个新项目,他们告诉你:“我们有 基础架构即代码”。 事实证明 作为 bash 历史的基础设施 或者例如 作为 bash 历史记录的文档。 这是一个非常真实的情况,例如,Denis Lysenko 在一次演讲中描述了一个类似的案例 如何更换整个基础设施并开始安然入睡,他讲述了他们如何从 bash 历史中获得该项目的连贯基础设施。

带着某种愿望,我们可以说 作为 bash 历史的基础设施 这就像代码:

  1. 再现性:您可以获取 bash 历史记录,从那里运行命令,顺便说一下,您可能会获得工作配置作为输出。
  2. 版本控制:您知道谁进来以及他们做了什么,这并不是事实,这不会引导您在出口处找到工作配置。
  3. 故事:谁做了什么的故事。 只是如果您失去服务器,您将无法使用它。

怎么办呢?

基础架构即代码

我从测试 200 行基础设施代码中学到了什么

甚至像这样奇怪的案例 作为 bash 历史的基础设施 你可以拉着它的耳朵 基础架构即代码,但是当我们想做一些比旧的 LAMP 服务器更复杂的事情时,我们会得出这样的结论:这段代码需要以某种方式修改、改变、改进。 接下来我们要考虑之间的相似之处 基础架构即代码 和软件开发。

干燥

我从测试 200 行基础设施代码中学到了什么

在一个存储系统开发项目中,有一个子任务 定期配置 SDS:我们正在发布一个新版本 - 需要推出它以进行进一步测试。 任务非常简单:

  • 通过ssh登录这里并执行命令。
  • 将文件复制到那里。
  • 更正此处的配置。
  • 在那里启动服务
  • ...
  • 利润!

对于所描述的逻辑,bash 是绰绰有余的,特别是在项目的早期阶段,刚刚开始的时候。 这 你用 bash 也不错,但随着时间的推移,有人请求部署类似但略有不同的东西。 第一个想到的就是复制粘贴。 现在我们已经有了两个非常相似的脚本,它们几乎做同样的事情。 随着时间的推移,脚本的数量不断增加,我们面临这样一个事实:部署安装有一定的业务逻辑,需要在不同的脚本之间同步,这是相当复杂的。

我从测试 200 行基础设施代码中学到了什么

原来还有DRY(Do not Repeat Yourself)这样的做法。 这个想法是重用现有的代码。 这听起来很简单,但我们并没有立即想到这一点。 在我们的例子中,这是一个平庸的想法:将配置与脚本分开。 那些。 如何单独部署安装、单独配置的业务逻辑。

适用于 CFM 的 SOLID

我从测试 200 行基础设施代码中学到了什么

随着时间的推移,该项目不断发展并 自然延续 Ansible 的出现。 它出现的主要原因是团队中有专业知识,并且 bash 不是为复杂逻辑而设计的。 Ansible 也开始包含复杂的逻辑。 为了防止复杂的逻辑变成混乱,软件开发中组织代码有一些原则 坚硬的 另外,例如,格里戈里·彼得罗夫(Grigory Petrov)在《为什么IT专家需要个人品牌》的报告中提出了一个问题,即一个人的设计方式是为了让他更容易与一些社会实体合作,在软件开发中,这些是对象。 如果我们将这两个想法结合起来并继续发展它们,我们会发现我们还可以使用 坚硬的 以便将来更容易维护和修改此逻辑。

单一责任原则

我从测试 200 行基础设施代码中学到了什么

每个类只执行一项任务。

无需混合代码并制作单一的神圣意大利面怪物。 基础设施应该由简单的砖块组成。 事实证明,如果您将 Ansible 剧本分成小部分,阅读 Ansible 角色,那么它们会更容易维护。

开闭原则

我从测试 200 行基础设施代码中学到了什么

开闭原则。

  • 开放扩展:意味着可以通过创建新的实体类型来扩展实体的行为。
  • 禁止更改:由于扩展了实体的行为,因此不应对使用这些实体的代码进行任何更改。

最初,我们在虚拟机上部署了测试基础设施,但由于部署的业务逻辑与实现是分离的,所以我们添加了部署到裸机,没有任何问题。

里氏替换原则

我从测试 200 行基础设施代码中学到了什么

芭芭拉·利斯科夫的替代原则。 程序中的对象必须可以用其子类型的实例替换,而不改变程序的正确执行

如果你从更广泛的角度来看,它并不是任何特定项目的功能都可以在那里应用 坚硬的,一般都是关于CFM的,比如在另一个项目上需要在各种Java、应用服务器、数据库、OS等之上部署一个盒装的Java应用程序。 使用这个例子,我将考虑进一步的原则 坚硬的

在我们的例子中,基础设施团队内部达成了一项协议:如果我们安装了 imbjava 或 oraclejava 角色,那么我们就有了一个 java 二进制可执行文件。 这是必要的,因为上游角色取决于此行为;他们期望 java.lang. 同时,这允许我们将一个 java 实现/版本替换为另一个 java 实现/版本,而无需更改应用程序部署逻辑。

这里的问题在于,在 Ansible 中不可能实现这一点,因此团队内部出现了一些协议。

接口隔离原则

我从测试 200 行基础设施代码中学到了什么

接口分离原则:“许多特定于客户端的接口比一个通用接口更好。

最初,我们尝试将应用程序部署的所有可变性放入一个 Ansible playbook 中,但很难支持,并且当我们指定了外部接口(客户端期望端口 443)时,可以从单个基础设施中组装基础设施具体实现的砖块。

依赖倒置原则

我从测试 200 行基础设施代码中学到了什么

依赖倒置的原理。 较高级别的模块不应依赖于较低级别的模块。 两种类型的模块都必须依赖于抽象。 抽象不应该依赖于细节。 细节必须依赖于抽象。

这里的示例将基于反模式。

  1. 其中一位客户拥有私有云。
  2. 我们在云中订购了虚拟机。
  3. 但由于云的性质,应用程序部署与虚拟机所在的虚拟机管理程序相关联。

那些。 高级应用程序部署逻辑依赖于较低级别的虚拟机管理程序,这意味着重用此逻辑时会出现问题。 不要那样做

互动效果

我从测试 200 行基础设施代码中学到了什么

基础设施即代码不仅涉及代码,还涉及代码与人之间的关系,涉及基础设施开发人员之间的交互。

总线系数

我从测试 200 行基础设施代码中学到了什么

假设您的项目中有 Vasya。 Vasya 了解您的基础设施的一切,如果 Vasya 突然消失会发生什么? 这是一个非常真实的情况,因为他可能会被公共汽车撞到。 有时候这种情况会发生。 如果发生这种情况,并且关于代码、其结构、工作原理、外观和密码的知识没有在团队中分布,那么您可能会遇到许多不愉快的情况。 为了最大限度地减少这些风险并在团队内分配知识,您可以使用各种方法

配对消除

我从测试 200 行基础设施代码中学到了什么

这不像 作为一个笑话,管理员喝了啤酒,更改了密码,以及类似的结对编程。 那些。 两名工程师坐在一台计算机、一个键盘前,开始一起设置基础设施:设置服务器、编写 Ansible 角色等。 听起来不错,但对我们来说不起作用。 但这种做法的特殊情况是有效的。 一名新员工到来,他的导师与他一起承担实际任务,工作并传授知识。

另一个特殊情况是事件呼叫。 在出现问题时,一群值班人员和相关人员聚集在一起,任命一名领导者,他分享他的屏幕并表达思路。 其他参与者跟随领导者的想法,从控制台监视技巧,检查他们没有错过日志中的一行,并了解有关系统的新知识。 这种方法通常很有效。

代码审查

我从测试 200 行基础设施代码中学到了什么

主观上,使用代码审查来传播有关基础设施及其工作原理的知识更有效:

  • 基础设施由存储库中的代码描述。
  • 更改发生在单独的分支中。
  • 在合并请求期间,您可以看到基础架构中的更改增量。

这里的亮点是审稿人是根据时间表一一选出的,即您有可能会进入一个新的基础设施。

代码风格

我从测试 200 行基础设施代码中学到了什么

随着时间的推移,评审期间开始出现争吵,因为…… 审稿人有自己的风格,审稿人的轮换以不同的风格堆叠他们:2个空格或4个,camelCase或snake_case。 不可能立即实施这一点。

  • 第一个想法是推荐使用linter,毕竟大家都是工程师,大家都很聪明。 但不同的编辑器、操作系统,不太方便
  • 这演变成一个机器人,它为每个有问题的提交写入 slack 并附加 linter 输出。 但在大多数情况下,还有更重要的事情要做,而代码仍然没有修复。

绿色建造大师

我从测试 200 行基础设施代码中学到了什么

随着时间的流逝,我们得出的结论是,未通过某些测试的提交不能被允许进入 master。 瞧! 我们发明了Green Build Master,它在软件开发中已经实践了很长时间:

  • 开发工作正在一个单独的分支中进行。
  • 测试正在该线程上运行。
  • 如果测试失败,代码将不会进入母版。

做出这个决定是非常痛苦的,因为…… 引起了很多争议,但这是值得的,因为...... 评论开始收到风格上没有差异的合并请求,随着时间的推移,问题区域的数量开始减少。

IaC测试

我从测试 200 行基础设施代码中学到了什么

除了样式检查之外,您还可以使用其他方法,例如,检查您的基础设施是否可以实际部署。 或者检查基础设施的变化不会导致金钱损失。 为什么需要这个? 这个问题既复杂又哲学,最好用一个故事来回答:不知何故,Powershell 上有一个自动缩放器,它没有检查边界条件 => 创建了比必要的更多的虚拟机 => 客户花费了比计划更多的钱。 这不是很令人愉快,但是很可能在早期阶段发现这个错误。

有人可能会问,为什么要让复杂的基础设施变得更加复杂? 就像代码测试一样,基础设施的测试不是为了简化,而是为了了解基础设施应该如何工作。

IaC 测试金字塔

我从测试 200 行基础设施代码中学到了什么

IaC 测试:静态分析

如果你一次性部署整个基础设施并检查它是否正常工作,你可能会发现这需要花费很多时间并且需要很多时间。 所以,基础一定是见效快的东西,有很多,而且涵盖了很多原始的地方。

Bash 很棘手

让我们看一个简单的例子。 选择当前目录中的所有文件并复制到另一个位置。 我首先想到的是:

for i in * ; do 
    cp $i /some/path/$i.bak
done

如果文件名中有空格怎么办? 好吧,我们很聪明,我们知道如何使用引号:

for i in * ; do cp "$i" "/some/path/$i.bak" ; done

做得好? 不! 如果目录中没有任何内容怎么办,即通配符不起作用。

find . -type f -exec mv -v {} dst/{}.bak ;

现在做得好了吗? 不...忘记文件名中可以​​包含什么 n.

touch x
mv x  "$(printf "foonbar")"
find . -type f -print0 | xargs -0 mv -t /path/to/target-dir

静态分析工具

当我们忘记引号时,可能会发现上一步的问题,为此,自然界中有很多补救措施 壳牌检查,一般来说有很多,并且很可能您可以在 IDE 下找到适合您的堆栈的 linter。

语言
工具

打坏
壳牌检查

红宝石
防暴警察

蟒蛇
pylint的

ansible
Ansible Lint

IaC 测试:单元测试

我从测试 200 行基础设施代码中学到了什么

正如我们从前面的例子中看到的,linter 并不是万能的,不能指出所有的问题区域。 此外,通过类比软件开发中的测试,我们可以回忆起单元测试。 立即想到的是 舒尼特, unit, 规格, 测试。 但是如何处理 ansible、chef、saltstack 和其他类似的东西呢?

一开始我们谈到 坚硬的 我们的基础设施应该由小砖块组成。 他们的时代已经到来。

  1. 基础设施被分为小块,例如 Ansible 角色。
  2. 部署某种环境,无论是 docker 还是虚拟机。
  3. 我们将 Ansible 角色应用到这个测试环境中。
  4. 我们检查一切是否按我们的预期运行(我们运行测试)。
  5. 我们决定好还是不好。

IaC 测试:单元测试工具

问题,CFM 测试是什么? 您可以简单地运行脚本,也可以使用现成的解决方案:

CFM
工具

Ansible
测试弗拉

厨师
检验

厨师
服务器规范

盐堆
戈斯

testinfra 示例,检查用户 test1, test2 存在并且在一个组中 sshusers:

def test_default_users(host):
    users = ['test1', 'test2' ]
    for login in users:
        assert host.user(login).exists
        assert 'sshusers' in host.user(login).groups

选择什么? 问题复杂且模糊,下面是 2018-2019 年 github 上项目变化的示例:

我从测试 200 行基础设施代码中学到了什么

IaC 测试框架

问题出现了:如何将它们组合在一起并启动它? 能 自己做吧 如果有足够数量的工程师。 或者您可以采用现成的解决方案,尽管数量不是很多:

CFM
工具

Ansible
分子

厨师
测试厨房

Terraform
地测

2018-2019 年 github 上项目变更示例:

我从测试 200 行基础设施代码中学到了什么

分子对比测试厨房

我从测试 200 行基础设施代码中学到了什么

最初我们 尝试使用测试厨房:

  1. 并行创建虚拟机。
  2. 应用 Ansible 角色。
  3. 运行检查。

对于 25-35 个角色,工作时间为 40-70 分钟,时间很长。

我从测试 200 行基础设施代码中学到了什么

下一步是过渡到 jenkins/docker/ansible/molecule。 从本质上讲,一切都是一样的

  1. Lint 剧本。
  2. 排列角色。
  3. 启动容器
  4. 应用 Ansible 角色。
  5. 运行测试基础设施。
  6. 检查幂等性。

我从测试 200 行基础设施代码中学到了什么

40 个角色的检查和十几个角色的测试开始需要大约 15 分钟。

我从测试 200 行基础设施代码中学到了什么

选择什么取决于很多因素,例如使用的堆栈、团队的专业知识等。 这里每个人自己决定如何结束单元测试问题

IaC 测试:集成测试

我从测试 200 行基础设施代码中学到了什么

基础设施测试金字塔的下一步将是集成测试。 它们类似于单元测试:

  1. 基础设施被分为小块,例如 Ansible 角色。
  2. 部署某种环境,无论是 docker 还是虚拟机。
  3. 对于此测试环境适用 许多 Ansible 角色。
  4. 我们检查一切是否按我们的预期运行(我们运行测试)。
  5. 我们决定好还是不好。

粗略地说,我们不会像在单元测试中那样检查系统单个元素的性能,而是检查整个服务器的配置方式。

IaC 测试:端到端测试

我从测试 200 行基础设施代码中学到了什么

在金字塔的顶端,我们受到端到端测试的欢迎。 那些。 我们不会检查单独的服务器、单独的脚本或基础设施的单独块的性能。 我们检查许多服务器是否连接在一起,我们的基础设施是否按我们的预期运行。 不幸的是,我从未见过现成的盒装解决方案,可能是因为...... 基础设施通常是独特的,难以模板化和创建测试框架。 结果,每个人都创建了自己的解决方案。 有需求,但没有答案。 因此,我会告诉你什么是为了促使其他人做出正确的想法,或者是为了让我觉得一切都是很久以前就在我们之前发明的。

我从测试 200 行基础设施代码中学到了什么

一个有着丰富历史的项目。 它用于大型组织,可能你们每个人都间接接触过它。 该应用程序支持许多数据库、集成等。 了解基础设施可能是什么样子的是大量的 docker-compose 文件,了解在哪个环境中运行哪些测试是 Jenkins。

我从测试 200 行基础设施代码中学到了什么

这个方案运行了相当长的一段时间,直到在框架内 研究 我们还没有尝试将其转移到 Openshift。 容器保持不变,但启动环境已更改(再次问候 DRY)。

我从测试 200 行基础设施代码中学到了什么

研究想法更进一步,在 openshift 中他们发现了 APB(Ansible Playbook Bundle)这样的东西,它允许您将如何将基础设施部署到容器中的知识打包。 那些。 关于如何部署基础设施有一个可重复、可测试的知识点。

我从测试 200 行基础设施代码中学到了什么

所有这一切听起来都不错,直到我们遇到异构基础设施:我们需要 Windows 来进行测试。 因此,关于什么、在哪里、如何部署和测试的知识都在 jenkins 中。

结论

我从测试 200 行基础设施代码中学到了什么

基础设施即代码

  • 代码在存储库中。
  • 人际交往。
  • 基础设施测试。

链接

来源: habr.com

添加评论