輸送用コンテナの中に住んでいない限り、おそらくコンテナについて聞いたことがあるでしょう。業界は永続的なインフラストラクチャから一時的なインフラストラクチャへの明確な移行を行っており、コンテナはその移行の真っ只中にあります。理由は非常に単純です。コンテナーは確かに開発チームが迅速に立ち上げて実行するのに役立ちますが、運用の様相を完全に変える可能性はさらに高くなります。
しかし、それは正確にはどのように見えますか?ローカルで、またはいくつかのサーバーで手動で実行中のコンテナーから飛躍する準備ができたらどうなりますか?理想的な世界では、アプリケーションをサーバーのクラスターに投げて、「実行してください」と言いたいだけです。
ありがたいことに、それは 私たちがいる場所 今日。
この記事では、Docker Swarmとは何か、そしてDockerSwarmが提供する優れた機能のいくつかについて説明します。次に、実際にスウォームモードを使用してスウォームにデプロイする方法を確認し、デプロイされたスウォームでの日常の操作がどのようになるかの例をいくつか示します。 Dockerとコンテナーの基本的な知識は絶対にお勧めですが、これは優れたものです。 ブログ投稿 まず、コンテナを初めて使用する場合。
最初のスウォームの作成とデプロイに取り掛かる前に、Dockerスウォームとは何かを理解しておくと役に立ちます。 Docker自体は何年も前から存在しており、今日ではほとんどの人がDockerをコンテナーランタイムと考えています。しかし実際には、Dockerは多くの異なる部分で構成されており、すべてが連携して機能します。たとえば、そのコンテナランタイム部分は、と呼ばれる2つの小さなコンポーネントによって処理されます。 runC そして コンテナ 。 Dockerが進化し、コミュニティに還元されるにつれて、これらの小さなコンポーネントを作成することが、機能を成長させて迅速に追加するための最良の方法であることがわかりました。そのため、SwarmKitと、Dockerに直接組み込まれているSwarmモードがあります。
Docker Swarmは、コンテナーオーケストレーションエンジンです。大まかに言うと、異なるホストで実行されている複数のDockerエンジンが必要であり、それらを一緒に使用できます。使い方は簡単です。アプリケーションをサービスのスタックとして宣言し、残りはDockerに処理させます。サービスは、アプリケーションインスタンスからデータベース、またはRedisやRabbitMQなどのユーティリティまで何でもかまいません。これはまったく同じ概念であるため、開発でdocker-composeを使用したことがある場合は、おなじみのように聞こえます。実際、スタック宣言は文字通りdocker-compose.yml
です。バージョン3.1構文のファイル。つまり、開発とスウォームのデプロイに同様の(多くの場合は同一の)構成構成を使用できますが、ここでは少し先を行っています。 SwarmモードのDockerのインスタンスがあるとどうなりますか?
Swarmの世界には、マネージャーとワーカーの2種類のノード(サーバー)があります。マネージャーは労働者でもあり、物事を実行し続けるという追加の責任があることを覚えておくことが重要です。すべての群れは、リーダーとして指定された1つのマネージャーノードから始まります。そこから、1つのコマンドを実行するだけで、ノードを群れに安全に追加できます。
Swarmは、Raftアルゴリズムの実装のおかげで高可用性を実現します。すでにラフトがあるので、ラフトについてはあまり詳しく説明しません。 素晴らしいチュートリアル それがどのように機能するかについてですが、一般的な考え方は次のとおりです。リーダーノードは常に他のマネージャーノードにチェックインし、それらの状態を同期しています。状態の変化が「受け入れられる」ために、マネージャーノードは多くのコンセンサスに達します。これは、ノードの大部分が状態の変化を確認したときに発生します。
これの利点は、マネージャーノードが群れのコンセンサスを損なうことなく散発的にドロップオフできることです。状態の変化がコンセンサスに達した場合、それは大多数のマネージャーノードに存在することが保証されており、現在のリーダーに障害が発生しても持続します。
拡張現実はいつ始まりましたか
A、B、Cという名前の3つのマネージャーノードがあるとします。もちろん、Aは恐れを知らないリーダーです。ある日、一時的なネットワークエラーがAをオフラインにし、BとCをそのままにします。長い間(数百ミリ秒)Aから連絡がなかったため、BとCはランダムに生成された期間待機してから、選挙に出て相手に通知します。もちろん、この場合、最初に当選した人が当選します。この例では、Bが新しいリーダーになり、クォーラムが復元されます。しかし、それでは、どんでん返し:Aがオンラインに戻るとどうなりますか?まだリーダーだと思いますよね?各選挙には用語が関連付けられているため、Aは実際には用語1で選出されました。Aがオンラインに戻り、BとCの注文を開始するとすぐに、Bが用語2のリーダーであることを知らせてくれます。 Aは辞任します。
もちろん、これと同じプロセスははるかに大規模に機能します。 3つ以上のマネージャーノードを持つことができます。ただし、もう1つ簡単なメモを追加します。各スウォームは、特定の数のマネージャーの損失のみを受け取ることができます。 n個のマネージャーノードの群れは(n-1)/2
を失う可能性がありますクォーラムを失うことなくマネージャー。つまり、3人のマネージャーの群れの場合、1人を失う可能性があり、5人の場合、2人を失う可能性があります。これの根本的な理由は、多数派のコンセンサスについての考えに戻ります。これは、本番環境に移行するときに必ず覚えておくべきことです。
これまでのところ、マネージャーは同期を保つのが本当に得意であることがわかっています。すごい!しかし、彼らは実際に何をしているのでしょうか? Swarmにサービスのスタックをデプロイすると言ったことを覚えていますか?サービスを宣言するときは、実際にサービスを実行する方法に関する重要な情報をSwarmに提供します。これには、各サービスに必要なレプリカの数、レプリカの配布方法、特定のノードでのみ実行する必要があるかどうかなどのパラメーターが含まれます。
サービスがデプロイされたら、設定したデプロイメント要件が引き続き満たされるようにするのはマネージャーの仕事です。 Nginxサービスをデプロイし、レプリカが3つあることを指定するとします。マネージャーは、コンテナーが実行されていないことを確認し、使用可能なノード全体に3つのコンテナーを均等に分散します。
ただし、さらにクールなのは、コンテナに障害が発生した場合(またはノード全体がオフラインになった場合)、Swarmは残りのノードにコンテナを自動的に作成してその違いを補うことです。 3つのコンテナを実行したい場合は、3つのコンテナを実行し、Swarmがすべての重要な詳細を処理します。さらに、これは大きなプラスです。スケールアップまたはスケールダウンは、Swarmに新しいレプリケーション設定を与えるのと同じくらい簡単です。
最後の例から重要ですが微妙な詳細を指摘したいと思います。Swarmが選択したノードでコンテナーをインテリジェントに開始している場合、それらのコンテナーがどこで実行されるかは必ずしもわかりません。最初は怖いように聞こえるかもしれませんが、実際にはSwarmの最も強力な機能の1つです。
同じNginxの例を続けて、これらのコンテナーはポート80を公開する必要があることをDockerに伝えたと想像してください。ブラウザーをポート80でそのコンテナーを実行しているノードに向けると、そのコンテナーのコンテンツが表示されます。そこには驚きはありません。ただし、驚くべきことは、そのコンテナを実行していないノードにリクエストを送信しても、同じコンテンツが表示されることです。ここで何が起こっているのですか?
Swarmは実際には、入力ネットワークを使用して、そのコンテナを実行している利用可能なノードにリクエストを送信し、同時に負荷分散を行っています。したがって、同じノードに3つのリクエストを行うと、3つの異なるコンテナにヒットする可能性があります。スウォーム内の単一ノードのIPを知っている限り、そのノードで実行されているすべてのものにアクセスできます。逆に、これにより、何がどこで実行されているかを気にすることなく、群れのすべてのノードにロードバランサー(ELBなど)を向けることができます。
外部接続だけではありません。同じスタックで実行されているサービスには、相互に通信できるオーバーレイネットワークがあります。コードにIPアドレスをハードコーディングする代わりに、接続するホスト名としてサービスの名前を使用できます。たとえば、アプリが「redis」という名前のRedisサービスと通信する必要がある場合、ホスト名として「redis」を使用するだけで、Swarmはそのリクエストを適切なコンテナーにルーティングします。また、これはdocker-composeを使用した開発と、Docker Swarmを使用した本番環境でシームレスに機能するため、アプリをデプロイする際に心配する必要が1つ少なくなります。
運用中の場合は、本番環境の更新がひどく失敗したときにパニック発作を経験した可能性があります。それは悪いコード更新、あるいは単に構成エラーである可能性がありますが、突然生産がダウンしています!上司はどちらの方法も気にしない可能性があります。彼らはそれがあなたのせいであることを知っているだけです。まあ、心配しないでください、スウォームもこれに背を向けています。
サービスを更新するときに、一度に更新する必要のあるコンテナーの数と、新しいコンテナーが失敗し始めた場合にどうなるかを定義できます。特定のしきい値の後、Swarmは更新を停止するか、(Docker 17.04以降)コンテナーを前のイメージと設定にロールバックできます。明日の朝、上司にコーヒーを持ってくる必要はありません。
最後になりましたが、Docker Swarmには、すぐに使用できる優れたセキュリティ機能が備わっています。ノードが群れに参加するとき、ノードはそれ自体を検証するだけでなく、それがあなたが思っている群れに参加していることも検証するトークンを使用します。その瞬間から、ノード間のすべての通信は相互TLS暗号化を使用して行われます。この暗号化はすべてSwarmによって自動的にプロビジョニングおよび管理されるため、証明書の更新やその他の一般的なセキュリティの問題について心配する必要はありません。もちろん、キーを強制的に回転させたい場合は、そのためのコマンドがあります。
Docker Swarmの最新バージョンには、シークレット管理も組み込まれています。これにより、キーやパスワードなどのシークレットを、それらを必要とするサービスだけに安全にデプロイできます。シークレットを使用してサービスを提供すると、そのサービスのコンテナーには、シークレットの値を含む特別なファイルがファイルシステムにマウントされます。言うまでもありませんが、これは従来のアプローチであった環境変数を使用するよりもはるかに安全です。
あなたが私のような人なら、飛び込んでこれらすべての機能を試してみたくなります!それで、これ以上面倒なことはせずに、飛び込みましょう!
Docker Swarmのパワーと使いやすさを示すために、非常に基本的なFlaskアプリを作成しました。 Webアプリは、リクエストを処理したコンテナ、処理されたリクエストの総数、および「シークレット」データベースパスワードを示すページを表示するだけです。
これは、実際のFlaskアプリ、Nginxリバースプロキシ、Redisキーストアの3つのサービスに分類されます。リクエストごとに、アプリはnum_requests
をインクリメントしますRedisでキーを押すと、ヒットしているFlaskインスタンスに関係なく、正しい数のリクエストが反映されていることがわかります。
すべてのソースコードはで入手できます GitHub 何が起こっているのかを「チェックアウト」したい場合。
このチュートリアルを実行するときは、独自のサーバーを自由に使用してください。ただし、使用することを強くお勧めします。 play-with-docker.com ただ飛び込みたい場合。これは、Dockerがプリインストールされている複数のネットワークノードを起動できる、数人のDocker開発者によって運営されているサイトです。 4時間後にシャットダウンされますが、この例ではこれで十分です。
了解しました。どうぞ!先に進み、PWD(play-with-docker)で3つのインスタンスを作成するか、お気に入りのVPS(仮想プライベートサーバー)サービスで3つのサーバーを起動し、それらすべてにDockerエンジンをインストールします。いつでもイメージを作成して、将来ノードを追加するときにそれを再利用できることを覚えておいてください。マネージャーノードとワーカーノードの間にソフトウェアの違いはないため、2つの異なるイメージを維持する必要はありません。
まだ回転していますか?心配しないで、待ちます。では、最初のマネージャーとリーダーノードを作成します。最初のインスタンスで、群れを初期化します。
docker swarm init --advertise-addr
ノードのIPアドレスに置き換えます。 PWDでは、IPアドレスが上部に表示されます。独自のVPSを使用している場合は、ネットワーク内の他のノードからアクセスできる限り、サーバーのプライベートIPアドレスを自由に使用してください。
あなたは今群れを持っています!ただし、ノードが1つしかないため、かなり退屈な群れです。先に進んで、他のノードを追加しましょう。 init
を実行すると、参加トークンの使用方法を説明する長いメッセージが表示されていることがわかります。他のノードをワーカーにするため、これは使用しません。これらのノードをマネージャーにします。最初のノードでこれを実行して、マネージャーの参加トークンを取得しましょう。
プラグナンツのゲシュタルトルールは、視覚系が
docker swarm join-token manager
結果のコマンドをコピーして、2番目と3番目のノードで実行します。見よ、3ノードの群れ!すべてのノードが実際に存在することを確認しましょう。 docker node ls
コマンドは、群れのすべてのノードを一覧表示します。次のようなものが表示されます。
$ docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS su1bgh1uxqsikf1129tjhg5r8 * node1 Ready Active Leader t1tgnq38wb0cehsry2pdku10h node3 Ready Active Reachable wxie5wf65akdug7sfr9uuleui node2 Ready Active Reachable
最初のノードのIDの横にアスタリスクがあることに注意してください。これは、現在接続しているノードであることを示しているだけです。また、このノードが現在リーダーであり、何かが発生した場合に他のノードが到達可能であることがわかります。
それがいかに簡単であったかを理解するために少し時間を取って、最初のアプリをデプロイしましょう!
これで、ビジネス開発チームは、新しいアプリが1時間以内にデプロイされ、準備が整うことをクライアントに約束しました。典型的な、私は知っています。ただし、恐れることはありません。Dockerを使用して構築されているため、それほど時間は必要ありません。開発者は親切にも私たちに彼らのdocker-compose
を貸してくれましたファイル:
version: '3.1' services: web: image: lsapan/docker-swarm-demo-web command: gunicorn --bind 0.0.0.0:5000 wsgi:app deploy: replicas: 2 secrets: - db_password nginx: image: lsapan/docker-swarm-demo-nginx ports: - 8000:80 deploy: mode: global redis: image: redis deploy: replicas: 1 secrets: db_password: external: true
すぐに分解しますが、まだその時間はありません。展開しましょう!先に進み、最初のノードにdocker-compose.yml
というファイルを作成します。上記の構成を入力します。echo '' > docker-compose.yml
を使用して簡単に行うことができます。
通常、これをデプロイすることもできますが、構成にはdb_password
というシークレットを使用することが記載されているため、そのシークレットをすばやく作成しましょう。
echo 'supersecretpassword' | docker secret create db_password -
すごい!これで、Dockerに構成を使用するように指示するだけです。
docker stack deploy -c docker-compose.yml demo
このコマンドを実行すると、Dockerが定義した3つのサービスweb
、nginx
、redis
を作成していることがわかります。ただし、スタックデモに名前を付けたため、サービスには実際にはdemo_web
、demo_nginx
、およびdemo_redis
という名前が付けられています。 docker service ls
を実行すると、実行中のサービスを確認できます。コマンド。次のように表示されます。
$ docker service ls ID NAME MODE REPLICAS IMAGE PORTS cih6u1t88vx7 demo_web replicated 2/2 lsapan/docker-swarm-demo-web:latest u0p1gd6tykvu demo_nginx global 3/3 lsapan/docker-swarm-demo-nginx:latest *:8000->80/ tcp wa1gz80ker2g demo_redis replicated 1/1 redis:latest
出来上がり! Dockerは、イメージを適切なノードにダウンロードし、サービス用のコンテナーを作成しました。レプリカがまだフルキャパシティーになっていない場合は、しばらく待ってからもう一度確認してください。 Dockerはまだイメージをダウンロードしている可能性があります。
ただし、私の言葉(またはDockerの言葉)を受け入れないでください。アプリに接続してみましょう。サービス構成では、Dockerにポート8000でNGINXを公開するように指示しています。PWDを使用している場合は、ページの上部に「8000」という青いリンクが表示されます。 PWDは、実際には、そのポートでサービスが実行されていることを自動的に検出しました。それをクリックすると、ポート8000で選択したノードにルーティングされます。独自のサーバーをロールした場合は、ポート8000でサーバーのIPの1つに移動するだけです。
いくつかの基本的な情報を提供する美しいスタイルの画面が表示されます。
どのコンテナがリクエストを処理したかをメモしてから、ページを更新します。オッズは変更されています。しかし、なぜ?そうですね、DockerにFlaskアプリのレプリカを2つ作成するように指示しました。これにより、両方のインスタンスにリクエストが配信されます。たまたまもう一方のコンテナに2回ヒットしました。また、両方のFlaskコンテナが指定した単一のRedisインスタンスと通信しているため、リクエストの数が増えたことにも気付くでしょう。
任意のノードからポート8000をヒットしてみてください。アプリに適切にルーティングされます。
この時点で、すべてが機能し、うまくいけば、プロセスが無痛であることがわかりました!それを詳しく見てみましょうdocker-compose.yml
ファイルを作成して、実際にDockerに伝えたことを確認してください。大まかに言うと、web
、nginx
、redis
の3つのサービスが定義されていることがわかります。通常の作成ファイルと同様に、各サービスで使用するイメージと実行するコマンドをDockerに提供しました。 nginx
の場合、ホストのポート8000をコンテナのポート80にマップするように指定しました。これはすべて、これまでの標準の構成構文です。
ここで新しいのは、デプロイキーとシークレットキーです。これらのキーはdocker-compose
によって無視されるため、開発環境には影響しませんが、docker stack
によって使用されます。 Webサービスを見てみましょう。非常に簡単ですが、Flaskアプリで2つのレプリカを実行することをDockerに伝えています。また、Webサービスにはdb_password
が必要であることをDockerに通知しています。秘密。これにより、コンテナに/run/secrets/db_password
という名前のファイルが確実に含まれるようになります。シークレットの値が含まれています。
Nginxに移動すると、デプロイモードがglobal
に設定されていることがわかります。デフォルト値(Webで暗黙的に使用されます)はreplicated
です。これは、必要なレプリカの数を指定することを意味します。 global
を指定すると、群れのすべてのノードがサービスのインスタンスを1つだけ実行する必要があることをDockerに通知します。実行docker service ls
繰り返しになりますが、nginx
に気付くでしょう群れの各ノードに1つずつ、合計3つのレプリカがあります。
最後に、群れのどこかでRedisの単一インスタンスを実行するようにDockerに指示しました。 Webコンテナは、Redisホストを要求すると自動的にルーティングされるため、どこでも問題ありません。
最初のアプリをDockerSwarmにデプロイしました。おめでとうございます。使用する一般的なコマンドをいくつか確認してみましょう。
あなたのサービスをチェックする必要がありますか? docker service ls
をお試しくださいおよびdocker service ps
。前者は各サービスの概要を示し、後者は指定されたサービスで実行されている各コンテナーに関する情報を示します。これは、どのノードがサービスを実行しているかを確認する場合に特に役立ちます。
アプリを更新する準備ができたらどうしますか?さて、docker stack deploy
についてのクールなこと実際には、既存のスタックにも更新が適用されます。新しいDockerイメージをリポジトリにプッシュしたとしましょう。実際には、最初に使用したのと同じデプロイコマンドを実行するだけで、群れが新しいイメージをダウンロードしてデプロイします。
もちろん、スタック内のすべてのサービスを常に更新したい場合はありません。サービスレベルでも更新を実行できます。最近、Webサービスの画像を更新したとしましょう。このコマンドを発行して、すべてのWebコンテナーを更新できます。
docker service update --image lsapan/docker-swarm-demo-web:latest demo_web
このコマンドの追加の利点は、元の構成で行うように指定した場合にローリング更新が適用されることです。また、そうでない場合でも、次のようにローリング更新を実行するように指示するフラグを更新に渡すことができます。
docker service update --image lsapan/docker-swarm-demo-web:latest --update-parallelism 1 --update-delay 30s demo_web
これにより、一度に1つのコンテナが更新され、更新の合間に30秒待機します。
2つのWebコンテナがあることは素晴らしいことですが、何が優れているか知っていますか? 10を持っている!群れの中でサービスを上下にスケーリングするのは、次のように簡単です。
docker service scale demo_web=10
そのコマンドを実行し、docker service ps demo_web
の出力を確認します。現在、コンテナは10個あり、そのうち8個はほんの少し前に開始されたことがわかります。興味がある場合は、Webアプリケーションに戻ってページを数回更新し、元の2つ以上のコンテナIDを取得していることを確認することもできます。
スタックとサービスがデプロイおよびスケーリングされ、すばらしいです!しかし今、あなたはそれらをオフラインにしたいのです。これは、それぞれのrm
で実行できます。コマンド。デモスタックを削除するには、次のコマンドを実行します。
g.co/express/hello
docker stack rm demo
または、1つのサービスを削除するだけの場合は、次を使用します。
docker service rm demo_web
実行したときのことを覚えておいてくださいdocker node ls
私たちの群れのノードをチェックするために以前に?これは、各ノードに関する一連の情報を提供しました。 可用性 。デフォルトでは、ノードは アクティブ 、つまり、コンテナを実行するための公正なゲームです。ただし、メンテナンスを実行するためにノードを一時的にオフラインにする必要がある場合があります。確かに、シャットダウンするだけで群れは回復しますが、Moby(Dockerクジラ)に少し注意を払うのはいいことです。
ここで、ノードの排出が行われます。ノードを次のようにマークすると、 ドレイン 、Docker Swarmは、その上で実行されているすべてのコンテナーを他のノードに委任し、可用性をに戻すまで、ノード上のコンテナーを開始しません。 アクティブ 。
node1
を排出したいとしましょう。実行できます:
docker node update --availability drain node1
簡単!仕事に戻す準備ができたら:
docker node update --availability active node1
これまで見てきたように、DockerとSwarmモードを組み合わせると、これまで以上に効率的かつ確実にアプリケーションをデプロイできます。 DockerSwarmが唯一のコンテナオーケストレーションエンジンではないことは言及する価値があります。実際、それは若いものの1つです。 知事 ずっと長く使用されており、より多くの本番アプリケーションで確実に使用されています。とは言うものの、SwarmはDockerによって公式に開発されたものであり、彼らは毎日さらに多くの機能を追加することに取り組んでいます。どちらを使用する場合でも、コンテナを使用してください。
Docker Swarmは、コンテナーオーケストレーションエンジンです。そのため、クラスター内のノード間でのコンテナーのスケジューリングとバランシングを高可用性の方法で処理します。
インフラストラクチャを手動で管理する代わりに、Docker Swarmを使用すると、アプリのデプロイ方法とスケーリング方法を宣言的に指定できます。展開すると、仕様が継続的に満たされるようになります。
あまりない!ホストにDockerをインストールし、そのうちの1つに群れを初期化させるだけです。それが完了すると、他のホストはすぐに参加できます。
docker-composeと同じ構文を使用するDockerスタックのおかげで、開発者はスタック構成を作成する作業のほとんどをすでに完了しています。これは、ライブに移行するときの驚きが少ないことを意味し、それは常に良いことです。