swarm调度

Posted 会飞の鱼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了swarm调度相关的知识,希望对你有一定的参考价值。

Swarm filters

Configure the available filters

过滤器分为两类,即节点过滤器和容器配置过滤器。 节点过滤器对Docker主机的特性或Docker守护程序的配置进行操作。 容器配置过滤器根据容器的特性或主机上image的可用性进行操作。

每个过滤器都有一个标识它的名称。 节点过滤器是:

  • constraint
  • health
  • containerslots

The container configuration filters are:

  • affinity
  • dependency
  • port

当您使用swarm manage命令启动Swarm管理器时,将启用所有过滤器。 如果要限制Swarm可用的过滤器,请通过传递--filter标志和名称来指定一个过滤器子集:

$ swarm manage --filter=health --filter=dependency

注意:应用过滤器时,容器配置过滤器将匹配所有容器,包括已停止的容器。 要释放容器使用的节点,必须从节点中删除该容器。

Node filters

创建容器或构建iimage时,您可以使用constrainthealth过滤器来选择要计划的节点子集。 如果Swarm群集中的节点具有带有containerslots和数字值的标签,Swarm将不会启动比给定号码更多的容器。

Use a constraint filter

节点约束可以指Docker的默认标签或自定义标签。 默认标签来自docker info。 通常它们与Docker主机的属性有关。 目前,默认标签包括:

  • node to refer to the node by ID or name
  • storagedriver
  • executiondriver
  • kernelversion
  • operatingsystem

Custom node labels you apply when you start the docker daemon, for example:

$ docker daemon --label com.example.environment="production" --label com.example.storage="ssd"

然后,当您在群集上启动容器时,可以使用这些默认标签或自定义标签设置约束。 Swarm调度程序在集群上查找匹配的节点,并在那里启动容器。 这种方法有几个实际应用:
  • 基于特定主机属性进行计划,例如,storage = ssd在特定硬件上调度容器。
  • 强制容器在给定位置运行,例如region = us-east。
  • 通过将集群分成具有不同属性的子集群(例如environment = production)来创建逻辑集群分区。

Example node constraints

To specify custom label for a node, pass a list of --label options at docker startup time. For instance, to start node-1 with the storage=ssd label:

$ docker daemon --label storage=ssd
$ swarm join --advertise=192.168.0.42:2375 token://XXXXXXXXXXXXXXXXXX

You might start a different node-2 with storage=disk:

$ docker daemon --label storage=disk
$ swarm join --advertise=192.168.0.43:2375 token://XXXXXXXXXXXXXXXXXX

一旦节点连接到群集,Swarm manager将拉出各自的标签。 展望未来,在安排新container时,manager会考虑标签。

继续上一个示例,假设您的群集具有node-1和node-2,您可以在群集上运行mysql服务器容器。 运行容器时,可以使用约束来确保数据库获得良好的I / O性能。 您可以通过使用闪存驱动器的节点进行过滤:

$ docker tcp://<manager_ip:manager_port>  run -d -P -e constraint:storage==ssd --name db mysql
f8b693db9cd6

$ docker tcp://<manager_ip:manager_port>  ps
CONTAINER ID        IMAGE               COMMAND             CREATED                  STATUS              PORTS                           NAMES
f8b693db9cd6        mysql:latest        "mysqld"            Less than a second ago   running             192.168.0.42:49178->3306/tcp    node-1/db

在此示例中,管理员选择了满足storage = ssd约束的所有节点,并在其上面应用了资源管理。 只有节点1被选中,因为它是唯一的主机运行闪存。

假设你想在一个集群中运行一个nginx前端。 在这种情况下,您不需要闪存驱动器,因为前端主要将日志写入磁盘。
调度程序选择node-2,因为它是以storage = disk标签启动的。

最后,构建args可以用于将节点约束应用于docker构建。 再次,你会避免闪存驱动器。



$ mkdir sinatra
$ cd sinatra
$ echo "FROM ubuntu:14.04" > Dockerfile
$ echo "RUN apt-get update && apt-get install -y ruby ruby-dev" >> Dockerfile
$ echo "RUN gem install sinatra" >> Dockerfile
$ docker build --build-arg=constraint:storage==disk -t ouruser/sinatra:v2 .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM ubuntu:14.04
 ---> a5a467fddcb8
Step 2 : RUN apt-get update && apt-get install -y ruby ruby-dev
 ---> Running in 26c9fbc55aeb
 ---> 30681ef95fff
Removing intermediate container 26c9fbc55aeb
Step 3 : RUN gem install sinatra
 ---> Running in 68671d4a17b0
 ---> cd70495a1514
Removing intermediate container 68671d4a17b0
Successfully built cd70495a1514

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
dockerswarm/swarm   manager             8c2c56438951        2 days ago          795.7 MB
ouruser/sinatra     v2                  cd70495a1514        35 seconds ago      318.7 MB
ubuntu              14.04               a5a467fddcb8        11 days ago         187.9 MB

Use the health filter

节点健康过滤器防止调度程序在不健康的节点上运行容器。 如果节点关闭或无法与集群存储通信,则节点被认为是不健康的。

Use the containerslots filter

You may give your Docker nodes the containerslots label

$ docker daemon --label containerslots=3


如果所有节点都为“满”,Swarm将在此节点运行多达3个容器,则会抛出错误,指示找不到合适的节点。 如果该值不可转换为整数或不存在,则容器数量不会有限制。

Container filters

When creating a container, you can use three types of container filters:

Use an affinity filter

使用亲和过滤器在容器之间创建“景点”。 例如,您可以运行一个容器,并指示Swarm根据这些亲和力将其安排在另一个容器旁边:

  • container name or ID
  • an image on the host
  • a custom label applied to the container

这些亲和性确保容器运行在同一个网络节点上,而无需知道每个节点正在运行。

Example name affinity

您可以根据容器名称或ID来安排新容器运行到另一个容器。 例如,您可以启动一个名为frontend运行nginx的容器:

$ docker tcp://<manager_ip:manager_port>  run -d -p 80:80 --name frontend nginx
 87c4376856a8


$ docker tcp://<manager_ip:manager_port> ps
CONTAINER ID        IMAGE               COMMAND             CREATED                  STATUS              PORTS                           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值来计划第二个容器来定位并运行在名为frontend的容器旁

$ docker tcp://<manager_ip:manager_port> run -d --name logger -e affinity:container==frontend logger
 87c4376856a8

$ docker tcp://<manager_ip:manager_port> ps
CONTAINER ID        IMAGE               COMMAND             CREATED                  STATUS              PORTS                           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/logger

由于名称相关性,记录器容器与前端容器一起结束在节点1上。 您可以提供其ID,而不是frontend名称,如下所示:

$ docker tcp://<manager_ip:manager_port> run -d --name logger -e affinity:container==87c4376856a8

Example image affinity

您可以安排一个容器仅在已经拉出特定图像的节点上运行。 例如,假设您将一个redis映像拖放到两个主机和一个mysql映像到三分之一。

$ docker -H node-1:2375 pull redis
$ docker -H node-2:2375 pull mysql
$ docker -H node-3:2375 pull redis

只有节点1和节点3具有redis映像。 指定-e affinity:image == redis过滤器以安排在这些节点上运行的多个附加容器。

$ docker tcp://<manager_ip:manager_port> run -d --name redis1 -e affinity:image==redis redis
$ docker tcp://<manager_ip:manager_port> run -d --name redis2 -e affinity:image==redis redis
$ docker tcp://<manager_ip:manager_port> run -d --name redis3 -e affinity:image==redis redis
$ docker tcp://<manager_ip:manager_port> run -d --name redis4 -e affinity:image==redis redis
$ docker tcp://<manager_ip:manager_port> run -d --name redis5 -e affinity:image==redis redis
$ docker tcp://<manager_ip:manager_port> run -d --name redis6 -e affinity:image==redis redis
$ docker tcp://<manager_ip:manager_port> run -d --name redis7 -e affinity:image==redis redis
$ docker tcp://<manager_ip:manager_port> run -d --name redis8 -e affinity:image==redis redis

$ docker tcp://<manager_ip:manager_port> ps
CONTAINER ID        IMAGE               COMMAND             CREATED                  STATUS              PORTS                           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镜像的节点上。 您可以指定image ID而不是image名称。
$ docker images
REPOSITORY                         TAG                       IMAGE ID            CREATED             VIRTUAL SIZE
redis                              latest                    06a1f75304ba        2 days ago          111.1 MB

$ docker tcp://<manager_ip:manager_port> run -d --name redis1 -e affinity:image==06a1f75304ba redis

Example label affinity

标签亲和性允许您根据自定义容器标签进行过滤。 例如,您可以运行一个nginx容器并应用com.example.type = frontend自定义标签。

$ docker tcp://<manager_ip:manager_port> run -d -p 80:80 --label com.example.type=frontend nginx
 87c4376856a8

$ docker tcp://<manager_ip:manager_port> ps  --filter "label=com.example.type=frontend"
CONTAINER ID        IMAGE               COMMAND             CREATED                  STATUS              PORTS                           NAMES
87c4376856a8        nginx:latest        "nginx"             Less than a second ago   running             192.168.0.42:80->80/tcp         node-1/trusting_yonath

Then, use -e affinity:com.example.type==frontend to schedule a container next to the container with the com.example.type==frontend label.

$ docker tcp://<manager_ip:manager_port> run -d -e affinity:com.example.type==frontend logger
 87c4376856a8

$ docker tcp://<manager_ip:manager_port> ps
CONTAINER ID        IMAGE               COMMAND             CREATED                  STATUS              PORTS                           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                                          

The logger container ends up on node-1 because its affinity with the com.example.type==frontend label.

Use a dependency filter

容器依赖过滤器在相同的节点上调度相关容器。 目前,依赖关系声明如下:

  • --volumes-from=dependency (shared volumes)
  • --link=dependency:alias (links)
  • --net=container:dependency (shared network stacks)

Swarm尝试将依赖容器同时放置在同一个节点上。 如果不能完成(因为从属容器不存在,或因为节点没有足够的资源),它将阻止容器创建。

如果可能,多个依赖关系的组合将得到尊重。 例如,如果指定--volumes-from = A --net = container:B,则调度程序将尝试将与A和B相同节点上的容器进行共同定位。如果这些容器在不同的节点上运行,则Swarm 不安排容器。

Use a port filter

启用端口过滤器后,将使用容器的端口配置作为唯一约束。 Docker Swarm选择一个特定端口可用并且被其他容器或进程占用的节点。 可以通过映射主机端口或使用主机网络并使用容器配置暴露端口来指定所需的端口。

Example in bridge mode

默认情况下,容器在Docker的网桥上运行。 要将端口过滤器与桥接网络一起使用,请运行以下容器。

$ docker tcp://<manager_ip:manager_port> run -d -p 80:80 nginx
87c4376856a8

$ docker tcp://<manager_ip:manager_port> ps
CONTAINER ID    IMAGE               COMMAND         PORTS                       NAMES
87c4376856a8    nginx:latest        "nginx"         192.168.0.42:80->80/tcp     node-1/prickly_engelbart
 Docker Swarm选择端口80可用并且被其他容器或进程占用的节点,在本例中为节点-1。 尝试运行另一个使用主机端口80的容器导致Swarm选择不同的节点,因为端口80已在节点1上占用:
$ docker tcp://<manager_ip:manager_port> run -d -p 80:80 nginx
963841b138d8

$ docker tcp://<manager_ip:manager_port> ps
CONTAINER ID        IMAGE          COMMAND        PORTS                           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

再次,重复相同的命令将导致节点3的选择,因为端口80在节点1和节点2上都不可用:

$ docker tcp://<manager_ip:manager_port> run -d -p 80:80 nginx
963841b138d8

$ docker tcp://<manager_ip:manager_port> ps
CONTAINER ID   IMAGE               COMMAND        PORTS                           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

最后,Docker Swarm将拒绝运行另一个需要端口80的容器,因为它在集群中的任何节点上都不可用:
$ docker tcp://<manager_ip:manager_port> run -d -p 80:80 nginx
2014/10/29 00:33:20 Error response from daemon: no resources available to schedule container
当容器创建时,每个容器在其驻留节点上占用端口80,并在容器被删除时释放端口。 退出状态的容器仍然拥有端口。 如果节点1上的prickly_engelbart已停止但未被删除,
则尝试启动需要端口80的节点1上的另一个容器将失败,因为端口80与prickly_engelbart相关联。 要增加nginx的运行实例,可以重新启动prickly_engelbart,也可以在删除prickly_englbart后启动另一个容器。

Node port filter with host networking

运行于--net = host的容器与默认bridge模式不同,因为主机模式不执行任何端口绑定。 相反,主机模式要求您显式公开一个或多个端口号。 您在Dockerfile中使用EXPOSE公开端口或在命令行上使用--expose。

Swarm使用此信息与主机模式一起选择新容器的可用节点。

例如,以下命令在3节点集群上启动nginx。

$ docker tcp://<manager_ip:manager_port> run -d --expose=80 --net=host nginx
640297cb29a7
$ docker tcp://<manager_ip:manager_port> run -d --expose=80 --net=host nginx
7ecf562b1b3f
$ docker tcp://<manager_ip:manager_port> run -d --expose=80 --net=host nginx
09a92f582bc2

端口绑定信息通过docker ps命令不可用,因为所有节点都是使用host网络启动的。
$ docker tcp://<manager_ip:manager_port> 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

尝试实例化第4个容器时,Swarm拒绝操作。
$  docker tcp://<manager_ip:manager_port> 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
 
 
 
 

 
 

以上是关于swarm调度的主要内容,如果未能解决你的问题,请参考以下文章

swarm调度

Docker之Docker Swarm调度容器

使用 docker swarm 自动配置新主机

生产环境swarm集群规划和管理

生产环境swarm集群规划和管理

failover swarm 故障转移