Docker メモリ監視とストレステストの方法

Docker メモリ監視とストレステストの方法

起動していたDockerコンテナはメモリを使い果たした状態になっており、再起動せずにコンテナのメモリを使い果たしている状態です。バックグラウンドを確認するとプロセスがメモリをあまり占有していないことがわかります。メモリはcadvisorによって監視され、cadvisorページ計算方式を使用して計算されるので、dockerのメモリ計算について調べてみることにしました。

docker バージョン:

クライアント:
 バージョン: 1.12.6
 APIバージョン: 1.24
 Goバージョン: go1.6.4
 Gitコミット: 78d1802
 作成日: 2017年1月10日火曜日 20:20:01
 OS/アーキテクチャ: linux/amd64

サーバ:
 バージョン: 1.12.6
 APIバージョン: 1.24
 Goバージョン: go1.6.4
 Gitコミット: 78d1802
 作成日: 2017年1月10日火曜日 20:20:01
 OS/アーキテクチャ: linux/amd64

Kubernetes バージョン:

クライアント バージョン: version.Info{メジャー:"1", マイナー:"8", GitVersion:"v1.8.2+coreos.0", GitCommit:"4c0769e81ab01f47eec6f34d7f1bb80873ae5c2b", GitTreeState:"clean", BuildDate:"2017-10-25T16:24:46Z", GoVersion:"go1.8.3", コンパイラ:"gc", プラットフォーム:"linux/amd64"}
サーバー バージョン: version.Info{Major:"1", Minor:"8", GitVersion:"v1.8.2+coreos.0", GitCommit:"4c0769e81ab01f47eec6f34d7f1bb80873ae5c2b", GitTreeState:"clean", BuildDate:"2017-10-25T16:24:46Z", GoVersion:"go1.8.3", Compiler:"gc", Platform:"linux/amd64"}

1. ポッドyamlファイルを作成し、busyboxイメージをテストに使用し、イメージのコア数とメモリの制限を2Gに設定します。

[docker@k8s busybox]$ cat busybox.yaml


APIバージョン: v1
種類: ポッド
メタデータ:
 名前: ビジーボックス
 名前空間: デフォルト
仕様:
 コンテナ:
 - イメージ: registry.dcos:8021/public/busybox:latest
 指示:
  - 寝る
  - 「3600」
 イメージプルポリシー: IfNotPresent
 名前: ビジーボックス
 リソース:
  制限:
  CPU: "2"
  メモリ: 2Gi
  リクエスト:
  CPU: 100m
  メモリ: 64Mi
 再起動ポリシー: 常に

2. kubectlコマンドでbusyboxサービスを生成する

[docker@k8s busybox]$ kubectl create -f busybox.yaml


ポッド「busybox」が作成されました

3. コンテナの/sys/fs/cgroup/memoryディレクトリに入り、lsを使用して次のファイルを確認します。

-rw-r--r-- 1 ルート ルート 0 5月31日 03:18 cgroup.clone_children
--w--w--w- 1 ルート ルート 0 5月31日 03:18 cgroup.event_control
-rw-r--r-- 1 ルート ルート 0 5月31日 03:18 cgroup.procs
-rw-r--r-- 1 ルート ルート 0 5月31日 03:18 memory.failcnt
--w------ 1 ルート ルート 0 5月31日 03:18 memory.force_empty
-rw-r--r-- 1 ルート ルート 0 5月31日 03:18 memory.kmem.failcnt
-rw-r--r-- 1 ルート ルート 0 5月31日 03:18 memory.kmem.limit_in_bytes
-rw-r--r-- 1 ルート ルート 0 5月31日 03:18 memory.kmem.max_usage_in_bytes
-r--r--r-- 1 ルート ルート 0 5月31日 03:18 memory.kmem.slabinfo
-rw-r--r-- 1 ルート ルート 0 5月31日 03:18 memory.kmem.tcp.failcnt
-rw-r--r-- 1 ルート ルート 0 5月31日 03:18 memory.kmem.tcp.limit_in_bytes
-rw-r--r-- 1 ルート ルート 0 5月31日 03:18 memory.kmem.tcp.max_usage_in_bytes
-r--r--r-- 1 ルート ルート 0 5月31日 03:18 memory.kmem.tcp.usage_in_bytes
-r--r--r-- 1 ルート ルート 0 5月31日 03:18 memory.kmem.usage_in_bytes
-rw-r--r-- 1 ルート ルート 0 5月31日 03:18 memory.limit_in_bytes
-rw-r--r-- 1 ルート ルート 0 5月31日 03:18 メモリ最大使用量バイト
-rw-r--r-- 1 ルート ルート 0 5月31日 03:18 memory.memsw.failcnt
-rw-r--r-- 1 ルート ルート 0 5月31日 03:18 memory.memsw.limit_in_bytes
-rw-r--r-- 1 ルート ルート 0 5月31日 03:18 memory.memsw.max_usage_in_bytes
-r--r--r-- 1 ルート ルート 0 5月31日 03:18 memory.memsw.usage_in_bytes
-rw-r--r-- 1 ルート ルート 0 5月31日 03:18 memory.move_charge_at_immigrate
-r--r--r-- 1 ルート ルート 0 5月31日 03:18 memory.numa_stat
-rw-r--r-- 1 ルート ルート 0 5月31日 03:18 memory.oom_control
---------- 1 ルート ルート 0 5月31日 03:18 memory.pressure_level
-rw-r--r-- 1 ルート ルート 0 5月31日 03:18 memory.soft_limit_in_bytes
-r--r--r-- 1 ルート ルート 0 5月31日 03:18 memory.stat
-rw-r--r-- 1 ルート ルート 0 5月31日 03:18 memory.swappiness
-r--r--r-- 1 root root 0 5月31日 03:18 メモリ使用量バイト
-rw-r--r-- 1 ルート ルート 0 5月31日 03:18 memory.use_hierarchy
-rw-r--r-- 1 ルート ルート 0 5月31日 03:18 通知オンリリース
-rw-r--r-- 1 ルート ルート 0 5月31日 03:18 タスク

私たちは主にいくつかのファイルに焦点を当てています

ファイル名意味
メモリ使用量(バイト単位)使用されているメモリの量(キャッシュとバッファを含む)(バイト)。Linux の used_meme に相当します。
メモリ制限バイト数制限されたメモリの総量(バイト)。Linux の total_mem に相当します。
メモリ.失敗数失敗したメモリ要求の数
メモリ統計メモリ関連の状態

memory.statファイルの内容

フィールド意味
キャッシュページキャッシュ(tmpfs(shmem)を含む)(バイト単位)
rss匿名およびスワップ キャッシュ (tmpfs (shmem) を除く) (バイト単位)
マップされたファイルメモリマップされたマップされたファイルのサイズ(tmpfs(shmem)を含む、バイト単位)
pgpginメモリに保存されているページ数
pgpgoutメモリから読み取られたページ数
スワップ使用されたスワップの量(バイト単位)
アクティブ_匿名tmpfs (shmem) を含む匿名キャッシュとスワップ キャッシュ (アクティブな LRU (Least-Recently Used) リスト内のバイト単位)
非アクティブ_匿名tmpfs (shmem) を含む非アクティブ LRU リスト内の匿名キャッシュとスワップ キャッシュ (バイト単位)
アクティブファイルアクティブ LRU リスト内のファイル バックアップ メモリ (バイト単位)
非アクティブファイル非アクティブ LRU リスト内のファイル バックアップ メモリ (バイト単位)
負けない更新不可能なメモリ(バイト単位)
階層メモリ制限メモリ cgroup を含むレベルのメモリ制限 (バイト単位)
階層メモリ制限メモリ cgroup を含むレベルのメモリとスワップの制限 (バイト単位)

memory.limit_in_bytes ファイルを表示

/sys/fs/cgroup/memory # cat メモリ.limit_in_bytes 
2147483648

コンピューティング コンテナーのメモリ制限は 2 GB で、これは YAML ファイルで定義されたメモリ制限と同じです。 memory.usag_in_bytes ファイルを表示する

/sys/fs/cgroup/memory # cat メモリ使用量バイト数 
2739376

docker stats container id を使用して、memory.usage_in_bytes のデータと一致するコンテナのメモリ使用量を表示します。

4. ddコマンドを使用して1.5gの大きなファイルを素早く生成する

~ # dd if=/dev/zero of=test bs=1M count=1500
1500+0件のレコード
1500+0 レコードが出力されました
1572864000 バイト (1.5GB) をコピーしました。1.279989 秒、1.1GB/秒

docker stats container idを使用して、コンテナが占有しているメモリを再度表示します。

memory.usage_in_bytes ファイルを表示する

/sys/fs/cgroup/memory # cat メモリ使用量バイト数 
1619329024

コンテナが占有するメモリが1.5gに達していることがわかりました。memory.statを確認してください。

/sys/fs/cgroup/memory # cat メモリ.stat
キャッシュ 1572868096
147456 より
rss_huge 0
マップされたファイル 0
汚い 1572868096
書き戻し 0
スワップ 0
pgpgin 384470
pgpgout 433
ページフォールト 607
pgmajfault 0
非アクティブ匿名 77824
アクティブ匿名 12288
非アクティブファイル 1572864000
アクティブファイル 4096
追放不可能 0
階層メモリ制限 2147483648
階層メモリ制限 4294967296
合計キャッシュ 1572868096
合計 147456
合計RSS巨大0
合計マップファイル数 0
合計ダーティ 1572868096
合計書き戻し 0
合計スワップ 0
合計ページ数 384470
合計ページ数 433
合計ページエラー 607
合計pgmajfault 0
合計非アクティブ匿名 77824
合計アクティブ匿名 12288
非アクティブファイル合計 1572864000
合計アクティブファイル 4096
合計_非追放可能数 0

memory.stat ファイルの cache フィールドは 1.5g を追加し、inactive_file フィールドは 1.5g なので、dd によって生成されるファイル キャッシュは inactive_file に基づいて計算されます。キャッシュは再利用可能であり、プロセスによって占有されるメモリを反映しないため、コンテナ メモリの監視が高くなります。

一般に、監視メモリは次の式に従って計算できます。

active_anon + inactive_anon = 匿名メモリ + tmpfs のファイル キャッシュ + スワップ キャッシュ
したがって
active_anon + inactive_anon ≠ rss です。rss には tmpfs が含まれていないためです。
active_file + inactive_file = キャッシュ - tmpfs のサイズ

したがって、実際のメモリ使用量は次のように計算されます。

実際の使用済み = メモリ使用量(バイト単位) - (アクティブファイル + 非アクティブファイル)

5. ストレステスト

(1)TomcatイメージとJMeterストレステストツールを準備します。Tomcat yamlファイルは次のとおりです。

apiバージョン: extensions/v1beta1
種類: デプロイメント
メタデータ:
 名前: tomcat-deployment
仕様:
 レプリカ: 1
 テンプレート:
 メタデータ:
  ラベル:
  アプリ: tomcat
 仕様:
  コンテナ:
  - 名前: トムキャット
  イメージ: registy.dcos:8021/public/tomcat:8
  ポート:
  - コンテナポート: 8080
  リソース:
   制限:
   CPU: "1"
   メモリ: 300Mi
--- 
APIバージョン: v1
種類: サービス
メタデータ:
 ラベル:
 名前: トムキャット
 名前: トムキャット
 名前空間: デフォルト
仕様:
 ポート:
 - 名前: トムキャット
 ポート: 8080
 プロトコル: TCP
 ターゲットポート: 8080
 タイプ: NodePort 
 セレクタ:
 アプリ: tomcat

yaml ファイルで、Tomcat イメージが使用するメモリを 300Mi に制限し、コマンドを実行してファイルを生成します。 docker stats を使用して、負荷のない Tomcat コンテナのメモリ使用量を表示します。

(2)Tomcatのサービスノードポートを抽出する

[docker@ecs-5f72-0006 ~]$ kubectl get svc tomcat -o=custom-columns=nodePort:.spec.ports[0].nodePort
ノードポート
31401

(3)jmeter公式サイトにログインしてストレステストツールをダウンロードする

Windows で jmeter ツールを実行し、bin ディレクトリに移動してクリックし、jmeter を次のように構成します。

テスト オプションを設定したら、[開始] ボタンをクリックしてストレス テストを開始します。docker stats でコンテナーのメモリ使用量を確認し、制限に達していることを確認します。

kubectl get pods を使用してポッドの実行ステータスを確認すると、メモリが制限を超えたために Tomcat が強制終了されたことがわかりました。

要約する

docker stats メモリ監視には常に問題がありました。Docker はメモリ計算にキャッシュ/バッファを含めるため、誤解が生じます。 Docker メモリの計算方法は、キャッシュ/バッファも含まれる Linux メモリ使用量の計算方法と同じです。

ただし、キャッシュは再利用可能であり、I/O 要求でよく使用され、再度アクセスされる可能性のあるデータをメモリを使用して解放することで、システム パフォーマンスが向上します。

公式 github では、多くの人がメモリ監視に関する問題を報告しています。この問題は、Docker 17.06 バージョンになって初めて docker stats で解決されました。

ただし、これは docker 統計の表示が正常に見えるようになるだけです。コンテナに入ってメモリ使用量を確認すると、キャッシュがまだ含まれています。cadvisor によって収集されたデータを直接使用すると、キャッシュがまだ含まれています。

Docker のストレス テストを実施した結果、ストレス テストがプログラムのメモリ制限に達すると、ポッドが再起動することが分かりました。これは、Docker モニタリングを使用すると、メモリが 99% 以上を占めていてもポッドが再起動されない理由も説明しています。メモリのかなりの部分がキャッシュによって占められています。

上記は私の個人的な経験です。参考になれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。間違いや不備な点がありましたら、遠慮なくご指摘ください。

以下もご興味があるかもしれません:
  • Docker 起動時の ES メモリ オーバーフローの解決方法
  • Docker JVM メモリ使用量の表示
  • Docker View プロセス、メモリ、カップ消費量
  • Docker が elasticsearch を起動するときのメモリ不足の問題と解決策
  • Docker でコンテナに使用できるメモリを制限する方法
  • Dockerは指定されたメモリで操作を実行します

<<:  MySQL における exists、in、any の基本的な使い方

>>:  HTMLタグを閉じるのを忘れないでください

推薦する

テキストエリアのテキストをHTMLに変換する方法、つまり復帰改行について

説明: テキストエリアの値の改行を新しい行に変更しますコードをコピーコードは次のとおりです。 <...

HTML iframe と frameset の違い_PowerNode Java Academy

導入1.<iframe> タグ: iframe は、ページ内に内部フレームを生成するイン...

CSS で TikTok テキスト揺れエフェクトを実装する例

日々の開発において、フロントエンドの学生はアニメーションやデザインについてよく議論します。デザイナー...

Q&A: XML と HTML の違い

Q: xml と html の違いがわかりません。違いは何ですか? A: XMLと HTML の違い...

sqlmap インジェクションの詳細なグラフィック説明

目次1. この Web サイトには SQL インジェクションの脆弱性がある可能性があることが判明しま...

Javascriptジェネレータの紹介と使用

ジェネレータとは何ですか?ジェネレーターは関数内で実行されるコードです。値を返した後、一時停止し、呼...

JavaScript に関する 6 つの奇妙で便利な点

目次1. 解体のヒント2. デジタルセパレーター3. try...catch...finally が...

MySql ストアド プロシージャ パラメータの初歩的な使用法の詳細な説明

パラメータでのストアドプロシージャの使用IN パラメータは、プロシージャに情報を渡すためにのみ使用さ...

Dockerデータ管理とネットワーク通信の使用

Docker をインストールし、Docker コアとインストールを通じて簡単な操作を実行できます。 ...

Linux にソフトウェアをインストールするときにソフトウェア パッケージが存在しない問題を解決する方法

ソフトウェア パッケージが存在しない場合は、インストールされているソフトウェアのソフトウェア ソース...

Reactのコンテキストとプロパティの説明

目次1. 文脈1. 使用シナリオ2. 使用手順3. 結論2. 小道具の詳細1. 子供の財産2. 小道...

iostat を使用して Linux ハードディスクの IO パフォーマンスを表示する方法

TOP 観察: IO 待機に占められる CPU 時間の割合。30% を超えると、IO の負荷が高くな...

VSCode+CMake+Clang+GCC 環境構築チュートリアル (Win10 の場合)

大学院入試に備えて、C/C++ を使って基本的なデータ構造とアルゴリズムを実装する予定です。アルゴリ...

MySQLのインストールと設定方法のグラフィックチュートリアル(CentOS7)

1. システム環境[root@localhost ホーム]# cat /etc/redhat-re...

HTML で margin:0 auto を使用するとページ全体が中央に配置されない問題の解決方法

今日、jsp ページを書きました。<div style="margin:0 auto...