docker
docker-swarm

SwarmもConsulも使わないシンプルなDockerクラスタを作る

More than 1 year has passed since last update.

前回の「Dockerのネットワークをbridgeで外と繋げる」では、マシン1台を例に説明しましたが、複数台でも同じように外へ繋ぐことができます。ただ、ゲートウェイの設定部分に少だけ工夫が必要なので、そこだけ注意が必要です。

では参考に、下記のような構成を例にして説明します。

Host
IP Address

MacBook
192.168.33.1

host1(VirtualBox)
192.168.33.10

host2(VirtualBox)
192.168.33.11

container1(on host1)
192.168.33.21

container2(on host1)
192.168.33.22

container3(on host2)
192.168.33.23

container4(on host2)
192.168.33.24


Vagrantfileを準備する


Vagrant.configure(2) do |config|

config.vm.define "host1" do |host1|
host1.vm.box = "ubuntu/trusty64"
host1.vm.hostname = "host1"
host1.vm.network "private_network", ip: "192.168.33.10"
end

config.vm.define "host2" do |host2|
host2.vm.box = "ubuntu/trusty64"
host2.vm.hostname = "host2"
host2.vm.network "private_network", ip: "192.168.33.11"
end

config.vm.provider "virtualbox" do |v|
v.memory = "2048"
# ネットワークアダプタに変更を加える
v.customize ['modifyvm', :id, '--nictype1', 'Am79C973']
v.customize ['modifyvm', :id, '--nicpromisc1', 'allow-all']
v.customize ['modifyvm', :id, '--nictype2', 'Am79C973']
v.customize ['modifyvm', :id, '--nicpromisc2', 'allow-all']
end

# bridge-utilsをインストールする
config.vm.provision "shell", inline: <<-SHELL
apt-get update
apt-get -y install bridge-utils
SHELL
end


Dockerマシンを作る

# host1とhost2を立ち上げます

$ vagrant up

# host1をDockerマシンにします
$ docker-machine create \
--driver "generic" \
--generic-ip-address 192.168.33.10 \
--generic-ssh-user vagrant \
--generic-ssh-key .vagrant/machines/host1/virtualbox/private_key \
--generic-ssh-port 22 \
host1

# host2をDockerマシンにします
$ docker-machine create \
--driver "generic" \
--generic-ip-address 192.168.33.11 \
--generic-ssh-user vagrant \
--generic-ssh-key .vagrant/machines/host2/virtualbox/private_key \
--generic-ssh-port 22 \
host2


host1にブリッジdocker1とネットワークshared_nwを作る

# host1にログインします

$ vagrant ssh host1

# eth1のIPアドレスを削除します
$ sudo ip addr del 192.168.33.10/24 dev eth1

# "shared_nw"と"docker1"を作ってサブネットとゲートウェイを
# 設定します
$ sudo docker network create \
--driver bridge \
--subnet=192.168.33.0/24 \
--gateway=192.168.33.10 \
--opt "com.docker.network.bridge.name"="docker1" \
shared_nw

# docker1をeth1に接続します
$ sudo brctl addif docker1 eth1

ここで理解しておきたい点は、docker network createの際にdocker1に192.168.33.10がアサインされることです(ifconfig docker1で確認できます)。次のステップでは少しだけ工夫してhost2のコンテナに対してもこのIPアドレスをゲートウェイに指定します。


host2にブリッジdocker1とネットワークshared_nwを作る

# host2にログインします

$ vagrant ssh host2

# eth1のIPアドレスを削除します
$ sudo ip addr del 192.168.33.11/24 dev eth1

# "shared_nw"と"docker1"を作ってサブネットとゲートウェイを
# 設定します
$ sudo docker network create \
--driver bridge \
--subnet=192.168.33.0/24 \
--gateway=192.168.33.10 \
--opt "com.docker.network.bridge.name"="docker1" \
shared_nw

# docker1にアサインされてしまった192.168.33.10を削除して
# 192.168.33.11をアサインします
$ sudo ip addr del 192.168.33.10/24 dev docker1
$ sudo ip addr add 192.168.33.11/24 dev docker1

# docker1をeth1に接続します
$ sudo brctl addif docker1 eth1


コンテナを作る

host2からログアウトしてMacBookに戻ります。それからhost1とhost2のshared_nw上に固定IPでコンテナを作ります。環境の切替を簡単化するために$on_host1$on_host2に設定を入れておくと便利です。

$ on_host1=$(docker-machine config host1) 

$ on_host2=$(docker-machine config host2)
$ docker $on_host1 run --name container1 --net shared_nw --ip 192.168.33.21 -dt ubuntu
$ docker $on_host1 run --name container2 --net shared_nw --ip 192.168.33.22 -dt ubuntu
$ docker $on_host2 run --name container3 --net shared_nw --ip 192.168.33.23 -dt ubuntu
$ docker $on_host2 run --name container4 --net shared_nw --ip 192.168.33.24 -dt ubuntu

設定がうまく行っていれば、ちゃんとpingが通ります。試しにcontainer1のシェルから下記のような手順で確認できます。

$ docker $on_host1 ps | grep container1

# 例:container1のIDがf90891c5448eだった場合
$ docker $on_host1 exec -it f90891c5448e bash

$ ping -c 3 192.168.33.1 # --> macbook
$ ping -c 3 192.168.33.10 # --> host1
$ ping -c 3 192.168.33.11 # --> host2
$ ping -c 3 192.168.33.22 # --> container2
$ ping -c 3 192.168.33.23 # --> container3
$ ping -c 3 192.168.33.24 # --> container4
$ ping -c 3 www.google.com

この構成でいけば、ネットワークの見通しがすっきりしているので、オンプレミスのDocker導入がスムーズになりそうですね。


ネットワークの設定を恒久的にする

再起動後も設定が残るようにするために、ここでも少し工夫が必要になります。まずはhost1host2/etc/network/interfaceseth1の設定を下記のように変更します。

auto eth1

iface eth1 inet manual
pre-up ifconfig $IFACE up
post-down ifconfig $IFACE down

それから/etc/rc.localexit 0の前に下記のコマンドを付け足します。


host1

brctl addif docker1 eth1



host2

ip addr del 192.168.33.10/24 dev docker1

ip addr add 192.168.33.11/24 dev docker1
brctl addif docker1 eth1

実際に再起動して確認してみてください。

この程度のハックであれば、そんなにメンテナンスの手間にはならないと思うのですが、もう少しいい方法を知っている(あるいは見つけた)方はコメントを下さい。よろしくお願いします。


後片付け

テストが終わって要らなくなったDockerマシンは下記の手順で削除できます。

$ docker $on_host1 stop $(docker ps -aq)

$ docker $on_host1 rm $(docker ps -aq)
$ docker $on_host2 stop $(docker ps -aq)
$ docker $on_host2 rm $(docker ps -aq)
$ docker-machine rm host1
$ docker-machine rm host2
$ vagrant destroy


理解を深める

Dockerのbridgeについて理解を深めたい方は下記リンクの"Building your own bridge"と"How Docker networks a container"を読むと勉強になります。