この記事は、Dockerにおけるcgroupの具体的な使用法を徹底的に理解するのに役立ちます。

この記事は、Dockerにおけるcgroupの具体的な使用法を徹底的に理解するのに役立ちます。

序文

プロセスは、システム内の CPU、メモリ、ディスクなどのコンピューティング リソースまたはストレージ リソースを比較的任意に使用します。プロセス リソースの使用率を制限し、プロセス リソースの使用状況を追跡したいと考えています。これにより、プロセスを均一にグループ化し、グループに基づいてリソースを監視および制御するために使用される cgroup の出現が可能になります。

cgroupとは

Linux CGroup (Linux Control Group) は、実際には Linux カーネルの機能です。これは、プロセスをグループ別に管理するための Linux のメカニズムです。これは、2006 年に Google のエンジニアである Paul Menage 氏と Rohit Seth 氏によって最初に開始され、当初はプロセス コンテナと名付けられました。 2007 年以降、コンテナが導入されると、混乱を避けるために cgroup に名前が変更され、カーネル バージョン 2.6.24 に統合されました。
ユーザー レベルの観点から見ると、cgroup テクノロジはシステム内のすべてのプロセスを独立したツリーに編成します。各ツリーにはシステムのすべてのプロセスが含まれます。ツリーの各ノードはプロセス グループであり、各ツリーは 1 つ以上のサブシステムに関連付けられています。ツリーは主にプロセスをグループ化するために使用され、サブシステムはこれらのグループを操作するために使用されます。

cgroupの構成

Cグループは主に以下の2つの部分から構成されます

  • サブシステム: サブシステムはカーネル モジュールです。cgroup ツリーに関連付けられると、ツリー ノードに対して特定の操作を実行します。このサブシステムは、各プロセス グループのリソースをスケジュールまたは制限するために主に使用されるため、「リソース コントローラー」と呼ばれることがよくありますが、この記述は完全に正確ではありません。perf_event サブシステムのように、監視やステータスの観察を行うためだけにプロセスをグループ化することもあるためです。
  • 階層: 階層は cgroup ツリーとして理解できます。ツリーの各ノードはプロセス グループであり、各ツリーは複数のサブシステムに関連付けられています。ツリーには Linux システム内のすべてのプロセスが含まれますが、各プロセスは 1 つのノード (プロセス グループ) にのみ属することができます。システムには多数の cgroup ツリーが存在する可能性があり、各ツリーは異なるサブシステムに関連付けられ、プロセスは複数のツリーに属することができます。つまり、プロセスは複数のプロセス グループに属することができ、各プロセス グループが異なるサブシステムに関連付けられます。

/proc/cgroupディレクトリを表示することで、現在のシステムがサポートしているサブシステムの関連付けを確認できます。

ここに画像の説明を挿入

最初の列: サブシステム名を示します

2 番目の列: 関連付けられている cgroup ツリーの ID を示します。複数のサブシステムが同じ cgroup ツリーに関連付けられている場合、それらのフィールドは同じになります。たとえば、図の cpuset、cpu、cpuacct などです。

3 番目の列: サブシステムに関連付けられた cgroup ツリー内のプロセス グループの数、つまりツリー上のノードの数を示します。

cgroupが提供する機能

以下の機能を提供します

  • リソース制限: リソース使用制限
  • 優先順位付け: 優先度制御
  • 会計:監査または統計
  • 制御: プロセスを一時停止し、実行プロセスを再開する

一般的に、cgroupは次のことを行うために使用できます。

  • 一連のプロセス(すべてのMySQLプロセスなど)を分離し、コア制限などのリソースの使用を制限します。
  • このプロセスセットにメモリを割り当てる
  • このプロセスセットに十分な帯域幅とストレージ制限を割り当てる
  • 特定のデバイスへのアクセスを制限する

cgroupはLinuxのファイルシステムとして表示されます。次のコマンドを実行します。

ここに画像の説明を挿入

マウントが成功すると、/sys/fs の下に多くのサブシステムを含む cgroup ディレクトリがあることがわかります。たとえば、cpu、cpuset、blkio などです。
次に、/sys/fs/cgroup/cpu ディレクトリにサブディレクトリ test を作成します。この時点で、このディレクトリにはさらに多くのファイルがあることがわかります。

ここに画像の説明を挿入

cgroup 内の CPU を制限する

cgroup では、CPU 関連のサブシステムには cpusets、cpuacct、cpu が含まれます。
その中で、cpuset は主に CPU のアフィニティを設定するために使用されます。cgroup 内のプロセスを指定された CPU でのみ実行するように制限したり、指定された CPU で実行しないように制限したりできます。同時に、cpuset はメモリのアフィニティも設定できます。 cpuacct には、現在の cgroup によって使用されている CPU に関する統計が含まれています。ここでは、次の CPU についてのみ説明します。

次に、/sys/fs/cgroup/cpuの下にサブグループを作成し、このディレクトリの下のファイルリストを作成します。

ここに画像の説明を挿入

cpu.cfs_period_us は期間の長さを設定するために使用され、cpu.cfs_quota_us は設定された期間の長さ内で現在の cgroup が使用できる CPU 時間の量を設定するために使用されます。2 つのファイルは連携して CPU 使用量の上限を設定します。両方のファイルの単位はマイクロ秒 (us) です。cpu.cfs_period_us の値の範囲は 1 ミリ秒 (ms) から 1 秒 (s) です。cpu.cfs_quota_us の値は 1 ミリ秒より大きくなる場合があります。
CPU制限の使い方を説明するために例を挙げてみましょう。無限ループを書くと

ここに画像の説明を挿入

実行中は、topを使用して占有率が100%に達したことを確認します。

ここに画像の説明を挿入

cfs_quota_usを設定するには次のコマンドを実行します。

エコー 20000 > /sys/fs/cgroup/cpu/test/cpu.cfs_quota_us

このコマンドは、プロセスの CPU 使用率を 20% 削減し、プロセス PID を cgroup に追加することを意味します。

ここに画像の説明を挿入

もう一度 top を実行すると、CPU 使用率が低下していることがわかります。

ここに画像の説明を挿入

cgroup 内のメモリを制限する

コードにメモリ リークなどのバグがあると、システム メモリが枯渇し、メモリ割り当て不足により他のプログラムの動作が異常になります。システムがスワップ パーティションで構成されている場合、システムは大量のスワップ パーティションを使用するため、システムの動作が非常に遅くなります。
プロセス メモリに対する cgroup の主な制御は次のとおりです。

  • cgroup内のすべてのプロセスが使用するメモリの合計を制限する
  • cgroup内のすべてのプロセスで使用される物理コンテンツ+スワップの合計量を制限する
  • cgroup 内のすべてのプロセスで使用できるカーネル メモリとその他のカーネル リソースの合計量を制限します (CONFIG_MEMCG_KMEM)。

ここでのカーネル メモリの制限は、現在のプロセスによって占有されているカーネル スペース、ソケットによって占有されているメモリ スペースなど、cgroup によって現在使用されているカーネル リソースを制限することを意味します。メモリが不足している場合、現在の cgroup がプロセスの作成を継続したり、カーネルからさらにカーネル リソースを要求したりできなくなる可能性があります。

次の例は、cgroup がメモリを制御する方法を示しています。

#include <iostream>
#include <sys/types.h>
#include <cstdlib>
#include <cstdio>
#include <文字列.h>
#include <unistd.h>

#CHUNK_SIZE 512 を定義する


int メイン()
{
   整数サイズ = 0;
   char *p = nullptr; 
   ながら(1)
   {
          if((p = (char*)malloc(CHUNK_SIZE))==nullptr)
          {
              壊す;
         }

      memset(p, 0, CHUNK_SIZE);
       printf("[%u]-- [%d]MBが割り当てられています ", getpid(), ++size);
       睡眠(1);
   }
    
   0を返します。
}

まず、/sys/fs/cgroup/memoryの下にサブディレクトリを作成してサブcgroupを作成します。たとえば、ここではテストディレクトリを作成します。

$mkdir /sys/fs/cgroup/memory/test

テストディレクトリには以下のファイルが含まれています

ここに画像の説明を挿入

各ファイルの機能は以下に簡単に紹介されています。

書類例示する
cgroup.イベント制御eventfd のインターフェース
メモリ使用量(バイト単位)現在使用されているメモリを表示します
メモリ制限バイト数現在のメモリ制限を設定/表示します
メモリ.失敗数メモリ使用量が制限値に達した回数を表示します
メモリ最大使用量バイト数最大履歴メモリ使用量
メモリのソフト制限バイト数現在のメモリ制限を設定/表示します
メモリ統計現在のcgroupのメモリ使用量を表示します
メモリ使用階層現在の cgroup にサブ cgroup のメモリ使用量を含めるかどうかを設定/表示します。
メモリを強制的に空にする現在の cgroup で可能な限り多くの回収可能なメモリを直ちに回収するようにシステムをトリガーします。
メモリ圧力レベルcgroup.event_control と一緒に使用するメモリ不足の通知イベントを設定します。
メモリのスワップ現在の swappiness を設定して表示する
メモリ移動時の移行チャージプロセスが占有するメモリを別の cgroup に移動するときに、そのメモリも移動するかどうかを設定します。
メモリ.oom_control OOMコントロール関連の設定/表示
メモリ.numa_stat NUMA関連メモリを表示する

次に、memory.limit_in_bytes ファイルに書き込んで制限を設定します。ここでは、下の図に示すように、5Mの制限が設定されています。

ここに画像の説明を挿入

次の図に示すように、上記の例のプロセスをこのcgroupに追加します。

ここに画像の説明を挿入

スワップスペースの影響を受けないようにするには、次の図に示すように、swappiness を 0 に設定して、現在の cgroup がスワップを使用しないようにします。

ここに画像の説明を挿入

物理メモリが上限に達すると、システムのデフォルトの動作では、メモリを要求し続けている cgroup 内のプロセスが強制終了されます。では、この動作をどのように制御するのでしょうか?つまり、memory.oom_control を設定します。このファイルには、現在の cgroup に対して OOM-killer を開始するかどうかを制御するフラグが含まれています。このファイルに 0 が書き込まれると、OOM-killer が起動します。カーネルがプロセスに十分なメモリを割り当てられない場合、カーネルはプロセスを直接強制終了します。このファイルに 1 が書き込まれると、OOM-killer は起動しません。カーネルがプロセスに十分なメモリを割り当てられない場合、カーネルは空きメモリができるまでプロセスを一時停止し、その後実行を続けます。同時に、memory.oom_control には読み取り専用の under_oom フィールドも含まれており、これは現在の状態が OOM 状態に入ったかどうか、つまり一時停止されたプロセスがあるかどうかを示すために使用されます。プロセスが強制終了されたかどうかを示す読み取り専用の killed_oom フィールドもあります。

cgoupプロセスの数を制限する

cgroup には pids と呼ばれるサブシステムがあり、cgroup とそのすべての子孫 cgroup で作成できるタスクの合計数を制限します。ここでのタスクは、fork 関数と clone 関数によって作成されたプロセスを指します。clone 関数はスレッドも作成できるため、ここでのタスクにはスレッドも含まれます。
cgroup ツリーは以前にマウントされているため、ここで子 cgroup を直接作成し、test という名前を付けます。コマンドは以下のとおりです

ここに画像の説明を挿入

テストディレクトリ内のファイルを見てみましょう

ここに画像の説明を挿入

ここで、pids.current は、現在の cgroup とそのすべての孫 cgroup 内のプロセスの合計数を示します。

ここに画像の説明を挿入

pids.max 現在の cgroup とそのすべての孫 cgroup によって作成できるプロセスの最大数。

ここに画像の説明を挿入

実験してpids.maxを1に設定してみましょう

ここに画像の説明を挿入

次に、現在のbashプロセスをcgroupに追加します。

ここに画像の説明を挿入

ランダムにコマンドを実行します。現在のウィンドウでは pids.current が pids.max と等しいため、プロセスの作成は失敗します。

ここに画像の説明を挿入

現在の cgroup の pids.current と pids.max は、現在の cgroup とすべての子孫 cgroup のすべてのプロセスを表すため、子孫 cgroup の pids.max サイズは親 cgroup のサイズを超えることはできません。超過するとどうなりますか? pids.maxを3に設定する

ここに画像の説明を挿入

現在のプロセス数は2です

ここに画像の説明を挿入

シェルウィンドウを再度開き、孫cgroupを作成し、pids.maxを5に設定します。

ここに画像の説明を挿入

現在のシェルのbashプロセスをcroup.procsに書き込む

ここに画像の説明を挿入

元のシェルウィンドウに戻り、コマンドをランダムに実行して、実行が失敗したことを確認します。

ここに画像の説明を挿入

ご覧のとおり、子 cgroup 内のプロセス数は、自身の pids.max によって制限されるだけでなく、祖先 cgroup の pids.max によっても制限されます。

Docker における cgroup の具体的な使い方を徹底的に理解する方法についての記事はこれで終わりです。Docker cgroup に関するより関連性の高いコンテンツについては、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Dockerの核となる原則であるCgroupの詳細な説明
  • Docker基盤技術の適用に関する詳細な説明 名前空間Cgroup
  • docker cgroupリソース監視の詳細な説明
  • cgroups を使用して Docker コンテナのリソース使用量を制限する方法の詳細な説明

<<:  CSS3 オーバーフロープロパティの説明

>>:  javascript:void(0) の意味と使用例

推薦する

Centos7.3は起動時に自動的に起動または指定されたコマンドを実行します

Centos7では、/etc/rc.d/rc.localファイルの権限が削減されており、実行権限があ...

SSDストレージを有効にしたMySQLインスタンスの詳細な説明

SSDストレージを有効にしたMySQLインスタンスの詳細な説明特に OS と MySQL が同じディ...

背景画像に CSS3 変換を適用するためのソリューション

CSS 変換は便利ですが、背景画像にはまだ適用されていません。この投稿では、背景画像を回転させたい場...

HTMLはテキスト行のインターセプトの実装原理とコードを超えています

複数行を超えるテキストをインターセプトするための HTML コードは次のとおりです。 HTML:コー...

CSS テキスト装飾 text-decoration と text-emphasis の詳細な説明

CSS では、テキストは私たちが毎日扱う最も一般的なものの 1 つです。テキストの場合、テキストの装...

MySQL GTID の総合概要

目次01 GTIDの紹介02 GTIDの仕組み03 GTIDの利点と欠点04 テスト環境構築05 テ...

MySQLの保存場所を新しいディスクに移行する方法

1. 新しいディスクを準備し、現在のルートパーティションと同じファイルシステムでフォーマットし、ディ...

MySQL における識別子の大文字と小文字の区別の問題の詳細な分析

MySQL では、テーブル名の大文字と小文字の区別の問題が発生する可能性があります。実際、これはプラ...

Nginx キャッシュ設定例

Web アプリケーションの開発とデバッグを行う際には、テストのためにブラウザのキャッシュをクリアした...

特定のシンボルで複数の行と列に分割するMySQLの例

一部の障害コード テーブルでは、履歴またはパフォーマンス上の理由から、次の設計パターンが使用されます...

Nginx 静的ファイル サービスの構成と最適化の詳細な説明

ルートディレクトリとインデックスファイルroot ディレクティブは、ファイルの検索に使用するルート ...

Unicode署名BOMによる事故原因の分析

ここでは、通常ヘッダーとフッターに対して行われるインクルード ファイルを使用している可能性があります...

クリーンなコードのための Web デザインの 12 の法則 [グラフィック]

美しいコードは美しい Web サイトの基礎です。優れた CSS は、同様に優れた HTML の上にの...

CentOS8 yum/dnfで国内ソースを設定する方法

CentOS 8 ではソフトウェア パッケージのインストール プログラムが変更され、yum 構成方法...

jsネイティブカルーセルプラグインの制作

この記事では、jsネイティブカルーセルプラグインの具体的なコードを参考までに共有します。具体的な内容...