AWS: EC2 – ошибка “cannot open access to console”, инстансы T2 vs R5 и Ansible

Автор: | 19/10/2018

Имеется EC2 типа t2.large, которому через CloudFormation был изменён тип на r5.xlarge.

К инстансу подключен дополнительный EBS-раздел, который монтируется в /data.

Ирония ситуации ещё и в том, что “упал” сервер мониторинга, который должен сообщать о падениях всех остальных серверов 🙂

Проблема

После смены типа – он запускается, но зависает на старте.

Проверяем скриншот – правой кнопокй на инстансе > Instance Settings > Get Instance Screenshot:

Первая мысль – что-то с именами разделов, и из-за неправильной записи в /etc/fstab – он не может загрузится.

Сначала попробовал вернуть на предыдущий тип – откатил на t2.large, но ошибка осталась:

Логи загрузки:


[ *] A start job is running for dev-xvdb1.device (1min 27s / 1min 30s)
[ **] A start job is running for dev-xvdb1.device (1min 28s / 1min 30s)
[ ***] A start job is running for dev-xvdb1.device (1min 28s / 1min 30s)
[ *** ] A start job is running for dev-xvdb1.device (1min 29s / 1min 30s)
[ *** ] A start job is running for dev-xvdb1.device (1min 29s / 1min 30s)
[*** ] A start job is running for dev-xvdb1.device (1min 30s / 1min 30s)
[ TIME ] Timed out waiting for device dev-xvdb1.device.
[DEPEND] Dependency failed for /data.
[DEPEND] Dependency failed for Local File Systems.
[ OK ] Started ifup for eth0.
Starting Raise network interfaces…
[ OK ] Reached target Cloud-init target.
[ OK ] Reached target Timers.
[ OK ] Closed Syslog Socket.
Starting Create Volatile Files and Directories…
[ OK ] Started Emergency Shell.
[ OK ] Reached target Emergency Mode.
[ OK ] Reached target Sockets.
[ OK ] Reached target Login Prompts.
[ OK ] Started Create Volatile Files and Directories.
Starting Update UTMP about System Boot/Shutdown…
[ OK ] Started Update UTMP about System Boot/Shutdown.
Starting Update UTMP about System Runlevel Changes…
[ OK ] Started Update UTMP about System Runlevel Changes.
[ OK ] Started Raise network interfaces.
Starting Initial cloud-init job (metadata service crawler)…
[ OK ] Reached target Network.
[ 93.409237] cloud-init[417]: Cloud-init v. 0.7.9 running ‘init’ at Thu, 18 Oct 2018 14:11:29 +0000. Up 93.07 seconds.
[ 93.415129] cloud-init[417]: ci-info: ++++++++++++++++++++++++++++++Net device info++++++++++++++++++++++++++++++
[ 93.420918] cloud-init[417]: ci-info: +——–+——+———–+—————–+——-+——————-+
[ 93.426619] cloud-init[417]: ci-info: | Device | Up | Address | Mask | Scope | Hw-Address |
[ 93.432399] cloud-init[417]: ci-info: +——–+——+———–+—————–+——-+——————-+
[ 93.438271] cloud-init[417]: ci-info: | eth0: | True | 10.0.1.6 | 255.255.255.240 | . | 02:f7:94:1d:ba:7c |
[ 93.444010] cloud-init[417]: ci-info: | eth0: | True | . | . | d | 02:f7:94:1d:ba:7c |
[ 93.449690] cloud-init[417]: ci-info: | lo: | True | 127.0.0.1 | 255.0.0.0 | . | . |
[ OK ] Started Initial cloud-init job (metadata service crawler).
[ 93.458109] cloud-init[ OK ] Reached target Cloud-config availability.
[ OK [0[417]: ci-info: | lo: | True | . | . | d | . |
[ 93.468374] You are in emergcloud-init[417]: ci-info: +——–+——+———–+—————–+——-+——————-+
[ 93.475306] cloud-init[417]: ci-info: ++++++++++++++++++++++++++++Route IPv4 info+++++++++++++++++++++++++++++
[ 93.480831] cloud-init[417]: ci-info: +——-+————-+———-+—————–+———–+——-+
[ 93.486518] cloud-init[417]: ci-info: | Route | Destination | Gateway | Genmask | Interface | Flags |

Cannot open access to console, the root account is locked.
See sulogin(8) man page for more details.

Press Enter to continue.
[ 93.492157] cloud-init[417]: ci-info: +——-+————-+———-+—————–+———–+——-+
[ 93.501947] cloud-init[417]: ci-info: | 0 | 0.0.0.0 | 10.0.1.1 | 0.0.0.0 | eth0 | UG |
[ 93.507266] cloud-init[417]: ci-info: | 1 | 10.0.1.0 | 0.0.0.0 | 255.255.255.240 | eth0 | U |
[ 93.512663] cloud-init[417]: ci-info: +——-+————-+———-+—————–+———–+——-+


Собственно из лога видно, что таки да – проблема с EBS.

Решение

ОК, будем дебажить /etc/fstab.

Но в emergency shell виртуальной машины из веб-морды AWS не попасть, значит – сделаем снапшот рутового раздела виртуалки, из снапшота – новый диск, а потом этот диск подключим к новой, временной, машине отдельным диском – и на ней будем смотреть содержимое файлов на старом root.

Останавливаем машину, и создаём снапшот его root-раздела:

Создаём volume из этого снапшота – Create Volume:

Запускаем новый инстанс в той же Availability Zone, где создан новый volume, в данном случае us-east-2а:

Проверяем на нём диски:

[simterm]

root@ip-172-31-14-188:/home/admin# lsblk 
NAME    MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
xvda    202:0    0   8G  0 disk 
└─xvda1 202:1    0   8G  0 part /

[/simterm]

Останавливаем этот новый инстанс, и подключаем к нему созданный volume:

Запускаем новый инстанс снова, проверяем диски:

[simterm]

root@ip-172-31-14-188:/home/admin# lsblk 
NAME    MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
xvda    202:0    0   8G  0 disk 
└─xvda1 202:1    0   8G  0 part /
xvdf    202:80   0   8G  0 disk 
└─xvdf1 202:81   0   8G  0 part

[/simterm]

/dev/xvdf1 – старый root-раздел со старого инстанса.

Монтируем его куда-то:

[simterm]

root@ip-172-31-14-188:/home/admin# mkdir /mnt/old-root
root@ip-172-31-14-188:/home/admin# mount /dev/xvdf1 /mnt/old-root/

[/simterm]

Проверяем содержимое:

[simterm]

root@ip-172-31-14-188:/home/admin# ls -l /mnt/old-root/
total 96
drwxr-xr-x  2 root root  4096 Aug 20 13:09 bin
drwxr-xr-x  3 root root  4096 Oct  9 03:39 boot
drwxr-xr-x  2 root root  4096 Jun 22 10:16 data
drwxr-xr-x  4 root root  4096 May  1 23:06 dev
drwxr-xr-x 84 root root  4096 Oct 18 14:35 etc
...
drwxr-xr-x 10 root root  4096 May  1 23:06 usr
drwxr-xr-x 12 root root  4096 Jun 22 10:20 var
lrwxrwxrwx  1 root root    26 Aug 20 13:09 vmlinuz -> boot/vmlinuz-4.9.0-8-amd64
lrwxrwxrwx  1 root root    26 May  1 23:09 vmlinuz.old -> boot/vmlinuz-4.9.0-6-amd64

[/simterm]

Хорошо – данные на месте, проверяем старый /etc/fstab:

[simterm]

root@ip-172-31-14-188:/mnt/old-root# cat etc/fstab
# /etc/fstab: static file system information.
#
# <file sys>    <mount point>   <type>  <options>       <dump>  <pass>

# device during installation: /dev/loop0p1
UUID=40a5b6b3-8dfe-422d-b0e4-844c9f336125       /       ext4    rw,discard,errors=remount-ro    0       1
/dev/xvdb1 /data ext4 defaults 0 0

[/simterm]

В fstab EBS подключается /dev/xvdb1, жаль – не посмотрел под какой буквой он подключался после обновления типа через CloudFormation (и после отката на T2 тип).

Возвращаемся к старому инстансу, отключаем диск – и подключаем его как xvdb:

Рестартуем старый инстанс – готово:

[simterm]

admin@monitonrig-production:~$ lsblk 
NAME    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
xvda    202:0    0    8G  0 disk 
└─xvda1 202:1    0    8G  0 part /
xvdb    202:16   0  200G  0 disk 
└─xvdb1 202:17   0  100G  0 part /data

[/simterm]

Причина и выводы

А причина – “банальна”.

Изначально /data монтировался и подключался через Ansible:

...
- name: Mount data-volume {{ data_volume_id }}1 to {{ data_volume_mount_path }}
  mount:
    path: "{{ data_volume_mount_path }}"
    src: "{{ data_volume_id }}1"
    state: mounted
    fstype: ext4
...

И в data_volume_id прописан xvdb:

[simterm]

$ cat hosts.ini | grep data_volume_id -A 2
data_volume_id="/dev/xvdb"
set_hostname="monitonrig-dev"

--
data_volume_id="/dev/xvdb"
set_hostname="monitonrig-production"

[/simterm]

И Ansible же обновлял /etc/fstab, в котором и прописал /dev/xvdb1 /data.

После смены типа инстанса – диск переименовался в nvme0n1p1 (см. Device Naming on Linux Instances) – вот как выглядят диски на R5 инстансах:

[simterm]

admin@ip-172-31-45-50:~$ lsblk 
NAME        MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme1n1     259:0    0   8G  0 disk 
nvme0n1     259:1    0   8G  0 disk 
└─nvme0n1p1 259:2    0   8G  0 part /

[/simterm]

Вывод – перед сменой типа инстанса – надо на нём вручную закомментировать /etc/fstab, отключить EBS, потом выполнить обновление типа инстанса, потом сменить имя раздела в переменной data_volume_id – и запустить Ansible, что бы он подключил диск и смонтировал его.

Или другой вариант – монтировать с опцией nofail в opts для модуля mount, после обновления типа инстанса – обновить переменную в Ansible, и запустить его, что бы он перегенерировал /etc/fstab.

Ссылки по теме

How To Repair An AWS EC2 Instance Without Console

How can I execute user data after the initial launch of my EC2 instance?

Troubleshooting Instances with Failed Status Checks