пятница, 30 марта 2012 г.

Удаленная замена корневой ФС в GNU/linux


image
Иногда мне приходится сталкиваться с заменой корневой файловой системы. Имея загрузочный диск и доступ к серверу, это не сложно. Однако, я хочу поделиться опытом замены корневой ФС удаленно, через ssh.

Причины для замены коневой ФС бывают разные:
  • перевод / в LVM
  • перевод / в mdraid
  • замена типа файловой системы (ext3 => btrfs)
  • уменьшение размера ФС (resize2fs)


Сразу оговорюсь, что не смотря на то, что у меня ни разу не было потери данных при этой операции,резеервное копирование никто не отменял!
Кроме того, я пишу эту статью для тех, кто уже знаком с LVM и понимает что ядро не сможет самостоятельно замонтировать / без помощи initramfs!

Описание буду проводить на примере gentoo GNU/linux.
Данный способ был проверен мной также и на debian GNU/linux.

Дано


Есть удаленный сервер, размещенный в датацентре.
В нашем случае это будет хост система, с запущенными виртуальными машинами KVM.

Жесткий диск /dev/sda, где находится корневая ФС, разбит на три msdos раздела:
  • sda1 200Мб /boot
  • sda2 2Гб /
  • sda3 197Гб LVM

Задачи


  1. Переместить корневую ФС с раздела /dev/sda2 в LVM в логический том «root» группы «sys» (/dev/mapper/sys-root)
  2. Увеличить размер корневой ФС с 2 Гб до 3Гб

Прежде чем начать


Нам понадобится утилита lsof.
Нужно понимать, что в процессе решения задачи нам потребуется перезапустить все процессы на сервере.

Решение


1. Содаем новый логический том в LVM
Том будет размером 3Гб и называться root
lvcreate -L 3g -n root sys
  Logical volume "root" created

2. Создаем папки для монтирования
mkdir /mnt/oldroot /mnt/newroot

3. Готовимся к перемонтированию старой корневой ФС / в режиме readonly
Это нужно для того, чтобы копировать старую корневую ФС в консистентном состоянии.
Но сама ФС, скорее всего, сейчас используется процессами для записи данных.

3.1. Проверяем удаленные файлы
lsof / | grep ' DEL \|delete'
dmeventd   3397   root  txt    REG  8,2    31816  71851 /sbin/dmeventd (deleted)
dmeventd   3397   root  DEL    REG  8,2           87761 /lib64/libdevmapper.so.1.02|paludis-midmerge
dmeventd   3397   root  DEL    REG  8,2           87769 /lib64/libdevmapper-event.so.1.02|paludis-midmerge
sshd       5601   root  txt    REG  8,2   482592  14452 /usr/sbin/sshd (deleted)

Если такие файлы нашлись, то процессы нужно перезапустить или остановить.
У меня такие файлы есть. Они возникли из-за того, что недавно были обновлены пакеты net-misc/openssh и sys-fs/lvm2

3.2. Перезапускаем и/или останавливаем процессы с удаленными файлами
В моем случае я перезапускаю sshd и завершаю dmeventd
/etc/init.d/sshd restart
 * Stopping sshd ...  [ ok ]
 * Starting sshd ...  [ ok ]

/etc/init.d/dmeventd stop
 * WARNING: you are stopping a boot service
 * Stopping dmeventd ...  [ ok ]

3.3. Убеждаемся, что нет больше удаленных файлов
lsof / | grep ' DEL \|delete'
Убедились.

3.4. Проверяем открытые на запись файлы

lsof / | grep -v ' \(mem\|txt\|rtd\|cwd\) '
COMMAND     PID   USER   FD   TYPE DEVICE SIZE/OFF  NODE NAME
cron      29035   root    3u   REG   8,2        6 11427 /var/run/cron.pid
snmpd     29530   root    3w   REG   8,2  1035580 84179 /var/log/net-snmpd.log
snmpd     29530   root    8r   REG   8,2     1316 28549 /etc/mtab
rsyslogd  29678   root    1w   REG   8,2   642199 11587 /var/log/messages
rsyslogd  29678   root    2w   REG   8,2    62061 12377 /var/log/cron
rsyslogd  29678   root    4w   REG   8,2     2155 12375 /var/log/secure
rsyslogd  29678   root    5w   REG   8,2      259 12376 /var/log/maillog

Смотрим на файлы, у которых режим открытия (колонка FD) содержит одну из букв: uUwW
В моем случае я не вижу проблем остановить все эти сервисы на время перемещения.
В вашем случае, решайте сами.

3.5. Останавливаем процессы, которые держат открытые файлы
/etc/init.d/rsyslog stop
 * Stopping rsyslogd ... [ ok ]

/etc/init.d/snmpd stop
 * Stopping snmpd ...  [ ok ]

/etc/init.d/vixie-cron stop
 * Stopping vixie-cron ... [ ok ]

3.6. Убеждаемся, что нет больше открытых на запись файлов
lsof / | grep -v ' \(mem\|txt\|rtd\|cwd\) '
COMMAND     PID   USER   FD   TYPE DEVICE SIZE/OFF  NODE NAME

3.7. Размонтируем все loop устройства
В моем случае я размонтирую squashfs файловую систему в /usr/portage
umount /usr/portage

3.8. Размонтируем ФС типа nfs, cifs, fuse и aufs
В моем случае таких нет.

3.9. Смотрим файловые (unix) сокеты
netstat --unix -a |grep '/\|Path$'
Proto RefCnt Flags       Type       State         I-Node   Path
unix  2      [ ACC ]     STREAM     LISTENING     3682265  /var/run/kvm/kvm204.sock
unix  2      [ ACC ]     STREAM     LISTENING     3279538  /var/run/kvm/kvm209.sock
unix  2      [ ACC ]     STREAM     LISTENING     3389038  /var/run/kvm/kvm207.monitor.sock
unix  2      [ ACC ]     STREAM     LISTENING     3603323  /var/run/kvm/kvm208.monitor.sock
unix  2      [ ACC ]     STREAM     LISTENING     3279539  /var/run/kvm/kvm209.monitor.sock
unix  2      [ ACC ]     STREAM     LISTENING     3607000  /var/run/kvm/kvm210.monitor.sock
unix  2      [ ACC ]     STREAM     LISTENING     3612458  /var/run/kvm/kvm211.monitor.sock
unix  2      [ ACC ]     STREAM     LISTENING     3682266  /var/run/kvm/kvm204.monitor.sock
unix  2      [ ACC ]     STREAM     LISTENING     3612457  /var/run/kvm/kvm211.sock
unix  2      [ ACC ]     STREAM     LISTENING     3279518  /var/run/kvm/kvm205.sock
unix  2      [ ACC ]     STREAM     LISTENING     3603322  /var/run/kvm/kvm208.sock
unix  2      [ ACC ]     SEQPACKET  LISTENING     3605138  @/org/kernel/udev/udevd
unix  2      [ ACC ]     STREAM     LISTENING     3608717  /var/run/kvm/kvm206.sock
unix  2      [ ACC ]     STREAM     LISTENING     3280746  /var/run/kvm/kvm205.monitor.sock
unix  2      [ ACC ]     STREAM     LISTENING     3608718  /var/run/kvm/kvm206.monitor.sock
unix  2      [ ACC ]     STREAM     LISTENING     3606999  /var/run/kvm/kvm210.sock
unix  2      [ ACC ]     STREAM     LISTENING     3389037  /var/run/kvm/kvm207.sock

При переносе корневой ФС эти сокеты перестанут быть связанными со своими приложениями.
Это решается:
— предварительной остановкой этих приложений (рекомендуется)
— перезапуском этих приложений после подмены корневой ФС
Меня не пугает потеря связи с приложениями через эти сокеты.

4. Перемонтируем корневую ФС / в режим readonly
mount -n -o remount,ro /
Если все успешно, то команда завершится тихо.
Если же появится строка «mount: / is busy», то корневая ФС все еще занята. Возвращайтесь к пункту 3 и проверяйте. Возможно вы что-то забыли. 

Не исключаю, что я тоже мог что-то не предусмотреть, но на данном этапе, если вам не удается этот шаг, то дальше двигаться нельзя. Вы еще ничего не успели изменить. Просто возвращайте в работу остановленные процессы.

Если же у вас все прошло успешно, то движемся дальше.

5. Резервное копирование (опционально)
Для себя я не вижу в этом необходимости, т.к. после всей операции в качестве резервной копии останется старый раздел sda2.

6. Копируем корневую ФС с устройства sda2 в LVM том root
dd if=/dev/root of=/dev/sys/root bs=8M
239+1 records in
239+1 records out
2006843392 bytes (2.0 GB) copied, 58.1021 s, 34.5 MB/s

7. Изменяем размер ФС

7.1. Первоначально проверяем ФС на ошибки
fsck -fC /dev/sys/root
fsck from util-linux 2.20.1
e2fsck 1.42 (29-Nov-2011)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/mapper/sys-root: 46848/122640 files (2.0% non-contiguous), 216129/489952 blocks

7.2. Производим изменение размера ФС
В нашем случае, мы увеличиваем ФС до размеров LVM тома.
resize2fs -p /dev/sys/root
resize2fs 1.42 (29-Nov-2011)
Resizing the filesystem on /dev/sys/root to 786432 (4k) blocks.
Begin pass 1 (max = 9)
Extending the inode table     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
The filesystem on /dev/sys/root is now 786432 blocks long.

8. Монтируем копию
mount -n /dev/sys/root /mnt/newroot

9. Сама подмена корневой ФС
Это то, ради чего мы все это затеяли.
С этого момента наступает опасное время.
Важно: После подмены корневой ФС, если произойдет обрыв SSH сессии, то система не сможет установить новое соединение!
Подменяем ФС:
cd /mnt/newroot
pivot_root. mnt/oldroot
Важно выполнить именно эти две команды в том виде, в котором они написаны, чтобы избежать блокировок.
После этой команды, том /dev/sys/root встанет на место /, а раздел sda2 сместит точку монтирования в /mnt/oldroot. При этом все другие замонтированные ФС тоже сместят точку монтирования. Например, файловая система /dev переместится в /mnt/oldroot/dev.

10. Возврат точек монтирования всех ФС (кроме старой корневой ФС)
Переносим стандартные ФС, которые есть у большинства:
mount -n --move /mnt/oldroot/proc /proc
mount -n --move /mnt/oldroot/dev /dev
mount -n --move /mnt/oldroot/sys /sys

Теперь можно смотреть в /proc/mounts, что еще нужно вернуть на место
cat /proc/mounts |grep oldroot
rc-svcdir /mnt/oldroot/lib64/rc/init.d tmpfs rw,nosuid,nodev,noexec,relatime,size=1024k,mode=755 0 0
/dev/root /mnt/oldroot ext3 ro,noatime,errors=continue,barrier=1,data=writeback 0 0
/dev/mapper/sys-distfiles /mnt/oldroot/var/distfiles ext2 rw,noatime,errors=continue 0 0
/dev/mapper/sys-vardb /mnt/oldroot/var/db reiserfs rw,noatime 0 0

В моем примере, я переношу
mount -n --move /mnt/oldroot/lib64/rc/init.d /lib64/rc/init.d
mount -n --move /mnt/oldroot/var/distfiles /var/distfiles
mount -n --move /mnt/oldroot/var/db /var/db

С этого момента вы вне опасности. Новые SSH сессии должны успешно открываться.

11. Перезапуск приложений с новой ФС

11.1. Смотрим, файлы процессов
lsof /mnt/oldroot
...
agetty    28783   root mem    REG   8,2    52884 99214 /mnt/oldroot/lib64/libnss_nis-2.13.so
agetty    28783   root mem    REG   8,2   109446 98354 /mnt/oldroot/lib64/libnsl-2.13.so
agetty    28783   root mem    REG   8,2    38724 99216 /mnt/oldroot/lib64/libnss_compat-2.13.so
agetty    28783   root mem    REG   8,2  1898114 99218 /mnt/oldroot/lib64/libc-2.13.so
agetty    28783   root mem    REG   8,2   156052 99219 /mnt/oldroot/lib64/ld-2.13.so
udevd     29118   root txt    REG   8,2   130216 49072 /mnt/oldroot/sbin/udevd
udevd     29118   root mem    REG   8,2    62227 99210 /mnt/oldroot/lib64/libnss_files-2.13.so
udevd     29118   root mem    REG   8,2    52884 99214 /mnt/oldroot/lib64/libnss_nis-2.13.so
udevd     29118   root mem    REG   8,2   109446 98354 /mnt/oldroot/lib64/libnsl-2.13.so
udevd     29118   root mem    REG   8,2    38724 99216 /mnt/oldroot/lib64/libnss_compat-2.13.so
udevd     29118   root mem    REG   8,2   135986 99220 /mnt/oldroot/lib64/libpthread-2.13.so
udevd     29118   root mem    REG   8,2  1898114 99218 /mnt/oldroot/lib64/libc-2.13.so
udevd     29118   root mem    REG   8,2    48545 99211 /mnt/oldroot/lib64/librt-2.13.so
udevd     29118   root mem    REG   8,2   156052 99219 /mnt/oldroot/lib64/ld-2.13.so
sshd      29455   root txt    REG   8,2   482592 74222 /mnt/oldroot/usr/sbin/sshd
sshd      29455   root mem    REG   8,2    62227 99210 /mnt/oldroot/lib64/libnss_files-2.13.so
sshd      29455   root mem    REG   8,2    52884 99214 /mnt/oldroot/lib64/libnss_nis-2.13.so
sshd      29455   root mem    REG   8,2    38724 99216 /mnt/oldroot/lib64/libnss_compat-2.13.so
sshd      29455   root mem    REG   8,2   440512 75579 /mnt/oldroot/usr/lib64/libgmp.so.10.0.2
sshd      29455   root mem    REG   8,2  1898114 99218 /mnt/oldroot/lib64/libc-2.13.so
sshd      29455   root mem    REG   8,2   135986 99220 /mnt/oldroot/lib64/libpthread-2.13.so
sshd      29455   root mem    REG   8,2    98598 99206 /mnt/oldroot/lib64/libresolv-2.13.so
sshd      29455   root mem    REG   8,2    40981 99205 /mnt/oldroot/lib64/libcrypt-2.13.so
sshd      29455   root mem    REG   8,2   109446 98354 /mnt/oldroot/lib64/libnsl-2.13.so
sshd      29455   root mem    REG   8,2    92624 98190 /mnt/oldroot/lib64/libz.so.1.2.5
sshd      29455   root mem    REG   8,2    14367 99217 /mnt/oldroot/lib64/libutil-2.13.so
sshd      29455   root mem    REG   8,2    19321 99203 /mnt/oldroot/lib64/libdl-2.13.so
sshd      29455   root mem    REG   8,2  1699456 74274 /mnt/oldroot/usr/lib64/libcrypto.so.1.0.0
sshd      29455   root mem    REG   8,2   373376 76226 /mnt/oldroot/usr/lib64/libssl.so.1.0.0
sshd      29455   root mem    REG   8,2    51760 98532 /mnt/oldroot/lib64/libpam.so.0.83.1
sshd      29455   root mem    REG   8,2   156052 99219 /mnt/oldroot/lib64/ld-2.13.so
smartd    29484   root txt    REG   8,2   374520 75866 /mnt/oldroot/usr/sbin/smartd
smartd    29484   root mem    REG   8,2  1898114 99218 /mnt/oldroot/lib64/libc-2.13.so
smartd    29484   root mem    REG   8,2   533499 82722 /mnt/oldroot/usr/lib64/gcc/x86_64-pc-linux-gnu/4.5.3/libgcc_s.so.1
smartd    29484   root mem    REG   8,2   614022 99202 /mnt/oldroot/lib64/libm-2.13.so
...

Видим, что все процессы запущены со старой корневой ФС.

11.2. Начинаем перезапускать системные процессы
Я рекомендую в первую очередь:
/etc/init.d/udev restart
/etc/init.d/sshd restart

11.3. Открываем вторую ssh сессию на сервер
Если вход успешен, то первую сессию нужно завершить, для того чтобы закрыть старую оболочку bash и форк старой sshd.
смотрим lsof /mnt/oldroot
все sshd процессы, запущенные со старой корневой ФС должны исчезнуть.

11.4. Необычные процессы. 
Перезапускаем agetty и init

С agetty (или другими *tty) все просто:
killall agetty
Не стоит бояться, init их перезапустит

Cам init перезапускаем командой
telinit u

11.5. Монтируем файловые системы, отключенные ранее
Я монтирую squashfs в /usr/portage
mount /usr/portage

12.6. Запускаем остановленные ранее сервисы
В моем случае я запускаю:
/etc/init.d/rsyslog start
 * Starting rsyslog ...  [ ok ]

/etc/init.d/snmpd start
 * Starting snmpd ...  [ ok ]

/etc/init.d/vixie-cron start
 * Starting vixie-cron ...  [ ok ]

11.7. Продолжаем перезапускать сервисы

смотрим lsof /mnt/oldroot, и перезапускаем, что осталось

/etc/init.d/ntpd restart
/etc/init.d/radvd restart
/etc/init.d/smartd restart
/etc/init.d/dnsmasq restart

В том числе, я перезапускаю виртуальные машины, которые все это время спокойно работали.
Более того, теперь уже нет особой надобности торопиться.
Мы перезапускаем сервисы, только чтобы размонтировать старую корневую ФС.
/etc/init.d/kvm.204 restart
/etc/init.d/kvm.205 restart
/etc/init.d/kvm.206 restart

12. Операции после переезда

12.1. Не забываем изменить fstab
Я пользуюсь метками LABEL=, поэтому ничего не меняю
LABEL=root              /                       ext3  noatime           0 1

12.2. Размонтируем старую корневую ФС
umount /mnt/oldroot
rmdir /mnt/oldroot /mnt/newroot
Она больше никем не используется
Для тех, кто хочет сохранить старую корневую ФС, я рекомендую поменять у нее LABEL и UUID, чтобы она не мешала новой корневой ФС.
Я предпочитаю удалять дубли ФС.
wipefs /dev/sda2 -o 0x438

12.3. Не забываем добавить/изменить initramfs, при переходе на LVM

12.4. Не забываем переконфигурировать загрузчик
В моем случае это grub2
Устанавливаем загрузчик на sda
grub2-install --no-floppy /dev/sda
Installation finished. No error reported.

Обновляем конфигурацию:
grub2-mkconfig -o /boot/grub2/grub.cfg
Generating grub.cfg ...
Found linux image: /boot/vmlinuz-3.2.12-gentoo-64-beaver-b
Found initrd image: /boot/initrd-3.2.12-gentoo-64-beaver-b
done

Замечания



После переезда на новую корневую ФС сервер может спокойно продолжать работать без перезагрузки.

Комментариев нет:

Отправить комментарий