mirror of
https://github.com/yeasy/docker_practice.git
synced 2026-03-27 12:15:34 +00:00
Update swarm and mesos chapter
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
# Docker Swarm 项目
|
||||
Docker Swarm 是 Docker 官方编排(Orchestration)项目之一,负责对 Docker 集群进行管理。
|
||||
# Docker 三剑客之 Docker Swarm
|
||||
Docker Swarm 是 Docker 官方三剑客项目之一,提供 Docker 容器集群服务,是 Docker 官方对容器云生态进行支持的核心方案。
|
||||
|
||||
本章将介绍 Swarm 项目情况以及安装和使用。
|
||||
使用它,用户可以将多个 Docker 主机封装为单个大型的虚拟 Docker 主机,快速打造一套容器云平台。
|
||||
|
||||
本章将介绍 Swarm 项目的相关情况,以及如何进行安装和使用。最后还对 Swarm 的服务发现后端、调度器和过滤器等功能进行讲解。
|
||||
|
||||
BIN
swarm/_images/docker_swarm.png
Normal file
BIN
swarm/_images/docker_swarm.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 121 KiB |
BIN
swarm/_images/swarm.png
Normal file
BIN
swarm/_images/swarm.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 103 KiB |
164
swarm/filter.md
164
swarm/filter.md
@@ -1,100 +1,108 @@
|
||||
## Swarm 过滤器
|
||||
swarm 的调度器(scheduler)在选择节点运行容器的时候支持几种过滤器 (filter):Constraint,Affinity,Port,Dependency,Health
|
||||
## Swarm 中的过滤器
|
||||
|
||||
可以在执行 `swarm manage` 命令的时候通过 `--filter` 选项来设置。
|
||||
Swarm 的调度器可以按照指定调度策略自动分配容器到节点。但有些时候希望能对这些分配加以干预。比如说,让 IO 敏感的容器分配到安装了 SSD 的节点上;让计算敏感的容器分配到 CPU 核数多的机器上;让网络敏感的容器分配到高带宽的机房;让某些容器尽量放同一个节点……。
|
||||
|
||||
###Constraint Filter
|
||||
constraint 是一个跟具体节点相关联的键值对,可以看做是每个节点的标签,这个标签可以在启动docker daemon的时候指定,比如
|
||||
```bash
|
||||
sudo docker -d --label label_name=label01
|
||||
这可以通过过滤器(filter)来实现,目前支持 `Constraint`、`Affinity`、`Port`、`Dependency`、`Health` 等五种过滤器。
|
||||
|
||||
### Constraint 过滤器
|
||||
Constraint 过滤器是绑定到节点的键值对,相当于给节点添加标签。
|
||||
|
||||
可在启动 Docker 服务的时候指定,例如指定某个节点颜色为 `red`。
|
||||
|
||||
```sh
|
||||
$ sudo docker daemon --label color=red -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
|
||||
```
|
||||
|
||||
也可以写在docker的配置文件里面(在ubuntu上面是 `/etc/default/docker`)。
|
||||
同样的,可以写在 Docker 服务的配置文件里面(以 Ubuntu 14.04 为例,是 `/etc/default/docker`)。
|
||||
|
||||
在本次试验中,给083添加标签--label label_name=083,084添加标签--label label_name=084,124添加标签--label label_name=124,
|
||||
|
||||
以083为例,打开/etc/default/docker文件,修改DOCKER_OPTS:
|
||||
```bash
|
||||
DOCKER_OPTS="-H 0.0.0.0:2375 -H unix:///var/run/docker.sock --label label_name=083"
|
||||
```sh
|
||||
DOCKER_OPTS="--label color=red -H 0.0.0.0:2375 -H unix:///var/run/docker.sock"
|
||||
```
|
||||
|
||||
在使用docker run命令启动容器的时候使用 `-e constarint:key=value` 的形式,可以指定container运行的节点。
|
||||
使用 Swarm 启动容器的时候,采用 `-e constarint:key=value` 的形式,可以过滤选择出匹配条件的节点。
|
||||
|
||||
比如我们想在84上面启动一个 redis 容器。
|
||||
```bash
|
||||
rio@085:~$ sudo docker -H 192.168.1.83:2376 run --name redis_1 -d -e constraint:label_name==084 redis
|
||||
fee1b7b9dde13d64690344c1f1a4c3f5556835be46b41b969e4090a083a6382d
|
||||
```
|
||||
注意,是**两个**等号,不是一个等号,这一点会经常被忽略。
|
||||
例如,我们将 `192.168.0.2` 节点打上红色标签,`192.168.0.3` 节点打上绿色标签。
|
||||
|
||||
接下来再在084这台机器上启动一个redis 容器。
|
||||
```bash
|
||||
rio@085:~$ sudo docker -H 192.168.1.83:2376 run --name redis_2 -d -e constraint:label_name==084 redis 4968d617d9cd122fc2e17b3bad2f2c3b5812c0f6f51898024a96c4839fa000e1
|
||||
```
|
||||
然后再在083这台机器上启动另外一个 redis 容器。
|
||||
```bash
|
||||
rio@085:~$ sudo docker -H 192.168.1.83:2376 run --name redis_3 -d -e constraint:label_name==083 redis 7786300b8d2232c2335ac6161c715de23f9179d30eb5c7e9c4f920a4f1d39570
|
||||
然后,分别启动两个容器,指定使用过滤器分别为红色和绿色。
|
||||
|
||||
```sh
|
||||
$ docker -H 192.168.0.2:12375 run -d -e constraint:color==red ubuntu:14.04 ping 127.0.0.1
|
||||
252ffb48e64e9858c72241f5eedf6a3e4571b1ad926faf091db3e26672370f64
|
||||
$ docker -H 192.168.0.2:12375 run -d -e constraint:color==green ubuntu:14.04 ping 127.0.0.1
|
||||
3d6f8d7af8583416b17061d038545240c9e5c3be7067935d3ef2fbddce4b8136
|
||||
```
|
||||
|
||||
现在来看下执行情况:
|
||||
```bash
|
||||
rio@085:~$ sudo docker -H 192.168.1.83:2376 ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
7786300b8d22 redis:latest "/entrypoint.sh redi 15 minutes ago Up 53 seconds 6379/tcp 083/redis_3
|
||||
4968d617d9cd redis:latest "/entrypoint.sh redi 16 minutes ago Up 2 minutes 6379/tcp 084/redis_2
|
||||
fee1b7b9dde1 redis:latest "/entrypoint.sh redi 19 minutes ago Up 5 minutes 6379/tcp 084/redis_1
|
||||
*注:指定标签中间是两个等号*
|
||||
|
||||
查看它们将被分配到指定节点上。
|
||||
|
||||
```sh
|
||||
$ docker -H 192.168.0.2:12375 ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
252ffb48e64e ubuntu:14.04 "ping 127.0.0.1" 1 minutes ago Up 1 minutes Host-2/sick_galileo
|
||||
3d6f8d7af858 ubuntu:14.04 "ping 127.0.0.1" 2 minutes ago Up 2 minutes Host-3/compassionate_ritchie
|
||||
```
|
||||
|
||||
可以看到,执行结果跟预期的一样。
|
||||
另外,Docker 内置了一些常见的过滤器,包括 `node`、`storagedriver`、`executiondriver`、`kernelversion`、`operatingsystem` 等。这些值可以通过 `docker info` 命令查看。
|
||||
|
||||
但是如果指定一个不存在的标签的话来运行容器会报错。
|
||||
```bash
|
||||
rio@085:~$ sudo docker -H 192.168.1.83:2376 run --name redis_0 -d -e constraint:label_name==0 redis
|
||||
FATA[0000] Error response from daemon: unable to find a node that satisfies label_name==0
|
||||
例如,目前集群中各个节点的信息为:
|
||||
|
||||
```sh
|
||||
$ docker -H 192.168.0.2:12375 info
|
||||
Containers: 5
|
||||
Images: 39
|
||||
Role: primary
|
||||
Strategy: spread
|
||||
Filters: health, port, dependency, affinity, constraint
|
||||
Nodes: 2
|
||||
Host-2: 192.168.0.2:2375
|
||||
└ Containers: 4
|
||||
└ Reserved CPUs: 0 / 4
|
||||
└ Reserved Memory: 1 GiB / 4.053 GiB
|
||||
└ Labels: color=red, executiondriver=native-0.2, kernelversion=3.16.0-43-generic, operatingsystem=Ubuntu 14.04.3 LTS, storagedriver=aufs
|
||||
Host-3: 192.168.0.3:2375
|
||||
└ Containers: 1
|
||||
└ Reserved CPUs: 0 / 8
|
||||
└ Reserved Memory: 0 B / 16.46 GiB
|
||||
└ Labels: color=green, executiondriver=native-0.2, kernelversion=3.16.0-30-generic, operatingsystem=Ubuntu 14.04.3 LTS, storagedriver=aufs
|
||||
CPUs: 12
|
||||
Total Memory: 20.51 GiB
|
||||
Name: 946d65606f7c
|
||||
```
|
||||
|
||||
###Affinity Filter
|
||||
通过使用 Affinity Filter,可以让一个容器紧挨着另一个容器启动,也就是说让两个容器在同一个节点上面启动。
|
||||
### Affinity 过滤器
|
||||
Affinity 过滤器允许用户在启动一个容器的时候,让它分配到某个已有容器的节点上。
|
||||
|
||||
例如,下面我们将启动一个 nginx 容器,让它分配到已经运行某个 ubuntu 容器的节点上。
|
||||
|
||||
在 Constraint 过滤器的示例中,我们分别启动了两个 ubuntu 容器 `sick_galileo` 和 `compassionate_ritchie`,分别在 Host-2 和 Host-3 上。
|
||||
|
||||
现在其中一台机器上面启动一个 redis 容器。
|
||||
```bash
|
||||
rio@085:~$ sudo docker -H 192.168.1.83:2376 run -d --name redis redis
|
||||
ea13eddf667992c5d8296557d3c282dd8484bd262c81e2b5af061cdd6c82158d
|
||||
rio@085:~$ sudo docker -H 192.168.1.83:2376 ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
ea13eddf6679 redis:latest /entrypoint.sh redis 24 minutes ago Up Less than a second 6379/tcp 083/redis
|
||||
现在启动一个 nginx 容器,让它跟容器 `sick_galileo` 放在一起,都放到 Host-2 节点上。可以通过 `-e affinity:container==<name or id>` 参数来实现。
|
||||
|
||||
```sh
|
||||
$ docker -H 192.168.0.2:12375 run -d -e affinity:container==sick_galileo nginx
|
||||
```
|
||||
|
||||
然后再次启动两个 redis 容器。
|
||||
```bash
|
||||
rio@085:~$ sudo docker -H 192.168.1.83:2376 run -d --name redis_1 -e affinity:container==redis redis
|
||||
bac50c2e955211047a745008fd1086eaa16d7ae4f33c192f50412e8dcd0a14cd
|
||||
rio@085:~$ sudo docker -H 192.168.1.83:2376 run -d --name redis_1 -e affinity:container==redis redis
|
||||
bac50c2e955211047a745008fd1086eaa16d7ae4f33c192f50412e8dcd0a14cd
|
||||
```
|
||||
现在来查看下运行结果,可以看到三个容器都是在一台机器上运行
|
||||
```bash
|
||||
rio@085:~$ sudo docker -H 192.168.1.83:2376 ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
449ed25ad239 redis:latest /entrypoint.sh redis 24 minutes ago Up Less than a second 6379/tcp 083/redis_2
|
||||
bac50c2e9552 redis:latest /entrypoint.sh redis 25 minutes ago Up 10 seconds 6379/tcp 083/redis_1
|
||||
ea13eddf6679 redis:latest /entrypoint.sh redis 28 minutes ago Up 3 minutes 6379/tcp 083/redis
|
||||
```
|
||||
通过 `-e affinity:image=image_name` 命令可以指定只有已经下载了`image_name`镜像的机器才运行容器
|
||||
```bash
|
||||
sudo docker –H 192.168.1.83:2376 run –name redis1 –d –e affinity:image==redis redis
|
||||
```
|
||||
redis1 这个容器只会在已经下载了 redis 镜像的节点上运行。
|
||||
然后启动一个 redis 容器,让它跟容器 `compassionate_ritchie` 放在一起,都放到 Host-3 节点上。
|
||||
|
||||
```bash
|
||||
sudo docker -H 192.168.1.83:2376 run -d --name redis -e affinity:image==~redis redis
|
||||
```
|
||||
这条命令达到的效果是:在有 redis 镜像的节点上面启动一个名字叫做 redis 的容器,如果每个节点上面都没有 redis 容器,就按照默认的策略启动 redis 容器。
|
||||
|
||||
###Port Filter
|
||||
Port 也会被认为是一个唯一的资源
|
||||
```bash
|
||||
sudo docker -H 192.168.1.83:2376 run -d -p 80:80 nginx
|
||||
```sh
|
||||
$ docker -H 192.168.0.2:12375 run -d -e affinity:container==compassionate_ritchie redis
|
||||
```
|
||||
|
||||
执行完这条命令,之后任何使用 80 端口的容器都是启动失败。
|
||||
查看所有容器运行情况。
|
||||
|
||||
```sh
|
||||
$ docker -H 192.168.0.2:12375 ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
0a32f15aa8ee redis "/entrypoint.sh redis" 2 seconds ago Up 1 seconds 6379/tcp Host-3/awesome_darwin
|
||||
d2b9a53e67d5 nginx "nginx -g 'daemon off" 29 seconds ago Up 28 seconds 80/tcp, 443/tcp Host-2/fervent_wilson
|
||||
252ffb48e64e ubuntu:14.04 "ping 127.0.0.1" 2 minutes ago Up 2 minutes Host-2/sick_galileo
|
||||
3d6f8d7af858 ubuntu:14.04 "ping 127.0.0.1" 3 minutes ago Up 3 minutes Host-3/compassionate_ritchie
|
||||
```
|
||||
|
||||
### 其它过滤器
|
||||
其它过滤器的使用方法也是大同小异,例如通过 `-e affinity:image==<name or id>` 来选择拥有指定镜像的节点;通过 `-e affinity:label_name==value` 来选择拥有指定标签的容器所允许的节点。
|
||||
|
||||
此外,当容器端口需要映射到宿主机指定端口号的时候,Swarm 也会自动分配容器到指定宿主机端口可用的节点。
|
||||
|
||||
当不同容器之间存在数据卷或链接依赖的时候,Swarm 会分配这些容器到同一个节点上。
|
||||
|
||||
@@ -1,9 +1,81 @@
|
||||
## 安装
|
||||
安装swarm的最简单的方式是使用Docker官方的swarm镜像
|
||||
> $ sudo docker pull swarm
|
||||
## 安装 Swarm
|
||||
Swarm 安装有几种方式,可以基于 Docker Machine 来进行安装,也可以手动配置。为了能更容易理解 Swarm 的组件和更灵活的进行管理,推荐使用手动配置方式。
|
||||
|
||||
可以使用下面的命令来查看swarm是否成功安装。
|
||||
> $ sudo docker run --rm swarm -v
|
||||
|
||||
输出下面的形式则表示成功安装(具体输出根据swarm的版本变化)
|
||||
> swarm version 0.2.0 (48fd993)
|
||||
对于 Docker 1.12+ 版本,Swarm 相关命令已经原生嵌入到了 Docker engine 的支持,对于较低版本的 Docker,需要额外进行配置。
|
||||
|
||||
### 下载镜像
|
||||
Docker 官方已经提供了 Swarm 镜像使用,需要在所有被 Swarm 管理的 Docker 主机上下载该镜像。
|
||||
|
||||
```sh
|
||||
$ docker pull swarm
|
||||
```
|
||||
|
||||
可以使用下面的命令来查看 Swarm 版本,验证是否成功下载 Swarm 镜像。
|
||||
|
||||
```sh
|
||||
$ docker run --rm swarm -v
|
||||
swarm version 1.2.2 (34e3da3)
|
||||
```
|
||||
|
||||
### 配置节点
|
||||
Docker 主机在加入 Swarm 集群前,需要进行一些简单配置,添加 Docker daemon 的网络监听。
|
||||
|
||||
例如,在启动 Docker daemon 的时候通过 `-H` 参数:
|
||||
|
||||
```sh
|
||||
$ sudo docker daemon -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock
|
||||
```
|
||||
|
||||
*注:Docker 1.8.0 版本之前不支持 daemon 命令,可以用 -d 代替。*
|
||||
|
||||
如果是通过服务方式启动,则需要修改服务的配置文件。
|
||||
|
||||
以 Ubuntu 14.04 为例,配置文件为 `/etc/default/docker`(其他版本的 Linux 上略有不同)。
|
||||
|
||||
在文件的最后添加:
|
||||
|
||||
```sh
|
||||
DOCKER_OPTS="$DOCKER_OPTS -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock"
|
||||
```
|
||||
|
||||
### 启动集群
|
||||
Docker 集群管理需要使用服务发现(Service Discover)功能,Swarm 支持以下的几种方式:DockerHub、本地文件、etcd、consel、zookeeper 和手动指定节点 IP 地址信息等。
|
||||
|
||||
除了手动指定外,这些方法原理上都是通过维护一套数据库机制,来管理集群中注册节点的 Docker daemon 的访问信息。
|
||||
|
||||
本地配置集群推荐使用 consel 作为服务发现后端。利用社区提供的 Docker 镜像,整个过程只需要三步即可完成。
|
||||
|
||||
#### 启动 Consel 服务后端
|
||||
启动 consel 服务容器,映射到主机的 8500 端口。
|
||||
|
||||
```sh
|
||||
$ docker run -d -p 8500:8500 --name=consul progrium/consul -server -bootstrap
|
||||
```
|
||||
|
||||
获取到本地主机的地址作为 consul 的服务地址:`<consul_ip>:8500`。
|
||||
|
||||
#### 启动管理节点
|
||||
首先,启动一个主管理节点,映射到主机的 4000 端口,并获取所在主机地址为 `<manager0_ip>`。其中 4000 端口是 Swarm 管理器的默认监听端口,用户也可以指定映射为其它端口。
|
||||
|
||||
```sh
|
||||
$ docker run -d -p 4000:4000 swarm manage -H :4000 --replication --advertise <manager0_ip>:4000 consul://<consul_ip>:8500
|
||||
```
|
||||
|
||||
为了提高高可用性,用户也可以启动从管理节点。假定获取所在主机地址为 `<manager1_ip>`。
|
||||
|
||||
```sh
|
||||
$ docker run -d swarm manage -H :4000 --replication --advertise <manager1_ip>:4000 consul://<consul_ip>:8500
|
||||
```
|
||||
|
||||
#### 启动工作节点
|
||||
需要在每个工作节点上启动 agent 服务。
|
||||
|
||||
获取节点的主机地址为 `<node_ip>`,并指定前面获取到的 consel 服务地址。
|
||||
|
||||
```sh
|
||||
$ docker run -d swarm join --advertise=<node_ip>:2375 consul://<consul_ip>:8500
|
||||
```
|
||||
|
||||
节点启动后,用户可以指定 Docker 服务地址为 `<manager0_ip>:4000>` 来测试各种 Docker 命令,可以看到整个 Swarm 集群就像一个虚拟的 Docker 主机一样正常工作。
|
||||
|
||||
由于 Swarm 实际上是通过 agent 调用了本地的 Docker daemon 来运行容器,当 Swarm 集群服务出现故障时,无法接受新的请求,但已经运行起来的容器将不会受到影响。
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
## 简介
|
||||
Docker Swarm 是 Docker公司官方在 2014 年 12月初发布的一套管理 Docker 集群的工具。它将一群 Docker 宿主机变成一个单一的,虚拟的主机。
|
||||
## Swarm 简介
|
||||

|
||||
|
||||
Swarm 使用标准的 Docker API 接口作为其前端访问入口,换言之,各种形式的 Docker 工具比如 Dokku,Compose,Krane,Deis,docker-py,Docker 本身等都可以很容易的与 Swarm 进行集成。
|
||||
Docker Swarm 是 Docker 公司推出的官方容器集群平台,基于 Go 语言实现,代码开源在 [https://github.com/docker/swarm](https://github.com/docker/swarm)。目前,包括 Rackspace 等平台都采用了 Swarm,用户也很容易在 AWS 等公有云平台使用 Swarm。
|
||||
|
||||

|
||||
Swarm 的前身是 Beam 项目和 libswarm 项目,首个正式版本(Swarm V1)在 2014 年 12 月初发布。为了提高可扩展性,2016 年 2 月对架构进行重新设计,推出了 V2 版本,支持超过 1K 个节点。最新的 Docker Engine 已经集成了 SwarmKit,加强了对 Swarm 的协作支持。
|
||||
|
||||
在使用 Swarm 管理docker 集群时,会有一个 swarm manager 以及若干的 swarm node,swarm manager上运行 swarm daemon,用户只需要跟 swarm manager 通信,然后 swarm manager 再根据discovery service的信息选择一个swarm node 来运行container。
|
||||
作为容器集群管理器,Swarm 最大的优势之一就是 100% 支持标准的 Docker API。各种基于标准 API 的工具比如 Compose、docker-py、各种管理软件,甚至 Docker 本身等都可以很容易的与 Swarm 进行集成。这大大方便了用户将原先基于单节点的系统移植到 Swarm 上。同时 Swarm 内置了对 Docker 网络插件的支持,用户可以很容易地部署跨主机的容器集群服务。
|
||||
|
||||
值得注意的是 swarm daemon 只是一个任务调度器(scheduler)和路由器(router),它本身不运行容器,它只接受 Docker client 发送过来的请求,调度合适的 swarm node 来运行 container。这意味着,即使 swarm daemon 由于某些原因挂掉了,已经运行起来的容器也不会有任何影响。
|
||||

|
||||
|
||||
上图是来自官方的 V1 结构图。可以看出,Swarm 是典型的 master-slave 结构,通过发现服务来选举 manager。manager 是中心管理节点,各个 node 上运行 agent 接受 manager 的统一管理。
|
||||
|
||||
有以下两点需要注意:
|
||||
在 V2 中,集群中会自动通过 Raft 协议分布式选举出 manager 节点,无需额外的发现服务支持,避免了单点瓶颈。同时,V2 中内置了基于 DNS 的负载均衡和对外部负载均衡机制的集成支持。
|
||||
|
||||
* 集群中的每台节点上面的 Docker 的版本都不能小于1.4
|
||||
* 为了让 swarm manager 能够跟每台 swarm node 进行通信,集群中的每台节点的 Docker daemon 都必须监听同一个网络接口。
|
||||
目前,Swarm V1 支持 Docker 版本为 1.6.0+,V2 支持 Docker 版本为 1.12.0+。本章将以 Swarm V1 为主进行介绍,并结合 V2 的部分最新特性。
|
||||
|
||||
@@ -1,73 +1,73 @@
|
||||
## swarm 调度策略
|
||||
swarm支持多种调度策略来选择节点。每次在swarm启动container的时候,swarm会根据选择的调度策略来选择节点运行container。目前支持的有:spread,binpack和random。
|
||||
## Swarm 中的调度器
|
||||
调度是集群十分重要的功能,Swarm 目前支持三种调度策略:`spread`、`binpack` 和 `random`。
|
||||
|
||||
在执行`swarm manage`命令启动 swarm 集群的时候可以通过 `--strategy` 参数来指定,默认的是spread。
|
||||
在执行`swarm manage`命令启动管理服务的时候,可以通过 `--strategy` 参数指定调度策略,默认的是 `spread`。
|
||||
|
||||
spread和binpack策略会根据每台节点的可用CPU,内存以及正在运行的containers的数量来给各个节点分级,而random策略,顾名思义,他不会做任何的计算,只是单纯的随机选择一个节点来启动container。这种策略一般只做调试用。
|
||||
简单来说,这三种调度策略的优化目标如下:
|
||||
|
||||
使用spread策略,swarm会选择一个正在运行的container的数量最少的那个节点来运行container。这种情况会导致启动的container会尽可能的分布在不同的机器上运行,这样的好处就是如果有节点坏掉的时候不会损失太多的container。
|
||||
* `spread`:如果节点配置相同,选择一个正在运行的容器数量最少的那个节点,即尽量平摊容器到各个节点;
|
||||
* `binpack`:跟 `spread` 相反,尽可能的把所有的容器放在一台节点上面运行,即尽量少用节点,避免容器碎片化。
|
||||
* `random`:直接随机分配,不考虑集群中节点的状态,方便进行测试使用。
|
||||
|
||||
binpack 则相反,这种情况下,swarm会尽可能的把所有的容器放在一台节点上面运行。这种策略会避免容器碎片化,因为他会把未使用的机器分配给更大的容器,带来的好处就是swarm会使用最少的节点运行最多的容器。
|
||||
### spread 调度策略
|
||||
仍然以之前创建好的集群为例,来演示下 spread 策略的行为。
|
||||
|
||||
### spread 策略
|
||||
先来演示下 spread 策略的情况。
|
||||
```bash
|
||||
rio@083:~$ sudo docker run -d -p 2376:2375 -v $(pwd)/cluster:/tmp/cluster swarm manage --strategy=spread file:///tmp/cluster
|
||||
7609ac2e463f435c271d17887b7d1db223a5d696bf3f47f86925c781c000cb60
|
||||
ats@sclu083:~$ sudo docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
7609ac2e463f swarm:latest "/swarm manage --str 6 seconds ago Up 5 seconds 0.0.0.0:2376->2375/tcp focused_babbage
|
||||
```
|
||||
三台机器除了83运行了 Swarm之外,其他的都没有运行任何一个容器,现在在85这台节点上面在swarm集群上启动一个容器
|
||||
```bash
|
||||
rio@085:~$ sudo docker -H 192.168.1.83:2376 run --name node-1 -d -P redis
|
||||
2553799f1372b432e9b3311b73e327915d996b6b095a30de3c91a47ff06ce981
|
||||
rio@085:~$ sudo docker -H 192.168.1.83:2376 ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
2553799f1372 redis:latest /entrypoint.sh redis 24 minutes ago Up Less than a second 192.168.1.84:32770->6379/tcp 084/node-1
|
||||
```
|
||||
启动一个 redis 容器,查看结果
|
||||
```bash
|
||||
在 `192.168.0.2` 节点启动管理服务,管理 token://946d65606f7c2f49766e4dddac5b4365 的集群。
|
||||
|
||||
rio@085:~$ sudo docker -H 192.168.1.83:2376 run --name node-2 -d -P redis
|
||||
7965a17fb943dc6404e2c14fb8585967e114addca068f233fcaf60c13bcf2190
|
||||
rio@085:~$ sudo docker -H 192.168.1.83:2376 ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
7965a17fb943 redis:latest /entrypoint.sh redis Less than a second ago Up 1 seconds 192.168.1.124:49154->6379/tcp 124/node-2
|
||||
2553799f1372 redis:latest /entrypoint.sh redis 29 minutes ago Up 4 minutes 192.168.1.84:32770->6379/tcp 084/node-1
|
||||
```
|
||||
再次启动一个 redis 容器,查看结果
|
||||
```bash
|
||||
rio@085:~$ sudo docker -H 192.168.1.83:2376 run --name node-3 -d -P redis
|
||||
65e1ed758b53fbf441433a6cb47d288c51235257cf1bf92e04a63a8079e76bee
|
||||
rio@085:~$ sudo docker -H 192.168.1.83:2376 ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
7965a17fb943 redis:latest /entrypoint.sh redis Less than a second ago Up 4 minutes 192.168.1.227:49154->6379/tcp 124/node-2
|
||||
65e1ed758b53 redis:latest /entrypoint.sh redis 25 minutes ago Up 17 seconds 192.168.1.83:32770->6379/tcp 083/node-3
|
||||
2553799f1372 redis:latest /entrypoint.sh redis 33 minutes ago Up 8 minutes 192.168.1.84:32770->6379/tcp 084/node-1
|
||||
```
|
||||
可以看到三个容器都是分布在不同的节点上面的。
|
||||
|
||||
### binpack 策略
|
||||
现在来看看binpack策略下的情况。在083上面执行命令:
|
||||
```bash
|
||||
rio@083:~$ sudo docker run -d -p 2376:2375 -v $(pwd)/cluster:/tmp/cluster swarm manage --strategy=binpack file:///tmp/cluster
|
||||
f1c9affd5a0567870a45a8eae57fec7c78f3825f3a53fd324157011aa0111ac5
|
||||
```sh
|
||||
$ docker run -d -p 12375:2375 swarm manage --strategy "spread" token://946d65606f7c2f49766e4dddac5b4365
|
||||
c6f25e6e6abbe45c8bcf75ac674f2b64d5f31a5c6070d64ba954a0309b197930
|
||||
```
|
||||
|
||||
现在在集群中启动三个 redis 容器,查看分布情况:
|
||||
```bash
|
||||
rio@085:~$ sudo docker -H 192.168.1.83:2376 run --name node-1 -d -P redis
|
||||
18ceefa5e86f06025cf7c15919fa64a417a9d865c27d97a0ab4c7315118e348c
|
||||
rio@085:~$ sudo docker -H 192.168.1.83:2376 run --name node-2 -d -P redis
|
||||
7e778bde1a99c5cbe4701e06935157a6572fb8093fe21517845f5296c1a91bb2
|
||||
rio@085:~$ sudo docker -H 192.168.1.83:2376 run --name node-3 -d -P redis
|
||||
2195086965a783f0c2b2f8af65083c770f8bd454d98b7a94d0f670e73eea05f8
|
||||
rio@085:~$ sudo docker -H 192.168.1.83:2376 ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
2195086965a7 redis:latest /entrypoint.sh redis 24 minutes ago Up Less than a second 192.168.1.83:32773->6379/tcp 083/node-3
|
||||
7e778bde1a99 redis:latest /entrypoint.sh redis 24 minutes ago Up Less than a second 192.168.1.83:32772->6379/tcp 083/node-2
|
||||
18ceefa5e86f redis:latest /entrypoint.sh redis 25 minutes ago Up 22 seconds 192.168.1.83:32771->6379/tcp 083/node-1
|
||||
列出集群中节点。
|
||||
|
||||
```sh
|
||||
$ docker run --rm swarm list token://946d65606f7c2f49766e4dddac5b4365
|
||||
192.168.0.3:2375
|
||||
192.168.0.2:2375
|
||||
```
|
||||
|
||||
可以看到,所有的容器都是分布在同一个节点上运行的。
|
||||
此时,两个节点上除了 swarm 外都没有运行其它容器。
|
||||
|
||||
启动一个 ubuntu 容器。
|
||||
|
||||
```sh
|
||||
$ docker -H 192.168.0.2:12375 run -d ubuntu:14.04 ping 127.0.0.1
|
||||
bac3dfda5306181140fc959969d738549d607bc598390f57bdd432d86f16f069
|
||||
```
|
||||
|
||||
查看发现它实际上被调度到了 `192.168.0.3` 节点(当节点配置相同时候,初始节点随机选择)。
|
||||
|
||||
再次启动一个 ubuntu 容器。
|
||||
|
||||
```sh
|
||||
$ docker -H 192.168.0.2:12375 run -d ubuntu:14.04 ping 127.0.0.1
|
||||
8247067ba3a31e0cb692a8373405f95920a10389ce3c2a07091408281695281c
|
||||
```
|
||||
|
||||
查看它的位置,发现被调度到了另外一个节点:`192.168.0.2` 节点。
|
||||
|
||||
```sh
|
||||
$ docker -H 192.168.0.2:12375 ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
8247067ba3a3 ubuntu:14.04 "ping 127.0.0.1" 1 minutes ago Up 1 minutes Host-2/sick_galileo
|
||||
bac3dfda5306 ubuntu:14.04 "ping 127.0.0.1" 2 minutes ago Up 2 minutes Host-3/compassionate_ritchie
|
||||
```
|
||||
|
||||
当节点配置不同的时候,`spread`会更愿意分配到配置较高的节点上。
|
||||
|
||||
### binpack 调度策略
|
||||
现在来看看 `binpack` 策略下的情况。
|
||||
|
||||
直接启动若干 ubuntu 容器,并查看它们的位置。
|
||||
|
||||
```sh
|
||||
$ docker -H 192.168.0.2:12375 run -d ubuntu:14.04 ping 127.0.0.1
|
||||
$ docker -H 192.168.0.2:12375 ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
4c4f45eba866 ubuntu:14.04 "ping 127.0.0.1" 3 minutes ago Up 3 minutes Host-3/hopeful_brown
|
||||
5e650541233c ubuntu:14.04 "ping 127.0.0.1" 3 minutes ago Up 3 minutes Host-3/pensive_wright
|
||||
99c5a092530a ubuntu:14.04 "ping 127.0.0.1" 3 minutes ago Up 3 minutes Host-3/naughty_engelbart
|
||||
4ab392c26eb2 ubuntu:14.04 "ping 127.0.0.1" 3 minutes ago Up 3 minutes Host-3/thirsty_mclean
|
||||
```
|
||||
可以看到,所有的容器都是分布在同一个节点(`192.168.0.3`)上运行的。
|
||||
97
swarm/servicebackend.md
Normal file
97
swarm/servicebackend.md
Normal file
@@ -0,0 +1,97 @@
|
||||
## 使用其它服务发现后端
|
||||
|
||||
Swarm 目前可以支持多种服务发现后端,这些后端功能上都是一致的,即维护属于某个集群的节点的信息。不同方案并无优劣之分,在实际使用时候,可以结合自身需求和环境限制进行选择,甚至自己定制其它方案。
|
||||
|
||||
使用中可以通过不同的路径来选择特定的服务发现后端机制。
|
||||
|
||||
* `token://<token>`:使用 DockerHub 提供的服务,适用于可以访问公网情况;
|
||||
* `file://path/to/file`:使用本地文件,需要手动管理;
|
||||
* `consul://<ip>/<path>`:使用 consul 服务,私有环境推荐;
|
||||
* `etcd://<ip1>,<ip2>/<path>`:使用 etcd 服务,私有环境推荐;
|
||||
* `zk://<ip1>,<ip2>/<path>`:使用 zookeeper 服务,私有环境推荐;
|
||||
* `[nodes://]<ip1>,<ip2>`:手动指定集群中节点的地址,方便进行服务测试。
|
||||
|
||||
### 使用文件
|
||||
|
||||
使用本地文件的方式十分简单,就是讲所有属于某个集群的节点的 Docker daemon 信息写入一个文件中,然后让 manager 从这个文件中直接读取相关信息。
|
||||
|
||||
首先,在 Swarm 管理节点(`192.168.0.2`)上新建一个文件,把要加入集群的机器的 Docker daemon 信息写入文件:
|
||||
|
||||
```sh
|
||||
$ tee /tmp/cluster_info <<-'EOF'
|
||||
192.168.0.2:2375
|
||||
192.168.0.3:2375
|
||||
EOF
|
||||
```
|
||||
|
||||
然后,本地执行 `swarm manage` 命令,并指定服务发现机制为本地文件,注意因为是容器方式运行 manager,需要将本地文件挂载到容器内。
|
||||
|
||||
```sh
|
||||
$ docker run -d -p 12375:2375 -v /tmp/cluster_info:/tmp/cluster_info swarm manage file:///tmp/cluster_info
|
||||
```
|
||||
|
||||
接下来就可以通过使用 Swarm 服务来进行管理了,例如使用 info 查看所有节点的信息。
|
||||
|
||||
```sh
|
||||
$ docker -H 192.168.0.2:12375 info
|
||||
Containers: 18
|
||||
Images: 36
|
||||
Role: primary
|
||||
Strategy: spread
|
||||
Filters: health, port, dependency, affinity, constraint
|
||||
Nodes: 2
|
||||
Host-1: 192.168.0.2:2375
|
||||
└ Containers: 15
|
||||
└ Reserved CPUs: 0 / 4
|
||||
└ Reserved Memory: 1 GiB / 4.053 GiB
|
||||
└ Labels: executiondriver=native-0.2, kernelversion=3.16.0-43-generic, operatingsystem=Ubuntu 14.04.3 LTS, storagedriver=aufs
|
||||
Host-2: 192.168.0.3:2375
|
||||
└ Containers: 3
|
||||
└ Reserved CPUs: 0 / 8
|
||||
└ Reserved Memory: 0 B / 16.46 GiB
|
||||
└ Labels: executiondriver=native-0.2, kernelversion=3.16.0-30-generic, operatingsystem=Ubuntu 14.04.3 LTS, storagedriver=aufs
|
||||
CPUs: 12
|
||||
Total Memory: 20.51 GiB
|
||||
Name: e71eb5f1d48b
|
||||
```
|
||||
|
||||
### 其它发现服务后端
|
||||
其它服务发现后端的使用方法,也是大同小异,不同之处在于使用 Swarm 命令时指定的路径格式不同。
|
||||
|
||||
例如,对于前面介绍的 consul 服务后端来说。
|
||||
|
||||
快速部署一个 consul 服务的命令为:
|
||||
|
||||
```sh
|
||||
$ docker run -d -p 8500:8500 --name=consul progrium/consul -server -bootstrap
|
||||
```
|
||||
|
||||
之后创建 Swarm 的管理服务,指定使用 consul 服务,管理端口监听在本地的 4000 端口。
|
||||
|
||||
```sh
|
||||
$ docker run -d -p 4000:4000 swarm manage -H :4000 --replication --advertise <manager_ip>:4000 consul://<consul_ip>:8500
|
||||
```
|
||||
|
||||
Swarm 节点注册时候命令格式类似于:
|
||||
|
||||
```sh
|
||||
$ swarm join --advertise=<node_ip:2375> consul://<consul_addr>/<optional path prefix>
|
||||
```
|
||||
|
||||
对于 etcd 服务后端来说,节点注册时候命令格式类似于:
|
||||
|
||||
```sh
|
||||
$ swarm join --addr=<node_addr:2375> etcd://<etcd_addr1>,<etcd_addr2>/<optional path prefix>
|
||||
```
|
||||
启动管理服务时候,格式类似于:
|
||||
|
||||
```sh
|
||||
$ swarm manage -H tcp://<manager_ip>:4000 etcd://<etcd_addr1>,<etcd_addr2>/<optional path prefix>
|
||||
```
|
||||
|
||||
### 地址和端口的范围匹配
|
||||
对于基于文件,以及手动指定节点信息两种服务发现后端机制来说,其中地址和端口域可以支持指定一个范围,以一次性指定多个地址。
|
||||
例如:
|
||||
|
||||
* `192.168.0.[2:10]:2375` 代表 `192.168.0.2:2375` -- `192.168.0.10:2375` 一共 9 个地址;
|
||||
* `192.168.0.2:[2:9]375` 代表 `192.168.0.2:2375` -- `192.168.0.2:9375` 一共 8 个地址。
|
||||
10
swarm/summary.md
Normal file
10
swarm/summary.md
Normal file
@@ -0,0 +1,10 @@
|
||||
## 本章小结
|
||||
本章笔者介绍了 Docker Swarm 的安装、使用和主要功能。
|
||||
|
||||
通过使用 Swarm,用户可以将若干 Docker 主机节点组成的集群当作一个大的虚拟 Docker 主机使用。并且,原先基于单机的 Docker 应用,可以无缝的迁移到 Swarm 上来。
|
||||
|
||||
实现这些功能的前提是服务自动发现能力。在现代分布式系统中,服务的自动发现、注册、更新等能力将成为系统的基本保障和重要基础。
|
||||
|
||||
在生产环境中,Swarm 的管理节点和发现服务后端要采用高可用性上的保护,可以采用集群模式。
|
||||
|
||||
值得一提的是,Swarm V2 功能已经被无缝嵌入到了 Docker 1.12+ 版本中,用户今后可以直接使用 Docker 命令来完成相关功能的配置,这将使得集群功能的管理更加简便。
|
||||
297
swarm/usage.md
297
swarm/usage.md
@@ -1,170 +1,181 @@
|
||||
## 使用
|
||||
在使用 swarm 管理集群前,需要把集群中所有的节点的 docker daemon 的监听方式更改为 `0.0.0.0:2375`。
|
||||
## 使用 Swarm
|
||||
前面演示了基于 consel 服务发现后端来配置一个本地 Swarm 集群。其中,consel 也可以被替换为 etcd、zookeeper 等。
|
||||
|
||||
可以有两种方式达到这个目的,第一种是在启动docker daemon的时候指定
|
||||
```bash
|
||||
sudo docker -H 0.0.0.0:2375&
|
||||
另外一个更方便的方式是直接使用 DockerHub 提供的免费服务发现后端。
|
||||
|
||||
下面使用这种方式来演示 Swarm 的主要操作,包括:
|
||||
|
||||
* create:创建一个集群;
|
||||
* list:列出集群中的节点;
|
||||
* manage:管理一个集群;
|
||||
* join:让节点加入到某个集群。
|
||||
|
||||
注意,使用 DockerHub 的服务发现后端,需要各个节点能通过公网访问到 DockerHub 的服务接口。
|
||||
|
||||
### 创建集群 id
|
||||
|
||||
在任意一台安装了 Swarm 的机器上执行 `swarm create` 命令来在 DockerHub 服务上进行注册。
|
||||
|
||||
Swarm 会通过服务发现后端(此处为 DockerHub 提供)来获取一个唯一的由数字和字母组成的 token,用来标识要管理的集群。
|
||||
|
||||
```sh
|
||||
$ docker run --rm swarm create
|
||||
946d65606f7c2f49766e4dddac5b4365
|
||||
```
|
||||
|
||||
第二种方式是直接修改 Docker 的配置文件(Ubuntu 上是 `/etc/default/docker`,其他版本的 Linux 上略有不同)
|
||||
注意返回的字符串,这是集群的唯一 id,加入集群的各个节点将需要这个信息。
|
||||
|
||||
在文件的最后添加下面这句代码:
|
||||
```bash
|
||||
DOCKER_OPTS="-H 0.0.0.0:2375 -H unix:///var/run/docker.sock"
|
||||
### 配置集群节点
|
||||
|
||||
在所有要加入集群的普通节点上面执行 `swarm join` 命令,表示把这台机器加入指定集群当中。
|
||||
|
||||
例如某台机器 IP 地址为 `192.168.0.2`,将其加入我们刚创建的 `946d65606f7c2f49766e4dddac5b4365` 集群,则可以通过:
|
||||
|
||||
```sh
|
||||
$ docker run --rm swarm join --addr=192.168.0.2:2375 token://946d65606f7c2f49766e4dddac5b4365
|
||||
time="2015-12-09T08:59:43Z" level=info msg="Registering on the discovery service every 20s..." addr="192.168.0.2:2375" discovery="token://946d65606f7c2f49766e4dddac5b4365"
|
||||
...
|
||||
```
|
||||
|
||||
*注:其中 `--addr` 指定的 IP 地址信息将被发送给服务发现后端,用以区分集群不同的节点。manager 服务必须要通过这个地址可以访问到该节点。*
|
||||
|
||||
需要注意的是,一定要在所有希望被 Swarm 管理的节点上进行的。修改之后要重启 Docker
|
||||
```bash
|
||||
sudo service docker restart
|
||||
通过控制台可以看到,上述命令执行后,默认每隔 20 秒(可以通过 `--heartbeat` 选项指定),会输出一条心跳信息。对于发现服务后端来说,默认如果超过 60 秒(可以通过 `--ttl` 选项指定)没有收到心跳信息,则将节点从列表中删除。
|
||||
|
||||
如果不希望看到输出日志信息,则可以用 `-d` 选项替换 `--rm` 选项,让服务后台执行。
|
||||
|
||||
执行 `swarm join` 命令实际上是通过 agent 把自己的信息注册到发现服务上,因此,此时对于后端的发现服务来说,已经可以看到有若干节点注册上来了。那么,如何管理和使用这些节点呢,这就得需要 Swarm 的 manager 服务了。
|
||||
|
||||
|
||||
### 配置管理节点
|
||||
配置管理节点需要通过 `swarm manage` 命令,该命令将启动 manager 服务,默认监听到 `2375` 端口,所有对集群的管理可以通过该服务接口进行。
|
||||
|
||||
读者可能注意到,manager 服务默认监听的端口跟 Docker 服务监听端口是一样的,这是为了兼容其它基于 Docker 的服务,可以无缝地切换到 Swarm 平台上来。
|
||||
|
||||
仍然在节点 `192.168.0.2` 进行操作。由于我们是采用 Docker 容器形式启动 manager 服务,本地的 `2375` 端口已经被 Docker Daemon 占用。我们将 manager 服务监听端口映射到本地一个空闲的 `12375` 端口。
|
||||
|
||||
```sh
|
||||
$ docker run -d -p 12375:2375 swarm manage token://946d65606f7c2f49766e4dddac5b4365
|
||||
1e1ca8c4117b6b7271efc693f9685b4e907d8dc95324350392b21e94b3cffd18
|
||||
```
|
||||
|
||||
Docker 集群管理需要使用服务发现(Discovery service backend)功能,Swarm支持以下的几种方式:DockerHub 提供的服务发现功能,本地的文件,etcd,consul,zookeeper 和 IP 列表,本文会详细讲解前两种方式,其他的用法都是大同小异的。
|
||||
可以通过 `docker ps` 命令来查看启动的 swarm manager 服务容器。
|
||||
|
||||
先说一下本次试验的环境,本次试验包括三台机器,IP地址分别为192.168.1.84,192.168.1.83和192.168.1.124.利用这三台机器组成一个docker集群,其中83这台机器同时充当swarm manager节点。
|
||||
|
||||
### 使用 DockerHub 提供的服务发现功能
|
||||
|
||||
#### 创建集群 token
|
||||
|
||||
在上面三台机器中的任何一台机器上面执行 `swarm create` 命令来获取一个集群标志。这条命令执行完毕后,Swarm 会前往 DockerHub 上内置的发现服务中获取一个全球唯一的 token,用来标识要管理的集群。
|
||||
```bash
|
||||
sudo docker run --rm swarm create
|
||||
```sh
|
||||
$ docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
1e1ca8c4117b swarm "/swarm manage token:" 11 seconds ago Up 10 seconds 0.0.0.0:12375->2375/tcp jovial_rosalind
|
||||
```
|
||||
|
||||
我们在84这台机器上执行这条命令,输出如下:
|
||||
```bash
|
||||
rio@084:~$ sudo docker run --rm swarm create
|
||||
b7625e5a7a2dc7f8c4faacf2b510078e
|
||||
命令如果执行成功会返回刚启动的 Swarm 容器的 ID,此时一个简单的 Swarm 集群就已经搭建起来了,包括一个普通节点和一个管理节点。
|
||||
|
||||
### 查看集群节点列表
|
||||
|
||||
集群启动成功以后,用户可以在任何一台节点上使用 `swarm list` 命令查看集群中的节点列表。例如
|
||||
|
||||
```sh
|
||||
$ docker run --rm swarm list token://946d65606f7c2f49766e4dddac5b4365
|
||||
192.168.0.2:2375
|
||||
```
|
||||
显示正是之前用 `swarm join` 命令加入集群的节点的地址。
|
||||
|
||||
我们在另外一台节点 `192.168.0.3` 上同样使用 `swarm join` 命令新加入一个节点:
|
||||
```sh
|
||||
$docker run --rm swarm join --addr=192.168.0.3:2375 token://946d65606f7c2f49766e4dddac5b4365
|
||||
time="2015-12-10T02:05:34Z" level=info msg="Registering on the discovery service every 20s..." addr="192.168.0.3:2375" discovery="token://946d65606f7c2f49766e4dddac5b4365"
|
||||
...
|
||||
```
|
||||
|
||||
可以看到我们返回的 token 是 `b7625e5a7a2dc7f8c4faacf2b510078e`,每次返回的结果都是不一样的。这个 token 一定要记住,后面的操作都会用到这个 token。
|
||||
再次使用 `swarm list` 命令查看集群中的节点列表信息,可以看到新加入的节点:
|
||||
|
||||
#### 加入集群
|
||||
|
||||
在所有要加入集群的节点上面执行 `swarm join` 命令,表示要把这台机器加入这个集群当中。在本次试验中,就是要在 83、84 和 124 这三台机器上执行下面的这条命令:
|
||||
```bash
|
||||
sudo docker run -d swarm join --addr=ip_address:2375 token://token_id
|
||||
```sh
|
||||
$ docker run --rm swarm list token://946d65606f7c2f49766e4dddac5b4365
|
||||
192.168.0.3:2375
|
||||
192.168.0.2:2375
|
||||
```
|
||||
其中的 ip_address 换成执行这条命令的机器的 IP,token_id 换成上一步执行 `swarm create` 返回的 token。
|
||||
|
||||
在83这台机器上面的执行结果如下:
|
||||
```bash
|
||||
rio@083:~$ sudo docker run -d swarm join --addr=192.168.1.83:2375 token://b7625e5a7a2dc7f8c4faacf2b510078e
|
||||
3b3d9da603d7c121588f796eab723458af5938606282787fcbb03b6f1ac2000b
|
||||
### 使用集群服务
|
||||
那么,怎么使用 Swarm 提供的服务呢?
|
||||
|
||||
实际上,所有 Docker 客户端可以继续使用,只要指定使用 Swarm manager 服务的监听地址即可。
|
||||
|
||||
例如,manager 服务监听的地址为 `192.168.0.2:12375`,则可以通过指定 `-H 192.168.0.2:12375` 选项来继续使用 Docker 客户端,执行任意 Docker 命令,例如 `ps`、`info`、`run` 等等。
|
||||
|
||||
在任意节点上使用 `docker run` 来启动若干容器,例如
|
||||
|
||||
```sh
|
||||
$docker -H 192.168.0.2:12375:12375 run -d ubuntu ping 127.0.0.1
|
||||
4c9bccbf86fb6e2243da58c1b15e9378fac362783a663426bbe7058eea84de46
|
||||
```
|
||||
这条命令通过 `-d` 参数启动了一个容器,使得83这台机器加入到集群。如果这个容器被停止或者被删除,83这台机器就会从集群中消失。
|
||||
|
||||
#### 启动swarm manager
|
||||
因为我们要使用 83 这台机器充当 swarm 管理节点,所以需要在83这台机器上面执行 `swarm manage` 命令:
|
||||
```bash
|
||||
sudo docker run -d -p 2376:2375 swarm manage token://b7625e5a7a2dc7f8c4faacf2b510078e
|
||||
使用 `ps` 命令查看集群中正在运行的容器。
|
||||
|
||||
```sh
|
||||
$ docker -H 192.168.0.2:12375 ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
4c9bccbf86fb ubuntu "ping 127.0.0.1" About a minute ago Up About a minute clever_wright
|
||||
730061a3801a registry:latest "docker-registry" 2 minutes ago Up 2 minutes 192.168.0.2:5000->5000/tcp Host-1/registry_registry_1
|
||||
72d99f24a06f redis:3.0 "/entrypoint.sh redis" 2 minutes ago Up 2 minutes 6379/tcp Host-1/registry_redis_1,Host-1/registry_registry_1/redis,Host-1/registry_registry_1/redis_1,Host-1/registry_registry_1/registry_redis_1
|
||||
```
|
||||
执行结果如下:
|
||||
```bash
|
||||
rio@083:~$ sudo docker run -d -p 2376:2375 swarm manage token://b7625e5a7a2dc7f8c4faacf2b510078e
|
||||
83de3e9149b7a0ef49916d1dbe073e44e8c31c2fcbe98d962a4f85380ef25f76
|
||||
```
|
||||
这条命令如果执行成功会返回已经启动的 Swarm 的容器的 ID,此时整个集群已经启动起来了。
|
||||
|
||||
现在通过 `docker ps` 命令来看下有没有启动成功。
|
||||
```bash
|
||||
rio@083:~$ sudo docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
83de3e9149b7 swarm:latest "/swarm manage token 4 minutes ago Up 4 minutes 0.0.0.0:2376->2375/tcp stupefied_stallman
|
||||
```
|
||||
可以看到,Swarm 已经成功启动。
|
||||
在执行 `Swarm manage` 这条命令的时候,有几点需要注意的:
|
||||
输出结果中显示目前集群中正在运行的容器(注意不包括 Swarm manager 服务容器),可以在不同节点上使用 `docker ps` 查看本地容器,发现这些容器实际上可能运行在集群中多个节点上(被 Swarm 调度策略进行分配)。
|
||||
|
||||
* 这条命令需要在充当 swarm 管理者的机器上执行
|
||||
* Swarm 要以 daemon 的形式执行
|
||||
* 映射的端口可以使任意的除了 2375 以外的并且是未被占用的端口,但一定不能是 2375 这个端口,因为 2375 已经被 Docker 本身给占用了。
|
||||
使用 info 查看所有节点的信息。
|
||||
|
||||
集群启动成功以后,现在我们可以在任何一台节点上使用 `swarm list` 命令查看集群中的节点了,本实验在 124 这台机器上执行 `swarm list` 命令:
|
||||
```bash
|
||||
rio@124:~$ sudo docker run --rm swarm list token://b7625e5a7a2dc7f8c4faacf2b510078e
|
||||
192.168.1.84:2375
|
||||
192.168.1.124:2375
|
||||
192.168.1.83:2375
|
||||
```
|
||||
输出结果列出的IP地址正是我们使用 `swarm join` 命令加入集群的机器的IP地址。
|
||||
|
||||
现在我们可以在任何一台安装了 Docker 的机器上面通过命令(命令中要指明swarm manager机器的IP地址)来在集群中运行container了。
|
||||
本次试验,我们在 192.168.1.85 这台机器上使用 `docker info` 命令来查看集群中的节点的信息。
|
||||
|
||||
其中 info 也可以换成其他的 Docker 支持的命令。
|
||||
```bash
|
||||
rio@085:~$ sudo docker -H 192.168.1.83:2376 info
|
||||
Containers: 8
|
||||
```sh
|
||||
$ docker -H 192.168.0.2:12375 info
|
||||
Containers: 18
|
||||
Images: 36
|
||||
Role: primary
|
||||
Strategy: spread
|
||||
Filters: affinity, health, constraint, port, dependency
|
||||
Filters: health, port, dependency, affinity, constraint
|
||||
Nodes: 2
|
||||
sclu083: 192.168.1.83:2375
|
||||
└ Containers: 1
|
||||
└ Reserved CPUs: 0 / 2
|
||||
└ Reserved Memory: 0 B / 4.054 GiB
|
||||
sclu084: 192.168.1.84:2375
|
||||
└ Containers: 7
|
||||
└ Reserved CPUs: 0 / 2
|
||||
└ Reserved Memory: 0 B / 4.053 GiB
|
||||
```
|
||||
结果输出显示这个集群中只有两个节点,IP地址分别是 192.168.1.83 和 192.168.1.84,结果不对呀,我们明明把三台机器加入了这个集群,还有 124 这一台机器呢?
|
||||
经过排查,发现是忘了修改 124 这台机器上面改 docker daemon 的监听方式,只要按照上面的步骤修改写 docker daemon 的监听方式就可以了。
|
||||
|
||||
在使用这个方法的时候,使用swarm create可能会因为网络的原因会出现类似于下面的这个问题:
|
||||
```bash
|
||||
rio@227:~$ sudo docker run --rm swarm create
|
||||
[sudo] password for rio:
|
||||
time="2015-05-19T12:59:26Z" level=fatal msg="Post https://discovery-stage.hub.docker.com/v1/clusters: dial tcp: i/o timeout"
|
||||
```
|
||||
|
||||
### 使用文件
|
||||
|
||||
第二种方法相对于第一种方法要简单得多,也不会出现类似于上面的问题。
|
||||
|
||||
第一步:在 swarm 管理节点上新建一个文件,把要加入集群的机器 IP 地址和端口号写入文件中,本次试验就是要在83这台机器上面操作:
|
||||
```bash
|
||||
rio@083:~$ echo 192.168.1.83:2375 >> cluster
|
||||
rio@083:~$ echo 192.168.1.84:2375 >> cluster
|
||||
rio@083:~$ echo 192.168.1.124:2375 >> cluster
|
||||
rio@083:~$ cat cluster
|
||||
192.168.1.83:2375
|
||||
192.168.1.84:2375
|
||||
192.168.1.124:2375
|
||||
```
|
||||
|
||||
第二步:在083这台机器上面执行 `swarm manage` 这条命令:
|
||||
```bash
|
||||
rio@083:~$ sudo docker run -d -p 2376:2375 -v $(pwd)/cluster:/tmp/cluster swarm manage file:///tmp/cluster
|
||||
364af1f25b776f99927b8ae26ca8db5a6fe8ab8cc1e4629a5a68b48951f598ad
|
||||
```
|
||||
使用`docker ps`来查看有没有启动成功:
|
||||
```bash
|
||||
rio@083:~$ sudo docker ps
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
364af1f25b77 swarm:latest "/swarm manage file: About a minute ago Up About a minute 0.0.0.0:2376->2375/tcp happy_euclid
|
||||
```
|
||||
可以看到,此时整个集群已经启动成功。
|
||||
|
||||
在使用这条命令的时候需要注意的是注意:这里一定要使用-v命令,因为cluster文件是在本机上面,启动的容器默认是访问不到的,所以要通过-v命令共享。
|
||||
|
||||
接下来的就可以在任何一台安装了docker的机器上面通过命令使用集群,同样的,在85这台机器上执行docker info命令查看集群的节点信息:
|
||||
```bash
|
||||
rio@s085:~$ sudo docker -H 192.168.1.83:2376 info
|
||||
Containers: 9
|
||||
Strategy: spread
|
||||
Filters: affinity, health, constraint, port, dependency
|
||||
Nodes: 3
|
||||
atsgxxx: 192.168.1.227:2375
|
||||
└ Containers: 0
|
||||
Host-1: 192.168.0.2:2375
|
||||
└ Containers: 15
|
||||
└ Reserved CPUs: 0 / 4
|
||||
└ Reserved Memory: 0 B / 2.052 GiB
|
||||
sclu083: 192.168.1.83:2375
|
||||
└ Containers: 2
|
||||
└ Reserved CPUs: 0 / 2
|
||||
└ Reserved Memory: 0 B / 4.054 GiB
|
||||
sclu084: 192.168.1.84:2375
|
||||
└ Containers: 7
|
||||
└ Reserved CPUs: 0 / 2
|
||||
└ Reserved Memory: 0 B / 4.053 GiB
|
||||
└ Reserved Memory: 1 GiB / 4.053 GiB
|
||||
└ Labels: executiondriver=native-0.2, kernelversion=3.16.0-43-generic, operatingsystem=Ubuntu 14.04.3 LTS, storagedriver=aufs
|
||||
Host-2: 192.168.0.3:2375
|
||||
└ Containers: 3
|
||||
└ Reserved CPUs: 0 / 8
|
||||
└ Reserved Memory: 0 B / 16.46 GiB
|
||||
└ Labels: executiondriver=native-0.2, kernelversion=3.16.0-30-generic, operatingsystem=Ubuntu 14.04.3 LTS, storagedriver=aufs
|
||||
CPUs: 12
|
||||
Total Memory: 20.51 GiB
|
||||
Name: 1e1ca8c4117b
|
||||
```
|
||||
结果输出显示这个集群目前只有两个节点,地址分别是 `192.168.0.2` 和 `192.168.0.3`。
|
||||
|
||||
类似的,也可以通过 Compose 模板来启动多个服务。不过请注意,要想让服务分布到多个 Swarm 节点上,需要采用版本 2 的写法。
|
||||
|
||||
### 使用网络
|
||||
Swarm 为了支持跨主机的网络,默认采用了 `overlay` 网络类型,实现上通过 vxlan 来构建联通整个 Swarm 集群的网络。
|
||||
|
||||
首先,在集群中所有节点上,添加配置 Docker daemon 选项:
|
||||
|
||||
```
|
||||
--cluster-store=<DISCOVERY_HOST:PORT> --cluster-advertise=<DOCKER_DAEMON_HOST:PORT>
|
||||
```
|
||||
|
||||
以 consul 服务为例,可能类似:
|
||||
|
||||
```sh
|
||||
--cluster-store=consul://<consul 服务地址>:8500 --cluster-advertise=192.168.0.3:2375
|
||||
```
|
||||
|
||||
之后重启 Docker 服务。
|
||||
|
||||
首先,创建一个网络。
|
||||
|
||||
```sh
|
||||
$ docker -H 192.168.0.2:12375 network create swarm_network
|
||||
```
|
||||
|
||||
查看网络,将看到一个 overlay 类型的网络。
|
||||
|
||||
```sh
|
||||
$ docker -H 192.168.0.2:12375 network ls
|
||||
NETWORK ID NAME DRIVER
|
||||
6edf2d16ec97 swarm_network overlay
|
||||
```
|
||||
|
||||
此时,所有添加到这个网络上的容器将自动被分配到集群中的节点上,并且彼此联通。
|
||||
Reference in New Issue
Block a user