个性化阅读
专注于IT技术分析

加快软件部署-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
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS
su1bgh1uxqsikf1129tjhg5r8 *   node1               Ready               Active              Leader
t1tgnq38wb0cehsry2pdku10h     node3               Ready               Active              Reachable
wxie5wf65akdug7sfr9uuleui     node2               Ready               Active              Reachable

请注意, 我们的第一个节点在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_password

    nginx:
        image: lsapan/docker-swarm-demo-nginx
        ports:
            - 8000:80
        deploy:
            mode: global

    redis:
        image: redis
        deploy:
            replicas: 1

secrets:
    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
ID                  NAME                MODE                REPLICAS            IMAGE                                   PORTS
cih6u1t88vx7        demo_web            replicated          2/2                 lsapan/docker-swarm-demo-web:latest
u0p1gd6tykvu        demo_nginx          global              3/3                 lsapan/docker-swarm-demo-nginx:latest   *:8000->80/
tcp
wa1gz80ker2g        demo_redis          replicated          1/1                 redis:latest

瞧! Docker已将我们的映像下载到适当的节点, 并为我们的服务创建了容器。如果你的副本尚未满负荷, 请稍等片刻, 然后再次检查。 Docker可能仍会下载图像。

眼见为实

不过请不要相信我的话(或Docker的话)。让我们尝试连接到我们的应用。我们的服务配置告诉Docker在端口8000上公开NGINX。如果你使用的是PWD, 则页面顶部的蓝色链接应显示” 8000″。 PWD实际上已自动检测到我们在该端口上正在运行服务!单击该按钮, 它将把你路由到端口8000上的选定节点。如果你滚动了自己的服务器, 只需导航到端口8000上服务器的IP之一即可。

精美的屏幕为你带来了一些基本信息, 其中包括:

创建的堆栈提供的内容

记下哪个容器满足了你的请求, 然后刷新页面。改变的可能性。但为什么?好吧, 我们告诉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秒。

向上或向下扩展服务

有两个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正式开发的, 并且他们每天都在努力添加更多功能。不管你选择使用哪种容器, 都应保持容器包装!

赞(0)
未经允许不得转载:srcmini » 加快软件部署-Docker Swarm教程

评论 抢沙发

评论前必须登录!