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

推薦する

Vue+swiperでタイムライン効果を実現

この記事では、タイムライン効果を実現するためのvue+swiperの具体的なコードを参考までに共有し...

CSS3 ボタン境界アニメーションの実装

まず効果を見てみましょう: html <a href="#"> &l...

MySQLでMyISAMストレージエンジンをInnodbに変更した操作記録のまとめ

一般的に、MySQL はデフォルトでさまざまなストレージ エンジンを提供しており、次のように表示され...

SQL重複排除方法の概要

SQL を使用してデータを抽出する場合、テーブル内で重複した値に遭遇することがよくあります。たとえ...

Linux システムで IPv6 をサポートするように Nginx を設定する方法

1. 既存のnginxがipv6をサポートしているかどうかを確認する既存の nginx が ipv6...

WeChatアプレットトラック再生の実装と遭遇した落とし穴の詳細な説明

WeChat アプレットの軌跡再生では、主に線描画操作にポリラインを使用し、車の移動操作にマーカーを...

CentOS で LibreOffice を使用してドキュメント形式を変換する方法

プロジェクト要件では、アップロードされたドキュメントの前処理が必要です。ユーザーが doc 形式でド...

フローティング要素が親要素の高さを崩す原因と解決策の詳細な説明

フローティング要素は、親要素の高さを縮小します。要素を float float:left/right...

Linux で Nginx 1.16.0 をインストールするための詳細なチュートリアル

最近 Linux をいじっていたので、nginx の新しいバージョンをインストールしたいと思いました...

JSはカリキュラムタイムテーブルアプレット(スーパーカリキュラムタイムテーブルを模倣)を実装し、カスタムバックグラウンド機能を追加します

概要:市販されているいくつかのタイムテーブルソフトウェアから教訓を得ました。機能が複雑すぎるため、タ...

CSS3 境界効果

CSSとは# CSS (Cascading Style Sheets の略) は、「カスケーディング...

Linux での umask の使用に関する詳細な説明

私は最近 Linux を学び始めました。Ma Ge の umask に関する Linux コースを読...

CSS3 のフィルタプロパティの使用に関する詳細な説明

最近、イントラネットポータルを修正していたときに、フィルターを使用する必要がある箇所に遭遇しました。...

メタビューポートはiPhoneでウェブページをフルスクリーン表示コントロールします

困り果てて、ふと、私がよく行くSinaのタッチスクリーン版はどうやって作られているのだろう?と考えま...

Linux コマンド sort、uniq、tr ツールの詳細な説明

並べ替えツールLinux の sort コマンドは、テキスト ファイルの内容を並べ替えるために使用さ...