如何在 Azure 中的 Kubernetes 中执行 Scala 堆转储
How to do scala heap dump in Kubernetes in Azure
我在将堆自动转储到 Microsoft Azure AKS (Kubernetes) 中已挂载的持久卷时遇到问题。
所以情况是这样的:
- 运行带参数-Xmx200m的程序导致内存不足
异常
- 在 AKS 中构建、推送和部署 docker 图像之后
秒 pod 被杀死并重新启动
- 我在 hello.txt 中的已安装卷中收到消息,但没有转储文件
已创建
出现这种行为的原因可能是什么?
我的测试程序是这样的:
import java.io._
object Main {
def main(args: Array[String]): Unit = {
println("Before printing test info to file")
val pw = new PrintWriter(new File("/borsuk_data/hello.txt"))
pw.write("Hello, world")
pw.close
println("Before allocating to big Array for current memory settings")
val vectorOfDouble = Range(0, 50 * 1000 * 1000).map(x => 666.0).toArray
println("After creating to big Array")
}
}
我的entrypoint.sh:
#!/bin/sh
java -jar /root/scala-heap-dump.jar -Xmx200m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/scala-heap-dump.bin
我的 Dockerfile:
FROM openjdk:jdk-alpine
WORKDIR /root
ADD target/scala-2.12/scala-heap-dump.jar /root/scala-heap-dump.jar
ADD etc/entrypoint.sh /root/entrypoint.sh
ENTRYPOINT ["/bin/sh","/root/entrypoint.sh"]
我的部署 yaml:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: scala-heap-dump
spec:
replicas: 1
template:
metadata:
labels:
app: scala-heap-dump
spec:
containers:
- name: scala-heap-dump-container
image: PRIVATE_REPO_ADDRESS/scala-heap-dump:latest
imagePullPolicy: Always
resources:
requests:
cpu: 500m
memory: "1Gi"
limits:
cpu: 500m
memory: "1Gi"
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: dynamic-persistence-volume-claim
dnsPolicy: ClusterFirst
hostNetwork: false
imagePullSecrets:
- name: regsecret
更新:
正如 lawrencegripper 指出的那样,第一个问题是 pod 由于 yaml 中的内存限制而被 OOM 杀死。将内存更改为 2560Mi 或更高后(我什至在 yaml 中尝试了 CPU: 1000m 和内存 5Gi 这样荒谬的值)我没有得到 OOM 被杀死的原因。但是,不会创建转储文件,并且在终止的 lastState 下会出现不同类型的消息。原因是:错误。不幸的是,这不是很有帮助。如果有人知道如何缩小范围,请帮忙。
更新 2:
我在代码中添加了一些 println 以便更好地理解正在发生的事情。 killed pod 的日志是:
Before printing test info to file
Before allocating to big Array for current memory settings
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at scala.reflect.ManifestFactory$DoubleManifest.newArray(Manifest.scala:153)
at scala.reflect.ManifestFactory$DoubleManifest.newArray(Manifest.scala:151)
at scala.collection.TraversableOnce.toArray(TraversableOnce.scala:285)
at scala.collection.TraversableOnce.toArray$(TraversableOnce.scala:283)
at scala.collection.AbstractTraversable.toArray(Traversable.scala:104)
at Main$.main(Main.scala:12)
at Main.main(Main.scala)
所以你可以看到程序永远不会到达:println("After creating to big Array").
这是一个远景,但一种可能性是 Kubernetes 正在杀死 pod,因为它在构建转储时但在将其写入磁盘之前违反了 YAML
中设置的内存限制。
使用 kubectl get pod <yourPodNameHere> --output=yaml
获取 pod 信息并在 lastState
下查找 Reason: OOMKilled
https://kubernetes.io/docs/tasks/configure-pod-container/assign-memory-resource/
我认为问题出在 entrypoint.sh 命令上。
> java --help
Usage: java [options] <mainclass> [args...]
(to execute a class)
or java [options] -jar <jarfile> [args...]
(to execute a jar file)
请注意,-jar 之后的任何内容都是传递给您的应用程序的参数,而不是传递给 JVM 的参数。
尝试:
java -Xmx200m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/scala-heap-dump.bin -jar /root/scala-heap-dump.jar
我在将堆自动转储到 Microsoft Azure AKS (Kubernetes) 中已挂载的持久卷时遇到问题。
所以情况是这样的:
- 运行带参数-Xmx200m的程序导致内存不足 异常
- 在 AKS 中构建、推送和部署 docker 图像之后 秒 pod 被杀死并重新启动
- 我在 hello.txt 中的已安装卷中收到消息,但没有转储文件 已创建
出现这种行为的原因可能是什么?
我的测试程序是这样的:
import java.io._
object Main {
def main(args: Array[String]): Unit = {
println("Before printing test info to file")
val pw = new PrintWriter(new File("/borsuk_data/hello.txt"))
pw.write("Hello, world")
pw.close
println("Before allocating to big Array for current memory settings")
val vectorOfDouble = Range(0, 50 * 1000 * 1000).map(x => 666.0).toArray
println("After creating to big Array")
}
}
我的entrypoint.sh:
#!/bin/sh
java -jar /root/scala-heap-dump.jar -Xmx200m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/scala-heap-dump.bin
我的 Dockerfile:
FROM openjdk:jdk-alpine
WORKDIR /root
ADD target/scala-2.12/scala-heap-dump.jar /root/scala-heap-dump.jar
ADD etc/entrypoint.sh /root/entrypoint.sh
ENTRYPOINT ["/bin/sh","/root/entrypoint.sh"]
我的部署 yaml:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: scala-heap-dump
spec:
replicas: 1
template:
metadata:
labels:
app: scala-heap-dump
spec:
containers:
- name: scala-heap-dump-container
image: PRIVATE_REPO_ADDRESS/scala-heap-dump:latest
imagePullPolicy: Always
resources:
requests:
cpu: 500m
memory: "1Gi"
limits:
cpu: 500m
memory: "1Gi"
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: dynamic-persistence-volume-claim
dnsPolicy: ClusterFirst
hostNetwork: false
imagePullSecrets:
- name: regsecret
更新: 正如 lawrencegripper 指出的那样,第一个问题是 pod 由于 yaml 中的内存限制而被 OOM 杀死。将内存更改为 2560Mi 或更高后(我什至在 yaml 中尝试了 CPU: 1000m 和内存 5Gi 这样荒谬的值)我没有得到 OOM 被杀死的原因。但是,不会创建转储文件,并且在终止的 lastState 下会出现不同类型的消息。原因是:错误。不幸的是,这不是很有帮助。如果有人知道如何缩小范围,请帮忙。
更新 2: 我在代码中添加了一些 println 以便更好地理解正在发生的事情。 killed pod 的日志是:
Before printing test info to file
Before allocating to big Array for current memory settings
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at scala.reflect.ManifestFactory$DoubleManifest.newArray(Manifest.scala:153)
at scala.reflect.ManifestFactory$DoubleManifest.newArray(Manifest.scala:151)
at scala.collection.TraversableOnce.toArray(TraversableOnce.scala:285)
at scala.collection.TraversableOnce.toArray$(TraversableOnce.scala:283)
at scala.collection.AbstractTraversable.toArray(Traversable.scala:104)
at Main$.main(Main.scala:12)
at Main.main(Main.scala)
所以你可以看到程序永远不会到达:println("After creating to big Array").
这是一个远景,但一种可能性是 Kubernetes 正在杀死 pod,因为它在构建转储时但在将其写入磁盘之前违反了 YAML
中设置的内存限制。
使用 kubectl get pod <yourPodNameHere> --output=yaml
获取 pod 信息并在 lastState
下查找 Reason: OOMKilled
https://kubernetes.io/docs/tasks/configure-pod-container/assign-memory-resource/
我认为问题出在 entrypoint.sh 命令上。
> java --help
Usage: java [options] <mainclass> [args...]
(to execute a class)
or java [options] -jar <jarfile> [args...]
(to execute a jar file)
请注意,-jar 之后的任何内容都是传递给您的应用程序的参数,而不是传递给 JVM 的参数。
尝试:
java -Xmx200m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/scala-heap-dump.bin -jar /root/scala-heap-dump.jar