为什么docker在高内存使用率时崩溃?

问题描述:

我有一个docker容器,它运行用python Flask编写的REST服务。我在OSx上使用VirtualBox运行容器。为什么docker在高内存使用率时崩溃?

这是在OSX上的内存统计信息在容器启动时:

enter image description here

所以,我有3GB〜可用内存。所以,我跑我的容器2 GB

docker run -d -m 2g --name mycontainer -p 5000:5000 foobar 

的内存限制,现在我送〜100个REST请求到容器上运行,而在同一时间运行docker stats服务。

最终,码头容器崩溃。

在容器崩溃之前,我正在粘贴来自docker stats以下的数据。

崩溃1:当运行100个不同的请求(容器崩溃几乎瞬间

CONTAINER   CPU %    MEM USAGE/LIMIT  MEM %    NET I/O    BLOCK I/O 
27ee4ed4f98a  99.27%    256.9 MB/2.147 GB 11.96%    163.2 kB/7.958 kB 107.4 MB/0 B 
CONTAINER   CPU %    MEM USAGE/LIMIT MEM %    NET I/O    BLOCK I/O 
27ee4ed4f98a  99.77%    324 MB/2.147 GB 15.09%    163.2 kB/7.958 kB 107.4 MB/0 B 
CONTAINER   CPU %    MEM USAGE/LIMIT MEM %    NET I/O    BLOCK I/O 
CONTAINER   CPU %    MEM USAGE/LIMIT MEM %    NET I/O    BLOCK I/O 
CONTAINER   CPU %    MEM USAGE/LIMIT MEM %    NET I/O    BLOCK I/O 

崩溃2:大约30之后当运行1个请求100倍(容器崩溃)

CONTAINER   CPU %    MEM USAGE/LIMIT  MEM %    NET I/O    BLOCK I/O 
41fc484677fb  79.00%    891.5 MB/2.147 GB 41.52%    12.13 MB/429.8 kB 2.379 GB/61.85 MB 
CONTAINER   CPU %    MEM USAGE/LIMIT MEM %    NET I/O    BLOCK I/O 
41fc484677fb  85.83%    892 MB/2.147 GB 41.54%    12.13 MB/429.8 kB 3.071 GB/61.85 MB 
CONTAINER   CPU %    MEM USAGE/LIMIT MEM %    NET I/O    BLOCK I/O 
41fc484677fb  85.83%    892 MB/2.147 GB 41.54%    12.13 MB/429.8 kB 3.071 GB/61.85 MB 
CONTAINER   CPU %    MEM USAGE/LIMIT MEM %    NET I/O    BLOCK I/O 
41fc484677fb  86.01%    892 MB/2.147 GB 41.54%    12.13 MB/429.8 kB 3.81 GB/61.85 MB 
CONTAINER   CPU %    MEM USAGE/LIMIT MEM %    NET I/O    BLOCK I/O 
41fc484677fb  86.01%    892 MB/2.147 GB 41.54%    12.13 MB/429.8 kB 3.81 GB/61.85 MB 
CONTAINER   CPU %    MEM USAGE/LIMIT  MEM %    NET I/O    BLOCK I/O 
41fc484677fb  86.28%    892.2 MB/2.147 GB 41.55%    12.13 MB/429.8 kB 4.508 GB/61.85 MB 
CONTAINER   CPU %    MEM USAGE/LIMIT  MEM %    NET I/O    BLOCK I/O 
41fc484677fb  86.28%    892.2 MB/2.147 GB 41.55%    12.13 MB/429.8 kB 4.508 GB/61.85 MB 
CONTAINER   CPU %    MEM USAGE/LIMIT MEM %    NET I/O    BLOCK I/O 
CONTAINER   CPU %    MEM USAGE/LIMIT MEM %    NET I/O    BLOCK I/O 
CONTAINER   CPU %    MEM USAGE/LIMIT MEM %    NET I/O    BLOCK I/O 

docker ps -a在碰撞后显示以下内容

CONTAINER ID  IMAGE      COMMAND    CREATED    STATUS      PORTS    NAMES 
41fc484677fb  foobar "python service.py" 7 minutes ago  Exited (137) 2 minutes ago      mycontainer 

运行的dmesg显示了几个内存不足的错误:

➜ ~ docker exec -it mycontainer dmesg | grep "Out of memory" 
Out of memory: Kill process 2006 (python) score 872 or sacrifice child 
Out of memory: Kill process 2496 (python) score 873 or sacrifice child 
Out of memory: Kill process 2807 (python) score 879 or sacrifice child 
Out of memory: Kill process 3101 (python) score 875 or sacrifice child 
Out of memory: Kill process 5393 (python) score 868 or sacrifice child 
Out of memory: Kill process 5647 (python) score 868 or sacrifice child 
Out of memory: Kill process 5926 (python) score 877 or sacrifice child 
Out of memory: Kill process 6328 (python) score 873 or sacrifice child 
Out of memory: Kill process 7923 (python) score 872 or sacrifice child 
Out of memory: Kill process 10183 (python) score 873 or sacrifice child 

问题

  1. 我怎样才能避免这样的事故?

  2. 这只是在我的本地机器上,但最终我打算将此容器部署到生产中。我应该遵循什么方法来防止崩溃?我应该将这个容器的多个克隆放在Nginx负载均衡器后面吗?

  3. 在生产中,我计划在单个服务器上运行单个容器。如果我在服务器上运行单个容器,并且不在该服务器上运行其他任何内容,容器是否能够使用所有可用的计算资源?

+0

如果内核内存不足,Linux内核就有杀死进程的习惯。找出它的原因。 –

+0

如果您在单个服务器上运行单个容器,为什么使用contsiner? – dirn

欢迎资源:)

的容器上放置一个极限的精彩世界并没有让你留下的限制下,它只是告诉内核何时开始挤压你的时候杀您。你必须保持低于你的极限。在很多情况下,这意味着当你无法在预算范围内满足他们的需求时,观察你的内存占用情况,排队或放弃请求。 AKA减载。

不过,好处是当你需要更多的容器副本时,你现在有一个非常明确的信号。

+0

“在很多情况下,这意味着当你无法在预算范围内满足他们的需求时,观察你的内存占用和排队或者丢弃请求”我想这样的事情是在应用程序/代码级完成的?另外,是否有东西会监视内存占用情况,并在容器崩溃之前创建副本?我从生产角度考虑这个问题 – Anthony

+0

一些解决方案内部包括用于自我监控和卸载的库,拥有响应负载增长容器的控制系统,响应负载添加复制品的控制系统,以及“机会主义”内存借用等待控制系统。 –

+0

哎呀,按回车。简而言之,在OSS的土地上,并非所有这些东西都可以提供给你。 Kubernetes内置支持自动缩放副本以响应加载,但只能水平。 Kubernetes也有能力描述借用记忆的容器,但我认为这并不像我们想要的那样健壮。您确实需要比普通Docker更全面的东西来使这种情况变得易于管理,这就是Kubernetes存在的原因(仅作为示例)。 –