AWS ElasticBeanstalk docker-thin-pool 已满并导致文件系统以只读方式重新挂载?

AWS ElasticBeanstalk docker-thin-pool 已满并导致文件系统以只读方式重新挂载?

我无法弄清楚 AWS 如何在 ElasticBeanstalk 上设置 Docker“精简池”以及它是如何被填满的。我的 Docker 精简池不知何故被填满,导致我的应用程序在尝试写入磁盘时崩溃。

这是从容器内部拍摄的:

>df -h
>     /dev/xvda1                  25G  1.4G   24G   6%

事实上,EBS 确实分配了 25GB 的磁盘;du -sh /返回的是 1.6 GB。

在 EC2 外部,它开始时没什么危害... (通过lvs)

LV          VG     Attr       LSize  Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
docker-pool docker twi-aot--- 11.86g             37.50  14.65

但是,文件系统很快就会重新以只读方式挂载。通过 dmesg:

[2077620.433382] Buffer I/O error on device dm-4, logical block 2501385
[2077620.437372] EXT4-fs warning (device dm-4): ext4_end_bio:329: I/O error -28 writing to inode 4988708 (offset 0 size 8388608 starting block 2501632)
[2077620.444394] EXT4-fs warning (device dm-4): ext4_end_bio:329: I/O error     [2077620.473581] EXT4-fs warning (device dm-4): ext4_end_bio:329: I/O error -28 writing to inode 4988708 (offset 8388608 size 5840896 starting block 2502912)

[2077623.814437] Aborting journal on device dm-4-8.
[2077649.052965] EXT4-fs error (device dm-4): ext4_journal_check_start:56: Detected aborted journal
[2077649.058116] EXT4-fs (dm-4): Remounting filesystem read-only

回到 EC2 实例域,Docker 报告了以下信息:(来自docker info

Pool Name: docker-docker--pool
Pool Blocksize: 524.3 kB
Base Device Size: 107.4 GB
Backing Filesystem: ext4
Data file:
Metadata file:
Data Space Used: 12.73 GB
Data Space Total: 12.73 GB
Data Space Available: 0 B
Metadata Space Used: 3.015 MB
Metadata Space Total: 16.78 MB
Metadata Space Available: 13.76 MB
Thin Pool Minimum Free Space: 1.273 GB

LVS 转储此信息:

  --- Logical volume ---
  LV Name                docker-pool
  VG Name                docker
  LV UUID                xxxxxxxxxxxxxxxxxxxxxxxxxxxx
  LV Write Access        read/write
  LV Creation host, time ip-10-0-0-65, 2017-03-25 22:37:38 +0000
  LV Pool metadata       docker-pool_tmeta
  LV Pool data           docker-pool_tdata
  LV Status              available
  # open                 2
  LV Size                11.86 GiB
  Allocated pool data    100.00%
  Allocated metadata     17.77%
  Current LE             3036
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:2

这个精简池是什么?为什么它会填满?我该如何阻止它填满?另外,如果我的 / 卷上的容器内有 20+ GB 的可用空间,为什么它会停止新的写入?据我所知,它与我的程序正在写入的文件无关。

谢谢你!

答案1

David Ellis 的建议.ebextensions对我有用。我无法对他的回答发表评论,但我想补充一点,您可以创建一个新的 EBS 卷,而不是使用快照。要安装 40GB EBS 卷,我使用了以下命令:

option_settings:
  - namespace: aws:autoscaling:launchconfiguration
    option_name: BlockDeviceMappings
    value: /dev/xvdcz=:40:true

也可以看看本文档,其中有一个将新的 100GB EBS 卷映射到 的示例/dev/sdh

true最后的 意思是“终止时删除” 。

我使用上述代码创建了一个包含文件的新.ebextensions目录,然后将该目录与我的压缩文件一起压缩。请注意,Dockerrun 文件必须位于 zip 的顶层,而不是子目录内。ebs.configDockerrun.aws.json

要查找 Elastic Beanstalk 安装卷的位置,请lsblk在失败的实例上使用。对我来说也是如此/dev/xvdcz,所以也许这是标准。

答案2

我们也遇到了同样的问题。根本原因似乎是 Docker 没有使用选项安装其存储引擎(devicemapperElastic Beanstalk 中默认采用精简配置)discard,这反过来会填满块直到它崩溃。

我无法找到一个明确的解决方案,但这里有一个解决方法(见此评论) 我可以在受影响的实例上使用:

docker ps -qa | xargs docker inspect --format='{{ .State.Pid }}' | xargs -IZ fstrim /proc/Z/root/

答案3

我按照 AWS 文档中提供的建议操作,现在一切都正常了。
但我必须结合两种解决方案:增加空间并添加 cronjob 以删除旧文件。
以下是我所做的。

首先,我将卷改为xvdcz使用 50GB 而不是 12GB。这就是我们在 上看到的存储空间docker system info。就我而言,它总是满的,因为我每天都会上传大量文件。

.ebextensions/blockdevice-xvdcz.config

option_settings:
  aws:autoscaling:launchconfiguration:
    BlockDeviceMappings: /dev/xvdcz=:50:true

我添加了一个 cronjob 来清理不再使用的已删除文件。这是必需的,因为出于某种原因 Docker 仍保留它们。对我来说,一天一次就足够了。如果你的上传量比我多,你可以配置 cronjob 以根据需要运行多少次。

.ebextensions/cronjob.config

files:
    "/etc/cron.d/mycron":
        mode: "000644"
        owner: root
        group: root
        content: |
            0 23 * * * root /usr/local/bin/remove_old_files.sh

     "/usr/local/bin/remove_old_files.sh":
        mode: "000755"
        owner: root
        group: root
        content: |
            #!/bin/bash
            docker ps -q | xargs docker inspect --format='{{ .State.Pid }}' | xargs -IZ sudo fstrim /proc/Z/root/
            exit 0

 commands:
    remove_old_cron:
        command: "rm -f /etc/cron.d/*.bak"

来源:https://docs.aws.amazon.com/pt_br/elasticbeanstalk/latest/dg/create_deploy_docker.container.console.html#docker-volumes

答案4

我为这个问题苦苦思索了一天多的时间,终于弄明白了。

AWS 正在使用devicemapper后端并创建一个 12GB SSD 卷,它安装并用于 docker 镜像。您必须通过 elasticbeanstalk 扩展概念覆盖它将安装的卷并通过 CLI 进行部署(遗憾的是,没有办法通过其 GUI 执行此操作)。

在文件所在的目录中Dockerrun.aws.json,创建一个名为的目录,然后在其中.ebextensions创建一个以 结尾的文件。我将我的文件命名为。然后将以下内容放入其中:.config01.correctebsvolume.config

option_settings: - namespace: aws:autoscaling:launchconfiguration option_name: BlockDeviceMappings value: /dev/xvdcz=snap-066cZZZZZZZZ:40:true:gp2

我直接 ssh 进入我的一个故障机器,发现它正在安装/dev/xvdcz。它可能对您来说可能有所不同。snap-066cZZZZZZZZ需要是有效的快照 ID。我创建了失败实例的 AMI 映像,并在过程中使用了它创建的快照。是40卷将有多少 GB,因此请替换您需要的内容。我不知道truegp2做什么,但它们来自 AMI 映像块设备数据,所以我保留了它们。

魔法namespace来自option_name这里在文档中。

相关内容