スウォームにおける永続記憶容量の共有方法


Docker swarmは、Kubernetesに似ているが、設定して管理するために簡単なオーケストレーションツールです.
スウォームはswarmモードで実行されて、管理者(メンバーシップと委任を管理するために)と労働者(swarmサービスを実行する)として機能する複数のDockerホストから成ります.与えられたDockerホストはマネージャ、労働者、または両方の役割を果たすことができます.
Dockerの群れ機能は、Dockerエンジン(swarmkitを使用して)に埋め込まれています.これは余分なパッケージをインストールする必要がないことを意味します.あなただけのDocker.あなたが場所にそれを置くことに決めたならば、アドレスに対する開いている問題の1つは永続的な記憶装置です.
昔は、多くのプロセスがローカルディスクをホスト上で共有することができました.それはファイルに書き込むプロセスを持っている一般的なパターンとそれらを消費するもう一つのパターンでした.つのプロセスは、同じホスト上で幸せに暮らしていました.しかし、それはコンテナ化された世界のもう一つの物語です.コンテナが管制官によって管理されるとき、あなたのコンテナがどこで動く予定であるかについて、あなたは本当に話すことができません.それは永久のホストを持っていません.そして、あなたがオーケストラストラテジー利点(弾力性、失敗するなど)の多くを失うので、あなたは特定のホストにそれをロックしたくありません.

問題:スウォームクラスタ上のデータ永続性


ディスクを共有する必要のあるサービス、またはREDISのようなデータ持続性を必要とするサービスがあるとします.オプションは何ですか.
一つの簡単なオプションはdocker volumesを使うことです.新しいdockerボリュームを作成するとき、それがつくられたホストの上にあるので、単一のノードで動くならば、それは良いオプションです.
しかし、それがクラスタ上で動作するときに何が起こりますか?良い質問.例を通して歩きましょう.Dockerドキュメンテーションを使用して1人になります(Get Started with Docker Compose)
以下に例を示します.
devopsian: ~/demo
➜ tree
.
 |-app.py
 |-Dockerfile
 |-docker-compose.yml
# app.py
import time

import redis
from flask import Flask

app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)

def get_hit_count():
    retries = 5
    while True:
        try:
            return cache.incr('hits')
        except redis.exceptions.ConnectionError as exc:
            if retries == 0:
                raise exc
            retries -= 1
            time.sleep(0.5)

@app.route('/')
def hello():
    count = get_hit_count()
    return 'Hello World! I have been seen {} times.\n'.format(count)
# Dockerfile
FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
RUN pip install -r flask redis
EXPOSE 5000
COPY . .
CMD ["flask", "run"]
# docker-compose.yml
version: "3.7"
services:
  app:
    build: .
    ports:
      - "5000:5000"
  redis:
    image: "redis:alpine"
    volumes:
      - "redisdata:/data"

volumes:
  redisdata:
    driver: "local"
3ノードの小さなクラスタを仮定します.(クラスタ内の役割は例ではない).あなたのアプリケーションを使用してDockerのファイルを作成し、Redisインスタンスでは、そのボリュームを定義します.あなたのDockerを作成する最初の時間は、Dockerはボリュームを作成し、起動時にあなたのサービスにマウントします.

次に、サービスの新しいバージョンを展開します.クラスタは、Redisインスタンスを以前とは異なるノードにスケジュールすることを決定します.あなたのボリュームに何が起こりますか?

ボリュームがサービスが走るノードに存在しないので、Dockerは新しいノードに同じ名前で新しいボリュームを作成します.前のボリュームはまだデータに存在しますが、古いノードに存在します.Redisサービスにはアクセスできません.Redisは実際に使用するための新しい、空のボリュームを持っています.あなたは一貫した状態で終わる.このソリューションは私たちのために動作しません.

エラスティックファイルシステム


Amazon Elastic File System (Amazon EFS) provides a simple, scalable, fully managed elastic NFS file system for use .. It is built to scale on-demand to petabytes without disrupting applications, growing and shrinking automatically as you add and remove files, eliminating the need to provision and manage capacity to accommodate growth.


EFSは、実行時にマウントできるNFSボリュームを提供します.スワームクラスタは、ノードの1つにサービスを実行し、コンテナにNFSボリュームをマウントするようにスケジュールします.
これらの構成で、クラスタが我々のREDISサービスを異なるノード(失敗、配備などのため)に動かすと決めるならば、マウント(そして、それゆえに、データ)は新しいノードにも動きます.私はEFSボリュームを作成する方法を通過しません.
そのためには、NFS共通パッケージをswarmノードにインストールする必要があります.Ubuntuでは以下のようにインストールできます.
次に、新しいドライバの種類とアドレスを使用して、Dockerのボリューム定義を更新します.下記のように見えます.
# docker-compose-with-efs.yml
version: "3.7"
services:
  app:
    build: .
    ports:
      - "5000:5000"
  redis:
    image: "redis:alpine"
    volumes:
      - "redis-efs:/data"

volumes:
  redis-efs:
    driver: local
    driver_opts:
      type: nfs
      o: addr=fs-1224ea45.efs.us-east-1.amazonaws.com,nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2
      device: "fs-1224ea45.efs.us-east-1.amazonaws.com:/"
ときに我々のアプリを実行すると、REDISデータボリュームは永続的です.これは、READISが実行しているノードに移動します.
here on aws tutorial
これは私たちの本来の問題を解決します.我々は現在、クラスタ間でデータを永続化する方法を持っています.

コスト


このブログ記事は、クラウド基盤としてAWSを使用しています.EFSを比較するとき、私が見つけることができる最も近いサービスAWSは、EBSボリュームです.私はあなたがよく知っていると思う.
あなたはあなたのユースケースの価格を調整するためにAWSからこれらの価格計算機を使用する必要があります.
これらはリンゴにリンゴではありませんが、2つの間の迅速な価格比較を行いましょう.EU地域で100 GBのボリュームを比較する.


種類
充電する
価格
ストレージ
0.088ドル/GB * 730 * 100
64.24ドル
iPOP
3 k -含まれる
0ドル
スループット
125 MB/s
0ドル
あなたは、追加費用でスループットやiopsを増やすことができます.

電子掲示板


EFSでは、料金は異なる(ショックああ?).アクティブなファイルシステムのワークロード用に設計された「標準記憶クラス」をお支払いいただきます.
あなたは、より頻繁にアクセスされたファイルに最適化されたコストである「不当なアクセスストレージクラス」(IA)に異なる価格を支払う.この比較のために、データの50 %が頻繁にアクセスされると見積もりましょう.
種類
充電する
価格
標準記憶装置
0.33ドル/GB月刊* 50
16.5ドル
ストレージ
0.025ドル/GB月刊* 50
1.25ドル
スループット
含まれる2.5 MB/s、6.60ドル
0ドル
スループット部分はちょっとトリッキーです.50 MB/sあたりのストレージストレージGB(50 GB * 50 KB = 2.5 MB/s)と150 KB/s(50 GB * 150 KB = 7.5 MB/s)の読み出し操作を得る.
ご覧のように、EBSとEBSを比較するときに大きなパフォーマンスの影響があります.あなたが高いスループットを必要とするならば、EFSは非常に高価になるかもしれません.

礁 結論


私がこのブログで書いた問題は、オーケストレーションツールを使ってマネージクラスタ上でマイクロサービスを実行するときによく知られている問題です.他の問題と同様に、それぞれのトレードオフがある複数のソリューションがあります.
私は、EFSが共有ストレージ問題を解決するために使用できる便利で、簡単な解決策であることを示しました.しかし、すべてのための正しい解決策ではありません.パフォーマンスは限られており、あなたのアプリケーションが高スループットを必要とする場合、それは非常に高価になることができます.それらのケースでは、あなたは他の何かを使いたいです.
あなたがスループットで妥協することができるならば、EFSはクラスタ共有記憶を管理する魅力的なオプションになります.
NFSボリュームをDocker構成ファイルに定義するときは、サービス定義の一部です.これは、使用するインフラストラクチャの世話をします.私は、このパターンがマイクロサービスを扱うとき、良いパターンを見つけます.
あなたがもう一つのクラスタにこのサービスを動かす必要があるならば、将来いつでも、NFSマウントはあなたがするのを覚えている必要がない1つのものです.