61

重新审视 Docker 和 Jenkins

 5 years ago
source link: http://www.10tiao.com/html/146/201807/2650082315/2.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.


协作翻译

原文:Revisting Docker and Jenkins

链接:https://engineering.riotgames.com/news/revisiting-docker-and-jenkins

译者: liyue李月, Tocy, kevinlinkai, 无若


今天,我想介绍下我们在使用 Docker 和 Jenkins 两年后在 Riot 中学到的经验。我还会为那些熟悉的人员详细介绍我为该系列文章做出的所有更新和改动,并介绍 Docker 容器和 Jenkins 的变迁。


开发者生态系统


早在2016年,当我第一次将笔放在纸上,安装 Docker 并在桌面上使用起来并不是很方便。当时 Docker Toolbox 是桌面设置中的最好的工具。该工具在桌面上设置 Virtualbox 并在 Linux 虚拟机中运行 Docker 。Docker 提供了一个叫做 Docker Machine 的具有创造性的客户端应用程序来创建和管理改 VM(如果你愿意的话,可以使用几个其他的)。这种设置运行良好,但是非常的重量级。


现在,Docker 为 Windows 和 OSX 提供了本地安装程序。尽管虚拟机管理程序现在更加本地化,并且不需要 Virtualbox ,但他们仍然依赖于虚拟机管理程序样式的解决方案。作为奖励,Windows 版的 Docker 可以在“本地窗口”模式下运行,这使得 Windows Docker 容器得益于微软的合作开发成果。这两种解决方案都像集成的桌面客户端,通过方便的图形用户界面驱动的设置菜单和选项,使得 Docker 的工作变得更加容易。我已经更新了一系列的博客来反映这些增加的内容,这反过来使得设置和运行更容易解释!


DOCKER的改变


在2016年Docker的版本是1.10左右,Docker composer几乎不支持Windows。我们的部署也依赖于Docker Swarm版本0.3.0。Docker 1.12于当年年末时候在DockerCon上宣布,标志着一个重大的进化。在这两年中对Docker的更改太多了,无法详细介绍,但是有几个更改影响了教程。


DOCKER VOLUMES


对Docker最重要的更改可能是添加了Docker Volumes。在Docker的1.10版本中,如果不希望从主机装载数据,您仍然需要创建一个“Docker数据容器”来封装存储持久性。这在Docker中创建了一个半永久volume,其他容器可以从中装载和共享数据。虽然很方便,但也有一定的风险,因为如果您希望维护存储,至少有一个容器必须指向数据容器内的volumes。这使得在生产Docker主机上使用这样的设置不太理想,实际上我们只在Jenkins的本地开发环境中使用这种设置。


通过引入真正的volume支持,您可以创建、命名和管理volumes,这些volumes可以独立于容器或包含大量集成命令的映像。volumes一直存在,直到您有意地从Docker主机中删除它们,并且它们甚至与存储插件集成在一起,以支持跨集群的共享数据volumes(如果您愿意的话)。我更新了博客关于消除笨重的数据volumes容器,并为数据存储定义和创建Docker卷。我想你会发现这种方法更加直观。事实上,你们中的许多人都写过,并提供反馈,认为这样的转换是长期需要的。


您可以在
这里阅读关于Docker Volumes及其各种存储特性的更多信息:


  • https://docs.docker.com/storage/volumes/


DOCKER NETWORKS


在2016年Docker的时代,pre Docker1.12,让两个容器相互通信,需要手动识别他们所暴露的端口,知道Docker主机的IP地址或使用Docker链接,这在同一个主机上是有效的。在最初的教程中,我建议为启用Docker的虚拟机安装检索您的IP地址,并将其提供给几个脚本,以便您的Jenkins安装可以修改NGINX和内部configs等内容。它使得像“localhost”这样的东西作为简单的DNS引用几乎是不可能的。这也意味着我们必须使用容器连接两个容器,以便它们能够很容易地找到彼此。


如今,Docker已经引入了Docker网络。随着Docker在Mac和Windows上的出现,Docker主机现在只使用机器的本地IP地址;容器链接被认为是过时的,并已被弃用。与Volumes一样,网络可以独立地创建、命名和维护,而不需要任何容器或图像。容器可以连接到网络,即使是最简单的Docker也提供服务发现,并通过DNS公开网络中的所有容器。


这使我们能够完全重新考虑教程和本地Jenkins设置的许多方面。为了使Jenkins和NGINX能够彼此对话我取消了使用容器链接,而是将它们放在Docker网络上。同样,我重新配置了Jenkins配置中的构建Docker的设置,以便它们连接到相同的网络,并且可以轻松找到Jenkins主服务器。


整个设置现在是自包含的,不再需要您提供一个IP地址。我们还可以消除在Jenkins配置中用于重命名字段的繁琐启动脚本。


新特性是广泛的,并且在整个Docker群集群中工作,允许您轻松地在主机之间桥接容器。您可以在
这里阅读更多Docker网络特性:


  • https://docs.docker.com/network/


DOCKER COMPOSE


在Docker Compose上也看到了许多变化。除了对Volumes和网络的完全支持之外,还获得了对Windows的完全原生的支持。这意味着,我现在几乎只在创建多容器应用程序时使用Docker composer在我的桌面上运行。Compose使名称变得超级简单,并创建多个网络、Volumes和“服务”(多容器应用程序)。规范文件也进行了一些修订,现在已经在版本3上了。您将发现,我已经完全接受了Docker composer的最新版本,相关的配置文件都已更新。


您可以在
这里阅读有关最新的Compose更改的更多信息:


  • https://docs.docker.com/compose/compose-file/


DOCKER PROXYING


随着对Docker进行如此多的更改以及切换到原生Docker安装版,一个问题出现了。为了让Jenkins安装动态创建构建从机能够和Docker容器一样,它需要在系统桌面上与Docker对话,就好像它是Docker主机一样。具有讽刺意味的是,当Docker主机在Virtualbox内的虚拟机中运行时,这相当简单,因为它有自己的本地IP地址,并可配置为不安全的监听端口2375或使用TLS证书监听端口2376。旧的教程让你通过获得这些证书并安全地与该终端通信。


现在Dockerhost因为智能安全的原因不会将自己暴露给公共互联网,而这种变化使Jenkins开发配置变得复杂,并在Windows和Mac上创造了独特的挑战。在OSX上,我选择通过使用socat,通过Docker网络上的端口2375(这仍然是不会暴露此文件到公开网络的)来公开Docker套接字文件来解决此问题。这使得与Jenkins的配置通信变得更加容易。这个技巧在Windows上不起作用,因为没有Docker套接字文件。因此,我选择了暴露公开端口2375的作为仅在Windows上的选项。这从技术上意味着本教程中的Windows配置比OSX更不安全。


其他DOCKER的变化


正如你所看到的,两年来Docker发生了很多变化。在本教程系列中,您会发现许多小细节,例如Docker构建时间参数,标签以及Dockerfiles中反映的其他小调整。其中有很多强大的新功能,但它们并没有彻底改变教程的性质,所以我会把它们留给你自己去发现。


JENKINS变化


就像Docker一样,Jenkins的时间也在不断前进。当我写这篇教程时,Jenkins 2刚刚上线。 Docker Plugin正在经历非常早的迭代,代码库被分入了另一个Docker插件最终Jenkins仍然像两年前一样工作,但是,Jenkins的Dockerfile设置已经发生了很多变化,配置和设置也发生了改变,它允许与Docker主机进行通信并构建从属设备。


JENKINS版本


本教程现在使用Jenkins v2.112(撰写本文时为最新版本)。大部分重大更改都在Dockerfile演练中,演示了Cloudbees如何设置Dockerfiles - 例如底层OS容器,Jenkins dockerfiles内部暴露的变量,启动以及Java选项,还有脚本。


DOCKER PLUGIN(S)


这个空间中最大的变化来自插件,用于在构建从服务器动态地派生Docker容器。2016年,当我完成博客系列时,另一个Docker插件作为Docker插件的一个分支刚刚上线。从这个插件看到了持续的改进和新版本的诞生,而最初的Docker插件在大约一年的时间里都没有改变。Docker插件直到最近才被Cloudbees的开发人员复兴,现在这两个插件都有非常不同的配置。我已经进行了广泛的测试,并且两者都运行良好。可以说Docker插件在本教程中更容易设置,因此在整个教程中都是突出显示的。


无论您使用哪个插件,我都主张放弃我在2016年写过的SSH连接设置。相反,这两个插件都提供了一种不同的方式来使用与Jenkins的反向JNLP连接,这将大大提高速度和性能。同样,它使配置和设置临时构建变得更容易。因此,本教程已经进行了更新,以消除SSH连接方法,并坚持使用更简单的方法。


那么你最终应该选择哪个插件呢?在2016年,我开始喜欢另一个Docker插件,因为当涉及到Jenkins时,我总是喜欢正在开发中的插件。最近,随着Cloudbees对Docker插件的支持,我怀疑这可能是最好的长期使用,我们的下一个升级将集中在最新的版本上。


更多已学到的经验教训


两年对处理Riot Jenkins部署等大型复杂系统的运营问题来说是一个相当长的时间。很可能,我会忘记我们一路上所学的所有微小的事情。这就是说,我认为这里有一些重要的经验教训值得一提。


规模


我们的Jenkins集群自发布第一篇文章以来就一直在增长。在之前文章撰写过程中,我相信我们所描述的Docker Jenkins设置定义了大约1,000-2,000个作业,并且峰值为每小时以120-200个作业。现在我们的服务器平均每小时平均可以处理200-400个作业,峰值为600个左右,并且定义了超过7,000个作业。


这当然会给系统带来很大的压力。我们仍然在该服务器上使用0.15版本的Docker Plugin(我们将随后升级),但我们必须在容器上进行多轮实例上限设定。我们的用户开始对Jenkins非常熟练,并且会创建多个流程,同时启用5个,10个甚至20个容器,以并行处理事务。较旧版本的插件无法处理所有这些情况,特别是在使用SSH时。我们发现立即构建环境实例数量控制在5到10之间对我们用例的最佳配置。


构建环境


在我们运行这个设置的两年时间里,我们的用户创建了大约240个独特的构建环境,最多可以有7000多个工作机会。经过培训、教育、交谈和反馈,这个数字已经缩减到150-180个左右。我们发现很多人在创建独特的环境时,实际上他们可以使用通用的设置,比如Java或Go软件开发。我们继续提倡合并。我们发现,在Riot的各个团队中,大多数不同的设置仍然存在于Python和NPM开发社区中,并且大部分由包管理和环境设置组成。


作为一种和平服务,我们为各种操作系统(Alpine, Ubuntu和Centos)提供基础构建服务,因此使用我们工具的团队可以与他们的包管理人员一起工作。除此之外,我们还提供Python、Java和Go从用例以及一组基本的实用程序脚本。我们得到了一个有力的教训,那就是升级这些系统实际上是非常痛苦的。当Jenkins切换到使用Java 1.8的强制性需求时,我们必须在几天内更新每个人的构建环境,在此期间许多团队的构建都无法工作。对于拥有核心服务的团队来说,这从来都不是一个好时机。


自从更新以来,我们提倡最小化基本构建环境中的内容。我们已经开始使用许多预先安装的脚本和工具,并在运行时通过从服务器的简单下载将它们安装或安装到容器中。在许多情况下,我们将实用程序转移到共享Jenkins管道的Groovy库(到目前为止,将代码放到环境中是最容易/最快的选择)。


JENKINS PIPELINE


在我们的Docker Jenkins配置的7,000个作业中,有近4400个是Jenkins管道作业。我们使用了Pipeline的Jenkins全局库功能创建了一套通用管道函数。这些自定义库中的大部分可以更容易地与各种Riot artifact商店和系统进行交互。有些只是通过最小化语法和使用常规默认值来使管道更容易使用。我将在不久之后写一篇关于我们的通用函数的博客。

Pipeline作业突飞猛进的主要原因是我们开始构建我称之为的“持续交付即服务”的部分。Riot的大部分后端软件栈已经整合到Java或Go服务中,其中大多数使用相同的内核软件库。因此,我们要求团队在代码仓库中放置了一个简单的Jenkinsfile,其中仅包含这些构建的配置数据。


我们使用Jenkins共享库来使用这些文件,并使用通用管道来构建我们的软件。因此,使用这些框架构建的团队不需要构建工程师。实际上,团队不需要编写单个构建脚本来发布他们的软件,因为即使他们的部署工作是自动化的。更多关于这个介绍将在未来的博客中!


JENKINS重新开始并恢复工作


虽然情况越来越好,但是使用临时构建环境的一个代价是缺少永久性的工作空间。这确实给许多Jenkins插件带来了一个循环,因为他们期望一个公共的工作空间存在于一个永久的构建上。虽然这在一些地方影响了我们(特别是源代码控制插件),但是最大的影响是Jenkins管道库本身及其恢复功能。


Jenkins有一个方便的重新启动特性,但是因为我们在瞬息万变的环境中使用了太多的管道,所以工作进程无法重新启动,如果我们不从磁盘上删除所有的恢复文件,那么重新启动常常会使Jenkins无法使用。我们创建了一个自定义的Jenkins重新启动过程,以禁用所有试图在重新启动后重新启动的Jenkins作业。


从那以后,Cloudbees引入了管道耐久性,或者全局禁用管道的能力。他们还修复了几个bug以提高Jenkins的稳定性。话虽如此,如果在重新开始之前,管道短暂的构建环境已经消失,那么管道仍然不太可能恢复,所以emptor警告说,使用这种方法意味着构建恢复特性可能没有那么有用。


不友好的容器和镜像设置


当我第一次写博客时,我讨论了这个问题,它仍然是值得注意的。 Docker 的插件在创建容器后尝试清理时做得相当不错,但容器在作业时会泄漏其他的容器。 尤其是长期运行的容器,我们必须调整我们的设置来消除。


因此,我们的 Docker Jenkins 环境在背景剔除正在运行的容器之前,最长运行时间约为24小时。 这使得该设置对于任何长时间运行作业(如性能测试)的任何人都不那么有用,除非他们在不到24小时的时候变更 Jenkins 节点。


一般的维护和自动化工作


虽然我们构建这个服务器是一个可扩展的软件构建平台,但是我们并没有预料到它会有多受欢迎,因为一般的自动化团队想要自动化各种维护过程或其他小的工作。


因为我们不需要团队提供传统的构建装置,所以我们的Jenkins平台成为一个有吸引力的选择。Jenkins是一个强大的任务运行系统,因为它集成了源代码控制和cron-like的调度功能。自动化作业是Jenkins服务器最主要的用途之一;Jenkins很容易实现从小数据ETL负载到跨几十个系统的健康检查的自动化。


自动化作业的负载配置文件与构建作业非常不同。当一个构建作业可能在工作时间提交源代码时触发时,自动化作业往往按照计划运行,从每15分钟到24小时不等。这些工作全天候24小时运行,为团队创建维护窗口的挑战。我们正在积极地考虑创建两个Jenkins环境,一个用于自动化风格的工作,一个用于软件构建。然而,我们还没有设计出一种清晰的方法来执行该策略,如果不进行简单的执行,它可能会给我们的Jenkins用户造成一些迷惑。


结论


自2016年以来,看到这一体系的发展,是令人难以置信的收获。随着时间的推移,由于Docker特性的改进,基本的开发设置变得更容易维护和使用。Jenkins也变得更健壮了更容易的整合了。Jenkins管道的成熟使它成为我们目前在Riot所拥有的最强大的自动化和构建系统之一。


我们的未来充满了这样的问题,即我们的Jenkins设置将扩展到什么程度,以及我们应该在什么时候进行分片,以便我们能够更容易地创建维护窗口和用户导航。问题不再是“这行得通吗?”但是“我们能推多远?”


最初的尝试是让构建环境完全实现自服务,并消除自定义构建装置的需要,而现在的系统已经开始消除自定义构建脚本和作业的需要,同时节省工程时间。一如既往,我热切期待您在下面的评论中的反馈,经验教训,和想法。我会思考并且回答问题,并从您的Docker和Jenkins的经历中学习。


此外,如果您不想花时间重新阅读所有教程,那么您可以在我的公共github中查找最新的“只需几步就能启动和运行”设置:


  • https://github.com/maxfields2000/dockerjenkins_tutorial

开源中国征稿开始啦!


开源中国 www.oschina.net 是目前备受关注、具有强大影响力的开源技术社区,拥有超过 200 万的开源技术精英。我们传播开源的理念,推广开源项目,为 IT 开发者提供一个发现、使用、并交流开源技术的平台。


现在我们开始对外征稿啦!如果你有优秀的技术文章想要分享,热点的行业资讯需要报道等等,欢迎联系开源中国进行投稿。投稿详情及联系方式请参见:我要投稿



推荐阅读

Python 之父宣布退出决策层,Python 该何去何从?

认为 C++ 太糟糕,独立游戏教父“吹神”亲自开发新语言

颠覆网站 C/S 模式,没有服务器的网站会带来什么变革?

为什么 Windows 7 会成为 Windows 10 最大的敌人?

RSS 之父 Winer 炮轰 Google 反客为主强推 HTTPS

点击“阅读原文”查看更多精彩内容

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK