我在带有 Kubernetes 的 GCP 上的 docker 容器中运行了芹菜。它的工作人员最近开始变得kill -9
- 这看起来与OOMKiller有关。kubectl get events
中没有 OOM 事件,如果这些事件仅在 Pod 主动变更resources.limits.memory
值时才出现,这是可以预料的。
所以,我的理论是,芹菜过程被杀死是Linux自己的OOMKiller的工作。但这没有意义:如果消耗了如此多的内存,以至于 OOMKiller 进入了阶段,那么这个 pod 怎么可能首先被安排?(假设 Kubernetes 不允许调度新的 pod,如果resources.limits.memory
的总和超过系统可用的内存量(。
但是,除了OOMKiller之外,我不知道这些SIGKILL还有其他合理的理由。
芹菜错误的示例(每个工作人员都有一个(:
[2017-08-12 07:00:12,124: ERROR/MainProcess] Process 'ForkPoolWorker-7' pid:16 exited with 'signal 9 (SIGKILL)'
[2017-08-12 07:00:12,208: ERROR/MainProcess] Task handler raised error: WorkerLostError('Worker exited prematurely: signal 9 (SIGKILL).',)
容器可以出于两个原因进行 OOMKilled。
- 如果它们超出了为其设置的内存限制。限制是按容器指定的,如果容器使用的内存超过限制,则将进行 OOMKilled。从进程的角度来看,这与系统内存不足相同。
-
如果系统内存不足。Kubernetes 中有两种资源规范:请求和限制。限制指定容器在 OOMKilled 之前可以使用的最大内存量。请求用于调度 Pod,如果未指定,则默认为限制。请求必须小于或等于容器限制。这意味着,如果多个容器同时使用的内存多于其各自的请求,则容器可能会在节点和 OOMKilled 上过载。
例如,如果进程 A 和进程 B 都有 1GB 的请求和 2GB 的限制,则它们都可以在具有 2GB 内存的节点上调度,因为请求是用于调度的。请求小于限制通常意味着容器可以突增到 2GB,但通常使用小于 1GB。现在,如果两者同时突增超过 1GB,则系统可能会耗尽内存,并且一个容器将获得 OOMKilled,同时仍低于容器上设置的限制。
您可以通过检查 Pod 上的containerStatuses
字段来调试容器是否正在 OOMKilled。
$ kubectl get pod X -o json | jq '.status.containerStatuses'
如果 pod 是 OOMKilled,它通常会在lastState
字段中说出类似的话。在您的情况下,看起来它可能是基于针对芹菜提交的问题(如这个(的 OOM 错误。