こんにちは。
株式会社クラスアクト インフラストラクチャ事業部の大塚です。
今回はDocker SwarmとNFSを使ってdocker volumeを共有化した環境を構築してみます。
docker volumeを共有化することでSwarmのservice本領発揮です!
環境イメージ
今回構築する環境は以下となります。
3台でSwarm環境を構成。Swarmのマスターは第4オクテッドが70のホスト(ohtsuka-swarm01)です。
うち1台をNFSサーバとして兼用して構築します。NFSサーバに/home/docker-volumeディレクトリを作成して、そこをエクスポートしてNFSクライアントからマウント出来るようにします。
docker volumeはデフォルトで/var/lib/docker/volume/配下に作成されるのでNFSクライアント側ではこれを/home/docker-volumeとマウントしてvolumeをSwarm環境で共有化します。
※余談のところでも書いていますが、wordpress serviceに関してもreplicateは1の方が良いと思います。3つ立てるとたぶんセッション管理等などもやらないといけなくなり、、、ページの遷移があべこべになってしまうかと思います。
参考手順
過去に私が投稿した記事になります。
Docker Swarm環境構築は以下を参考にしています。
NFSサーバの構築に関しては以下を参考にしてます。
構築
Swarm環境構築
Swarm環境は参考手順のまま実行すればOKです。
NFSサーバ構築
以下のコマンドを作ってNFSサーバインストール、環境設定を行います。
apt -y install nfs-kernel-server
cp -p /etc/exports /etc/exports.org
vi /etc/exports
cat /etc/exports
# /etc/exports: the access control list for filesystems which may be exported
# to NFS clients. See exports(5).
#
# Example for NFSv2 and NFSv3:
# /srv/homes hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check)
#
# Example for NFSv4:
# /srv/nfs4 gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)
# /srv/nfs4/homes gss/krb5i(rw,sync,no_subtree_check)
#
/home/docker-volume 192.168.2.0/24(rw,no_root_squash)
mkdir /home/docker-volume
cd /home/
chmod 777 docker-volume
exportfs -a
systemctl restart nfs-server
systemctl enable nfs-server
NFSクライアント構築
NFSサーバを使用したい全てのサーバで以下を実行します。
apt install -y nfs-common
mount -t nfs 192.168.2.72:/home/docker-volume /var/lib/docker/volumes
コマンド実行後、以下のコマンドを実行してマウント先が表示されていればOKです。
root@ohtsuka-swarm01:~# df -m
Filesystem 1M-blocks Used Available Use% Mounted on
tmpfs 794 2 793 1% /run
/dev/mapper/ubuntu--vg-ubuntu--lv 15011 5305 8923 38% /
tmpfs 3969 0 3969 0% /dev/shm
tmpfs 5 0 5 0% /run/lock
/dev/sda2 1946 129 1699 8% /boot
tmpfs 794 1 794 1% /run/user/1000
192.168.2.72:/home/docker-volume 15011 4957 9270 35% /var/lib/docker /volumes
実際にdocker volumeを作成してvolumeを共有化することが出来ているかを確認します。まずSwarmのマスタで以下を実行します。
root@ohtsuka-swarm01:~# docker volume create test
test
root@ohtsuka-swarm01:~# docker volume ls
DRIVER VOLUME NAME
local test
次にSwarmのworkerにsshしてvolumeが格納されているディレクトリでlsをしてみます。testと出力されることを確認します。
※docker volume lsでも表示できるのですが、testという名前ではなく別の名前で保存されているようなので確認するためには微妙な気がしました。
root@ohtsuka-swarm03-nfs:~# ls /var/lib/docker/volumes/
test
またNFSサーバのマウント先でも確認をしてみます。
あることから問題ないことが判断できると思います。
root@ohtsuka-swarm03-nfs:~# ls /home/docker-volume/
test
正常なSwarm + NFS環境となっているかを確認する
まず今回デプロイするservice用のオーバーレイネットワークを作成します。
以下のコマンドを実行します。
Swarm環境下では同じネットワークにおり、serviceデプロイ時に--nameで名前を指定すると、その名前で名前解決が出来るようです。
root@ohtsuka-swarm01:~# docker network create --driver overlay wordpress-net
root@ohtsuka-swarm01:~# docker network ls
NETWORK ID NAME DRIVER SCOPE
6984d9f9992c bridge bridge local
bbadddba21f4 docker_gwbridge bridge local
90186f06fe04 host host local
o4q6jh524kdd ingress overlay swarm
b15de6d941c8 none null local
jsf4rm30hp61 wordpress-net overlay swarm
次にwordpressで使用する実データを保存するvolumeを作成します。
root@ohtsuka-swarm01:~# docker volume create mysql-volume
mysql-volume
root@ohtsuka-swarm01:~# docker volume ls
DRIVER VOLUME NAME
local mysql-volume
local test
wordpressに紐づけられるMySQL serviceをデプロイしていきます。
以下のコマンドを実行します。
docker service create --name mysql-container \
--env MYSQL_ROOT_PASSWORD=password \
--env MYSQL_DATABASE=wordpress \
--env MYSQL_USER=test \
--env MYSQL_PASSWORD=password \
--network wordpress-net \
--replicas 1 \
--mount type=volume,source=mysql-volume,target=/var/lib/mysql \
mysql:latest
次にwordpress serviceをデプロイします。
docker service create --name wordpress-container \
-e DB_HOST=mysql-container \
-e DB_NAME=wordpress \
-e DB_USER=test \
-e DB_PASSWORD=password \
--network wordpress-net \
--replicas 3 \
--publish 8080:80 \
wordpress:latest
serviceがデプロイされていることを確認します。
root@ohtsuka-swarm01:~# docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
gdzyjypak9l9 mysql-container replicated 1/1 mysql:latest
lgsaflc1u2ag wordpress-container replicated 3/3 wordpress:latest *:8080->80/tcp
どこのホストで稼働しているかも確認してみます。
wordpressのserviceに関してはSwarmの全てのノード上にデプロイされています。一方でMySQL serviceに関しては1号機(マスター)上にデプロイされていることがわかります。
root@ohtsuka-swarm01:~# docker service ps wordpress-container
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
pjl1kfcbjefq wordpress-container.1 wordpress:latest ohtsuka-swarm03-nfs Running Running 3 minutes ago
bkivh2c2ykh1 wordpress-container.2 wordpress:latest ohtsuka-swarm02 Running Running 3 minutes ago
v6ljjbdxgq37 wordpress-container.3 wordpress:latest ohtsuka-swarm01 Running Running 3 minutes ago
root@ohtsuka-swarm01:~# docker service ps mysql-container
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
krvel5swqie6 mysql-container.1 mysql:latest ohtsuka-swarm01 Running Running 3 minutes ago
任意のWebブラウザを開いて任意のノードのIPアドレス:8080にアクセスします。
Database HostはMySQL serviceをデプロイした時の--nameオプションと同じです。名前解決が出来るはずです。
ログインしてみたり、画面遷移が正常に進むことを確認します。
MySQLコンテナを削除してみます。
その前にMySQLが乗っかっているノードに意図的に負荷をかけるためにnginxをデプロイします。
※これをしないとMySQLコンテナを消しても同じノードにデプロイしなおされてしまってvolumeが共有化されていることが確認できません。
root@ohtsuka-swarm01:~# docker run --name nginx-container -d nginx:latest
root@ohtsuka-swarm01:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
16fe7dd29de1 nginx:latest "/docker-entrypoint.…" 5 seconds ago Up 3 seconds 80/tcp nginx-container
d600da8ecf77 mysql:latest "docker-entrypoint.s…" 3 minutes ago Up 3 minutes 3306/tcp, 33060/tcp mysql-container.1.oxghwygrgc3mm7rd9lzl516rs
29c9d907398f wordpress:latest "docker-entrypoint.s…" 27 minutes ago Up 27 minutes 80/tcp wordpress-container.3.v6ljjbdxgq37ttv5et7vzzjtp
改めてMySQLコンテナを削除します。
削除後、service psコマンドを実行してMySQL serviceがどのノード上にデプロイしなおされたかを確認します。今度はohtsuka-swarm02ノード上にデプロイされていますね。移動していることがわかります。
root@ohtsuka-swarm01:~# docker stop d600da8ecf77 && docker rm d600da8ecf77
d600da8ecf77
d600da8ecf77
root@ohtsuka-swarm01:~# docker service ps mysql-container
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
ke85nk3z83w2 mysql-container.1 mysql:latest ohtsuka-swarm02 Running Preparing 20 seconds ago
改めてwebブラウジングしてみます。
同じ画面が表示されることを確認します。共有化出来ていることがわかりますね。
※共有化出来ていないとwordpressの初期設定画面が表示されるはずです。
余談
ここまでグダグダとwordpressコンテナを3つで構築していますが、こちらも基本的に1の方が良い気がします。。。