среда, 23 января 2013 г.

Клонирование P2V в инфраструктуру VMware без vCenter Converter


Производить миграцию или клонирование P2V серверов в инфраструктуру vmware, конечно удобно проводить при помощи vCenter Converter. Однако, vCenter Converter будет работать только если разделы ОС находятся под управлением LVM, или это должны быть диски с разделами (а не просто диски). Подробнее узнать об ограничениях можно здесь. В случае если условия не удовлетворяют, Вам придется произвести миграцию самостоятельно. В моем случае было 10 серверов, настроенных на загрузку с SAN, LVM на них не используется, в качестве разделов ОС как раз использовались целые диски без партиций (LUN с схд). Операционная система – CentOS 5 x86_64. Сервера располагаются в ЦОД’е в Нью Йорке, виртуальные машины должны быть во Франкфурте. Итак, миграция по шагам, используя примеры команд. Я постарался документировать этот достаточно утомительный процесс и попробовать его автоматизировать:

Создание виртуальной машины
Создайте виртуальную машину с нужными характеристиками. Если хотите что то поменять по сравнению с физической - самое время это сделать. Я изменил количество дисков, т.к. разумно использовать один диск совместно с LVM.
Примонтируте любой live дистрибутив linux, например knoppix, fedora, gentoo и т.д. Обратите внимание на то, что архитектура дистрибутива Live CD должна соответствовать той, которую имеет переносимый сервер. У меня под руками был Gentoo 11.0. После загрузки, назначите IP адрес, шлюз, пароль root, и запустите sshd:

Gentoo-11 ~ # ifconfig eth0 192.168.1.25/24
Gentoo-11 ~ # route add default gw 192.168.1.25
Gentoo-11 ~ # passwd root
Gentoo-11 ~ # /etc/init.d/sshd start

Создание и форматирование разделов:
Поскольку я хотел использовать LVM, то простое копирование структуры дисковой подсистемы не годилось. Выбранная структура – один диск, разделенный на две партиции. Первая партиция - под загрузчик (500МБ), а вторая отдается под управление LVM.

Gentoo-11 ~ # parted -s /dev/sda mklabel msdos
Gentoo-11 ~ # parted -s /dev/sda mkpart primary 1MB 525MB
Gentoo-11 ~ # parted -s /dev/sda toggle 1 boot
Gentoo-11 ~ # parted -s /dev/sda mkpart primary 525MB 53.7GB
Gentoo-11 ~ # parted -s /dev/sda toggle 2 lvm

Создадим тома в LVM, разделы: подкачки, /root и /var/log

Gentoo-11 ~ # pvcreate /dev/sda2
Gentoo-11 ~ # vgcreate vgname /dev/sda2
Gentoo-11 ~ # lvcreate -L 2048 -n swap vgname
Gentoo-11 ~ # lvcreate -L 20480 -n root vgname
Gentoo-11 ~ # lvcreate -l 7042 -n log vgname

Внесите необходимые коррективы, если ваша таблица разделов будет отличаться.
Произведем форматирование:

Gentoo-11 ~ # mkfs.ext3 -L boot /dev/sda1
Gentoo-11 ~ # mkswap -L swap /dev/mapper/vgname-swap
Gentoo-11 ~ # mkfs.ext3 -L root /dev/mapper/vgname-root
Gentoo-11 ~ # mkfs.ext3 -L log /dev/mapper/vgname-log

Создайте папки, в которые затем примонтируем разделы:

Gentoo-11 ~ # mkdir -p /mnt/root
Gentoo-11 ~ # mount /dev/mapper/vgname-root /mnt/root/
Gentoo-11 ~ # mkdir -p /mnt/root/boot /mnt/root/var/log
Gentoo-11 ~ # mount /dev/sda1 /mnt/root/boot
Gentoo-11 ~ # mount /dev/mapper/vgname-log /mnt/root/var/log

Перенос данных.
Переносить данные будем через sftp. Для того, что бы не вводить пароль – скопируйте публичный ключ пользователя root с физического сервера:

root@source:~# ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.1.25

Данные будем переносить в виде tar архива. Архив можно не создавать на исходном сервере, а сразу передать на целевой с помощью pipe, например:

root@source:~# tar czf - /usr | ssh root@192.168.1.25 "dd of=/mnt/root/var/usr.tgz"

Команде tar так же можно указать, что не нужно помещать в архив. Это можно указать в командной строке через параметр --exclude pattern, или создать файл исключений, который указывается через параметр -X file. В файле исключений можно указать директории /dev, /proc, /var/log и т.д. Но в отличие от данных в нутрии этих директорий – сами директории нужны, поэтому после переноса данных их нужно будет создать.
Перенос данных можно автоматизировать. Я написал скрипт converter.sh. Он создает tar архив и формирует файл скрипта mkdir.sh, которые передаются на целевой сервер. Скрипт mkdir.sh необходим для создания директорий, а так же он монтирует служебные файловые системы, такие как например proc. Файл exclude используется для указания исключений.

root@source:~# cat converter.sh
#!/bin/bash

exclude=./exclude
log=./converter.log

if [ $# -ne 2 ]; then echo "Usage: converter.sh destionation_server destination_directory"; exit 1; fi

cat /dev/null > $log 

ls / | while read dir
  do
    tar -czX $exclude -f - /$dir 2>>$log| ssh root@$1 "dd of=$2/$dir.tgz"
    echo -e "Backup /$dir \e[00;32mcomplete\e[00m"
  done

# Make the file, which makes directories
echo -n "Make and transfer executive file:"
cat /dev/null > ./mkdir.sh
echo -e "#!/bin/sh \n\n#Make directories" >> ./mkdir.sh
echo "if [ \$# -ne 1 ]; then echo \"Usage: mkdir.sh mount_point\"; exit 1; fi" >> ./mkdir.sh

for dir in /dev /proc /selinux /sys /tmp
do
  usrgrp=`stat -c %u:%g $dir`
  perm=`stat -c %a $dir`
  echo -e "mkdir \$1$dir \nchmod $perm \$1$dir \nchown $usrgrp \$1$dir" >> ./mkdir.sh
done

dirs=(`grep -v "$#\|$^\|dev\|proc\|selinux\|lost+found\|sys\|tmp" ./exclude | while read dir
do
  find $dir -type d | grep -v "lost+found"
done`)
element_count=${#dirs[@]}

index=0
while [ "$index" -lt "$element_count" ]
do
  usrgrp=`stat -c %u:%g ${dirs[$index]}`
  perm=`stat -c %a ${dirs[$index]}`
  echo -e "mkdir \$1${dirs[$index]} \nchmod $perm \$1${dirs[$index]} \nchown $usrgrp \$1${dirs[$index]}" >> ./mkdir.sh
  let "index=$index+1"
done

echo -e "mount --bind /dev \$1/dev \nmount --bind /proc \$1/proc \nmount --bind /sys \$1/sys" >> ./mkdir.sh

scp ./mkdir.sh root@$1:$2 2>>$log
echo -e " \e[00;32mcomplete\e[00m"

Для корректной работы скрипта, файл exclude должен быть в той же директории что и скрипт. Содержимое моего exclude:

root@source:~# cat ./exclude
/dev
/lost+found
/proc
/selinux
/sys
/var/log

Входные параметры скрипта converter.sh – dns имя сервера или его ip адрес, а так же директория назначения.
Выполним перенос данных:

root@source:~# ./converter.sh 192.168.1.25 /mnt/root/var/log

Развертывание данных
Теперь перейдем на целевой сервер и развернем данные:

Gentoo-11 ~ # cd /mnt/root
Gentoo-11 root # ls var/log/*.tgz | while read arch; do tar -xf $arch; done

Создадим директории и примонтируем служебные файловые системы при помощи скрипта mkdir.sh. Скрипт имеет входной параметр – место куда примонтирован корневой раздел:

Gentoo-11 root # sh var/log/mkdir.sh /mnt/root

Внесение изменений в конфигурационные файлы, установка grub
Так как, по сравнению с исходной системой, в таблицу разделов внесено изменение, то необходимо внести соответствующие изменения на целевом сервере. Внесите коррективы в fstab. Согласно моему:

Gentoo-11 root # cat /mnt/root/etc/fstab
LABEL=root  /        ext3   defaults 1 1
LABEL=boot  /boot    ext3   defaults 1 2
tmpfs       /dev/shm tmpfs  defaults 0 0
devpts      /dev/pts devpts gid=5,mode=620 0 0
sysfs       /sys     sysfs  defaults 0 0
proc        /proc    proc   defaults 0 0
LABEL=swap  swap     swap   defaults 0 0
tmpfs       /tmp     tmpfs  defaults,size=1G 0 0
LABEL=log   /var/log ext3   defaults 1 3

Теперь нужно войти в созданное окружение:

Gentoo-11 root # chroot /mnt/root

Уберите все лишнее из /etc/modprobe.conf и проверьте есть ли у вас строки:

Gentoo-11 root # cat /etc/modprobe.conf
alias scsi_hostadapter mptbase
alias scsi_hostadapter1 mptspi
alias scsi_hostadapter2 ata_piix

Это позволит включить эти модули ядра в initrd, что позволит в свою очередь корректно произвести загрузку (по умолчанию vmware выбирает адаптер LSI Logic Parallel)

Создадим новый initrd:

Gentoo-11 root # mkinitrd -v /boot/initrd-2.6.18-274-1.el5.img 2.6.18-274.el5

Внесите коррективы в настройки grub, учитывая смену диска root и новый initrd:

Gentoo-11 root # cat boot/grub/menu.lst
default=0
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title CentOS (2.6.18-274.el5)
root (hd0,0)
kernel /vmlinuz-2.6.18-274.el5 ro root=/dev/vgname/root
initrd /initrd-2.6.18-274-1.el5.img

Финальная часть, необходимо установить загрузчик:

Gentoo-11 root # grub

grub> root (hd0,0)
root (hd0,0)
Filesystem type is ext2fs, partition type 0x83
grub> setup (hd0)
setup (hd0)
Checking if "/boot/grub/stage1" exists... no
Checking if "/grub/stage1" exists... yes
Checking if "/grub/stage2" exists... yes
Checking if "/grub/e2fs_stage1_5" exists... yes
Running "embed /grub/e2fs_stage1_5 (hd0)"... failed (this is not fatal)
Running "embed /grub/e2fs_stage1_5 (hd0,0)"... failed (this is not fatal)
Running "install /grub/stage1 (hd0) /grub/stage2 p /grub/grub.conf "... succeeded
Done.
grub> quit
quit


Все! Можно перегружать виртуальный сервер и расслабиться после нудной работы.

Напоследок, команды, которые могут понадобиться:

  1. Просмотр таблицы разбиения диска
parted /dev/sda print
  1. Активация lvm
vgchange -a y

суббота, 19 января 2013 г.

Использование записей /etc/hosts в nginx


Недавно столкнулся с интересной особенностью в nginx. У меня возникла необходимость прописать в параметре proxy_path имя сервера, которое в свою очередь определено в /etc/hosts. Не работает! Немного погуглив, я нашел совет. Рекомендации которого заключается в следующем:
Прописать директиву

resolver 127.0.0.1

Которая указывает адрес (можно указать так же и порт) для днс запросов, установить на этот же сервер dnsmasq, который может брать информацию из /etc/hosts (немного о настройке dnsmasq можно прочитать в статье про настройку wi-fi точки доступа). Однако, имена в /etc/hosts все же можно использовать без этих манипуляций. Имя сервера нужно прописать в upstream, которое затем использовать в proxy_path. Все работает! Пример использования:

upstream example {
  server  www.host.local;
}


location = /api/example/ {
  rewrite  ^/api/example(/.*) $1 break;
  access_log  /var/log/nginx/example.access.log main;
  error_log   /var/log/nginx/example.error.log  debug;
  proxy_set_header        Host  dns-name.domain.ru;
  proxy_pass              http://example/$request_uri;
}

В данном примере запросы вида http://nginx_site/api/example/something проксируются на хост dns-name.domain.ru с использованием hosts записи www.host.local. Проксированный урл запроса после обработки будет выглядеть так: http://dns-name.domain.ru/something.