Создание своего образа с чистым CentOS 8.1 в облаке Amazon

Данное руководство, является «форком» одноименной статьи про CentOS 5.9, и учитывает особенности новой OS. На данный момент в AWS Marketplace нет официального образа Centos8 от centos.org.

Как известно, в облаке Amazon виртуальные инстансы запускаются на основе образов (так называемые AMI). Amazon предоставляет большое их количество, также можно использовать публичные образы, подготовленные сторонними организациями, за которые облачный провайдер, естественно, никакой ответственности не несёт. Но иногда нужен образ чистой системы с нужными параметрами, которого нет в списке образов.

Тогда единственный выход — сделать свой AMI.

В официальной документации описан способ создания «instance store-backed AMI».

Минус такого подхода заключается в том, что готовый образ нужно будет ещё и сконвертировать в «EBS-backed AMI». Так же, стоит отметить Cockpit Image Builder. Он позволит создавать кастомные образы, в CLI или WEB GUI режиме, но когда у вас уже будет Centos 8.

О том, как создать свой EBS-backed AMI в облаке Amazon без промежуточных шагов, пойдёт речь в этой статье.

План действий

  • Подготовить окружение
  • Установить чистую систему, сделать необходимые настройки
  • Сделать snapshot (слепок) диска
  • Зарегистрировать AMI

Подготовка окружения

Для наших целей подойдёт любой официальный инстанс Centos 7 любого шейпа, хоть t2.micro. Запустить его можно через CLI:

aws ec2 run-instances 
  --image-id ami-4bf3d731 
  --region us-east-1 
  --key-name alpha 
  --instance-type t2.micro 
  --subnet-id subnet-240a8618 
  --associate-public-ip-address 
  --block-device-mappings DeviceName=/dev/sda1,Ebs={VolumeSize=8} 
  --block-device-mappings DeviceName=/dev/sdb,Ebs={VolumeSize=4}

Команда поднимет инстанс в VPC, к которой относится указанный subnet-id. Предполагается, что подсеть будет публичная, и SG ‘default’ разрешает все.

Теперь залогинимся на инстанс по ssh, обновим систему, установим dnf и перезагрузимся:

sudo yum update -y && sudo yum install -y dnf && sudo reboot

Все дальнейшие операции будут выполняться от root.

Установка чистого Centos 8.1

Разметка файловой системы и монтирование разделов

DEVICE=/dev/xvdb
ROOTFS=/rootfs
parted -s ${DEVICE} mktable gpt
parted -s ${DEVICE} mkpart primary ext2 1 2
parted -s ${DEVICE} set 1 bios_grub on
parted -s ${DEVICE} mkpart primary xfs 2 100%

mkfs.xfs -L root ${DEVICE}2
mkdir -p $ROOTFS
mount ${DEVICE}2 $ROOTFS

mkdir $ROOTFS/{proc,sys,dev,run}
mount --bind /proc $ROOTFS/proc
mount --bind /sys $ROOTFS/sys
mount --bind /dev $ROOTFS/dev
mount --bind /run $ROOTFS/run

Создание дерева каталогов

Система RPM позволяет легко и быстро подготовить дерево каталогов будущей ОС:

PKGSURL=http://mirror.centos.org/centos/8/BaseOS/x86_64/os/Packages
rpm --root=$ROOTFS --initdb
rpm --root=$ROOTFS -ivh 
  $PKGSURL/centos-release-8.1-1.1911.0.8.el8.x86_64.rpm 
  $PKGSURL/centos-gpg-keys-8.1-1.1911.0.8.el8.noarch.rpm 
  $PKGSURL/centos-repos-8.1-1.1911.0.8.el8.x86_64.rpm

dnf --installroot=$ROOTFS --nogpgcheck --setopt=install_weak_deps=False 
   -y install audit authselect basesystem bash biosdevname coreutils 
   cronie curl dnf dnf-plugins-core dnf-plugin-spacewalk dracut-config-generic 
   dracut-config-rescue e2fsprogs filesystem firewalld glibc grub2 grubby hostname 
   initscripts iproute iprutils iputils irqbalance kbd kernel kernel-tools 
   kexec-tools less linux-firmware lshw lsscsi ncurses network-scripts 
   openssh-clients openssh-server passwd plymouth policycoreutils prefixdevname 
   procps-ng  rng-tools rootfiles rpm rsyslog selinux-policy-targeted setup 
   shadow-utils sssd-kcm sudo systemd util-linux vim-minimal xfsprogs 
   chrony cloud-init 

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

При желании, вы можете использовать примерно такой вариант:

dnf --installroot=$ROOTFS groupinstall base core 
    --excludepkgs "NetworkManager*" 
     -e "i*-firmware"

В yum нет --excludepkgs, и раньше приходилось устанавливать группы, и потом удалять пакеты.

Список пакетов и зависимых групп можно просмотреть командой dnf group info core для группы core.

Кастомизация файлов ОС

Создадим конфиги для сети, fstab, grub2 и используем интернальные 169.254 адреса AWS для DNS и NTP.

cat > $ROOTFS/etc/resolv.conf << HABR
nameserver 169.254.169.253
HABR

cat > $ROOTFS/etc/sysconfig/network << HABR
NETWORKING=yes
NOZEROCONF=yes
HABR

cat > $ROOTFS/etc/sysconfig/network-scripts/ifcfg-eth0  << HABR
DEVICE=eth0
ONBOOT=yes
BOOTPROTO=dhcp
HABR

cat > $ROOTFS/etc/fstab << HABR
LABEL=root / xfs defaults,relatime 1 1
HABR

sed -i  "s/cloud-user/centos/" $ROOTFS/etc/cloud/cloud.cfg
echo "server 169.254.169.123 prefer iburst minpoll 4 maxpoll 4" >> $ROOTFS/etc/chrony.conf
sed -i "/^pool /d" $ROOTFS/etc/chrony.conf
sed -i "s/^AcceptEnv/# /" $ROOTFS/etc/ssh/sshd_config

cat > $ROOTFS/etc/default/grub << HABR
GRUB_TIMEOUT=1
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="crashkernel=auto console=ttyS0,115200n8 console=tty0 net.ifnames=0 biosdevname=0"
GRUB_DISABLE_RECOVERY="true"
GRUB_ENABLE_BLSCFG=true
HABR

Именно тут, в GRUB_CMDLINE_LINUX я рекомендую указывать selinux=0, для тех кто все еще боится SELinux.

Пересборка initramfs в chroot

После правки фалов grub и fstab необходимо выполнить пересборку.
Выполняем обновление:

KERNEL=$(ls $ROOTFS/lib/modules/) 
chroot $ROOTFS dracut -f -v /boot/initramfs-$KERNEL.img $KERNEL
chroot $ROOTFS grub2-mkconfig -o /boot/grub2/grub.cfg
chroot $ROOTFS grub2-install $DEVICE
chroot $ROOTFS update-crypto-policies --set FUTURE

Тут update-crypto-policies — по желанию, для параноиков 🙂

Для «прода», можно сделать так:

chroot $ROOTFS fips-mode-setup --enable
chroot $ROOTFS grub2-mkconfig -o /boot/grub2/grub.cfg
chroot $ROOTFS grub2-install $DEVICE

После загрузки ОС, команда update-crypto-policies --show выдаст FIPS.

Автозапуск и Чистка мусора

chroot $ROOTFS systemctl enable network.service
chroot $ROOTFS systemctl enable sshd.service
chroot $ROOTFS systemctl enable cloud-init.service
chroot $ROOTFS systemctl mask tmp.mount
dnf --installroot=$ROOTFS clean all
truncate -c -s 0 $ROOTFS/var/log/*.log
rm -rf var/lib/dnf/*
touch $ROOTFS/.autorelabel

autorelabel — нужен для автоматической установки SELinux контекста файлов при первой загрузке.

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

sync
umount $ROOTFS/{proc,sys,dev,run}
umount $ROOTFS

Регистрация AMI

Чтобы получить из ebs-диска ami, нужно сделать сначала снапшот диска:

aws ec2 create-snapshot 
    --volume-id vol-09f26eba4c50da110  --region us-east-1 
    --description 'centos-release-8.1-1.1911.0.8 4.18.0-147.5.1 01'

Какое-то время надо будет подождать. Проверем статус по полученому SnapshotId:

aws ec2   describe-snapshots  --region us-east-1 --snapshot-ids snap-0b665542fc59e58ed

Когда получим "State": "completed", можно зарегистрировать AMI и сделать его публичным:

aws ec2 register-image 
    --region us-east-1 
    --name 'CentOS-8.1-1.1911.0.8-minimal' 
    --description 'centos-release-8.1-1.1911.0.8 4.18.0-147.5.1 01' 
    --virtualization-type hvm --root-device-name /dev/sda1 
    --block-device-mappings '[{"DeviceName":"/dev/sda1","Ebs": { "SnapshotId": "snap-0b665542fc59e58ed", "VolumeSize":4,  "DeleteOnTermination": true, "VolumeType": "gp2"}}]' 
    --architecture x86_64 --sriov-net-support simple --ena-support

aws ec2 modify-image-attribute 
    --region us-east-1 
    --image-id ami-011ed2a37dc89e206 
    --launch-permission 'Add=[{Group=all}]'

На этом все. Теперь можно запускать инстансы.

Таким способом можно сделать образ, скорее всего, с любым Linux-дистрибутивом. По крайней мере, точно Debian (используя debootstrap для установки чистой системы) и RHEL-семейства.

UPDATE По заявкам читателей. Автоматизировать данный процесс может Packer, только Автоматизировать. Тут представлен пример темплейта.

Источник: habr.com