Overview

Docker service scheduling is one of important aspect in planing and deployment of service over docker cluster. Your Docker swarm mode default’s scheduling strategy is “spread”. With spread strategy, swarm scheduler ranks node based on available CPU,RAM and number of containers.

NOTE: Docker containers eat resources during its life-cycle irrespective of their state, even containers with Exited state. Hence scheduler consider all containers including container with Exited state

TODO: Why needs to be controlled?

But it can be controlled by adding various constraints.

Constraints: Operators can control or limit the set of nodes on which tasks can be scheduled.

Constraints: Operators can limit the set of nodes where a task can be scheduled by defining constraint expressions. Multiple constraints find nodes that satisfy every expression, i.e., an AND match. Constraints can match node attributes in the following table. Note that engine.labels are collected from Docker Engine with information like operating system, drivers, etc. node.labels are added by cluster administrators for operational purpose. For example, some nodes have security compliant labels to run tasks with compliant requirements.

node attributematchesexample
node.idnode’s IDnode.id == 2ivku8v2gvtg4
node.hostnamenode’s hostnamenode.hostname != node-2
node.rolenode’s manager or worker rolenode.role == manager
node.labelsnode’s labels added by cluster adminsnode.labels.security == high
engine.labelsDocker Engine’s labelsengine.labels.operatingsystem == ubuntu 14.04

Why node lebels when docker engines had engine labels?

  • Engine labels can’t be trusted for security sensitive scheduling decisions, since any worker can report any label up to a manager. They are, however, useful for things like “Does this host have an SSD?", or “how much ram/disk space does this host have?".

These swarm labels, on the other hand, are always trustworthy, since they are set by an administrator explicitly. This means that we can label a host as pci-dss, and create a constraint to ensure that credit-card-app only gets scheduled on worker nodes that are labeled as pci-dss, and that no malicious worker can self-label itself as pci-dss.

$ docker-machine create -d virtualbox --engine-env HTTP_PROXY="http://proxy.rdh.ecl.ntt.co.jp:20066" --engine-env HTTPS_PROXY="http://proxy.rdh.ecl.ntt.co.jp:20066" --engine-label node=node2 --engine-label storage=ssd node2
Running pre-create checks...
Creating machine...
(node2) Unable to get the latest Boot2Docker ISO release version:  Get https://api.github.com/repos/boot2docker/boot2docker/releases/latest: x509: certificate is valid for inetnf.auth, not api.github.com
(node2) Copying /Users/kunalkushwaha/.docker/machine/cache/boot2docker.iso to /Users/kunalkushwaha/.docker/machine/machines/node2/boot2docker.iso...
(node2) Creating VirtualBox VM...
(node2) Creating SSH key...
(node2) Starting the VM...
(node2) Check network to re-create if needed...
(node2) Waiting for an IP...
Waiting for machine to be running, this may take a few minutes...
Detecting operating system of created instance...
Waiting for SSH to be available...
Detecting the provisioner...
Provisioning with boot2docker...
Copying certs to the local machine directory...
Copying certs to the remote machine...
Setting Docker configuration on the remote daemon...
Checking connection to Docker...
Docker is up and running!
To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: docker-machine env node2

$ eval $(docker-machine env node2)

$ docker info
Containers: 0
 Running: 0
 Paused: 0
 Stopped: 0
Images: 0
Server Version: 1.12.3
Storage Driver: aufs
 Root Dir: /mnt/sda1/var/lib/docker/aufs
 Backing Filesystem: extfs
 Dirs: 0
 Dirperm1 Supported: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: overlay null host bridge
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Security Options: seccomp
Kernel Version: 4.4.27-boot2docker
Operating System: Boot2Docker 1.12.3 (TCL 7.2); HEAD : 7fc7575 - Thu Oct 27 17:23:17 UTC 2016
OSType: linux
Architecture: x86_64
CPUs: 1
Total Memory: 995.8 MiB
Name: node2
ID: 5HAZ:LAGO:KVF4:WLRP:P356:O6IA:W6GD:3LYO:JGDJ:5QN6:U6L6:J3BZ
Docker Root Dir: /mnt/sda1/var/lib/docker
Debug Mode (client): false
Debug Mode (server): true
 File Descriptors: 13
 Goroutines: 23
 System Time: 2016-11-22T02:20:13.630275393Z
 EventsListeners: 0
Http Proxy: http://proxy.rdh.ecl.ntt.co.jp:20066
Https Proxy: http://proxy.rdh.ecl.ntt.co.jp:20066
Username: kunalkushwaha
Registry: https://index.docker.io/v1/
Labels:
 node=node2
 storage=ssd
 provider=virtualbox
Insecure Registries:
 127.0.0.0/8

 $ eval $(docker-machine env default)

~/Downloads  11:21:03
$ docker swarm init --advertise-addr 192.168.99.100
Swarm initialized: current node (4r4qnxd8ztxuiusldvrf9gub6) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join \
    --token SWMTKN-1-1b7a6a6ophwlo85ihe3ss2lkg678d0re52p5dqezk5m3xtwur5-2vsgk9in2cm2b97f3gg3xmii4 \
    192.168.99.100:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

~/Downloads  11:21:22
$ eval $(docker-machine env node2)

~/Downloads  11:21:37
$ docker swarm join \
    --token SWMTKN-1-1b7a6a6ophwlo85ihe3ss2lkg678d0re52p5dqezk5m3xtwur5-2vsgk9in2cm2b97f3gg3xmii4 \
    192.168.99.100:2377
This node joined a swarm as a worker.

$ docker info
Containers: 0
 Running: 0
 Paused: 0
 Stopped: 0
Images: 0
Server Version: 1.12.3
Storage Driver: aufs
 Root Dir: /mnt/sda1/var/lib/docker/aufs
 Backing Filesystem: extfs
 Dirs: 0
 Dirperm1 Supported: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: bridge null overlay host
Swarm: active
 NodeID: 5z607lfu3sigaliuzcpo0wsrf
 Is Manager: false
 Node Address: 192.168.99.101
Runtimes: runc
Default Runtime: runc
Security Options: seccomp
Kernel Version: 4.4.27-boot2docker
Operating System: Boot2Docker 1.12.3 (TCL 7.2); HEAD : 7fc7575 - Thu Oct 27 17:23:17 UTC 2016
OSType: linux
Architecture: x86_64
CPUs: 1
Total Memory: 995.8 MiB
Name: node2
ID: 5HAZ:LAGO:KVF4:WLRP:P356:O6IA:W6GD:3LYO:JGDJ:5QN6:U6L6:J3BZ
Docker Root Dir: /mnt/sda1/var/lib/docker
Debug Mode (client): false
Debug Mode (server): true
 File Descriptors: 22
 Goroutines: 68
 System Time: 2016-11-22T02:21:46.868274301Z
 EventsListeners: 0
Http Proxy: http://proxy.rdh.ecl.ntt.co.jp:20066
Https Proxy: http://proxy.rdh.ecl.ntt.co.jp:20066
Username: kunalkushwaha
Registry: https://index.docker.io/v1/
Labels:
 node=node2
 storage=ssd
 provider=virtualbox
Insecure Registries:
 127.0.0.0/8

 docker service create \
  --replicas 2 \
  --name helloworld1 \
  --constraint 'engine.labels.storage == ssd' \
  alpine ping docker.com

  ~/work/GlobalMentorWeek on  master!  13:53:25
  $ docker node update --label-add key1=master default
  default

  ~/work/GlobalMentorWeek on  master!  13:54:05
  $ docker node inspect 4r4qnxd8ztxuiusldvrf9gub6 --pretty
  ID:			4r4qnxd8ztxuiusldvrf9gub6
  Labels:
   - key = primary
   - key1 = master
  Hostname:		default
  Joined at:		2016-11-22 02:21:21.596149476 +0000 utc
  Status:
   State:			Ready
   Availability:		Active
  Manager Status:
   Address:		192.168.99.100:2377
   Raft Status:		Reachable
   Leader:		Yes
  Platform:
   Operating System:	linux
   Architecture:		x86_64
  Resources:
   CPUs:			1
   Memory:		995.8 MiB
  Plugins:
    Network:		bridge, host, null, overlay
    Volume:		local
  Engine Version:		1.12.3
  Engine Labels:
   - node = node1
   - provider = virtualbox
   - storage = hdd

$ docker service create \
  --replicas 2 \
  --name helloworld2 \
  --constraint 'node.labels.key == primary' \
  alpine ping docker.com
b2g40mrmok4ii9wcmqdlgv7s0