コンテナが単一プロセス モデルであるのはなぜですか?

コンテナが単一プロセス モデルであるのはなぜですか?

現在、Go 言語の主な応用分野の 1 つは、コンテナ (Docker に代表される)、Kubernetes、Prometheus などを含むクラウド ネイティブ テクノロジーです。後ほど、クラウド ネイティブ テクノロジー スタックの主要テクノロジーを紹介する一連の記事を書く予定です。

過去 2 年間、多くの大企業にとって主要な技術的方向性の 1 つは、アプリケーションをクラウドに移行することでした。このプロセスにおける典型的な誤用は、コンテナを仮想マシンとして使用し、コンテナ内で一連のプロセスを開始することです。ただし、コンテナと仮想マシンのプロセス管理機能には大きな違いがあります。コンテナでも仮想マシンでも、プロセス番号 1 が存在します。仮想マシンでは systemd プロセスであり、コンテナではエントリポイントの起動プロセスです。その後、他のすべてのスレッドはプロセス番号 1 の子プロセス、または子プロセスの子プロセスとなり、これを再帰的に繰り返します。ここでの主な違いは、systemd プロセスがゾンビ プロセスをリサイクルできるかどうかです。より多くのコンテナ技術の専門家とコミュニケーションを取りたい場合は、私の WeChat liyingjiese を追加し、「グループに参加」と記入してください。このグループは、世界中の大手企業のベストプラクティスと業界の最新動向を毎週報告しています。

[[277611]]

ゾンビプロセス

ゾンビ プロセスといえば、Linux システムにおけるプロセスの状態について簡単に説明します。 ps や top などのコマンドを使用して、システム内のプロセスを表示できます。たとえば、ecs 仮想マシンで ps aux を実行すると、次の出力が得られます。

  1. [root@emr-header-1 ~]# ps 補助
  2. ユーザーPID %CPU %MEM VSZ RSS TTY STAT 開始時間コマンド
  3. ルート 1 0.1 0.0 190992 3568 ? Ss 3月16日 289:04 /usr/lib/systemd/systemd --switched-root --system --de  
  4. ルート 2 0.0 0.0 0 0 ? S 3月16日 0:05 [kthreadd]
  5. ルート 3 0.0 0.0 0 0 ? S 3月16日 13:01 [ksoftirqd/0]
  6. ルート 5 0.0 0.0 0 0 ? S< 3月16日 0:00 [kworker/0:0H]
  7. ルート 7 0.0 0.0 0 0 ? S 3月16日 14:41 [移行/0]
  8. ルート 8 0.0 0.0 0 0 ? S 3月16日 0:00 [rcu_bh]
  9. ルート 9 0.0 0.0 0 0 ? S 3月16日 243:19 [rcu_sched]
  10. ルート 10 0.0 0.0 0 0 ? S 3月16日 0:50 [ウォッチドッグ/0]
  11. ルート 11 0.0 0.0 0 0 ? S 3月16日 0:39 [ウォッチドッグ/1]
  12. ルート 12 0.0 0.0 0 0 ? S 3月16日 23:51 [移行/1]
  13. ルート 13 0.0 0.0 0 0 ? S 3月16日 15:44 [ksoftirqd/1]
  14. ルート 15 0.0 0.0 0 0 ? S< 3月16日 0:00 [kworker/1:0H]

最初のものは、先ほど説明したプロセス No. 1 systemd であることがわかります。 STAT 列はプロセスのステータスです。ここでのステ​​ータスはすべて S に関連していますが、通常は R、D、Z などのステータスもあります。各ステータスの意味を簡単に説明すると次のようになります。

  • S:割り込み可能なスリープは、中国語では割り込み可能なスリープ状態とも呼ばれ、特定のリソースまたはイベントの準備が整うのを待っているため、システムによってプロセスが一時的に中断されていることを意味します。リソースまたはイベントが準備完了になると、プロセスは R 状態に切り替わります。
  • R:これは Running の略で、Runnable を指す場合もあります。これは、プロセスが実行中であるか、実行を待機中であることを示します。
  • Z:ゾンビ、つまりゾンビプロセスです。各プロセスは pid などの特定のリソースを占有することがわかっています。プロセスが終了してもリソースがリサイクルされない場合、そのプロセスはゾンビ プロセスになります。
  • D:ディスク スリープは、中断不可能なスリープとも呼ばれ、中断不可能なスリープ状態です。通常、プロセスは IO やその他のリソースを待機しており、中断することはできません。 D状態 実際に初めてPSを使うときに、つまづく人も多いと思います。通常、IO およびその他のリソースの準備が完了すると、D 状態は R 状態に切り替わります。プロセスが長時間 D 状態にある場合、IO に問題があることが多いです。ほとんどの場合、解決策はマシンを再起動することです。
  • I:アイドル、つまりアイドル状態、割り込み不可能なスリープ状態にあるカーネル スレッド。 D 状態プロセスとの主な違いは、実際には負荷の増加を引き起こさない可能性があることです。

ゾンビプロセスに関しては、ここで議論を続けましょう。通常の使用では、子プロセスを作成するには、通常、親プロセスがシステム コール wait() または waitpid() を介して子プロセスが終了するのを待機し、子プロセスのリソースを再利用する必要があります。この方法に加えて、リサイクルは非同期的に実行することもできます。この方法の基本は、子プロセスが終了した後、親プロセスに SIGCHLD シグナルを送信することです。これに基づいて、親プロセスは子プロセスのリソースをリサイクルするための SIGCHLD シグナル処理関数を登録します。これら 2 つの方法を覚えておいてください。それらについては後で説明します。

ゾンビ プロセスの最大の害は、プロセス番号などのリソースが永続的に占有されることです。システムには最大プロセス数 n の制限があり、プロセス番号 1 から n が占有されると、システムはプロセスとスレッドを作成できなくなります (OS では、プロセスとスレッドは同じデータ構造 task_struct で表されます)。この時点で、ユーザーの直感では、シェルはコマンドを実行できないと感じます。その理由は、シェルコマンド実行の本質は fork だからです。

  1. [root@emr-header-1 ~]# ulimit -a
  2. コアファイルサイズ(ブロック、-c) 0
  3. データセグメントサイズ(キロバイト、-d) 無制限
  4. スケジュール優先度 (-e) 0
  5. ファイルサイズ(ブロック、-f)無制限
  6. 保留中のシグナル (-i) 63471
  7. 最大ロックメモリ (キロバイト、-l) 64
  8. 最大メモリサイズ(キロバイト、-m) 無制限
  9. 開いているファイル (-n) 131070
  10. パイプサイズ(512 バイト、-p) 8
  11. POSIX メッセージ キュー (バイト、-q) 819200
  12. リアルタイム優先( -r ) 0
  13. スタックサイズ(kbytes, -s) 8192
  14. CPU時間(秒、-t)無制限
  15. 最大 ユーザープロセス (-u) 63471
  16. 仮想メモリ (キロバイト、-v) 無制限
  17. ファイルロック (-x) 無制限

孤立したプロセス

前述したように、子プロセスが親プロセスより先に終了し、親プロセスが子プロセスの残りのリソースをリサイクルしない場合は、ゾンビ プロセスが生成されます。ここに別の状況があります。親プロセスが子プロセスより先に終了した場合、子プロセスのリソースを誰が再利用するのでしょうか?

親プロセスは子プロセスより先に終了します。この時点で、まだ実行中の子プロセスを一般に孤立プロセスと呼びます。ただし、実際には孤立プロセスの明確な定義はなく、そのステータスは上記で説明したいくつかのプロセス状態のままです。では、孤立プロセスのリソースを誰が回収するのでしょうか?この状況に対応して、Unix 系システムでは、これらの孤立プロセスの親プロセスをプロセス番号 1、つまり systemd プロセスに設定し、systemd は孤立プロセスのリソースを再利用します。

シングルプロセスモデルの本質

上記の 2 つのセクションを読んだ後、仮想マシンまたは完全な OS がゾンビ プロセスを回避する方法がわかるはずです。ただし、コンテナでは、プロセス 1 が一般にエントリ ポイント プロセスになります。コンテナは、ゾンビプロセス処理を回避するために、孤立プロセスの親プロセスをプロセス番号 1 に設定する上記の方法を処理できません。これにより、孤立プロセスなどの異常なシナリオでは、コンテナ内のゾンビプロセスを完全に処理できないというジレンマが発生します。

したがって、コンテナの単一プロセス モデルの本質は、コンテナ内のプロセス 1 には、複数のプロセスや複数のスレッドなどの複雑なシナリオを管理する機能がないことです。これらの複雑な状況をコンテナ内で処理する必要がある場合、開発者はエントリ ポイント プロセスにこの機能を提供する必要があります。これにより、開発者の精神的負担が増大することは間違いありません。これは、一般的なテクノロジーやプラットフォーム フレームワークが望まない恥ずかしい状況です。

回避方法

開発者がエントリポイント プロセスに複数のプロセスを管理する機能を与えることについてのセクション 2 での説明に加えて、これを行うには Kubernetes を使用することをお勧めします。今では誰もコンテナを手動で管理していないと思います。ほとんどの人はコンテナ オーケストレーションおよびスケジューリング ツール Kubernetes に目を向けています (まだ Swarm を使用している人には、できるだけ早く暗闇を捨てて光に参加することをお勧めします :))。

Kubernetes では、複数のコンテナを Pod にオーケストレーションし、同じ Linux NameSpace を共有できます。この技術の本質は、Kubernetes を使用して一時停止イメージを提供することです。詳しく説明すると、一時停止イメージを使用して最初に NameSpace をインスタンス化し、次に他のコンテナーをこの NameSpace に追加して NameSpace の共有を実現します。突然、これにはコンテナと名前空間の技術的な背景が必要であることに気付きました。スペースが限られているため、この技術的な背景についてはご自身で調べていただければ幸いです。あるいは、次の記事でコンテナ技術の本質について論じるつもりです。

では早速、一時停止について紹介しましょう。 Pause は、Kubernetes バージョン 1.16 で導入されたテクノロジーです。 pause を使用するには、次のように、Pod によって作成された yaml で shareProcessNamespace パラメータを true に指定するだけです。

  1. APIバージョン: v1
  2. 種類: ポッド
  3. メタデータ:
  4. 名前: nginx
  5. 仕様:
  6. プロセス名前空間を共有: true  
  7. コンテナ:
  8. -名前: nginx
  9. 画像: nginx
  10. -名前: シェル
  11. 画像: ビジーボックス
  12. セキュリティコンテキスト:
  13. 機能:
  14. 追加
  15. -SYS_PTRACE
  16. 標準入力: 
  17. 端末: 

ポッドを作成する:

  1. kubectl を適用 -fshare-プロセス名前空間.yaml

Pod に接続し、ps を使用してプロセス リストを表示します。

  1. / # ps 斧
  2. PIDユーザー     タイムコマンド
  3. 1 ルート 0:00 /一時停止
  4. 8 root 0:00 nginx: マスタープロセス nginx -g デーモンオフ;
  5. 14 101 0:00 nginx: ワーカープロセス
  6. 15 ルート 0:00 sh
  7. 21 ルート 0:00 ps ax

Pod 内のプロセス 1 が /pause になり、他のコンテナのエントリポイント プロセスがプロセス 1 の子プロセスになることがわかります。ここで、問題の核心に迫ります。/pause プロセスは、ゾンビ プロセスを回避するために、どのようにして孤立プロセスの親をプロセス 1 に設定するのでしょうか。ソースコードを見てみましょう。git リポジトリ: pause.c:

  1. #define STRINGIFY(x) #x
  2. #define VERSION_STRING(x) STRINGIFY(x)
  3.  
  4. #ifndef バージョン
  5. #define バージョンヘッド
  6. #終了
  7.  
  8. 静的void sigdown( int signo) {
  9. psignal(signo, "シャットダウン中、信号を受信しました" );
  10. 終了(0);
  11. }
  12.  
  13. 静的void sigreap( int signo) {
  14. (waitpid(-1, NULL , WNOHANG) > 0)の間
  15. ;
  16. }
  17.  
  18. int main( int argc, char **argv) {
  19. 整数i;
  20. (i = 1; i < argc; ++i)の場合{
  21. if (!strcasecmp(argv[i], "-v" )) {
  22. printf( "pause.c %s\n" , VERSION_STRING(VERSION));
  23. 0を返します
  24. }
  25. }
  26.  
  27. (getpid() != 1) の場合
  28. /* pause はインフラ コンテナー外部で使用されるため、エラーにはなりません*/
  29. fprintf(stderr, "警告: 一時停止は最初のプロセスである必要があります\n" );
  30.  
  31. (sigaction(SIGINT、&(struct sigaction){.sa_handler = sigdown}、 NULL )< 0)の場合
  32. 1 を返します
  33. if (sigaction(SIGTERM, &(struct sigaction){.sa_handler = sigdown}, NULL ) < 0)
  34. 2を返します
  35. if (sigaction(SIGCHLD, &(struct sigaction){.sa_handler = sigreap,
  36. .sa_flags = SA_NOCLDSTOP},
  37. NULL ) < 0)
  38. 3を返します
  39.  
  40. のために(;;)
  41. 一時停止();
  42. fprintf(stderr, "エラー: 無限ループが終了しました\n" );
  43. 42を返します
  44. }

35 行目と 13 行目に特に注意してください。これが上で説明した内容です。

  • この方法に加えて、リサイクルは非同期的に実行することもできます。この方法の基本は、子プロセスが終了した後、親プロセスに SIGCHLD シグナルを送信することです。これに基づいて、親プロセスは子プロセスのリソースをリサイクルするための SIGCHLD シグナル処理関数を登録します。

SIGCHLD シグナル処理関数の中核は、 while (waitpid(-1, NULL, WNOHANG) > 0) の行です。ここで、WNOHANG パラメータは、親プロセスがブロックせずに直接戻ることを可能にします。

要約する

コンテナ化への変革への道のりは非常に長いです。変換プロセス中、多くのビジネス関係者は、思考の慣性によりコンテナを仮想マシンとして使用したいと考えますが、これにより多くの問題が発生する可能性があります。おそらく、より良い実践のために、いくつかのコンテナ設計パターンを検討することができるでしょう。

<<:  クラウド コンピューティングによる混乱を経験している 3 つのホットな市場はどれですか?

>>:  IBM はハイブリッド クラウドでクラウド コンピューティングの状況を変えることができるでしょうか?

推薦する

公式アカウントのコンテンツをより強力にするには?

公開アカウントであっても、親アカウントであっても、コンテンツが王様であるというルールは依然として適用...

成功するオンラインプロモーション記事の書き方

パスカルは人間は考える葦であると言った。これは、人間の尊さと価値を強調する儒教の「人間本位」の考えと...

SEOを行うには強い心が必要

私はSEOを半月以上やっています。今やっている仕事はSEO業界の最も基本的で簡単な仕事に過ぎず、まだ...

A5ウェブマスターネットワークの第2回タオバオSEOトレーニングコースの申し込み受付を開始しました

Taobao 検索ランキングの最適化は、Taobao SEO とも呼ばれ、Taobao ストアを開設...

A5最適化チーム:ウェブサイトのランキング変動の全体的な原因のSEO診断

ウェブサイトの最適化の過程で、ウェブサイトのランキングが変動する原因に遭遇することはよくありますが、...

ウェブサイトのプレビュー: 新しいウェブサイトの立ち上げを急がないでください

他のウェブマスターと話し合った結果、Xiaomao は、新しいウェブサイトを構築した友人たちが皆、ウ...

草の根談話:WeChatは市場の信頼に応えられるか?

WeChat 5.0のリリースは、最近比較的大きなニュースです。コミュニケーション機能から始まった製...

金華にまたもやリベート型のねずみ講ウェブサイトが出現、今回の仕掛けは「米ドル投機」

「EU Rebate Network」のスクリーンショット。完全に英語で書かれているので、かなり威圧...

企業ウェブサイトの Baidu 最適化にはどのような戦略に従うべきでしょうか?

ご存知のとおり、電子商取引ネットワーク マーケティングの発展に伴い、企業の Web サイトは徐々にイ...

クラウドデータベースはテクノロジースタックの重要な部分です

適切なクラウド データベースを導入すると、クラウドからモバイル、エッジに至るまで、企業が依存するさま...

Cloudopsツールの統合はツール自体よりも重要です

平日の午前 3 時、ある会社の AIops ツールは、ネットワーク トラフィックが飽和点に達したこと...

クラウドネイティブ時代の機会と課題: DevOps で打開する方法

クラウドネイティブ時代において、国内外の多くのクラウドベンダーが強力な技術的配当をリリースしています...

分散ストレージ Ceph の進化 · SOSP 2019

[[347277]] 「Read the Papers」は、コンピューターおよびソフトウェア エンジ...

百度は再びスパム外部リンクの厳しい取り締まりを宣言、ウェブマスターは生き残りに苦戦

4月25日、百度幹部の李氏は再び外部リンクに関する声明を発表した。百度のアルゴリズム更新に伴い、百度...

私たちはウェブサイトの自然な最適化ランキングを提唱しています

インターネット企業を経営している方なら、Baidu、Google、Yahoo などの検索エンジンでウ...