Библиотека девопса | DevOps, SRE, Sysadmin
Все самое полезное для девопсера в одном канале. Наши курсы: https://clc.to/ZJ7Z1w По рекламе: @proglib_adv Для обратной связи: @proglibrary_feeedback_bot РКН: https://gosuslugi.ru/snet/6798b4e4509aba56522d1787
Mostrar más📈 Análisis del canal de Telegram Библиотека девопса | DevOps, SRE, Sysadmin
El canal Библиотека девопса | DevOps, SRE, Sysadmin (@devopsslib) en el segmento lingüístico de Ruso es un actor destacado. Actualmente la comunidad reúne a 10 393 suscriptores, ocupando la posición 11 449 en la categoría Tecnologías y Aplicaciones y el puesto 61 235 en la región Rusia.
📊 Métricas de audiencia y dinámica
Desde su creación el невідомо, el proyecto ha mostrado un crecimiento acelerado, reuniendo a 10 393 suscriptores.
Según los últimos datos del 27 agosto, 2026, el canal mantiene una actividad estable. En los últimos 30 días la variación de miembros fue de 6, y en las últimas 24 horas de 0, conservando un alto alcance.
- Estado de verificación: No verificado
- Tasa de interacción (ER): El promedio de interacción de la audiencia es 10.22%. Durante las primeras 24 horas tras publicar, el contenido suele obtener 4.22% de reacciones respecto al total de suscriptores.
- Alcance de las publicaciones: Cada publicación recibe en promedio 1 062 visualizaciones. En el primer día suele acumular 439 visualizaciones.
- Reacciones e interacción: La audiencia responde de forma activa: el promedio de reacciones por publicación es 1.
- Intereses temáticos: El contenido se centra en temas clave como devops'a, навигация, скрипт, docker, git.
📝 Descripción y política de contenido
El autor describe el recurso como un espacio para expresar opiniones subjetivas:
“Все самое полезное для девопсера в одном канале.
Наши курсы: https://clc.to/ZJ7Z1w
По рекламе: @proglib_adv
Для обратной связи: @proglibrary_feeedback_bot
РКН: https://gosuslugi.ru/snet/6798b4e4509aba56522d1787”
Gracias a la alta frecuencia de actualizaciones (últimos datos recibidos el 28 agosto, 2026), el canal mantiene la vigencia y un amplio alcance. La analítica demuestra que la audiencia interactúa activamente con el contenido, lo que lo convierte en un punto de referencia dentro de la categoría Tecnologías y Aplicaciones.
winpodx предлагает другой путь — запустить Windows-приложение прямо из меню рабочего стола, как обычную Linux-программу.
Что это такое
winpodx поднимает Windows-контейнер через Podman или Docker на базе и пробрасывает приложения на рабочий стол через FreeRDP. Каждое приложение открывается в отдельном окне без полного десктопа Windows. Написан на Python 3.11+, без внешних зависимостей.
Проект молодой: первый релиз v0.1.0 вышел в апреле 2026 года.
Что умеет
Из коробки поддерживаются 14 приложений: встроенные в Windows (Notepad, Explorer, Paint, PowerShell) и те, что нужно установить вручную (Word, Excel, PowerPoint, VS Code, Teams). Можно добавить любое своё приложение через TOML-конфиг.
Помимо базового запуска:
• Буфер обмена и звук работают по умолчанию через RDP.
• USB-накопители монтируются автоматически: подключаете флешку на Linux, PowerShell-скрипт на стороне Windows присваивает ей букву диска.
• HiDPI определяется сам, поддерживаются GNOME, KDE, Sway, Hyprland, Cinnamon.
• Контейнер паузится при простое и возобновляется при следующем запуске.
• Каждые 7 дней RDP-пароль меняется автоматически.
• Qt6-трей для управления контейнером прямо из панели задач.
Как установить:
git clone https://github.com/kernalix7/winpodx.git
cd winpodx
./install.sh
Скрипт сам определит дистрибутив и установит нужные зависимости с подтверждением перед каждым шагом. После этого все 14 приложений появятся в меню рабочего стола.
Как запустить:
winpodx app run word # открыть Word
winpodx app run word ~/doc.docx # открыть конкретный файл
winpodx app run desktop # полный десктоп Windows
При первом запуске winpodx сам сгенерирует конфиг, поднимет контейнер и настроит RDP. Ничего делать вручную не нужно.
Добавить своё приложение:
mkdir -p data/apps/myapp
cat > data/apps/myapp/app.toml << 'EOF'
name = "myapp"
full_name = "My Application"
executable = "C:\\Program Files\\MyApp\\myapp.exe"
categories = ["Utility"]
mime_types = []
EOF
winpodx app install myapp
Конфигурация
Файл живёт в ~/.config/winpodx/winpodx.toml с правами 0600. Основные параметры:
[rdp]
scale = 100 # масштаб, определяется автоматически
password_max_age = 7 # дней до ротации пароля
[pod]
backend = "podman"
win_version = "11" # 11 | 10 | ltsc10 | tiny11 | tiny10
cpu_cores = 4
ram_gb = 4
idle_timeout = 0 # секунды до автоприостановки, 0 = выкл.
winpodx делает то же, что winapps и LinOffice, но идёт дальше: нулевая ручная настройка, поддержка любых приложений (не только Office), автоматическая ротация пароля, работа с USB и звуком из коробки.
➡️ Репозиторий
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека devops'a
#арсенал_инженераmemory.min (жёсткая защита, ядро не тронет эту память ни при каких условиях) и memory.low (мягкая защита, ядро постарается не трогать, но может при крайней нехватке). Memory QoS использует оба.
Как это работает в v1.36
Политика называется TieredReservation и работает так.
• Guaranteed-поды получают memory.min, равный requests. Ядро гарантирует эту память безусловно.
• Burstable-поды получают memory.low, равный requests. Ядро постарается сохранить эту память, но при сильном давлении может забрать.
• BestEffort-поды не получают никакой защиты.
Дополнительно для Burstable-подов kubelet выставляет memory.high — порог, при превышении которого начинается троттлинг. Считается по формуле:
memory.high = requests + 0.9 * (limits - requests)Это даёт 10% «буфер» до жёсткого лимита
memory.max, чтобы под не уходил в OOM kill резко.
Как включить
Функция находится в alpha и по умолчанию выключена. Включается через feature gate в конфигурации kubelet:
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
featureGates:
MemoryQoS: true
Дополнительно можно настроить политику резервирования через параметр memoryReservationPolicy. Если хотите отключить memory.min без отключения всей фичи — ставите Disabled. Если хотите убрать ранний троттлинг — memoryThrottlingFactor: 1.0.
Требования
Нужны Linux с cgroup v2 и ядро версии 5.9 или выше. На более старых ядрах есть баг: когда под упирается в memory.high, процесс зависает вместо того, чтобы двигаться к OOM kill. В v1.36 kubelet логирует предупреждение при старте, если ядро старше 5.9 и фича включена.
Поддержка со стороны CRI-рантайма тоже обязательна. Сейчас это containerd и CRI-O.
Что изменилось по сравнению с предыдущими версиями
В v1.27 была попытка перевести фичу в beta, но её заблокировал именно тот баг с livelock на старых ядрах. В v1.36 добавили метрики на уровне ноды, механизм отката (rollback reconciliation) и возможность тонкой настройки. Логика выставления memory.min тоже поправлена: раньше при requests = 0 memory.min мог выставляться некорректно, теперь сбрасывается в 0 явно.
➡️ Блог k8s
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека devops'a
#арсенал_инженераЧто такое архитектура «ничего общего»➡️ Как ответить на собесе 📍 Навигация: Вакансии • Задачи • Собесы 🐸 Библиотека devops'a #задача_со_звёздочкой
Проблема не в Git как таком. Инфраструктура вокруг него — issues, pull requests, Actions — стала нестабильной настолько, что мешает нормально делать работу каждый день.➡️ Источник 📍 Навигация: Вакансии • Задачи • Собесы 🐸 Библиотека devops'a #пульс_индустрии
AF_ALG — сокет, который открывает доступ к криптоподсистеме для любого пользователя без прав. splice() — системный вызов, который передаёт данные между файловыми дескрипторами без копирования, напрямую через ссылки на страницы кеша страниц. И authencesn — AEAD-шаблон для IPsec с поддержкой 64-битных порядковых номеров.
В 2017 году в algif_aead.c добавили оптимизацию: операции AEAD стали выполняться in-place, то есть req->src и req->dst указывают на один и тот же scatterlist. Когда пользователь через splice() подаёт файл в AF\_ALG сокет, страницы с кэшем страниц этого файла попадают прямо в записываемый scatterlist.
authencesn при расшифровании использует буфер назначения как временное хранилище для перестановки байт ESN. Конкретно — пишет 4 байта по смещению dst[assoclen + cryptlen], то есть за пределами легитимного буфера вывода. Эти байты он никогда не восстанавливает.
В итоге scatterwalk_map_and_copy доходит до страниц кэша страниц целевого файла и пишет туда 4 байта, которые контролирует атакующий. Операция возвращает ошибку (контрольная сумма не сходится — данные подделаны), но запись в кэш страниц уже произошла.
Что контролирует атакующий
Три параметра полностью в руках атакующего:
Первый — какой файл. Любой файл, доступный для чтения текущему пользователю.
Второй — какое смещение. Через параметры splice() и assoclen можно выбрать конкретные 4 байта внутри кэша страниц нужного файла.
Третий — какое значение. Записываемые байты берутся из байт 4–7 AAD, которые атакующий формирует сам через sendmsg().
Как выглядит эксплойт
Цель по умолчанию — /usr/bin/su, исполняемый файл с битом смены идентификатора пользователя, который есть на всех основных дистрибутивах:
a = socket.socket(38, 5, 0) # AF_ALG, SOCK_SEQPACKET
a.bind(("aead", "authencesn(hmac(sha256),cbc(aes))"))
# ... установить ключ, принять request socket u ...
u.sendmsg([b"A"*4 + payload_chunk], [cmsg_headers], MSG_MORE)
os.splice(target_fd, pipe_wr, offset)
os.splice(pipe_rd, alg_fd, offset)
u.recv(...) # вызывает decrypt → запись в page cache
Скрипт итерируется по 4-байтовым чанкам шелл-кода, записывает их в кэш страниц /usr/bin/su. Затем execve("/usr/bin/su") — ядро читает бинарь из кэша, запускает инжектированный код с UID 0.
Как закрыть
Патч убирает оптимизацию 2017 года и возвращает out-of-place операции для AEAD в algif_aead.c. Теперь req->src указывает на TX SGL, req->dst на RX SGL. Страницы page cache больше не попадают в записываемый scatterlist.
Для немедленного отключения вектора атаки, до обновления ядра, можно заблокировать модуль:
echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif-aead.conf
rmmod algif_aead 2>/dev/null
Уязвимость существовала почти десять лет. Каждое из трёх изменений 2011, 2015 и 2017 годов было разумным по отдельности. Проблема возникла на их пересечении, и никто не связал их вместе.
Найдена уязвимость с помощью AI-инструмента Xint Code: исследователь сформулировал поверхность атаки, инструмент за час проанализировал криптоподсистему и выдал CVE-2026-31431 как наиболее критичную находку.
➡️ Источник
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека devops'a
#разбор_полётовreact-waiting-game — React-компонент с пятью встроенными аркадными играми для экранов ожидания.
Что это
Библиотека без внешних зависимостей. Все игры нарисованы в стиле 1-bit pixel art на одном canvas. Управление одной кнопкой — клавиатура, мышь и тач работают одинаково. Компонент SSR-safe и сам ставится на паузу, если вкладка скрыта.
Пять игр на выбор:
- jellyfish — медуза плывёт вверх пока держишь кнопку, тонет когда отпускаешь
- runner — прыжки через кактусы и уклонение от птиц
- gravity — инверсия гравитации между шипами на полу и потолке
- invaders — авто-стрельба вправо, переключение между рядами нажатием
- rhythm — ноты летят в зону попадания, короткий тап или удержание в ритм
Все пять поддерживают комбо-множитель, бонус за near-miss, три пауэр-апа и пять достижений каждая.
Как использовать
Установка:
npm install react-waiting-game
Базовый пример:
import { WaitingArcade } from 'react-waiting-game';
function LoadingScreen() {
return <WaitingArcade game="runner" autoStart />;
}
Пример с LLM-запросом, игра появляется пока идёт ответ и исчезает когда он пришёл:
import { useState } from 'react';
import { WaitingArcade } from 'react-waiting-game';
function Chat() {
const [loading, setLoading] = useState(false);
async function ask() {
setLoading(true);
await fetch('/api/chat', { method: 'POST', body: '...' });
setLoading(false);
}
return (
<div>
<button onClick={ask} disabled={loading}>Ask</button>
{loading && (
<WaitingArcade
game="runner"
autoStart
persistHighScore
persistAchievements
/>
)}
</div>
);
}
Пропс paused позволяет поставить игру на паузу снаружи — удобно именно в тот момент, когда ответ пришёл и нужно переключить внимание пользователя.
Настройки
Цвет всего элемента меняется одним пропсом color. Скины переключаются через skin — у каждой игры свои варианты, например ninja или frog для runner, octopus для jellyfish. Лучший счёт и достижения сохраняются в localStorage если передать persistHighScore и persistAchievements.
Пример:
<WaitingArcade
game="jellyfish"
skin="octopus"
color="#4f46e5"
persistHighScore
persistAchievements
onGameOver={(score) => console.log('score:', score)}
/>
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека devops'a
#пульс_индустрииMutablePodResourcesForSuspendedJobs перешла в бету и включена по умолчанию. Теперь можно менять CPU, память, GPU и другие ресурсы контейнеров прямо в шаблоне пода у приостановленного Job, без пересоздания.
Какую проблему это решает
Batch-задачи и ML-обучение часто запускаются через очереди — Kueue и подобные контроллеры. Очередь может решить, что Job нужно запустить с другим количеством GPU или памяти, исходя из текущей загрузки кластера. Раньше так не получалось: ресурсы в шаблоне пода были неизменяемы после создания Job. Единственный выход — удалить джобу и создать заново, теряя историю, статусы и метаданные.
Теперь это работает нативно: приостановил Job, поменял ресурсы, возобновил.
Как это работает
Фича снимает ограничение на изменение полей ресурсов в pod template, но только пока Job находится в состоянии suspend: true и у него нет активных подов (status.active == 0). Все остальные правила валидации остаются в силе: лимиты не могут быть меньше реквестов, extended resources указываются целыми числами.
Пример Job с изменёнными ресурсами перед запуском:
apiVersion: batch/v1
kind: Job
metadata:
name: training-job-example-abcd123
spec:
suspend: true
template:
spec:
containers:
- name: trainer
image: example-registry.example.com/training:2026-04-23T150405.678
resources:
requests:
cpu: "4"
memory: "16Gi"
example-hardware-vendor.com/gpu: "2"
limits:
cpu: "4"
memory: "16Gi"
example-hardware-vendor.com/gpu: "2"
restartPolicy: Never
Очередь меняет блок resources, затем снимает spec.suspend: false, и новые поды стартуют уже с обновлёнными ресурсами.
Что важно учесть
Если Job уже запускался и был приостановлен, нужно дождаться завершения всех активных подов. API-сервер отклонит изменения, пока status.active > 0.
Если у Job могут быть упавшие поды, стоит выставить podReplacementPolicy: Failed. Это гарантирует, что замещающие поды создадутся только после полного завершения предыдущих и не будет конкуренции за ресурсы.
Dynamic Resource Allocation (DRA) не затронут. resourceClaimTemplates остаются неизменяемыми. Если воркload использует DRA, claim templates нужно пересоздавать отдельно.
Как включить
В v1.36 фича работает без дополнительной конфигурации. На v1.35 нужно явно включить feature gate на kube-apiserver:
--feature-gates=MutablePodResourcesForSuspendedJobs=true➡️ Блог разработчиков 📍 Навигация: Вакансии • Задачи • Собесы 🐸 Библиотека devops'a #арсенал_инженера
Plasma 6.7 появится возможность снова перетаскивать приложения в виджете Quick Launch. Виджет Audio Volume будет корректно определять новое аудиоустройство при подключении.
Также в Kirigami добавили компонент Badge, который теперь используется в разных приложениях Plasma для единообразного оформления. Страницы приложений в Discover обновили, System Monitor теперь различает GPU по именам, а не номерам. В меню Kicker начали подсвечивать недавно установленные приложения.
➡️ Источник
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека devops'a
#пульс_индустрииinferno64 это форк, который переносит систему на amd64 и arm64.
Что это такое
Программы для Inferno пишутся на языке Limbo — конкурентном языке с поддержкой CSP-каналов. Код компилируется в байт-код Dis, который исполняется на виртуальной машине emu. Это значит, что один и тот же код работает везде, где есть эмулятор.
Вся работа с ресурсами в Inferno идёт через файловую иерархию. Сеть, устройства, сервисы — всё открывается через обычные операции open, read, write, close. Протокол для этого тот же, что и в Plan 9 — 9P. Любой ресурс можно экспортировать по сети и подключить к пространству имён другого процесса.
Чем inferno64 отличается от оригинала
Форк фокусируется на трёх вещах: поддержка 64-битных платформ, работа JIT-компилятора для amd64 и байндинги к популярным библиотекам вроде SQLite. JIT для arm64 пока в разработке. Важный момент: dis-файлы из 64-битной версии несовместимы с оригинальным 32-битным dis.
Как собрать на Linux
Устанавливаем зависимости:
apt install libx11-dev libxext-dev linux-libc-dev
Собираем из корня репозитория:
export ROOT=<путь до inferno64>
export objtype=amd64
export PATH=$PATH:$ROOT/Linux/$objtype/bin
./makemk.sh
mk mkdirs
mk install
После сборки в Linux/amd64/bin появятся бинарники mk, iyacc, limbo и emu, а также весь скомпилированный dis-код. Запускаем эмулятор:
emu ; wm/wm&Пахнет ли здесь ИИ? Возможно, но даже так это отличный форк. Делайте своих ИИ-агентов на нашем курсе и переписывайте старое ПО на новый лад. Осталось всего 4 места. Набор закрывается 30 апреля. 🔗 Успеть на обучение ➡️ Репозиторий 📍 Навигация: Вакансии • Задачи • Собесы 🐸 Библиотека devops'a #пульс_индустрии
helm repo add nixys https://registry.nixys.io/chartrepo/public
helm install my-release nixys/nxs-universal-chart -f values.yaml
Минимальный values.yaml для деплоя веб-приложения выглядит так:
deployments:
app:
containers:
app:
image: nginx
tag: stable
ports:
- containerPort: 80
services:
app:
ports:
- port: 80
targetPort: 80
Если у вас в кластере больше пяти похожих сервисов, а поддержка отдельных чартов начинает утомлять — стоит посмотреть.
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека devops'a
#пульс_индустрииКак эффективно управлять контекстным окном LLM в мультиагентных системах и не сливать бюджет на токеныЖдем вас сегодня в 19:00 по московскому времени. Не пропустите начало, будет много практики! 👉 Успей занять место
\Processor(_Total)\% Processor Time \System\Processor Queue Length \Hyper-V Hypervisor Virtual Processor(*)\CPU Wait Time Per DispatchНагрузку создавал через PowerShell внутри VM:
1..8 | ForEach-Object {
while ($true) { Get-Process | Sort-Object CPU -Descending | Select-Object -First 5 | Out-Null }
}
На Snapdragon % Processor Time почти не колебался, Processor Queue Length держался на нуле, CPU Wait Time Per Dispatch был ровным. На Intel все три метрики давали заметные всплески.
Затем он прогнал Measure-Command на реальных операциях прямо внутри VM. Для IIS:
Measure-Command { 1..1000 | foreach { Invoke-WebRequest http://localhost -UseBasicParsing | Out-Null } }
Аналогично для DNS:
Resolve-DnsName "domainX.com" -Server 127.0.0.1 | Out-Null
Для Active Directory:
Get-ADUser -Filter * -ResultSetSize 1 | Out-Null
Для файлового I/O:
$path = "C:\TestFiles"
mkdir $path -ea 0
Measure-Command {
1..2000 | foreach {
$file = "$path\file$_.txt"
Set-Content $file "test"
Get-Content $file | Out-Null
Remove-Item $file
}
}
По всем тестам Snapdragon давал стабильный результат от прогона к прогону. Intel иногда обходил его в пике, но в среднем проигрывал.
Что с этим делать
Делайте своих ИИ-агентов. У нас как раз есть курс, но на него осталось всего 4 места. Успейте до 30 апреля!
👉 Регистрация здесь
➡️ Оригинал статьи
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека devops'a
#локализацияgit history
Появилась новая команда для переписывания истории. Пока экспериментальная, но уже умеет делать split — разбивать коммиты. Детали пока скудные, но команда явно будет развиваться.
git replay стал умнее
git replay теперь умеет три режима: pick, replay и новый revert. Плюс он научился пропускать коммиты, которые становятся пустыми после replay, и поддерживает replay вплоть до корневого коммита.
Хуки теперь можно настраивать в конфиге
Раньше хук — это скрипт в .git/hooks/. Теперь хуки можно определять прямо в конфигурации Git, в том числе централизованно. И запускать несколько хуков на одно событие. Это открывает нормальную возможность шарить хуки между командой без сторонних инструментов вроде husky.
git add -p стал удобнее
Два улучшения сразу: теперь видно текущий статус показываемого куска, и можно вернуться к файлу, который уже обработали. Для тех, кто активно использует интерактивное добавление, это заметное улучшение.
git status теперь сравнивает с несколькими ветками
Через конфиг status.compareBranches можно указать список веток, с которыми git status будет показывать сравнение. Удобно, если работаете с несколькими долгоживущими ветками одновременно.
git rebase получил --trailer
Новая опция позволяет добавлять трейлеры к коммитам прямо в процессе rebase. Больше не нужно делать это отдельным шагом через git interpret-trailers.
Исправления, которые стоит знать
git blame --ignore-revs с --color-lines давал неверную раскраску для соседних строк в одном коммите — починили. git log --graph --stat неправильно считал ширину цветного графика — тоже исправлено. git diff --stat путался с шириной путей, содержащих не-ASCII символы, — исправлено.
git maintenance меняет стратегию по умолчанию
Теперь по умолчанию используется стратегия geometric вместо прежней. Это влияет на то, как Git управляет packfile-ами в фоне. Если настраивали git maintenance вручную, стоит проверить, не изменилось ли поведение.
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека devops'a
#пульс_индустрииholos решает именно эту проблему. Он берёт синтаксис, знакомый по docker compose, и применяет его к настоящим виртуальным машинам на KVM/QEMU без libvirt, без XML, без сетевых мостов с root-доступом.
Что он делает
Вы описываете стек в holos.yaml. Каждый сервис — это ВМ со своим образом, ресурсами и cloud-init-конфигом. Поддерживаются зависимости между сервисами, проброс портов, монтирование директорий, реплики и healthcheck.
Пример:
name: my-stack
services:
db:
image: ubuntu:noble
vm:
vcpu: 2
memory_mb: 1024
cloud_init:
packages:
- postgresql
runcmd:
- systemctl enable postgresql
- systemctl start postgresql
web:
image: ubuntu:noble
replicas: 2
depends_on:
- db
ports:
- "8080:80"
cloud_init:
packages:
- nginx
runcmd:
- systemctl restart nginx
Затем одна команда:
holos up
И у вас работают две ВМ с nginx и одна с PostgreSQL, все видят друг друга по имени сервиса.
Как это работает внутри
Каждая ВМ получает два сетевых интерфейса: user-mode для проброса портов с хоста и socket multicast для L2-связи между машинами. Статические IP назначаются автоматически в подсети 10.10.0.0/24, а /etc/hosts прописывается через cloud-init. Ничего настраивать вручную не нужно.
Для хранения данных между перезапусками есть named volumes, они живут как qcow2-файлы и не удаляются при holos down.
volumes:
pgdata:
size: 20G
services:
db:
image: ubuntu:noble
volumes:
- pgdata:/var/lib/postgresql
Внутри гостевой системы том появляется как /dev/disk/by-id/virtio-vol-pgdata. cloud-init сам создаёт файловую систему и прописывает /etc/fstab при первом запуске.
Основные команды:
holos up # запустить стек
holos down # остановить и удалить
holos ps # список запущенных проектов
holos exec web-0 # SSH в инстанс
holos logs web # логи сервиса
holos install --enable # автозапуск через systemd после ребута
Для SSH holos генерирует пару ключей для каждого проекта и инжектирует публичный ключ через cloud-init. Порт пробрасывается автоматически.
Поддержка GPU passthrough
Если нужно отдать физическую видеокарту виртуальной машине:
services:
ml:
image: ubuntu:noble
vm:
vcpu: 8
memory_mb: 16384
devices:
- pci: "01:00.0"
- pci: "01:00.1"
holos сам включает UEFI (OVMF), выставляет kernel-irqchip=on для совместимости с NVIDIA и создаёт отдельное хранилище EFI-переменных для каждого инстанса. Настройку IOMMU и привязку GPU к vfio-pci нужно сделать на хосте самостоятельно — holos devices --gpu поможет найти PCI-адреса.
Что нужно на хосте
/dev/kvm, qemu-system-x86_64, qemu-img и любой из инструментов для создания cloud-init ISO: cloud-localds, genisoimage, mkisofs или xorriso.
holos это не замена Kubernetes. Он не умеет в кластеры, live migration и service mesh. Его задача — сделать KVM удобным для одного хоста без операционной сложности оркестраторов. Если вам нужен воспроизводимый стек из нескольких ВМ на одной машине, это рабочий вариант.
➡️ Репозиторий
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека devops'a
#арсенал_инженера