7
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Docker Swarmで実現するローリングアップデート

Posted at

はじめに

本記事は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_swarm_update.png

以下は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が出力するログの考慮や、挙動が不安定なときもあるのでリスクヘッジを抑えてからの運用を行うのが望ましいです。

参考

7
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?