今天,我们将讨论DevOps,或更确切地说,主要是关于Ops。 他们说很少有人对他们的操作自动化水平感到满意。 但是这种情况似乎是可以解决的。 在本文中,Nikolai Ryzhikov将谈论他在扩展Kubernetes方面的经验。

该材料是根据Nikolai在2017年DevOops秋季会议上的演讲准备的。该报告的剪裁-视频和文字抄本。
目前,Nikolai Ryzhikov正在Health-IT部门工作,以创建医疗信息系统。 圣彼得堡功能程序员FPROG社区的成员。 在线Clojure社区的活跃成员,HL7 FHIR医学信息交换标准的成员。 已经编程了15年。
DevOps有什么优势? 十年来,我们的DevOps公式非常简单:开发人员负责运营,部署开发人员,维护开发人员。 通过这种看起来有点苛刻的安排,无论如何您都将成为DevOps。 如果您想快速而痛苦地实施DevOps,请让开发人员负责您的生产。 如果这些家伙很聪明,那么他们将开始走出去并了解一切。

我们的故事:很久以前,当没有厨师和自动化时,我们已经部署了自动Capistrano。 然后他们开始让他觉得无聊,这样他就会变得时尚。 但随后厨师出现了。 我们切换到它,然后转到云:我们对数据中心感到厌倦。 然后Ansible出现了,Docker出现了。 之后,我们与Camel上手写的Condo Docker主管一起移至Terraform。 现在,我们正在转向Kubernetes。

运营最糟糕的事情是什么? 很少有人对他们的操作自动化水平感到满意。 我确认,这很可怕:我们花费了大量资源和精力为自己收集了所有这些堆栈,结果令人不满意。
感觉到随着Kubernetes的到来,某些事情可能会改变。 我致力于精益生产,从他的角度来看,运营通常无济于事。 理想的操作是项目中不存在操作或操作最少。 开发人员生产产品时会创造价值。 准备就绪后,交付不会增加价值。 但是您需要降低成本。

对我而言,理想永远是heroku。 我们将其用于简单的应用程序,开发人员可以在其中部署服务,只需说git push和配置heroku。 需要一分钟

如何成为 您可以购买NoOps-也可以购买heroku。 而且我建议您购买,否则有机会花更多的钱来发展常规业务。
有Deis家伙,他们正在尝试在Kubernetes上做类似heroku的事情。 有云铸造厂,它也提供了一个工作平台。

但是,如果您打扰更复杂或更大型的东西,则可以自己完成。 现在,与Docker和Kubernetes一起,这已成为一项任务,可以在合理的时间内以合理的成本完成。 过去太残酷了。

关于Docker和Kubernetes的一些知识
操作的问题之一是可重复性。 码头工人带来的好处是两个阶段。 我们有一个构建阶段。
泊坞窗中令人高兴的第二点是用于启动任意服务的通用接口。 有人组装了Docker,在其中放入了东西,然后进行了操作,足以说明Docker可以运行和启动。

什么是Kubernetes? 因此,我们制作了Docker,我们需要启动,集成,配置并将其与其他人连接。 Kubernetes允许您执行此操作。 他介绍了一系列抽象,称为“资源”。 我们将快速浏览它们,甚至尝试进行创建。
抽象化
第一个抽象是POD或一组容器。 正确完成的工作,实际上是一
组容器,而不是一组。 集可以在它们之间通过localhost相互查看的卷中翻阅。 这使您可以使用诸如sidecar之类的模式(这是在我们启动主容器时,附近有辅助容器对此有所帮助)。
例如,大使方法。 这是当您不希望容器思考某些服务的位置时。 您在其旁边放置一个容器,以了解这些服务的位置。 并且它们可用于localhost上的主容器。 因此,环境开始看起来像您在本地工作。

让我们提出POD并查看其描述。 您可以在本地开发minikube。 它占用了大量CPU,但允许您在virtualbox上引发一个小型Kubernetes集群并使用它。
让我们部署POD。 我说过Kubernetes适用并淹没了POD。 我可以看到有哪些POD:我看到已部署一个POD。 这意味着Kubernetes已经启动了这些容器。
我什至可以进入这个容器。
从这个角度来看,Kubernetes是为人而生的。 确实,我们在操作中不断进行的工作(例如,使用kubectl实用程序在Kubernetes绑定中)可以轻松完成。
但是POD是致命的。 它从Docker运行开始:如果有人停止它,没有人会举起它。 在这种抽象之上,Kubernetes开始构建以下内容-例如,副本集。 这样的主管可以监视POD,监视其数量,如果POD掉落,则可以提起它们。 这是Kubernetes中重要的自我修复概念,可让您在晚上安然入睡。
复制集上方是部署的抽象概念,也是一种资源,可用于进行零时间部署。 例如,一个副本集有效。 当我们确实在部署内部部署并更改容器的版本时,例如我们的容器版本,就会出现另一个副本集。 我们等到这些容器启动之后,通过它们的运行状况检查,然后我们快速切换到新的副本集。 也是经典和好的做法。

让我们选择一个简单的服务。 例如,我们有一个部署。 在内部,他描述了将要拾取的POD的模式。 我们可以应用此部署,看看有什么。 Kubernetes的很酷的功能-一切都在数据库中,我们可以观察系统中发生了什么。
在这里,我们看到一个部署。 如果我们尝试查看POD,就会发现某些POD已经上升。 我们可以删除此POD。 POD会怎样? 一架被摧毁,第二架立即升起。 此副本集控制器未找到所需的POD,并启动了另一个POD。
此外,如果这是某种Web服务,或者我们的服务内部必须进行通信,则我们需要服务发现。 您必须为服务指定名称和入口点。 Kubernetes为此提供了一种称为服务的资源。 他可以处理负载平衡并负责服务发现。

让我们看一个简单的服务。 我们通过标签将其与部署和POD连接起来:这样的动态链接。 Kubernetes中一个非常重要的概念:系统是动态的。 所有这些以什么顺序创建都没有关系。 服务将尝试找到带有此类标签的POD,并开始其负载平衡。
应用服务,看看我们有什么服务。 我们进入已提出的测试POD,并执行nslookup。 Kubernetes为我们提供了一个DNS-ku,服务可以通过它相互查看和发现。
服务是一个接口。 有几种不同的实现方式,因为负载平衡和服务的任务非常复杂:一种方式是使用普通数据库,另一种方式是使用加载的数据库,而一些简单的数据库则变得非常简单。 这也是Kubernetes中的一个重要概念:有些东西可以称为接口,而不是实现。 它们不是严格固定的,并且例如云提供商提供不同的实现。 也就是说,例如,存在一个资源持久卷,该资源持久卷已通过其常规方式在每个特定的云中实现。
接下来,我们通常要推出Web服务。 Kubernetes有一个入口抽象。 通常在此处添加SSL。

最简单的入口看起来像这样。 我们在此处编写规则:将哪些URL,哪些主机,哪个内部服务重定向到该请求。 同样,我们可以提高入口。
之后,在主机中本地注册后,您可以从此处查看此服务。
这是一项常规任务:我们部署了某个Web服务,并与Kubernetes进行了一些接触。
我们将清理所有内容,删除入口并查看所有资源。
有许多资源,例如configmap和secret。 这些纯粹是信息资源,您可以将其安装在容器中并在其中进行传输,例如postgres的密码。 您可以将其与将在启动时注入到容器中的环境变量关联。 您可以挂载文件系统。 一切都非常方便:标准任务,出色的解决方案。
存在持久卷-由不同的云提供商以不同的方式实现的接口。 它分为两个部分:存在持久的批量声明(请求),然后创建一些拖到容器的EBS。 您可以使用状态服务。

但是它在内部如何工作? 这个概念本身非常简单和透明。 Kubernetes有两个部分。 一个只是拥有所有这些资源的数据库。 可以将资源视为平板电脑:具体地说,这些实例只是平板电脑中的记录。 在Kubernetes之上,配置了一个API服务器。 也就是说,当您拥有一个Kubernetes集群时,通常会与API服务器通信(更确切地说,是客户端与之通信)。
因此,我们创建的内容(POD,服务等)只需写入数据库即可。 该数据库是由ETCD实现的,即 因此它在高可用性级别上是稳定的。
接下来会发生什么? 此外,在每种类型的资源下,都有一个特定的控制器。 这只是一项监视其资源类型并在外部世界中执行某些操作的服务。 例如,Docker是否运行。 如果我们有POD,则对于每个节点,都有一个kubelet服务来监视插入到该节点中的POD。 他所做的只是在下一次定期检查之后(如果此POD不存在)运行Docker。
此外,这非常重要-一切都是实时发生的,因此该控制器的功率高于最小值。 通常,控制器仍然会采用指标并查看其开始的时间。 即 从现实世界中删除反馈并将其写入数据库,以便您或其他控制器可以看到它。 例如,相同的POD状态将被写回到ETCD。
因此,一切都在Kubernetes中实现。 信息模型与手术室分开很酷。 在数据库中,通过通常的CRUD接口,我们声明应该是什么。 然后,这组控制器会尝试使所有事情正确。 没错,这并不总是会发生。
这是一个控制论模型。 我们有一个特定的预设,有某种机器正在尝试将现实世界或机器定向到所需的位置。 并非总是这样:我们应该有一个反馈循环。 有时机器无法做到这一点,必须转向一个人。

在实际系统中,我们以更高层次的抽象思想进行思考:我们拥有一些服务,数据库,并且我们都将其连接在一起。 我们不考虑POD和Ingress,而是要构建下一个抽象层次。

这样开发人员就尽可能地容易:这样他就简单地说:“我想启动这样的服务”,其他所有事情都发生在内部。
有这样的东西HELM。 这是错误的方式-Ansible样式模板化,在这里我们只是试图产生一组已配置的资源并将其放入Kubernetes集群中。
首先,问题在于这仅在滚动时才完成。 也就是说,他不能实现很多逻辑。 其次,在运行时这种抽象消失了。 当我查看群集时,我只看到POD和服务。 我看不到部署了某一种这样的服务,那里没有提出这种带有复制的基础。 我只看到那里有数十个炉膛。 抽象消失在矩阵中。

内部解决方案模型
另一方面,Kubernetes本身已经在内部提供了一个非常有趣且简单的扩展模型。 我们可以声明新的资源类型,例如部署。 这是建立在POD或副本集之上的资源。 我们可以为该资源编写一个控制器,将该资源放入数据库中并运行控制论循环,以便一切正常。 这听起来很有趣,在我看来,这是扩展Kubernetes的正确方法。

我希望能够为我的heroku风格的服务写一些清单。 一个非常简单的示例:我想在实际环境中部署某种应用程序。 已经有协议,SSL,购买域。 我只是想为开发人员提供最简单的界面。 清单告诉我要提升哪个容器,该容器仍需要哪些资源。 他将此公告发布到集群中,一切开始工作。

从定制资源和控制器的角度来看,这将如何? 在这里,我们将在数据库中有一个资源应用程序。 应用程序控制器将产生三个资源。 也就是说,他将在入口处写下有关如何路由到该服务,启动该服务以实现负载平衡以及使用某种配置启动部署的规则。

在Kubernetes中创建自定义资源之前,我们需要对其进行声明。 为此,有一个名为CustomResourceDefinition的元资源。
为了在Kubernetes中声明一个新资源,我们发布这样的公告就足够了。 考虑此创建表。
创建了一个表。 之后,我们可以通过kubectl获取我们拥有的第三方资源。 宣布后,我们也收到了标语。 例如,我们可以做kubeclt获取应用程序。 但是到目前为止没有应用程序。
让我们来编写一些应用程序。 之后,我们可以创建一个自定义资源实例。 让我们在YAML中查看它,并通过发布到特定的URL来创建它。
如果我们运行并查看kubectl,则会出现一个应用程序。 但是尽管什么也没有发生,但它只存在于数据库中。 例如,您可以获取并请求所有应用程序资源。
我们可以通过简单地更改名称,从同一模板中创建第二个此类资源。 这是第二个资源。
此外,我们的控制器应该像HELM一样做模板。 也就是说,在收到我们应用程序的描述之后,我必须生成资源部署和资源服务,并在入口处输入条目。 这是最简单的部分:在Clojure中是erlmacro。 我传递数据结构,它提取部署功能,传递给调试,即管道。 这是一个纯函数:简单的模板。 因此,以最幼稚的形式,我可以立即创建它,将其转换为控制台实用程序并开始分发。
我们对服务执行相同的操作:服务函数接受声明并为我们生成Kubernetes资源。
我们对进入的行执行相同的操作。
这一切如何运作? 现实世界中将会有某些东西,而我们会想要些东西。 我们想要的-我们获取应用程序资源并在其上生成应有的资源。 现在我们需要看看是什么。 我们通过REST API请求的内容。 我们可以获得所有服务,所有部署。
我们的自定义控制器将如何工作? 他将从这个div接收我们想要的东西,然后将其应用于Kubernetes。 这类似于React。 当某些函数只是生成JS对象树时,我想到了一个虚拟DOM。 然后某种算法计算补丁并将其应用于真实DOM。
我们将在这里做同样的事情。 这是用50行代码完成的。 想要-一切都在Github上。 最后,我们应该获得协调行动功能。
我们有一个协调动作函数,它什么也不做,只计算这个div。 她需要什么,再加上需要的东西。 然后,它给出了将第一个带到第二个需要做什么。
让我们拖拉她。 她没有什么错;她可以被贬低。 她说您需要创建一个入口服务,在其中输入两个条目,创建部署1和2,创建服务1和2。
在这种情况下,应该已经只有一项服务。 从入口我们可以看到仅剩下一个条目。
然后剩下的就是编写一个函数将此补丁应用到Kubernetes集群。 为此,我们只需将协调动作传递给协调功能,一切都会适用。 现在我们看到POD已经增加,部署已经开始,服务已经开始。
让我们添加另一个服务:再次执行reconcile-actions函数。 让我们看看发生了什么。 一切都开始了,一切都很好。
该如何处理? 我们将所有这些打包在一个Docker容器中。 之后,我们编写一个函数,该函数会定期唤醒,调和并入睡。 速度不是很重要,它可以睡五秒钟,并且不经常进行和解动作。
我们的自定义控制器只是一项服务,它将唤醒并定期计算补丁。
现在我们有两个服务zaddeloino,让我们删除其中一个应用程序。 让我们看看集群的反应:一切正常。 我们删除第二个:清除所有内容。
让我们看一下开发人员的眼睛。 他只需要说Kubernetes申请并命名新服务即可。 我们执行此操作,我们的控制器拾取并创建了所有内容。
然后,我们将所有这些收集在部署服务中,然后使用Kubernetes标准工具将此自定义控制器扔到集群中。 我们为200行代码创建了一个抽象。
一切看上去都像HELM,但实际上更强大。 控制器在集群中工作:它可以看到基础,可以看到外界,并且可以变得足够聪明。
自己的CI
考虑Kubernetes扩展示例。 我们决定将CI纳入基础架构。 很好,从安全角度来看很方便-私有存储库。 我们尝试使用jenkins,但这是一个过时的工具。 我想要一个黑客CI。 我们不需要界面,我们喜欢ChatOps:只需在聊天中说出构建是否失败即可。 另外,我想在本地调试所有内容。

我们坐下来写了一周的CI。 就像Kubernetes的扩展一样。 如果考虑CI,那么这只是运行某种工作的工具。 作为这项工作的一部分,我们构建了一些东西,运行测试并经常部署。
一切如何运作? 它基于自定义控制器的相同概念构建。
首先,我们在Kubernetes中描述了我们要遵循的存储库。控制器只是转到github并添加了web-hook。我们还有内省。接下来是web-hook,其唯一的任务是处理传入的JSON并将其放入自定义构建资源中,该资源也加到Kubernetes数据库中。构建资源由构建控制器监视,构建控制器读取项目内部的清单并启动POD。在此POD中,将启动所有必要的服务。在POD中,这是一个非常简单的代理,它以travis或circleci的方式读取声明,在YAML中是一组步骤。他开始履行他们。然后,在构建结束时,他将结果扔给Telegram。Kubernetes附带的另一个功能是,可以在true sleep 10时简单地设置执行CI或连续交付的命令之一,并且POD在这一步将冻结。您可以执行kubectl exec,在构建中找到自己,就可以首次亮相。另一个功能-一切都建立在docker上,您可以通过启动docker在本地调试脚本。总共花了两周时间和300行代码。
与postgres合作
我们的产品基于postgres构建,我们使用了各种有趣的功能。我们甚至编写了许多扩展。但是我们不能使用RDS或其他任何东西。我们现在正在开发一个坚不可摧的postgres的运算符。我会讲建筑。我想说:“集群,给我一个不能被杀死的postgres。”此外,我需要两个异步副本,一个同步副本,每天备份,最大备份量为TB。我把所有东西都扔了,然后我的集群控制器开始进行编排并扩展我的容器。它创建负责每个等距事例的pginstance资源。这将是集群postgres。进一步的pginstance控制器,非常简单,只需尝试使用此postgres运行POD或在其中进行部署。心脏是持久的体积。整个机器完全控制了postgres。您给她一个Docker容器,其中仅包含二进制postgres。其他一切:控制器本身完成postgres启动集群的配置和创建。他这样做是为了让我们以后可以重新配置,并且他可以配置复制,日志级别等。最初,临时POD在持久卷上运行,并为那里的master创建一个postgres集群。接下来,最重要的是,部署从master开始。然后,以相同的方式创建持久卷。另一个POD进行驱动,进行基本备份,将其提取,最重要的是,部署从属服务器开始。接下来,集群控制器创建备份资源(在与备份一起描述之后)。备份控制器已经将其放入并放入一些S3中。
接下来是什么?
让我们与您一起介绍不久的将来。可能会发生这样的情况,迟早我们会有如此有趣的自定义资源,自定义控制器,我会说:“给我postgres,给我kafka,给我CI,然后开始一切。”一切都会很简单。如果我们不谈论不久的将来,那么作为声明性程序员,我认为仅逻辑或关系编程要比功能编程高。在那里,我们的操作语义与信息语义完全分开。如果仔细查看我们所做的自定义控制器,那么我们的数据库中就会有一个资源应用程序。我们从中获得了另外三个资源。这与数据库视图非常相似。这是事实发现。这是逻辑或关系视图。Kubernetes的下一步是给人一种对关系或逻辑基础的错觉,而不是切碎的REST API,您可以在其中编写规则。既然迟早所有事物都会涌向数据库,包括反馈,规则听起来可能像这样:“如果负载如此增加,那么就那样增加复制。”我们将有一个小的sql或逻辑规则。您只需要一个通用引擎即可。但这是光明的未来。
— DevOops 2018 ! — .
«The DevOps Handbook» , «Learning Chef: A Guide to Configuration Management and Automation» , «How to containerize your Go code» «Liquid Software: How to Achieve Trusted Continuous Updates in the DevOps World» — . - .
: !
: 1 您可以以折扣价预订DevOops 2018的门票。