构建一个自给自足的Docker集群

自给自足的系统是一种能够复原和适应的系统。 修复意味着群集将始终处于设计状态。 例如,如果服务的副本出现故障,则系统需要再次将其恢复。 另一方面,适应是关于期望状态的修改,以便系统可以处理变化的条件。 一个简单的例子就是增加流量。 发生这种情况时,需要扩大服务规模。 当康复和适应自动进行时,我们将获得自我修复和自我适应。 它们共同构成了一个自给自足的系统,无需人工干预即可运行。

自给自足的系统看起来如何? 它的主要部分是什么? 谁是演员?

我们将讨论的范围限制在服务上,而忽略硬件同样重要的事实。 考虑到这样的局限性,我们将描绘一个从服务的角度描述(主要是)自治系统的高级视图。 我们将从细节中提升自己,并对该系统有一个全面的了解。

如果您是万事通类型的人并且想一次看到所有内容,则系统如图10-1所示。

具有自我修复和自适应服务的系统

这样的图可能太多了,无法立即处理。 把它扔到你的脸上可能会让你认为同情不是我的长处之一。 如果是这样,您并不孤单。 即使没有任何图表,我妻子也有同样的印象。 这次,我将尽力改变您的意见,并从头开始。

我们可以将系统分为两个主要领域: 人与机器。 将它们视为Matrix 。 如果您还没有看过电影,请立即停止阅读这本书,制作一些爆米花,然后观看。

在Matrix中,机器已经超越了世界。 除了少数人意识到发生了什么事之外,人类没有做太多事情。 大多数人生活在一个反映人类历史过去事件的梦中。 他们实际上是现在,但是他们的思想是过去。 对于现代集群也可以观察到相同的情况。 大多数人仍然像1999年一样操作它们。几乎所有的操作都是手动的,过程繁琐,并且由于残酷的力量和浪费的能源,系统得以幸存。 有人认为今年是2017年(至少在撰写本文时),精心设计的系统是可以自主完成大部分工作的系统。 几乎所有东西都由机器而不是人工操作。

这并不意味着我们(人类)没有地方。 有,但是与创造性和非重复性任务更多相关。 因此,如果我们仅关注集群操作,则人的领域正在缩小,并被机器领域接管。

该系统可以分为不同的角色。 正如您将看到的,工具或人员可以非常专业并且仅执行单个角色,或者可以负责操作的多个方面。

开发人员在系统中的角色

人为领域由手动操作的过程和工具组成。 我们正在努力从该领域转移所有可重复的行动。 这并不意味着目标是使该域消失。 恰恰相反。 通过将重复的任务推开,我们将自己从平凡的任务中解放出来,并增加了与那些带来真正价值的任务所花费的时间。 我们执行可委派给机器的任务的次数越少,我们可以将更多的时间花在需要创造力的任务上。 这种哲学与这部戏的长处和短处或每个演员都相符。 机器擅长处理数字。 他们知道如何快速执行预定义的操作。 他们在这方面比我们更好,更可靠。 与机器不同,我们有能力进行批判性思考。 我们可以发挥创造力。 我们可以对那些机器进行编程。 我们可以告诉他们做什么和何时做。

我指定一名开发人员为人类领域的主要演员。 我故意避免使用单词编码器。 开发人员是每个从事软件开发项目的人。 您是编码员,测试员,操作大师还是Scrum管理员都无关紧要。 我将所有人都标记为开发人员。 工作的结果是将某些内容推送到代码存储库。 直到到达那里,好像它不存在一样。 它是放在笔记本电脑上,在笔记本电脑上,在桌子上还是在信鸽的小纸上都没关系。 从系统的角度来看,它直到进入代码存储库才存在。 该存储库希望是Git,但是出于争论的考虑,它可以在任何其他可以存储和版本化内容的地方。

该代码存储库也是人类领域的一部分。 即使它是一个软件,它也属于我们。 我们操作它。 我们正在推动提交,提取代码,合并,有时是出于过多的合并冲突而产生的绝望。 这并不意味着它没有自动化的操作,也不意味着机器域的某些部分在没有任何人工干预的情况下就无法操作它。 尽管如此,只要某些事情大部分是动手的,我们将其视为人类领域的一部分。 代码存储库绝对符合需要大量人工干预的系统范围。

开发人员将代码提交到代码存储库

让我们看看将提交推送到代码存储库时会发生什么。

系统中的持续部署角色

连续部署过程是完全自动化的。 没有例外。 如果您的管道不是自动化的,则它不是连续部署。 您可能需要手动操作才能部署到生产环境。 如果该操作包括按下一个以粗体显示deploy的按钮,则您的过程是连续交付。 我可以接受。 使用这种按钮可能是出于商业原因。 自动化水平仍然与连续部署相同。 您只是决策者。 如果还有其他手动操作,则您是在进行连续集成,或者更有可能是在名称中不包含连续词。

无论是连续部署还是交付,该过程都是完全自动化的。 仅当您的系统是组织选择不接触的旧系统(通常是Cobol应用程序)时,才可以免除手动过程的麻烦。 它只是坐在服务器顶部并执行某些操作。 我非常喜欢“没人知道它在做什么,不要碰它”这类规则。 这是在保持安全距离的同时表示最大尊重的一种方式。 但是,我认为这不是您的情况。 您想触摸它。 欲望在你内心燃烧。 如果不是这种情况,而您却不幸地无法使用其中一种与众不同的系统,那么您读的书是错误的,我很惊讶您没有意识到自己。

一旦代码存储库收到提交或请求请求,它就会触发Web挂钩,该Web挂钩将请求发送到CD工具,该工具启动连续部署过程。 在我们的案例中,该工具是Jenkins 。 该请求将启动管道的构建,该管道将执行各种连续的部署任务。 它签出代码并运行单元测试。 它生成一个映像并将其推送到注册表。 它运行功能,集成,性能以及其他需要实时服务的测试。 流程的最后(不包括生产测试)是对调度程序的请求,以在生产集群中部署或更新服务。 对于调度程序,我们的选择是Docker Swarm。

通过Jenkins部署服务

与连续部署并行,另一组进程正在运行,并试图保持系统配置为最新。

系统中的服务配置角色

每当集群的任何方面发生更改时,都需要重新配置系统的各个部分。 代理可能需要更新其配置,指标收集器可能需要新的目标,日志解析器可能需要更新其规则。

无论系统的哪些部分需要更改,这些更改都需要自动应用。 几乎没有人对此表示怀疑。 更大的问题是在哪里可以找到应纳入系统的信息。 最佳位置是服务本身。 由于几乎所有调度程序都使用Docker,因此有关服务信息的最合乎逻辑的地方就是其内部的标签形式。 将信息设置在其他任何地方都将阻止我们获得单一的事实来源,并使自动发现变得很难完成。

在其内部拥有有关服务的信息并不意味着相同的信息不应驻留在集群中的其他位置。 这应该。 但是,服务是主信息必须存在的地方,并且从那里开始,它应传播到其他服务。 Docker使这非常容易。 它已经有一个API,任何人都可以插入并发现有关任何服务的任何信息。

发现服务信息并将其传播到系统其余部分的工具的选择是Docker Flow Swarm Listener(DFSL) 。 您可以选择其他方式或构建自己的解决方案。 这种工具(尤其是Docker Flow Swarm Listener)的目标是侦听Docker Swarm事件。 如果服务包含一组特定的标签,则侦听器将在部署或更新服务后立即获取信息,并将其传递给所有相关方。 在这种情况下,这就是Docker Flow Proxy(DFP) (内部带有HAProxy)和Docker Flow Monitor(DFM) (内部带有Prometheus)。 结果,两者都具有始终最新的配置。 代理具有所有公共服务的路由,而Prometheus具有有关出口商,警报, Alertmanager的地址以及许多其他信息的信息。

通过Docker Flow Swarm Listener重新配置系统

在进行部署和重新配置时,用户必须能够访问我们的服务而不会停机。

系统中的代理角色

每个群集都需要一个代理,该代理将接收来自单个端口的请求并将其转发到目标服务。 唯一的例外是当我们只有一项面向公众的服务时。 在这种情况下,不仅我们是否需要代理,而且根本是否需要集群都值得怀疑。

当请求到达代理服务器时,将对其进行评估,并根据其路径,域或其他一些报头将其转发给服务之一。

Docker淘汰了很多代理。 没有理由进行负载平衡。 Docker的Overlay网络为我们服务。 无需维护托管服务的节点的IP。 服务发现为我们做到了。 标头和转发的评估几乎是代理应做的所有事情。

由于Docker Swarm会在服务的某个方面发生更改时利用滚动更新,因此持续部署(CD)流程不应产生任何停机时间。 为了使该说法正确,需要满足一些要求。 其中,服务需要运行至少两个副本,最好运行多个副本。 否则,使用单个副本对服务进行的任何更新将不可避免地造成停机时间。 是一分钟,一秒还是一毫秒都没有关系。

停机时间并不总是灾难性的。 这完全取决于服务的类型。 如果Prometheus更新为较新的版本,则由于无法扩展,将导致停机。 但是,除非您算几个运营商,否则它不是面向公众的服务。 几秒钟的停机时间没什么大不了的。

面向公众的服务(如在线零售商店,成千上万甚至数百万的用户正在购物)如果失败,很快就会失去良好的声誉。 我们像消费者一样宠坏了,一个小故障就能改变我们的想法并使我们进入竞争。 如果这种“小故障”一遍又一遍地重复,几乎可以保证业务损失。 连续部署具有许多优势,但是由于执行相当频繁,因此还会放大潜在的部署问题,其中停机时间就是其中之一。 每天造成多次停机时间确实是不可接受的。

好消息是,只要代理始终是最新的,滚动更新与多个副本的结合将使我们避免停机。

滚动更新与可自动重新配置自身的代理的组合导致用户可以随时将请求发送到服务而不受连续部署,故障以及群集状态的其他更改影响的情况。

当用户将请求发送到域时,该请求通过任何运行正常的节点进入集群,并由Docker的Ingress网络接管。 网络依次检测到请求使用了代理发布的端口并将其转发。 另一方面,代理评估请求的路径,域或其他方面,并将其转发到目标服务。

我们正在使用Docker Flow Proxy(DFP) ,它在HAProxy之上添加了所需的动态级别。

向目标服务的请求流

我们将讨论的下一个角色是关于收集指标。

指标在系统中的作用

任何集群的关键部分,尤其是那些旨在自我适应的集群,都是数据。 几乎没有人会质疑拥有过去和现在的指标的需求。 没有它们,发生问题时,我们将像无头鸡一样奔跑。 中心问题不是是否需要它们,而是我们如何处理它们。 传统上,操作员会花费大量时间观察仪表板。 那远没有效率。 改为观看Netflix。 至少,这更有趣。 系统应使用指标。 系统生成它们,收集它们,并且当它们达到某些阈值时,它应该决定要执行哪些操作。 只有这样,系统才能自适应。 只有在没有人为干预的情况下行动,它才能自给自足。

实现自适应的系统需要收集数据,存储数据并对其进行操作。 我将跳过有关推送和抓取数据之间的优缺点的讨论。 由于我们选择将Prometheus用作存储和评估数据的地方,以及将其用作生成和触发警报的服务,因此选择是擦除数据。 该数据以出口商的形式提供。 它们可以是通用的(例如,Node Exporter,cAdvisor等),也可以是特定于服务的。 在后一种情况下,服务必须公开Prometheus期望的简单格式的指标。

与我们前面描述的流程无关,出口商正在公开不同类型的指标。 Prometheus会定期对其进行刮擦并将其存储在其数据库中。 与抓取并行,Prometheus不断评估警报设置的阈值,如果达到阈值,则将其传播到Alertmanager 。 在大多数情况下,由于条件变化(例如,系统负载增加)而达到了这些限制。

数据收集和警报

警报接收者才是与众不同的原因。

系统中的警报角色

根据警报接收者的不同,警报分为两大类。 它可以转发给系统或人类。 当警报符合应发送到系统的类型时,通常会将请求转发到能够评估情况并执行适合系统的任务的服务。 在我们的例子中,该服务是Jenkins ,它执行预定义的作业之一。

詹金斯执行的最常见的一组任务是扩展(或缩减)服务。 但是,在尝试扩展之前,它需要发现当前副本数并将其与我们通过服务标签设置的上限和下限进行比较。 如果缩放将导致超出这些边界的许多副本,它将向Slack发送通知,以便人们可以决定应该采取哪些正确的措施来解决该问题。 另一方面,当扩展使副本数保持在限制范围内时,Jenkins向Swarm管理器中的一个发送请求,该请求又增加(或减少)服务的副本数。 我们称流程为自适应,是因为系统无需人工干预即可适应变化的条件。

通知系统自适应

即使目标是使系统完全自治,但几乎可以肯定在某些情况下需要人工干预。 从本质上讲,这些案例是无法预测的。 当发生某些意外情况时,让系统对其进行修复。 另一方面,在发生意外情况时打电话给人类。 在这种情况下,Alertmanager将消息发送到人员域。 在我们的情况下,这是一条Slack消息,但也可以是任何其他通信服务。

当您开始设计自我修复系统时,大多数警报将属于“意外”类别。 您无法预测系统可能发生的所有情况。 您可以做的是确保所有这些情况仅在一次意外情况下发生。 收到警报时,您的第一组任务应该是手动调整系统。 同样重要的第二组操作是改进Alertmanager和Jenkins中的规则,以便下次发生相同事件时,系统可以自动处理它。

发生意外情况时通知人类

建立一个自适应系统很困难,而且它永远不会真正结束。 它将需要不断的改进。 自我修复怎么样? 这同样难以实现吗?

系统中的调度程序角色

与自我适应不同,自我修复相对容易实现。 只要有可用资源,调度程序就会确保指定数量的副本始终处于运行状态。 在我们的例子中,该调度程序是Docker Swarm

副本可能失败,可以被杀死,也可以驻留在不正常的节点中。 这并不重要,因为Swarm会确保在需要时重新安排它们的时间,并且(几乎)始终在运行。 如果我们所有的服务都是可扩展的,并且我们至少在运行每个服务的几个副本,则永远不会出现停机。 Docker内部的自我修复过程将确保这一点,而我们自己的自我适应过程旨在提供高可用性。 两者的结合使系统几乎完全自治且自给自足。

当服务不可扩展时,问题开始堆积。 如果我们不能有一个服务的多个副本,那么Swarm无法保证不会出现停机。 如果副本失败,它将被重新安排。 但是,如果该副本是唯一的副本,则从失败到启动并运行之间的时间间隔将导致停机。 与我们类似的情况。 我们生病了,卧床不起,过了一会儿,返回工作岗位。 问题是,如果我们是公司中唯一的员工,而在外出时没有人接管业务。 服务也是如此。 对于希望避免停机的任何服务,最少要有两个副本。

Docker Swarm确保无停机

不幸的是,您的服务在设计时可能没有考虑可伸缩性。 即使是这样,也有可能您正在使用的某些第三方服务没有。 可伸缩性是一项重要的设计决策,这是我们在选择要使用的下一个工具时应评估的基本要求。 我们必须对必须永不停机的服务和在几秒钟内不可用时不会造成系统风险的服务加以区分。 做出区分后,您将知道哪些必须可扩展。 可伸缩性是无停机服务的要求。

系统中的群集角色

最后,我们所做的一切都在一个或多个集群中。 不再有单独的服务器。 我们不决定去哪里。 调度程序。 从我们(人类)的角度来看,最小的实体是群集,它是诸如内存和CPU之类的资源的集合。

一切都是集群

一切都是集群

DevOps 2.2工具包:自我修复Docker集群

您刚刚阅读的文章是我们在The DevOps 2.2 Toolkit:Self-Healing Docker Clusters中取得的进展的摘要。 您可以在本书中找到构建系统的动手练习。

如果您喜欢本文,则可能对The DevOps 2.2 Toolkit:Self-Healing Docker Clusters一书感兴趣。 该书超越了Docker和调度程序,并尝试探索构建自适应和自我修复的Docker集群的方法。 如果您是Docker用户,并且想探索用于创建集群和管理服务的高级技术,那么本书可能正是您所需要的。

该书仍在开发中。 如果您选择成为早期读者并影响本书的发展方向,请从LeanPub获得一份副本。 每当添加新章节时,您都会收到通知。

试试看,让我知道你的想法

翻译自: https://www.javacodegeeks.com/2017/07/building-self-sufficient-docker-cluster.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值