Тиражирование Linux через PXE

Рассмотрю вариант тиражирование настроеной ОС Linux через локальную сеть.
Схема такого тиражирования довольно проста:

  • Создаем образ который мы собирается тиражировать
  • Собираем минимальный образ линукс для загрузки через сеть, он будет распаковывать сжатый образ тиражируемой системы
  • Настраиваем сервер для раздачи загрузчика

Следуя этому плану устанавливаем ОС Linux на какой нибудь ПК, также можно использовать виртуальный ПК, мне удобнее было использовать отдельный ноутбук.
Затем нам необходимо снять с него образ.

Снятие образа с отдельного жесткого диска

Для снятия образа я буду использовать утилиту mksquashfs, она позволяет в дальнейшем распаковывать в несколько потоков, что в несколько раз быстрее работы архиватора tar.
Создаем рабочий каталог

1
 mkdir root

Монтируем в него корень и все остальные разделы в соответствии с их точками монтирования. У меня система имеет два раздела с точками монтирования / и /home:

1
2
sudo mount /dev/sdc1 ./root
sudo mount /dev/sda6 ./root/home

Затем планируем снимок образа, мне удобнее всего было разбить образ на части:

  • /home
  • /var
  • /usr
  • /etc

В случае каких либо изменений можно будет переписывать не все разделы целиком а только отдельные.
Для такого снятия я написал небольшой срипт:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#Создаем каталог image, куда мы сложим сжатые образы
mkdir -p image
#Зачищаем предыдущие образы, если таковые имеются
if [ -f image/root.squashfs ]; then
rm image/root.squashfs -f
fi
if [ -f image/home.squashfs ]; then
rm image/home.squashfs -f
fi
if [ -f image/etc.squashfs ]; then
rm image/etc.squashfs -f
fi
if [ -f image/etc.squashfs ]; then
rm image/etc.squashfs -f
fi
#Создаем точку монтирования root
mkdir root
#Монтируем все необходимые разделы.
mount /dev/sdc1 root
mount /dev/sdc6 root/home
#Снимаем образы с каталогов с системой
sudo mksquashfs root image/root.squashfs -e root/tmp root/usr root/etc root/var root/home -comp xz -mem 8G
sudo mksquashfs root/etc image/etc.squashfs -comp xz -mem 8G
sudo mksquashfs root/var image/var.squashfs -comp xz -mem 8G
sudo mksquashfs root/usr image/usr.squashfs -comp xz -mem 8G
sudo mksquashfs root/home image/home.squashfs -comp xz -mem 8G

Образы готовы, теперь перейдем в загрузке по сети.

Для загрузки можно использовать gentoo-minimal — это образ gentoo предназначеный для установки gentoo на ПК, он отлично подходит чтобы его можно было загрузить через сеть.
Настройка DHCP и TFTP описана в статье PXE-загрузка-загружаем LiveCD Ubuntu

Подготовка загрузчика Gentoo

Скачиваем с сайта Gentoo x64 уcтановочный образ Gentoo Minimal, так как с 32-х разрядным у меня не заработало, опеределялось только около 800 Мб оперативной памяти и unsquashfs падал из-за нехватки памяти, в последней версии не у меня не заработала локальная сеть, не загружался модуль tg3, пока не нашел как это исправить, поэтому залил старый образ gentoo-minimal в файлообменник.
Для распаковки созданых образов нам необходима утилита unsquashfs, но ее нет в gentoo, возьмем ее из репозитория Slackware Linux , нас интересует архив squashfs-tools-4.3-x86_64-1.txz, поместим его вместе с iso образом.

Скрипт generate.sh

Сайте gentoo есть статья по альтернативной установке, она не подходит для нового образа gentoo-minimal, поэтому внесем в нее некоторые изменения:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#!/bin/bash -xe
sudo ./clean.sh
source ./config.cfg
test -z "$tftproot" -o -z "$image" && echo "Usage: $0 " >&2 && exit 1
test -e "$tmp" && echo "Temporary path '$tmp' already exists." >&2 && exit 1

# prepare directories
mkdir -p "$tmp" "$iso" "$initrd/mnt/cdrom"

# extract files from ISO image
sudo mount -o ro,loop "$image" "$iso"
cp "$iso"/{image.squashfs,isolinux/gentoo,isolinux/gentoo.igz} "$tmp"
sudo umount "$iso"

# patch initramfs and add squashfs to it
xz -dc "$tmp/gentoo.igz" | ( cd "$initrd" && sudo cpio -idv )
sudo patch -d "$initrd" -p0 <<'EOF'
--- init.orig 2018-07-21 18:33:34.528587830 +0300
+++ init 2018-07-21 21:08:15.106424520 +0300
@@ -491,9 +491,9 @@
CHROOT=${NEW_ROOT}
fi

- if [ /dev/nfs != "$REAL_ROOT" ] && [ sgimips != "$LOOPTYPE" ] && [ 1 != "$aufs" ] && [ 1 != "$overlayfs" ]; then
- bootstrapCD
- fi
+# if [ /dev/nfs != "$REAL_ROOT" ] && [ sgimips != "$LOOPTYPE" ] && [ 1 != "$aufs" ] && [ 1 != "$overlayfs" ]; then
+# bootstrapCD
+# fi

if [ "${REAL_ROOT}" = '' ]
then
@@ -558,7 +558,7 @@
REAL_ROOT="${ROOT_DEV}"
else
prompt_user "REAL_ROOT" "root block device"
- got_good_root=0
+ got_good_root=1
continue
fi
;;
@@ -636,7 +636,7 @@
else
bad_msg "Block device ${REAL_ROOT} is not a valid root device..."
REAL_ROOT=""
- got_good_root=0
+ got_good_root=1
fi
done

@@ -718,7 +718,7 @@
[ -z "${LOOP}" ] && find_loop
[ -z "${LOOPTYPE}" ] && find_looptype

- cache_cd_contents
+ #cache_cd_contents

# If encrypted, find key and mount, otherwise mount as usual
if [ -n "${CRYPT_ROOT}" ]
EOF
echo "Unpack image squashfs"
sudo ./unsqfs.sh $tmp $tmp/image.squashfs
if [ $auto -eq 1 ]; then
echo "Add Squashfs tool in image"
sudo ./prepare.sh
sudo ./mkautostart.sh
sudo ./pack_image.sh
sudo ./mkpxeboot.sh
fi

Скрипт config.sh

Для работы этого скрипта создадим файл конфигурации config.cfg

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/env bash
#Дериктория куда будут сложены загрузочные файлы
tftproot="tftp"
#Путь к образу gentoo-minimal
image="source/install-amd64-minimal-20180719T214502Z.iso"
archivesqfs="source/squashfs-tools-4.3-x86_64-1.txz"
#расположение временного каталога
tmp="./tmp"
#Расположение каталога для распаковки gentoo minimal
iso="$tmp/iso"
#Расположение каталога где будет раполагаться распакованый initrd
initrd="$tmp/initrd.dir"
#Автоматический режим
auto=1

Скрипт prepare.sh

Таже нам нужен файл prepare.sh, который установит squashfs-tool в наш образ

1
2
3
#!/bin/bash -xe
source ./config.cfg
tar -xvf $archivesqfs -C "tmp/root" --exclude install

После запуска скрипта будет создана дериктория tmp, в которой располагается распакованые образы initrd и image.squashfs
Запускаем скрипт prepare.sh,который установит squashfs-tools в загрузчик

Скрипт mkautostart.sh

Нам необходимо добавить скрипт автозапуска, который запустит скрипт разметки и установки, он должен располагаться в /root/.bashrc
Для этого выполним файл mkautostart.sh:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/bin/bash -xe
source ./config.cfg
sudo patch -d "$tmp/root/root/" -p0 <<'EOF'
--- .bashrc.orig 2018-07-19 03:56:34.000000000 +0300
+++ .bashrc 2018-07-22 17:12:50.973585791 +0300
@@ -12,3 +12,25 @@
fi
fi
fi
+
+setterm -blank 0
+server='192.168.0.1'
+share="pxeboot"
+if [ $(tty) = "/dev/tty1" ];then
+rmmod tg3
+sleep 1s
+modprobe tg3
+while :
+ do
+ sleep 1;
+ if [ $(ping $server -c 10 -w 30 -q &> /dev/null && echo $?) ]
+ then
+ break
+ fi
+ done
+ntpdate $server
+ip address
+mkdir -p /mnt/net
+mount -t nfs 192.168.0.1:/srv/template /mnt/net
+/mnt/net/script.sh
+fi

Скрипт pack_image.sh

После запуска скрипта в автозагрузку root/.bashrc добавятся строчки ожидания сервера, затем монтирование общего каталога на сервере и запуска с него установочного скрипта
Теперь нам необходимо упаковать образ, для этого выполним pack_image.sh :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash -xe
source ./config.cfg
sudo mksquashfs $tmp/root $tmp/image.squashfs
cp "$tmp/image.squashfs" "$initrd/mnt/cdrom"
( cd "$initrd" && find . -print | cpio -o -H newc | gzip -9 -c - ) > "$tmp/initramfs.gz"

# prepare boot data
if [ ! -d $tftproot/pxelinux.cfg ]; then
mkdir -p "$tftproot/pxelinux.cfg"
fi
cat > "$tftproot/pxelinux.cfg/default" <<'EOF'
default Gentoo
label Gentoo
kernel gentoo
append initrd=initramfs.gz root=/dev/ram0 init=/linuxrc loop=image.squashfs looptype=squashfs cdroot=1 real_root=/
EOF
cp "$tmp"/{gentoo,initramfs.gz} "$tftproot/"
#
## cleanup
sudo rm -rf "$tmp"

Теперь необходимо добавить подключение по nfs, на сервере в файле /etc/exports

1
/srv/template 192.168.1.1/255.255.255.0(rw,insecure,nohide,all_squash,anonuid=1000,anongid=1000,no_subtree_check)

Перезапускаем nfs-kernel-server

1
systemctl restart nfs-kernel-server

Скрипт авторазметки script.sh

Остался скрипт авторазметки:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#!/bin/bash
SETCOLOR_SUCCESS="echo -en \\033[1;32m"
SETCOLOR_FAILURE="echo -en \\033[1;31m"
SETCOLOR_NORMAL="echo -en \\033[0;39m"
function failedExit {
if [ $? -eq 0 ]; then
$SETCOLOR_SUCCESS
echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]"
$SETCOLOR_NORMAL
echo
else
$SETCOLOR_FAILURE
echo -n "$(tput hpa $(tput cols))$(tput cub 6)[fail]"
$SETCOLOR_NORMAL
echo
exit 1
fi
}
function failedOk {
if [ $? -eq 0 ]; then
$SETCOLOR_SUCCESS
echo -n "$(tput hpa $(tput cols))$(tput cub 6)[OK]"
$SETCOLOR_NORMAL
echo
else
$SETCOLOR_FAILURE
echo -n "$(tput hpa $(tput cols))$(tput cub 6)[fail]"
$SETCOLOR_NORMAL
echo
fi
}
ip address
net='net'
mkdir /mnt/root
echo "Create table"
(parted /dev/sda mktable msdos -s &>/dev/null
parted /dev/sda mkpart primary 1 20G print free -s &>/dev/null
parted /dev/sda mkpart primary 20G 24G print free -s &>/dev/null
parted /dev/sda mkpart primary 24G 28G print free -s &>/dev/null)
failedExit
parted /dev/sda print -s
echo "MkFS..."
(echo "y" | mkfs.ext4 -U '52324238-502c-4a6c-a8a4-e63480b7d9ea' /dev/sda1 &>/dev/null
echo "y" | mkfs.ext4 -U '18719e4d-7318-4077-876a-2ae6392465d9' /dev/sda3 &>/dev/null
mkswap -U '9ce9eb70-1ec1-46c7-9691-c83e5720ab1e' /dev/sda2 &>/dev/null)
failedExit
### Mount /dev/sda
echo "Mount disk..."
mount /dev/sda1 /mnt/root &>/dev/null
failedExit
### Unpack Squashfs to /mnt/root
echo "Unpack FS "$i
unsquashfs -d /mnt/root -f /mnt/$net/root.squashfs
failedOk
for i in 'usr' 'var' 'etc'; do
echo "Unpack FS "$i
unsquashfs -d /mnt/root/$i -f /mnt/$net/$i.squashfs
failedOk
done
### Mount /dev/sda3
echo "Unpack FS home"
mount /dev/sda3 /mnt/root/home &>/dev/null
failedExit
unsquashfs -d /mnt/root/home -f /mnt/$net/home.squashfs
failedOk
echo "Mount Directory"
(mount -o bind /dev /mnt/root/dev &>/dev/null
mount -o bind /proc /mnt/root/proc &>/dev/null
mount -o bind /sys /mnt/root/sys &>/dev/null
chroot /mnt/root grub-install /dev/sda &>/dev/null)
failedExit
echo "Poweroff"
poweroff

Скрипт clean.sh

Добавим скрипт очистки от файлов сборки

1
2
sudo rm -rf tmp
sudo rm -rf tftp

Кладем его вместе с образами в каталог /srv/template
Готово, мы получили сервер для тиражирования по сети.
Можем попробовать загрузиться.
Все скрипты можно найти в GitHub
Загрузка в память

Процесс загрузки gentoo-minimal

Процесс загрузки

Распаковка unsquashfs

Добавить комментарий

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.