使用Docker Swarm来运行服务

本文讲的是使用Docker Swarm来运行服务【编者的话】本文介绍了Docker 1.12中的Docker Swarm Mode,包括如何安装Docker Engine、如何建立Swarm集群、如何部署服务和创建Global Service。

Docker的最新版本v1.12,包含了很多更新和Docker Swarm提供的功能。在今天的文章中,我们将探讨如何使用Docker Swarm来部署服务。

在Ubuntu 16.04中激活Swarm模式

在我们使用Docker Engine Swarm部署服务之前,我们需要建立一个Swarm集群。因为我们需要1.12新添加的功能,所以我们也要安装Docker Engine的最新版本。

以下步骤将指导你在Ubuntu 16.04上安装Docker Engine。对于其他平台和版本,你可以参考Docker的 官方安装文档
设置Docker Apt仓库
我们会使用Ubuntu的标准安装方式,依赖于Apt包管理器。因为我们需要安装最新版本的Docker Engine,所以我们需要配置Apt,从Docker官方Apt仓库来安装 docker-engine ,而不是从系统预配置的仓库。
添加Docker公钥
配置Apt来使用新仓库的第一步是想Apt缓存中添加该库的公钥。使用 apt-key 命令:
# apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D

以上的 apt-key 命令向密钥服务器 p80.pool.sks-keyservers.net 请求一个特定的密钥( 58118E89F3A912897C070ADBF76221572C52609D )。公钥将会被用来验证从新仓库下载的所有包。
指定Docker仓库的位置
引入Docker的公钥,我们可以配置Apt使用Docker的仓库服务器。我们可以在 /etc/apt/sources.list.d/ 目录中添加一个条目。
# echo "deb https://apt.dockerproject.org/repo ubuntu-xenial main" >> /etc/apt/sources.list.d/docker.list

当我们刷新Apt缓存时,Apt将会搜索 sources.list.d/ 目录下的所有文件,来寻找新的包仓库。上述命令会创建一个新文件 docker.list ,其中包含了一个添加了 apt.dockerproject.org 仓库的条目。
更新Apt包缓存
运行 apt-get 命令的 update 选项,来刷新Apt包缓存。
# apt-get update

这会触发Apt重新读取配置文件,刷新仓库列表,包含进我们添加的那个仓库。该命令也会查询这些仓库来缓存可用的包列表。
安装linux-image-extra
在安装Docker Engine之前,我们需要安装一个先决软件包(prerequisite package)。 linux-image-extra 包是一个内核相关的包,Ubuntu系统需要它来支持 aufs 存储设备驱动。Docker会使用该驱动来加载卷。

为了安装该包,我们将使用 apt-get 命令的 install 选项。
# apt-get install linux-image-extra-$(uname -r)

apt-get 命令中, $(uname -r) 将返回正在运行的内核的版本。任何对于该系统的内核更新应当包括安装 linux-image-extra ,它的版本需要与新内核版本相一致。如果该包没有正确更新的话,Docker加载卷的功能可能受到影响。

安装Docker Engine

在Apt配置好和 linux-image-extra 安装好之后,我们可以继续安装Docker Engine了。我们可以使用 apt-get 命令的 install 选项来安装 docker-engine 包。
# apt-get install docker-engine

此时,我们应该已经安装好了 Docker Engine v1.12.0 或者更新版本。我们可以执行 docker 命令的 version 选项来验证我们已经安装了最新版本。
# docker version
Client:
Version:      1.12.0
API version:  1.24
Go version:   go1.6.3
Git commit:   8eab29e
Built:        Thu Jul 28 22:11:10 2016
OS/Arch:      linux/amd64

Server:
Version:      1.12.0
API version:  1.24
Go version:   go1.6.3
Git commit:   8eab29e
Built:        Thu Jul 28 22:11:10 2016
OS/Arch:      linux/amd64

我们可以看到,Server版本和Client版本都是 1.12.0 。接下来,我们会创建Swarm集群。

创建一个Docker Swarm集群

在这一小节中,我们将在多台机器上执行多个任务。为了更清楚地表述,我会在例子中包含主机名。

我们会使用两个节点来启动Swarm集群。此时,两个节点都按照上述步骤安装了Docker Engine。

当创建Swarm集群时,我们需要指定一个manager节点。在这个例子中,我们会使用主机名为 swarm-01 的主机作为manager节点。为了使 swarm-01 成为manager节点,我们需要首先在 swarm-01 执行命令来创建Swarm集群。这个命令就是 docker 命令的 swarm init 选项。
root@swarm-01:~# docker swarm init --advertise-addr 10.0.0.1
Swarm initialized: current node (awwiap1z5vtxponawdqndl0e7) is now a manager.

To add a worker to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-51pzs5ax8dmp3h0ic72m9wq9vtagevp1ncrgik115qwo058ie6-3fokbd3onl2i8r7dowtlwh7kb \
10.0.0.1:2377

To add a manager to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-51pzs5ax8dmp3h0ic72m9wq9vtagevp1ncrgik115qwo058ie6-bwex7fd4u5aov4naa5trcxs34 \
10.0.0.1:2377

在上述命令中,除了 swarm init 之外,我们还指定了 --advertise-addr 10.0.0.1 。Swarmmanager节点会使用该IP地址来广告Swarm集群服务。虽然该地址可以是私有地址,重要的是,为了使节点加入该集群,那些节点需要能通过该IP的 2377 端口来访问manager节点。

在运行 docker swarm init 命令之后,我们可以看到 swarm-01 被赋予了一个节点名字( awwiap1z5vtxponawdqndl0e7 ),并被选为Swarm集群的管理器。输出中也提供了两个命令:一个命令可以添加worker节点到swarm中,另一个命令可以添加另一个manager节点到该Swarm中。

Docker Swarm Mode可以支持多个manager节点。然而,其中的一个会被选举为主节点服务器,它会负责Swarm的编排。
添加worker节点到Swarm集群中
Swarm集群建立之后,我们需要添加一个新的worker节点。
root@swarm-02:~# docker swarm join \
> --token SWMTKN-1-51pzs5ax8dmp3h0ic72m9wq9vtagevp1ncrgik115qwo058ie6-3fokbd3onl2i8r7dowtlwh7kb \
> 10.0.0.1:2377
This node joined a swarm as a worker.

在本例中,我们将 swarm-02 添加到了swarm中,作为worker节点。Swarm集群中的worker节点的角色是用来运行任务(tasks)的;在该例中,任务(tasks)就是容器(containers)。另一方面,manager节点的角色是管理任务(容器)的编排,并维护Swarm集群本身。

除此之外,manager节点本身也是worker节点,也可以运行任务。
查看当前的Swarm节点
我们现在有了一个最基本的两节点的Swarm集群。我们可以执行 docker 命令的 node ls 选项来验证集群的状态。
root@swarm-01:~# docker node ls
ID                           HOSTNAME              STATUS  AVAILABILITY  MANAGER STATUS
13evr7hmiujjanbnu3n92dphk    swarm-02.example.com  Ready   Active        
awwiap1z5vtxponawdqndl0e7 *  swarm-01.example.com  Ready   Active        Leader

从输出中可以看到, swarm-01 swarm-02 都处于 Ready Active 状态。因此,我们可以继续在Swarm集群上部署服务了。

创建一个服务

在Docker Swarm Mode中,服务是指一个长期运行(long-running)的Docker容器,它可以被部署到任意一台worker节点上,可以被远端系统或者Swarm中其他容器连接和消费(consume)的。

在本例中,我们会部署一个Redis服务。
部署一个有副本的服务
一个有副本的服务是一个Docker Swarm服务,运行了特定数目的副本(replicas)。这些副本是由多个Docker容器的实例组成的。在本例中,每个副本都是一个独立的Redis实例。

为了创建新服务,我们会使用 docker 命令的 service create 选项。以下命令将创建一个名为 redis 的服务,包含 2 个副本,并在集群中发布 6379 端口。
root@swarm-01:~# docker service create --name redis --replicas 2 --publish 6379:6379 redis
er238pvukeqdev10nfmh9q1kr

除了 service create 选项之外,我们还指定了 --name redis --replicas 表示该服务需要运行在 2 个不同的节点上。我们可以运行 docker 命令的 service ls 选项来验证该服务是运行在两个节点上的。
root@swarm-01:~# docker service ls
ID            NAME   REPLICAS  IMAGE  COMMAND
er238pvukeqd  redis  2/2       redis

从输出中可以看到, 2 个副本都在运行。如果我们想看到这些任务的更多细节,我们可以运行 docker 命令的 service ps 选项。
root@swarm-01:~# docker service ps redis
ID                         NAME     IMAGE  NODE                  DESIRED STATE  CURRENT STATE           ERROR
5lr10nbpy91csmc91cew5cul1  redis.1  redis  swarm-02.example.com  Running        Running 40 minutes ago  
1t77jsgo1qajxxdekbenl4pgk  redis.2  redis  swarm-01.example.com  Running        Running 40 minutes ago

service ps 选项会显示特定服务的任务(容器)。在本例中,我们可以看到 redis 服务有一个任务(容器)运行在两个Swarm节点上。
连接Redis服务
我们已经验证了服务正在运行,我们可以尝试从远端系统,使用 redis-cli 客户端来连接该服务。
vagrant@vagrant:~$ redis-cli -h swarm-01.example.com -p 6379
swarm-01.example.com:6379>

从上面的连接可以看到,我们已经成功地连接上了 redis 服务。这意味着我们的服务已经运行起来了。
Docker Swarm是如何发布服务的
当我们创建了 redis 服务时,我们使用了 --publish 选项。该选项用来告知Docker将端口 6379 发布为 redis 服务的可用端口。

当Docker发布了服务端口时,它在Swarm集群上的所有节点上监听该端口。当流量到达该端口时,该流量将被路由到运行该服务的容器上。如果所有节点都运行着一个服务的容器,那么概念是相对标准的;然而,当我们的节点数比副本多时,概念就变得有趣了。
添加第三个worker节点
为了添加另一个worker节点,我们只要简单地重复第一部分中的安装步骤。因为我们已经做过这些步骤了,所以我们直接跳到3节点的Swarm集群。再一次地,我们可以运行 docker 命令来检查集群状态。
root@swarm-01:~# docker node ls
ID                           HOSTNAME              STATUS  AVAILABILITY  MANAGER STATUS
13evr7hmiujjanbnu3n92dphk    swarm-02.example.com  Ready   Active        
awwiap1z5vtxponawdqndl0e7 *  swarm-01.example.com  Ready   Active        Leader
e4ymm89082ooms0gs3iyn8vtl    swarm-03.example.com  Ready   Active

我们可以看到集群包含三个主机:
  • swarm-01
  • swarm-02
  • swarm-03

当我们创建了两个副本的服务时,它在 swarm-01 swarm-02 上分别创建了任务(容器)。即便我们添加了另一个worker节点,我们可以看到情况仍然是这样的。
root@swarm-01:~# docker service ps redis
ID                         NAME     IMAGE  NODE                  DESIRED STATE  CURRENT STATE           ERROR
5lr10nbpy91csmc91cew5cul1  redis.1  redis  swarm-02.example.com  Running        Running 55 minutes ago  
1t77jsgo1qajxxdekbenl4pgk  redis.2  redis  swarm-01.example.com  Running        Running 55 minutes ago

Docker Swarm通过replicated服务,可以保证对于每个指定的副本,都运行了一个任务(容器)。当我们创建 redis 服务时,我们指定了 2 个副本。这就意味着,即便我们有了第三个节点,Docker也没有理由在新节点上创建一个新任务。

此时,我们遇到了一个有趣的情形:我们在 3 个Swarm节点中的 2 个上运行了服务。在non-swarm的世界中,这就意味着当连接第三个Swarm节点时, redis 服务将变得不可用。然而,Swarm Mode中,情况却不是这样的。
在一个无任务运行的worker节点上连接服务
之前,我们提到Docker是如何发布服务端口的,Swarm在所有节点上都发布了该端口。有趣的是,当我们连接一个并未运行任何容器的worker节点时,会发生什么呢。

让我们看一下,当我们连接 swarm-03 redis 端口时,会发生什么呢。
vagrant@vagrant:~$ redis-cli -h swarm-03.example.com -p 6379
swarm-03.example.com:6379>

有趣的是,连接竟然成功了。尽管 swarm-03 上并未运行任何 redis 容器,但是连接成功了。这是因为,在内部,Docker将 redis 服务流量重路由到运行了 redis 容器的worker节点。

Docker称之为入口负载均衡(ingress load balancing)。它的工作方式是,所有worker节点都监听在发布的服务端口上。当该服务被外部系统调用时,收到流量的节点会通过Docker提供的内部DNS服务,将流量负载均衡该流量。

因此,即便我们将Swarm集群扩展至100个worker节点时, redis 服务的终端用户可以连接到任意一个worker节点。他们会被重定向到运行了任务(容器)的两个Docker宿主机之一。

这些重路由和负载均衡对于终端用户是完全透明的。
让服务global化
此时,我们已经建立了 redis 服务,运行了 2 个副本,这意味着, 3 个节点中的 2 个正在运行容器。

如果我们希望 redis 服务在每一个worker节点上运行一个实例,我们可以简单地修改服务的副本数目,从 2 增加到 3 。这意味着,如果我们增加或者减少worker节点数目,我们需要调整副本数目。

我们可以自动化地做这件事,只要把我们的服务变成一个Global Service。Docker Swarm Mode中的Global Service使用了创建一个服务,该服务会自动地在每个worker节点上运行任务。这种方法对于像Redis这样的一般服务都是有效的。

让我们重新创建 redis 服务为Global Service。
root@swarm-01:~# docker service create --name redis --mode global --publish 6379:6379 redis
5o8m338zmsped0cmqe0guh2to

同样是 docker service create 命令,唯一的区别是指定了 --mode 参数为 global

服务建立好之后,运行 docker 命令的 service ps 选项,我们可以看到,Docker是如何分发该服务的。
root@swarm-01:~# docker service ps redis
ID                         NAME       IMAGE  NODE                  DESIRED STATE  CURRENT STATE           ERROR
27s6q5yvmyjvty8jvp5k067ul  redis      redis  swarm-03.example.com  Running        Running 26 seconds ago  
2xohhkqvlw7969qj6j0ca70xx   \_ redis  redis  swarm-02.example.com  Running        Running 38 seconds ago  
22wrdkun5f5t9lku6sbprqi1k   \_ redis  redis  swarm-01.example.com  Running        Running 38 seconds ago

我们可以看到,一旦该服务被创建为Global Service,那么每个worker节点上都会运行一个任务。

小结

在本文中,我们不仅安装了Docker Engine,也创建了一个Swarm集群,部署了一个有副本的服务,然后创建了Global Service。

在最近的一篇 文章 中,我不仅安装了Kubernetes,也创建了Kubernetes服务。通过比较Docker Swarm Mode服务和Kubernetes服务,我发现Swarm Mode服务更容易创建。如果只想使用Kubernetes的服务特性,而不需要Kubernetes的其他功能,那么Docker Swarm Mode可能是一个更容易的选择。

原文链接:Running Services within a Docker Swarm(翻译:夏彬)

原文发布时间为:2016-10-08

本文作者:夏彬

本文来自云栖社区合作伙伴Dockerone.io,了解相关信息可以关注Dockerone.io。

原文标题:使用Docker Swarm来运行服务

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用Docker Swarm和Docker Compose搭建并运行Kafka服务的简单步骤: 1. 首先,您需要创建一个docker-compose.yml文件,其中包含Kafka服务的配置。以下是一个简单的docker-compose.yml文件,用于启动单个Kafka节点: ``` version: '3.8' services: zookeeper: image: confluentinc/cp-zookeeper:6.2.0 hostname: zookeeper container_name: zookeeper ports: - "2181:2181" kafka: image: confluentinc/cp-kafka:6.2.0 hostname: kafka container_name: kafka depends_on: - zookeeper ports: - "9092:9092" environment: KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092 KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true" ``` 在上面的配置中,我们使用了Confluent公司提供的Kafka和Zookeeper镜像,并将它们分别命名为zookeeper和kafka。我们还指定了Zookeeper的端口号为2181,Kafka的端口号为9092。 2. 接下来,您需要在Swarm管理节点上初始化Swarm。如果您还没有初始化Swarm,请使用以下命令: ``` docker swarm init ``` 3. 然后,您需要将docker-compose.yml文件复制到Swarm管理节点上,并使用以下命令启动Kafka服务: ``` docker stack deploy -c docker-compose.yml kafka ``` 这将在您的Swarm集群中启动Kafka服务。 4. 要检查Kafka服务是否正在运行,请使用以下命令: ``` docker service ls ``` 这将显示正在运行的Kafka服务。 5. 最后,您可以使用Kafka的客户端工具来测试Kafka服务是否正在工作。例如,您可以使用以下命令向Kafka发送一条消息: ``` docker run --net=kafka_kafka-net --rm confluentinc/cp-kafka:6.2.0 kafka-console-producer --broker-list kafka:9092 --topic test ``` 然后,您可以使用以下命令从Kafka中读取消息: ``` docker run --net=kafka_kafka-net --rm confluentinc/cp-kafka:6.2.0 kafka-console-consumer --bootstrap-server kafka:9092 --topic test --from-beginning ``` 如果您看到了您发送的消息,则表示Kafka服务已经在Swarm集群中成功启动。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值