2017-01-26

Docker 1.10 with Devicemapper direct LVM vs. OverlayFS

During some load testing work we had a big problems with too big disk consumption when on Devicemapper direct LVM - our use-case of very many small (cpu/ram-vise) containers is not good for this storage driver. We have experimented and compared Docker 1.10 (docker-1.10.3-59.el7.x86_64) with Devicemapper direct LVM vs. OverlayFS (with XFS as a "hosting" FS) and there are some random numbers in this post. Docker also have page comparing different storage drivers. Red Hat documentation warns about OverlayFS stability, so we will see how it goes later in real load.

Configuring Docker for Devicemapper direct LVM

You need LVM volume group with free space for this.
systemctl stop docker
:>/etc/sysconfig/docker-storage
rm -rf /var/lib/docker/*
echo "VG='volume_group_with_free_space_for_docker'" >/etc/sysconfig/docker-storage-setup
docker-storage-setup
systemctl start docker

Configuring Docker for OverlayFS

Docker's documentation advises to use separate partition for OverlayFS as this storage driver consumes lots of inodes ("overlay2" should be better for that, but afaict this comes with Docker 1.12). We will see how it goes as we did not do any tunings when creating filesystem there. How to create XFS filesystem for OverlayFS and Changing Storage Configuration and "Overlay Graph Driver" below:
systemctl stop docker
sed -i '/OPTIONS=/s/--selinux-enabled//' /etc/sysconfig/docker
:>/etc/sysconfig/docker-storage
rm -rf /var/lib/docker/*
lvcreate --name docker --extents 100%FREE volume_group_with_free_space_for_docker
mkfs -t xfs -n ftype=1 /dev/volume_group_with_free_space_for_docker/docker
echo "/dev/volume_group_with_free_space_for_docker/docker /var/lib/docker xfs defaults 0 0" >>/etc/fstab
mount /var/lib/docker
echo "STORAGE_DRIVER='overlay'" >/etc/sysconfig/docker-storage-setup
docker-storage-setup
systemctl start docker

Comparing Devicemapper direct LVM vs. OverlayFS

This is the container we are using.

Starting containers

# time for i in $(seq 10); do docker run -h "con$i.example.com" -d r7perfsat; done
Devicemapper direct LVM: 38.832s
OverlayFS: 7.530s

Inspecting container sizes

# time docker inspect --size -f "SizeRw={{.SizeRw}} SizeRootFs={{.SizeRootFs}}" some_container
Devicemapper direct LVM: 18.254s
  SizeRw=2917 SizeRootFs=1633247414
OverlayFS: 2.694s
  SizeRw=2921 SizeRootFs=1633247406

Note: not sure if above is a relevant test case.

Stopping containers

# time docker stop 10_containers_we_have_created_before
Devicemapper direct LVM: 4.888s
OverlayFS: 3.266s

Removing stopped containers

# time docker rm 10_containers_we_have_created_before
Devicemapper direct LVM: 2.289s
OverlayFS: 0.206s

Registering containers

Running ansible playbook which registers via subscription-manager to Satellite 6 and installs Katello Agent and does few quick changes to the container on 5 of these containers in parallel:

Devicemapper direct LVM: 2m54.169s
OverlayFS: 2m45.890s

Note that during this load on the docker host seems much smaller on OverlayFS enable docker host, but that night be because of lots of other containers there are running on the host.

Downgrading few packages in containers

Running ansible playbook which downgrades few most small packages on 5 of these containers in parallel:

Devicemapper direct LVM: 1m34.035s
OverlayFS: 1m1.685s

At first glance, OverlayFS seems faster.

2017-01-06

Changing (growing) xfs partition size which is not on the LVM

XFS is a default file systems type in Red Hat Enterprise Linux 7. It is quite well known to me how to grow file system size when it is on LVM, but when it is not, I was very unsure. Anyway, this worked:

I want to increase root partition size and because the host is actually a virtual machine, it is easy to add more space. So in the VM we are using about 50 GB out of 161 GB available disk space. When using fdisk, guide advises to switch it to "sectors" mode. That seems to be default, but option is there just to be sure. Note the start sector (5222400 in my case) for the /dev/vda3 partition which hosts root file system:

[root@rhevm ~]# df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda3        48G   36G   13G  75% /
devtmpfs         11G     0   11G   0% /dev
tmpfs            11G     0   11G   0% /dev/shm
tmpfs            11G  8.4M   11G   1% /run
tmpfs            11G     0   11G   0% /sys/fs/cgroup
/dev/vda1       497M  208M  289M  42% /boot
tmpfs           2.1G     0  2.1G   0% /run/user/0
[root@rhevm ~]# fdisk -u=sectors -l /dev/vda 

Disk /dev/vda: 161.1 GB, 161061273600 bytes, 314572800 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x000e38b0

   Device Boot      Start         End      Blocks   Id  System
/dev/vda1   *        2048     1026047      512000   83  Linux
/dev/vda2         1026048     5222399     2098176   82  Linux swap / Solaris
/dev/vda3         5222400   104857599    49817600   83  Linux

If we try to extend XFS file system now, it wont work because it does not have space for the expansion (ignore the actual numbers, as I have taken them after the expansion shown below):

[root@rhevm ~]# xfs_info /
meta-data=/dev/vda3              isize=256    agcount=9, agsize=3113600 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=0        finobt=0 spinodes=0
data     =                       bsize=4096   blocks=26214400, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=0
log      =internal               bsize=4096   blocks=6081, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
[root@rhevm ~]# xfs_growfs -D 30000000 /
meta-data=/dev/vda3              isize=256    agcount=9, agsize=3113600 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=0        finobt=0 spinodes=0
data     =                       bsize=4096   blocks=26214400, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=0
log      =internal               bsize=4096   blocks=6081, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data size 30000000 too large, maximum is 26214400

So, lets delete the partition and create it again at required size (I want it 100 GB big):

[root@rhevm ~]# fdisk -u=sectors /dev/vda 
Welcome to fdisk (util-linux 2.23.2).

Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


Command (m for help): m   
Command action
   a   toggle a bootable flag
   b   edit bsd disklabel
   c   toggle the dos compatibility flag
   d   delete a partition
   g   create a new empty GPT partition table
   G   create an IRIX (SGI) partition table
   l   list known partition types
   m   print this menu
   n   add a new partition
   o   create a new empty DOS partition table
   p   print the partition table
   q   quit without saving changes
   s   create a new empty Sun disklabel
   t   change a partition's system id
   u   change display/entry units
   v   verify the partition table
   w   write table to disk and exit
   x   extra functionality (experts only)

Command (m for help): p

Disk /dev/vda: 161.1 GB, 161061273600 bytes, 314572800 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x000e38b0

   Device Boot      Start         End      Blocks   Id  System
/dev/vda1   *        2048     1026047      512000   83  Linux
/dev/vda2         1026048     5222399     2098176   82  Linux swap / Solaris
/dev/vda3         5222400   104857599    49817600   83  Linux

Command (m for help): d
Partition number (1-3, default 3): 3
Partition 3 is deleted

Command (m for help): n
Partition type:
   p   primary (2 primary, 0 extended, 2 free)
   e   extended
Select (default p): p
Partition number (3,4, default 3): 3
First sector (5222400-314572799, default 5222400): 5222400
Last sector, +sectors or +size{K,M,G} (5222400-314572799, default 314572799): +100G
Partition 3 of type Linux and of size 100 GiB is set

Command (m for help): p

Disk /dev/vda: 161.1 GB, 161061273600 bytes, 314572800 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x000e38b0

   Device Boot      Start         End      Blocks   Id  System
/dev/vda1   *        2048     1026047      512000   83  Linux
/dev/vda2         1026048     5222399     2098176   82  Linux swap / Solaris
/dev/vda3         5222400   214937599   104857600   83  Linux

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: Re-reading the partition table failed with error 16: Device or resource busy.
The kernel still uses the old table. The new table will be used at
the next reboot or after you run partprobe(8) or kpartx(8)
Syncing disks.
[root@rhevm ~]# partprobe 
Error: Partition(s) 3 on /dev/vda have been written, but we have been unable to inform the kernel of the change, probably because it/they are in use.  As a result, the old partition(s) will remain in use.  You should reboot now before making further changes.
[root@rhevm ~]# shutdown -r now

After reboot, we are finally ready to grow the file system:

[root@rhevm ~]# xfs_growfs /
meta-data=/dev/vda3              isize=256    agcount=4, agsize=3113600 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=0        finobt=0 spinodes=0
data     =                       bsize=4096   blocks=12454400, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=0
log      =internal               bsize=4096   blocks=6081, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
data blocks changed from 12454400 to 26214400
[root@rhevm ~]# df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda3       100G   36G   65G  36% /
devtmpfs         11G     0   11G   0% /dev
tmpfs            11G     0   11G   0% /dev/shm
tmpfs            11G  8.4M   11G   1% /run
tmpfs            11G     0   11G   0% /sys/fs/cgroup
/dev/vda1       497M  208M  289M  42% /boot
tmpfs           2.1G     0  2.1G   0% /run/user/0

2017-01-02

Remember that in Bash each command in pipeline is executed in a subshell

This took me some time to debug recently so wanted to share. Not new or so at all, but good to be reminded that from time to time :-)

$ function aaa() {
>   return 10 | true
> }
$ aaa
$ echo $?
0

Above can surprise a bit (why the heck I'm not getting exit code 10 when that return was executed?) especially when hidden in some bigger chunk of code, but with set -o pipefail I get what I wanted:

$ set -o pipefail
$ aaa
$ echo $?
10

2016-12-30

Creating "Solaris patch" for testing with Spacewalk

Spacewalk is Linux systems management solution. Until some time ago it had support for Solaris clients as well, but that was removed recently. This needs some testing right?

In Solaris, you have 3 ways to deliver software (AFAICT - I have absolutely 0 knowledge about administering Solaris):

  • package - check OpenCSW project for some of these and if you wanted to push these to Spacewalk, you had to throw them to solaris2mpm utility which creates *.mpm package from these *.pkg.gz files. These *.mpm were then push-able to Spacewalk using rhnpush. When pushed, this package will appear in "Packages" tab of your Solaris channel.
  • Solaris patch - this is AFAICT something created by SUN (or Oracle) only and only distributed by them via payed subscriptions, I have not found any guide on how to create one yourself. Again, you need to use solaris2mpm to transform the file to push-able *.mpm file.
  • Solaris patch cluster - same as for Solaris patch

This post is about very lame way on how to create solaris patch file which after push appears under "Patches" tab in older Spacewalk in Solaris channel. There is absolutely no intention to have this actually installable by Solaris client.

  1. First of all notice solaris2mpm is broken in Spacewalk so use version from Satellite I have not reported it, as the functionality was actually removed anyway.
  2. Notice that solaris2mpm is present in normal fedora rhnpush package as well, but see this old bug about its missing dependencies
  3. Install heirloom-pkgtools from Spacewalk's build system. Although this build (direct link to rpm) is very old, it worked on mine Fedora 25
  4. Build aaa-1.pkg:
    $ pwd
    /tmp/solaris_yay
    $ cat pkginfo
    PKG=aaa-1
    NAME=Just a demo solaris patch
    VERSION=0.0.1
    CATEGORY=application
    DESC=Some loooong description of this cool package or patch or whatever
    ARCH=i386
    VENDOR=http://where.you.got.it
    EMAIL=root@ocalhost
    $ rm -rf aaa* README.*; P=aaa-1; mkdir $P; date > $P/data; echo "Date: $( date +%Y-%m-%d )" > README.$P; echo "Relevant Architectures: i386" >> README.$P
    $ (echo 'i pkginfo'; pkgproto /tmp/solaris_yay/README.aaa-1=/README.aaa-1 /tmp/solaris_yay/aaa-1=/) >prototype
    $ pkgmk -o -d /tmp/; echo $?; pkgtrans -s /tmp /tmp/aaa-1.pkg aaa-1; echo $?
    
    I have made these ugly lines because I have been experimenting a lot with that and it allowed me to kinda automate parts of the process
  5. Now on RHEL6 Satellite (so solaris2mpm works - see first point here) with heirloom-pkgtools package installed (see third point) (so you do not need to do this on Solaris machine) run:
    # solaris2mpm aaa-1.pkg
    Writing patch-solaris-aaa-1-1.i386-solaris-patch.mpm
    
  6. Push resulting *.mpm to the Spacewalk's/Satellite's Solaris channel using rhnpush and enjoy looking at "Patches" tab of the channel filled with some content without SUN/Oracle subscription.

Some links I have used along the way:

2016-10-16

Creating RHEL4 chroot on RHEL6

I needed to run some Python script (from package rhn-applet) which was lastly distributed for RHEL4. I have started with just extracting content of rpm packages, but that ended with kinda dependency hell.

mkdir mycontent
cd myconten
wget .../rhn-applet-2.1.29-4.el4.x86_64.rpm
rpm2cpio rhn-applet-2.1.29-4.el4.x86_64.rpm | cpio -idmv

Creating the chroot is quite easy (assuming you have yum repo rhel4-chroot.repo of RHEL4 packages available so yum, although RHEL6 version, can install these RHEL4 packages):

AFFAIR="rhel4-chroot"
ROOT="$( pwd )/$AFFAIR/"
mkdir $ROOT
rpm --root $ROOT --initdb   # this creates $ROOT/var/lib/rpm database
yum --disablerepo '*' --enablerepo $AFFAIR --installroot=$ROOT -y install rhn-applet   # install desired package from our repository to chroot and into RPM database from previous step
echo $( hostname -i ) $( hostname ) > $ROOT/etc/hosts   # script I run later needs to be able to connect to localhost

Now my chroot was behaving as I needed. One problem I had is that I had rpm database created by RHEL6 version of rpm there. That is bad, because it is unreadable for rpm present in RHEL4 and currently installed in the chroot.

# chroot $ROOT rpm -qa
rpmdb: /var/lib/rpm/Packages: unsupported hash version: 9
error: cannot open Packages index using db3 - Invalid argument (22)
error: cannot open Packages database in /var/lib/rpm
no packages

To fix it, you can follow these steps. Because I did not needed rpm database to be correct, only needed redhat-release package in there, I just reinstalled it with empty rpm database:

rm -rf $ROOT/var/lib/rpm/*
chroot $ROOT rpm --initdb   # create empty RHEL4 rpm formatted database
wget -P $ROOT http://repos.example.com/released/RHEL-4/U9/Desktop/x86_64/repo-Desktop-x86_64/RPMS/redhat-release-4Desktop-10.x86_64.rpm
chroot $ROOT rpm -ivh redhat-release-*.rpm --nodeps --justdb

2016-10-06

Total newbie guide for MicroPython on ESP8266

OK, disclaimer first. I know completely nothing about microelectronics. With that in mind:

Mine goal is to create cheep battery powered thermometer which would be reporting temperature in fixed intervals using http via mine home router WiFi network. This was occupying mine mind from this article (in czech only, executive summary: ESP8266 is old, new and better ESP32 is on the way). Till reading that article I did not knew there is cheep SoC which can connect to WiFi and you can read from external sensors attached to it (i.e. thermometer). There is lots of guides for this exact thing.

Purchasing ESP8266 ESP-01 and USB programmer

On E-Bay I have bought 3 ESP8266 Serial WIFI Wireless Transceiver Module Send Receive LWIP AP+STA for $9.44 (I have no idea on what all these letters in the name mean, but you want ESP8266 version labelled as ESP-01). And because I'm scared of wiring anything myself, I have bought ESP01 Programmer Adapter UART GPIO0 ESP-01 Adaptateur ESP8266 USB nb (to connect ESP8266 to computer via serial port emulated via USB; you do not need to install any drivers on Fedora 24). It took less than 20 days to receive all the items.

Lets use Python

I like Python, so was very surprised that there is a way how to program in it on ESP8266: MicroPython - a lean and efficient Python implementation for microcontrollers and constrained systems - especially MicroPython port for the WiFi modules based on Espressif ESP8266 chip.

To be able to build MicroPython, we need to build esp-open-sdk first.

Building toolchain: esp-open-sdk

esp-open-sdk if SDK for software development with the Espressif ESP8266 chips and at the end, it had 3.8GB on the disk and it contains some non-open-source binary blobs and I do not understand majority of the README, so I have decided to work with that as different user on my Fedora 24 system:

# dnf install autoconf gcc gcc-c++ gperf bison flex texinfo patch libtool ncurses-devel expat-devel pyserial help2man
# useradd esp
# sudo -u esp -i
$ git clone https://github.com/pfalcon/esp-open-sdk.git
$ cd esp-open-sdk/
$ make

I have taken this partly from Starting IoT development in Fedora (ESP8266), from Building and Running MicroPython on the ESP8266 (they are building in virtual machine here) and from esp8266/README.md in MicroPython git linked above.

Building MicroPython ESP8266 port

Now here we build binary image we will later upload to the chip.

$ git clone https://github.com/micropython/micropython.git
$ cd micropython/
$ git submodule update --init
$ make -C mpy-cross
$ export PATH=/home/esp/esp-open-sdk/xtensa-lx106-elf/bin:$PATH
$ cd esp8266/
$ make axtls
$ make

Flashing (uploading) MicroPython image to ESP8266

First try to talk to original firmware

Plug ESP8266 board into the UART-to-USB converter firmly and put it into USB port. Now you will see bunch of messages in journal (tail it with # journalctl -f). We need device name (that differs based on which USB port you will use). Now you can connect to serial console:

<date> <hostname> kernel: usb 3-1: new full-speed USB device number 6 using xhci_hcd
<date> <hostname> kernel: usb 3-1: New USB device found, idVendor=1a86, idProduct=7523
<date> <hostname> kernel: usb 3-1: New USB device strings: Mfr=0, Product=2, SerialNumber=0
<date> <hostname> kernel: usb 3-1: Product: USB2.0-Serial
<date> <hostname> kernel: ch341 3-1:1.0: ch341-uart converter detected
<date> <hostname> kernel: usb 3-1: ch341-uart converter now attached to ttyUSB0
<date> <hostname> mtp-probe[10120]: checking bus 3, device 6: "/sys/devices/pci0000:00/0000:00:14.0/usb3/3-1"
<date> <hostname> mtp-probe[10120]: bus: 3, device: 6 was not an MTP device
<date> <hostname> systemd-udevd[10119]: Process '/usr/bin/setfacl -m g:lirc:rw ' failed with exit code 2.
$ screen /dev/ttyUSB0 115200

This will fail because your "esp" user does not have write permissions to /dev/ttyUSB0. What I did was I have added "esp" user to "dialout" group with # usermod -a -G dialout esp, logged out, in again and verified that I have the group with $ groups command. Once done, start screen again.

You can try some AT commands - e.g. to switch to "station" mode and then listing available "access points" (your home WiFi network should be amongst them) as noted in Getting Started with ESP8266 article. Note that you need to press "Ctrl+M" (i.e. carriage return, "Enter" worked for me as well) and "Ctrl+J" (i.e. linefeed) to submit each command.

AT+GMR
AT version:0.25.0.0(Jun  5 2015 16:27:16)
SDK version:1.1.1
Ai-Thinker Technology Co. Ltd.
Jun  5 2015 23:07:20

OK
AT+CWMODE=3

OK
AT+CWLAP
+CWLAP:(3,"Internet_80",-82,"5c:f4:ab:02:da:12",1)
+CWLAP:(3,"Stonehenge",-81,"48:5b:39:38:56:56",6)
+CWLAP:(3,"krakonos",-67,"10:c3:7b:d6:b8:34",10)

OK

Once done, to terminate screen, use "Ctrl+a \".

To get some detail on current serial port setup (mostly baud rate is important), use $ stty < /dev/ttyUSB0.

Upload new firmware

First you need to start into flashing mode - to do that you need to wire GPIO 0 to GND before pushing into USB port. If your USB-to-UART converter do not have any switch or so, you need to be creative. For me, one small wire squeezed between these two pins made the trick - see the photo :-)

No erase current flash content and upload yours (took me few tries to actually upload correct file, so make sure you are uploading build/firmware-combined.bin). It all takes below minute:

$ esptool.py -p /dev/ttyUSB0 -b 115200 erase_flash
$ esptool -p /dev/ttyUSB0 --baud 115200 write_flash --flash_size=8m --verify 0 build/firmware-combined.bin

So I have Python on that tiny chip now?

Remove whatever you have used to start in flashing mode and plug it in again to start in normal mode. Again, use screen to connect. Press "Enter" and say wow, familiar >>> is here!

>>> print("Hello world")
Hello world
>>> print(sys.version)
3.4.0
>>> print(sys.implementation)
(name='micropython', version=(1, 8, 4))
>>> print(sys.platform)
esp8266

Next step would be to learn how to access wifi in MicroPython.

2016-08-02

Recovering RHEL in emergency mode in AWS EC2

OK. I'm sure everybody knows that, but I did not. When you have AWS EC2 instance, say c3.8xlarge, you will get 2 x 320 GB SSD storage. Thats nice, isn't it? But, besides you have to manually attach that storage when launching the machine (4. Add Storage -> Add New Volume -> Volume Type: Instance Store 0 and repeat for Instance Store 1), it gets purged every time you stop and start your instance. I did not knew that so I have created LVM on these and added physical volume to the /etc/fstab to be auto mounted on next boot:

# pvcreate --yes /dev/xvdb
# pvcreate --yes /dev/xvdc
# vgcreate mygroup /dev/xvdb /dev/xvdc
# lvcreate --size 1GB --name myvol mygroup
# echo "/dev/mapper/mygroup-myvol /mnt/test xfs defaults 0 0" >>/etc/fstab

Now, here comes the problem: on instance stop and start, RHEL notices there is now no logical volume and skips into emergency mode? Now what? Let's recover using second machine. Executive summary:

  1. Take some working machine
  2. Detach root device volume from broken machine
  3. Attach it to working machine
  4. From the working machine mount, fix fstab and umount
  5. Detach
  6. Attach (do not ask me why, but as a Device, I had to use /dev/sda1 instead of /dev/sda)

Because mine broken and working machines were created from same RHEL 7.2 image, when I have attempted to mount I got this:

# mount /dev/xvdf2 /mnt/tmp/
mount: wrong fs type, bad option, bad superblock on /dev/xvdf2,
       missing codepage or helper program, or other error

       In some cases useful info is found in syslog - try
       dmesg | tail or so.
# dmesg | tail
[  265.755327] SELinux: initialized (dev tmpfs, type tmpfs), uses transition SIDs
[  288.106763] SELinux: initialized (dev tmpfs, type tmpfs), uses transition SIDs
[  568.495065] Adjusting xen more than 11% (9437184 vs 9311354)
[  583.752252] blkfront: xvdf: barrier or flush: disabled; persistent grants: disabled; indirect descriptors: enabled;
[  583.766118]  xvdf: xvdf1 xvdf2
[  662.933196] XFS (xvdf2): Filesystem has duplicate UUID 379de64d-ea11-4f5b-ae6a-0aa50ff7b24d - can't mount
[  752.706161] XFS (xvdf2): Filesystem has duplicate UUID 379de64d-ea11-4f5b-ae6a-0aa50ff7b24d - can't mount
[  842.806648] XFS (xvdf2): Filesystem has duplicate UUID 379de64d-ea11-4f5b-ae6a-0aa50ff7b24d - can't mount
[  879.618806] XFS (xvdf): Invalid superblock magic number
[  884.951716] XFS (xvdf2): Filesystem has duplicate UUID 379de64d-ea11-4f5b-ae6a-0aa50ff7b24d - can't mount

So I had to mount with -o nouuid option.