はじめに
本記事はDocker Swarmで実現するローリングアップデートについて記載しています。
Kubernetesではアプリケーションのローリングアップデートを実行することで、ダウンタイムなしのアップデートができます。
従来のオンプレミスのシステムにおけるメンテナンス時の運用では、sorryサーバを用意してLBから1台ずつ切り離してアップデートを行い、アップデート終了後にまた組み込みを行う運用が一つのデザインパターンでした。
クラウドネィティブ時代ではローリングアップデートの恩恵は大きく、今後もデファクトスタンダードになるでしょう。本記事ではDocker Swarm環境における極力ダウンタイムを減らすための運用方法について解説します。
ローリングアップデート
本記事ではDocker Swarmによるクラスタ環境を構築し、ローカルでDockerレジストリをセットアップしていることを前提としています。
Docker Swarmによるクラスタ環境構築については、以前書いたDocker Swarmで学ぶサービスメッシュを参照。
ビルド作業
例えば、ローリングアップデートを行わないでコンテナのビルドを行う場合はポートが重複するため、一度コンテナを停止して再度ビルドを行う必要があります。そのため、シングル構成の場合はサービスのダウンタイムを避けることができません。
しかし、ローリングアップデートの場合は先にビルドができるため、アプリケーションリリースで時間の短縮ができます。
まずは、アプリケーションのアップデートを行うサーバに対して資産を配備します。
ローリングアップデートを行うときのポイントは、Docker-composeファイルでイメージのバージョンを変更します。
以下のDocker-composeファイル抜粋の例では、imageで指定するタグ名を変更しています。
- アップデート前
version: '3'
networks:
MyApp:
services:
app:
deploy:
replicas: 2
image: 127.0.0.1:5000/stackdemo
- アップデート時
version: '3'
networks:
MyApp:
services:
app:
deploy:
replicas: 2
image: 127.0.0.1:5000/stackdemo_v2
アップデート前にdocker images
コマンドを実行した結果は以下になります。
REPOSITORY TAG IMAGE ID CREATED SIZE
127.0.0.1:5000/stackdemo latest 1f25d780708a 4 minutes ago 878MB
redis latest 4cdbec704e47 2 weeks ago 98.2MB
registry <none> 708bc6af7e5e 2 months ago 25.8MB
node 12.2-alpine f391dabf9dce 11 months ago 77.7MB
以下のコマンドを実行してビルドします。
# docker-compose build
WARNING: Some services (app, redis) use the 'deploy' key, which will be ignored. Compose does not support 'deploy' configuration - use `docker stack deploy` to deploy to a swarm.
redis uses an image, skipping
Building app
Step 1/10 : FROM node:12.2-alpine
---> f391dabf9dce
(略)
Successfully built f03dc959d289
Successfully tagged 127.0.0.1:5000/stackdemo_v2:lates
docker images
コマンドを実行し、新しいイメージが作成されていることを確認します。
REPOSITORY TAG IMAGE ID CREATED SIZE
127.0.0.1:5000/stackdemo_v2 latest f03dc959d289 3 minutes ago 879MB
127.0.0.1:5000/stackdemo latest 1f25d780708a 10 minutes ago 878MB
redis latest 4cdbec704e47 2 weeks ago 98.2MB
registry <none> 708bc6af7e5e 2 months ago 25.8MB
node 12.2-alpine f391dabf9dce 11 months ago 77.7MB
ローカルのDockerレジストリにプッシュします。
# docker-compose push
WARNING: Some services (app, redis) use the 'deploy' key, which will be ignored. Compose does not support 'deploy' configuration - use `docker stack deploy` to deploy to a swarm.
Pushing app (127.0.0.1:5000/stackdemo_v2:latest)...
The push refers to repository [127.0.0.1:5000/stackdemo_v2]
6b65a73c07f0: Pushed
647209689cbb: Pushed
a5bda7b4ef65: Pushed
80f6c9bc1a2c: Pushed
76e5dca151d7: Mounted from stackdemo
917da41f96aa: Mounted from stackdemo
7d6e2801765d: Mounted from stackdemo
f1b5933fe4b5: Mounted from stackdemo
latest: digest: sha256:84ee56656dc9a9e87d4058bba2c98ebdd3615629258f13c4ac81ff56def69b11 size: 2002
serviceによるデプロイ
docker service update
コマンドでデプロイする場合は以下のコマンドを実行します。--update-delay
などのオプションで指定している引数は例になります。
# docker service update --update-delay 5s --update-parallelism 1 --image 127.0.0.1:5000/stackdemo_v2 stackdemo_app
overall progress: 2 out of 2 tasks
1/2: running [==================================================>]
2/2: running [==================================================>]
verify: Service converged
stackによるデプロイ
docker stack
コマンドでデプロイする場合の手順は以下のコマンドを実行します。通常時のstackによるデプロイと同じです。
# docker stack deploy --compose-file docker-compose.yml stackdemo
アプリケーションのダウングレード
元の資産があるディレクトリに移動し、docker service update
コマンドまたは、docker stack
コマンドでデプロイします。以下はdocker stack
コマンドの例です。
# docker stack deploy --compose-file docker-compose.yml stackdemo
ナレッジ
最小構成のシステムを基準に考えた場合は、アップデートする前のDocker-compose.yml
ファイルで指定するreplicasの数は2以上が望ましいと考えます。
docker service update
コマンドの--update-delay 60s
のオプションを指定することで、アップデートの間隔を設けることができます。1サーバに対して2コンテナ以上稼働する様に設定することでダウンダイムの影響を局所化することができます。
以下はdocker service update
コマンドでローリングアップデート実行時の動きです。
本記事の構成はMaster1台とNode1台になります。docker-compose.yml
ファイルで指定するreplicasの数を2としているので、それぞれのホストでアプリケーションコンテナは2個ずつ作成されます。
ローリングアップデート実行後、コンテナ1個毎にアプリケーションのアップデートが始まります。
stackdemo_app
overall progress: 1 out of 4 tasks
1/4: running [==================================================>]
2/4:
3/4:
4/4:
docker service update
コマンドの--update-delay 60s
のオプションにより、アプリケーションのアップデートは60秒の間隔で実行されます。
stackdemo_app
overall progress: 2 out of 4 tasks
1/4: running [==================================================>]
2/4: running [==================================================>]
3/4:
4/4:
例としてこのアプリケーションのAPIはバージョン情報をレスポンスとして返します。以下はLBのDNS名にアクセスしたレスポンスとして、{"version":"1.0"}
と{"version":"1.1"}
が交互に返ってくることから、順次アプリケーションのアップデートが行われているのが確認できます。
{"version":"1.0"}
{"version":"1.1"}
{"version":"1.0"}
{"version":"1.1"}
{"version":"1.0"}
{"version":"1.1"}
overall progress: 3 out of 4 tasks
1/4: running [==================================================>]
2/4: running [==================================================>]
3/4: running [==================================================>]
4/4:
全てのコンテナに対するローリングアップデートが終了しました。
overall progress: 4 out of 4 tasks
1/4: running [==================================================>]
2/4: running [==================================================>]
3/4: running [==================================================>]
4/4: running [==================================================>]
verify: Service converged
docker container ps -a
コマンドを実行すると、古いアプリケーションが稼働していたコンテナは停止し、新しいアプリケーションのコンテナが作成されていることが確認できます。なお、ローリングアップデート時の動きとしては、まず古いアプリケーションのコンテナが停止し、新しいコンテナが生成されます。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
52db94935164 127.0.0.1:5000/stackdemo_v2:latest "/bin/sh -c 'yarn st…" 38 minutes ago Up 38 minutes 3001/tcp stackdemo_app.4.j5vgh0f7azp88zal6rd7gveny
8ea68352da6c 127.0.0.1:5000/stackdemo_v2:latest "/bin/sh -c 'yarn st…" 41 minutes ago Up 41 minutes 3001/tcp stackdemo_app.2.zc2pzhd2xkbc8obvc4apvg7qh
4733dd99b9f4 127.0.0.1:5000/stackdemo:latest "/bin/sh -c 'yarn st…" 43 minutes ago Exited (1) 41 minutes ago stackdemo_app.2.s0lq2qx6zkj5v51mdnfrl4ygr
fee3bf216379 127.0.0.1:5000/stackdemo:latest "/bin/sh -c 'yarn st…" 43 minutes ago Exited (1) 38 minutes ago stackdemo_app.4.uymqss60i5ac4ozxa05xfgaw4
4ef0610778f0 redis:latest "docker-entrypoint.s…" 43 minutes ago Up 43 minutes 6379/tcp stackdemo_redis.2.ls88b5nb1h5qeo0todl6lc7dn
867d0cadeeea registry:2 "/entrypoint.sh /etc…" About an hour ago Up About an hour 5000/tcp registry.1.wspi67ubshjo47af8b55kvz10
Docker-compose.yml
ファイルで指定するreplicasの数を増やした場合、Dockerで出力されるログはコンテナ分増量します。
Docker Swarm設計のポイントとして、ダウンタイムを考慮したけれどもストレージを考慮していなかったために、Dockerのログでディスクが枯渇したら本末転倒です。その場合はDockerで使用するディスク領域を別にするなど工夫が必要になります。
おわりに
Docker Swarmは十分本番環境で使用できる技術ですが、Dockerが出力するログの考慮や、挙動が不安定なときもあるのでリスクヘッジを抑えてからの運用を行うのが望ましいです。