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タグを閉じるのを忘れないでください

推薦する

ウェブデザインスキル:中国語と英語が混在するウェブページの上位表示の問題

<br />私はこの問題で気が狂いそうです。症状は次のとおりです。 症状の説明: Int...

JavaScriptでよく使われる配列重複排除実戦ソースコード

アレイの重複排除は、通常、就職面接中に遭遇し、アレイの重複排除方法のコードを手動で記述することが求め...

ウェブページのドロップダウンリストとdivレイヤーのカバーの問題を選択する

HTML の select 要素に関する質問は、さまざまな場所で提起されています。最近のプロジェクト...

自動的にフォーカスを取得する要素入力ボックスの実装

最近のプロジェクトでフォームを作成するときに、コメント ボックスまで自動的にスクロールし、コメント ...

React 純粋関数コンポーネント setState がページ更新を更新しない問題の解決方法

目次問題の説明:原因分析:解決:補足: Reactでは、フックが使用されている場合、useState...

MySQL 5.0.96 for Windows x86 32 ビット グリーン簡易版インストール チュートリアル

MySQL 5.0 は、いくつかの「高度な機能」があるため定番となっています。これは、Windows...

Zabbix が MySQL のマスター/スレーブ状態を監視する方法の詳細な説明

MySQLマスタースレーブを設定した後、スレーブの状態が正常かどうかわからないことが多く、例外が発生...

Vueはechart円グラフの凡例のパーセンテージを表示するメソッドを実装します

この記事では主に、echart を使用してパーセンテージを表示する Vue の円グラフデータ部分を紹...

MySQLは、統計クエリを最適化するために、sum、case、whenを巧みに使用します。

私は最近、会社で統計レポートの開発に関わるプロジェクトに取り組んでいました。データの量が比較的多かっ...

WeChatミニプログラムはどのようにしてユーザー情報とユーザーの電話番号を同時に取得するのか

今日ログインページを書いていたとき、個人情報と携帯電話番号を認証する必要がありましたが、ページにボタ...

透明な入力ボックスにアイコンを追加する HTML コード

最近、弁護士推薦のウェブサイトを作成していたのですが、検索ボックスに問題がありました。検索ボックス内...

JSはカード配布アニメーションを実現します

この記事の例では、カード配布アニメーションを実装するためのJSの具体的なコードを参考までに共有してい...

Docker で複数のアプリケーション サイトをプロキシするために Nginx を使用する方法

序文エージェントの役割は何ですか? - 複数のドメイン名が同じサーバーに解決される- 1つのサーバー...

JavaScript における this ポイントの問題の詳細な説明

要約する地球環境 ➡️ ウィンドウ通常関数 ➡️ ウィンドウまたは未定義コンストラクター ➡️ 構築...

PHP で JSON バックスラッシュを削除する例

1. 「stripslashes($_POST['json']);」メソッドを使用し...