标签 容器 下的文章

一旦公司越过了“让我们看看这些容器如何工作”的阶段,他们最终会在许多不同的地方运行容器

Man conducting orchestra

需要快速、高效地交付程序的公司 —— 而今天,哪些公司不需要这样做?—— 是那些正在转向 Linux 容器的公司。他们还发现,一旦公司越过了“让我们看看这些容器如何工作”的阶段,他们最终会在许多不同的地方运行容器。

Linux 容器技术不是新技术,但它随着最初由 Docker 发明的创新性打包格式(现在的 OCI 格式)以及新应用对持续开发和部署的需求开始变得流行。在 Red Hat 的 2016 年 5 月的 Forrester 研究中,有 48% 的受访者表示已经在开发中使用容器,今年的数字预计将达到 53%。只有五分之一的受访者表示,他们在 2017 年不会在开发过程中利用容器。

像乐高积木一样,容器镜像可以轻松地重用代码和服务。每个容器镜像就像一个单独的、旨在做好一部分工作的乐高积木。它可能是数据库、数据存储、甚至预订服务或分析服务。通过单独包装每个组件,从而可以在不同的应用中使用。但是,如果没有某种程序定义(即 指令手册 instruction booklet ),则难以在不同环境中创建完整应用程序的副本。那就是容器编排的来由。

life container megabricks

容器编排提供了像乐高系统这样的基础设施 —— 开发人员可以提供如何构建应用程序的简单说明。编排引擎将知道如何运行它。这使得可以轻松创建同一应用程序的多个副本,跨越开发人员电脑、CI/CD 系统,甚至生产数据中心和云提供商环境。

Linux 容器镜像允许公司在整个运行时环境(操作系统部件)中打包和隔离应用程序的构建块。在此基础上,通过容器编排,可以很容易地定义并运行所有的块,并一起构成完整的应用程序。一旦定义了完整的应用程序,它们就可以在不同的环境(开发、测试、生产等)之间移动,而不会破坏它们,且不改变它们的行为。

仔细调查容器

很明显,容器是有意义的,越来越多的公司像“对轮胎踹两脚”一样去研究容器。一开始,可能是一个开发人员使用一个容器工作,或是一组开发人员在使用多个容器。在后一种情况下,开发人员可能会随手编写一些代码来处理在容器部署超出单个实例之后快速出现的复杂性。

这一切都很好,毕竟他们是开发人员 —— 他们已经做到了。但即使在开发人员世界也会变得混乱,而且随手代码模式也没法跟着容器进入 QA 和生产环境下。

编排工具基本上做了两件事。首先,它们帮助开发人员定义他们的应用程序的表现 —— 一组用来构建应用程序实例的服务 —— 数据库、数据存储、Web 服务等。编排器帮助标准化应用程序的所有部分,在一起运行并彼此通信,我将这称之为标准化程序定义。其次,它们管理一个计算资源集群中启动、停止、升级和运行多个容器的过程,这在运行任何给定应用程序的多个副本时特别有用,例如持续集成 (CI) 和连续交付 (CD)。

想像一个公寓楼。居住在那里的每个人都有相同的街道地址,但每个人都有一个数字或字母或两者的组合,专门用来识别他或她。这是必要的,就像将正确的邮件和包裹交付给合适的租户一样。

同样,在容器中,只要你有两个容器或两个要运行这些容器的主机,你必须跟踪开发人员测试数据库连接或用户连接到正在运行的服务的位置。容器编排工具实质上有助于管理跨多个主机的容器的后勤。它们将生命周期管理功能扩展到由多个容器组成的完整应用程序,部署在一组机器上,从而允许用户将整个集群视为单个部署目标。

这真的很简单,又很复杂。编排工具提供了许多功能,从配置容器到识别和重新调度故障容器​​,将容器暴露给集群外的系统和服务,根据需要添加和删除容器等等。

虽然容器技术已经存在了一段时间,但容器编排工具只出现了几年。编排工具是 Google 从内部的高性能计算(HPC)和应用程序管理中吸取的经验教训开发的。在本质上,其要解决的就是在一堆服务器上运行一堆东西(批处理作业、服务等)。从那时起,编排工具已经进化到可以使公司能够战略性地利用容器。

一旦你的公司确定需要容器编排,下一步就是确定哪个平台对于业务是最有意义的。在评估容器编排时,请仔细查看(尤其):

  • 应用程序定义语言
  • 现有能力集
  • 添加新功能的速度
  • 开源还是专有
  • 社区健康度(成员的积极性/高效,成员提交的质量/数量,贡献者的个人和公司的多样性)
  • 强化努力
  • 参考架构
  • 认证
  • 产品化过程

有三个主要的容器编排平台,它们似乎领先于其他,每个都有自己的历史。

  1. Docker Swarm: Swarm 是容器典范 Docker 的附件。Swarm 允许用户建立并管理 Docker 节点的集群为单个虚拟系统。Swarm 似乎正在成为一个单一供应商的项目。
  2. Mesos: Mesos 是从 Apache 和高性能计算中成长起来的,因此是一个优秀的调度员。Mesos 的技术也非常先进,虽然与其他相比似乎没有发展速度或投资优势。
  3. Kubernetes: 由 Google 开发,由其内部编排工具 Borg 经验而来,Kubernetes 被广泛使用,并拥有强大的社区。其实这是 GitHub 上排名第一的项目。Mesos 目前可能比 Kubernetes 略有技术优势,但是 Kubernetes 是一个快速发展的项目,这也是为了长期技术上的收益而进行的架构投资。在不久的将来,在技术能力上应该能赶超 Mesos。

编排的未来

展望未来,企业们可以期待看到编排工具在应用程序和服务为中心的方向上发展。因为在现实中,如今快速应用程序开发实际上是在快速地利用服务、代码和数据的组合。无论这些服务是开源的,还是由内部团队部署的抑或从云提供商处购买的,未来将会是两者的混合。由于今天的编排器也在处理应用程序定义方面的挑战,所以期望看到它们越来越多地应对外部服务的整合。

此时此刻,想要充分利用容器的公司必须利用容器编排。

(题图:Thinkstock)


via: https://www.infoworld.com/article/3205304/containers/orchestration-tools-enable-companies-to-fully-exploit-linux-container-technology.html

作者:Scott McCarty 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

作为一名开发者,我会尝试留意那些我可能不会每天使用的技术的进步。了解这些技术至关重要,因为它们可能会间接影响到我的工作。比如由 Docker 推动的、近期正在兴起的容器化技术,可用于上规模地托管 Web 应用。从技术层面来讲,我并不是一个 DevOps,但当我每天构建 Web 应用时,多去留意这些技术如何去发展,会对我有所裨益。

这种进步的一个绝佳的例子,是近一段时间高速发展的容器编排平台。它允许你轻松地部署、管理容器化应用,并对它们的规模进行调整。目前看来,容器编排的流行工具有 Kubernetes (来自 Google)Docker SwarmApache Mesos。如果你想较好的了解上面那些技术以及它们的区别,我推荐你看一下这篇文章

在这篇文章中,我们将会从一些简单的操作开始,了解一下 Kubernetes 平台,看看如何将一个 WordPress 网站部署在本地机器上的一个单节点集群中。

安装 Kubernetes

Kubernetes 文档中有一个很好的互动教程,涵盖了很多东西。但出于本文的目的,我只会介绍在 MacOS 中 Kuberentes 的安装和使用。

我们要做的第一件事是在你的本地主机中安装 Kubernetes。我们将使用一个叫做 MiniKube 的工具,它专门用于在你的机器上方便地设置一个用于测试的 Kubernetes 集群。

根据 Minikube 文档,在我们开始之前,有一些先决条件。首先要保证你已经安装了一个 Hypervisor (我将会使用 Virtualbox)。接下来,我们需要安装 Kubernetes 命令行工具(也就是 kubectl)。如果你在用 Homebrew,这一步非常简单,只需要运行命令:

$ brew install kubectl

现在我们可以真正 安装 Minikube 了:

$ curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.21.0/minikube-darwin-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/

最后,我们要启动 Minicube 创建一个虚拟机,来作为我们的单节点 Kubernetes 集群。现在我要说一点:尽管我们在本文中只在本地运行它,但是在真正的服务器上运行 Kubernetes 集群时,后面提到的大多数概念都会适用。在多节点集群上,“主节点”将负责管理其它工作节点(虚拟机或物理服务器),并且 Kubernetes 将会在集群中自动进行容器的分发和调度。

$ minikube start --vm-driver=virtualbox

安装 Helm

现在,本机中应该有一个正在运行的(单节点)Kubernetes 集群了。我们现在可以用任何方式来与 Kubernetes 交互。如果你想现在可以体验一下,我觉得 kubernetesbyexample.com 可以很好地向你介绍 Kubernetes 的概念和术语。

虽然我们可以手动配置这些东西,但实际上我们将会使用另外的工具,来将我们的 WordPress 应用部署到 Kubernetes 集群中。Helm 被称为“Kubernetes 的包管理工具”,它可以让你轻松地在你的集群中部署预构建的软件包,也就是“ 图表 chart ”。你可以把图表看做一组专为特定应用(如 WordPress)而设计的容器定义和配置。首先我们在本地主机上安装 Helm:

$ brew install kubernetes-helm

然后我们需要在集群中安装 Helm。 幸运的是,只需要运行下面的命令就好:

$ helm init

安装 WordPress

现在 Helm 已经在我们的集群中运行了,我们可以安装 WordPress 图表。运行:

$ helm install --namespace wordpress --name wordpress --set serviceType=NodePort stable/wordpress  

这条命令将会在容器中安装并运行 WordPress,并在容器中运行 MariaDB 作为数据库。它在 Kubernetes 中被称为“Pod”。一个 Pod 基本上可视为一个或多个应用程序容器和这些容器的一些共享资源(例如存储卷,网络等)的组合的抽象。

我们需要给这个部署一个名字和一个命名空间,以将它们组织起来并便于查找。我们同样会将 serviceType 设置为 NodePort 。这一步非常重要,因为在默认设置中,服务类型会被设置为 LoadBalancer。由于我们的集群现在没有负载均衡器,所以我们将无法在集群外访问我们的 WordPress 站点。

在输出数据的最后一部分,你会注意到一些关于访问你的 WordPress 站点的有用的命令。运行那些命令,你可以获取到我们的 WordPress 站点的外部 IP 地址和端口:

$ export NODE_PORT=$(kubectl get --namespace wordpress -o jsonpath="{.spec.ports[0].nodePort}" services wordpress-wordpress)
$ export NODE_IP=$(kubectl get nodes --namespace wordpress -o jsonpath="{.items[0].status.addresses[0].address}")
$ echo http://$NODE_IP:$NODE_PORT/admin

你现在访问刚刚生成的 URL(忽略 /admin 部分),就可以看到 WordPress 已经在你的 Kubernetes 集群中运行了!

扩展 WordPress

Kubernetes 等服务编排平台的一个伟大之处,在于它将应用的扩展和管理变得易如反掌。我们看一下应用的部署状态:

$ kubectl get deployments --namespace=wordpress

kubectl get deployments

可以看到,我们有两个部署,一个是 Mariadb 数据库,一个是 WordPress 本身。现在,我们假设你的 WordPress 开始承载大量的流量,所以我们想将这些负载分摊在多个实例上。我们可以通过一个简单的命令来扩展 wordpress-wordpress 部署:

$ kubectl scale --replicas 2 deployments wordpress-wordpress --namespace=wordpress

再次运行 kubectl get deployments,我们现在应该会看到下面的场景:

kubectl get deployments

你刚刚扩大了你的 WordPress 站点规模!超级简单,对不对?现在我们有了多个 WordPress 容器,可以在它们之中对流量进行负载均衡。想了解 Kubernetes 扩展的更多信息,参见这篇指南

高可用

Kubernetes 等平台的的另一大特色在于,它不单单能进行方便的扩展,还可以通过自愈组件来提供高可用性。假设我们的一个 WordPress 部署因为某些原因失效了,那 Kubernetes 会立刻自动替换掉这个部署。我们可以通过删除我们 WordPress 部署的一个 pod 来模拟这个过程。

首先运行命令,获取 pod 列表:

$ kubectl get pods --namespace=wordpress

kubectl get pods

然后删除其中一个 pod:

$ kubectl delete pod wordpress-wordpress-876183909-jqc8s --namespace=wordpress

如果你再次运行 kubectl get pods 命令,应该会看到 Kubernetes 立刻换上了新的 pod (3l167)。

kubectl get pods

更进一步

我们只是简单了解了 Kubernetes 能完成工作的表面。如果你想深入研究,我建议你查看以下功能:

你在容器平台上运行过 WordPress 吗?有没有使用过 Kubernetes(或其它容器编排平台),有没有什么好的技巧?你通常会怎么扩展你的 WordPress 站点?请在评论中告诉我们。


作者简介:

Gilbert 喜欢构建软件。从 jQuery 脚本到 WordPress 插件,再到完整的 SaaS 应用程序,Gilbert 一直在创造优雅的软件。 他粗昂做的最有名的的产品,应该是 Nivo Slider.


via: https://deliciousbrains.com/running-wordpress-kubernetes-cluster/

作者:Gilbert Pellegrom 译者:StdioA 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

介绍

想在笔记本电脑上尝试 MongoDB?只需执行一个命令,你就会有一个轻量级的、独立的沙箱。完成后可以删除你所做的所有痕迹。

想在多个环境中使用相同的 程序栈 application stack 副本?构建你自己的容器镜像,让你的开发、测试、运维和支持团队使用相同的环境克隆。

容器正在彻底改变整个软件生命周期:从最早的技术性实验和概念证明,贯穿了开发、测试、部署和支持。

编排工具用来管理如何创建、升级多个容器,并使之高可用。编排还控制容器如何连接,以从多个微服务容器构建复杂的应用程序。

丰富的功能、简单的工具和强大的 API 使容器和编排功能成为 DevOps 团队的首选,将其集成到连续集成(CI) 和连续交付 (CD) 的工作流程中。

这篇文章探讨了在容器中运行和编排 MongoDB 时遇到的额外挑战,并说明了如何克服这些挑战。

MongoDB 的注意事项

使用容器和编排运行 MongoDB 有一些额外的注意事项:

  • MongoDB 数据库节点是有状态的。如果容器发生故障并被重新编排,数据则会丢失(能够从副本集的其他节点恢复,但这需要时间),这是不合需要的。为了解决这个问题,可以使用诸如 Kubernetes 中的 数据卷 volume 抽象等功能来将容器中临时的 MongoDB 数据目录映射到持久位置,以便数据在容器故障和重新编排过程中存留。
  • 一个副本集中的 MongoDB 数据库节点必须能够相互通信 - 包括重新编排后。副本集中的所有节点必须知道其所有对等节点的地址,但是当重新编排容器时,可能会使用不同的 IP 地址重新启动。例如,Kubernetes Pod 中的所有容器共享一个 IP 地址,当重新编排 pod 时,IP 地址会发生变化。使用 Kubernetes,可以通过将 Kubernetes 服务与每个 MongoDB 节点相关联来处理,该节点使用 Kubernetes DNS 服务提供“主机名”,以保持服务在重新编排中保持不变。
  • 一旦每个单独的 MongoDB 节点运行起来(每个都在自己的容器中),则必须初始化副本集,并添加每个节点到其中。这可能需要在编排工具之外提供一些额外的处理。具体来说,必须使用目标副本集中的一个 MongoDB 节点来执行 rs.initiaters.add 命令。
  • 如果编排框架提供了容器的自动化重新编排(如 Kubernetes),那么这将增加 MongoDB 的弹性,因为这可以自动重新创建失败的副本集成员,从而在没有人为干预的情况下恢复完全的冗余级别。
  • 应该注意的是,虽然编排框架可能监控容器的状态,但是不太可能监视容器内运行的应用程序或备份其数据。这意味着使用 MongoDB Enterprise AdvancedMongoDB Professional 中包含的 MongoDB Cloud Manager 等强大的监控和备份解决方案非常重要。可以考虑创建自己的镜像,其中包含你首选的 MongoDB 版本和 MongoDB Automation Agent

使用 Docker 和 Kubernetes 实现 MongoDB 副本集

如上节所述,分布式数据库(如 MongoDB)在使用编排框架(如 Kubernetes)进行部署时,需要稍加注意。本节将介绍详细介绍如何实现。

我们首先在单个 Kubernetes 集群中创建整个 MongoDB 副本集(通常在一个数据中心内,这显然不能提供地理冗余)。实际上,很少有必要改变成跨多个集群运行,这些步骤将在后面描述。

副本集的每个成员将作为自己的 pod 运行,并提供一个公开 IP 地址和端口的服务。这个“固定”的 IP 地址非常重要,因为外部应用程序和其他副本集成员都可以依赖于它在重新编排 pod 的情况下保持不变。

下图说明了其中一个 pod 以及相关的复制控制器和服务。

图 1:MongoDB 副本集成员被配置为 Kubernetes Pod 并作为服务公开

逐步介绍该配置中描述的资源:

  • 从核心开始,有一个名为 mongo-node1 的容器。mongo-node1 包含一个名为 mongo 的镜像,这是一个在 Docker Hub 上托管的一个公开可用的 MongoDB 容器镜像。容器在集群中暴露端口 27107
  • Kubernetes 的数据卷功能用于将连接器中的 /data/db 目录映射到名为 mongo-persistent-storage1 的永久存储上,这又被映射到在 Google Cloud 中创建的名为 mongodb-disk1 的磁盘中。这是 MongoDB 存储其数据的地方,这样它可以在容器重新编排后保留。
  • 容器保存在一个 pod 中,该 pod 中有标签命名为 mongo-node,并提供一个名为 rod 的(任意)示例。
  • 配置 mongo-node1 复制控制器以确保 mongo-node1 pod 的单个实例始终运行。
  • 名为 mongo-svc-a负载均衡 服务给外部开放了一个 IP 地址以及 27017 端口,它被映射到容器相同的端口号上。该服务使用选择器来匹配 pod 标签来确定正确的 pod。外部 IP 地址和端口将用于应用程序以及副本集成员之间的通信。每个容器也有本地 IP 地址,但是当容器移动或重新启动时,这些 IP 地址会变化,因此不会用于副本集。

下一个图显示了副本集的第二个成员的配置。

图 2:第二个 MongoDB 副本集成员配置为 Kubernetes Pod

90% 的配置是一样的,只有这些变化:

  • 磁盘和卷名必须是唯一的,因此使用的是 mongodb-disk2mongo-persistent-storage2
  • Pod 被分配了一个 instance: janename: mongo-node2 的标签,以便新的服务可以使用选择器与图 1 所示的 rod Pod 相区分。
  • 复制控制器命名为 mongo-rc2
  • 该服务名为mongo-svc-b,并获得了一个唯一的外部 IP 地址(在这种情况下,Kubernetes 分配了 104.1.4.5

第三个副本成员的配置遵循相同的模式,下图展示了完整的副本集:

图 3:配置为 Kubernetes 服务的完整副本集成员

请注意,即使在三个或更多节点的 Kubernetes 群集上运行图 3 所示的配置,Kubernetes 可能(并且经常会)在同一主机上编排两个或多个 MongoDB 副本集成员。这是因为 Kubernetes 将三个 pod 视为属于三个独立的服务。

为了在区域内增加冗余,可以创建一个附加的 headless 服务。新服务不向外界提供任何功能(甚至不会有 IP 地址),但是它可以让 Kubernetes 通知三个 MongoDB pod 形成一个服务,所以 Kubernetes 会尝试在不同的节点上编排它们。

图 4:避免同一 MongoDB 副本集成员的 Headless 服务

配置和启动 MongoDB 副本集所需的实际配置文件和命令可以在白皮书《启用微服务:阐述容器和编排》中找到。特别的是,需要一些本文中描述的特殊步骤来将三个 MongoDB 实例组合成具备功能的、健壮的副本集。

多个可用区 MongoDB 副本集

上面创建的副本集存在风险,因为所有内容都在相同的 GCE 集群中运行,因此都在相同的 可用区 availability zone 中。如果有一个重大事件使可用区离线,那么 MongoDB 副本集将不可用。如果需要地理冗余,则三个 pod 应该在三个不同的可用区或地区中运行。

令人惊奇的是,为了创建在三个区域之间分割的类似的副本集(需要三个集群),几乎不需要改变。每个集群都需要自己的 Kubernetes YAML 文件,该文件仅为该副本集中的一个成员定义了 pod、复制控制器和服务。那么为每个区域创建一个集群,永久存储和 MongoDB 节点是一件很简单的事情。

图 5:在多个可用区域上运行的副本集

下一步

要了解有关容器和编排的更多信息 - 所涉及的技术和所提供的业务优势 - 请阅读白皮书《启用微服务:阐述容器和编排》。该文件提供了获取本文中描述的副本集,并在 Google Container Engine 中的 Docker 和 Kubernetes 上运行的完整的说明。


作者简介:

Andrew 是 MongoDB 的产品营销总经理。他在去年夏天离开 Oracle 加入 MongoDB,在 Oracle 他花了 6 年多的时间在产品管理上,专注于高可用性。他可以通过 @andrewmorgan 或者在他的博客(clusterdb.com)评论联系他。


via: https://www.mongodb.com/blog/post/running-mongodb-as-a-microservice-with-docker-and-kubernetes

作者:Andrew Morgan 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

容器在过去几年内取得很大的进展。现在我们来回顾它发展的时间线。

Linux 容器是如何演变的

在过去几年内,容器不仅成为了开发者们热议的话题,还受到了企业的关注。持续增长的关注使得在它的安全性、可扩展性以及互用性等方面的需求也得以增长。满足这些需求需要很大的工程量,下面我们讲讲在红帽这样的企业级这些工程是如何发展的。

我在 2013 年秋季第一次遇到 Docker 公司(Docker.io)的代表,那时我们在设法使 Red Hat Enterprise Linux (RHEL) 支持 Docker 容器(现在 Docker 项目的一部分已经更名为 Moby)的运行。在移植过程中,我们遇到了一些问题。处理容器镜像分层所需的写时拷贝(COW)文件系统成了我们第一个重大阻碍。Red Hat 最终贡献了一些 COW 文件系统实现,包括 Device Mapperbtrf,以及 OverlayFS 的第一个版本。在 RHEL 上,我们默认使用 Device Mapper, 但是我们在 OverlayFS 上也已经取得了很大进展。

我们在用于启动容器的工具上遇到了第二个主要障碍。那时的上游 docker 使用 LXC 工具来启动容器,然而我们不想在 RHEL 上支持 LXC 工具集。而且在与上游 docker 合作之前,我们已经与 libvrit 团队携手构建了 virt-sandbox 工具,它使用 libvrit-lxc 来启动容器。

在那时,红帽里有员工提到一个好办法,换掉 LXC 工具集而添加桥接器,以便 docker 守护进程通过 libvirt-lxc 与 libvirt 通讯来启动容器。这个方案也有一些顾虑。考虑下面这个例子,使用 Docker 客户端(docker-cli)来启动容器,各层调用会在容器进程(pid1OfContainer)之前依次启动:

docker-cli → docker-daemon → libvirt-lxc → pid1OfContainer

我不是很喜欢这个方案,因为它在启动容器的工具与最终的容器进程之间有两个守护进程。

我的团队与上游 docker 开发者合作实现了一个原生的 Go 编程语言 版本的容器运行时,叫作 libcontainer。这个库作为 [OCI 运行时规范]的最初版实现与 runc 一同发布。

docker-cli → docker-daemon @ pid1OfContainer

大多数人误认为当他们执行一个容器时,容器进程是作为 docker-cli 的子进程运行的。实际上他们执行的是一个客户端/服务端请求操作,容器进程是在一个完全单独的环境作为子进程运行的。这个客户端/服务端请求会导致不稳定性和潜在的安全问题,而且会阻碍一些实用特性的实现。举个例子,systemd 有个叫做套接字唤醒的特性,你可以将一个守护进程设置成仅当相应的套结字被连接时才启动。这意味着你的系统可以节约内存并按需执行服务。套结字唤醒的工作原理是 systemd 代为监听 TCP 套结字,并在数据包到达套结字时启动相应的服务。一旦服务启动完毕,systemd 将套结字交给新启动的守护进程。如果将守护进程运行在基于 docker 的容器中就会出现问题。systemd 的 unit 文件通过 Docker CLI 执行容器,然而这时 systemd 却无法简单地经由 Docker CLI 将套结字转交给 Docker 守护进程。

类似这样的问题让我们意识到我们需要一个运行容器的替代方案。

容器编排问题

上游的 docker 项目简化了容器的使用过程,同时也是一个绝佳的 Linux 容器学习工具。你可以通过一条简单的命令快速地体验如何启动一个容器,例如运行 docker run -ti fedora sh 然后你就立即处于一个容器之中。

当开始把许多容器组织成一个功能更为强大的应用时,你才能体会到容器真正的能力。但是问题在于伴随多容器应用而来的高复杂度使得简单的 Docker 命令无法胜任编排工作。你要如何管理容器应用在有限资源的集群节点间的布局与编排?如何管理它们的生命周期等等?

在第一届 DockerCon,至少有 7 种不同的公司/开源项目展示了其容器的编排方案。红帽演示了 OpenShiftgeard 项目,它基于 OpenShift v2 的容器(叫作 gears)。红帽觉得我们需要重新审视容器编排,而且可能要与开源社区的其他人合作。

Google 则演示了 Kubernetes 容器编排工具,它来源于 Google 对其自内部架构进行编排时所积累的知识经验。OpenShift 决定放弃 Gear 项目,开始和 Google 一同开发 Kubernetes。 现在 Kubernetes 是 GitHub 上最大的社区项目之一。

Kubernetes

Kubernetes 原先被设计成使用 Google 的 lmctfy 容器运行时环境来完成工作。在 2014 年夏天,lmctfy 兼容了 docker。Kubernetes 还会在 kubernetes 集群的每个节点运行一个 kubelet 守护进程,这意味着原先使用 docker 1.8 的 kubernetes 工作流看起来是这样的:

kubelet → dockerdaemon @ PID1

回退到了双守护进程的模式。

然而更糟糕的是,每次 docker 的新版本发布都使得 kubernetes 无法工作。Docker 1.10 切换镜像底层存储方案导致所有镜像重建。而 Docker 1.11 开始使用 runc 来启动镜像:

kubelet → dockerdaemon @ runc @PID1

Docker 1.12 则增加了一个容器守护进程用于启动容器。其主要目的是为了支持 Docker Swarm (Kubernetes 的竞争者之一):

kubelet → dockerdaemon → containerd @runc @ pid1

如上所述,每一次 docker 发布都破坏了 Kubernetes 的功能,这也是为什么 Kubernetes 和 OpenShift 请求我们为他们提供老版本 Docker 的原因。

现在我们有了一个三守护进程的系统,只要任何一个出现问题,整个系统都将崩溃。

走向容器标准化

CoreOS、rkt 和其它替代运行时

因为 docker 运行时带来的问题,几个组织都在寻求一个替代的运行时。CoreOS 就是其中之一。他们提供了一个 docker 容器运行时的替代品,叫 rkt (rocket)。他们同时还引入一个标准容器规范,称作 appc (App Container)。从根本上讲,他们是希望能使得所有人都使用一个标准规范来管理容器镜像中的应用。

这一行为为标准化工作树立了一面旗帜。当我第一次开始和上游 docker 合作时,我最大的担忧就是最终我们会分裂出多个标准。我不希望类似 RPM 和 DEB 之间的战争影响接下来 20 年的 Linux 软件部署。appc 的一个成果是它说服了上游 docker 与开源社区合作创建了一个称作 开放容器计划 Open Container Initiative (OCI) 的标准团体。

OCI 已经着手制定两个规范:

OCI 运行时规范:OCI 运行时规范“旨在规范容器的配置、执行环境以及生命周期”。它定义了容器的磁盘存储,描述容器内运行的应用的 JSON 文件,容器的生成和执行方式。上游 docker 贡献了 libcontainer 并构建了 runc 作为 OCI 运行时规范的默认实现。

OCI 镜像文件格式规范:镜像文件格式规范主要基于上游 docker 所使用的镜像格式,定义了容器仓库中实际存储的容器镜像格式。该规范使得应用开发者能为应用使用单一的标准化格式。一些 appc 中描述的概念被加入到 OCI 镜像格式规范中得以保留。这两份规范 1.0 版本的发布已经临近(LCTT 译注:已经发布)。上游 docker 已经同意在 OCI 镜像规范定案后支持该规范。Rkt 现在既支持运行 OCI 镜像也支持传统的上游 docker 镜像。

OCI 通过为工业界提供容器镜像与运行时标准化的环境,帮助在工具与编排领域解放创新的力量。

抽象运行时接口

得益于标准化工作, Kubernetes 编排领域也有所创新。作为 Kubernetes 的一大支持者,CoreOS 提交了一堆补丁,使 Kubernetes 除了 docker 引擎外还能通过 rkt 运行容器并且与容器通讯。Google 和 Kubernetes 上游预见到增加这些补丁和将来可能添加的容器运行时接口将给 Kubernetes 带来的代码复杂度,他们决定实现一个叫作 容器运行时接口 Container Runtime Interface (CRI) 的 API 协议规范。于是他们将 Kubernetes 由原来的直接调用 docker 引擎改为调用 CRI,这样任何人都可以通过实现服务器端的 CRI 来创建支持 Kubernetes 的容器运行时。Kubernetes 上游还为 CRI 开发者们创建了一个大型测试集以验证他们的运行时对 Kubernetes 的支持情况。开发者们还在努力地移除 Kubernetes 对 docker 引擎的调用并将它们隐藏在一个叫作 docker-shim 的薄抽象层后。

容器工具的创新

伴随 skopeo 而来的容器仓库创新

几年前我们正与 Atomic 项目团队合作构建 atomic CLI。我们希望实现一个功能,在镜像还在镜像仓库时查看它的细节。在那时,查看仓库中的容器镜像相关 JSON 文件的唯一方法是将镜像拉取到本地服务器再通过 docker inspect 来查看 JSON 文件。这些镜像可能会很大,上至几个 GiB。为了允许用户在不拉取镜像的情况下查看镜像细节,我们希望在 docker inspect 接口添加新的 --remote 参数。上游 docker 拒绝了我们的代码拉取请求(PR),告知我们他们不希望将 Docker CLI 复杂化,我们可以构建我们自己的工具去实现相同的功能。

我们的团队在 Antonio Murdaca 的领导下执行这个提议,构建了 skopeo。Antonio 没有止步于拉取镜像相关的 JSON 文件,而是决定实现一个完整的协议,用于在容器仓库与本地主机之间拉取与推送容器镜像。

skopeo 现在被 atomic CLI 大量用于类似检查容器更新的功能以及 atomic 扫描 当中。Atomic 也使用 skopeo 取代上游 docker 守护进程拉取和推送镜像的功能。

Containers/image

我们也曾和 CoreOS 讨论过在 rkt 中使用 skopeo 的可能,然而他们表示不希望运行一个外部的协助程序,但是会考虑使用 skopeo 所使用的代码库。于是我们决定将 skopeo 分离为一个代码库和一个可执行程序,创建了 image 代码库。

containers/images 代码库和 skopeo 被几个其它上游项目和云基础设施工具所使用。Skopeo 和 containers/image 已经支持 docker 和多个存储后端,而且能够在容器仓库之间移动容器镜像,还拥有许多酷炫的特性。skopeo 的一个优点是它不需要任何守护进程的协助来完成任务。Containers/image 代码库的诞生使得类似容器镜像签名等增强功能得以实现。

镜像处理与扫描的创新

我在前文提到 atomic CLI。我们构建这个工具是为了给容器添加不适合 docker CLI 或者我们无法在上游 docker 中实现的特性。我们也希望获得足够灵活性,将其用于开发额外的容器运行时、工具和存储系统。Skopeo 就是一例。

我们想要在 atomic 实现的一个功能是 atomic mount。从根本上讲,我们希望从 Docker 镜像存储(上游 docker 称之为 graph driver)中获取内容,把镜像挂在到某处,以便用工具来查看该镜像。如果你使用上游的 docker,查看镜像内容的唯一方法就是启动该容器。如果其中有不可信的内容,执行容器中的代码来查看它会有潜在危险。通过启动容器查看镜像内容的另一个问题是所需的工具可能没有被包含在容器镜像当中。

大多数容器镜像扫描器遵循以下流程:它们连接到 Docker 的套结字,执行一个 docker save 来创建一个 tar 打包文件,然后在磁盘上分解这个打包文件,最后查看其中的内容。这是一个很慢的过程。

通过 atomic mount,我们希望直接使用 Docker graph driver 挂载镜像。如果 docker 守护进程使用 device mapper,我们将挂载这个设备。如果它使用 overlay,我们会挂载 overlay。这个操作很快而且满足我们的需求。现在你可以执行:

# atomic mount fedora /mnt
# cd /mnt

然后开始探查内容。你完成相应工作后,执行:

# atomic umount /mnt

我们在 atomic scan 中使用了这一特性,实现了一个快速的容器扫描器。

工具协作的问题

其中一个严重的问题是 atomic mount 隐式地执行这些工作。Docker 守护进程不知道有另一个进程在使用这个镜像。这会导致一些问题(例如,如果你先挂载了 Fedora 镜像,然后某个人执行了 docker rmi fedora 命令,docker 守护进程移除镜像时就会产生奇怪的操作失败,同时报告说相应的资源忙碌)。Docker 守护进程可能因此进入一个奇怪的状态。

容器存储系统

为了解决这个问题,我们开始尝试将从上游 docker 守护进程剥离出来的 graph driver 代码拉取到我们的代码库中。Docker 守护进程在内存中为 graph driver 完成所有锁的获取。我们想要将这些锁操作转移到文件系统中,这样我们可以支持多个不同的进程来同时操作容器的存储系统,而不用通过单一的守护进程。

我们创建了 containers/storage 项目,实现了容器运行、构建、存储所需的所有写时拷贝(COW)特性,同时不再需要一个单一进程来控制和监控这个过程(也就是不需要守护进程)。现在 skopeo 以及其它工具和项目可以直接利用镜像的存储系统。其它开源项目也开始使用 containers/storage,在某些时候,我们也会把这些项目合并回上游 docker 项目。

驶向创新

当 Kubernetes 在一个节点上使用 docker 守护进程运行容器时会发生什么?首先,Kubernetes 执行一条类似如下的命令:

kubelet run nginx -image=nginx

这个命令告诉 kubelet 在节点上运行 NGINX 应用程序。kubelet 调用 CRI 请求启动 NGINX 应用程序。在这时,实现了 CRI 规范的容器运行时必须执行以下步骤:

  1. 检查本地是否存在名为 nginx 的容器。如果没有,容器运行时会在容器仓库中搜索标准的容器镜像。
  2. 如果镜像不存在于本地,从容器仓库下载到本地系统。
  3. 使用容器存储系统(通常是写时拷贝存储系统)解析下载的容器镜像并挂载它。
  4. 使用标准的容器运行时执行容器。

让我们看看上述过程使用到的特性:

  1. OCI 镜像格式规范定义了容器仓库存储的标准镜像格式。
  2. Containers/image 代码库实现了从容器仓库拉取镜像到容器主机所需的所有特性。
  3. Containers/storage 提供了在写时拷贝的存储系统上探查并处理 OCI 镜像格式的代码库。
  4. OCI 运行时规范以及 runc 提供了执行容器的工具(同时也是 docker 守护进程用来运行容器的工具)。

这意味着我们可以利用这些工具来使用容器,而无需一个大型的容器守护进程。

在中等到大规模的基于 DevOps 的持续集成/持续交付环境下,效率、速度和安全性至关重要。只要你的工具遵循 OCI 规范,开发者和执行者就能在持续集成、持续交付到生产环境的自动化中自然地使用最佳的工具。大多数的容器工具被隐藏在容器编排或上层容器平台技术之下。我们预想着有朝一日,运行时和镜像工具的选择会变成容器平台的一个安装选项。

系统(独立)容器

在 Atomic 项目中我们引入了 原子主机 atomic host ,一种新的操作系统构建方式:所有的软件可以被“原子地”升级并且大多数应用以容器的形式运行在操作系统中。这个平台的目的是证明将来所有的软件都能部署在 OCI 镜像格式中并且使用标准协议从容器仓库中拉取,然后安装到系统上。用容器镜像的形式发布软件允许你以不同的速度升级应用程序和操作系统。传统的 RPM/yum/DNF 包分发方式把应用更新锁定在操作系统的生命周期中。

在以容器部署基础设施时多数会遇到一个问题——有时一些应用必须在容器运行时执行之前启动。我们看一个使用 docker 的 Kubernetes 的例子:Kubernetes 为了将 pods 或者容器部署在独立的网络中,要求先建立一个网络。现在默认用于创建网络的守护进程是 flanneld,而它必须在 docker 守护进程之前启动,以支持 docker 网络接口来运行 Kubernetes 的 pods。而且,flanneld 使用 etcd 来存储数据,这个守护进程必须在 flanneld 启动之前运行。

如果你想把 etcd 和 flanneld 部署到容器镜像中,那就陷入了鸡与鸡蛋的困境中。我们需要容器运行时来启动容器化的应用,但这些应用又需要在容器运行时之前启动。我见过几个取巧的方法尝试解决这个问题,但这些方法都不太干净利落。而且 docker 守护进程当前没有合适的方法来配置容器启动的优先级顺序。我见过一些提议,但它们看起来和 SysVInit 所使用的启动服务的方式相似(我们知道它带来的复杂度)。

systemd

用 systemd 替代 SysVInit 的原因之一就是为了处理服务启动的优先级和顺序,我们为什么不充分利用这种技术呢?在 Atomic 项目中我们决定在让它在没有容器运行时的情况下也能启动容器,尤其是在系统启动早期。我们增强了 atomic CLI 的功能,让用户可以安装容器镜像。当你执行 atomic install --system etc,它将利用 skopeo 从外部的容器仓库拉取 etcd 的 OCI 镜像,然后把它分解(扩展)为 OSTree 底层存储。因为 etcd 运行在生产环境中,我们把镜像处理为只读。接着 atomic 命令抓取容器镜像中的 systemd 的 unit 文件模板,用它在磁盘上创建 unit 文件来启动镜像。这个 unit 文件实际上使用 runc 来在主机上启动容器(虽然 runc 不是必需的)。

执行 atomic install --system flanneld 时会进行相似的过程,但是这时 flanneld 的 unit 文件中会指明它依赖 etcd。

在系统引导时,systemd 会保证 etcd 先于 flanneld 运行,并且直到 flanneld 启动完毕后再启动容器运行时。这样我们就能把 docker 守护进程和 Kubernetes 部署到系统容器当中。这也意味着你可以启动一台原子主机或者使用传统的基于 rpm 的操作系统,让整个容器编排工具栈运行在容器中。这是一个强大的特性,因为用户往往希望改动容器主机时不受这些组件影响。而且,它保持了主机的操作系统的占用最小化。

大家甚至讨论把传统的应用程序部署到独立/系统容器或者被编排的容器中。设想一下,可以用 atomic install --system httpd 命令安装一个 Apache 容器,这个容器可以和用 RPM 安装的 httpd 服务以相同的方式启动(systemctl start httpd ,区别是这个容器 httpd 运行在一个容器中)。存储系统可以是本地的,换言之,/var/www 是从宿主机挂载到容器当中的,而容器监听着本地网络的 80 端口。这表明了我们可以在不使用容器守护进程的情况下将传统的负载组件部署到一个容器中。

构建容器镜像

在我看来,在过去 4 年来容器发展方面最让人失落的是缺少容器镜像构建机制上的创新。容器镜像不过是将一些 tar 包文件与 JSON 文件一起打包形成的文件。基础镜像则是一个 rootfs 与一个描述该基础镜像的 JSON 文件。然后当你增加镜像层时,层与层之间的差异会被打包,同时 JSON 文件会做出相应修改。这些镜像层与基础文件一起被打包,共同构成一个容器镜像。

现在几乎所有人都使用 docker build 与 Dockerfile 格式来构建镜像。上游 docker 已经在几年前停止了接受修改或改进 Dockerfile 格式的拉取请求(PR)了。Dockerfile 在容器的演进过程中扮演了重要角色,开发者和管理员/运维人员可以通过简单直接的方式来构建镜像;然而我觉得 Dockerfile 就像一个简陋的 bash 脚本,还带来了一些尚未解决的问题,例如:

  • 使用 Dockerfile 创建容器镜像要求运行着 Docker 守护进程。

    • 没有可以独立于 docker 命令的标准工具用于创建 OCI 镜像。
    • 甚至类似 ansible-containers 和 OpenShift S2I (Source2Image) 的工具也在底层使用 docker-engine
  • Dockerfile 中的每一行都会创建一个新的镜像,这有助于创建容器的开发过程,这是因为构建工具能够识别 Dockerfile 中的未改动行,复用已经存在的镜像从而避免了未改动行的重复执行。但这个特性会产生大量的镜像层。

    • 因此,不少人希望构建机制能压制镜像消除这些镜像层。我猜想上游 docker 最后应该接受了一些提交满足了这个需求。
  • 要从受保护的站点拉取内容到容器镜像,你往往需要某种密钥。比如你为了添加 RHEL 的内容到镜像中,就需要访问 RHEL 的证书和订阅。

    • 这些密钥最终会被以层的方式保存在镜像中。开发者要费很大工夫去移除它们。
    • 为了允许在 docker 构建过程中挂载数据卷,我们在我们维护的 projectatomic/docker 中加入了 -v volume 选项,但是这些修改没有被上游 docker 接受。
  • 构建过程的中间产物最终会保留在容器镜像中,所以尽管 Dockerfile 易于学习,当你想要了解你要构建的镜像时甚至可以在笔记本上构建容器,但它在大规模企业环境下还不够高效。然而在自动化容器平台下,你应该不会关心用于构建 OCI 镜像的方式是否高效。

Buildah 起航

在 DevConf.cz 2017,我让我们团队的 Nalin Dahyabhai 考虑构建被我称为 containers-coreutils 的工具,它基本上就是基于 containers/storage 和 containers/image 库构建的一系列可以使用类似 Dockerfile 语法的命令行工具。Nalin 为了取笑我的波士顿口音,决定把它叫做 buildah。我们只需要少量的 buildah 原语就可以构建一个容器镜像:

  • 最小化 OS 镜像、消除不必要的工具是主要的安全原则之一。因为黑客在攻击应用时需要一些工具,如果类似 gccmakednf 这样的工具根本不存在,就能阻碍攻击者的行动。
  • 减小容器的体积总是有益的,因为这些镜像会通过互联网拉取与推送。
  • 使用 Docker 进行构建的基本原理是在容器构建的根目录下利用命令安装或编译软件。
  • 执行 run 命令要求所有的可执行文件都包含在容器镜像内。只是在容器镜像中使用 dnf 就需要完整的 Python 栈,即使在应用中从未使用到 Python。
  • ctr=$(buildah from fedora):

    • 使用 containers/image 从容器仓库拉取 Fedora 镜像。
    • 返回一个容器 ID (ctr)。
  • mnt=$(buildah mount $ctr):

    • 挂载新建的容器镜像($ctr).
    • 返回挂载点路径。
    • 现在你可以使用挂载点来写入内容。
  • dnf install httpd –installroot=$mnt:

    • 你可以使用主机上的命令把内容重定向到容器中,这样你可以把密钥保留在主机而不导入到容器内,同时构建所用的工具也仅仅存在于主机上。
    • 容器内不需要包含 dnf 或者 Python 栈,除非你的应用用到它们。
  • cp foobar $mnt/dir:

    • 你可以使用任何 bash 中可用的命令来构造镜像。
  • buildah commit $ctr:

    • 你可以随时创建一个镜像层,镜像的分层由用户而不是工具来决定。
  • buildah config --env container=oci --entrypoint /usr/bin/httpd $ctr:

    • Buildah 支持所有 Dockerfile 的命令。
  • buildah run $ctr dnf -y install httpd:

    • Buildah 支持 run 命令,但它是在一个锁定的容器内利用 runc 执行命令,而不依赖容器运行时守护进程。
  • buildah build-using-dockerfile -f Dockerfile .

    • 我们希望将移植类似 ansible-containers 和 OpenShift S2I 这样的工具,改用 buildah 以去除对容器运行时守护进程的依赖。
    • 使用与生产环境相同的容器运行时构建容器镜像会遇到另一个大问题。为了保证安全性,我们需要把权限限制到支持容器构建与运行所需的最小权限。构建容器比起运行容器往往需要更多额外的权限。举个例子,我们默认允许 mknod 权限,这会允许进程创建设备节点。有些包的安装会尝试创建设备节点,然而在生产环境中的应用几乎都不会这么做。如果默认移除生产环境中容器的 mknod 特权会让系统更为安全。
    • 另一个例子是,容器镜像默认是可读写的,因为安装过程意味着向 /usr 存入软件包。然而在生产环境中,我强烈建议把所有容器设为只读模式,仅仅允许它们写入 tmpfs 或者是挂载了数据卷的目录。通过分离容器的构建与运行环境,我们可以更改这些默认设置,提供一个更为安全的环境。
    • 当然,buildah 可以使用 Dockerfile 构建容器镜像。

CRI-O :一个 Kubernetes 的运行时抽象

Kubernetes 添加了 容器运行时接口 Container Runtime Interface (CRI)接口,使 pod 可以在任何运行时上工作。虽然我不是很喜欢在我的系统上运行太多的守护进程,然而我们还是加了一个。我的团队在 Mrunal Patel 的领导下于 2016 年后期开始构建 [CRI-O] 守护进程。这是一个用来运行 OCI 应用程序的 OCI 守护进程。理论上,将来我们能够把 CRI-O 的代码直接并入 kubelet 中从而消除这个多余的守护进程。

不像其它容器运行时,CRI-O 的唯一目的就只是为了满足 Kubernetes 的需求。记得前文描述的 Kubernetes 运行容器的条件。

Kubernetes 传递消息给 kubelet 告知其运行 NGINX 服务器:

  1. kubelet 唤醒 CRI-O 并告知它运行 NGINX。
  2. CRI-O 回应 CRI 请求。
  3. CRI-O 在容器仓库查找 OCI 镜像。
  4. CRI-O 使用 containers/image 从仓库拉取镜像到主机。
  5. CRI-O 使用 containers/storage 解压镜像到本地磁盘。
  6. CRI-O 按照 OCI 运行时规范(通常使用 runc)启动容器。如前文所述,Docker 守护进程也同样使用 runc 启动它的容器。
  7. 按照需要,kubelet 也可以使用替代的运行时启动容器,例如 Clear Containers runcv

CRI-O 旨在成为稳定的 Kubernetes 运行平台。只有通过完整的 Kubernetes 测试集后,新版本的 CRI-O 才会被推出。所有提交到 https://github.com/Kubernetes-incubator/cri-o 的拉取请求都会运行完整的 Kubernetes 测试集。没有通过测试集的拉取请求都不会被接受。CRI-O 是完全开放的,我们已经收到了来自 Intel、SUSE、IBM、Google、Hyper.sh 等公司的代码贡献。即使不是红帽想要的特性,只要通过一定数量维护者的同意,提交给 CRI-O 的补丁就会被接受。

小结

我希望这份深入的介绍能够帮助你理解 Linux 容器的演化过程。Linux 容器曾经陷入一种各自为营的困境,Docker 建立起了镜像创建的事实标准,简化了容器的使用工具。OCI 则意味着业界在核心镜像格式与运行时方面的合作,这促进了工具在自动化效率、安全性、高可扩展性、易用性方面的创新。容器使我们能够以一种新奇的方式部署软件——无论是运行于主机上的传统应用还是部署在云端的微服务。而在许多方面,这一切还仅仅是个开始。


作者简介:

Daniel J Walsh - Daniel 有将近 30 年的计算机安全领域工作经验。他在 2001 年 8 月加入 Red Hat。

via: https://opensource.com/article/17/7/how-linux-containers-evolved

作者:Daniel J Walsh 译者:haoqixu 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

应用程序的性能决定了软件能多快完成预期任务。这回答有关应用程序的几个问题,例如:

  • 峰值负载下的响应时间
  • 与替代方案相比,它易于使用,受支持的功能和用例
  • 运营成本(CPU 使用率、内存需求、数据吞吐量、带宽等)

该性能分析的价值超出了服务负载所需的计算资源或满足峰值需求所需的应用实例数量的估计。性能显然与成功企业的基本要素挂钩。它揭示了用户的总体体验,包括确定什么会拖慢客户预期的响应时间,通过设计满足带宽要求的内容交付来提高客户粘性,选择最佳设备,最终帮助企业发展业务。

问题

当然,这是对业务服务的性能工程价值的过度简化。为了理解在完成我刚刚所描述事情背后的挑战,让我们把它放到一个真实的稍微有点复杂的场景中。

现实世界的应用程序可能托管在云端。应用程序可以利用非常大(或概念上是无穷大)的计算资源。在硬件和软件方面的需求将通过云来满足。从事开发工作的开发人员将使用云交付功能来实现更快的编码和部署。云托管不是免费的,但成本开销与应用程序的资源需求成正比。

除了 搜索即服务 Search as a Service (SaaS)、 平台即服务 Platform as a Service (PaaS)、 基础设施即服务 Infrastructure as a Service (IaaS)以及 负载平衡即服务 Load Balancing as a Service (LBaaS)之外,当云端管理托管程序的流量时,开发人员可能还会使用这些快速增长的云服务中的一个或多个:

  • 安全即服务 Security as a Service (SECaaS),可满足软件和用户的安全需求
  • 数据即服务 Data as a Service (DaaS),为应用提供了用户需求的数据
  • 登录即服务 Logging as a Service (LaaS),DaaS 的近亲,提供了日志传递和使用的分析指标
  • 搜索即服务 Search as a Service (SaaS),用于应用程序的分析和大数据需求
  • 网络即服务 Network as a Service (NaaS),用于通过公共网络发送和接收数据

云服务也呈指数级增长,因为它们使得开发人员更容易编写复杂的应用程序。除了软件复杂性之外,所有这些分布式组件的相互作用变得越来越多。用户群变得更加多元化。该软件的需求列表变得更长。对其他服务的依赖性变大。由于这些因素,这个生态系统的缺陷会引发性能问题的多米诺效应。

例如,假设你有一个精心编写的应用程序,它遵循安全编码实践,旨在满足不同的负载要求,并经过彻底测试。另外假设你已经将基础架构和分析工作结合起来,以支持基本的性能要求。在系统的实现、设计和架构中建立性能标准需要做些什么?软件如何跟上不断变化的市场需求和新兴技术?如何测量关键参数以调整系统以获得最佳性能?如何使系统具有弹性和自我恢复能力?你如何更快地识别任何潜在的性能问题,并尽早解决?

进入容器

软件容器微服务设计或面向服务的架构(SoA)的优点为基础,提高了性能,因为包含更小的、自足的代码块的系统更容易编码,对其它系统组件有更清晰、定义良好的依赖。测试更容易,包括围绕资源利用和内存过度消耗的问题比在宏架构中更容易确定。

当扩容系统以增加负载能力时,容器应用程序的复制快速而简单。安全漏洞能更好地隔离。补丁可以独立版本化并快速部署。性能监控更有针对性,测量更可靠。你还可以重写和“改版”资源密集型代码,以满足不断变化的性能要求。

容器启动快速,停止也快速。它比虚拟机(VM)有更高效资源利用和更好的进程隔离。容器没有空闲内存和 CPU 闲置。它们允许多个应用程序共享机器,而不会丢失数据或性能。容器使应用程序可移植,因此开发人员可以构建并将应用程序发送到任何支持容器技术的 Linux 服务器上,而不必担心性能损失。容器生存在其内,并遵守其集群管理器(如 Cloud Foundry 的 Diego、Kubernetes、Apache Mesos 和 Docker Swarm)所规定的配额(比如包括存储、计算和对象计数配额)。

容器在性能方面表现出色,而即将到来的 “serverless” 计算(也称为 功能即服务 Function as a Service (FaaS))的浪潮将扩大容器的优势。在 FaaS 时代,这些临时性或短期的容器将带来超越应用程序性能的优势,直接转化为在云中托管的间接成本的节省。如果容器的工作更快,那么它的寿命就会更短,而且计算量负载纯粹是按需的。


作者简介:

Garima 是 Red Hat 的工程经理,专注于 OpenShift 容器平台。在加入 Red Hat 之前,Garima 帮助 Akamai Technologies&MathWorks Inc. 开创了创新。


via: https://opensource.com/article/17/2/performance-container-world

作者:Garima 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

CoreOS,一款最新的 Linux 发行版本,支持自动升级内核软件,提供各集群间配置的完全控制。

关于使用哪个版本的 Linux 服务器系统的争论,常常是以这样的话题开始的:

你是喜欢基于 Red Hat Enterprise Linux (RHEL)CentOS 或者 Fedora,还是基于 DebianUbuntu,抑或 SUSE 呢?

但是现在,一款名叫 CoreOS 容器 Linux 的 Linux 发行版加入了这场“圣战”。这个最近在 Linode 服务器上提供的 CoreOS,和它的老前辈比起来,它使用了完全不同的实现方法。

你可能会感到不解,这里有这么多成熟的 Linux 发行版本,为什么要选择用 CoreOS ?借用 Linux 主干分支的维护者,也是 CoreOS 顾问的 Greg Kroah-Hartman 先生的一句话:

CoreOS 可以控制发行版的升级(基于 ChromeOS 代码),并结合了 Docker 和潜在的核对/修复功能,这意味着不用停止或者重启你的相关进程,就可以在线升级。测试版本已经支持此功能,这是史无前例的。

当 Greg Kroah-Hartman 做出这段评价时,CoreOS 还处于 α 测试阶段,当时也许就是在硅谷的一个车库当中,开发团队正在紧锣密鼓地开发此产品,但 CoreOS 不像最开始的苹果或者惠普,其在过去的四年当中一直稳步发展。

当我参加在旧金山举办的 2017 CoreOS 大会时,CoreOS 已经支持谷歌云、IBM、AWS 和微软的相关服务。现在有超过 1000 位开发人员参与到这个项目中,并为能够成为这个伟大产品的一员而感到高兴。

究其原因,CoreOS 从开始就是为容器而设计的轻量级 Linux 发行版,其起初是作为一个 Docker 平台,随着时间的推移, CoreOS 在容器方面走出了自己的道路,除了 Docker 之外,它也支持它自己的容器 rkt (读作 rocket )。

不像大多数其他的 Linux 发行版,CoreOS 没有包管理器,取而代之的是通过 Google ChromeOS 的页面自动进行软件升级,这样能提高在集群上运行的机器/容器的安全性和可靠性。不用通过系统管理员的干涉,操作系统升级组件和安全补丁可以定期推送到 CoreOS 容器。

你可以通过 CoreUpdate 和它的 Web 界面上来修改推送周期,这样你就可以控制你的机器何时更新,以及更新以多快的速度滚动分发到你的集群上。

CoreOS 通过一种叫做 etcd 的分布式配置服务来进行升级,etcd 是一种基于 YAML 的开源的分布式哈希存储系统,它可以为 Linux 集群容器提供配置共享和服务发现等功能。

此服务运行在集群上的每一台服务器上,当其中一台服务器需要下线升级时,它会发起领袖选举,以便服务器更新时整个Linux 系统和容器化的应用可以继续运行。

对于集群管理,CoreOS 之前采用的是 fleet 方法,这将 etcd 和 systemd 结合到分布式初始化系统中。虽然 fleet 仍然在使用,但 CoreOS 已经将 etcd 加入到 Kubernetes 容器编排系统构成了一个更加强有力的管理工具。

CoreOS 也可以让你定制其它的操作系统相关规范,比如用 cloud-config 的方式管理网络配置、用户账号和 systemd 单元等。

综上所述,CoreOS 可以不断地自行升级到最新版本,能让你获得从单独系统到集群等各种场景的完全控制。如 CoreOS 宣称的,你再也不用为了改变一个单独的配置而在每一台机器上运行 Chef 了。

假如说你想进一步的扩展你的 DevOps 控制,CoreOS 能够轻松地帮助你部署 Kubernetes

CoreOS 从一开始就是构建来易于部署、管理和运行容器的。当然,其它的 Linux 发行版,比如 RedHat 家族的原子项目也可以达到类似的效果,但是对于那些发行版而言是以附加组件的方式出现的,而 CoreOS 从它诞生的第一天就是为容器而设计的。

当前容器和 Docker 已经逐渐成为商业系统的主流,如果在可预见的未来中你要在工作中使用容器,你应该考虑下 CoreOS,不管你的系统是在裸机硬件上、虚拟机还是云上。

如果有任何关于 CoreOS 的观点或者问题,还请在评论栏中留言。如果你觉得这篇博客还算有用的话,还请分享一下~


关于博主:Steven J. Vaughan-Nichols 是一位经验丰富的 IT 记者,许多网站中都刊登有他的文章,包括 ZDNet.comPC MagazineInfoWorldComputerWorldLinux TodayeWEEK 等。他拥有丰富的 IT 知识 - 而且他曾参加过智力竞赛节目 Jeopardy !他的相关观点都是自身思考的结果,并不代表 Linode 公司,我们对他做出的贡献致以最真诚的感谢。如果想知道他更多的信息,可以关注他的 Twitter @sjvn


via: https://medium.com/linode-cube/the-what-why-and-wow-behind-the-coreos-container-linux-fa7ceae5593c

作者:Steven J. Vaughan-Nichols 译者:吴霄/toyijiu 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出