标签 微服务 下的文章

微服务与容器天生匹配,但是你需要避开一些常见的陷阱。

因为微服务和容器是 天生的“一对”,所以一起来使用它们,似乎也就不会有什么问题。当我们将这对“天作之合”投入到生产系统后,你就会发现,随着你的 IT 基础的提升,等待你的将是大幅上升的成本。是不是这样的?

(让我们等一下,等人们笑声过去)

是的,很遗憾,这并不是你所希望的结果。虽然这两种技术的组合是非常强大的,但是,如果没有很好的规划和适配,它们并不能发挥出强大的性能来。在前面的文章中,我们整理了如果你想 使用它们你应该掌握的知识。但是,那些都是组织在容器中使用微服务时所遇到的常见问题。

事先了解这些可能出现的问题,能够帮你避免这些问题,为你的成功奠定更坚实的基础。

微服务和容器技术的出现是基于组织的需要、知识、资源等等更多的现实的要求。Mac Browning 说,“他们最常犯的一个 [错误] 是试图一次就想‘搞定’一切”,他是 DigitalOcean 的工程部经理。“而真正需要面对的问题是,你的公司应该采用什么样的容器和微服务。”

努力向你的老板和同事去解释什么是微服务?阅读我们的入门读本[如何简单明了地解释微服务。]

Browning 和其他的 IT 专业人员分享了他们遇到的,在组织中使用容器化微服务时的五个陷阱,特别是在他们的生产系统生命周期的早期时候。在你的组织中需要去部署微服务和容器时,了解这些知识,将有助于你去评估微服务和容器化的部署策略。

1、 在部署微服务和容器化上,试图同时从零开始

如果你刚开始从完全的单例应用开始改变,或者如果你的组织在微服务和容器化上还没有足够的知识储备,那么,请记住:微服务和容器化并不是拴在一起、不可分别部署的。这就意味着,你可以发挥你公司内部专家的技术特长,先从部署其中的一个开始。Sungard Availability Services]5 的资深 CTO 架构师 Kevin McGrath 建议,通过首先使用容器化来为你的团队建立知识和技能储备,通过对现有应用或者新应用进行容器化部署,接着再将它们迁移到微服务架构,这样才能最终感受到它们的优势所在。

McGrath 说,“微服务要想运行的很好,需要公司经过多年的反复迭代,这样才能实现快速部署和迁移”,“如果组织不能实现快速迁移,那么支持微服务将很困难。实现快速迁移,容器化可以帮助你,这样就不用担心业务整体停机”。

2、 从一个面向客户的或者关键的业务应用开始

对组织来说,一个相关陷阱恰恰就是从容器、微服务、或者两者同时起步:在尝试征服一片丛林中的雄狮之前,你应该先去征服处于食物链底端的一些小动物,以取得一些实践经验。

在你的学习过程中可以预期会有一些错误出现 —— 你是希望这些错误发生在面向客户的关键业务应用上,还是,仅对 IT 或者其他内部团队可见的低风险应用上?

DigitalOcean 的 Browning 说,“如果整个生态系统都是新的,为了获取一些微服务和容器方面的操作经验,那么,将它们先应用到影响面较低的区域,比如像你的持续集成系统或者内部工具,可能是一个低风险的做法。”你获得这方面的经验以后,当然会将这些技术应用到为客户提供服务的生产系统上。而现实情况是,不论你准备的如何周全,都不可避免会遇到问题,因此,需要提前为可能出现的问题制定应对之策。

3、 在没有合适的团队之前引入了太多的复杂性

由于微服务架构的弹性,它可能会产生复杂的管理需求。

作为 Red Hat 技术的狂热拥护者,Gordon Haff 最近写道,“一个符合 OCI 标准的容器运行时本身管理单个容器是很擅长的,但是,当你开始使用多个容器和容器化应用时,并将它们分解为成百上千个节点后,管理和编配它们将变得极为复杂。最终,你将需要回过头来将容器分组来提供服务 —— 比如,跨容器的网络、安全、测控”。

Haff 提示说,“幸运的是,由于容器是可移植的,并且,与之相关的管理栈也是可移植的”。“这时出现的编配技术,比如像 Kubernetes ,使得这种 IT 需求变得简单化了”(更多内容请查阅 Haff 的文章:容器化为编写应用带来的 5 个优势)。

另外,你需要合适的团队去做这些事情。如果你已经有 DevOps shop,那么,你可能比较适合做这种转换。因为,从一开始你已经聚集了相关技能的人才。

Mike Kavis 说,“随着时间的推移,部署了越来越多的服务,管理起来会变得很不方便”,他是 Cloud Technology Partners 的副总裁兼首席云架构设计师。他说,“在 DevOps 的关键过程中,确保各个领域的专家 —— 开发、测试、安全、运营等等 —— 全部都参与进来,并且在基于容器的微服务中,在构建、部署、运行、安全方面实现协作。”

4、 忽视重要的需求:自动化

除了具有一个合适的团队之外,那些在基于容器化的微服务部署比较成功的组织都倾向于以“实现尽可能多的自动化”来解决固有的复杂性。

Carlos Sanchez 说,“实现分布式架构并不容易,一些常见的挑战,像数据持久性、日志、排错等等,在微服务架构中都会变得很复杂”,他是 CloudBees 的资深软件工程师。根据定义,Sanchez 提到的分布式架构,随着业务的增长,将变成一个巨大无比的繁重的运营任务。“服务和组件的增殖,将使得运营自动化变成一项非常强烈的需求”。Sanchez 警告说。“手动管理将限制服务的规模”。

5、 随着时间的推移,微服务变得越来越臃肿

在一个容器中运行一个服务或者软件组件并不神奇。但是,这样做并不能证明你就一定在使用微服务。Manual Nedbal, ShieldX Networks 的 CTO,他警告说,IT 专业人员要确保,随着时间的推移,微服务仍然是微服务。

Nedbal 说,“随着时间的推移,一些软件组件积累了大量的代码和特性,将它们放在一个容器中将会产生并不需要的微服务,也不会带来相同的优势”,也就是说,“随着组件的变大,工程师需要找到合适的时机将它们再次分解”。


via: https://enterprisersproject.com/article/2017/9/using-microservices-containers-wisely-5-pitfalls-avoid

作者:Kevin Casey 译者:qhwdw 校对:wxy

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

云原生程序和基础架构需要完全不同的安全方式。牢记这些最佳实践

如今,大大小小的组织正在探索云原生技术的采用。“ 云原生 Cloud-native ”是指将软件打包到被称为容器的标准化单元中的方法,这些单元组织成微服务,它们必须对接以形成程序,并确保正在运行的应用程序完全自动化以实现更高的速度、灵活性和可伸缩性。

由于这种方法从根本上改变了软件的构建、部署和运行方式,它也从根本上改变了软件需要保护的方式。云原生程序和基础架构为安全专业人员带来了若干新的挑战,他们需要建立新的安全计划来支持其组织对云原生技术的使用。

让我们来看看这些挑战,然后我们将讨论安全团队应该采取的哪些最佳实践来解决这些挑战。首先挑战是:

  • 传统的安全基础设施缺乏容器可视性。 大多数现有的基于主机和网络的安全工具不具备监视或捕获容器活动的能力。这些工具是为了保护单个操作系统或主机之间的流量,而不是其上运行的应用程序,从而导致容器事件、系统交互和容器间流量的可视性缺乏。
  • 攻击面可以快速更改。云原生应用程序由许多较小的组件组​​成,这些组件称为微服务,它们是高度分布式的,每个都应该分别进行审计和保护。因为这些应用程序的设计是通过编排系统进行配置和调整的,所以其攻击面也在不断变化,而且比传统的独石应用程序要快得多。
  • 分布式数据流需要持续监控。容器和微服务被设计为轻量级的,并且以可编程方式与对方或外部云服务进行互连。这会在整个环境中产生大量的快速移动数据,需要进行持续监控,以便应对攻击和危害指标以及未经授权的数据访问或渗透。
  • 检测、预防和响应必须自动化。 容器生成的事件的速度和容量压倒了当前的安全操作流程。容器的短暂寿命也成为难以捕获、分析和确定事故的根本原因。有效的威胁保护意味着自动化数据收集、过滤、关联和分析,以便能够对新事件作出足够快速的反应。

面对这些新的挑战,安全专业人员将需要建立新的安全计划以支持其组织对云原生技术的使用。自然地,你的安全计划应该解决云原生程序的整个生命周期的问题,这些应用程序可以分为两个不同的阶段:构建和部署阶段以及运行时阶段。每个阶段都有不同的安全考虑因素,必须全部加以解决才能形成一个全面的安全计划。

确保容器的构建和部署

构建和部署阶段的安全性侧重于将控制应用于开发人员工作流程和持续集成和部署管道,以降低容器启动后可能出现的安全问题的风险。这些控制可以包含以下准则和最佳实践:

  • 保持镜像尽可能小。容器镜像是一个轻量级的可执行文件,用于打包应用程序代码及其依赖项。将每个镜像限制为软件运行所必需的内容, 从而最小化从镜像启动的每个容器的攻击面。从最小的操作系统基础镜像(如 Alpine Linux)开始,可以减少镜像大小,并使镜像更易于管理。
  • 扫描镜像的已知问题。当镜像构建后,应该检查已知的漏洞披露。可以扫描构成镜像的每个文件系统层,并将结果与​​定期更新的常见漏洞披露数据库(CVE)进行比较。然后开发和安全团队可以在镜像被用来启动容器之前解决发现的漏洞。
  • 数字签名的镜像。一旦建立镜像,应在部署之前验证它们的完整性。某些镜像格式使用被称为摘要的唯一标识符,可用于检测镜像内容何时发生变化。使用私钥签名镜像提供了加密的保证,以确保每个用于启动容器的镜像都是由可信方创建的。
  • 强化并限制对主机操作系统的访问。由于在主机上运行的容器共享相同的操作系统,因此必须确保它们以适当限制的功能集启动。这可以通过使用内核安全功能和 Seccomp、AppArmor 和 SELinux 等模块来实现。
  • 指定应用程序级别的分割策略。微服务之间的网络流量可以被分割,以限制它们彼此之间的连接。但是,这需要根据应用级属性(如标签和选择器)进行配置,从而消除了处理传统网络详细信息(如 IP 地址)的复杂性。分割带来的挑战是,必须事先定义策略来限制通信,而不会影响容器在环境内部和环境之间进行通信的能力,这是正常活动的一部分。
  • 保护容器所使用的秘密信息。微服务彼此相互之间频繁交换敏感数据,如密码、令牌和密钥,这称之为 秘密信息 secret 。如果将这些秘密信息存储在镜像或环境变量中,则可能会意外暴露这些。因此,像 Docker 和 Kubernetes 这样的多个编排平台都集成了秘密信息管理,确保只有在需要的时候才将秘密信息分发给使用它们的容器。

来自诸如 Docker、Red Hat 和 CoreOS 等公司的几个领先的容器平台和工具提供了部分或全部这些功能。开始使用这些方法之一是在构建和部署阶段确保强大安全性的最简单方法。

但是,构建和部署阶段控制仍然不足以确保全面的安全计划。提前解决容器开始运行之前的所有安全事件是不可能的,原因如下:首先,漏洞永远不会被完全消除,新的漏洞会一直出现。其次,声明式的容器元数据和网络分段策略不能完全预见高度分布式环境中的所有合法应用程序活动。第三,运行时控制使用起来很复杂,而且往往配置错误,就会使应用程序容易受到威胁。

在运行时保护容器

运行时阶段的安全性包括所有功能(可见性、检测、响应和预防),这些功能是发现和阻止容器运行后发生的攻击和策略违规所必需的。安全团队需要对安全事件的根源进行分类、调查和确定,以便对其进行全面补救。以下是成功的运行时阶段安全性的关键方面:

  • 检测整个​​环境以得到持续可见性。能够检测攻击和违规行为始于能够实时捕获正在运行的容器中的所有活动,以提供可操作的“真相源”。捕获不同类型的容器相关数据有各种检测框架。选择一个能够处理容器的容量和速度的方案至关重要。
  • 关联分布式威胁指标。 容器设计为基于资源可用性以跨计算基础架构而分布。由于应用程序可能由数百或数千个容器组成,因此危害指标可能分布在大量主机上,使得难以确定那些与主动威胁相关的相关指标。需要大规模,快速的相关性来确定哪些指标构成特定攻击的基础。
  • 分析容器和微服务行为。微服务和容器使得应用程序可以分解为执行特定功能的最小组件,并被设计为不可变的。这使得比传统的应用环境更容易理解预期行为的正常模式。偏离这些行为基准可能反映恶意行为,可用于更准确地检测威胁。
  • 通过机器学习增强威胁检测。容器环境中生成的数据量和速度超过了传统的检测技术。自动化和机器学习可以实现更有效的行为建模、模式识别和分类,从而以更高的保真度和更少的误报来检测威胁。注意使用机器学习的解决方案只是为了生成静态白名单,用于警报异常,这可能会导致严重的警报噪音和疲劳。
  • 拦截并阻止未经授权的容器引擎命令。发送到容器引擎(例如 Docker)的命令用于创建、启动和终止容器以及在正在运行的容器中运行命令。这些命令可以反映危害容器的意图,这意味着可以禁止任何未经授权的命令。
  • 自动响应和取证。容器的短暂寿命意味着它们往往只能提供很少的事件信息,以用于事件响应和取证。此外,云原生架构通常将基础设施视为不可变的,自动将受影响的系统替换为新系统,这意味着在调查时的容器可能会消失。自动化可以确保足够快地捕获、分析和升级信息,以减轻攻击和违规的影响。

基于容器技术和微服务架构的云原生软件正在迅速实现应用程序和基础架构的现代化。这种模式转变迫使安全专业人员重新考虑有效保护其组织所需的计划。随着容器的构建、部署和运行,云原生软件的全面安全计划将解决整个应用程序生命周期问题。通过使用上述指导方针实施计划,组织可以为容器基础设施以及运行在上面的应用程序和服务构建安全的基础。


作者:WeLien Dang 是 StackRox 的产品副总裁,StackRox 是一家为容器提供自适应威胁保护的安全公司。此前,他曾担任 CoreOS 产品负责人,并在亚马逊、Splunk 和 Bracket Computing 担任安全和云基础架构的高级产品管理职位。


via: https://www.infoworld.com/article/3233139/cloud-computing/how-cloud-native-applications-change-security.html

作者:Wei Lien Dang 译者:geekpi 校对:wxy

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

 title=

与互联网领域的领导们关于"容器"的讨论通常被总结如下:

作为一名 CxO,我面临杠杆时间术的持续的压力。IT 预算不断减少,我只有有限的资源。然而,交付的工作量却比以往更多。我花费太多的时间致力于解决预算的约束。另外,互联网的格局正在经历一个快速的改变,而且新的技术一直在被引进。我从我最信任的顾问那听来的最新的话题是一个“容器策略”的实现。我想理解:

  1. 什么是容器?
  2. 过渡到容器的企业价值是什么?
  3. 为什么我现在应该转移到容器?如果我不采纳会有一些坏处吗?
  4. 容器是否已经足够成熟用于企业消费?
  5. 我如何让我的企业因使用容器而快速地发展?

让我们从最开头开始。

容器

在过去的 10 年左右,企业已经从物理基础设施转向了虚拟机(VM)。转向 VM 的关键优势是可以减少数据中心的用量。通过在同一个物理机器上运行多个虚拟机,你可以在更少数量的物理机器上安装更多的应用程序。使用容器是另一种更轻量地打包应用程序的方式,而且其交付模式更快。它们是一种在单一的机器里运行多个应用程序进程的奇特方式,无论那个机器是一个虚拟机还是一个物理机。另外,容器在 DevOps 、微服务和云战略场景方面也扮演了重要角色。

容器 vs 虚拟机

容器和虚拟机在一些方面并不相同。一台虚拟机尽管不是物理机,但是它表现地就像是一台物理机。虚拟机是一个包含所有东西的独立的环境,是一个完整的(来宾)操作系统。在另一方面,容器是一个共享同一个物理机或虚拟机上资源的进程。容器显然更加有趣,因为:

  • 相比较而言,虚拟机要重一些,而容器更轻。因为容器只包括了它们所运行的程序所需要的库。
  • 虚拟机需要花费几分钟来启动,而容器在几秒钟内就可以启动。
  • 通常,相比虚拟机,你的基础设施中可以容纳更多的容器。

 title=

技术已经发展到足以保持这些容器安全、彼此独立,而且正确的设计选择可以保证那些坏掉的容器不会影响运行在同一个机器里的其他容器的性能。实际上,操作系统天生就是被用来构建成优化和运行容器的。

然而,当你转向容器时,你需要做出正确的选择。你需要做足够的尽职调查,以便你选择合适的技术合作伙伴和能够制作容器的制造商。开源技术起着很关键的作用。开源的 Docker 项目使得分层格式的容器很容易构建和使用。开放容器计划(OCI)已经成为被所有主要技术供应商所支持的开源容器标准。如 Red Hat 这样的开源技术提供商提供了为容器而准备的安全的操作系统。例如, Red Hat Enterprise Linux 7.x (包括 Red Hat Enterprise Linux 原子主机)进行了优化以原生地运行容器,同时也提供监控和管理容器的工具。其他的开源项目如来自 Tectonic 的 CoreOS 也正在进入市场。的确,容器正等着被企业所采用。

容器平台

容器平台让容器成为企业消耗品。在过去这些年中,你可能在你的企业里处理过虚拟机散乱的问题,容器散乱比那要糟糕好几倍。在你的数据中心横跨不同主机运行不同规模的容器,尽管容器故障仍然保证你的应用程序的高可用性,自动化健康检查和基于流入的工作载荷的自动化容器缩放等等,这些是你能期待容器平台应该有的一些关键特性。

当在一个被定位为容器即服务模型(CaaS)的平台上运行容器时,这些平台的一些其它特性如自动化生成和部署使这个平台成为平台即服务模型(PaaS)。虽然 CaaS 能让你规模化运行容器,但是,PaaS 可以让你利用你的源代码编译、创建容器,为你运行那些容器。另外,这些平台提供了完整操作管理特性,例如,集群的管理和监控、容器的安全缺陷检测,以及安全地运行容器、跟踪日志和度量等等。

尽管一些技术供应商正在使用他们的专有技术来构建容器平台,但总的来说,企业们正在围绕建立在 Kubernetes(K8S)的基础上的开源技术而进行标准化。K8S 是一项由 Google 发起的开源项目,现在很多大平台的供应商也支持它。K8S 也是云端原生计算基金会(CNCF)的一部分,CNCF 正在发展成以云为中心技术的标准体。当你在容器平台上做出选择时,围绕开源流程编排技术的标准化是非常重要的。它基本上允许你移植到不同的容器平台,如果你不喜欢你第一次做的选择的话。K8S 还允许你的容器工作载荷可跨越不同的公有云进行迁移。这些就是为什么我们会看到越来越多的技术公司正在使用 Kubernetes 的原因。

一些企业正在试图通过拼接几个包括 K8S 在内开源项目来打造他们自己 DIY 的容器平台。这确实是比继续跟随专有技术要更好的一种解决方案,但是要完成这项工作也仍然包含很多需要探讨的地方。然而,一个企业的维护和保持这样的 DIY 平台的能力应该被认真评估。许多企业并不是想做创建 IT 平台的工作,而是他们希望运行自己的主流业务。有很多可行的基于 K8S 的解决方案,比如红帽 OpenShift 平台容器ApprendaDeisRancher,它们提供一个企业级平台,这些解决方案中的每种都有不同完整程度的功能。

这些解决方案是由供应商认证和支持。有些方案是完全的开源 PaaS 解决方案,而另外一些可能是 CaaS。根据你的企业的需求,这些解决方案可能是比 DIY 容器平台更好的替代品。

企业的担忧和它们与容器的关系

今天,几乎每个企业都正在与数字时代转型打交道,这些转型影响包括 DevOps 战略、微服务和云等多个领域。容器在这些领域中的每一个中都起着相当重要的作用。

DevOps 策略

IT 组织被分成运维和应用开发,他们作为两个独立的团队运作,每一队都只有他们自己的一套目标。大多数企业为了将这两个团队联合起来正在朝 DevOps 的方向前进。

容器在 DevOps 倡议的成功中发挥着重要的作用。在 DevOps 中成功的关键标准之一是增加开发人员在运营中的份额。开发人员不仅应该把代码交给运维人员,而且他们还应该考虑他们的代码是如何在生产环境中运行的。普遍的技术是采用“架构即代码”,而不是提供几页容易出错的安装说明指示,开发团队应该提供像编程时的环境配置。

这恰恰就是容器可以解决的问题。可以作为容器的模版的容器镜像包括了从基本操作系统到应用程序代码的整个环境堆栈。利用容器,开发人员将不再只是从 Dev 到 QA 再到 Prod 这样生成应用程序;相反,他们将传递一个版本化的容器镜像,这个镜像包括生成的运行程序和它运行需要的环境。容器是包罗万象的,从操作系统库到中间件再到应用程序的所有东西都被整合进一个镜像里面。因此,容器在开发环境运行的方式和它在质量保证环境和生产环境下运行的方式完全一样。容器是 DevOps 成功的重要因素。

 title=

另外,容器平台正在进一步发展。典型的持续集成和交付(CICD)工具,如 Jenkins,可以作为容器,这个容器能在容器平台本身运行整个 CICD 过程,而不需要额外的基础设施。现在你可以使用 PaaS 平台来生成和运行你的 CICD 管道。

微服务策略

微服务是今天 IT 领域的另一个热门话题。应用程序是这样被设计的:把应用程序分解为离散化的小的服务,每个服务完成一个小任务。这些服务中的每一个都可以根据合适的技术用不同的编程语言进行编写。它们可以由小团队(双比萨团队)创建和管理,并且可以迅速地改变它们。所有这些要求再次需要用到容器。容器足够小到成为微服务的基础。容器能够支持任何你选择的技术和语言,容器易于创建和运行,并且可以快速地改变。微服务和容器现在已经不分彼此,如果有人说不使用容器来实现微服务,他们将会受到别人奇怪的表情。

实际情况是,虽然微服务有望让情况变得简单,但是它们的扩张也增加了复杂性。有几个微服务的设计和开发模式将能使它们易于实现。这意味着开发人员现在急需这样一个开发平台,在这个平台下,开发人员可以轻松地部署和组织微服务,而且还能:

  • 以一种语言不可知的方式实现这些微服务设计模式。
  • 不会因代码侵入而增加代码的复杂性,以便开发人员能将许多模式的代码包括进他们的业务逻辑中。
  • 足够灵活以便部署在你所选择的基础设施上,并且不会把你捆绑在特定的云上。

这就是选择一个正确的容器平台所起作用的地方。在具体的基础设施上按照某一特定供应商的方法来实现这些微服务将会把你的应用程序捆绑在那些供应商的平台上。使用类似兼容 OCI 的容器的容器化微服务将可以保证你的微服务能够被运行在任何兼容 OCI 的平台上。

选择正确的容器平台来运行你的微服务是需要做的另一个重要的决定。今天,有很少的选择和许多的 FUD。如果你作出选择时不足够慎重,其中一些选择会把你带到非标准的、特定供应商的路线上。

云策略

云战略是 IT 领域的又一个热门话题。无论你是否喜欢,服务化模型都是不可避免的变化。如果你不将其作为 IT 服务进行提供,你的开发团队将可能会找到创建“shadow IT”的方法来访问云。另外,尽管使用云技术将会让你从资本支出转移到运营支出,但是,管理云支出是一个不断的挑战。

云可以提供虚拟机,在你添加额外的虚拟机之前,你要确认这个云上的 CPU、内存和网络等资源都处于最佳使用状态。容器在这个地方扮演着很重要的角色。因为容器比虚拟机要小得多。并且,如果你的应用程序正运行在容器中,你可以在虚拟机中安装更多的容器,这比在每台虚拟机中运行一个应用程序组件要多很多。

公有云供应商有很多,其中 Amazon Web Services(AWS)、Microsoft Azure 和 Google Cloud 最受欢迎。另外,你可能想在你的基于 OpenStack 的数据中心里拥有你自己的私有云。这些云环境中的每一个都有它们自己的协议、API 和工具。当你想让你的应用程序在云上运行时,你不会想要让您的应用编排被云供应商所制约,也不会想要维护任何特定云的代码。在你的技术上与特定的云供应商锁定就像在未来几年内向供应商签署空白支票。

云的可移植性对您的云战略至关重要。你可以编写应用程序,而不用担心它们在哪里运行,容器平台可以将你和特定的云供应商协议隔离开来,从而避免你与一个云供应商锁定。

传统系统

微服务架构带给开发的优势很多,但并不是每个应用程序都可以重构它们自己,有些只能重构一部分。传统的应用程序被普遍接受,它们需要维护和管理。虽然容器可以实现微服务,但容器不仅仅只是微服务。可以想象,你可以将大型应用程序和微服务作为容器来运行,因此只要你选择正确的容器技术和正确的应用程序平台,就可以将许多(如果不是所有)的传统的应用程序作为容器运行。

总结

我希望这篇对各种策略和容器的深入剖析有助于你的公司对下一步进行评估。让我在评论里面了解您公司学习到的经验,或者说没能大步向前跨越,他们还需要我再提供一些什么信息。

(题图来源:Maersk Line. CC SA-BY 4.0


作者简介:

Veer Muchandi -- 开源爱好者,容器和PaaS倡导者,喜欢学习和分享。


via: https://opensource.com/article/17/1/container-strategy-for-executives

作者:Veer Muchandi 译者:zhousiyu325 校对:wxy

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

我们对微服务的需求可以归纳为一个词:速度。这种更快提供功能完善且可靠的软件的需求,彻底改变了软件开发模式。毫无疑问,这个改变对软件管理,包括系统监控的方式,都产生了影响。在这篇文章里,我们将重点关注放在有效地监控产品环境中的微服务所需做出的主要改变。我们将为这一新的软件架构拟定 5 条指导性原则来调整你的监控方法。

监控是微服务控制系统的关键部分,你的软件越复杂,那么你就越难了解其性能及问题排障。鉴于软件交付发生的巨大改变,监控系统同样需要进行彻底的改造,以便在微服务环境下表现更好。下面我们将介绍监控微服务的 5 条原则,如下:

  1. 监控容器及其里面的东西。
  2. 在服务性能上做监控,而不是容器性能。
  3. 监控弹性和多地部署的服务。
  4. 监控 API。
  5. 将您的监控映射到您的组织结构。

利用这 5 条原则,你可以在向微服务前进的道路上,建立更有效的对微服务的监控。这些原则,可以让你应对随着微服务而来的技术变化和组织变化。

微服务监控的原则

1、监控容器及其里面的东西

容器因构建微服务而凸显其重要性,容器的速度、可移植性和隔离特性让开发者很容易就爱上了微服务模型。容器的好处已经写的够多了,毋庸赘述。

容器对于其外围的系统来说就像是黑盒子。这对于开发来说大有裨益,从开发环境到生产环境,甚至从开发者的笔记本到云端,为它们带来高度的可移植性。但是当运行起来后,监控和解决服务问题时,这个黑盒子让常规的方法难以奏效了,我们会想:容器里到底在运行着什么?程序和代码运行性能如何?它有什么重要的输出指标吗?从 DevOps 的视角,你需要对容器有更深的了解而不是仅仅知道有一些容器的存在。

非容器环境下衡量的典型做法,是让一个代理程序运行在主机或者虚机上的用户空间里,但这并不适用于容器。因为容器的优点是小,将各种进程分离开来,并尽可能的减少依赖关系。

而且,从规模上看,成千上万的监测代理,对即使是一个中等大小的部署都是一个昂贵的资源浪费和管理的噩梦。对于容器有两个潜在的解决方案:1)要求你的开发人员直接监控他们的代码,或者2)利用一个通用的内核级的检测方法来查看主机上的所有应用程序和容器活动。这里我们不会深入说明,但每一种方法都有其优点和缺点。

2、 利用业务流程系统提醒服务性能

理解容器容器中的运行数据并不容易,一个单一容器相比组成一个功能或服务的容器聚合,测量复杂度要低得多。

这特别适用于应用程序级别的信息,比如哪个请求拥有最短响应时间,或者哪些 URL 遇到最多的错误,但它同样也适用于架构级别的监测,比如哪个服务的容器使用 CPU 资源超过了事先分配的资源数。

越来越多的软件部署需要一个 编排系统 orchestration system ,将应用程序的逻辑规划转化到物理的容器中。常见的编排系统包括 Kubernetes、Mesosphere DC/OS 和 Docker Swarm。团队可以用一个编排系统来(1)定义微服务(2)理解部署的每个服务的当前状态。你可以认为编排系统甚至比容器还重要。容器是短暂的,只有满足你的服务需求才会存在。

DevOps 团队应该将告警重点放到运行特征上,以尽可能贴近监控服务的体验。如果应用受到了影响,这些告警是评估事态的第一道防线。但是获得这些告警并不容易,除非你的监控系统是基于原生于容器的。

原生容器 Container-native 解决方案利用 编排元数据 orchestration metadata 来动态聚合容器和应用程序数据,并按每个服务计算监控度量。根据您的编排工具,您可能想在不同层次进行深入检测。比如,在 Kubernetes 里,你通常有 Namespace、ReplicaSet、Pod 和一些其他容器。聚合这些不同的层,对排除逻辑故障是很有必要的,与构成服务的容器的物理部署无关。

3、 监控 弹性 Elastic 多地部署 Multi-Location 的服务

弹性服务不是一个新概念,但是它在原生容器环境中的变化速度比在虚拟环境中快的多。迅速的变化会严重影响检测系统的正常运行。

监测传统的系统经常需要根据软件部署,手动调整检查指标。这种调整可以是具体的,如定义要捕获的单个指标,或基于应用程序在一个特定的容器中的操作配置要收集的数据。在小规模上(比如几十个容器)我们可以接受,但是再大规模就难以承受了。微服务的集中监控必须能够自由的随弹性服务而增长和缩减,无需人工干预。

比如,如果 DevOps 团队必须手动定义容器包含哪个服务需要监控,他们毫无疑问会失手,因为 Kubernetes 或者 Mesos 每天都会定期创建新的容器。同样,如果代码发布并置于生产环境时要求运维团队安装一个 定制的状态端点 custom stats endpoint ,也给开发者从 Docker 仓库获取基础镜像带来更多的挑战。

在生产环境中,建立面向跨越多个数据中心或多个云的复杂部署的监控,比如,如果你的服务跨越私有数据中心和 AWS,那么亚马逊的 AWS CloudWatch 就很难做到这一点。这就要求我们建立一个跨不同地域的监控系统,并可在动态的原生容器环境下运行。

4、 监控 API

在微服务环境中,API 接口是通用的。本质上,它们是将服务暴露给其它团队的唯一组件。事实上,API 的响应和一致性可以看作是“内部 SLA”,即使还没有定义一个正式的 SLA(服务等级协议)。

因此,API 接口的监控也是必要的。API 监控可以有不同的形式,但是很显然它绝对不是简单的二进制上下检查。例如,了解像时间函数这样的最常使用的 端点 endpoint 是有价值的。这使得团队可以看到服务使用的变化,无论是由于设计变更或用户的改变。

你也可以记录服务最缓慢的端点,这些可能揭示出重大的问题,或者至少指向需要在系统中做优化的区域。

最后,跟踪系统服务响应的能力是另一个很重要的能力,它主要是开发者使用,也能帮助你了解整体用户体验,同时将信息基于底层和应用程序视角分成两大部分。

5、 将您的监控映射到您的组织结构

这篇文章着重在微服务和监控上,像其他科技文章一样,这是因为很多人都关注此层面。

对于那些熟悉 康威定律 Conway’s law 的人来说,系统的设计是基于开发团队的组织结构。创造更快,更敏捷的软件的压力推动了团队去思考重新调整他们的开发组织和管理它的规则。

所以,如果他们想从这个新的软件架构(微服务)上获益,他们的团队必须将微服务映射到团队自身中。也就是说,他们需要更小的更松散耦合的团队,可以选择自己的方向只要能够满足整个需求即可。在每一个团队中,对于开发语言的使用,bug 的提交甚至工作职责都会有更大的控制能力。

DevOps 团队对此可以启用一个监控平台:让每一个微服务团队可以有自己的警报,度量指标,和控制面板,同时也要给出整体系统的视图。

总结

让微服务流行起来的是快捷。开发组织要想更快的为客户提供更多的功能,然后微服务技术就来了,架构转向微服务并且容器的流行让快捷开发成为可能,所有相关的进程理所当然的搭上了这辆火车。

最后,基本的监控原则需要适应伴随微服务而来的技术和结构。越早认识到这种转变的开发团队,能更早更容易的适应微服务这一新的架构。


via: http://thenewstack.io/five-principles-monitoring-microservices/

作者:Apurva DaveLoris Degioanni 译者:jiajia9linuxer 校对:jasminepeng

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

"微服务是一股新浪潮" - 现如今,将项目拆分成多个独立的、可扩展的服务是保障代码演变的最好选择。在 Python 的世界里,有个叫做 “Nameko” 的框架,它将微服务的实现变得简单并且强大。

微服务

在最近的几年里,“微服务架构”如雨后春笋般涌现。它用于描述一种特定的软件应用设计方式,这种方式使得应用可以由多个独立部署的服务以服务套件的形式组成。 - M. Fowler

推荐各位读一下 Fowler 的文章 以理解它背后的原理。

好吧,那它究竟意味着什么呢?

简单来说,微服务架构可以将你的系统拆分成多个负责不同任务的小的(单一上下文内) 功能块 responsibilities blocks ,它们彼此互无感知,各自只提供用于通讯的 通用指向 common point 。这个指向通常是已经将通讯协议和接口定义好的消息队列。

这里给大家提供一个真实案例

案例的代码可以通过 github: http://github.com/rochacbruno/nameko-example 访问,查看 service 和 api 文件夹可以获取更多信息。

想象一下,你有一个 REST API ,这个 API 有一个端点(LCTT 译注:REST 风格的 API 可以有多个端点用于处理对同一资源的不同类型的请求)用来接受数据,并且你需要将接收到的数据进行一些运算工作。那么相比阻塞接口调用者的请求来说,异步实现此接口是一个更好的选择。你可以先给用户返回一个 "OK - 你的请求稍后会处理" 的状态,然后在后台任务中完成运算。

同样,如果你想要在不阻塞主进程的前提下,在计算完成后发送一封提醒邮件,那么将“邮件发送”委托给其他服务去做会更好一些。

场景描述

用代码说话

让我们将系统创建起来,在实践中理解它:

环境

我们需要的环境:

  • 运行良好的 RabbitMQ(LCTT 译注:RabbitMQ 是一个流行的消息队列实现)
  • 由 VirtualEnv 提供的 Services 虚拟环境
  • 由 VirtualEnv 提供的 API 虚拟环境

Rabbit

在开发环境中使用 RabbitMQ 最简单的方式就是运行其官方的 docker 容器。在你已经拥有 Docker 的情况下,运行:

docker run -d --hostname my-rabbit --name some-rabbit -p 15672:15672 -p 5672:5672 rabbitmq:3-management

在浏览器中访问 http://localhost:15672 ,如果能够使用 guest:guest 验证信息登录 RabbitMQ 的控制面板,说明它已经在你的开发环境中运行起来了。

服务环境

现在让我们创建微服务来满足我们的任务需要。其中一个服务用来执行计算任务,另一个用来发送邮件。按以下步骤执行:

在 Shell 中创建项目的根目录

$ mkdir myproject
$ cd myproject

用 virtualenv 工具创建并且激活一个虚拟环境(你也可以使用 virtualenv-wrapper)

$ virtualenv service_env
$ source service_env/bin/activate

安装 nameko 框架和 yagmail

(service_env)$ pip install nameko
(service_env)$ pip install yagmail

服务的代码

现在我们已经准备好了 virtualenv 所提供的虚拟环境(可以想象成我们的服务是运行在一个独立服务器上的,而我们的 API 运行在另一个服务器上),接下来让我们编码,实现 nameko 的 RPC 服务。

我们会将这两个服务放在同一个 python 模块中,当然如果你乐意,也可以把它们放在单独的模块里并且当成不同的服务运行:

在名为 service.py 的文件中

import yagmail
from nameko.rpc import rpc, RpcProxy

class Mail(object):
    name = "mail"

    @rpc
    def send(self, to, subject, contents):
        yag = yagmail.SMTP('[email protected]', 'mypassword')
        # 以上的验证信息请从安全的地方进行读取
        # 贴士: 可以去看看 Dynaconf 设置模块
        yag.send(to=to.encode('utf-8), 
                 subject=subject.encode('utf-8), 
                 contents=[contents.encode('utf-8)])

class Compute(object):
    name = "compute"
    mail = RpcProxy('mail')    

    @rpc
    def compute(self, operation, value, other, email):
        operations = {'sum': lambda x, y: int(x) + int(y),
                      'mul': lambda x, y: int(x) * int(y),
                      'div': lambda x, y: int(x) / int(y),
                      'sub': lambda x, y: int(x) - int(y)}
        try:
            result = operations[operation](value, other)
        except Exception as e:
            self.mail.send.async(email, "An error occurred", str(e))
            raise
        else:
            self.mail.send.async(
                email, 
                "Your operation is complete!", 
                "The result is: %s" % result
            )
            return result

现在我们已经用以上代码定义好了两个服务,下面让我们将 Nameko RPC service 运行起来。

注意:我们会在控制台中启动并运行它。但在生产环境中,建议大家使用 supervisord 替代控制台命令。

在 Shell 中启动并运行服务

(service_env)$ nameko run service --broker amqp://guest:guest@localhost
starting services: mail, compute
Connected to amqp://guest:**@127.0.0.1:5672//
Connected to amqp://guest:**@127.0.0.1:5672//

测试

在另外一个 Shell 中(使用相同的虚拟环境),用 nameko shell 进行测试:

(service_env)$ nameko shell --broker amqp://guest:guest@localhost
Nameko Python 2.7.9 (default, Apr  2 2015, 15:33:21) 
[GCC 4.9.2] shell on linux2
Broker: amqp://guest:guest@localhost
>>>

现在你已经处在 RPC 客户端中了,Shell 的测试工作是通过 n.rpc 对象来进行的,它的使用方法如下:

>>> n.rpc.mail.send("[email protected]", "testing", "Just testing")

上边的代码会发送一封邮件,我们同样可以调用计算服务对其进行测试。需要注意的是,此测试还会附带进行异步的邮件发送。

>>> n.rpc.compute.compute('sum', 30, 10, "[email protected]")
40
>>> n.rpc.compute.compute('sub', 30, 10, "[email protected]")
20
>>> n.rpc.compute.compute('mul', 30, 10, "[email protected]")
300
>>> n.rpc.compute.compute('div', 30, 10, "[email protected]")
3

在 API 中调用微服务

在另外一个 Shell 中(甚至可以是另外一台服务器上),准备好 API 环境。

用 virtualenv 工具创建并且激活一个虚拟环境(你也可以使用 virtualenv-wrapper)

$ virtualenv api_env
$ source api_env/bin/activate

安装 Nameko、 Flask 和 Flasgger

(api_env)$ pip install nameko
(api_env)$ pip install flask
(api_env)$ pip install flasgger
注意: 在 API 中并不需要 yagmail ,因为在这里,处理邮件是服务的职责

创建含有以下内容的 api.py 文件:

from flask import Flask, request
from flasgger import Swagger
from nameko.standalone.rpc import ClusterRpcProxy

app = Flask(__name__)
Swagger(app)
CONFIG = {'AMQP_URI': "amqp://guest:guest@localhost"}


@app.route('/compute', methods=['POST'])
def compute():
    """
    Micro Service Based Compute and Mail API
    This API is made with Flask, Flasgger and Nameko
    ---
    parameters:
      - name: body
        in: body
        required: true
        schema:
          id: data
          properties:
            operation:
              type: string
              enum:
                - sum
                - mul
                - sub
                - div
            email:
              type: string
            value:
              type: integer
            other:
              type: integer
    responses:
      200:
        description: Please wait the calculation, you'll receive an email with results
    """
    operation = request.json.get('operation')
    value = request.json.get('value')
    other = request.json.get('other')
    email = request.json.get('email')
    msg = "Please wait the calculation, you'll receive an email with results"
    subject = "API Notification"
    with ClusterRpcProxy(CONFIG) as rpc:
        # asynchronously spawning and email notification
        rpc.mail.send.async(email, subject, msg)
        # asynchronously spawning the compute task
        result = rpc.compute.compute.async(operation, value, other, email)
        return msg, 200

app.run(debug=True)

在其他的 shell 或者服务器上运行此文件

(api_env) $ python api.py 
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

然后访问 http://localhost:5000/apidocs/index.html 这个 url,就可以看到 Flasgger 的界面了,利用它可以进行 API 的交互并可以发布任务到队列以供服务进行消费。

注意: 你可以在 shell 中查看到服务的运行日志,打印信息和错误信息。也可以访问 RabbitMQ 控制面板来查看消息在队列中的处理情况。

Nameko 框架还为我们提供了很多高级特性,你可以从 https://nameko.readthedocs.org/en/stable/ 获取更多的信息。

别光看了,撸起袖子来,实现微服务!


via: http://brunorocha.org/python/microservices-with-python-rabbitmq-and-nameko.html

作者: Bruno Rocha 译者: mr-ping 校对: wxy

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

我的上一篇文章里, 我介绍了 Linux 容器背后的技术的概念。我写了我知道的一切。容器对我来说也是比较新的概念。我写这篇文章的目的就是鼓励我真正的来学习这些东西。

我打算在使用中学习。首先实践,然后上手并记录下我是怎么走过来的。我假设这里肯定有很多像 "Hello World" 这种类型的知识帮助我快速的掌握基础。然后我能够更进一步,构建一个微服务容器或者其它东西。

我想,它应该不会有多难的。

但是我错了。

可能对某些人来说这很简单,因为他们在运维工作方面付出了大量的时间。但是对我来说实际上是很困难的,可以从我在Facebook 上的状态展示出来的挫折感就可以看出了。

但是还有一个好消息:我最终搞定了。而且它工作的还不错。所以我准备分享向你分享我如何制作我的第一个微服务容器。我的痛苦可能会节省你不少时间呢。

如果你曾经发现你也处于过这种境地,不要害怕:像我这样的人都能搞定,所以你也肯定行。

让我们开始吧。

一个缩略图微服务

我设计的微服务在理论上很简单。以 JPG 或者 PNG 格式在 HTTP 终端发布一张数字照片,然后获得一个100像素宽的缩略图。

下面是它的流程:

container-diagram-0

我决定使用 NodeJS 作为我的开发语言,使用 ImageMagick 来转换缩略图。

我的服务的第一版的逻辑如下所示:

container-diagram-1

我下载了 Docker Toolbox,用它安装了 Docker 的快速启动终端(Docker Quickstart Terminal)。Docker 快速启动终端使得创建容器更简单了。终端会启动一个装好了 Docker 的 Linux 虚拟机,它允许你在一个终端里运行 Docker 命令。

虽然在我的例子里,我的操作系统是 Mac OS X。但是 Windows 下也有相同的工具。

我准备使用 Docker 快速启动终端里为我的微服务创建一个容器镜像,然后从这个镜像运行容器。

Docker 快速启动终端就运行在你使用的普通终端里,就像这样:

container-diagram-2

第一个小问题和第一个大问题

我用 NodeJS 和 ImageMagick 瞎搞了一通,然后让我的服务在本地运行起来了。

然后我创建了 Dockerfile,这是 Docker 用来构建容器的配置脚本。(我会在后面深入介绍构建过程和 Dockerfile)

这是我运行 Docker 快速启动终端的命令:

$ docker build -t thumbnailer:0.1

获得如下回应:

docker: "build" requires 1 argument.

呃。

我估摸着过了15分钟我才反应过来:我忘记了在末尾参数输入一个点.

正确的指令应该是这样的:

$ docker build -t thumbnailer:0.1 .

但是这不是我遇到的最后一个问题。

我让这个镜像构建好了,然后我在 Docker 快速启动终端输入了 run 命令来启动容器,名字叫 thumbnailer:0.1:

$ docker run -d -p 3001:3000 thumbnailer:0.1

参数 -p 3001:3000 让 NodeJS 微服务在 Docker 内运行在端口3000,而绑定在宿主主机上的3001。

到目前看起来都很好,对吧?

错了。事情要马上变糟了。

我通过运行 docker-machine 命令为这个 Docker 快速启动终端里创建的虚拟机指定了 ip 地址:

$ docker-machine ip default

这句话返回了默认虚拟机的 IP 地址,它运行在 Docker 快速启动终端里。在我这里,这个 ip 地址是 192.168.99.100。

我浏览网页 http://192.168.99.100:3001/ ,然后找到了我创建的上传图片的网页:

container-diagram-3

我选择了一个文件,然后点击上传图片的按钮。

但是它并没有工作。

终端告诉我他无法找到我的微服务需要的 /upload 目录。

现在,你要知道,我已经在此耗费了将近一天的时间-从浪费时间到研究问题。我此时感到了一些挫折感。

然后灵光一闪。某人记起来微服务不应该自己做任何数据持久化的工作!保存数据应该是另一个服务的工作。

所以容器找不到目录 /upload 的原因到底是什么?这个问题的根本就是我的微服务在基础设计上就有问题。

让我们看看另一幅图:

container-diagram-4

我为什么要把文件保存到磁盘?微服务按理来说是很快的。为什么不能让我的全部工作都在内存里完成?使用内存缓冲可以解决“找不到目录”这个问题,而且可以提高我的应用的性能。

这就是我现在所做的。下面是我的计划:

container-diagram-5

这是我用 NodeJS 写的在内存运行、生成缩略图的代码:

// Bind to the packages
var express = require('express');
var router = express.Router();
var path = require('path'); // used for file path
var im = require("imagemagick");

// Simple get that allows you test that you can access the thumbnail process
router.get('/', function (req, res, next) {
 res.status(200).send('Thumbnailer processor is up and running');
});

// This is the POST handler. It will take the uploaded file and make a thumbnail from the 
// submitted byte array. I know, it's not rocket science, but it serves a purpose
router.post('/', function (req, res, next) {
 req.pipe(req.busboy);
 req.busboy.on('file', function (fieldname, file, filename) {
   var ext = path.extname(filename)

   // Make sure that only png and jpg is allowed 
   if(ext.toLowerCase() != '.jpg' && ext.toLowerCase() != '.png'){
     res.status(406).send("Service accepts only jpg or png files");
   }

   var bytes = [];

   // put the bytes from the request into a byte array 
   file.on('data', function(data) {
     for (var i = 0; i < data.length; ++i) {
       bytes.push(data[i]);
     }
     console.log('File [' + fieldname + '] got bytes ' + bytes.length + ' bytes');
   });

   // Once the request is finished pushing the file bytes into the array, put the bytes in 
   // a buffer and process that buffer with the imagemagick resize function
   file.on('end', function() {
     var buffer = new Buffer(bytes,'binary');
     console.log('Bytes  got ' + bytes.length + ' bytes');

     //resize
     im.resize({
         srcData: buffer,
         height: 100
     }, function(err, stdout, stderr){
       if (err){
         throw err;
       }
       // get the extension without the period
       var typ = path.extname(filename).replace('.','');
       res.setHeader("content-type", "image/" + typ);
       res.status(200);
       // send the image back as a response
       res.send(new Buffer(stdout,'binary'));
     });
   });
 });
});

module.exports = router;

好了,一切回到了正轨,已经可以在我的本地机器正常工作了。我该去休息了。

但是,在我测试把这个微服务当作一个普通的 Node 应用运行在本地时...

Containers Hard

它工作的很好。现在我要做的就是让它在容器里面工作。

第二天我起床后喝点咖啡,然后创建一个镜像——这次没有忘记那个"."!

$ docker build -t thumbnailer:01 .

我从缩略图项目的根目录开始构建。构建命令使用了根目录下的 Dockerfile。它是这样工作的:把 Dockerfile 放到你想构建镜像的地方,然后系统就默认使用这个 Dockerfile。

下面是我使用的Dockerfile 的内容:

FROM ubuntu:latest
MAINTAINER [email protected]

RUN apt-get update
RUN apt-get install -y nodejs nodejs-legacy npm
RUN apt-get install imagemagick libmagickcore-dev libmagickwand-dev
RUN apt-get clean

COPY ./package.json src/

RUN cd src && npm install

COPY . /src

WORKDIR src/

CMD npm start

这怎么可能出错呢?

第二个大问题

我运行了 build 命令,然后出了这个错:

Do you want to continue? [Y/n] Abort.

The command '/bin/sh -c apt-get install imagemagick libmagickcore-dev libmagickwand-dev' returned a non-zero code: 1

我猜测微服务出错了。我回到本地机器,从本机启动微服务,然后试着上传文件。

然后我从 NodeJS 获得了这个错误:

Error: spawn convert ENOENT

怎么回事?之前还是好好的啊!

我搜索了我能想到的所有的错误原因。差不多4个小时后,我想:为什么不重启一下机器呢?

重启了,你猜猜结果?错误消失了!(LCTT 译注:万能的“重启试试”)

继续。

将精灵关进瓶子里

跳回正题:我需要完成构建工作。

我使用 rm 命令删除了虚拟机里所有的容器。

$ docker rm -f $(docker ps -a -q)

-f 在这里的用处是强制删除运行中的镜像。

然后删除了全部 Docker 镜像,用的是命令 rmi:

$ docker rmi if $(docker images | tail -n +2 | awk '{print $3}')

我重新执行了重新构建镜像、安装容器、运行微服务的整个过程。然后过了一个充满自我怀疑和沮丧的一个小时,我告诉我自己:这个错误可能不是微服务的原因。

所以我重新看到了这个错误:

Do you want to continue? [Y/n] Abort.

The command '/bin/sh -c apt-get install imagemagick libmagickcore-dev libmagickwand-dev' returned a non-zero code: 1

这太打击我了:构建脚本好像需要有人从键盘输入 Y! 但是,这是一个非交互的 Dockerfile 脚本啊。这里并没有键盘。

回到 Dockerfile,脚本原来是这样的:

RUN apt-get update
RUN apt-get install -y nodejs nodejs-legacy npm
RUN apt-get install imagemagick libmagickcore-dev libmagickwand-dev
RUN apt-get clean

第二个apt-get 忘记了-y 标志,它用于自动应答提示所需要的“yes”。这才是错误的根本原因。

我在这条命令后面添加了-y

RUN apt-get update
RUN apt-get install -y nodejs nodejs-legacy npm
RUN apt-get install -y imagemagick libmagickcore-dev libmagickwand-dev
RUN apt-get clean

猜一猜结果:经过将近两天的尝试和痛苦,容器终于正常工作了!整整两天啊!

我完成了构建工作:

$ docker build -t thumbnailer:0.1 .

启动了容器:

$ docker run -d -p 3001:3000 thumbnailer:0.1

获取了虚拟机的IP 地址:

$ docker-machine ip default

在我的浏览器里面输入 http://192.168.99.100:3001/

上传页面打开了。

我选择了一个图片,然后得到了这个:

container-diagram-7

工作了!

在容器里面工作了,我的第一次啊!

这让我学到了什么?

很久以前,我接受了这样一个道理:当你刚开始尝试某项技术时,即使是最简单的事情也会变得很困难。因此,我不会把自己当成最聪明的那个人,然而最近几天尝试容器的过程就是一个充满自我怀疑的旅程。

但是你想知道一些其它的事情吗?这篇文章是我在凌晨2点完成的,而每一个受折磨的时刻都值得了。为什么?因为这段时间你将自己全身心投入了喜欢的工作里。这件事很难,对于所有人来说都不是很容易就获得结果的。但是不要忘记:你在学习技术,运行世界的技术。

P.S. 了解一下Hello World 容器的两段视频,这里会有 Raziel Tabib’s 的精彩工作内容。

千万被忘记第二部分...


via: https://deis.com/blog/2015/beyond-hello-world-containers-hard-stuff

作者:Bob Reselman 译者:Ezio 校对:wxy

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