【问题标题】:How to do scala heap dump in Kubernetes in Azure如何在 Azure 的 Kubernetes 中进行 Scala 堆转储
【发布时间】:2019-02-08 12:51:59
【问题描述】:

我在 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 指出的那样,第一个问题是由于yaml 中的内存限制,pod 被OOM 杀死。在将内存更改为 2560Mi 或更高之后(我甚至在 yaml 中尝试过诸如 CPU: 1000m 和内存 5Gi 之类的荒谬值)我没有得到 OOM 被杀死的原因。但是,不会创建转储文件,并且在 lastState 终止下会出现不同类型的消息。原因是:错误。不幸的是,这不是很有帮助。如果有人知道如何缩小范围,请帮助。

更新 2: 我在代码中添加了一些 println,以便更好地了解正在发生的事情。被杀死的 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 created to big Array").

【问题讨论】:

  • pod 日志说明了什么?

标签: scala azure docker kubernetes azure-aks


【解决方案1】:

我认为问题在于 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 

【讨论】:

  • 是的!这就是问题所在。非常感谢!
【解决方案2】:

这是一个远景,但一种可能性是 Kubernetes 正在杀死 pod,因为它在构建转储时但在将其写入磁盘之前违反了 YAML 中设置的内存限制。

使用 kubectl get pod &lt;yourPodNameHere&gt; --output=yaml 获取 pod 信息并在 lastState 下查找 Reason: OOMKilled

https://kubernetes.io/docs/tasks/configure-pod-container/assign-memory-resource/

【讨论】:

  • 非常感谢您的回复。是的,lastState 中的原因是 OOMKilled。所以我将yaml中的内存限制提高到2560Mi。但是,没有创建转储文件,现在我在 lastState 中得到一个不同的错误,它相当神秘,exitCode:1 和原因:错误。你知道为什么会这样吗?我有一种感觉,这是因为我的 kubernetes 资源太低了,但我不确定。感谢您对此事发表任何评论。
  • 抱歉,不确定那一点:(
  • 没问题 ;-)。我想我将不得不更深入地研究 kubernetes 文档。干杯。
猜你喜欢
  • 2013-09-02
  • 2022-10-19
  • 2021-01-15
  • 2015-09-04
  • 2021-05-31
  • 2017-10-31
  • 1970-01-01
  • 2016-06-18
  • 1970-01-01
相关资源
最近更新 更多