用例- docker持续交付的最佳实践

文摘:

Carl Quinn (Riot games软件架构师,2016年5月码头工人的容器然后深入研究使用JFrog Artifactory构建和部署Docker的最佳实践。码头工人介绍一种全新的打包和部署应用程序的方式。与新技术一样,在生产中使用它时,有许多需要解决的问题和方法。我们将讨论如何考虑并将服务组织到容器中,然后讨论构建映像的各种选项及其权衡。最后,我们将讨论图像发布和分发的策略。

讨论转录:

很好。所以今天我的演讲是关于Docker的最佳实践,持续交付——这张幻灯片并不完全正确。标题不太对。再讲一点Docker容器和映像的构建和交付。

我已经做了很长一段时间的构建工具和持续交付工具,Docker出现了,我们加入了它,我在几年前开始玩它,你学到的很多关于工件的干净和密封管理的实践仍然适用于Docker容器。但还有一些额外的小转折和一些更有趣的细节,我想谈谈并分享一些我在过去几年里为Riot游戏构建Docker容器和集群的生产部署的经验。

今天的议程是简单介绍Docker的容器和图像。我不知道这里有多少人已经熟悉Docker和容器以及建筑图像等等。有多少人对它不太熟悉?几。好的。所以我将很快地过一遍第一部分,只是——只是——设置词汇。我们会讲一点关于组织容器的一些哲学关于什么是构建容器的最佳方法,什么该放进去,什么不该放进去。如何制作图像。

这就是我要花更多的时间来讨论在图像中加入什么。要建造什么以及如何建造。这里有一些不同的技巧。不好意思,我本来要把这家伙干掉的。然后我们会讲更多关于交付和图像如何获得它们,如何管理你的回购,如何设置这些东西。最后是分布。那么,如何——如何——以一种有效的方式把你所有的图像都送到生产中去。还有一些你可能想要做和跟踪的事情。

容器和图像。Docker容器的类比非常适用于所有的集装箱和鲸鱼之类的东西。我们倾向于用容器这个术语来表示很多不同的东西。很多时候,当我们说容器的时候,我们指的是图像。你知道,只要人们理解它的上下文,这是可以的。但有时候,当我们谈论细节的时候,我们想要更精确一点。我们会详细讨论具体哪个部分是容器哪个部分是图像。

所以容器封装运行时状态。在Docker中,容器代表了一个进程或一组进程在操作系统中可以访问的范围。Docker与内核一起在运行时为容器设置环境。它可以控制对某些资源的特定访问,比如CPU,内存,块IO,网络IO,所以一个特定的容器可以2022世界杯阿根廷预选赛赛程从整个机器中获取多少是有限的。因此,您可以使用它来约束、包含和防止特定容器接管机器。当Docker刚问世时,它所能做的事情非常有限,现在它可以通过Docker的C组来管理和控制越来越多的事情。

容器的另一个很酷的地方是它们是功能性的。如果你构建了一个容器,并且设计得非常好,有点像微服务,你可以把它想象成一个数学函数。因此,一旦你设置了你的容器,你配置了它,你给了它一些环境变量,也许是一些参数,当你运行Docker时,启动容器。它是运行。它有点像一个黑盒子,你不需要文件进出,它只是用文件系统来存储。但它的基本思想是,它是网络上的一个函数,你知道,数据从网络上输入,端口被命中,进行查询,数据在网络上输出,这是一个很好的功能性黑盒。

容器是从图像开始的。因此,映像实际上是一个操作系统的磁盘或一个操作系统的一个小子集的快照,其中添加了文件。因此,构建一个图像的过程是从某种基础开始的,你在这个基础上启动一个容器,这样容器就在运行——它实际上在运行——你用来构建下一个图像的Docker文件的一部分告诉Docker在那里放什么。你可以向那个运行的容器中添加文件你可以复制文件,你可以在里面运行命令,比如apt-get或Yum update来获取你想要的文件,然后当你完成时,你可以进行快照,并再次将图像保存到磁盘。现在你有了上面的下一层。所以图像就像洋葱,就像食人魔,它们像这样层层构建。上面的每一层都引用下面的一层。也就是说,我是由我下面的人建立起来的那个人是由我下面的人建立起来的一直到某种根映像,从一个加载的操作系统的映像引导而来。

所以这个-这个-概念是一种值得记住的链,因为当你稍后将图像加载到工件库中时,我们将看到,所有这些层都必须被推到那里并进行管理。但当你使用特定的容器和你要运行的服务时,你会倾向于考虑这些图像你真正关心的是你引用的最上面的那个,所有其他的都是基于这些返回指针的。

当你准备好了,一旦你建立了你的映像,你必须把它放在某个地方,然后这些映像使用Docker push命令来识别你想要推送的映像,你把它推到注册表中。那个图像,那个层,会进入注册表所有其他层也会进入。如果他们一开始还没有登记的话。因此,用于保存图像的Docker API理解每一层都是该层内容的散列,然后Docker的push命令与注册表交互。来理解这些二进制散列中哪些已经存在了。所以如果这个层已经存在,它就不需要再次推送它。这种方法很有效因为它可以识别出它已经在那里了。举个例子,如果你下拉一个OS映像,添加一个文件,然后把生成的映像往上推,它只会推delta,上面的那个小图层。所以当你整理东西的时候要记住这些想法。

然后当你准备好运行并创建一个容器时你通过引用一个你想要运行的图像来运行它所以你可以提前把图像拉下来让它在机器上或者你可以直接说运行Docker会隐式地拉它。但无论哪种情况,它都对你有吸引力。pull是将图像从注册表中取出,放到本地磁盘上,由Docker缓存,然后运行从该图像启动容器。因此,您可以从同一个映像启动许多容器,并让它们在同一台机器上运行,它们只是某种短暂的快照——基于映像作为起点的运行时环境。

好了,有什么问题我可以边走边回答。我们将会看到时间如何发展。这部分我讲得很快。

现在我们来谈谈容器的组织。我知道Docker刚问世时人们认为。哦。噢,是的。去做吧。

(观众提问)

我要重复的问题是Docker映像和AMI相比如何?所以一个AMI,我很确定,最终是它最终状态的完整快照,在Docker镜像的情况下,Docker镜像可以再现整个状态,因为它引用了它需要的所有东西,贯穿整个链。如果你想的话,有很多方法可以将图像导出为单个焦油球。但通常在Dockers生态系统中使用它的方式是保持层分离,所有的工具都会在运行中为你抓取依赖项。它让事情变得很有效率,我们会在后面看到的。

所以当Docker刚出现的时候,每个人都认为Docker就像一个虚拟机。它就像一个虚拟机镜像,为什么它有什么不同。我要把整个庞大的应用程序,整个机器,放到Docker容器中。这是一种方法。其他人说,不,不,这应该是微服务。我们应该把一些小的东西放在每个容器里。因此,他们有两个阵营,一直在斗争。这是一个概念性的图表。所以在一边,你有一个小的微服务,里面有一个进程,差不多是一个进程-绝对是一个服务,它需要少量的操作系统文件,不是很多,因为通常它可能是一个小的运行时,也许它是一个Go程序,只需要[…],或者它是Java,但你可以在那里运行Jerry,无头Jerry而不需要很多操作系统。

另一方面,你可能需要一个完整的设备。比如你想要提供一些完全独立的东西。有利有弊,但在这种情况下,在设备世界中,您可以在那里放置多个服务,您可能需要运行像System D这样的服务,负责监督您的进程并重新启动它们。在这种情况下,设备方法将容器视为某种自修复、自运行的黑盒。

现在,在微服务的世界里,容器很精简、快速、小巧,但它们真的依赖于外部的编排。如果你要部署20个实例,一个微服务,30个微服务,40个微服务,然后把它们连接在一起你需要一些东西来把它们连接在一起,所以你需要某种平台。也许它只是Docker一次把东西组合在一起,或者可能是Swarm、Kubernetes或Mesos,但你需要某种编排工具来做这件事。所以只要你在这样的环境中工作,你就可以得到它,这是最好的选择。这真的是,我认为Docker的未来,未来的,你知道,开发操作容器和交付的东西又快又小,并取代它们这是我们最终想要走的路。

但是现在在这个阶段,调度程序正在以一种疯狂的方式竞争它们有点像正在进行的集群战争。不同的技术试图解决这个问题。所以目前还没有明确的赢家。没有明确的方法来交付像一个设备一样的东西,比如你要用Kubernetes交付你的设备,你要用Docker合成文件交付它。所以我认为为这些特定的用例提供设备容器是可以的。如果你想要交付一些独立的东西,你可以交给客户,说这是一个Docker映像,可以运行我所有的东西。Artifactory如何与nginx和Java一起运行,这是一个很好的用例,所以我认为在这个时间框架内是公平的。希望这些集群战争能够平息下来,我们将有更通用的方式来描述我们想要部署的堆栈的配置或拓扑。所以我认为这将会到来。

关于这个观点有什么问题吗?

不。好的。我们将讨论一些关于制作图像的内容。

[观众提问]我们正在处理的一件事是如何使用不同的微服务处理事件,以及当一个服务完全依赖于另一个服务时处理控制的最佳方式。

正确的。那么他们之间发生了什么?

(观众)对

是的,所以我认为这是整个生态系统的一部分,提出一个集群,你需要一些,像集群系统的一部分的基础设施,你知道。有些可能提供,有些可能不提供,但您需要某种方式来进行服务发现。当你设计微服务应用时,你还需要确保它们有12个因素。所以他们需要能够上来,其中一个因素我不记得了,就是对下游的依赖没有弹性。所以变得被动,等待下游的依赖关系回来。因此,服务实例化的顺序并不重要。否则,对于协调器来说,启动一系列微服务都变得非常复杂。如果它们都是健壮的,自给自足的,那就更好了,它可以把它们自动地粘在一起。但你确实需要一些精英服务发现,可以是基于DNS的,也可以是基于[…]的,或者你可以有自己的微服务来进行发现,就像Netflix和Eureka一样。

好的。制作图像。所以我认为一个主要的事情,Docker的网页和文档他们有一个很好的页面关于Docker文件最佳实践的技巧,所以我提到的很多都在那里。这是一个很好的资源。稍后我会把链接显示在屏幕上。

但我认为,最终目标之一是保持你的形象精简和简洁。好吧,让它们小一点。你不想把你不需要的东西放进图像中。为什么呢?我认为你会看到三件主要的事情:安全性、速度和规模。把你不知道或不需要的东西放到容器里,因为它很快,我的意思是,当你在做开发的时候,这很好,绝对不要担心它,就像你在桌面上做东西一样,只需要抓取你想要的基础。但总有一天你会进入生产阶段。这是你应该考虑的事情,让我们开始削减它,选择最好的基础使用,选择最好的类型-我们真正需要添加哪些包,哪些我们不需要添加。并做一些工作来修剪它们。

这是三个为什么。安全。因此,在运行时容器中拥有超过所需的东西会增加其中一些东西出现问题的几率。就像今天早上在舞台上一样,有一个可怕的,你知道,旧的库和坏的罐子,还有可怕的恶意软件。会有一些东西最终会泄漏到你的容器里,我的意思是,你会识别出漏洞,也许用x光检查。比如你的容器里有个东西,我们知道这是可疑的,里面有安全漏洞,你需要更换它。但作为开发人员,您可能知道我实际上并没有使用该组件。但是应用程序集的人说你的容器里有它。你不知道在公司层面或工具自动化层面,你会在容器中看到这些有风险的组件,你不知道它们是否被使用。因为它们就在那里,所以最好的办法就是一开始就不要把它们放在那里。 So trim down your images so that they only reference the things you actually need so that you’re not churning through a lot of security things. So make it easier for the security guys to find the real problems.

另一个原因是速度。你的图像越大越胖,组织越少,它们在网络上移动的时间就会长得多。对你来说,如果你做的是国际全局部署在世界各地的部署可能会有很大的延迟。这可能只是让你的内部网络过载,因为你移动的东西太多了。或者,如果你为广域网链接付费,你现在必须升级,因为你在那里塞了一些不需要的东西。这是另一个要记住的原因。

最后一个与速度有关,但它是一个空间。因此,在实际的Docker主机上,Docker守护进程在处理很多很多层方面并不是很好,如果你不定期进行垃圾收集,它会很容易被阻塞。一些集群管理器,比如Kubernetes有一个内置的垃圾收集器,可能Mesos也有。它们可以判断主机上什么时候不再使用映像并清理它们,但如果你运行的是更简单的东西,你只是想在Docker组合时进行简单的部署,而且周围没有自动化,这很容易使磁盘过载,实际上我的意思是随着时间的推移将磁盘填满特别是在构建时,我们有过构建节点,每隔几天构建节点就会宕机。我们不知道原因。它充满了图像。所以清理这些是你想要的,你需要处理的事情,但是有大量的脂肪图像会占用太多的空间,只会让问题更糟。

那么如何解决这些问题呢?所以,这都是关于底的。所有的基础。首先,有一些关于选择基像的规则。基本图像非常重要。你想要一个正式的基地,今天早上早些时候他们说要把你的基地放在Artifactory,我认为这很好。这也是个好主意。我们还没走到那一步。我们还在从Docker中心夺取官方基地。我认为这是可以的,只要你真的意识到只拿官方的。

所以如果你想要CentOS,就从CentOS那里买CentOS。不要买别人的CentOS,它可能更整洁,更精致,他在里面放了一些很酷的东西,但你不知道它在哪里。也许你测试了一次,你不知道六个月后当你推出下一个版本时会是什么样子。所以你只需要标准的。你确实想锁定一个特定的版本,有一些技术可以做到这一点。如果你只是直接从Docker中心构建,你想要指定并固定在标签上,这是完整的版本,这样你就知道你从什么开始,所以你有一个有效的版本-版本链,你可以遵循。

Docker有这个能力,它没有不可变标签。它们总是可变的,实际上它们可以改变但标记为7.2版本的东西,下个月可能还是7.2,但可能是不同的位。但你尽你所能,标记到最好的纹理版本。你也可以拉,比如,如果你使用Artifactory或其他本地内部回购作为缓存,你可以自己控制快照。所以你可以下拉官方版本,这是你想要的最新版本,并锁定它,也许添加你自己的标签,说这是我们今天使用的版本。然后从那里开始建造。总是从你所了解的开始构建。

然后是关于最近入住的标准提示。因此,总是尝试跟上,总是不断更新和重建新的版本,以确保你有所有的安全更新和性能修复和一切。同时也要选择一个最好的起点。所以不要总是只买你能找到的最大的Ubuntu或CentOS,它们有你需要的一切。这很简单,因为所有你可能需要的东西在你的主机上,在真正的主机上,都在容器里。你可能不需要全部。

所以你可能想看看一些建议的碱基。几年前,当我们第一次抓住Docker并开始使用Docker时,我在内部做了一个这样的演讲,我们在内部创建了一个推荐的基础列表。现在我注意到当我前几天回顾这个的时候它们比两年前小了很多。所以我认为这些构建标准发行版的官方版本的人越来越少了。因为他们知道他们不需要把厨房水槽里的所有东西都放在底座上。所以他们让他们更精简。这些痕迹都很好。你知道,如果你是一家CentOS红帽商店,CentOS真的很好。我们通常已经使用Debian很长时间了。我们认为是一个小[…]拥有一切。 But it turns out that the newest Ubuntu is smaller than Debian so — I don’t — those are really good choices.

如果你真的不需要很多操作系统,那么Alpine是很好的选择。这是我们构建的所有Go工具所使用的基本图像。因此,我们的很多内部基础设施运行时都是在Go中构建的,然后我们只需构建一个基于Alpine的容器并部署它。所以我们最终得到的是一个10兆字节的Go二进制文件,Alpine是另外5兆字节,所以我们有了这些图像,整个图像,整个运行时的15到20兆字节。这很好。

还有一些人尝试从零开始建造。你可以说我只想从头开始构建,完全没有图像,你必须把你需要的所有文件都放上去。所以你可以用一些语言来做,比如Go,或者你可以静态构建。把所有东西都放到二进制文件中。经常会有其他文件丢失。你经常会需要你的证书,诸如此类的东西,完成它需要一些探索。弄清楚你在运行时需要什么,你错过了什么,但如果你真的,真的想要做一些微小的东西这是,这是开始的方式。

是的。的问题。

(观众提问)

对,如果有人喜欢你说的,语言提供者可能有基础。我认为不同的语言在这种情况下会有所不同,所以对于Go来说,除了[…],真的没有其他运行时。因为Go是编译过的,所以你有一个二进制的原生代码。所以你不需要-你不需要一个Go运行时。你可以选择,如果Go的人提供了一个,比如,这是一个精简的Debian,它只有G库和Go需要的其他库,这可能是一个很好的选择。我不知道。其他语言,如Java,需要jvm。所以在Alpine上运行jvm,如果它来自一个官方发行版,也许来自Oracle,那将是非常有趣的。非常引人注目。

(观众提问)

不,这是真的,说得好。这样你可能会有不同的根。你必须权衡一下。我会在几张幻灯片中提到。所以我建议一般建立少量的根基地,或者我称之为你自己的基地。因此,这就是您可以获取特定Debian或CentOS的地方。只需要做一个非常简单的构建,进行更新,并添加公司可能需要的任何一种小东西。你公司的每个人。然后保存为一张图片。然后把它放在你的刺激回购区供其他人使用作为基础,然后从那里开始。 So this is one good technique for sort of locking down, and having a well-known root image that everybody can reference.

也许有两个。也许有些人喜欢Debian有些人喜欢基于CentOS的。因为不同的团队使用不同的工具。所以你可以有两个。但是,你知道,两个总比25个好,因为每个人都在不同的时间做了自己的工作,他们都有点不同。这样你就不需要等价的,而是二进制不同的,因为那是一种浪费。正如你提到的,这是幻灯片。我不知道这有多好读。这个想法是,当你构建Docker映像时,它们会引用它们的父映像,所以在一天结束时,你会得到一个看起来像树的东西。你运行应用程序的容器映像在顶部它们可能引用一个基本映像,其中有一些库的东西,然后另一个是你公司的祝福映像,然后引用官方映像。 They go on this tree. If you can consolidate to a small number of roots and shared intermediate bases you end up having a lot less copies that are similar but binary different. So that’s your point so reducing it to a small number, if you can build everything on top of the base distro that you like and you prefer then that’s great.

(观众提问)

我讲了一些我们最后可以问的问题。我试着过一遍如果我还没讲完的话。

[观众]这很有趣。

嗯好的。后面的同学还有问题吗?是的。

(观众提问)

是的。正确的。好的。所以要记录事物的版本。我的团队通常做的是,这种做法在我们公司很常见,但并不是一成不变的,只是给它加上后缀。比如你要抓取CentOS, 7.2.1511你要构建它并添加一些东西然后我们将它命名为7.2.1511。1。所以这是我们在上面的额外的东西。然后当你在上面构建图层时,我认为,在最后构建增量构建号后缀来跟踪你所做的事情。你知道,Java的哪个版本在CentOS的哪个版本之上的历史,以及其他东西的哪个版本,它会变得非常复杂。所以你不需要把所有东西都编码进去只要你确定了它的序列和唯一性。 I think that’s sufficient.

(观众提问)

是的。好吧,我要讲一下这方面的进展。我有一些建议,但没有明确的答案,但是

(观众)为什么?

JFrog有一些不错的新工具,我们可以稍后讨论。

另一个减少非常非常小的图像数量的技巧是把所有的命令和Docker文件压缩到一起,把它们加在一起。因此Docker文件中的每个运行命令或Docker文件中的每个添加命令最终都是一个层。所以如果你加上这个,加上这个,加上这个,你最终会有20层,只是增加了越来越多的间接。如果它们很小,你会认为它们不是很大,但每一层都有一堆元数据,每一层最终都需要一个交易才能通过网络获得它。如果你在Docker文件中以一种随意的顺序做事,每个人的Docker文件都会有点不同所有的层都会有点不同所以Docker人员的建议是你的基本内容应该按字母顺序排序,挤在一起变成少量的命令。如果你现在考虑一下,我们正在用shell脚本构建图像。在某种程度上,我们似乎倒退了。但它非常灵活和简单,Docker文件是如此线性,这是一个很好的,合理的咬大小来处理。

好了,现在我们知道了如何制作图像并将它们组合在一起,我们将不得不交付它们。你不觉得你的剪贴画很有创意吗?

有问题吗?

(观众提问)

对,转移功。我认为他们解决问题的方法不同[…],厨师,木偶。他们正在处理一个稍微不同的问题,他们试图把一个非常大的系统,比如整个主机,可能运行许多应用程序和许多共享库,并将其聚合到一个新的状态。而使用Docker,您总是从头开始构建图像。这样你就不用担心会改变文件或者改变东西或者你只在那个图像上运行一个东西,这就是容器要小的原因。你不必担心冲突,因为它只有一种用途。我认为,因为这是一个简单得多的问题,解决方案也可以简单得多,所以它更像是一个make文件。它只是说从这里开始,把这些东西加起来。所以你可以从零字节一直追踪到你放上去的东西。你知道上面会写什么就像你说的那样。 You don’t have to worry about mutating anything. So, I mean, I think you can learn from what you’ve done with Chef and Puppet and how you’ve built your systems and understand how it’s gone but probably won’t get much value from trying to reuse those files.

传递图像。那么,你将如何将图像以一种可以共享的方式传递呢?所以不是部署,而是交付部分。所以这很重要,在这个会议上的每个人都知道——每个人都知道——你需要不断地整合,快速地构建东西,并把它们推出去。但这其中的一部分,就像刚才提到的,你如何跟踪谁取决于什么。现在还没有什么神奇的解决方法。一些像X-Ray这样的工具可以做到这一点,你也可以使用Artifactory来跟踪元数据和依赖关系,或者你甚至可以创建你的Jenkins构建来实际跟踪你的基本映像的依赖关系链。所以当你发现一个漏洞,或者你只是决定我们需要转移到最新版本的Debian或CentOS时,所有依赖我们的人都需要重新构建。

所以你希望这是自动化的。所以你可以用Jenkins作业链来做,或者你可以用Artifactory来做,寻找标签,并再次触发你的构建,但是围绕它设置一些过程是很重要的。所以你可以找到所有依赖于你意识到需要改变的东西的应用程序。你希望它是自动的。如果负责基础映像的团队说,哦,我们有一个漏洞,我们有一个补丁,让我们提供补丁并重建。它应该是自动的,一直到应用程序团队-开发团队-自动获得他们的新版本的图像。如果他们不想被牵扯进来就不用被牵扯进来。

那么,当你建立了这些图像之后,你把它们放在哪里呢?所以有几种选择。这里的人可能还不知道这些。所以有一个开源的注册表,从Docker第一次发布开始就一直在更新。他们现在有了一个企业产品,可信注册中心。这是一个不错的选择。但我喜欢Artifactory,在这里说我喜欢Artifactory是对的。给我吗?

我说这些话都没人给我钱,虽然我应该有,对吧?

对我来说,JFrog的人知道如何构建高效和可扩展的二进制存储库。Docker只是另一种人工制品。尽管它的API有些古怪,但归根结底,它只是一些二进制工件,你可以通过哈希来识别,并在上面放置元数据,然后移动它。Artifactory在这方面做得很好。如果你使用Artifactory,它是一个很棒的Docker repo。如果你是白手起家,你是一家小公司,或者你只是一个想要建立小公司的人,你知道开源是很好的。如果您是一家已经从Docker获得了一些企业产品的商店,那么他们的可信注册表可能是一个不错的选择。hth华体会最新官方网站

所以你要做的第一件事是决定你的注册表的真相来源在哪里。您的存储库。Artifactory。并确保它对你有适当的可用性。如果你是亚马逊用户,或者和亚马逊有良好的连接,至少要有一些恢复能力,比如RDS和S3。弹性文件系统和弹性数据库。如果您需要它对所有开发人员全天候可用,那么您就需要使用Artifactory的HA版本,它将为您提供足够的冗余和主动故障转移,因此当您需要时—当事情变得疯狂时,当您需要将新东西推向生产时,您不会丢失主存储库。所以你想在你的主服务器中有一个可靠的真相来源。

这就是我们在Riot所拥有的。我们在拉斯维加斯的主数据中心建立了一个,那是我们保存所有主文件和主要副本的地方。我们实际上已经围绕用例组织了我们的回购。我们有一个针对Docker的Artifactory集群,因为这是Docker的用例。我们有其他的Artifactories用于其他目的,我们已经这样划分了,我不认为这是必要的,这取决于你的团队的规模和谁在管理什么。这对我们来说是可行的,因为我的团队和我们的大团队做集群和Docker之类的事情,所以我们运行的是我们想做Docker的那个。

有一件事是我们历经磨难才发现的。这有点好笑。把你的存储库分成开发部分和生产部分是个好主意。开发部分会有,那是默认的地方,当东西在构建中产生时,它会有很多变动,开发人员正在构建运行得很快的东西。里面会有很多你不一定需要用到的东西。它们可能只是坏了。它们可能完全没问题,但完全被替换了,你知道,一个小时后,当下一个CI重建时,它会很吵,很颠簸。你想要创造和开拓出一个小区域,一个独立的小逻辑仓库,这是我们的产品所在的地方。因此,一旦你编辑了东西,你运行了测试,你就可以有一个升级过程,在10分钟内复制东西,把东西复制到prod repo。这以后会给你带来一些好处。 Makes it easier for people to find things and then when we get to distribution that makes that a lot simpler too.

是的问题。

(观众提问)

是的。所以我们正在构建-上传-我会说你会使用Artifactory api在上面放一个标签,然后将它提升到Artifactory内的另一个逻辑回购,所以它是一个零副本。所以通常你不需要重建它。这是一个[…],你不需要上传,所以它是好的。

还有一件事也是我们经历了惨痛的经历才发现的。团队的权限。我们为许多不同的团队管理中央存储库。这真的很难读。但是我们发现——如果人们没有意识到Artifactory中的这个特性——权限对象真的很强大。这就是你真正需要做的就是创建一个团队的代表。因此,在权限对象中,我们可以为Docker组织分配一个权限对象,类似于Docker映像组织。这里有通配符-这肯定很难读-然后把用户加进去。可以用脚本添加它们。在这种情况下,我组成了一个团队。 That D team. And I put myself in it and we have permissions to do everything we want to in our repo. There’s a group object in Artifactory which is really handy for integrating with LDAP but if you’re not doing it with LGAP — LDAP — then you actually don’t need it. And it saves a step, makes things less complicated. We found out, yeah, so for us that’s something we learned.

是的。好的,继续。

(观众提问)

我就在这里提一下。我不喜欢。是的。

(观众提问)

我们利用Artifactory中可用的权限。我在这里没有很好地展示它但是团队成员可以有不同的-你可以管理,你可以删除,覆盖,部署。Artifactory中内置了一些不同的权限,我们只是使用它们,所以这很好。我们肯定有几十个不同的团队,每个团队都有所有的工程师和团队成员,他们可以访问回购,他们几乎都可以重写,完全访问它。然后我们有更多的基于角色的工具。然后,工具就变成了只读的。因此,我们实际的集群部署工具是对所有回购的只读访问。所以他们可以进行部署。

我会讲得快一点然后我们可以谈谈,稍后会有更多的问题。

这很重要,我没有一个完美的解决方案。我们遇到了这个问题,无论我走到哪里,你都会想出一些基本的想法。所以将回购拆分成两部分很有帮助。因为你的开发回购有更多的波动,你需要更积极地清理东西。你可以做一些事情,比如检测一个特定的图像是否从未被推广过,从未被引用过,是否完全被一个被取代的新图像所淘汰。可以立即删除。你可以设置一个很好的TTL,一旦它们没有使用过一段时间,你就可以清理它们。如果你把图像分离到prod中,那么你的prod TTL会更长。您可以将引用引用到生产环境中,以确保仍在运行的程序仍然有可用的映像。所以你可以这样交叉参照。 So, these are not complete solutions but just things to check.

(观众提问)

所有元数据都在Artifactory中可用,因此您可以找到所有这些信息。因此,您可以编写一个用户插件来完成它,或者像我过去所做的那样,编写一个Jenkins作业来收集元数据。所以我认为在Netflix,我们做了一个用户插件的组合,收集元数据,并产生一个转储,然后我们把它拉到Jenkins,检查它,然后用命令行工具做了一系列删除。这就是CLI。现在Artifactory有了自己很棒的CLI。你可以在用户插件中做更多的工作,找出需要删除的候选对象并标记它们,然后使用工具删除它们。是的。

(观众提问)

好吧,这就对了。很好。Artifactory插件会给你一个过期时间。太好了。然后我猜你会取代它如果你推广了一些东西,对吧,你想让它持续更久一点。

(观众提问)

所以我可以,让我讲完分布这可能会回答你的问题。现在我要讲的是如何分配图像来刺激,记住,我建议我们要做的是我们需要一个主要的真相来源。这就是所有元数据的来源,这是元数据的真实来源。以我们为例,我们有很多全球数据中心,我们把我们的图像推送到世界各地。我们有我们的小集群运行,我们需要得到图像。我们做推送复制,我会给你们看细节,但想法是我们想要prod中需要的图像的副本被推送到prod中并可用,这样当我们启动节点时,Docker需要运行,或者机器停机时,我们需要在新机器上重新启动相同的容器,我们希望速度快。

因此,我们希望减少重新部署的延迟,或者集群管理器需要将映像移动到启动容器的某个地方。我们还想减少广域网带宽,这样我们就不需要不断地从国际网络上提取图像,我们希望一次性推送,并将其缓存到远程服务器上。

我们使用Artifactory多推复制,所以每当一个图像被推到主,我们复制它的一种基于触发器的推。效果很好。我们犯的一个错误。我马上就会展示。这真的很方便,你也可以有一个cron-based。为了防止我们遗漏的一些图像在网络中丢失,cron-base将每天晚上或每隔几个晚上进行一次扫描,以确保所有的图像都被推送。这只是一个构建在Artifactory上的方便特性。我们现在有7个遥控器,我们要把这个数字翻倍,所以我们在全世界推广。

这是很关键的一点,我们之所以回过头来重新构建master的架构,其中一个原因是我们一开始没有做隔离。所以我们在世界各地复制这种堵塞我们管道的方法。我们建议在全世界范围内都这样做。这就是为什么我们想要建立一个新的小型数据中心(也许是在GCE中)的原因之一,因为团队需要所有东西的副本。要花点时间把那些他们不需要的东西搬过去。所以让它变得精简和简单,可以让它在需要的地方更加敏捷和快速地提供新的存储库。在我们的案例中,我们没有想它,我们提出它,它是有效的,然后我们自己的成功,每个人都开始使用我们的回购,它真的很满。所以我们现在运行了大约125000张图像,我们无法区分什么是什么。我们要做的就是清理这些。

就是这样。问题吗?

要么快速释放,要么死亡