Docker Swarm: 过滤器
过滤器
原文链接:https://docs.docker.com/swarm/scheduler/filter/
中文翻译:https://docs.docker.com/swarm/scheduler/filter/
Docker Swam调度器具有多个过滤器。
当将容器安排在节点的子集(部分)时,可以使用以下过滤器:
-
- Constraint(強制)
-
- Affinity(親密さ)
-
- Port(ポート)
-
- Dependency(依存性)
- Health(ヘルス)
当您想要使用某种筛选器时,请使用swam manage的–filter标志。
约束筛选器
约束将键值对关联到特定节点。这些约束可以通过节点标签进行查看。
在创建容器时,您可以选择节点的子集。这是为了调度而选择特定节点或者应该与键值对相匹配的节点。
这种方法有几种特定的使用方式:
-
- ホスト・プロパティを指定した選択(storage=ssd のように、特定のハードウェアにコンテナをスケジュールするため)
-
- 物理的な場所をノードの土台とタグ付けする(region=us-ease のように、指定した場所でコンテナを強制的に実行)
- 論理的なクラスタの分割(environment=production のように、プロパティの違いによりクラスタをサブクラスに分割)
在docker启动选项中,至少需要一个–label指定来对节点进行标记,以特定的键值对方式。
比如,我们启动节点-1时,可以尝试给它加上存储=固态硬盘的标签。
$ docker -d --label storage=ssd
$ swarm join --advertise=192.168.0.42:2375 token://XXXXXXXXXXXXXXXXXX
请再次启动 node-2,但这次使用 storage=disk。
$ docker -d --label storage=disk
$ swarm join --advertise=192.168.0.43:2375 token://XXXXXXXXXXXXXXXXXX
当节点被注册到集群后,主节点会获取每个节点的标签,并在调度新容器时进行相应的反映。
让我们启动MySQL服务器,并将其放在具有良好I/O性能的闪存驱动器上可用:
$ docker run -d -P -e constraint:storage==ssd --name db mysql
f8b693db9cd6
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NODE NAMES
f8b693db9cd6 mysql:latest "mysqld" Less than a second ago running 192.168.0.42:49178->3306/tcp node-1 db
在这个例子中,主节点会从所有被选中的节点上强制应用事先指定的存储=ssd的资源管理。node-1被选择作为在闪存驱动器上运行的主机。
接下来,我们将尝试在集群上运行 Nginx 前端。但是由于要将日志大量写入磁盘,我们不想使用闪存驱动器。
$ docker run -d -P -e constraint:storage==disk --name frontend nginx
963841b138d8
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NODE NAMES
963841b138d8 nginx:latest "nginx" Less than a second ago running 192.168.0.43:49177->80/tcp node-2 frontend
f8b693db9cd6 mysql:latest "mysqld" Up About a minute running 192.168.0.42:49178->3306/tcp node-1 db
调度器将在已启动的node-2上附加磁盘存储(storage=disk)并启动。
限制的标准
此外,即使在启动节点时没有特别指定,也可以使用容器调度所使用的默认约束集合。这些标签可以在”docker info”命令中确认,目前可用的有:
-
- ノード ID またはノード名(”node” をキーに用いる)
-
- storagedriver(ストレージ・ドライバ)
-
- executiondriver(実行ドライバ)
-
- kernelversion(カーネルバージョン)
- operatingsystem(オペレーティング・システム)
亲和性(亲密度)筛选器
可以使用”–affinity:<过滤器>”在创建容器时”吸引”容器之间的关系。例如,您可以指定容器在执行时的位置,并将具有特定映像或标签的容器放置在其旁边。通过这种吸引功能,确保容器在相同的网络节点上运行,而无需了解它们在哪个节点上运行。
容器的亲和性
在运行新容器之后,您可以在旁边运行具有其他名称或ID的容器。例如,您可以使用名称为”frontend”的nginx容器来运行:
$ docker run -d -p 80:80 --name front nginx
87c4376856a8
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NODE NAMES
87c4376856a8 nginx:latest "nginx" Less than a second ago running 192.168.0.42:80->80/tcp node-1 frontend
然后,使用-e affinity:container==frontend标志,在第二个容器旁边调度计划。
$ docker run -d --name logger -e affinity:container==frontend logger
87c4376856a8
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NODE NAMES
87c4376856a8 nginx:latest "nginx" Less than a second ago running 192.168.0.42:80->80/tcp node-1 frontend
963841b138d8 logger:latest "logger" Less than a second ago running node-1 logge
logger 容器将在与前端容器相同的 node-1 容器上运行,这取决于亲和性的名称。除了使用前端的名称外,还可以使用标识符进行指定,如下所示:
docker run -d --name logger -e affinity:container==87c4376856a8`
形象的亲和度
只能在已下载的节点上调度特定的映像来启动容器。
$ docker -H node-1:2375 pull redis
$ docker -H node-2:2375 pull mysql
$ docker -H node-3:2375 pull redis
node-1和node-3都拥有Redis镜像。使用“-e affinity:image==redis”过滤器,在这些节点上进行调度。
$ docker run -d --name redis1 -e affinity:image==redis redis
$ docker run -d --name redis2 -e affinity:image==redis redis
$ docker run -d --name redis3 -e affinity:image==redis redis
$ docker run -d --name redis4 -e affinity:image==redis redis
$ docker run -d --name redis5 -e affinity:image==redis redis
$ docker run -d --name redis6 -e affinity:image==redis redis
$ docker run -d --name redis7 -e affinity:image==redis redis
$ docker run -d --name redis8 -e affinity:image==redis redis
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NODE NAMES
87c4376856a8 redis:latest "redis" Less than a second ago running node-1 redis1
1212386856a8 redis:latest "redis" Less than a second ago running node-1 redis2
87c4376639a8 redis:latest "redis" Less than a second ago running node-3 redis3
1234376856a8 redis:latest "redis" Less than a second ago running node-1 redis4
86c2136253a8 redis:latest "redis" Less than a second ago running node-3 redis5
87c3236856a8 redis:latest "redis" Less than a second ago running node-3 redis6
87c4376856a8 redis:latest "redis" Less than a second ago running node-3 redis7
963841b138d8 redis:latest "redis" Less than a second ago running node-1 redis8
在这里可以看到,只有具有 redis 图像的节点才会安排容器。除了图像名称,还可以指定特定的图像 ID。
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
redis latest 06a1f75304ba 2 days ago 111.1 MB
$ docker run -d --name redis1 -e affinity:image==06a1f75304ba redis
标签的亲和力
通过标签亲和性,可以使用容器标签来引导并设置容器。例如,为 nginx 容器加上 com.example.type=frontend 标签来启动。
用中文直接表达这个句子:
运行命令:$ docker run -d -p 80:80 –label com.example.type=frontend nginx。容器ID为87c4376856a8。
$ docker ps --filter "label=com.example.type=front"
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NODE NAMES
87c4376856a8 nginx:latest "nginx" Less than a second ago running 192.168.0.42:80->80/tcp node-1 trusting_yonath
然后,使用-e affinity:com.example.type==frontend,在具有com.example.type==fronten标签的容器旁边进行调度。
$ docker run -d -e affinity:com.example.type==frontend logger
87c4376856a8
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NODE NAMES
87c4376856a8 nginx:latest "nginx" Less than a second ago running 192.168.0.42:80->80/tcp node-1 trusting_yonath
963841b138d8 logger:latest "logger" Less than a second ago running node-1 happy_hawking
日志记录容器最终将放置在节点1上。这是因为它具有与com.example.type==frontend标签的亲和性。
语法表达
亲和性和约束通过键值对的组合来表示。键遵循英数字的模式,但首字符必须为字母或下划线。
价值的定义如下:
-
- 英数字の文字列、ドット、ハイフン、アンダースコア
-
- 部分一致、例えば abc*
/regexp/ 形式の正規表現
Go 支持正则表达式语法。
目前的 Swarm 在亲和性约束上支持运算符 == 和 !=。
假设
constraint:node==node1 は、ノード node1 にマッチ
constraint:node!=node1 は、node1 をのぞく全てのノードにマッチ
constraint:region!=us* は、us が付いているリージョン以外のノードにマッチ
constraint:node==/node[12]/ は、node1 と node2 にマッチ
constraint:node==/node\d/ は、node + 10進数の1文字にマッチ
constraint:node!=/node-[01]/ は、node-0 と node-1 以外の全てのノードにマッチ
constraint:node!=/foo\[bar\]/ は、foo[var] 以外の全てのノードにマッチ
constraint:node==/(?i)node1/ は、大文字・小文字を区別しない node1 にマッチします。そのため、NoDe1 や NODE1 もマッチします。
柔性的亲和力/限制
默认情况下,亲和性和约束是硬性强制的。如果没有亲和性或约束,容器将不会被调度。如果存在软性亲和性/约束,则调度程序会尝试寻找与其匹配的规则进行调度。如果没有匹配,则调度程序会丢弃过滤器,并按照调度程序策略对容器进行调度。
软性亲和性/约束可以用~来表达。例如:
$ docker run -d --name redis1 -e affinity:image==~redis redis
如果集群中没有带有 Redis 镜像的节点,则调度器将放弃亲和性并根据策略进行调度。
$ docker run -d --name redis2 -e constraint:region==~us* redis
如果群集中没有属于美国区域的节点,则调度器将放弃限制并按照策略进行调度。
$ docker run -d --name redis5 -e affinity:container!=~redis* redis
亲和过滤器将新的redis5容器调度到没有包含指定redis*容器的节点上。如果集群的每个节点都有redis*容器,则调度程序将放弃亲和规则,并按照策略进行调度。
端口过滤器
这个端口过滤器被认为是一个独特的资源。
$ docker run -d -p 80:80 nginx
87c4376856a8
$ docker ps
CONTAINER ID IMAGE COMMAND PORTS NODE NAMES
87c4376856a8 nginx:latest "nginx" 192.168.0.42:80->80/tcp node-1 prickly_engelbart
从Docker集群中选择一个可以使用公共端口80的节点,并安排容器执行。在这个示例中,node-1就是符合条件的节点。
如果你想在另一个容器上使用公共端口80启动,由于node-1已经正在使用中,将会选择另一个节点。
$ docker run -d -p 80:80 nginx
963841b138d8
$ docker ps
CONTAINER ID IMAGE COMMAND PORTS NODE NAMES
963841b138d8 nginx:latest "nginx" 192.168.0.43:80->80/tcp node-2 dreamy_turing
87c4376856a8 nginx:latest "nginx" 192.168.0.42:80->80/tcp node-1 prickly_engelbart
如果尝试再次执行相同的命令,将选择使用端口80的不是node-1或node-2,而是node-3。
$ docker run -d -p 80:80 nginx
963841b138d8
$ docker ps
CONTAINER ID IMAGE COMMAND PORTS NODE NAMES
f8b693db9cd6 nginx:latest "nginx" 192.168.0.44:80->80/tcp node-3 stoic_albattani
963841b138d8 nginx:latest "nginx" 192.168.0.43:80->80/tcp node-2 dreamy_turing
87c4376856a8 nginx:latest "nginx" 192.168.0.42:80->80/tcp node-1 prickly_engelbart
当集群中没有可用的节点端口80时,Docker Swam 将拒绝容器执行。
$ docker run -d -p 80:80 nginx
2014/10/29 00:33:20 Error response from daemon: no resources available to schedule container
只需一种选项,用中文将以下内容改述为华文:在主机模式下的端口过滤
使用 Docker 的 –net=host 参数进行主机模式运行时,与默认的桥接模式不同,无法进行端口绑定。因此,需要明确指定一个或多个端口号(可以使用 Dockerfile 中的 EXPOSE 或命令行中的 –expose)。在选择为新容器分配节点时,Swarm 会使用主机模式的这些信息。
例如,下面的命令在三个节点集群中启动了nginx。
$ docker run -d --expose=80 --net=host nginx
640297cb29a7
$ docker run -d --expose=80 --net=host nginx
7ecf562b1b3f
$ docker run -d --expose=80 --net=host nginx
09a92f582bc2
通过docker ps命令,可以获取端口绑定的信息。这是因为所有节点都以主机模式启动。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
640297cb29a7 nginx:1 "nginx -g 'daemon of Less than a second ago Up 30 seconds box3/furious_heisenberg
7ecf562b1b3f nginx:1 "nginx -g 'daemon of Less than a second ago Up 28 seconds box2/ecstatic_meitner
09a92f582bc2 nginx:1 "nginx -g 'daemon of 46 seconds ago Up 27 seconds box1/mad_goldstine
即使您尝试准备第四个容器,Swarm也会拒绝。
$ docker run -d --expose=80 --net=host nginx
FATA[0000] Error response from daemon: unable to find a node with port 80/tcp available in the Host mode
可以选择绑定不同的端口,比如端口81。
$ docker run -d -p 81:80 nginx:latest
832f42819adc
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
832f42819adc nginx:1 "nginx -g 'daemon of Less than a second ago Up Less than a second 443/tcp, 192.168.136.136:81->80/tcp box3/thirsty_hawking
640297cb29a7 nginx:1 "nginx -g 'daemon of 8 seconds ago Up About a minute box3/furious_heisenberg
7ecf562b1b3f nginx:1 "nginx -g 'daemon of 13 seconds ago Up About a minute box2/ecstatic_meitner
09a92f582bc2 nginx:1 "nginx -g 'daemon of About a minute ago Up About a minute box1/mad_goldstine
依存过滤器
このフィルタは同じノード上でのコンテナ依存性をスケジュールします。
現時点では、次の依存性を宣言できます:
-
- ボリューム共有:–volumes-from=dependency
リンク: –link=dependency:alias
共有ネットワーク層:–net=container:dependency
Swarm は同じノード上で依存性のあるコンテナを設置しようとします。もし実行できなそうであれば(依存性のコンテナが存在しなかったり、ノードに十分なリソースが無い場合)、コンテナは作成されません。
可能であれば、複数の依存性を組み合わせることもできます。例えば、–volumes-from=A –net=container:B は、A と B と同じノード上にコンテナを置こうとします。これらのコンテナが別々のノードで動いているなら、Swarm はコンテナのスケジューリングを行いません。
ヘルス・フィルタ
筛选出发生障碍的节点。