Split out the swarm scheduling and filter sections

This commit is contained in:
Baohua Yang 2015-05-21 19:57:58 +08:00
parent 4cb1252a98
commit c814568560
5 changed files with 149 additions and 152 deletions

View File

@ -1,7 +1,7 @@
Docker —— 从入门到实践
===============
v0.4
v0.4.1
[Docker](docker.com) 是个伟大的项目,它彻底释放了虚拟化的威力,极大降低了云计算资源供应的成本,同时让应用的分发、测试、部署和分发都变得前所未有的高效和轻松!

View File

@ -83,6 +83,8 @@
* [简介](swarm/intro.md)
* [安装](swarm/install.md)
* [使用](swarm/usage.md)
* [调度器](swarm/scheduling.md)
* [过滤器](swarm/filter.md)
* [Etcd 项目](etcd/README.md)
* [简介](etcd/intro.md)
* [安装](etcd/install.md)

83
swarm/filter.md Normal file
View File

@ -0,0 +1,83 @@
## Swarm 过滤器
swarm的调度器(scheduler)在选择节点运行containers的时候支持几种过滤器 (filter)Constraint,Affinity,Port,Dependency,Health
这些选项可以在执行swarm manage命令的时候通过--filter选项来设置。
###Constraint Filter
constraint 是一个跟具体节点相关联的键值对可以看做是每个节点的标签这个标签可以在启动docker daemon的时候指定比如
<pre><code>
sudo docker -d --label label_name=label01
</code></pre>
也可以写在docker的配置文件里面在ubuntu上面是/etc/default/docker
在本次试验中给083添加标签--label label_name=083,084添加标签--label label_name=084,124添加标签--label label_name=084,
以083为例打开/etc/default/docker文件修改DOCKER_OPTS
<pre><code>
DOCKER_OPTS="-H 0.0.0.0:2375 -H unix:///var/run/docker.sock --label label_name=083"
</code></pre>
在使用docker run命令启动container的时候使用 -e constarint:key=value的形式可以指定container运行的节点,比如我们想在84上面启动一个redis container
<pre><code>
rio@085:~$ sudo docker -H 192.168.1.83:2376 run --name redis_1 -d -e constraint:label_name==084 redis
fee1b7b9dde13d64690344c1f1a4c3f5556835be46b41b969e4090a083a6382d
</code></pre>
主要,是**两个**等号,不是一个等号,这一点会经常被忽略。
接下来再在084这台机器上启动一个redis container
<pre><code>
rio@085:~$ sudo docker -H 192.168.1.83:2376 run --name redis_2 -d -e constraint:label_name==084 redis 4968d617d9cd122fc2e17b3bad2f2c3b5812c0f6f51898024a96c4839fa000e1
</code></pre>
然后再在083这台机器上启动另外一个redis container
<pre><code>
rio@085:~$ sudo docker -H 192.168.1.83:2376 run --name redis_3 -d -e constraint:label_name==083 redis 7786300b8d2232c2335ac6161c715de23f9179d30eb5c7e9c4f920a4f1d39570
</code></pre>
现在来看下执行情况:
<pre><code>
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
</code></pre>
可以看到,执行结果跟预期的一样。
但是如果指定一个不存在的标签的话来运行container会报错。
<pre><code>
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
</code></pre>
###Affinity Filter
通过使用Affinity Filter可以让一个container紧挨着另一个container启动也就是说让两个container在同一个节点上面启动。
现在其中一台机器上面启动一个redis
<pre><code>
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
</code></pre>
然后再次启动两台redis
<pre><code>
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
</code></pre>
现在来查看下运行结果,可以看到三个container都是在一台机器上运行
<pre><code>
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
</code></pre>
通过-e affinity:image=image_name命令可以指定只有已经下载了image_name的机器才运行容器
<pre><code>
sudo docker H 192.168.1.83:2376 run name redis1 d e affinity:image==redis redis
</code></pre>
redis1这个container只会在已经下载了redis镜像的节点上运行。
<pre><code>
sudo docker -H 192.168.1.83:2376 run -d --name redis -e affinity:image==~redis redis
</code></pre>
这条命令达到的效果是在有redis镜像的节点上面启动一个名字叫做redis的容器如果每个节点上面都没有redis容器就按照默认的策略启动redis容器。
###Port Filter
Port也会被认为是一个唯一的资源
<pre><code>
sudo docker -H 192.168.1.83:2376 run -d -p 80:80 nginx
</code></pre>
执行完这条命令之后任何使用80端口的容器都是启动失败。

63
swarm/scheduling.md Normal file
View File

@ -0,0 +1,63 @@
## swarm 调度策略
swarm支持多种调度策略来选择节点。每次在swarm启动container的时候swarm会根据选择的调度策略来选择节点运行container。目前支持的有:spread,binpack和random.再执行swarm manage的命令起送swarm集群的时候可以通过--strategy参数来指定默认的是spread。
spread和binpack策略会根据每台节点的可用CPU内存以及正在运行的containers的数量来给各个节点分级而random策略顾名思义他不会做任何的计算只是单纯的随机选择一个节点来启动container。这种策略一般只做调试用。
使用spread策略swarm会选择一个正在运行的container的数量最少的那个节点来运行container。这种情况会导致启动的container会尽可能的分布在不同的机器上运行这样的好处就是如果有节点坏掉的时候不会损失太多的container。而binpack恰恰相反这种情况下swarm会尽可能的把所有的容器放在一台节点上面运行。这种策略会避免容器碎片化因为他会把未使用的机器分配给更大的container带来的好处就是swarm会使用最少的节点运行最多的container。
先来演示下--strategy=spread的情况
<pre><code>
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
</code></pre>
三台机器除了83运行了swarm之外其他的都没有运行任何一个container现在在85这台节点上面在swarm集群上启动一个container
<pre><code>
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
</code></pre>
启动一个 redis 容器,查看结果
<pre><code>
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
</code></pre>
再次启动一个redis查看结果
<pre><code>
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
</code></pre>
可以看到三个container都是分布在不同的节点上面的。
现在来看看binpack策略下的情况。在083上面执行命令
<pre><code>
rio@083:~$ sudo docker run -d -p 2376:2375 -v $(pwd)/cluster:/tmp/cluster swarm manage --strategy=binpack file:///tmp/cluster
f1c9affd5a0567870a45a8eae57fec7c78f3825f3a53fd324157011aa0111ac5
</code></pre>
现在在集群中启动三个rediscontainer查看分布情况
<pre><code>
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
</code></pre>
可以看到所有的container都是分布在同一个节点上运行的。

View File

@ -150,154 +150,3 @@ Nodes: 3
└ Reserved CPUs: 0 / 2
└ Reserved Memory: 0 B / 4.053 GiB
</code></pre>
##swarm调度策略
swarm支持多种调度策略来选择节点。每次在swarm启动container的时候swarm会根据选择的调度策略来选择节点运行container。目前支持的有:spread,binpack和random.再执行swarm manage的命令起送swarm集群的时候可以通过--strategy参数来指定默认的是spread。
spread和binpack策略会根据每台节点的可用CPU内存以及正在运行的containers的数量来给各个节点分级而random策略顾名思义他不会做任何的计算只是单纯的随机选择一个节点来启动container。这种策略一般只做调试用。
使用spread策略swarm会选择一个正在运行的container的数量最少的那个节点来运行container。这种情况会导致启动的container会尽可能的分布在不同的机器上运行这样的好处就是如果有节点坏掉的时候不会损失太多的container。而binpack恰恰相反这种情况下swarm会尽可能的把所有的容器放在一台节点上面运行。这种策略会避免容器碎片化因为他会把未使用的机器分配给更大的container带来的好处就是swarm会使用最少的节点运行最多的container。
先来演示下--strategy=spread的情况
<pre><code>
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
</code></pre>
三台机器除了83运行了swarm之外其他的都没有运行任何一个container现在在85这台节点上面在swarm集群上启动一个container
<pre><code>
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
</code></pre>
在启动一个redis查看结果
<pre><code>
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
</code></pre>
再次启动一个redis查看结果
<pre><code>
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
</code></pre>
可以看到三个container都是分布在不同的节点上面的。
现在来看看binpack策略下的情况。在083上面执行命令
<pre><code>
rio@083:~$ sudo docker run -d -p 2376:2375 -v $(pwd)/cluster:/tmp/cluster swarm manage --strategy=binpack file:///tmp/cluster
f1c9affd5a0567870a45a8eae57fec7c78f3825f3a53fd324157011aa0111ac5
</code></pre>
现在在集群中启动三个rediscontainer查看分布情况
<pre><code>
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
</code></pre>
可以看到所有的container都是分布在同一个节点上运行的。
##Swarm Filters
swarm的调度器(scheduler)在选择节点运行containers的时候支持几种过滤器 (filter)Constraint,Affinity,Port,Dependency,Health
这些选项可以在执行swarm manage命令的时候通过--filter选项来设置。
###Constraint Filter
constraint 是一个跟具体节点相关联的键值对可以看做是每个节点的标签这个标签可以在启动docker daemon的时候指定比如
<pre><code>
sudo docker -d --label label_name=label01
</code></pre>
也可以写在docker的配置文件里面在ubuntu上面是/etc/default/docker
在本次试验中给083添加标签--label label_name=083,084添加标签--label label_name=084,124添加标签--label label_name=084,
以083为例打开/etc/default/docker文件修改DOCKER_OPTS
<pre><code>
DOCKER_OPTS="-H 0.0.0.0:2375 -H unix:///var/run/docker.sock --label label_name=083"
</code></pre>
在使用docker run命令启动container的时候使用 -e constarint:key=value的形式可以指定container运行的节点,比如我们想在84上面启动一个redis container
<pre><code>
rio@085:~$ sudo docker -H 192.168.1.83:2376 run --name redis_1 -d -e constraint:label_name==084 redis
fee1b7b9dde13d64690344c1f1a4c3f5556835be46b41b969e4090a083a6382d
</code></pre>
主要,是**两个**等号,不是一个等号,这一点会经常被忽略。
接下来再在084这台机器上启动一个redis container
<pre><code>
rio@085:~$ sudo docker -H 192.168.1.83:2376 run --name redis_2 -d -e constraint:label_name==084 redis 4968d617d9cd122fc2e17b3bad2f2c3b5812c0f6f51898024a96c4839fa000e1
</code></pre>
然后再在083这台机器上启动另外一个redis container
<pre><code>
rio@085:~$ sudo docker -H 192.168.1.83:2376 run --name redis_3 -d -e constraint:label_name==083 redis 7786300b8d2232c2335ac6161c715de23f9179d30eb5c7e9c4f920a4f1d39570
</code></pre>
现在来看下执行情况:
<pre><code>
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
</code></pre>
可以看到,执行结果跟预期的一样。
但是如果指定一个不存在的标签的话来运行container会报错。
<pre><code>
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
</code></pre>
###Affinity Filter
通过使用Affinity Filter可以让一个container紧挨着另一个container启动也就是说让两个container在同一个节点上面启动。
现在其中一台机器上面启动一个redis
<pre><code>
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
</code></pre>
然后再次启动两台redis
<pre><code>
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
</code></pre>
现在来查看下运行结果,可以看到三个container都是在一台机器上运行
<pre><code>
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
</code></pre>
通过-e affinity:image=image_name命令可以指定只有已经下载了image_name的机器才运行容器
<pre><code>
sudo docker H 192.168.1.83:2376 run name redis1 d e affinity:image==redis redis
</code></pre>
redis1这个container只会在已经下载了redis镜像的节点上运行。
<pre><code>
sudo docker -H 192.168.1.83:2376 run -d --name redis -e affinity:image==~redis redis
</code></pre>
这条命令达到的效果是在有redis镜像的节点上面启动一个名字叫做redis的容器如果每个节点上面都没有redis容器就按照默认的策略启动redis容器。
###Port Filter
Port也会被认为是一个唯一的资源
<pre><code>
sudo docker -H 192.168.1.83:2376 run -d -p 80:80 nginx
</code></pre>
执行完这条命令之后任何使用80端口的容器都是启动失败。