I can't figure out how AWS sets up their Docker 'thin pool' on ElasticBeanstalk and how it is getting filled. My docker thin pool is filling up somehow and causing my apps to crash when they try to write to disk.
This is from inside the container:
>df -h
> /dev/xvda1 25G 1.4G 24G 6%
The EBS does, in fact, have a 25GB disk apportioned to it; 1.6 gb is what du -sh /
returns.
Outside in EC2, it starts off innocuously enough... (via 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
However, the filesystem will soon re-mount as read-only. via 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
Back out in EC2 instance-land, Docker reports this: (from 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 dumps this info:
--- 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
What is this thin pool, why does it fill up, and how do I stop it from doing so? Also, if I have 20+ GB free from inside the container on my / volume, why does it stop new writes? As far as I can tell it is not connected to files that my programs are writing to.
Thank you!
The
.ebextensions
suggested by David Ellis worked for me. I'm unable to comment on his answer, but I wanted to add that you can create a new EBS volume instead of using a snapshot. To mount a 40GB EBS volume, I used the following:See also this documentation, which has an example of mapping a new 100GB EBS volume to
/dev/sdh
.The
true
at the end means "delete on terminate".I created a new
.ebextensions
directory containing anebs.config
file with the above code, then zipped that directory together with myDockerrun.aws.json
. Note that the Dockerrun file must be at the top level of the zip, not inside a subdirectory.To find where Elastic Beanstalk is mounting the volume, use
lsblk
on the failing instance. It was also/dev/xvdcz
for me, so maybe that is the standard.We got hit by the same issue. The root cause seems to be Docker not mounting its storage engine (thin-provisioned
devicemapper
by default in Elastic Beanstalk) with thediscard
options, which in turn fills blocks until it breaks.I wasn't able to find a definite solution to this, but here is a workaround (see this comment) that I was able to use on affected instances :
I followed the suggestions provided on AWS documentation and everything is working now.
But I had to combine two solutions: increase space and add cronjob to remove old files.
Here's what I did.
First, I changed the volume
xvdcz
to use 50GB instead of 12GB. That's the storage that we can see ondocker system info
. In my case it was always full because I upload lots of files every day..ebextensions/blockdevice-xvdcz.config
After I added a cronjob to clean my deleted files that were not used anymore. It was required because Docker still kept them for some reason. In my case once a day it's enough. If you have more uploads than me, you can configure the cronjob to run how many times you need.
.ebextensions/cronjob.config
Source: https://docs.aws.amazon.com/pt_br/elasticbeanstalk/latest/dg/create_deploy_docker.container.console.html#docker-volumes
AWS elasticbeanstalk docker section Environment Configuration documents how it works:
I beat my head against this problem for over a day and finally figured it out.
AWS is using the
devicemapper
backend and creates a 12GB SSD volume that it mounts and uses for the docker images. You have to override the volume it would mount through the elasticbeanstalk extensions concept and deploy via the CLI (there is no way to do this via their GUI, unfortunately).In the directory you have your
Dockerrun.aws.json
file, create a directory called.ebextensions
and then create a file that ends in.config
inside of it. I called mine01.correctebsvolume.config
. Then put the following contents in there:option_settings: - namespace: aws:autoscaling:launchconfiguration option_name: BlockDeviceMappings value: /dev/xvdcz=snap-066cZZZZZZZZ:40:true:gp2
I ssh'ed into one of my failing boxed directly and found it was mounting
/dev/xvdcz
. It may be different for you. Thesnap-066cZZZZZZZZ
needs to be a valid snapshot ID. I created an AMI image of the failing instance and used the snapshot that it created in the process. The40
is how many GB the volume will be, so substitute in what you need. I don't know what thetrue
orgp2
do, but they came from the AMI image block device data, so I kept them.The magic
namespace
andoption_name
come from here in the documentation.Just increasing the size of the disk will not solve the problem, it will just error later. AWS Recommends mapping a new disk to your container so that any create file /delete file does not affect the Docker Poll Layer.
I am currently looking on it, I've not tested yet but the soluction I come across is having this on m y blockdevice.config
Appreciate any comments.