выбираем и настраиваем ВМ для облака
Если вы знакомы с FreeBSD, вы уже знаете её достоинства и недостатки по сравнению с Linux. Просуммирую некоторые отличия, важные для выбора облачной ВМ.
- FreeBSD не поддерживает контейнеры в привычном понимании, ни docker, ни podman пока не портированы
- FreeBSD использует свою собственную лицензию The FreeBSD Copyright, позволяющую не раскрывать т.н. derivative work. Как результат, оценить распространённость FreeBSD иногда затруднительно, возможно, часть её кода используется и в Windows(C), и в MacOS(C). Только иногда разработчики сами признают её использование, напр. Евгений Гаврилов, руководитель проекта vStack
- Метод разработки FreeBSD ближе к академическому стилю, есть базовый набор пакетов base, включающий не только ядро, но и достаточно инструментов для сборки остальной системы, именуемой ports. Развитие системы управляется elected Core Team, на данный момент 9 человек.
- Во FreeBSD давно используется система snapshots/rollback, позволяющая откатить изменения, если что-то сломалось.
Есть дистрибутив Linux, взявший некоторые из перечисленных особенностей - это Fedora Core. Первоначально эти идеи возникли в другом дистрибутиве, RedHat CoreOS. Во-первых, это система ориентирована на использование в облаках, предоставляются образы для всех возможных систем виртуализации и форматов дисков. Во-вторых, она разделена на базовую систему, часть из которой монтируется только в режиме только чтение (ro:read only), и остальное, доступное ч/з контейнеры. Обновление системы возможно автоматически, появилась особая утилита rpm-ostree, и можно откатить на предыдущую версию, если что-то не так. Таким образом, CoreOS становиться иммутабельной, изменения базовой части системы невозможны в обход коммитов rpm-ostree.
Я как-то сделал эксперимент, установил в Яндекс облаке версию FedoraCore 35, выпущенную в конце 2021г., с включённым по умолчанию сервисом zincati, автоматически обновляющем базовую систему, стабильные релизы. Посчитал, сколько коммитов сделано с тех пор: да, также как в git, используется CAS(content-addressable storage), уже привычные нам хэши. ВМ обновилась и рестартанула 8 раз, если я не пропустил какой-либо рестарт:
grep ^Linux uname*|cut -d" " -f1,3,7-|sed 's/Linux//;s/ x86.*//'
uname35: 5.15.7-200.fc35.x86_64 Dec 8 19:00:47 UTC 2021
uname36: 5.17.5-300.fc36.x86_64 Thu Apr 28 15:51:30 UTC 2022
uname37: 6.1.18-200.fc37.x86_64 Sat Mar 11 16:09:14 UTC 2023
uname38: 6.5.8-200.fc38.x86_64 Fri Oct 20 15:53:48 UTC 2023
uname39.0: 6.6.8-200.fc39.x86_64 Thu Dec 21 04:01:49 UTC 2023
uname39.1: 6.8.4-200.fc39.x86_64 Thu Apr 4 20:45:21 UTC 2024
uname40.0: 6.8.11-300.fc40.x86_64 Mon May 27 14:53:33 UTC 2024
uname40.1: 6.11.3-200.fc40.x86_64 Thu Oct 10 22:31:19 UTC 2024
uname41: 6.12.7-200.fc41.x86_64 Fri Dec 27 17:05:33 UTC 2024
Теперь можно сравнить с этой же системой, установленной из свежего имиджа - как и ожидалось, системы не отличались, хэши коммитов одинаковы. Это то, что имеется ввиду под иммутабельностью ОС. Кроме иммутабельности и смонтированных только по чтению некоторых каталогов, есть и другие меры безопасности. Используется версия Security-Enhanced Linux, никаких логинов по умолчанию, настройки пользователя либо через утилиту cloud-init, либо специальная утилита butane и т.н. ignition file.
У проекта Fedora есть подробнейшая документация, безусловно, самое авторитетное руководство по установке. Тем не менее, у меня возникла пара вопросов. Во-первых, для преобразования .yaml файла в ignition, который по сути обычный .json файл, используется особый инструмент butane, написанный на языке go
, судя по размеру образа 130M, довольной увесистый, но никак не упоминаются другие утилиты для конвертациии .yaml в .json. Во-вторых, в простейшем случае, для первого логина, вообще не нужны ни butane, ни .yaml. Вот пример минимального ignition.json файла, который создаётся руками:
cat ignition.json
{
"ignition": {
"version": "3.3.0"
},
"passwd": {
"users": [
{
"name": "core",
"sshAuthorizedKeys": [
"<ssh-ed25519 your ssh pub key content>"
]
}
]
}
}
Скопируем этот файл в каталог /tmp
, он нужен 1 раз, для первого входа, не содержит секретов, к нему нужно будет указать полный путь. Как и ранее, скачиваем свежий образ для libvirt/qemu: выбрать нужную архитектуру и формат диска, проверяем контрольные суммы и цифровые подписи. Команды для создания ВМ будут немного отличаться от уже опробованной из прошлой статье - сначала сделаем для нашего ignition.json опцию, которую понимает virt-install:
export IGN=(--qemu-commandline="-fw_cfg name=opt/com.coreos/config,file=/tmp/ignition.json")
echo $IGN
--qemu-commandline=-fw_cfg name=opt/com.coreos/config,file=/tmp/ignition.json
Затем распаковываем образ в стандартный каталог и создаём ВМ:
xz -cdv fedora-coreos-41.20250215.3.0-qemu.x86_64.qcow2.xz > /var/lib/libvirt/images/fc41stab.qcow2
virt-install --import --memory 4096 --vcpus 1 -w bridge=br0 \
--os-variant="fedora-coreos-stable" --graphics=none \
-n fc41stab "${IGN[@]}" --disk /var/lib/libvirt/images/fc41stab.qcow2
Созданная заранее переменная шелл использована как "${IGN[@]}". virt-install
выдаст интереснейший лог процесса инсталяции, в самом конце, перед приглашением, покажет IP адрес вновь созданной ВМ. Переходим в другую консоль и проверяем наш ssh ключ: ssh -v [email protected]
в моём случае. После успешного логина выполняем первоочерёдные проверки и настройки:
$ id
uid=1000(core) gid=1000(core) groups=1000(core),4(adm),10(wheel),16(sudo),190(systemd-journal) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
$ sudo -l
Matching Defaults entries for core on fc41stab:
!visiblepw, always_set_home, match_group_by_gid, always_query_group_plugin, env_reset, env_keep="COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR
LS_COLORS", env_keep+="MAIL QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE", env_keep+="LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT
LC_MESSAGES", env_keep+="LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE", env_keep+="LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET
XAUTHORITY", secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/var/lib/snapd/snap/bin
User core may run the following commands on fc41stab:
(ALL) ALL
(ALL) NOPASSWD: ALL
$ sudo hostnamectl hostname fc41stab
$ sudo passwd core
Теперь ВМ можно остановить и сделать финальные настройки нашего персонального облака для этой ВМ. Добавим MAC и статический IP адреса в dnsmasq.conf, зададим имя новой ВМ в сети, см. пример из прошлой статьи. Откроем в virt-manager окно overview, затем откроем вкладку XML и в самом конце удалим конфиг для qemu, целиком вот этот фрагмент:
<qemu:commandline>
<qemu:arg value="-fw_cfg"/>
<qemu:arg value="name=opt/com.coreos/config,file=/tmp/ignition.json"/>
</qemu:commandline>
Далее кнопка Apply. Возможно, virt-manager попросит сначала установить Edit -> Preferences -> General -> Enable XML editing. То же самое можно сделать из командной строки: sudo virsh edit fc41stab
. Ignition файл нужен только для установки, далее эту ВМ можно донастраивать, клонировать, копировать её образ куда угодно, в том числе в большие облака.
Ну а мы продолжим знакомство с этой необычной системой, как её рекламирует проект Федора:
“Fedora CoreOS — это автоматически обновляемая, минимальная, монолитная, ориентированная на контейнеры операционная система, разработанная для кластеров, но также работоспособная автономно, оптимизированная для Kubernetes, но также отлично работающая и без него”
Проверим, что dnsmasq обновился, и начнём по порядку.
$ host fc41stab
fc41stab.local has address 192.168.100.118
fc41stab.local mail is handled by 1 fc41stab.local.
$ ssh -v fc41stab
Далее выполняем команды внутри ВМ. Основное, к чему придётся привыкнуть - что часть каталогов смонтированы readonly, запись в них в обход утилиты rpm-ostree невозможна даже судоерам:
core@fc41stab:~$ mount|grep ro,|grep ^/dev
/dev/vda4 on /sysroot type xfs (ro,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,prjquota)
/dev/vda3 on /boot type ext4 (ro,nosuid,nodev,relatime,seclabel)
core@fc41stab:~$ mount|grep rw,|grep ^/dev
/dev/vda4 on /etc type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,prjquota)
/dev/vda4 on /sysroot/ostree/deploy/fedora-coreos/var type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,prjquota)
/dev/vda4 on /var type xfs (rw,relatime,seclabel,attr2,inode64,logbufs=8,logbsize=32k,prjquota)
Я специально грепнул только реальные устройства, потому что кроме них смонтированы ещё 19 виртуальных, пока в них углубляться не будем. Как видно, в режиме rw
смонтированы /etc и /var. Даже стандартый home это линк /home -> var/home
.
За автоматические обновления отвечает сервис zincati
, если его отключить, обновления можно запускать вручную: rpm-ostree --bypass-driver upgrade
. После рестарта смотрим новое состояние системы:
core@fc41stab:~$ rpm-ostree status
State: idle
AutomaticUpdatesDriver: Zincati
DriverState: active; periodically polling for updates (last checked Tue 2025-03-18 12:22:26 UTC)
Deployments:
● fedora:fedora/x86_64/coreos/stable
Version: 41.20250302.3.2 (2025-03-17T22:11:15Z)
Commit: aa4d65c700789b34bb953c2ee8250c6643802ed57ab1f4f5dd61e821b2be8709
GPGSignature: Valid signature by 466CF2D8B60BC3057AA9453ED0622462E99D6AD1
fedora:fedora/x86_64/coreos/stable
Version: 41.20250215.3.0 (2025-03-04T19:05:12Z)
Commit: d0742b8c6b45095a6e4f856d787a65f4d2702316856d78227f0b68f8f85511b5
GPGSignature: Valid signature by 466CF2D8B60BC3057AA9453ED0622462E99D6AD1
rpm-ostree rollback
позволяет откатить обновления к предыдущему комиту. Другие полезные команды:
- rpm-ostree db diff - список обновлённых пакетов между комитами
- rpm-ostree db list
- список и версии пакетов в комитах
А как же устанавливать пакеты привычным dnf
? - своевременный вопрос. Посмотрим сначала что уже стоит:
core@fc41stab:~/temp$ rpm-ostree db list aa4d65> rpm-ostree.db.list.250317
core@fc41stab:~/temp$ head -1 rpm-ostree.db.list.250317
ostree commit: aa4d65 (aa4d65c700789b34bb953c2ee8250c6643802ed57ab1f4f5dd61e821b2be8709)
core@fc41stab:~/temp$ wc -l rpm-ostree.db.list.250317
440 rpm-ostree.db.list.250317
Это напоминает FreeBSD base, но важно, что этот набор включает podman, docker, git - для остального есть утилита toolbox. Она делает доступными все пакеты федоры, упакованные в контейнер. Заглянем в toolbox:
core@fc41stab:~/temp/tbox$ toolbox
Error: missing command
create Create a new Toolbx container
enter Enter an existing Toolbx container
list List all existing Toolbx containers and images
Run 'toolbox --help' for usage.
core@fc41stab:~/temp/tbox$ toolbox create tbox
Image required to create Toolbx container.
Download registry.fedoraproject.org/fedora-toolbox:41 (384.2MB)? [y/N]: y
Created container: tbox
Enter with: toolbox enter tbox
core@fc41stab:~/temp/tbox$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
registry.fedoraproject.org/fedora-toolbox 41 2288b69816a7 7 hours ago 2.29 GB
core@fc41stab:~/temp/tbox$ toolbox enter tbox
⬢ [core@toolbx tbox]$
Мы оказались внутри контейнера, об это говорит изменившееся приглашение $PS1. Если снова посмотреть mount
, увидим ещё больше и хитрее подмонтированных каталогов, этакий оверлей из базовой и контейнерной ФС. Но зато работает dnf
, можно устанавливать любые пакеты. Добавим привычные, без них неуютно в новой системе:
⬢ [core@toolbx tbox]$ sudo dnf update
Updating and loading repositories:
Fedora 41 openh264 (From Cisco) - x86_64 100% | 7.2 KiB/s | 4.8 KiB | 00m01s
Fedora 41 - x86_64 100% | 16.8 MiB/s | 35.2 MiB | 00m02s
Fedora 41 - x86_64 - Updates 100% | 5.2 MiB/s | 11.7 MiB | 00m02s
Repositories loaded.
Nothing to do.
⬢ [core@toolbx tbox]$ sudo dnf install tmux btop
Как видим, пакеты доступны, но желательно иметь их вне контейнера. Нет проблем, скопируем их в свой ~/bin каталог, он одинаков и внутри, и снаружи контейнера:
⬢ [core@toolbx tbox]$ type tmux
tmux is /usr/bin/tmux
⬢ [core@toolbx tbox]$ mkdir ~/bin
⬢ [core@toolbx tbox]$ cp /usr/bin/tmux ~/bin
⬢ [core@toolbx tbox]$ type btop
btop is /usr/bin/btop
⬢ [core@toolbx tbox]$ cp /usr/bin/btop ~/bin
Выйдем из контейнера и проверим:
⬢ [core@toolbx tbox]$
logout
core@fc41stab:~/temp/tbox$ ldd ~/bin/*
/var/home/core/bin/btop:
linux-vdso.so.1 (0x00007f45e8231000)
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f45e7fc3000)
libm.so.6 => /lib64/libm.so.6 (0x00007f45e7edd000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f45e7eae000)
libc.so.6 => /lib64/libc.so.6 (0x00007f45e7cbb000)
/lib64/ld-linux-x86-64.so.2 (0x00007f45e8233000)
/var/home/core/bin/tmux:
linux-vdso.so.1 (0x00007ff7f2acb000)
libsystemd.so.0 => /lib64/libsystemd.so.0 (0x00007ff7f28c8000)
libutempter.so.0 => /lib64/libutempter.so.0 (0x00007ff7f28c3000)
libtinfo.so.6 => /lib64/libtinfo.so.6 (0x00007ff7f2895000)
libevent_core-2.1.so.7 => /lib64/libevent_core-2.1.so.7 (0x00007ff7f285d000)
libm.so.6 => /lib64/libm.so.6 (0x00007ff7f2777000)
libresolv.so.2 => /lib64/libresolv.so.2 (0x00007ff7f2764000)
libc.so.6 => /lib64/libc.so.6 (0x00007ff7f256f000)
libcap.so.2 => /lib64/libcap.so.2 (0x00007ff7f2562000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007ff7f2533000)
/lib64/ld-linux-x86-64.so.2 (0x00007ff7f2acd000)
Будем считать что знакомство закончено, попробуем что-то посерьёзнее - настроить на fedora core сервер для команды разрабов, для начала полноценный dev env: репозитарий кода, образов контейнеров, инструменты для сборки и сервер приложений.
В команде, как обычно, есть админ, или несколько. Уже созданный пользователь core - это админ, у него есть права судо, ему доступен контейнер tbox. В нашей федоре каталог с секретами устроен особым образом:
core@fc41stab:~$ tree ~/.ssh/
/var/home/core/.ssh/
└── authorized_keys.d
└── ophil
2 directories, 1 file
Первоначально обычный файл authorized_keys назывался ignition и располагался в каталоге ~/.ssh/authorized_keys.d
, что подразумевает, что можно ещё добавить ключей, назвав их никами других админов. Так же можно поступить с разрабами, настроить для всех один dev env.
Создадим нового пользователя без прав судо:
sudo adduser dev;
sudo usermod -aG docker dev
sudo passwd dev
sudo cp -a ~/.ssh/ ~dev/
sudo chown -R dev:dev ~dev/.ssh
Как мы уже знаем, мелкие утилиты можно просто скопировать из тулбокса в ~/bin или /usr/local/bin. Для языков программирования и прочих инструментов есть замечательная программа mise. Сейчас мы её установим для dev и немного познакомимся. Мой ключ уже добавил в ~dev/.ssh/authorized_keys.d/
, так что логинимся и настраиваем инструменты для команды разрабов.
ssh -v dev@fc41stab
dev@fc41stab:~$ id
uid=1001(dev) gid=1001(dev) groups=1001(dev),983(docker) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
dev@fc41stab:~$ curl https://mise.run | sh
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 9557 100 9557 0 0 26211 0 --:--:-- --:--:-- --:--:-- 26255
mise: installing mise...
######################################################################## 100.0%
mise: installed successfully to /var/home/dev/.local/bin/mise
mise: run the following to activate mise in your shell:
echo "eval \"\$(/var/home/dev/.local/bin/mise activate bash)\"" >> ~/.bashrc
mise: run `mise doctor` to verify this is setup correctly
dev@fc41stab:~$ echo "eval \"\$(/var/home/dev/.local/bin/mise activate bash)\"" >> ~/.bashrc
dev@fc41stab:~$ . ~/.bashrc
mise позволяет устанавливать и использовать различные версии языков программирования, инструментов и библиотек. Другие менеджеры версий, например aqua, asdf, ubi - собрали репозитарии таких инструментов, mise их использует в качестве бэкендов. Огласим весь список:
dev@fc41stab:~/src$ mise registry > mise.registry
dev@fc41stab:~/src$ wc -l mise.registry
883 mise.registry
dev@fc41stab:~/src$ mise ls-remote python|tail
3.12.6
3.12.7
3.12.8
3.12.9
3.13.0
3.13-dev
3.13.1
3.13.2
3.14.0a6
3.14-dev
dev@fc41stab:~/src$ mise -v use -g [email protected]
dev@fc41stab:~/src$ mise ls
Tool Version Source Requested
python 3.12.9 ~/.config/mise/config.toml 3.12
Да, список великоват, сохранил в файл, 883 шт., и он постоянно растёт. Это только названия пакетов, поиск версий, команда mise ls-remote python
, выдала 911 вариантов для python.
Теперь можно настраивать пайплайны для наших разработчиков.