Docker 平台和容器已经成为打包、部署、和管理应用程序的标准。为了在一个集群内协调跨节点的容器，必须有一个关键的能力：一个容器编排器。对于关键的集群化以及计划的任务，编排器是起重大作用的，比如：管理容器计划和资源分配。支持服务发现和无缝的应用程序部署。分配应用程序运行必需的资源。不幸的是，在这种环境下，编排器的分布式特性和资源的短暂性使得确保编排器的安全是一个极具挑战性的任务。在这篇文章中，我们将讨论容器编排器安全模型中没有考虑到的、但是很重要的这方面的详细情况，以及 Docker 企业版中如何使用内置的编排性能、Swarm 模式，去克服这些问题。诱因和威胁模型使用 swarm 模式的 Docker 企业版的其中一个主要目标是提供一个内置安全特性的编排器。为达到这个目标，我们部署了第一个在我们心目中认为的以最小权限原则设计的容器编排器。在计算机科学中，一个分布式系统所要求的最小权限原则是，系统中的每个参与者仅仅能访问它正当目的所需要的信息和资源。不是更多，也不是更少。“一个进程必须仅仅能去访问它的正当目的所需要的信息和资源”最小权限原则在一个 Docker 企业版集群中的每个节点分配的角色：既不是管理者（manager），也不是工人（worker）。这些角色为节点定义了一个很粗粒度的权限级别：分别进行管理和任务执行。尽管如此，不用理会它的角色，通过使用加密的方式，来保证一个节点仅仅有执行它的任务所需要的信息和资源。结果是，确保集群安全变得更容易了，甚至可以防止大多数的有经验的攻击者模式：攻击者控制了底层通讯网络，或者甚至攻陷了集群节点。内核缺省安全这是一个很老的安全最大化状态：如果它不是缺省的，就没人用它。Docker Swarm 模式将缺省安全这一概念融入了核心，并且使用这一机制去解决编排器生命周期中三个很难并且很重要的部分：可信引导和节点引入。节点身份发布和管理。认证、授权和加密的信息存储和传播。我们来分别看一下这三个部分：可信引导和节点引入确保集群安全的第一步，没有别的，就是严格控制成员和身份。管理员不能依赖它们节点的身份，并且在节点之间强制实行绝对的负载隔离。这意味着，未授权的节点不能允许加入到集群中，并且，已经是集群一部分的节点不能改变身份，突然去伪装成另一个节点。为解决这种情况，通过 Docker 企业版 Swarm 模式管理的节点，维护了健壮的、不可改变的身份。期望的特性是，通过使用两种关键的构建块去保证加密：为集群成员使用 安全加入令牌 Secure join token 。从一个集中化的认证机构发行的内嵌唯一身份的证书。加入 Swarm要加入 Swarm，节点需要一份 安全加入令牌 Secure join token 的副本。在集群内的每个操作角色的令牌都是独一无二的 —— 现在有两种类型的节点：工人（workers）和管理者（managers）。由于这种区分，拥有一个工人令牌的节点将不允许以管理者角色加入到集群。唯一得到这个特殊令牌的方式是通过 swarm 的管理 API 去向集群管理者请求一个。令牌是安全的并且是随机生成的，它还有一个使得令牌泄露更容易被检测到的特殊语法：一个可以在你的日志和仓库中很容易监视的特殊前缀。幸运的是，即便发现一个泄露，令牌也可以很容易去更新，并且，推荐你经常去更新它们 —— 特别是，在一段时间中你的集群不进行扩大的情况下。引导信任作为它的身份标识创建的一部分，一个新的节点将向任意一个网络管理者请求发布一个新的身份。但是，在我们下面的威胁模型中，所有的通讯可以被一个第三方拦截。这种请求存在的问题是：一个节点怎么知道与它进行对话的对方是合法的管理者？幸运的是，Docker 有一个内置机制可以避免这种情况。这个加入令牌被主机用于加入 Swarm，包含了一个根 CA 证书的哈希串。所以，主机可以使用单向 TLS，并且使用这个哈希串去验证它加入的 Swarm 是否正确：如果管理者持有的证书没有被正确的 CA 哈希串签名，节点就知道它不可信任。节点身份发布和管理在一个 Swarm 中，身份标识是内嵌在每个节点都单独持有的一个 x509 证书中。在一个最小权限原则的表现形式中，证书的私钥被绝对限制在主机的原始位置。尤其是，管理者不能访问除了它自己的私钥以外的任何一个私钥。身份发布要接收它们的证书而无需共享它们的私钥，新的主机通过发布一个证书签名请求（CSR）来开始，管理者收到证书签名请求之后，转换成一个证书。这个证书成为这个新的主机的身份标识，使这个节点成为 Swarm 的一个完全合格成员！当和安全引导机制一起使用时，发行身份标识的这个机制来加入节点是缺省安全的：所有的通讯部分都是经过认证的、授权的，并且非敏感信息从来都不会以明文方式进行交换。身份标识延期尽管如此，给一个 Swarm 中安全地加入节点，仅仅是 “故事” 的一部分。为降低证书的泄露或者失窃造成的影响，并且移除管理 CRL 列表的复杂性，Swarm 模式为身份标识使用了较短存活周期的证书。这些证书缺省情况下三个月后将过期，但是，也可以配置为一个小时后即刻过期！较短的证书过期时间意味着不能手动去处理证书更新，所以，通常会使用一个 PKI 系统。对于 Swarm，所有的证书是以一种不中断的方式进行自动更新的。这个过程很简单：使用一个相互认证的 TLS 连接去证明一个特定身份标识的所有者，一个 Swarm 节点定期生成一个新的公钥/私钥密钥对，并且用相关的 CSR 去签名发送，创建一个维持相同身份标识的完整的新证书。经过认证、授权、和加密的信息存储和传播。在一个正常的 Swarm 的操作中，关于任务的信息被发送给去运行的工人（worker）节点。这里不仅仅包含将被一个节点运行的容器的信息；也包含那个容器运行所必需的资源的所有信息，包括敏感的机密信息，比如，私钥、密码和 API 令牌。传输安全事实上，参与 Swarm 的每个节点都拥有一个独一无二的 X509 格式的证书，因此，节点之间的通讯安全是没有问题的：节点使用它们各自的证书，与另一个连接方进行相互认证、继承机密、真实性、和 TLS 的完整性。关于 Swarm 模式的一个有趣的细节是，本质上它是使用了一个推送模式：仅管理者被允许去发送信息到工人们（workers）—— 显著降低了暴露在低权限的工人节点面前的管理者节点的攻击面。将负载严格隔离进安全区域管理者节点的其中一个责任是，去决定发送到每个工人（worker）节点的任务是什么。管理者节点使用多种策略去做这个决定；根据每个节点和每个负载的特性，去跨 Swarm 去安排负载。在使用 Swarm 模式的 Docker 企业版中，管理者节点通过使用附加到每个单个节点标识上的安全标签，去影响这些安排决定。这些标签允许管理者将节点组与不同的安全区域连接到一起，以限制敏感负载暴露，以及使相关机密信息更安全。安全分发机密除了加快身份标识发布过程之外，管理者节点还有存储和分发工人节点所需要的任何资源的任务。机密信息像任何其它类型的资源一样处理，并且基于安全的 mTLS 连接，从管理者推送到工人节点。在主机上，Docker 企业版能确保机密仅提供给它们指定的容器。在同一个主机上的其它容器并不能访问它们。Docker 以一个临时文件系统的方式显露机密给一个容器，确保机密总是保存在内存中，并且从不写入到磁盘。这种方式比其它竞争的替代者更加安全，比如，在环境变量中存储它们。一旦这个任务完成，这个机密将永远消失。存储机密在管理者主机上的机密总是保持加密的。缺省情况下，加密这些机密的密钥（被称为数据加密密钥，DEK）是以明文的方式存储在硬盘上的。这使得那些对安全性要求较低的人可以轻松地去使用 Docker Swarm 模式。但是，如果你运行一个生产集群，我们推荐你启用自动锁定模式。当自动锁定模式启用后，一个重新更新过的 DEK 被一个独立的加密密钥的密钥（KEK）所加密。这个密钥从不被存储在集群中；管理者有责任将它存储在一个安全可靠的地方，并且当集群启动的时候可以提供它。这就是所谓的 “解锁” Swarm。根据 Raft 故障容错一致性算法，Swarm 模式支持多个管理者。在这个场景中，无缝扩展了机密存储的安全性。每个管理者主机除了共享密钥之外，还有一个唯一的磁盘加密密钥。幸运的是，Raft 日志在磁盘上也是加密的，并且，在自动锁定模式下，没有 KEK 同样是不可访问的。当一个节点被攻陷后发生了什么？在传统的编排器中，挽回一台被攻陷的主机是一个缓慢而复杂的过程。使用 Swarm 模式，恢复它就像运行一个 Docker 节点的 rm 命令一样容易。这是从集群中删除一个受影响的节点，而 Docker 将去处理剩下的事情，即，重新均衡负载，并且确保其它的主机已经知道，而不会去与受影响的节点通讯。正如我们看到的那样，感谢最小权限的编排器，甚至是，如果攻击者在主机上持续活动，它们将被从剩余的网络上切断。主机的证书 —— 它的身份标识 —— 被列入黑名单，因此，管理者也不能有效访问它。结论使用 Swarm 模式的 Docker 企业版，在缺省情况下确保了编排器的所有关键区域的安全：加入集群。阻止恶意节点加入到集群。把主机分组为安全区域。阻止攻击者的横向移动。安排任务。任务将仅被委派到允许的节点。分配资源。恶意节点不能 “盗取” 其它的负载或者资源。存储机密。从不明文保存并且从不写入到工人节点的磁盘上。与工人节点的通讯。使用相互认证的 TLS 加密。因为 Swarm 模式的持续改进，Docker 团队正在努力将最小权限原则进一步推进。我们正在处理的一个任务是：如果一个管理者被攻陷了，怎么去保证剩下的节点的安全？路线图已经有了，其中一些功能已经可以使用，比如，白名单功能，仅允许特定的 Docker 镜像，阻止管理者随意运行负载。这是通过 Docker 可信内容来实现的。via: https://blog.docker.com/2017/10/least-privilege-container-orchestration/作者：Diogo Mónica 译者：qhwdw 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
让我们继续几周前在 CentOS 7.2 中开始的工作。 在本指南中，我们学习了如何初始化以及启动 Docker 1.12 中内置的原生的集群以及编排功能。但是我们只有 管理者 （ manager ） 节点还没有其它 工作者 （ worker ） 节点。今天我们会展开讲述这个。我将向你展示如何将不对称节点添加到 Sawrm 中，比如一个与 CentOS 相邻的 Fedora 24，它们都将加入到集群中，还有相关很棒的负载均衡等等。当然这并不是轻而易举的，我们会遇到一些障碍，所以它应该是非常有趣的。先决条件在将其它节点成功加入 Swarm 之前，我们需要做几件事情。理想情况下，所有节点都应该运行相同版本的 Docker，为了支持原生的编排功能，它的版本至少应该为 1.12。像 CentOS 一样，Fedora 内置的仓库没有最新的构建版本，所以你需要手动构建，或者使用 Docker 仓库手动添加和安装正确的版本，并修复一些依赖冲突。我已经向你展示了如何在 CentOS 中操作，经过是相同的。此外，所有节点都需要能够相互通信。这就需要有正确的路由和防火墙规则，这样 管理者 （ manager ） 和 工作者 （ worker ） 节点才能互相通信。否则，你无法将节点加入 Swarm 中。最简单的解决方法是临时清除防火墙规则 （iptables -F），但这可能会损害你的安全。请确保你完全了解你正在做什么，并为你的节点和端口创建正确的规则。Error response from daemon: Timeout was reached before node was joined. The attempt to join the swarm will continue in the background. Use the "docker info" command to see the current swarm status of your node.守护进程的错误响应：节点加入之前已超时。尝试加入 Swarm 的请求将在后台继续进行。使用 “docker info” 命令查看节点的当前 Swarm 状态。你需要在主机上提供相同的 Docker 镜像。在上一个教程中我们创建了一个 Apache 映像，你需要在你的 工作者 （ worker ） 节点上执行相同操作，或者分发已创建的镜像。如果你不这样做，你会遇到错误。如果你在设置 Docker 上需要帮助，请阅读我的介绍指南和网络教程。7vwdxioopmmfp3amlm0ulimcu \_ websky.11 my-apache2:latest localhost.localdomain Shutdown Rejected 7 minutes ago "No such image: my-apache2:lat&" 现在开始现在我们有一台启动了 CentOS 机器，并成功地创建了容器。你可以使用主机端口连接到该服务，这一切都看起来很好。目前，你的 Swarm 只有 管理者 （ manager ） 。加入 工作者 （ worker ） 要添加新的节点，你需要使用 join 命令。但是你首先必须提供令牌、IP 地址和端口，以便 工作者 （ woker ） 节点能正确地对 Swarm 管理器进行身份验证。接着（在 Fedora 上）执行：[root@localhost ~]# docker swarm join-token worker To add a worker to this swarm, run the following command: docker swarm join \ --token SWMTKN-1-0xvojvlza90nrbihu6gfu3qm34ari7lwnza ... \ 192.168.2.100:2377 如果你不修复防火墙和路由规则，你会得到超时错误。如果你已经加入了 Swarm，重复 join 命令会收到错误：Error response from daemon: This node is already part of a swarm. Use "docker swarm leave" to leave this swarm and join another one. 如果有疑问，你可以离开 Swarm，然后重试：[root@localhost ~]# docker swarm leave Node left the swarm. docker swarm join --token SWMTKN-1-0xvojvlza90nrbihu6gfu3qnza4 ... 192.168.2.100:2377 This node joined a swarm as a worker. 在 工作者 （ worker ） 节点中，你可以使用 docker info 来检查状态：Swarm: active NodeID: 2i27v3ce9qs2aq33nofaon20k Is Manager: false Node Address: 192.168.2.103 Likewise, on the manager: Swarm: active NodeID: cneayene32jsb0t2inwfg5t5q Is Manager: true ClusterID: 8degfhtsi7xxucvi6dxvlx1n4 Managers: 1 Nodes: 3 Orchestration: Task History Retention Limit: 5 Raft: Snapshot Interval: 10000 Heartbeat Tick: 1 Election Tick: 3 Dispatcher: Heartbeat Period: 5 seconds CA Configuration: Expiry Duration: 3 months Node Address: 192.168.2.100 创建或缩放服务现在，我们需要看下 Docker 是否以及如何在节点间分发容器。我的测试展示了一个在非常轻的负载下相当简单的平衡算法。试了一两次之后，即使在我尝试缩放并更新之后，Docker 也没有将运行的服务重新分配给新的 worker。同样，有一次，它在 工作者 （ worker ） 节点上创建了一个新的服务。也许这是最好的选择。在新的 工作者 （ worker ） 节点上完整创建新的服务。过了一段时间，两个容器之间的现有服务有一些重新分配，但这需要一些时间。新服务工作正常。这只是一个前期观察，所以我现在不能说更多。现在是开始探索和调整的新起点。负载均衡过了一会工作了。总结Docker 是一只灵巧的小野兽，它仍在继续长大，变得更复杂、更强大，当然也更优雅。它被一个大企业吃掉只是一个时间问题。当它带来了原生的编排功能时，Swarm 模式运行得很好，但是它不只是几个容器而已，而是充分利用了其算法和可扩展性。我的教程展示了如何将 Fedora 节点添加到由 CentOS 运行的群集中，并且两者能并行工作。关于负载平衡还有一些问题，但这是我将在以后的文章中探讨的。总而言之，我希望这是一个值得记住的一课。我们已经解决了在尝试设置 Swarm 时可能遇到的一些先决条件和常见问题，同时我们启动了一堆容器，我们甚至简要介绍了如何缩放和分发服务。要记住，这只是一个开始。干杯。作者简介：我是 Igor Ljubuncic。现在大约 38 岁，已婚但还没有孩子。我现在在一个大胆创新的云科技公司做首席工程师。直到大约 2015 年初时，我还在一个全世界最大的 IT 公司之一中做系统架构工程师，和一个工程计算团队开发新的基于 Linux 的解决方案，优化内核以及攻克 Linux 的问题。在那之前，我是一个为高性能计算环境设计创新解决方案的团队的技术领导。还有一些其他花哨的头衔，包括系统专家、系统程序员等等。所有这些都曾是我的爱好，但从 2008 年开始成为了我的付费工作。还有什么比这更令人满意的呢？从 2004 年到 2008 年间，我曾通过作为医学影像行业的物理学家来糊口。我的工作专长集中在解决问题和算法开发。为此，我广泛地使用了 Matlab，主要用于信号和图像处理。另外，我得到了几个主要的工程方法学的认证，包括 MEDIC 六西格玛绿带、试验设计以及统计工程学。我也开始写书，包括奇幻类和 Linux 上的技术性工作。彼此交融。要查看我开源项目、出版物和专利的完整列表，请滚动到下面。有关我的奖项，提名和 IT 相关认证的完整列表，请稍等一下。via: http://www.dedoimedo.com/computers/docker-swarm-adding-worker-nodes.html作者：Igor Ljubuncic 译者：geekpi 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
Swarm，听起来像是一个朋克摇滚乐队。但它确实是个新的编排机制，抑或者是，一个 Docker 现有编排体制的改进。简单来讲，如果你在用一个旧版本的 Docker，你必须手动配置 Swarm 来创建 Docker 集群。从 1.12 版开始，Docker 引擎集成了一个原生的实现（LCTT 译注：见下文）来支持无缝的集群设置。也就是为什么会有这篇文章。在这篇教程中，我将带你体验一下编排后的 Docker 将能做的事情。这篇文章并不是包含所有细节（如 BnB 一般）或是让你对其全知全能，但它能带你踏上你的集群之路。在我的带领下开始吧。技术概要如果把 Docker 详细而又好用的文档照搬到这里那将太丢人了，所以我将简要概括下这个技术的概要。我们已经有了 Docker，对吧。现在，你想要更多的服务器作为 Docker 主机，但同时你希望它们属于同一个逻辑上的实体。也就是说，你想建立一个集群。我们先从一个主机组成的集群开始。当你在一个主机上初始化一个 Swarm 集群，这台主机将成为这个集群的 管理者 （ manager ） 。从技术角度来讲，它成为了 共识组 （ consensus group ） 中的一个 节点 node 。其背后的数学逻辑建立在 Raft 算法之上。 管理者 （ manager ） 负责调度任务。而具体的任务则会委任给各个加入了 Swarm 集群的 工作者 （ worker ） 节点。这些操作将由 Node API 所管理。虽说我讨厌 API 这个词汇，但我必须在这里用到它。Service API 是这个实现中的第二个组件。它允许 管理者 （ manager ） 节点在所有的 Swarm 集群节点上创建一个分布式的服务。这个服务可以 被复制 （ replicated ） ，也就是说它们（LCTT 译注：指这些服务）会由平衡机制被分配到集群中（LCTT 译注：指 replicated 模式，多个容器实例将会自动调度任务到集群中的一些满足条件的节点），或者可以分配给全局（LCTT 译注：指 global 模式），也就是说每个节点都会运行一个容器实例。此外还有更多的功课需要做，但这些信息已经足够你上路了。现在，我们开始整些实际的。我们的目标平台是 CentOS 7.2，有趣的是在我写这篇教程的时候，它的软件仓库中只有 1.10 版的 Docker，也就是说我必须手动更新以使用 Swarm。我们将在另一篇教程中讨论这个问题。接下来我们还有一个跟进的指南，其中涵盖了如何将新的节点加入我们现有的集群（LCTT 译注：指刚刚建立的单节点集群），并且我们将使用 Fedora 进行一个非对称的配置。至此，请确保正确的配置已经就位，并有一个工作的集群启动并正在运行（LCTT 译注：指第一个节点的 Docker 已经安装并已进入 Swarm 模式，但到这里笔者并没有介绍如何初始化 Swarm 集群，不过别担心下章会讲）。配置镜像和服务我将尝试配置一个负载均衡的 Apache 服务，并使用多个容器实例通过唯一的 IP 地址提供页面内容。挺标准的吧（LCTT 译注：指这个负载均衡的网页服务器）。这个例子同时也突出了你想要使用集群的大多数原因：可用性、冗余、横向扩展以及性能。当然，你同时需要考虑网络和储存这两块，但它们超出了这篇指南所涉及的范围了。这个 Dockerfile 模板其实可以在官方镜像仓库里的 httpd 下找到。你只需一个最简单的设置来起步。至于如何下载或创建自己的镜像，请参考我的入门指南，链接可以在这篇教程的顶部可以找到。docker build -t my-apache2 . Sending build context to Docker daemon 2.048 kB Step 1 : FROM httpd:2.4 Trying to pull repository docker.io/library/httpd ... 2.4: Pulling from docker.io/library/httpd 8ad8b3f87b37: Pull complete c95e1f92326d: Pull complete 96e8046a7a4e: Pull complete 00a0d292c371: Pull complete 3f7586acab34: Pull complete Digest: sha256:3ad4d7c4f1815bd1c16788a57f81b413...a915e50a0d3a4 Status: Downloaded newer image for docker.io/httpd:2.4 ---> fe3336dd034d Step 2 : COPY ../public-html/ /usr/local/apache2/htdocs/ ... 在你继续下面的步骤之前，你应该确保你能无错误的启动一个容器实例并能链接到这个网页服务器上（LCTT 译注：使用下面的命令）。一旦你确保你能连上，我们就可以开始着手创建一个分布式的服务。docker run -dit --name my-running-app my-apache2 将这个 IP 地址输入浏览器，看看会出现什么。Swarm 初始化和配置下一步就是启动 Swarm 集群了。你将需要这些最基础的命令来开始，它们与 Docker 博客中的例子非常相似：docker service create --name frontend --replicas 5 -p 80:80/tcp my-apache2:latest 这里我们做了什么？我们创建了一个叫做 frontent 的服务，它有五个容器实例。同时我们还将主机的 80 端口和这些容器的 80 端口相绑定。我们将使用刚刚新创建的 Apache 镜像来做这个测试。然而，当你在自己的电脑上直接键入上面的指令时，你将看到下面的错误：docker service create --name frontend --replicas 5 -p 80:80/tcp my-apache2:latest Error response from daemon: This node is not a swarm manager. Use "docker swarm init" or "docker swarm join" to connect this node to swarm and try again. 这意味着你没有将你的主机（节点）配置成一个 Swarm 管理者 （ manager ） 。你可以在这台主机上初始化 Swarm 集群或是让它加入一个现有的集群。由于我们目前还没有一个现成的集群，我们将初始化它（LCTT 译注：指初始化 Swarm 集群并使当前节点成为 manager）：docker swarm init Swarm initialized: current node (dm58mmsczqemiikazbfyfwqpd) is now a manager. 为了向这个 Swarm 集群添加一个 工作者 （ worker ） ，请执行下面的指令：docker swarm join \ --token SWMTKN-1-4ofd46a2nfyvrqwu8w5oeetukrbylyznxla 9srf9vxkxysj4p8-eu5d68pu5f1ci66s7w4wjps1u \ 10.0.2.15:2377 为了向这个 Swarm 集群添加一个 管理者 （ manager ） ，请执行 docker swarm join-token manager 并按照指示操作。操作后的输出不用解释已经很清楚明了。我们成功的创建了一个 Swarm 集群。新的节点们将需要正确的 令牌 （ token ） 来加入这个 Swarm 集群。如果你需要配置防火墙，你还需找到它的 IP 地址和端口（LCTT 译注：指 Docker 的 Swarm 模式通讯所需的端口，默认 2377）。此外，你还可以向 Swarm 集群中添加管理者节点。现在，重新执行刚刚的服务创建指令：docker service create --name frontend --replicas 5 -p 80:80/tcp my-apache2:latest 6lrx1vhxsar2i50is8arh4ud1 测试连通性现在，我们来验证下我们的服务是否真的工作了。从某些方面讲，这很像我们在 Vagrant 和 coreOS 中做的事情那样。毕竟它们的原理几乎相同。相同指导思想的不同实现罢了（LCTT 译注：笔者观点，无法苟同）。首先需要确保 docker ps 能够给出正确的输出。你应该能看到所创建服务的多个容器副本。docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES cda532f67d55 my-apache2:latest "httpd-foreground" 2 minutes ago Up 2 minutes 80/tcp frontend.1.2sobjfchdyucschtu2xw6ms9a 75fe6e0aa77b my-apache2:latest "httpd-foreground" 2 minutes ago Up 2 minutes 80/tcp frontend.4.ag77qtdeby9fyvif5v6c4zcpc 3ce824d3151f my-apache2:latest "httpd-foreground" 2 minutes ago Up 2 minutes 80/tcp frontend.2.b6fqg6sf4hkeqs86ps4zjyq65 eda01569181d my-apache2:latest "httpd-foreground" 2 minutes ago Up 2 minutes 80/tcp frontend.5.0rmei3zeeh8usagg7fn3olsp4 497ef904e381 my-apache2:latest "httpd-foreground" 2 minutes ago Up 2 minutes 80/tcp frontend.3.7m83qsilli5dk8rncw3u10g5a 我也测试了不同的、非常规的端口，它们都能正常工作。对于你如何连接服务器和收取请求你将会有很多可配置的余地。你可以使用 localhost 或者 Docker 网络接口（笔者注：应该是指 Docker 的默认网桥 docker0，其网关为 172.17.0.1） 的 IP 地址的正确端口去访问。下面的例子使用了端口 1080：至此，这是一个非常粗略、简单的开始。真正的挑战是创建一个优化过的、可扩展的服务，但是它们需要一个准确的技术用例。此外，你还会用到 docker info 和 docker service（还有 inspect 和 ps）命令来详细了解你的集群是如何工作的。可能会遇到的问题你可能会在把玩 Docker 和 Swarm 时遇到一些小的问题（也许没那么小）。比如 SELinux 也许会抱怨你正在执行一些非法的操作（LCTT 译注：指在强制访问控制策略中没有权限的操作）。然而，这些错误和警告应该不会对你造成太多阻碍。docker service 不是一条命令（docker service is not a docker command）当你尝试执行必须的命令去创建一个 复制模式 （ replicated ） 的服务时，你可能会遇到一条错误说 docker: 'service' is not a docker command（LCTT 译注：见下面的例子）。这表示你的 Docker 版本不对（使用 -v 选项来检查）。我们将在将来的教程讨论如何修复这个问题。docker service create --name frontend --replicas 5 -p 80:80/tcp my-apache2:latest docker: 'service' is not a docker command. docker tag 无法识别（docker tag not recognized）你也许会看到下面的错误：docker service create -name frontend -replicas 5 -p 80:80/tcp my-apache2:latest Error response from daemon: rpc error: code = 3 desc = ContainerSpec: "-name" is not a valid repository/tag 关于这个错误已经有多个相关的讨论和帖子了。其实这个错误也许相当无辜。你也许是从浏览器粘贴的命令，在浏览器中的横线也许没被正确解析（笔者注：应该用 --name 而不是 -name）。就是这么简单的原因所导致的。扩展阅读关于这个话题还有很多可谈的，包含 1.12 版之前的 Swarm 集群实现（笔者注：旧的 Swarm 集群实现，下文亦作独立版本，需要 Consul 等应用提供服务发现），以及当前的 Docker 版本提供的（笔者注：新的 Swarm 集群实现，亦被称为 Docker 引擎的 Swarm 模式）。也就是说，请别偷懒花些时间阅读以下内容：Docker Swarm 概述（独立版本的 Swarm 集群安装）构建一个生产环境的 Swarm 集群（独立版本安装）安装并创建一个 Docker Swarm 集群（独立版本安装）Docker 引擎 Swarm 概述（对于 1.12 版）Swarm 模式入门（对于 1.12 版）总结你总算看到这里了。到这里仍然无法保证你学到了什么，但我相信你还是会觉得这篇文章有些用的。它涵盖了一些基础的概念，以及一个 Swarm 集群模式是如何工作的以及它能做什么的概述，与此同时我们也成功的下载了并创建了我们的网页服务器的镜像，并且在之后基于它运行了多个集群式的容器实例。虽然我们目前只在单一节点做了以上实验，但是我们会在将来解释清楚（LCTT 译注：以便解释清楚多节点的 Swarm 集群操作）。并且我们解决了一些常见的问题。我希望你能认为这篇指南足够有趣。结合着我过去所写的关于 Docker 的文章，这些文章应该能给你一个像样的解释，包括：怎么样操作镜像、网络栈、储存、以及现在的集群。就当热身吧。的确，请享受并期待在新的 Docker 教程中与你见面。我控几不住我记几啊。祝你愉快。via: http://www.dedoimedo.com/computers/docker-swarm-intro.html作者：Dedoimedo 译者：Viz 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
Ben Firshman 最近在 Dockercon 做了一个关于使用 Docker 构建无服务应用的演讲，你可以在这里查看详情（还有视频）。之后，我写了一篇关于如何使用 AWS Lambda 构建微服务系统的文章。今天，我想展示给你的就是如何使用 Docker Swarm 部署一个简单的 Python Falcon REST 应用。这里我不会使用dockerrun 或者是其他无服务特性，你可能会惊讶，使用 Docker Swarm 部署（复制）一个 Python（Java、Go 都一样）应用是如此的简单。注意：这展示的部分步骤是截取自 Swarm Tutorial，我已经修改了部分内容，并且增加了一个 Vagrant Helper 的仓库来启动一个可以让 Docker Swarm 工作起来的本地测试环境。请确保你使用的是 1.12 或以上版本的 Docker Engine。我写这篇文章的时候，使用的是 1.12RC2 版本。注意的是，这只是一个测试版本，可能还会有修改。你要做的第一件事，就是如果你想本地运行的话，你要保证 Vagrant 已经正确的安装和运行了。你也可以按如下步骤使用你最喜欢的云服务提供商部署 Docker Swarm 虚拟机系统。我们将会使用这三台 VM：一个简单的 Docker Swarm 管理平台和两台 worker。安全注意事项：Vagrantfile 代码中包含了部分位于 Docker 测试服务器上的 shell 脚本。这是一个潜在的安全问题，它会运行你不能控制的脚本，所以请确保你会在运行代码之前审查过这部分的脚本。$ git clone https://github.com/chadlung/vagrant-docker-swarm $ cd vagrant-docker-swarm $ vagrant plugin install vagrant-vbguest $ vagrant up Vagrant up 命令需要一些时间才能完成。SSH 登录进入 manager1 虚拟机：$ vagrant ssh manager1 在 manager1 的 ssh 终端会话中执行如下命令：$ sudo docker swarm init --listen-addr 192.168.99.100:2377 现在还没有 worker 注册上来：$ sudo docker node ls 让我们注册两个新的 worker，请打开两个新的终端会话（保持 manager1 会话继续运行）：$ vagrant ssh worker1 在 worker1 的 ssh 终端会话上执行如下命令：$ sudo docker swarm join 192.168.99.100:2377 在 worker2 的 ssh 终端会话上重复这些命令。在 manager1 终端上执行如下命令：$ docker node ls 你将会看到：在 manager1 的终端里部署一个简单的服务。sudo docker service create --replicas 1 --name pinger alpine ping google.com 这个命令将会部署一个服务，它会从 worker 之一 ping google.com。（或者 manager，manager 也可以运行服务，不过如果你只是想 worker 运行容器的话，也可以禁用这一点）。可以使用如下命令，查看哪些节点正在执行服务:$ sudo docker service tasks pinger 结果会和这个比较类似：所以，我们知道了服务正跑在 worker1 上。我们可以回到 worker1 的会话里，然后进入正在运行的容器：$ sudo docker ps 你可以看到容器的 id 是: ae56769b9d4d，在我的例子中，我运行如下的代码：$ sudo docker attach ae56769b9d4d 你可以按下 CTRL-C 来停止服务。回到 manager1，然后移除这个 pinger 服务。$ sudo docker service rm pinger 现在，我们将会部署可复制的 Python 应用。注意，为了保持文章的简洁，而且容易复制，所以部署的是一个简单的应用。你需要做的第一件事就是将镜像放到 Docker Hub上，或者使用我已经上传的一个。这是一个简单的 Python 3 Falcon REST 应用。它有一个简单的入口: /hello 带一个 value 参数。放在 chadlung/hello-app 上的 Python 代码看起来像这样：import json from wsgiref import simple_server import falcon class HelloResource(object): def on_get(self, req, resp): try: value = req.get_param('value') resp.content_type = 'application/json' resp.status = falcon.HTTP_200 resp.body = json.dumps({'message': str(value)}) except Exception as ex: resp.status = falcon.HTTP_500 resp.body = str(ex) if __name__ == '__main__': app = falcon.API() hello_resource = HelloResource() app.add_route('/hello', hello_resource) httpd = simple_server.make_server('0.0.0.0', 8080, app) httpd.serve_forever() Dockerfile 很简单：FROM python:3.4.4 RUN pip install -U pip RUN pip install -U falcon EXPOSE 8080 COPY . /hello-app WORKDIR /hello-app CMD ["python", "app.py"] 上面表示的意思很简单，如果你想，你可以在本地运行该进行来访问这个入口： http://127.0.0.1:8080/hello?value=Fred这将返回如下结果：{"message": "Fred"} 在 Docker Hub 上构建和部署这个 hello-app（修改成你自己的 Docker Hub 仓库或者使用这个）：$ sudo docker build . -t chadlung/hello-app:2 $ sudo docker push chadlung/hello-app:2 现在，我们可以将应用部署到之前的 Docker Swarm 了。登录 manager1 的 ssh 终端会话，并且执行：$ sudo docker service create -p 8080:8080 --replicas 2 --name hello-app chadlung/hello-app:2 $ sudo docker service inspect --pretty hello-app $ sudo docker service tasks hello-app 现在，我们已经可以测试了。使用任何一个 Swarm 节点的 IP 来访问 /hello 入口。在本例中，我在 manager1 的终端里使用 curl 命令：注意，Swarm 中的所有的 IP 都可以，不管这个服务是运行在一台还是更多的节点上。$ curl -v -X GET "http://192.168.99.100:8080/hello?value=Chad" $ curl -v -X GET "http://192.168.99.101:8080/hello?value=Test" $ curl -v -X GET "http://192.168.99.102:8080/hello?value=Docker" 结果：* Hostname was NOT found in DNS cache * Trying 192.168.99.101... * Connected to 192.168.99.101 (192.168.99.101) port 8080 (#0) > GET /hello?value=Chad HTTP/1.1 > User-Agent: curl/7.35.0 > Host: 192.168.99.101:8080 > Accept: */* > * HTTP 1.0, assume close after body < HTTP/1.0 200 OK < Date: Tue, 28 Jun 2016 23:52:55 GMT < Server: WSGIServer/0.2 CPython/3.4.4 < content-type: application/json < content-length: 19 < {"message": "Chad"} 从浏览器中访问其他节点：如果你想看运行的所有服务，你可以在 manager1 节点上运行如下代码：$ sudo docker service ls 如果你想添加可视化控制平台，你可以安装 Docker Swarm Visualizer（这对于展示非常方便）。在 manager1 的终端中执行如下代码：$ sudo docker run -it -d -p 5000:5000 -e HOST=192.168.99.100 -e PORT=5000 -v /var/run/docker.sock:/var/run/docker.sock manomarks/visualizer 打开你的浏览器，并且访问： http://192.168.99.100:5000/结果如下（假设已经运行了两个 Docker Swarm 服务）：要停止运行 hello-app（已经在两个节点上运行了），可以在 manager1 上执行这个代码：$ sudo docker service rm hello-app 如果想停止 Visualizer， 那么在 manager1 的终端中执行：$ sudo docker ps 获得容器的 ID，这里是： f71fec0d3ce1，从 manager1 的终端会话中执行这个代码：$ sudo docker stop f71fec0d3ce1 祝你成功使用 Docker Swarm。这篇文章主要是以 1.12 版本来进行描述的。via: http://www.giantflyingsaucer.com/blog/?p=5923作者：Chad Lung 译者：MikeCoder 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
嗨，大家好。今天我们来学一学Swarm相关的内容吧，我们将学习通过Swarm来创建Docker原生集群。Docker Swarm是用于Docker的原生集群项目，它可以将一个Docker主机池转换成单个的虚拟主机。Swarm工作于标准的Docker API，所以任何可以和Docker守护进程通信的工具都可以使用Swarm来透明地伸缩到多个主机上。就像其它Docker项目一样，Swarm遵循“内置电池，并可拆卸”的原则（LCTT 译注：batteries included，内置电池原来是 Python 圈里面对 Python 的一种赞誉，指自给自足，无需外求的丰富环境；but removable，并可拆卸应该指的是非强制耦合）。它附带有一个开箱即用的简单的后端调度程序，而且作为初始开发套件，也为其开发了一个可插拔不同后端的API。其目标在于为一些简单的使用情况提供一个平滑的、开箱即用的体验，并且它允许切换为更强大的后端，如Mesos，以用于大规模生产环境部署。Swarm配置和使用极其简单。这里给大家提供Swarm 0.2开箱的即用一些特性。Swarm 0.2.0大约85%与Docker引擎兼容。它支持资源管理。它具有一些带有限制和类同功能的高级调度特性。它支持多个发现后端（hubs，consul，etcd，zookeeper）它使用TLS加密方法进行安全通信和验证。那么，我们来看一看Swarm的一些相当简单而简用的使用步骤吧。1. 运行Swarm的先决条件我们必须在所有节点安装Docker 1.4.0或更高版本。虽然各个节点的IP地址不需要要公共地址，但是Swarm管理器必须可以通过网络访问各个节点。注意：Swarm当前还处于beta版本，因此功能特性等还有可能发生改变，我们不推荐你在生产环境中使用。2. 创建Swarm集群现在，我们将通过运行下面的命令来创建Swarm集群。各个节点都将运行一个swarm节点代理，该代理会注册、监控相关的Docker守护进程，并更新发现后端获取的节点状态。下面的命令会返回一个唯一的集群ID标记，在启动节点上的Swarm代理时会用到它。在集群管理器上运行：# docker run swarm create 3. 启动各个节点上的Docker守护进程我们需要登录进我们将用来创建集群的每个节点，并在其上使用-H标记启动Docker守护进程。它会保证Swarm管理器能够通过TCP访问到各个节点上的Docker远程API。要启动Docker守护进程，我们需要在各个节点内部运行以下命令。# docker -H tcp://0.0.0.0:2375 -d 4. 添加节点在启用Docker守护进程后，我们需要添加Swarm节点到发现服务，我们必须确保节点IP可从Swarm管理器访问到。要完成该操作，我们需要在各个节点上运行以下命令。# docker run -d swarm join --addr=<node_ip>:2375 token://<cluster_id> 注意：我们需要用步骤2中获取到的节点IP地址和集群ID替换这里的和。5. 开启Swarm管理器现在，由于我们已经获得了连接到集群的节点，我们将启动swarm管理器。我们需要在集群管理器中运行以下命令。# docker run -d -p <swarm_port>:2375 swarm manage token://<cluster_id> 6. 检查配置一旦管理运行起来后，我们可以通过运行以下命令来检查配置。# docker -H tcp://<manager_ip:manager_port> info 注意：我们需要替换为运行swarm管理器的主机的IP地址和端口。7. 使用docker CLI来访问节点在一切都像上面说得那样完美地完成后，这一部分是Docker Swarm最为重要的部分。我们可以使用Docker CLI来访问节点，并在节点上运行容器。# docker -H tcp://<manager_ip:manager_port> info # docker -H tcp://<manager_ip:manager_port> run ... 8. 监听集群中的节点我们可以使用swarm list命令来获取所有运行中节点的列表。# docker run --rm swarm list token://<cluster_id> 尾声Swarm真的是一个有着相当不错的功能的docker，它可以用于创建和管理集群。它相当易于配置和使用，当我们在它上面使用限制器和类同器时它更为出色。高级调度程序是一个相当不错的特性，它可以应用过滤器来通过端口、标签、健康状况来排除节点，并且它使用策略来挑选最佳节点。那么，如果你有任何问题、评论、反馈，请在下面的评论框中写出来吧，好让我们知道哪些材料需要补充或改进。谢谢大家了！尽情享受吧 :-)via: http://linoxide.com/linux-how-to/configure-swarm-clustering-docker/作者：Arun Pyasi 译者：GOLinux 校对：wxy本文由 LCTT 原创翻译，Linux中国 荣誉推出