zoukankan      html  css  js  c++  java
  • docker 容器terminal失败

    关键一句话:docker 容器的teminal失败,一定是等待资源导致的,不管是pid资源,还是内存资源。本文主要讲因为内存资源导致进程D状态,然后导致teminal容器失败。

    目前在集群中,cpu占用率其实一直较低,也就是说,load高目前都是因为D状态的进程多,或者说D状态的进程时间比较久,这种情况下,如果该进程归属的容器需要terminal,则会失败。

    总结的规律是:

    1.有的集群,由于kmem的泄露,导致容器的runc有时候会在创建的时候出现申请内存失败而在内核态循环的情况,这种情况,只要增加对应容器的内存就能解决。然后升级runc不默认开启kmem的记账。

    2.普通的业务集群,没有开启kmem记账,那么当用户态占用内存较多达到limit时,会因为申请不到内存而在内核态循环,而触发了oom,

    常见的堆栈如下:

    [<ffffffffba3da5f5>] wait_iff_congested+0x135/0x150
    [<ffffffffba3cce5a>] shrink_inactive_list+0x30a/0x5d0
    [<ffffffffba3cd815>] shrink_lruvec+0x385/0x730
    [<ffffffffba3cdc36>] shrink_zone+0x76/0x1a0
    [<ffffffffba3ce140>] do_try_to_free_pages+0xf0/0x4e0
    [<ffffffffba3ce62c>] try_to_free_pages+0xfc/0x180
    [<ffffffffba47941e>] free_more_memory+0xae/0x100
    [<ffffffffba47a73b>] __getblk+0x15b/0x300---这个地方会有一个循环
    [<ffffffffc075bd43>] __ext4_get_inode_loc+0xe3/0x3c0 [ext4]
    [<ffffffffc075e49d>] ext4_get_inode_loc+0x1d/0x20 [ext4]
    [<ffffffffc0760256>] ext4_reserve_inode_write+0x26/0xa0 [ext4]
    [<ffffffffc0760323>] ext4_mark_inode_dirty+0x53/0x210 [ext4]
    [<ffffffffc0763b20>] ext4_dirty_inode+0x40/0x60 [ext4]
    [<ffffffffba4715ad>] __mark_inode_dirty+0x16d/0x270
    [<ffffffffba45f6a9>] update_time+0x89/0xd0
    [<ffffffffba45f790>] file_update_time+0xa0/0xf0
    [<ffffffffc0763d4c>] ext4_page_mkwrite+0x6c/0x470 [ext4]
    [<ffffffffba3e5a3a>] do_page_mkwrite+0x8a/0xe0
    [<ffffffffba3e60d6>] do_shared_fault.isra.62+0x86/0x280
    [<ffffffffba3ea664>] handle_pte_fault+0xe4/0xd10
    [<ffffffffba3ed3ad>] handle_mm_fault+0x39d/0x9b0
    [<ffffffffba971603>] __do_page_fault+0x203/0x4f0
    [<ffffffffba971925>] do_page_fault+0x35/0x90
    [<ffffffffba96d768>] page_fault+0x28/0x30
    [<ffffffffffffffff>] 0xffffffffffffffff

    这种就是典型的由于pagefault进来,然后因为申请内存不到而在内核态死循环的。此时pagefault的oom的执行需要

    mem_cgroup_oom_enable,同时,也要求mem_cgroup_oom_synchronize能够顺利执行才会最终杀进程,而很多时候循环在

    __getblk 的循环中,如果当前进程被选择为需要oom的进程,则必须退出循环才能处理。所以出现了软死锁,这个非常关键,我们要跳出循环才能执行oom杀进程,所以不是没有oom,

    而是oom在这种情况下没法执行。

    另外,不是所有的pagefault进来都是这个堆栈,比如是因为写时复制的原因进来,这个时候堆栈大多数情况下是如下:

    PID: 112272 TASK: ffff9ae9eaff8000 CPU: 21 COMMAND: "runc:[2:INIT]"
    #0 [ffff9adf48673608] __schedule at ffffffffb6769a72
    #1 [ffff9adf48673698] schedule at ffffffffb6769f19
    #2 [ffff9adf486736a8] schedule_timeout at ffffffffb6767968
    #3 [ffff9adf48673758] io_schedule_timeout at ffffffffb67695ed
    #4 [ffff9adf48673788] wait_iff_congested at ffffffffb61da5f5
    #5 [ffff9adf486737e8] shrink_inactive_list at ffffffffb61cce5a
    #6 [ffff9adf486738b0] shrink_lruvec at ffffffffb61cd815
    #7 [ffff9adf486739b0] shrink_zone at ffffffffb61cdc36
    #8 [ffff9adf48673a08] do_try_to_free_pages at ffffffffb61ce140
    #9 [ffff9adf48673a80] try_to_free_mem_cgroup_pages at ffffffffb61ce78a
    #10 [ffff9adf48673b18] mem_cgroup_reclaim at ffffffffb6234d1e
    #11 [ffff9adf48673b58] __mem_cgroup_try_charge at ffffffffb62356dc
    #12 [ffff9adf48673c10] mem_cgroup_charge_common at ffffffffb6236049
    #13 [ffff9adf48673c58] wp_page_copy at ffffffffb61e6b50
    #14 [ffff9adf48673cc8] do_wp_page at ffffffffb61e8f6b
    #15 [ffff9adf48673d70] handle_pte_fault at ffffffffb61ea8fd
    #16 [ffff9adf48673e08] handle_mm_fault at ffffffffb61ed3ad
    #17 [ffff9adf48673eb0] __do_page_fault at ffffffffb6771603
    #18 [ffff9adf48673f20] do_page_fault at ffffffffb6771925
    #19 [ffff9adf48673f50] page_fault at ffffffffb676d768

    这种情况下,runc会由于写时复制而出现没有内存的情况,返回值一般是:

    mem_cgroup_charge_common return=0xfffffffffffffff4,这个就是-12了,也就是没有内存。

    这种情况虽然不会出现死循环,但是由于用户态确实需要访问写时复制的page,这样会导致它长期地持有

    mmap_sem这把锁,一方面会导致load升高,其他等待这把锁的会处于D状态,另一方面,runc的阻塞,也会导致docker exec 卡住。

    3.还有一种load高,是因为内存翻转导致,比如提交的io飞了,一直在等待某个page释放等,这种概率虽然低,但是一旦遇到很难定位,我在oppo短短半年就遇到3次,都是mce

    检测不出来,但是堆栈明显是内存翻转,后来升级bios解决。

    4.很多ps进程阻塞,这个也是表象,ps阻塞还出现过读锁堵塞读,只要是因为防止写饥饿,因为虽然读者持有sem的读端,当写者来写时,排队会阻塞后端再来的读。

    既然说到load高,如果是cpu占用高,则需要分析cpu占用,如果是D状态,比如说之前一直出现的lxcfs导致的fuse的D状态,则一方面会导致load升高,另外一方面就会导致

    进程杀不掉,也就是container 在teminnal的时候会出现阻塞。前段时间一直报的重启lxcfs来规避,就是fuse阻塞较多,后来运维发现lxcfs复位也不能解决所有D状态,这个是很

    正常的,因为D状态的触发路径有很多,fuse只是占了其中一部分而已。

  • 相关阅读:
    在命令行下运行Matlab
    VMWare无法共享文件夹(Win7宿主机Ubuntu14.04客户机)
    [转] CVonline: Image Databases
    第二天
    第一天
    二宝软件的NABCD分析
    用c++实现环形数组的最大子数组之和
    返回一个二维整数数组中最大子数组的和
    求最大子数组之和
    四则运算
  • 原文地址:https://www.cnblogs.com/10087622blog/p/13581921.html
Copyright © 2011-2022 走看看