Google Container Engine(GKE)で実行されている現在のKubernetesクラスターは、Googleが管理しているDebian GNU/Linux 7.9(wheezy)を実行しているn1-standard-1
マシンタイプ(1つの仮想CPUと3.75 GBのメモリ)で構成されています。サービスの負荷とメモリ使用量が増加しているため、ノードをより大きなマシンタイプにアップグレードする必要があります。私たちのテストクラスターでこれを試している間、私たちは(私たちにとって)非常に奇妙に見える何かを経験しました。
GoogleノードにデプロイされたときにJVMアプリケーションによって消費されるメモリは、ノードで使用可能なコアの数に比例しているようです。 JVMの最大メモリ(Xmx)を128Mbに設定しても、1コアマシンで約250Mbを消費します(これは、JVMがGCやJVM自体などのために最大制限よりも多くのメモリを消費するため、理解できます)。 2コアマシン(n1-standard-2
)で700Mb、4コアマシン(n1-standard-4
)で約1.4Gb。唯一異なるのはマシンタイプであり、まったく同じDockerイメージと構成が使用されます。
たとえば、n1-standard-4
マシンタイプを使用してマシンにSSHで接続し、Sudo docker stats <container_name>
を実行すると、次のようになります。
CONTAINER CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O
k8s.name 3.84% 1.11 GB / 1.611 GB 68.91% 0 B / 0 B
sameDockerイメージを正確なsame(アプリケーション)構成でローカルに実行すると(mac osxおよびdocker-machine)が表示されます:
CONTAINER CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O
name 1.49% 236.6 MB / 1.044 GB 22.66% 25.86 kB / 14.84 kB 0 B / 0 B
これは、Xmx
設定により、私が期待するものとはるかに調和しています(レコードの場合、8コアと16Gbのメモリがあります)。 GKEインスタンスでtop -p <pid>
を実行すると、同じことが確認されます。これにより、1.1〜1.4GbのRES/RSSメモリ割り当てが得られます。
Dockerイメージは次のように定義されます。
FROM Java:8u91-jre
EXPOSE 8080
EXPOSE 8081
ENV Java_TOOL_OPTIONS -Dfile.encoding=UTF-8
# Add jar
ADD uberjar.jar /data/uberjar.jar
CMD Java -jar /data/uberjar.jar -Xmx128m -server
私も追加してみました:
ENV MALLOC_ARENA_MAX 4
this などのいくつかのスレッドで推奨されているのを見てきましたが、これまでのところ何の違いもないようです。また、別のJavaベースイメージに変更したり、Alpine Linuxを使用したりしてみましたが、これでも状況は変わらないようです。
ローカルのDockerバージョンは1.11.1で、Kubernetes/GKEのDockerバージョンは1.9.1です。 Kubernetesのバージョン(重要な場合)はv1.2.4です。
また興味深いのは、ポッド/コンテナの複数のインスタンスを同じマシン/ノードにデプロイすると、一部のインスタンスが割り当てるメモリがはるかに少なくなることです。たとえば、最初の3つは1.1〜1.4Gbのメモリを割り当てますが、後続の10個のコンテナはそれぞれ約250 Mbしか割り当てません。これは、すべてのインスタンスが割り当てるとほぼ予想される量です。問題は、マシンのメモリ制限に達した場合、最初の3つのインスタンス(1.1Gbメモリを割り当てているインスタンス)が割り当てられたメモリを解放していないように見えることです。マシンの圧力が高いときにメモリを解放する場合、これについては心配しませんが、マシンがロードされてもメモリ割り当てを保持するため、問題になります(このマシンで他のコンテナをスケジュールすることが禁止されているため、したがって、リソースが無駄になります)。
質問:
問題は、Dockerfile
で指定されたJVM設定にありました。次のようにJVMを開始しました。
CMD Java -jar /data/uberjar.jar -Xmx128m -server
しかし、切り替えたとき:
CMD Java -Xmx128m -server -jar /data/uberjar.jar
設定が考慮されました。なぜこれをローカルで見なかったのかはまだわかりませんが、なんとか解決できて良かったです。
指定する場合
_CMD Java -jar /data/uberjar.jar -Xmx128m -server
_
次に、JVM引数(_-Xmx128m -server
_)にする予定の値が、コマンドライン引数として.jarファイルのMainクラスに渡されます。これらは、public static void main(String... args)
メソッドの引数として使用できます。
これは、実行可能なjar
ファイルを指定するのではなく、名前でメインクラスを実行している場合にも当てはまることに注意してください。
それらをプログラムへの引数ではなくJVM引数として渡すには、_-jar
_引数の前にそれらを指定する必要があります。