出典: http://dockone.io/article/1037
Docker の出現後、コンテナ技術はインターネット分野で前例のない人気を獲得しました大企業や新興企業のコーダーは基本的に、さまざまな技術コミュニティやさまざまな講演やカンファレンスで関連テクノロジーについて学んでいます。私たちも新興企業として例外ではありません。昨年 Docker について学び、1 年前にいくつかのソリューションをテストしました。今日は、その過程で遭遇したさまざまな落とし穴といくつかの考えをまとめたいと思います。これが、Docker について学習し、それを試してみたいと考えている学生に刺激を与えることを願っています。もちろん、この分野で豊富な経験を持つ人は大歓迎です。クラスメートはいくつかの提案や指導をしてくれました。
この記事では、Docker の理論的な知識や基本的な概念については触れません。基本的な理論については、Docker の公式ドキュメントを参照することをお勧めします。 Coolshell ブログのいくつかの記事を参照できます: Docker 基本技術: Linux 名前空間 (パート 1)、Docker 基本技術: Linux 名前空間 (パート 2)、Docker 基本技術: Linux CGroup、Docker 基本技術: AUFS、Docker 基本技術: DeviceMapper 。
1. プロジェクト環境
私たちのプロジェクトで使用されている標準的な PHP テクノロジー スタック: PHP-FPM + Nginx は Alibaba Cloud の ECS 上で実行され、データベースも Alibaba Cloud のサービスです。
2. 起源
普通の襄西スタートアップ企業の貂蝉プロジェクトでは、理論上、あまり複雑な技術を使用する必要はなく、新しい技術を抑制するのもプログラマーの責任です。 . 職業倫理。しかし、私がこのプロジェクトに挑戦したのは、新しい技術を試したかったからではなく、前回の記事で述べたlaravelのパフォーマンスの問題やHHVMなど、プロジェクト立ち上げ以来さまざまな問題に遭遇したためです。または、PHP7 などの新しいテクノロジはパフォーマンスについて大きく言及しています。それらをすべて一度に切り替えるのは危険すぎるため、コンテナを使用して特定のサービスを実行してテストすることができます。別の例としては、以前にバグがあり、特定のインターフェイスにバグがあった場合があります。問題が発生して、システム全体の応答がタイムアウトになりました。別の例として、さまざまな技術カンファレンスで他の人が共有した経験を読んだ後、私も実際に試してみたくなりました (笑)。
3. 簡単なテスト
Docker の哲学によれば、各コンテナは独立したサービスであり、サービスはインターフェイスを通じて相互に連携します。私たちが採用したソリューションは、PHP-FPM と Nginx が異なるコンテナーで実行され、PHP-FPM コンテナーがポートを Nginx コンテナーに公開するというものです。
当初、コンテナ間のネットワーク通信には Docker に付属のリンクが使用されていましたが、リンクはコンテナの作成時に /etc/hosts ファイルを変更することで実装されます。これを使用しているときに遭遇した問題の 1 つは、リンクされたコンテナーが再起動された後、コンテナーの IP が変更されるのに、リンク コンテナーが更新されないことでした (バージョン 1.10 ではリンク メカニズムが変更されました。これが原因かどうかはわかりません)。問題は解決されました (詳しくは調べていません)。もう 1 つの問題は、同じサービスが複数のコンテナを開く必要がある場合、処理がさらに困難になることです。クラスター内で実行されるため、リンクはローカル開発中にのみ再生でき、実稼働環境ではほとんど役に立ちません。この最後の部分で使用される解決策は、サービス検出に consul を使用することです。ここでは consul については説明しません。興味のある方は、Consul と Registrator を使用した Docker コンテナーのサービス検出を参照してください。
次に、コードがホスト上に配置され、コンテナーの起動時にコードのディレクトリがマウントされます。インターフェースの使用シナリオに従って、インターフェースをいくつかの異なるコンテナーに分割して実行し、リソースの分離に関するストレス テストを実施しました。これは期待どおりであり、非常に満足しています。次に、2 つのコンテナを選択し、テストのために HHVM を実行しました。確かにパフォーマンスは大幅に向上しました。全体の構造を以下に示します。
これは普通に使えますが、次はログの処理です。最初はログを保存するためにホスト上のディレクトリをマウントしていましたが、これは Docker の概念と一致しないため、logstash コンテナを作成しました。ログを保存するために使用され、さまざまなコンテナーのログが logstash コンテナーに書き込まれます。
次に、oneapm が提供するサービスを使用しました。これは悪くありません。他のオープンソース ツールのオプションもありますが、oneapm のサービスを使用する方が便利です。
このようにして完全なテクノロジースタックが完成し、数日間実行しても問題はありませんでした。もちろん、プログラマーを目指す私には、より高い要件が必要です。そこで、次の質問を思いつきました。Docker の概念は、コンテナーが完全なサービスであるということですが、私たちの用途は、コンテナー内で PHP-FPM を実行することです。は含まれていませんが、ディレクトリ マウントを通じて実装されます。このように、コードをホストにデプロイする必要があります。サービスとしてのコンテナーの概念を完全に実装することはできません。よし、完璧を追求しよう!
4. 完璧への道
実際、コードをコンテナーに入れるのは、概念的な完璧さを追求するためだけではなく、Docker ベースの CI という別の目的もあります。基本的な考え方は、リリースごとに新しいバージョンのイメージがビルドされ、ビルド プロセス中にコードを最新バージョンに更新し、依存するサードパーティ ライブラリやその他のビジネス関連の前処理を行う必要があるということです。ビルドが完了したら、それをレジストリにプッシュし、各ノードをプルダウンしてコンテナを再起動します。プロセス全体を以下に示します:
どうですか?これで完璧です!現実が完璧であればいいのですが、現実には常にさまざまな落とし穴が待っています。
まず、このメカニズムが使用される前は、ブランチをマージして各ノードからコードをプルするだけでコードを解放するのに数秒しかかかりませんでしたが、Docker を使用した後は、ブランチをマージした後、イメージをビルドし、ビルド後にレジストリにプッシュし、各ノードに移動してイメージをプルダウンする必要があります。これには少なくとも数分かかります。現時点では、Docker ミラーリングの原理はレイヤー メカニズムではない、と言う学生もいるかもしれません。確かに、各ビルドは更新する必要があるレイヤーを更新するだけで済みますが、更新する方法はまだありません。 git ファイルのようないくつかのファイルだけが、少なくともプロジェクトのコード ディレクトリ全体を更新します。
次に、以前はコードを更新するだけで済みましたが、今はコンテナを再起動する必要があります。元々、コンテナーの再起動は非常に高速でしたが、コンテナー内での PHP-FPM の実行は非常に遅くなりました。おそらく、docker stop が実行されると、SIGTERM シグナルがコンテナー内のプロセスに送信され、PHP-FPM がそのプロセスを処理することになります。 SIGTERM シグナル。いくつかのクリーニングが行われます。ノード上には少なくとも数十のコンテナがあり、各コンテナを再起動するには非常に時間がかかります。
このような単純なリリースは、この「完璧な」メカニズムを使用した後、実際には数分かかります。プロセス全体は完全に自動化されていますが、完璧を期すためにそのような妥協をする必要はありません。
さらに、別の非常に奇妙な問題にも遭遇しました。1.10 にアップグレードした後、コンテナに入ってネットワーク リクエストを開始すると、ポートがブロックされることがよくあります。次の IP に ping を実行すると、ポートは通常の状態に戻ります。さまざまなツールを使って長い間デバッグを続けましたが、依然として問題が何であるかを突き止めることができませんでした。ディアオシの新興企業には、そのような深刻な問題を研究するエネルギーがなかったため、当面は脇に置いておかなければなりませんでした。 。
長い間苦労した後、ようやく以前のやり方に戻りました。
5. 現実に直面する
概念的に完璧な解決策はありませんが、トラフィックのピーク時にノードを迅速に起動するなど、アーキテクチャ全体を拡張しやすくする必要があります。近年のクラウドコンピューティングの発展のおかげで、この問題は比較的簡単に解決できます。前述したように、コードはホストのディレクトリに配置されるため、基本的に各ホストがオンラインになるために必要な条件は次の 3 つだけです:
プロジェクト コード ディレクトリ Docker のインストール Salt-minion の設定 (設定ファイルの更新に使用) ECS を購入し、システム イメージを生成した後でのみ、上記の操作を完了する必要があります。新しいノードを起動する必要がある場合は、このシステム イメージを使用します。サーバーを直接設定するだけです。ノードがオンラインになったら、各コンテナを起動し、前述の consul によって実装されたサービス検出メカニズムを通じて自動的にクラスターに参加します。
6. 探索を続けます
将来、単純なクラスター管理に Docker Swarm を使用する予定です。将来、スケジューリングの需要が高まったら、Mesos または Kubernetes を試すかもしれません。ただし、コンテナに関するエコロジカル チェーンは急速に発展しています。必要に応じて、より良いソリューションが見つかるかもしれません。
アーキテクチャの観点から、プロセス全体についての私の考えを簡単にまとめておきます。完璧なアーキテクチャは存在しません。唯一、あなたに最適なアーキテクチャがあります。プログラマーの観点から見ると、テクノロジーを選択するときに最も重要なことは、現在のプロジェクトのニーズ、さまざまなテクノロジーに対するチームの理解、テクノロジーの選択によってもたらされる複雑さを比較検討することです。数人の専門家による技術アーキテクチャの共有を読んだ後は、自分のプロジェクトに積極的に挑戦しないでください。最終的には、自分で処理することさえできず、他の人に後始末を任せなければなりません。最後に、プロジェクトの反復中にプロジェクトをシンプルに保つ能力は、コーダーの技術レベルを測る上で常に重要な基準となります。