Docker Swarm ストラテジ

Docker Swarm スケジューラは、複数のストラテジ(strategy;方針)機能でノードを順位付けします。選択したストラテジによって、 Swarm が順位を算出します。Swarm で新しいコンテナを作成するときは、選択したストラテジに従って、コンテナを置くために最も順位の高いノードを算出します。

順位付けのストラテジを選択するには、 swarm manage コマンドに --strategy フラグを使い、ストラテジ値を指定します。現時点でサポートしている値は次の通りです。

  • spread
  • binpack
  • random

spreadbinpack ストラテジは、ノードで利用可能な CPU 、RAM 、実行中のコンテナ数から順位を算出します。 random ストラテジは計算をしません。ノードをランダムに選択するもので、主にデバッグ用に使います。

あなたの会社の必要性に従ってクラスタを最適化するのが、ストラテジを選択する目的(ゴール)です。

spread ストラテジの下では、Swarm はノードで実行中のコンテナ数に応じて最適化します。 pinback ストラテジは利用するノードが最も少なくなるよう最適化します。 random ストラテジでは、利用可能な CPU やメモリに関わらずランダムにノードを選びます。

spread ストラテジを使えば、結果として多くのマシンに幅広く展開します。このストラテジの利点は、ノードがダウンしても、失われるのは小数のコンテナだけです。

binpack は分散しないストラテジです。これは、使っていないマシンに大きなコンテナを動かす余地を残すためです。この binpack ストラテジの利点は、できるだけ少ないマシンしか使わないよう、Swarm はノードに多くのコンテナを詰め込みます。

もし --strategy を指定しなければ、Swarm はデフォルトで spread を使います

Spread ストラテジの例

この例では、Swarm は spread ストラテジでノードを最適化し、多くのコンテナを起動してみます。このクラスタは、 node-1node-2 は 2GB のメモリ、2 CPUであり、他のノードではコンテナは動いていません。このストラテジでは node-1node-2 は同じ順位です。

新しいコンテナを実行するときは、クラスタ上で同じランキングのノードが存在しますので、そこからランダムに node-1 をシステムが選びます。

$ docker tcp://<manager_ip:manager_port> run -d -P -m 1G --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

次は別のコンテナで 1GB のメモリを使います。

$ docker run tcp://<manager_ip:manager_port> -d -P -m 1G --name frontend nginx
963841b138d8

$ docker tcp://<manager_ip:manager_port> ps
CONTAINER ID        IMAGE               COMMAND             CREATED                  STATUS              PORTS                           NAMES
963841b138d8        nginx:latest        "nginx"             Less than a second ago   running             192.168.0.42: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

コンテナ frontendnode-2 で起動します。これは直前に実行したノードだからです。もし2つのノードがあって、同じメモリや CPU であれば、 spread ストラテジは最後にコンテナを実行したノードを選びます。

BinPack ストラテジの例

この例では、 node-1node-2 いずれも 2GB のメモリを持ち、コンテナを実行していないとします。ノードが同じとき、コンテナの実行は、今回はクラスタから node-1 が選ばれたとします

$ docker run tcp://<manager_ip:manager_port> -d -P -m 1G --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

これで再び、1GB のメモリを使う別のコンテナを起動してみましょう。

$ docker run tcp://<manager_ip:manager_port> -d -P -m 1G --name frontend nginx
963841b138d8

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

システムは node-1 上で新しい frontend コンテナを起動します。これはノードは既に集約するようになっているためです。これにより、2GB のメモリが必要なコンテナは node-2 で動きます。

もし2つのノードが同じメモリと CPU であれば、 binpack ストラテジは最もコンテナが実行しているノードを選択します。