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

推薦する

WangEditor リッチ テキスト コンポーネントを Angular でカプセル化する方法

リッチ テキスト コンポーネントは、Web プログラムで、特にブログやフォーラムなどの Web サイ...

Linuxサーバ侵入緊急対応記録(概要)

最近、お客様から支援の依頼を受けました。管理されている通信コンピュータ ルームから、サーバーの 1 ...

データベースミドルウェアMyCatの紹介

1. Mycatの適用シナリオMycat は幅広いシナリオに合わせて開発されており、新しいユーザーが...

Vue 折りたたみ表示の複数行テキスト コンポーネントの実装コード

折りたたみ表示の複数行テキストコンポーネント複数行のテキスト コンポーネントを折りたたんで表示し、展...

Dockerのインストール、イメージの作成、NodeJSプログラムの読み込みと実行の詳細なプロセス

システム環境: Windows 7 1. DockerをインストールするDocker公式サイトからd...

Zabbix パスワードをリセットする方法 (ワンステップ)

問題の説明長い間アカウントパスワードを入力して Zabbix にログインしていないため、管理者パスワ...

Centos6でgitlabを構築する方法

序文元のプロジェクトは、パブリックネットワークgitlabに配置されていました。セキュリティ上の理由...

Mysql5.7 以降での ONLY_FULL_GROUP_BY エラーの解決方法

最近、開発プロセス中に、プロジェクト開発環境に接続されている MySQL データベースは Aliba...

練習と面接のための Linux シェル スクリプトのヒント 9 つを共有する

予防1) 先頭にインタープリターを追加します: #!/bin/bash 2) 構文のインデントに 4...

Dockerコンテナ間のホスト間通信 - オーバーレイベースの実装方法

オーバーレイネットワーク分析組み込みのホスト間ネットワーク通信は、常に Docker の待望の機能で...

メタタグにおける http-equiv 属性の使用の概要

metaはhtml言語のhead領域にある補助タグです。おそらく、これらのコードは不要だと思うかもし...

MySQL アップグレードのベストプラクティス

MySQL 5.7 には、オンライン DDL、マルチソース レプリケーション、拡張された半同期、テー...

表のセル間の境界線/区切り線を非表示にする方法

上の境界線のみを表示する <table frame=above>下の境界線のみを表示する...

フォームから Vue ElementUI を使用してログイン効果を実装する例

目次1. ElementUIで基本的なスタイルを構築する2. [送信]ボタンをクリックして、アカウン...

EclipseのプロジェクトをTomcatに追加できない問題を解決する方法

1. プロジェクトを右クリックしてプロパティを選択します2. プロジェクトファセットをクリック3. ...