即使未达到 Pod 限制,Pod 内的进程也被 OOMKilled

Tin*_*you 5 kubernetes google-kubernetes-engine

我们对整个 Kubernetes 世界有点陌生,但现在有许多服务在 GKE 中运行。然而,今天我们看到了一些奇怪的行为,其中一个运行在我们的一个 Pod 内的进程被杀死,即使 Pod 本身有足够的可用资源,并且没有接近其极限。

限制定义如下:

resources:
  requests:
    cpu: 100m
    memory: 500Mi
  limits:
    cpu: 1000m
    memory: 1500Mi
Run Code Online (Sandbox Code Playgroud)

在 pod 中,一个 Celery (Python) 正在运行,这个特殊的正在消耗一些相当长的运行任务。

在其中一项任务的运行过程中,celery 进程突然被杀死,似乎是 OOM 引起的。GKE 集群操作日志显示以下内容:

Memory cgroup out of memory: Kill process 613560 (celery) score 1959 or sacrifice child
Killed process 613560 (celery) total-vm:1764532kB, anon-rss:1481176kB, file-rss:13436kB, shmem-rss:0kB
Run Code Online (Sandbox Code Playgroud)

该时间段的资源图如下所示:

Pod 的 CPU 和内存使用率

可以清楚地看到,CPU 或内存使用量都没有接近 Pod 定义的限制,所以我们对为什么会发生 OOMKilling 感到困惑?进程本身被杀死而不是实际的 Pod 被杀死这一事实也有点困惑?

这种特殊的 OOM 是否真的发生在操作系统内部而不是在 Kubernetes 中?如果是这样 - 是否有解决此特定问题的解决方案?

Edu*_*llo 8

关于您的声明:

还有一点困惑的是,进程本身被杀死了,而不是实际的 Pod?

计算资源(CPU/内存)是为容器配置的,而不是为 Pod 配置的。

如果 Pod容器被 OOM 杀死Pod 不会被驱逐。底层容器根据kubeletRestartPolicy. Pod 仍将存在于同一节点上,并且Restart Count将会递增(除非您正在使用RestartPolicy: Never,这不是您的情况)。

如果您kubectl describe在 pod 上执行 a 操作,新生成的容器将处于Running状态,但您可以在 中找到上次重启原因Last State。此外,您还可以检查它重新启动了多少次:

State:          Running
  Started:      Wed, 27 Feb 2019 10:29:09 +0000
Last State:     Terminated
  Reason:       OOMKilled
  Exit Code:    137
  Started:      Wed, 27 Feb 2019 06:27:39 +0000
  Finished:     Wed, 27 Feb 2019 10:29:08 +0000
Restart Count:  5
Run Code Online (Sandbox Code Playgroud)

资源图可视化可能与内存的实际使用情况有所不同。由于它使用1 min interval (mean)采样,如果您的内存突然增加超过上限,则可以在平均内存使用量在图表上绘制为高峰之前重新启动容器。如果您的 Python 容器出现短暂/间歇性的高内存使用情况,即使这些值不在图表中,它也很容易重新启动。

kubectl top您可以查看为 Pod 注册的最后一次内存使用情况。尽管可以更准确地查看特定时间点的内存使用情况,但请记住,它从 中获取值metrics-server,其中包含--metric-resolution

从 Kubelet 中抓取指标的时间间隔(默认为 60 秒)。

如果您的容器对内存的使用“尖峰”,您可能仍然会看到它正在重新启动,甚至看不到 上的内存使用情况kubectl top