kubernetes等容器技术可以将所有的业务进程运行在公共的资源池中,提高资源利用率,节约成本,但是为避免不同进程之间相互干扰,对底层docker, kubernetes的隔离性就有了更高的要求,kubernetes作为一门新盛的技术,在这方面还不够成熟, 近期在一个staging集群就发生了,inode资源被耗尽的事件:

现象

在测试集群中,许多pod被Evicted掉

  1. [root@node01 ~]$ kubectl get pods
  2. NAME READY STATUS RESTARTS AGE
  3. default-http-backend-78d96f979f-5ljx4 1/1 Running 0 8d
  4. perfcounter-proxy-8b884c4ff-2ng4j 0/2 Evicted 0 1d
  5. perfcounter-proxy-8b884c4ff-5hq5k 0/2 Evicted 0 1d
  6. perfcounter-proxy-8b884c4ff-66qfw 0/2 Evicted 0 23h
  7. perfcounter-proxy-8b884c4ff-6hf7f 0/2 Evicted 0 23h
  8. perfcounter-proxy-8b884c4ff-6knrm 0/2 Evicted 0 1d
  9. perfcounter-proxy-8b884c4ff-6m9p5 0/2 Evicted 0 1d
  10. perfcounter-proxy-8b884c4ff-768g6 0/2 Evicted 0 1d
  11. perfcounter-proxy-8b884c4ff-7d74k 0/2 Evicted 0 20h
  12. perfcounter-proxy-8b884c4ff-998kx 0/2 Evicted 0 1d
  13. perfcounter-proxy-8b884c4ff-bmvjc 0/2 Evicted 0 1d
  14. perfcounter-proxy-8b884c4ff-cbh6m 0/2 Evicted 0 23h
  15. perfcounter-proxy-8b884c4ff-cd8jb 0/2 Evicted 0 1d
  16. perfcounter-proxy-8b884c4ff-d2m25 0/2 Evicted 0 1d
  17. perfcounter-proxy-8b884c4ff-dgtkk 0/2 Evicted 0 1d
  18. perfcounter-proxy-8b884c4ff-ftf2r 0/2 Evicted 0 20h
  19. perfcounter-proxy-8b884c4ff-hdz9x 0/2 Evicted 0 23h
  20. perfcounter-proxy-8b884c4ff-hgftx 0/2 Evicted 0 23h
  21. perfcounter-proxy-8b884c4ff-ks5sq 0/2 Evicted 0 1d
  22. perfcounter-proxy-8b884c4ff-kwf6x 0/2 Evicted 0 23h
  23. perfcounter-proxy-8b884c4ff-lnqct 2/2 Running 0 20h
  24. perfcounter-proxy-8b884c4ff-ngs9s 0/2 Evicted 0 2d

pod驱逐一般发生在某个node状态notready后,比如说磁盘写满,网络异常等,此时kuernetes就会将该异常node上面的pod进行驱逐,以免影响服务实例数,但是上面显示的如此频繁的驱逐是一定有问题的,机器状态不稳定,不断的flapping,执行kubectl describe node node04之后发现是由于node04机器上inode资源不足导致:

  1. Events:
  2. Type Reason Age From Message
  3. ---- ------ ---- ---- -------
  4. Warning EvictionThresholdMet 3d (x3 over 4d) kubelet, node04.kscn Attempting to reclaim nodefsInodes
  5. Normal NodeHasDiskPressure 3d (x3 over 4d) kubelet, node04.kscn Node node04.kscn status is now: NodeHasDiskPressure
  6. Normal NodeHasNoDiskPressure 3d (x3 over 4d) kubelet, node04.kscn Node node04.kscn status is now: NodeHasNoDiskPressure
  7. Warning EvictionThresholdMet 2d (x8 over 2d) kubelet, node04.kscn Attempting to reclaim nodefsInodes
  8. Normal NodeHasDiskPressure 2d (x2 over 2d) kubelet, node04.kscn Node node04.kscn status is now: NodeHasDiskPressure
  9. Normal NodeHasNoDiskPressure 2d (x2 over 2d) kubelet, node04.kscn Node node04.kscn status is now: NodeHasNoDiskPressure
  10. Warning EvictionThresholdMet 20h (x9 over 1d) kubelet, node04.kscn Attempting to reclaim nodefsInodes
  11. Normal NodeHasDiskPressure 20h (x6 over 1d) kubelet, node04.kscn Node node04.kscn status is now: NodeHasDiskPressure
  12. Normal NodeHasNoDiskPressure 20h (x6 over 1d) kubelet, node04.kscn Node node04.kscn status is now: NodeHasNoDiskPressure

登录到node04,查看后确实/home分区inode数据可用比较少

  1. [root@node04 gaorong]# df -i
  2. Filesystem Inodes IUsed IFree IUse% Mounted on
  3. /dev/vda1 1310720 150802 1159918 12% /
  4. devtmpfs 4116012 359 4115653 1% /dev
  5. tmpfs 4118414 61 4118353 1% /dev/shm
  6. tmpfs 4118414 2083 4116331 1% /run
  7. tmpfs 4118414 15 4118399 1% /sys/fs/cgroup
  8. /dev/vdb 819200 762459 56741 94% /home

解决

首先需要确定到底是那个服务导致inode耗尽的,确定inode占用较多的是那个目录, 根据目录可以确定是那个服务了,这里使用inodes这个工具来显示每个目录的占用inodes数目,发现/home/docker/aufs这个目录占用较多:

  1. [root@node04 gaorong]# inodes --d /home/docker/aufs/ -t 50000 -e 500
  2. ------------------------------------------
  3. [CONFIG] Directory to scan specified as /home/docker/aufs/
  4. ------------------------------------------
  5. [CONFIG] Tree directories above 50000 inodes
  6. ------------------------------------------
  7. [CONFIG] Exclude directories below 100 inodes
  8. ------------------------------------------
  9. INODE USAGE SUMMARY
  10. ------------------------------------------
  11. INODES | SIZE | DIRECTORY
  12. ------------------------------------------
  13. 493221 | 16G | diff
  14. --5417 | --130M | --016fe5bdd62c9264bcda0c44ef1548aaf8b82acfee2b0b8943e7394218118550
  15. --166 | --65M | --047d364456b37521445751910a4251faa6adcd50908f4d2f064ecbe80f20d332
  16. --10536 | --203M | --0a0b37e475c91a49cea4d732f83e6f87010edae86e25f4c7e14203e66c4122ea
  17. ... 此处省略若干行....
  18. --2050 | --64M | --f5fa7a7efabad90d1dfa4519f5c7fae611bdbfc9a9b43eb58b8c8bc035a15336
  19. --8714 | --304M | --f7618789addc900474c931ce9bbdc52abd5bf61ab98cd23d46e6189bd41094d1
  20. --241 | --174M | --faf7ea4dc438088688dded3164ce7a11018a7a5dc346d621b43965bc3b0e60cb
  21. --10921 | --325M | --fb08d1ed58bcdd3374ed835fcb27554ab52bcdd4822d502eb00066dec4d70650
  22. 386 | 1.6M | layers
  23. 179712 | 6.4G | mnt
  24. --7110 | --467M | --06feaf7d4336e97f3b11440865b97c0fadedd5488126215216be616c656e82f5
  25. --10764 | --337M | --26f394cad00c1876f832e2a4fb83816253dd8d70303a0d3b96a46edaf3564a05
  26. --18914 | --1.2G | --3912a58cf254540753d8accf69ed7a8c1c9d9539d73d35be9bd105dde94effe5
  27. --2965 | --168M | --401c0221bb62e36b3fcfb181420b64ec21147783860c72732299dba2f69f0280
  28. --3759 | --85M | --773333aef4b7f00f1f585b4c41fcbe20906c28b53999cfb78df268034d9b59e4
  29. --18692 | --626M | --79a76870faa7ed5f218b87e942d12523e5a9dd14cdb8449ccea5af279f45b526
  30. --26462 | --758M | --81d5c11dcc68df6ceee547fe84236c0234e4a63844e4ffc19047b6846185871b
  31. --2333 | --24M | --91bc77e078602f1e7285d2d742368a7a17ad0c0c3c736305fcbe68a11aa23e4c
  32. --10623 | --218M | --97a5ff749684b366c4a3ecff5536990e1db907577065deb7839e9da3c116ff93
  33. --18914 | --1.2G | --a4b945841c02a8a38463096f5cc1fd314563d94c78f8ccc92221b7f2571b2c3c
  34. --6749 | --157M | --aaa03c1ad6cd6fb332cce4c033eb74e2ae9f62364d5ea6e9d434aa88b6925644
  35. --17989 | --488M | --b6fb0a75102f0f25aa14a2f76b3013fab19c3f49b9ab49a2a8c230d52b84ff74
  36. --28536 | --674M | --d01bdbddb09cf36411c6179cb9657390eb4ed0f440f8aa05c94e38f7de49439c
  37. --5284 | --113M | --e3c555a3df172a2cd852cff210b43693bbc1cfa0b7cb5dbaee7645a4abdcfdb0
  38. ------------------------------------------
  39. 673320 | 22G | /home/docker/aufs/
  40. ------------------------------------------

/home/docker/aufs目录是docker采用aufs作为storage driver时用来存储镜像layer的目录,镜像中的每个文件都会在这里找到对应的文件。(docker默认的存储位置是/var/lib/docker,此环境因为项目需要改为/home/docker目录),aufs中小文件太多导致inode耗尽也是是比较常见的问题,如果使用deviceMapper等这种块设备的storage driver就不存在这个问题了。kubernetes会定期自动清理imagefs中的文件,删除没用的镜像和容器, 如果还是没有足够的资源的话才会驱逐pod。经过确认之后,该node上面的镜像都在使用中, kubernetes应该是尽力去清理镜像了, 清理完之后还是有inode pressure, 于是只能驱逐pod了, 驱逐之后node状态变为ready , 随后有新创建的pod会调度到该node上面,运行一段时间后inode资源又不足, 又进行驱逐回收... 如此循环往复,导致集群状态不稳定,有大量的pod被evict掉。因为Image资源我们没有办法继续清理,只能交给kubernetes去回收了。看看还有那些目录占用资源较多。

上面显示aufs占用的是673320,但df -i显示占用的inode数目是819200,说明还有其他地方导致占用比较多,约20w。仔细查找后发现另一个占用比较多的目录home/docker/volumes

  1. [root@node04 docker]# inodes --d /home/docker/volumes -t 50000 -e 500
  2. ------------------------------------------
  3. [CONFIG] Directory to scan specified as /home/docker/volumes
  4. ------------------------------------------
  5. [CONFIG] Tree directories above 50000 inodes
  6. ------------------------------------------
  7. [CONFIG] Exclude directories below 500 inodes
  8. ------------------------------------------
  9. INODE USAGE SUMMARY
  10. ------------------------------------------
  11. INODES | SIZE | DIRECTORY
  12. ------------------------------------------
  13. 10995 | 715M | 0afe5e70b2b22d1bee735977a8e931e2f2a65da5d79c08babf08a4de1a69877a
  14. 6576 | 378M | 0d0453ed64d4e830f408cf920a5ae13cefe1d4bfe3444464b9e612e699872a17
  15. 8497 | 414M | 1708cd1ce59818132e93bada3db8926a9eb03e08f553ad66f9df738424408704
  16. 6862 | 289M | 2940dea37d29501423d6eb50056034c89a9caf92cd2cd567ea3ffc02b54c813d
  17. 3224 | 102M | 2fe657a647b3c8b9b9a4d552cdeee682bd465edff14d90477a3277d79eeed807
  18. 9522 | 409M | 354c182b47707cc173de72ccf7ad99cabccc61d1f44e70a72d66a32334894d14
  19. 15204 | 533M | 4d49d25d55ab02f59fef56d984bfd811c3a2c8ec02378c0d7e860fac9df9d3ee
  20. 9546 | 407M | 4e1d2bb4ab8ca730df17b8a16910740dba8046cf8d9dc71625a017d67e16f95f
  21. 9205 | 408M | 51acc932cc72f620c9fded3cb93ea877467b78364731d35e58c08a72b2b247c2
  22. 9801 | 481M | 56a0e0a016c8c65cc27430dcd4053a18dec81bfd444da505148fe3fc30f4506c
  23. 17675 | 473M | 6ee2b44c4351790ef36bb7a1774fa2647b6d4c9ecc5dce1bcb33a9a522ea0808
  24. 9035 | 484M | 7928e4c94867ee49de041565e92a4c36517a6a7f904149dbd5b7df331b4f6a0e
  25. 7788 | 285M | 85c76690344f6b11ccaa95153df0b317b6ade6a6f6179e19ad3c40b9c2ba4d27
  26. 11193 | 856M | 8d51785afbeb6754e70286c73ee1fa5044b8eab02b606d692e64eea342303449
  27. 3054 | 79M | 9252da456a675c2c6519568b1bae3c7e410f1d5dc89e47f4e13bdd26964367e4
  28. 8604 | 377M | 962d4c2e6dd47f642aafe49557b660b9767b859c472ae0002c4f2ef4789bb350
  29. 5366 | 132M | 9bb9e9d8eff02f63eeea8dee9c351d6608b3e061d659a013ee5370b961961707
  30. 9171 | 480M | b8edb07ae19b7e5920b3aa254fb437670cc2f21f570cde693a778400a8e2784f
  31. 15088 | 592M | bd017c95ed823d8bbe7e4d7ee8bb40160c86b613fe9683c9a09a1e4dde3f017e
  32. 7813 | 285M | bf89566ba7852b07dc52fa5ef9d3a467dbcc5608532f6c2b0682feebed508401
  33. 14454 | 1.2G | c5a858a1ea25032f90d97b3765bebd32ffcecd5b911087451cd6d4fdaee1c92c
  34. 10427 | 467M | c9548dfca3e3de3dd1387c47a1a6771fe8aaf3908ab17a58287dad8511fa416c
  35. 4530 | 215M | cc4bde58318575c1c5fa8dde53e05d1f082b5a9944cecec23ac50989cebd963c
  36. 8036 | 381M | ced3dd5ecabdde6e313db4514290b30f735f8f18431ac6cb848d65d980e101b5
  37. 6439 | 374M | d0b3ca6b65cf9a686f0d521a813cb27d91e9dfd6078b80171e1dc16fdba6a922
  38. 15891 | 589M | e6292e24cc7d4a5ec43ed5ede58e9356b369e8e72f24327d297dd668fc20a640
  39. 11088 | 831M | ef175210467e4b58fb2215e35d679435699f8ce1f043a6225ff4fa1033c0e345
  40. ------------------------------------------
  41. 259083 | 15G | /home/docker/volumes
  42. ------------------------------------------

/home/docker/volumes目录是docker创建的,用于支持VOLUME 定义匿名卷,(默认路径是 /var/lib/docker/volumes , 此处是由于项目需要改变为 /home/docker/volumes目录)。我们平时启动容器的时候,挂载数据卷一般是执行docker run -ti -v /home/gaorong/:/home/gaorong nginx,这样就将容器里的"/home/gaorong"目录和宿主机上的"/home/gaorong"绑定在一起, 但是如果我们没有显式指定要挂载在宿主机的那个目录, 那docker 只能为其创建一个默认的目录了,比如执行docker run -ti -v /home/gaorong nginx, 他在容器中的目录"/home/gaorong",其实挂载的是宿主机上/var/libe/docker/volumes这个目录。

我们看看里面有些什么?

  1. [root@node04 volumes]# tree -L 3
  2. .
  3. ├── 0ad528934774355e22f4afa2df56a85cbe18bed0f922f37d054c1c0362baf648
  4.    └── _data
  5.    └── luhualin
  6. ├── 16d08b2bdb76ebeede9b6ee6da1378e44cf47ba825d6545f1a0ead8e21f9ffc0
  7.    └── _data
  8. ├── 1708cd1ce59818132e93bada3db8926a9eb03e08f553ad66f9df738424408704
  9.    └── _data
  10.    ├── global-bigdata-micsql
  11.    └── global-bigdata-micsql.tmp
  12. ├── 1a5c420084d42c370ac670d6e483cc2a960f4da71cf0fa0a765e1bf099a7c027
  13.    └── _data
  14.    ├── data
  15.    ├── meta
  16.    └── wal
  17. ├── 1fca6975f0af913c116aad7273a32f0a2795e62f3439ab779b39524c9434cf5d
  18.    └── _data
  19.    └── ContainerCloud
  20. ├── 3bb2d14dd39cca6d93296c742bbce8446c79a5c441b81c60d07a661a9a252b63
  21.    └── _data
  22. ├── 3c4845e864469457b3dac0a077e7f542db0dcfd9e20fbb112fde0e514d23a261
  23.    └── _data
  24. ├── 53ea91b9a833cb676d71cf336ffab97f20fe326bbd165427b64c9685e26a0f1f
  25.    └── _data
  26.    └── ContainerCloud
  27. ...此处省略若干行...
  28. ├── fc82dfd844191eb8baf1a68d3378e8fe0553d9cc705eb2fdfd3e5398a17783e2
  29.    └── _data
  30.    ├── k8s-node-frigga
  31.    └── k8s-node-frigga.tmp
  32. ├── fd3dec13f142dc59ad8dbbc2acf3841fd893f6d548ebe74aa2348af8f26fa448
  33.    └── _data
  34. └── metadata.db

可以看到其中有许多小文件,该集群中有些CICD 任务, 下载了许多源码文件,小而多的文件占用inode较多。 我们可以通过docker volume ls查看到目前没有被删除的匿名volume

  1. [root@node04 volumes]# docker volume ls
  2. DRIVER VOLUME NAME
  3. local 3a42fa60c84ebf1363c9b65c874a86e5663c883f2629edd0ac22575893f9a9ae
  4. local 2714f98661dfb0c6f94c99a0acf2c33f30d491667ce251e6499b069497095260
  5. ...此处省略若干行...
  6. local ac04c0925a0203cd87c55eaf1c6f094cf7e0b2cf3173c80d9de459f2aca1ccd4

接下来就需要定位是那个容器/pod创建的,为什么会创建匿名volume。 执行docker ps -a | grep -v NAME | awk '{print $1}' | xargs docker inspect | grep -B 100 3a42fa60c84ebf1363c9b65c874a86e5663c883f2629edd0ac22575893f9a9ae看一看是哪个容器创建的这些volume,找到其中一个容器 docker inpsect一下:

  1. [root@node04 global-bigdata]# docker inspect 25b3d4902305
  2. [
  3. {
  4. "Id": "25b3d4902305258371fbc71851dcb4aade62e393f567750f4776b7a3843e1ae4",
  5. "Created": "2019-02-27T06:58:27.091296766Z",
  6. "Path": "/docker-entrypoint.sh",
  7. "Args": [
  8. "zkServer.sh",
  9. "start-foreground"
  10. ],
  11. ...此处省略若干行...
  12. "GraphDriver": {
  13. "Data": null,
  14. "Name": "aufs"
  15. },
  16. "Mounts": [
  17. {
  18. "Type": "bind",
  19. "Source": "/home/kubelet/pods/1461d38d-3a5d-11e9-a499-fa163e08f614/volumes/kubernetes.io~secret/default-token-h7vj9",
  20. "Destination": "/var/run/secrets/kubernetes.io/serviceaccount",
  21. "Mode": "ro,rslave",
  22. "RW": false,
  23. "Propagation": "rslave"
  24. },
  25. {
  26. "Type": "bind",
  27. "Source": "/home/kubelet/pods/1461d38d-3a5d-11e9-a499-fa163e08f614/etc-hosts",
  28. "Destination": "/etc/hosts",
  29. "Mode": "",
  30. "RW": true,
  31. "Propagation": "rprivate"
  32. },
  33. {
  34. "Type": "bind",
  35. "Source": "/home/kubelet/pods/1461d38d-3a5d-11e9-a499-fa163e08f614/containers/zk/1d590aa4",
  36. "Destination": "/dev/termination-log",
  37. "Mode": "",
  38. "RW": true,
  39. "Propagation": "rprivate"
  40. },
  41. {
  42. "Type": "volume",
  43. "Name": "ac04c0925a0203cd87c55eaf1c6f094cf7e0b2cf3173c80d9de459f2aca1ccd4",
  44. "Source": "/home/docker/volumes/ac04c0925a0203cd87c55eaf1c6f094cf7e0b2cf3173c80d9de459f2aca1ccd4/_data",
  45. "Destination": "/data",
  46. "Driver": "local",
  47. "Mode": "",
  48. "RW": true,
  49. "Propagation": ""
  50. },
  51. {
  52. "Type": "volume",
  53. "Name": "3a42fa60c84ebf1363c9b65c874a86e5663c883f2629edd0ac22575893f9a9ae",
  54. "Source": "/home/docker/volumes/3a42fa60c84ebf1363c9b65c874a86e5663c883f2629edd0ac22575893f9a9ae/_data", <- 注意看这里
  55. "Destination": "/datalog",
  56. "Driver": "local",
  57. "Mode": "",
  58. "RW": true,
  59. "Propagation": ""
  60. },
  61. {
  62. "Type": "volume",
  63. "Name": "2714f98661dfb0c6f94c99a0acf2c33f30d491667ce251e6499b069497095260",
  64. "Source": "/home/docker/volumes/2714f98661dfb0c6f94c99a0acf2c33f30d491667ce251e6499b069497095260/_data",
  65. "Destination": "/logs",
  66. "Driver": "local",
  67. "Mode": "",
  68. "RW": true,
  69. "Propagation": ""
  70. }
  71. ],
  72. "Config": {
  73. "Hostname": "zk-7848b46c9d-6nqhz",
  74. "Domainname": "",
  75. "User": "0",
  76. "AttachStdin": false,
  77. "AttachStdout": false,
  78. "AttachStderr": false,
  79. "ExposedPorts": {
  80. "2181/tcp": {},
  81. "2888/tcp": {},
  82. "3888/tcp": {}
  83. },
  84. "Tty": false,
  85. "OpenStdin": false,
  86. "StdinOnce": false,
  87. "Cmd": [
  88. "zkServer.sh",
  89. "start-foreground"
  90. ],
  91. "Healthcheck": {
  92. "Test": [
  93. "NONE"
  94. ]
  95. },
  96. "ArgsEscaped": true,
  97. "Volumes": {
  98. "/data": {},
  99. "/datalog": {},
  100. "/logs": {}
  101. },
  102. "WorkingDir": "/zookeeper-3.4.13",
  103. "Entrypoint": [
  104. "/docker-entrypoint.sh"
  105. ],
  106. "OnBuild": null,
  107. "Labels": {
  108. "annotation.io.kubernetes.container.hash": "ee6d75c4",
  109. "annotation.io.kubernetes.container.ports": "[{\"containerPort\":2181,\"protocol\":\"TCP\"}]",
  110. "annotation.io.kubernetes.container.restartCount": "0",
  111. "annotation.io.kubernetes.container.terminationMessagePath": "/dev/termination-log",
  112. "annotation.io.kubernetes.container.terminationMessagePolicy": "File",
  113. "annotation.io.kubernetes.pod.terminationGracePeriod": "30",
  114. "io.kubernetes.container.logpath": "/var/log/pods/1461d38d-3a5d-11e9-a499-fa163e08f614/zk/0.log",
  115. "io.kubernetes.container.name": "zk",
  116. "io.kubernetes.docker.type": "container",
  117. "io.kubernetes.pod.name": "zk-7848b46c9d-6nqhz",
  118. "io.kubernetes.pod.namespace": "rpc",
  119. "io.kubernetes.pod.uid": "1461d38d-3a5d-11e9-a499-fa163e08f614",
  120. "io.kubernetes.sandbox.id": "a0fd95b0bb06a573e385f23dc21187c23b8232d59a252d0d8790770e946851a5"
  121. }
  122. },
  123. }
  124. ]

看到确实就是该容器mount这个目录, 其对应的image是zookper这个image, 我们看看其DockerFile是怎么写的:

  1. [root@node04 global-bigdata]# docker image history zookper
  2. IMAGE CREATED CREATED BY SIZE COMMENT
  3. 06b178591ab3 3 weeks ago /bin/sh -c #(nop) CMD ["zkServer.sh" "start… 0B
  4. <missing> 3 weeks ago /bin/sh -c #(nop) ENTRYPOINT ["/docker-entr… 0B
  5. <missing> 3 weeks ago /bin/sh -c #(nop) COPY file:e241c4b758b1c071… 1.13kB
  6. <missing> 3 weeks ago /bin/sh -c #(nop) ENV PATH=/usr/local/sbin:… 0B
  7. <missing> 3 weeks ago /bin/sh -c #(nop) EXPOSE 2181 2888 3888 0B
  8. <missing> 3 weeks ago /bin/sh -c #(nop) VOLUME [/data /datalog /l… 0B <- 注意看这里
  9. <missing> 3 weeks ago /bin/sh -c #(nop) WORKDIR /zookeeper-3.4.13 0B
  10. <missing> 3 weeks ago |2 DISTRO_NAME=zookeeper-3.4.13 GPG_KEY=C61B 61.1MB
  11. <missing> 3 weeks ago /bin/sh -c #(nop) ARG DISTRO_NAME=zookeeper… 0B
  12. <missing> 3 weeks ago /bin/sh -c #(nop) ARG GPG_KEY=C61B346552DC5… 0B
  13. <missing> 3 weeks ago /bin/sh -c set -ex; adduser -D "$ZOO_USE… 4.83kB
  14. <missing> 3 weeks ago /bin/sh -c #(nop) ENV ZOO_USER=zookeeper ZO… 0B
  15. <missing> 3 weeks ago /bin/sh -c apk add --no-cache bash s… 4.12MB
  16. <missing> 3 weeks ago /bin/sh -c set -x && apk add --no-cache o… 79.5MB
  17. <missing> 3 weeks ago /bin/sh -c #(nop) ENV JAVA_ALPINE_VERSION=8… 0B
  18. <missing> 3 weeks ago /bin/sh -c #(nop) ENV JAVA_VERSION=8u191 0B
  19. <missing> 3 weeks ago /bin/sh -c #(nop) ENV PATH=/usr/local/sbin:… 0B
  20. <missing> 3 weeks ago /bin/sh -c #(nop) ENV JAVA_HOME=/usr/lib/jv… 0B
  21. <missing> 3 weeks ago /bin/sh -c { echo '#!/bin/sh'; echo 'set… 87B
  22. <missing> 3 weeks ago /bin/sh -c #(nop) ENV LANG=C.UTF-8 0B
  23. <missing> 4 weeks ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B
  24. <missing> 4 weeks ago /bin/sh -c #(nop) ADD file:2a1fc9351afe35698… 5.53MB

原来是DockerFile中指定了VOLUME,但在启动改pod/容器的时候却没有mount到具体的某个目录,所以就会docker会创建一个匿名volume, 挂载到/home/docker/volume下,在其中写入大量小文件,进而占用该文件系统的inode。

查看官方的Dockfile文档里有这么一句话:

The host directory is declared at container run-time: The host directory (the mountpoint) is, by its nature, host-dependent. This is to preserve image portability, since a given host directory can’t be guaranteed to be available on all hosts. For this reason, you can’t mount a host directory from within the Dockerfile. The VOLUME instruction does not support specifying a host-dir parameter. You must specify the mountpoint when you create or run the container.

也就是说我们在启动该镜像的时候必须覆盖该Volume mountpoint,如果不覆盖的话就会在/home/docker/volumes目录下生成一个默认的mountPoint, 对应于kubernetes,也就是我们必须手动指定volume来挂载到该目录上, 可以是emptyDir, PV等whatever只要覆盖就不会写到该默认的路径下面了。

如果不进行覆盖该mount point, 使用默认配置,则该匿名volume的生命周期对应于pod的生命周期,pod删除就会自动删除该volume,/home/docker/volumes下对应的数据也会删除。如果想在pod退出后还保存这部分数据的就应该小心了。

言归正传,对于这种inode耗尽的问题要想从本质上解决问题还是得限制每个pod/容器可以占用的inode数目, 但是目前大多数的container storage driver不支持inode隔离的, 还是得使用诸如deviceMapper这类基于块设备的存储插件比较合适, 还有就是单独给一些特殊的pod/容器,IO比较特殊的任务单独挂载一块磁盘(当然此处磁盘也可以是虚拟化出来的), 避免相互影响。

2019.9 update:

社区issue: https://github.com/kubernetes/kubernetes/issues/52032

kubernetes continually evict pod when node's inode exhausted的更多相关文章

  1. Kubernetes — 深入解析Pod对象:基本概念(一)

    在上一篇文章中,我详细介绍了 Pod 这个 Kubernetes 项目中最重要的概念. 现在,你已经非常清楚:Pod,而不是容器,才是 Kubernetes 项目中的最小编排单位.将这个设计落实到 A ...

  2. Kubernetes — 深入解析Pod对象:基本概念(二)

    作为 Kubernetes 项目里最核心的编排对象,Pod 携带的信息非常丰富.其中,资源定义(比如 CPU.内存等),以及调度相关的字段.在本篇,我们就先从一种特殊的 Volume 开始,来帮助你更 ...

  3. [Kubernetes]深入解析Pod对象

    k8s集群搭建是比较容易的,但是我们为什么要搭建,里面涉及到的内容,我们为什么需要? 这篇文章就尝试来讲讲,我们为什么需要一个Pod,对Pod对象来一个深入解析. 我们为什么需要Pod 我们先来谈一个 ...

  4. kubernetes集群pod使用tc进行网络资源限额

    kubernetes集群pod使用tc进行网络资源限额 Docker容器可以实现CPU,内存,磁盘的IO限额,但是没有实现网络IO的限额.主要原因是在实际使用中,构建的网络环境是往超级复杂的大型网络. ...

  5. Kubernetes对象之Pod

    系列目录 Pod是Kubernetes调度的最小单元.一个Pod可以包含一个或多个容器,因此它可以被看作是内部容器的逻辑宿主机.Pod的设计理念是为了支持多个容器在一个Pod中共享网络和文件系统 因此 ...

  6. kubernetes调度之pod优先级和资源抢占

    系列目录 Pod可以拥有优先级.优先意味着相对于其它pod某个pod更为重要.如果重要的pod不能被调度,则kubernetes调度器会优先于(驱离)低优先级的pod来让处于pending状态的高优先 ...

  7. [Kubernetes]深入解析Pod

    Pod是Kubernetes项目的原子调度单位 为什么需要Pod? 容器是未来云计算系统中的进程,容器镜像就是这个系统里的".exe"安装包,那Kubernetes就是操作系统. ...

  8. 傲视Kubernetes(三):Kubernetes中的Pod

    从本文开始,将正式开始Kubernetes的核心内容学习.首先要了解的是Pod,总共大约分为六篇左右,本篇是第一篇,相信学完之后,我们会对Pod有一个整体的理解. 本文内容: 1.什么是Pod 2.P ...

  9. Kubernetes 实战 —— 03. pod: 运行于 Kubernetes 中的容器

    介绍 pod P53 pod 是 Kubernetes 中最为重要的核心概念,而其他对象仅仅用于 pod 管理. pod 暴露或被 pod 使用. pod 是一组并置的容器,代表了 Kubernete ...

随机推荐

  1. Google Summer of Code礼包

    这个暑假参加google summer of code, 给Google的分布式容器管理系统kubernates开发新的特性,希望从中学习更多的分布式的技术,锻炼自己的编程技巧. 中午在学校的图书馆吗 ...

  2. EasyUi 合并单元格占列显示

    $("#TableContainer").datagrid({                url: '',                method: "get&q ...

  3. ClsoSee(v2) Alpha测试中!这是一个临时的帮助页面...

    Clso See 测试中,最新的更新信息会显示在这里,欢迎您随时关注新版本动态. 您可以单击这里让程序打开本地帮助文件(新说明.txt) 等程序完成后,会制作专门的帮助页面. 因为采用了键盘Hook技 ...

  4. C# 图片反色处理 图片夜间模式

    项目属性-->生成-->允许不安全代码勾上. 代码: /// <summary> /// 反色处理 /// </summary> private Bitmap In ...

  5. c# 协变与抗变

    定义 协变:与原始类型转换方向相同的可变性称为协变. 抗变:与派生类型转换方向相同的可变性称为抗变. 补充: 参数是协变的,可以使用派生类对象传入需要基类参数的方法,反之不行 返回值是抗变的,不能使用 ...

  6. 机器学习、深度学习、和AI算法可以在网络安全中做什么?

    本文由  网易云发布. 本文作者:Alexander Polyakov,ERPScan的首席技术官和联合创始人.EAS-SEC总裁,SAP网络安全传播者. 现在已经出现了相当多的文章涉及机器学习及其保 ...

  7. 登录状态保持Session/Cookie

    登录成功: 1.Session保存User对象. 2.Cookie保存唯一值UserID(或者usercode)和加密Sign(生成规则自己定义,MD5用户名,用户ID,私有串等),并设置过期时间. ...

  8. scapy IPv6 NS NA报文构造

    NS 报文构造: #! /bin/python from scapy.all import * a=IPv6(src='2a01:4f8:161:5300::40', dst='ff02::1:ff0 ...

  9. 记一次生产发版时SpringBoot服务停用启用的问题

    近期项目交接,接手了个SpringBoot项目.生产环境里,jar包是通过软链接做成linux服务来启动和停用. 然而,每次通过jenkins构建发版,项目构建完毕,还要手动再去重启服务. 听交接的同 ...

  10. elasticsearch索引路径规则

    Path to data on disk In prior versions of Elasticsearch, the path.data directory included a folder f ...