加快软件部署-Docker Swarm教程

本文概述

  • 什么是Docker Swarm?
  • 深入Docker Swarm
  • 常常使用Docker Swarm
  • 本文总结
除非你一直生活在运输集装箱中, 否则你可能听说过集装箱。从持久性基础设施到临时性基础设施, 该行业一直在做出明显的转变, 而在此过程中, 容器是方形的。原因很简单:尽管容器确实可以帮助开发团队快速启动和运行, 但它们具有完全改变运营方式的更大潜力。
但是那到底是什么样的呢?当你准备好从本地运行容器或在几台服务器上手动运行容器时, 会发生什么?在理想的世界中, 你只想将应用程序放在服务器集群上并说” 运行它!”
幸运的是, 今天就是今天。
在本文中, 我们将探讨Docker Swarm是什么, 以及它所提供的一些出色功能。然后, 我们来看看实际使用Swarm模式并部署到集群的实际情况, 并总结一些示例, 说明部署后的集群的日常操作是什么样的。绝对建议你具备Docker和容器的基本知识, 但是如果你不熟悉容器, 可以先阅读这篇出色的博客文章。
什么是Docker Swarm?
加快软件部署-Docker Swarm教程

文章图片
在深入了解如何创建和部署第一个集群之前, 了解一下Docker Swarm是有帮助的。 Docker本身已经存在了很多年, 今天大多数人都将其视为容器运行时。但是实际上, Docker由许多不同的部分组成, 所有这些部分协同工作。例如, 该容器运行时部分由两个较小的组件(称为runC和containerd)处理。随着Docker的发展并回馈社区, 他们发现创建这些较小的组件是增长和快速添加功能的最佳方法。这样, 我们现在有了SwarmKit和Swarm模式, 它直接内置在Docker中。
Docker Swarm是一个容器编排引擎。从高层次上讲, 它需要在不同主机上运行的多个Docker引擎, 并让它们一起使用。用法很简单:将你的应用程序声明为服务堆栈, 然后让Docker处理其余部分。服务可以是从应用程序实例到数据库的任何东西, 或者是Redis或RabbitMQ之类的实用程序。如果你曾经在开发中使用过docker-compose, 这听起来应该很熟悉, 因为它是完全相同的概念。实际上, 栈声明实际上只是具有3.1版语法的docker-compose.yml文件。这意味着你可以使用类似(在许多情况下相同)的组合配置来进行开发和大量部署, 但是在这里, 我有点领先。当你在Swarm模式下拥有Docker实例时会发生什么?
加快软件部署-Docker Swarm教程

文章图片
不要掉下来
在Swarm世界中, 我们有两种类型的节点(服务器):管理者和工作者。重要的是要记住, 经理也是工人, 他们还有责任保持运转。每个群集都以一个指定为领导者的管理器节点开始。从那里开始, 只需运行一个命令即可安全地将节点添加到群集。
Swarm由于其Raft算法的实现而高度可用。我不会在Raft上做太多详细的介绍, 因为已经有一个很好的有关Raft如何工作的教程, 但是这里有一个基本的想法:Leader节点不断检查其同级Manager节点并同步其状态。为了使状态更改” 被接受” , 管理器节点必须达成共识, 这在大多数节点确认状态更改时会发生。
这样做的好处是, 管理器节点可以零星地掉线而不会影响集群的共识。如果状态变更达成共识, 我们知道可以保证大多数管理者节点上都存在该状态变更, 即使当前领导者失败, 该变更也将持续存在。
假设我们有三个管理者节点, 分别为A, B和C。当然, A是我们的无畏领导者。好吧, 有一天, 一个短暂的网络错误使A脱机, 从而使B和C独处。在很长一段时间(几百毫秒)内都没有听到过A的消息, B和C等待了一段随机产生的时间, 然后开始进行选举并通知对方。当然, 在这种情况下, 将选举第一个参加选举的人。在此示例中, B成为新的领导者, 并且恢复了仲裁。但是, 情节又变了:当A重新上线时会发生什么?会认为它仍然是领导者, 对不对?每次选举都有一个与之相关的术语, 因此A实际上是在术语1中选举的。一旦A重新上线并开始订购B和C, 他们便会告知B是术语2的领导者, 并且A将下台。
当然, 相同的过程在更大的范围内起作用。你可以具有三个以上的管理器节点。我将添加其他快速笔记。每个群只能承受特定数量的经理损失。 n个管理器节点群可能会丢失(n-1)/ 2个管理器而不会丢失仲裁。这意味着对于三名经理群来说, 你可能会输掉一个, 五名经理则可能输掉两个, 依此类推。其根本原因归结于关于多数共识的想法, 这绝对是你生产时要牢记的。
任务计划与协调
到目前为止, 我们已经确定我们的经理真的很擅长保持同步。大!但是他们实际上在做什么?还记得我曾说过将一堆服务部署到Swarm吗?声明服务时, 将为Swarm提供有关你实际希望如何运行服务的重要信息。其中包括一些参数, 例如每个服务需要多少个副本, 副本应如何分布, 是否仅应在某些节点上运行等等。
部署服务后, 管理人员的工作就是确保继续满足你设置的所有部署要求。假设你部署了Nginx服务, 并指定应有三个副本。管理人员将看到没有容器在运行, 并且将三个容器均匀分布在可用节点上。
不过, 更酷的是, 如果容器发生故障(或整个节点都将脱机), 则Swarm会在其余节点上自动创建容器以弥补差异。如果你说要运行三个容器, 那么你将运行三个容器, 而Swarm负责处理所有细节问题。加-这是一个很大的优点-向上或向下扩展与给Swarm一个新的复制设置一样容易。
服务发现和负载平衡
我想在最后一个示例中指出一个重要但微妙的细节:如果Swarm在其选择的节点上智能地启动了容器, 我们不一定知道这些容器将在哪里运行。乍一看听起来很吓人, 但这实际上是Swarm最强大的功能之一。
继续相同的Nginx示例, 假设我们告诉Docker这些容器应该公开端口80。如果将浏览器指向在端口80上运行该容器的节点, 你将看到该容器的内容。那里并不奇怪。不过, 可能令人惊讶的是, 如果将请求发送到未运行该容器的节点, 你仍然会看到相同的内容!这里发生了什么事?
Swarm实际上是使用入口网络将你的请求发送到运行该容器的可用节点, 并同时对其进行负载平衡。因此, 如果你对同一节点发出三个请求, 则很可能会碰到三个不同的容器。只要知道群集中单个节点的IP, 就可以访问其中运行的任何对象。相反, 这使你可以将负载均衡器(例如ELB)指向群集中的所有节点, 而不必担心什么在哪里运行。
它不止于外部连接。在同一堆栈上运行的服务具有覆盖网络, 可让它们彼此通信。无需在代码中对IP地址进行硬编码, 你只需使用服务名称作为你要连接的主机名即可。例如, 如果你的应用程序需要与名为” redis” 的Redis服务进行通信, 则可以仅使用” redis” 作为主机名, 而Swarm会将其请求路由到适当的容器。而且由于这在使用docker-compose进行的开发和使用Docker Swarm进行的生产中都可以无缝运行, 因此部署应用程序时不必担心。
加快软件部署-Docker Swarm教程

文章图片
滚动更新
如果你是操作人员, 则可能在生产更新严重错误时遇到了恐慌攻击。这可能是错误的代码更新, 甚至可能只是配置错误, 但突然生产下降了!老板不会理会这两种情况, 这很奇怪。他们只会知道这是你的错。好吧, 不用担心, Swarm也支持这一点。
更新服务时, 你可以定义一次应更新多少个容器, 以及新容器开始出现故障时应如何处理。在某个阈值之后, Swarm可以停止更新, 或者(从Docker 17.04开始)将容器回滚到先前的映像和设置。不用担心明天早晨要带老板喝杯咖啡。
安全
最后, 但并非最不重要的一点是, Docker Swarm具备了出色的安全功能。当节点加入群集时, 它使用的令牌不仅可以验证自身, 还可以验证它是否正在加入你认为是的群集。从那时起, 节点之间的所有通信都使用相互TLS加密进行。这些加密全部由Swarm自动设置和管理, 因此你无需担心续订证书和其他典型的安全麻烦。当然, 如果你想强制旋转键, 则有一个命令。
加快软件部署-Docker Swarm教程

文章图片
最新版本的Docker Swarm还带有内置的机密管理。这使你可以安全地将机密(例如密钥和密码)部署到需要它们的服务, 以及仅部署到需要它们的服务。当你为服务提供机密时, 该服务的容器将在其文件系统中挂载一个包含机密值的特殊文件。不用说, 但这比使用环境变量(传统方法)要安全得多。
深入Docker Swarm 如果你和我一样, 就渴望加入并使用所有这些功能!因此, 事不宜迟, 让我们开始吧!
Docker Swarm示例应用程序
我创建了一个非常简单的Flask应用程序, 以演示使用Docker Swarm的功能和便捷性。该Web应用程序仅显示一个页面, 该页面告诉你哪个容器满足了你的请求, 已服务了多少个请求以及” 秘密” 数据库密码是什么。
它分为三项服务:实际的Flask应用程序, Nginx反向代理和Redis密钥库。对于每个请求, 应用程序都会增加Redis中的num_requests键, 因此无论你遇到哪个Flask实例, 你都会看到正确反映的请求数。
如果你想” 查看” 正在发生的事情, 那么所有源代码都可以在GitHub上找到。
玩Docker!
在学习本教程时, 可以随意使用自己的服务器, 但是如果你想直接进入, 我强烈建议使用play-with-docker.com。它是由几个Docker开发人员运行的站点, 可让你启动多个联网的站点。预先安装了Docker的节点。他们将在四个小时后关闭, 但是对于这个示例来说, 已经足够了!
创建群
好了, 我们开始!继续并在PWD(与docker一起玩)中创建三个实例, 或在你最喜欢的VPS(虚拟专用服务器)服务中启动三台服务器, 然后在所有实例上安装Docker引擎。请记住, 将来你总是可以创建映像并重复使用该映像。管理者节点和工作者节点在软件方面没有区别, 因此你不需要维护两个不同的图像。
还在旋转吗?不用担心, 我会等待。好的, 现在我们要创建第一个经理和领导者节点。首先, 初始化一个集群:
docker swarm init --advertise-addr < node ip here>

将< node_ip_here> 替换为你节点的IP地址。在PWD上, 该IP地址显示在顶部, 如果你使用自己的VPS, 只要可以从网络中的其他节点访问该服务器的私有IP地址, 就可以随意使用。
你现在有一群!但是, 这是一个很无聊的工作, 因为它只有一个节点。让我们继续添加其他节点。你会注意到, 在运行init时, 它显示了一条长消息, 说明如何使用加入令牌。我们不会使用该节点, 因为它将使其他节点成为工作节点, 我们希望它们成为管理者。通过在第一个节点上运行该令牌来获取经理的加入令牌:
docker swarm join-token manager

复制结果命令, 然后在第二个和第三个节点上运行它。看哪, 有三个结点群!让我们验证我们所有的节点是否确实存在。 docker node ls命令将列出我们集群中的所有节点。你应该会看到以下内容:
$ docker node ls IDHOSTNAMESTATUSAVAILABILITYMANAGER STATUS su1bgh1uxqsikf1129tjhg5r8 *node1ReadyActiveLeader t1tgnq38wb0cehsry2pdku10hnode3ReadyActiveReachable wxie5wf65akdug7sfr9uuleuinode2ReadyActiveReachable

请注意, 我们的第一个节点在ID旁边是一个星号。这只是告诉我们当前正在连接的节点。我们还可以看到, 该节点当前是Leader, 其他节点在发生某些情况时都是Reachable。
花一点时间来欣赏一下这有多么容易, 让我们部署我们的第一个应用程序!
装运它!
刚好, 业务开发团队向客户承诺, 他们的新应用将在一个小时内部署并准备就绪!我知道很典型。但是不要担心, 因为它是使用Docker构建的, 所以我们几乎不需要那么多时间!开发人员非常友好, 可以借给我们他们的docker-compose文件:
version: '3.1'services: web: image: lsapan/docker-swarm-demo-web command: gunicorn --bind 0.0.0.0:5000 wsgi:app deploy: replicas: 2 secrets: - db_passwordnginx: image: lsapan/docker-swarm-demo-nginx ports: - 8000:80 deploy: mode: globalredis: image: redis deploy: replicas: 1secrets: db_password: external: true

我们待会儿将其分解, 但现在还没有时间。让我们部署它!继续在你的第一个节点上创建一个名为docker-compose.yml的文件, 并使用上面的配置填充它。你可以通过echo” < 粘贴的内容在这里> ” > docker-compose.yml轻松实现。
通常, 我们可以部署它, 但是我们的配置提到我们使用了一个名为db_password的秘密, 因此让我们快速创建一个秘密:
echo "supersecretpassword" | docker secret create db_password -

大!现在, 我们需要做的就是告诉Docker使用我们的配置:
docker stack deploy -c docker-compose.yml demo

运行此命令时, 你将看到Docker创建了我们定义的三个服务:web, nginx和redis。但是, 由于我们将堆栈演示命名为服务, 因此我们的服务实际上被命名为demo_web, demo_nginx和demo_redis。我们可以通过运行docker service ls命令来查看正在运行的服务, 该命令应显示如下内容:
$ docker service ls IDNAMEMODEREPLICASIMAGEPORTS cih6u1t88vx7demo_webreplicated2/2lsapan/docker-swarm-demo-web:latest u0p1gd6tykvudemo_nginxglobal3/3lsapan/docker-swarm-demo-nginx:latest*:8000-> 80/ tcp wa1gz80ker2gdemo_redisreplicated1/1redis:latest

瞧! Docker已将我们的映像下载到适当的节点, 并为我们的服务创建了容器。如果你的副本尚未满负荷, 请稍等片刻, 然后再次检查。 Docker可能仍会下载图像。
眼见为实
不过请不要相信我的话(或Docker的话)。让我们尝试连接到我们的应用。我们的服务配置告诉Docker在端口8000上公开NGINX。如果你使用的是PWD, 则页面顶部的蓝色链接应显示” 8000″ 。 PWD实际上已自动检测到我们在该端口上正在运行服务!单击该按钮, 它将把你路由到端口8000上的选定节点。如果你滚动了自己的服务器, 只需导航到端口8000上服务器的IP之一即可。
精美的屏幕为你带来了一些基本信息, 其中包括:
加快软件部署-Docker Swarm教程

文章图片
记下哪个容器满足了你的请求, 然后刷新页面。改变的可能性。但为什么?好吧, 我们告诉Docker创建我们Flask应用程序的两个副本, 并将其分发请求到这两个实例。你只是碰巧第二次碰到另一个容器。你还会注意到请求数量增加了, 因为两个Flask容器都与我们指定的单个Redis实例通信。
随时尝试从任何节点访问端口8000。你仍然可以正确路由到该应用。
揭开魔术的神秘面纱
至此, 一切正常, 希望你发现此过程很轻松!让我们仔细看一下docker-compose.yml文件, 看看我们实际告诉Docker的内容。在较高的层次上, 我们看到我们定义了三种服务:web, nginx和redis。就像普通的撰写文件一样, 我们为Docker提供了用于每个服务的映像以及要运行的命令。对于nginx, 我们还指定了主机上的端口8000应该映射到容器中的端口80。到目前为止, 所有这些都是标准的composite语法。
这里的新功能是deploy和secrets密钥。这些键会被docker-compose忽略, 因此它们不会影响你的开发环境, 但会被docker stack使用。让我们看一下网络服务。很简单, 我们告诉Docker我们想运行Flask应用程序的两个副本。我们还让Docker知道该网络服务需要db_password密码。这样可以确保容器具有一个名为/ run / secrets / db_password的文件, 其中包含机密值。
移至Nginx, 我们可以看到部署模式设置为global。复制默认值(在网络中隐式使用), 这意味着我们将指定所需的副本数。当我们指定global时, 它告诉Docker集群中的每个节点都应该运行该服务的一个实例。再次运行docker service ls, 你会注意到nginx具有三个副本, 其中每个副本用于集群中的每个节点。
最后, 我们指示Docker在群集中的某个地方运行Redis的单个实例。没关系, 因为我们的网络容器在请求Redis主机时会自动路由到该容器。
常常使用Docker Swarm 恭喜你将第一个应用程序部署到Docker Swarm!让我们花点时间回顾一下你将要使用的一些常用命令。
检查你的群
需要检查你的服务吗?尝试使用docker service ls和docker service ps < 服务名称> 。前者向你显示每个服务的高级概述, 后者向你提供有关为指定服务运行的每个容器的信息。当你想查看哪些节点正在运行服务时, 该功能特别有用。
滚动更新
准备何时更新应用程序该怎么办?好吧, 关于docker stack deploy的很酷的事情是它实际上也会将更新也应用到现有堆栈。假设你已将新的Docker映像推送到存储库中。实际上, 你可以运行与第一次使用的相同的deploy命令, 你的集群将下载并部署新映像。
当然, 你可能并不总是希望更新堆栈中的每个服务。我们也可以在服务级别执行更新。假设我最近更新了网络服务的图片。我可以发出以下命令来更新所有Web容器:
docker service update \ --image lsapan/docker-swarm-demo-web:latest \ demo_web

该命令的另一个好处是, 如果你指定应使用原始配置, 它将应用滚动更新。即使你没有这样做, 也可以传递标志进行更新, 以指示它进行滚动更新, 如下所示:
docker service update \ --image lsapan/docker-swarm-demo-web:latest \ --update-parallelism 1 --update-delay 30s \ demo_web

这将一次更新一个容器, 两次更新之间等待30秒。
向上或向下扩展服务
【加快软件部署-Docker Swarm教程】有两个Web容器很棒, 但是你知道哪个更好吗?有十个!成群地扩展服务很简单:
docker service scale demo_web=10

运行该命令并检查docker service ps demo_web的输出。你会看到我们现在有10个容器, 而其中的8个容器是在不久前启动的。如果你有兴趣, 也可以返回Web应用程序并刷新页面几次, 以查看现在你获得的不仅仅是原始的两个容器ID。
删除堆栈和服务
你的堆栈和服务已部署和扩展, 很棒!但是现在你想让它们脱机。这可以通过相应的rm命令来完成。要删除我们的演示堆栈, 请运行以下命令:
docker stack rm demo

或者, 如果你只想删除一项服务, 请使用:
docker service rm demo_web

排水节点
还记得我们之前运行docker node ls来检查集群中的节点吗?它提供了有关每个节点的大量信息, 包括其可用性。默认情况下, 节点是活动的, 这意味着它们是运行容器的公平游戏。但是, 有时你可能需要使节点暂时脱机以执行维护。当然, 你可以将其关闭, 然后群可以恢复, 但是给Moby(Docker鲸鱼)一点点通知是很好的。
这是耗尽节点的地方。当你将一个节点标记为Drain时, Docker Swarm会将其上运行的所有容器委派给其他节点, 并且在你将其可用性更改回Active之前, 它不会启动该节点上的任何容器。
假设我们要消耗node1。我们可以运行:
docker node update --availability drain node1

简单!准备好恢复工作时:
docker node update --availability active node1

本文总结 如我们所见, 与Swarm模式结合使用的Docker使我们能够比以往更有效, 更可靠地部署应用程序。值得一提的是, Docker Swarm绝不是唯一的容器编排引擎。实际上, 它是年轻的之一。 Kubernetes已经存在了很长时间, 并且肯定会在更多的生产应用中使用。也就是说, Swarm是由Docker正式开发的, 并且他们每天都在努力添加更多功能。不管你选择使用哪种容器, 都应保持容器包装!

    推荐阅读