🛠️ Идемпотентность API — как защитить систему от дубликатов запросов?
Представьте ситуацию: пользователь в мобильном приложении нажимает кнопку «Оплатить заказ». Клик улетает на бэкенд, списываются деньги, но в этот самый момент на телефоне на секунду пропадает связь. Приложение не получает ответ от сервера, считает, что произошел сбой, и автоматически отправляет запрос повторно. Если ваш бэкенд не обладает свойством идемпотентности, у пользователя спишутся деньги дважды.
Идемпотентность в программировании — это свойство метода или всей системы выдавать один и тот же результат при многократных идентичных запросах. Сколько бы раз вы ни отправили один и тот же запрос, состояние системы изменится только один раз, а все последующие ответы будут точной копией первого успешного ответа.
В стандартном REST API некоторые HTTP-методы идемпотентны по определению:
— GET: сколько раз ни запрашивай профиль пользователя, он не изменится.
— PUT / DELETE: если вы обновили имя на конкретное значение или удалили пост с
— POST: не идемпотентен. Каждый новый вызов по умолчанию пытается создать новую запись в базе данных. Именно с ним и возникают проблемы при дублировании сетевых пакетов.
Как это правильно реализовать на практике:
Самый надежный способ защитить неидемпотентные операции (например, создание транзакции или отправку сообщения) — использование специального ключа идемпотентности (
— Генерация ключа: Перед отправкой POST-запроса фронтенд (или клиент) генерирует уникальный UUID для этой операции и прикрепляет его в заголовки:
— Проверка на бэкенде: Когда запрос приходит на сервер, бэкенд первым в цепочке (например, через Middleware) проверяет, есть ли такой ключ в быстром кэше (идеально подходит Redis со временем жизни ключа в 24 часа).
— Если ключа нет: Сервер понимает, что это уникальный запрос. Он сохраняет ключ в Redis со статусом «в обработке» (
— Если ключ уже есть: Сервер видит, что этот запрос дубликат. Если статус еще «в обработке», он просит клиента подождать. Если статус «выполнено» — сервер просто берет готовый ответ из Redis и возвращает его клиенту, вообще не трогая основную базу данных и не выполняя код повторно.
Зачем это инженеру? Это критически важный стандарт при работе с любыми финансовыми шлюзами, внешними интеграциями и распределенными системами. Сетевые сбои, повторные нажатия кнопок пользователями или автоматические ретраи (retries) в очередях задач — обычное дело для продакшена.
Реализация идемпотентности гарантирует предсказуемость и стабильность данных. Вы можете спать спокойно, зная, что даже при сотне одинаковых сетевых запросов система отработает ровно один раз, сохранив целостность базы данных и нервы ваших пользователей.
🚪 Bash Ready | #практика
Представьте ситуацию: пользователь в мобильном приложении нажимает кнопку «Оплатить заказ». Клик улетает на бэкенд, списываются деньги, но в этот самый момент на телефоне на секунду пропадает связь. Приложение не получает ответ от сервера, считает, что произошел сбой, и автоматически отправляет запрос повторно. Если ваш бэкенд не обладает свойством идемпотентности, у пользователя спишутся деньги дважды.
Идемпотентность в программировании — это свойство метода или всей системы выдавать один и тот же результат при многократных идентичных запросах. Сколько бы раз вы ни отправили один и тот же запрос, состояние системы изменится только один раз, а все последующие ответы будут точной копией первого успешного ответа.
В стандартном REST API некоторые HTTP-методы идемпотентны по определению:
— GET: сколько раз ни запрашивай профиль пользователя, он не изменится.
— PUT / DELETE: если вы обновили имя на конкретное значение или удалили пост с
id=5, повторные вызовы дадут тот же результат (пост останется удаленным).— POST: не идемпотентен. Каждый новый вызов по умолчанию пытается создать новую запись в базе данных. Именно с ним и возникают проблемы при дублировании сетевых пакетов.
Как это правильно реализовать на практике:
Самый надежный способ защитить неидемпотентные операции (например, создание транзакции или отправку сообщения) — использование специального ключа идемпотентности (
Idempotency-Key).— Генерация ключа: Перед отправкой POST-запроса фронтенд (или клиент) генерирует уникальный UUID для этой операции и прикрепляет его в заголовки:
Idempotency-Key: 7b9e84b2-a42e-4e1b-b461-9f9361ad2a48.— Проверка на бэкенде: Когда запрос приходит на сервер, бэкенд первым в цепочке (например, через Middleware) проверяет, есть ли такой ключ в быстром кэше (идеально подходит Redis со временем жизни ключа в 24 часа).
— Если ключа нет: Сервер понимает, что это уникальный запрос. Он сохраняет ключ в Redis со статусом «в обработке» (
In Progress) и начинает выполнять код. После успешного завершения статус меняется на «выполнено» (Completed), а рядом сохраняется тело ответа (Response Body).— Если ключ уже есть: Сервер видит, что этот запрос дубликат. Если статус еще «в обработке», он просит клиента подождать. Если статус «выполнено» — сервер просто берет готовый ответ из Redis и возвращает его клиенту, вообще не трогая основную базу данных и не выполняя код повторно.
Зачем это инженеру? Это критически важный стандарт при работе с любыми финансовыми шлюзами, внешними интеграциями и распределенными системами. Сетевые сбои, повторные нажатия кнопок пользователями или автоматические ретраи (retries) в очередях задач — обычное дело для продакшена.
Реализация идемпотентности гарантирует предсказуемость и стабильность данных. Вы можете спать спокойно, зная, что даже при сотне одинаковых сетевых запросов система отработает ровно один раз, сохранив целостность базы данных и нервы ваших пользователей.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3❤1
🔄 Пул соединений (Connection Pool) — как не положить базу данных при нагрузке
Когда ваш Python-скрипт или веб-сервер делает запрос к базе данных (PostgreSQL, MySQL), под капотом происходит сложный процесс: приложение стучится к серверу базы по сети, проходит авторизацию, открывает сетевой сокет, выполняет SQL-запрос и закрывает соединение. Если на каждый клик пользователя открывать новое соединение с нуля, сервер моментально захлебнется. Решение этой проблемы — Connection Pool.
Открытие нового соединения — это одна из самых «дорогих» и медленных операций в работе с базами данных. Приложении тратит драгоценное время процессора и сети еще до того, как выполнит сам SQL-код.
Пул соединений работает по принципу кэширования: при старте приложения создается фиксированное количество готовых, уже авторизованных сетевых подключений к базе (например, 10–20 штук), которые удерживаются в памяти в активном состоянии.
Как устроен жизненный цикл запроса с Connection Pool:
— Запрос к базе: Когда вашему коду нужно вытянуть данные, он не создает новое подключение, а просит пул выдать одно из свободных.
— Выполнение кода: Приложение мгновенно получает готовый сокет, выполняет SQL-запрос и забирает результат.
— Возврат в пул: Вместо закрытия соединения (
Зачем это инженеру? Чтобы защитить базу от падения и ускорить приложение в разы. У любой СУБД (например, PostgreSQL) есть жесткий лимит на максимальное количество одновременных подключений (
В экосистеме Python при работе с асинхронным бэкендом (FastAPI / SQLAlchemy) пул соединений настраивается автоматически прямо при создании движка (Engine).
Пример настройки пула в SQLAlchemy:
Если ваше приложение разрастается на несколько серверов или Docker-контейнеров, локального пула внутри кода может не хватить (ведь каждый контейнер заберет себе по 20 подключений, и лимит базы снова исчерпается). В таких масштабах перед PostgreSQL ставят специализированные внешние прокси-пулеры — PgBouncer или Odyssey, которые умеют эффективно делить подключения между тысячами независимых процессов.
Использование Connection Pool превращает хаотичные сетевые запросы в упорядоченный, предсказуемый поток данных, снижая нагрузку на сервер и обеспечивая стабильную работу проекта даже в моменты жесткого хабраэффекта.
🚪 Bash Ready | #практика
Когда ваш Python-скрипт или веб-сервер делает запрос к базе данных (PostgreSQL, MySQL), под капотом происходит сложный процесс: приложение стучится к серверу базы по сети, проходит авторизацию, открывает сетевой сокет, выполняет SQL-запрос и закрывает соединение. Если на каждый клик пользователя открывать новое соединение с нуля, сервер моментально захлебнется. Решение этой проблемы — Connection Pool.
Открытие нового соединения — это одна из самых «дорогих» и медленных операций в работе с базами данных. Приложении тратит драгоценное время процессора и сети еще до того, как выполнит сам SQL-код.
Пул соединений работает по принципу кэширования: при старте приложения создается фиксированное количество готовых, уже авторизованных сетевых подключений к базе (например, 10–20 штук), которые удерживаются в памяти в активном состоянии.
Как устроен жизненный цикл запроса с Connection Pool:
— Запрос к базе: Когда вашему коду нужно вытянуть данные, он не создает новое подключение, а просит пул выдать одно из свободных.
— Выполнение кода: Приложение мгновенно получает готовый сокет, выполняет SQL-запрос и забирает результат.
— Возврат в пул: Вместо закрытия соединения (
connection.close()), код просто возвращает его обратно в пул. Оно остается открытым и ждет следующего пользователя.Зачем это инженеру? Чтобы защитить базу от падения и ускорить приложение в разы. У любой СУБД (например, PostgreSQL) есть жесткий лимит на максимальное количество одновременных подключений (
max_connections). Если 500 пользователей одновременно зайдут на сайт без пула, база выдаст ошибку Too many connections и сайт упадет. Пул выступает в роли умного диспетчера.В экосистеме Python при работе с асинхронным бэкендом (FastAPI / SQLAlchemy) пул соединений настраивается автоматически прямо при создании движка (Engine).
Пример настройки пула в SQLAlchemy:
from sqlalchemy.ext.asyncio import create_async_engine
DATABASE_URL = "postgresql+asyncpg://user:password@localhost/mydb"
# Настраиваем пул соединений
engine = create_async_engine(
DATABASE_URL,
pool_size=10, # Базовое количество соединений, удерживаемых всегда
max_overflow=20, # Сколько максимум можно создать сверх нормы при пиковой нагрузке
pool_timeout=30, # Сколько секунд ждать свободное соединение из пула, прежде чем выкинуть ошибку
pool_recycle=1800 # Сбрасывать соединения каждые 30 минут, чтобы они не застаивались
)
Если ваше приложение разрастается на несколько серверов или Docker-контейнеров, локального пула внутри кода может не хватить (ведь каждый контейнер заберет себе по 20 подключений, и лимит базы снова исчерпается). В таких масштабах перед PostgreSQL ставят специализированные внешние прокси-пулеры — PgBouncer или Odyssey, которые умеют эффективно делить подключения между тысячами независимых процессов.
Использование Connection Pool превращает хаотичные сетевые запросы в упорядоченный, предсказуемый поток данных, снижая нагрузку на сервер и обеспечивая стабильную работу проекта даже в моменты жесткого хабраэффекта.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
⚙️ Графическое вычисление (GPU) против Центрального процессора (CPU) — когда бэкендеру нужны видеокарты?
Когда речь заходит об ускорении работы скриптов или сервисов, первая мысль разработчика — оптимизировать алгоритм или разложить задачи по ядрам процессора (CPU). Но бывают задачи, где даже самый мощный серверный процессор начинает безбожно тормозить. В этот момент тяжелые вычисления переносят на видеокарты (GPU).
---
CPU (Центральный процессор) — это «мозг» компьютера, спроектированный для решения общих и сложных последовательных задач. У него относительно мало ядер (обычно от 4 до 64), но каждое ядро невероятно мощное, имеет высокую тактовую частоту и огромный кэш. CPU отлично справляется с ветвлением логики (
GPU (Графический процессор) — устроен совершенно иначе. Он создавался для отрисовки графики и работы с 3D, где нужно одновременно просчитывать цвет миллионов пикселей на экране. Для этого вместо нескольких мощных ядер в него упаковали тысячи мелких, простых ядер, работающих параллельно.
Главные отличия в архитектуре вычислений:
— Параллелизм: CPU обрабатывает задачи последовательно (или в несколько мощных потоков). GPU берет массив данных и обрабатывает тысячи элементов одновременно по одной и той же инструкции (архитектура SIMD — *Single Instruction, Multiple Data*).
— Сложность операций: Ядро GPU не умеет эффективно выполнять сложную логику со множеством ветвлений. Его стихия — простая, однотипная математика: умножение матриц и работа с векторами.
Зачем это инженеру? Чтобы понимать, в какой момент архитектуру проекта нужно дополнить видеокартами. Если вы пишете стандартное REST API или парсер — GPU вам ничем не поможет. Но есть три сферы, где без видеокарт проект просто не запустится:
— Искусственный интеллект и Нейросети (AI/ML): Обучение моделей и генерация (будь то текст в LLM или картинки в Stable Diffusion) — это чистая линейная алгебра и гигантские матрицы. На GPU (например, с использованием ядер Nvidia CUDA или Тензорных ядер) эти процессы ускоряются в 100–1000 раз по сравнению с CPU.
— Обработка медиаданных: Сжатие «на лету» потокового видео, кодирование аудио высокого разрешения или рендеринг 3D-сцен на сервере.
— Криптография и Хэширование: Перебор паролей (брутфорс при аудите безопасности) или работа с блокчейн-сетями.
В экосистеме Python для работы с GPU бэкенд-разработчики используют библиотеки вроде PyTorch, TensorFlow или CuPy (аналог NumPy для видеокарт). Они позволяют перенести массив данных из обычной оперативной памяти (RAM) в видеопамять (VRAM) одной командой:
🚪 Bash Ready | #практика
Когда речь заходит об ускорении работы скриптов или сервисов, первая мысль разработчика — оптимизировать алгоритм или разложить задачи по ядрам процессора (CPU). Но бывают задачи, где даже самый мощный серверный процессор начинает безбожно тормозить. В этот момент тяжелые вычисления переносят на видеокарты (GPU).
---
CPU (Центральный процессор) — это «мозг» компьютера, спроектированный для решения общих и сложных последовательных задач. У него относительно мало ядер (обычно от 4 до 64), но каждое ядро невероятно мощное, имеет высокую тактовую частоту и огромный кэш. CPU отлично справляется с ветвлением логики (
if/else), управлением операционной системой, работой баз данных и выполнением стандартного кода вашего приложения.GPU (Графический процессор) — устроен совершенно иначе. Он создавался для отрисовки графики и работы с 3D, где нужно одновременно просчитывать цвет миллионов пикселей на экране. Для этого вместо нескольких мощных ядер в него упаковали тысячи мелких, простых ядер, работающих параллельно.
Главные отличия в архитектуре вычислений:
— Параллелизм: CPU обрабатывает задачи последовательно (или в несколько мощных потоков). GPU берет массив данных и обрабатывает тысячи элементов одновременно по одной и той же инструкции (архитектура SIMD — *Single Instruction, Multiple Data*).
— Сложность операций: Ядро GPU не умеет эффективно выполнять сложную логику со множеством ветвлений. Его стихия — простая, однотипная математика: умножение матриц и работа с векторами.
Зачем это инженеру? Чтобы понимать, в какой момент архитектуру проекта нужно дополнить видеокартами. Если вы пишете стандартное REST API или парсер — GPU вам ничем не поможет. Но есть три сферы, где без видеокарт проект просто не запустится:
— Искусственный интеллект и Нейросети (AI/ML): Обучение моделей и генерация (будь то текст в LLM или картинки в Stable Diffusion) — это чистая линейная алгебра и гигантские матрицы. На GPU (например, с использованием ядер Nvidia CUDA или Тензорных ядер) эти процессы ускоряются в 100–1000 раз по сравнению с CPU.
— Обработка медиаданных: Сжатие «на лету» потокового видео, кодирование аудио высокого разрешения или рендеринг 3D-сцен на сервере.
— Криптография и Хэширование: Перебор паролей (брутфорс при аудите безопасности) или работа с блокчейн-сетями.
В экосистеме Python для работы с GPU бэкенд-разработчики используют библиотеки вроде PyTorch, TensorFlow или CuPy (аналог NumPy для видеокарт). Они позволяют перенести массив данных из обычной оперативной памяти (RAM) в видеопамять (VRAM) одной командой:
import torch
# Проверяем, доступна ли видеокарта от Nvidia
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# Создаем тяжелую матрицу и отправляем её на вычисление в GPU
x = torch.randn(10000, 10000, device=device)
y = torch.randn(10000, 10000, device=device)
# Мгновенное матричное умножение силами ядер видеокарты
result = torch.matmul(x, y)
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤2😁1
Проверка времени отклика сервисов
Когда сервис работает, но пользователи жалуются на медлительность, нужно мерить не аптайм, а отклик. Это легко сделать обычным curl.
▪️ Самый простой замер
Показывает общее время выполнения запроса и быстро понять, тормозит или нет.
▪️ Точнее: только сетевое время
Полезные метрики:
Пример:
▪️ Проверка нескольких сервисов
▪️ Таймаут обязателен
Без таймаута любой мониторинг бесполезен.
Когда сервис работает, но пользователи жалуются на медлительность, нужно мерить не аптайм, а отклик. Это легко сделать обычным curl.
time curl -s https://bashtex.com > /dev/null
Показывает общее время выполнения запроса и быстро понять, тормозит или нет.
curl -s -o /dev/null -w "time_total: %{time_total}\n" https://bashtex.com
Полезные метрики:
time_namelookup
time_connect
time_starttransfer
time_totalПример:
curl -w "DNS:%{time_namelookup} CONNECT:%{time_connect} TTFB:%{time_starttransfer} TOTAL:%{time_total}\n" \
-o /dev/null -s https://bashtex.com
for url in https://a.ru https://b.ru; do
curl -o /dev/null -s -w "$url %{time_total}\n" "$url"
done
curl --connect-timeout 3 --max-time 5 https://bashtex.com
Без таймаута любой мониторинг бесполезен.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍4
This media is not supported in your browser
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7😁1
Руководитель группы продукта «Поиск и Рекомендации» Яндекс Маркета Любовь Горбунова считает, что необходимость в предельно точных формулировках снижается: нейросеть все лучше понимает запросы и в перспективе с ней можно будет общаться как с консультантом в магазине — в свободной форме и с уточнениями по ходу диалога.
Еще один тренд — использование ИИ вместе с VR/AR-технологиями. Уже сейчас такие решения улучшают сценарии виртуальной примерки одежды. А в будущем подход может распространиться и на другие категории, например, на «примерку» мебели в интерьере.
Please open Telegram to view this post
VIEW IN TELEGRAM
В новом исследовании изучили Spotify и выяснили, что 93% нейротреков не набирают даже 1000 прослушиваний.
Авторы называют это music slop. Тысячи композиций заливают пачками в разные жанры, надеясь случайно попасть в рекомендации. Дистрибьюторы почти этому не мешают, а детекторы пока легко обходятся.
А как часто вам попадается в реках нейрохрючево?
• Источник
Please open Telegram to view this post
VIEW IN TELEGRAM
😁5
Поиск забытых .ssh директорий
После чистки пользователей в системе нередко остаются их .ssh-каталоги. Это мусор + потенциальная дыра: старые ключи могут лежать годами.
▪️ Быстрый поиск по системе
Найдет все .ssh, включая:
нестандартные каталоги
▪️ Проверяем, существует ли владелец
Если владелец:
UNKNOWN
или пользователь отсутствует в
то каталог подозрительный.
▪️ Поиск .ssh без пользователя
⚠️ Перед удалением лучше сделать архив
После чистки пользователей в системе нередко остаются их .ssh-каталоги. Это мусор + потенциальная дыра: старые ключи могут лежать годами.
find / -type d -name .ssh 2>/dev/null
Найдет все .ssh, включая:
/home/*/.ssh
/root/.sshнестандартные каталоги
find / -type d -name .ssh -exec stat -c '%U %n' {} \;
Если владелец:
UNKNOWN
или пользователь отсутствует в
/etc/passwdто каталог подозрительный.
while read user path; do
id "$user" &>/dev/null || echo "Лишний: $path"
done < <(find / -type d -name .ssh -exec stat -c '%U %n' {} \;)
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Циклы while vs for - где что правильно
В bash оба цикла нужны, но для разных задач. Путаница между ними - источник проблем.
▪️ for - перебор готового списка. Используй, когда список уже есть.
файлы;
аргументы "$@";
элементы массива.
⚠️ Пример ошибок:
▪️ while - поток данных. Идеален для чтения ввода.
строки с пробелами;
вывод команд;
большие файлы.
⚠️ Частая ошибка:
(цикл в subshell!)
В bash оба цикла нужны, но для разных задач. Путаница между ними - источник проблем.
for f in *.log; do
echo "$f"
done
файлы;
аргументы "$@";
элементы массива.
for f in $(ls *.log); do # ломается на пробелах
while IFS= read -r line; do
echo "$line"
done < file.txt
строки с пробелами;
вывод команд;
большие файлы.
cat file | while read line; do
count=$((count+1)) # переменная пропадёт
done
(цикл в subshell!)
for не является универсальным, а while безопаснее для данных. Перед созданием цикла нужно задавать себе вопрос: список или поток.Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤1
🧠 Быстрый просмотр SSL-сертификата домена
Нужно быстро проверить срок действия SSL-сертификата у удалённого сайта без браузера?
📌 Покажет строки вида:
🔒 Хочешь только дату окончания? Добавь
📦 Убедись, что установлен
💡 Подходит для мониторинга и ручной проверки валидности сертификатов.
Нужно быстро проверить срок действия SSL-сертификата у удалённого сайта без браузера?
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -dates
📌 Покажет строки вида:
notBefore=Jun 1 00:00:00 2024 GMT
notAfter=Aug 30 23:59:59 2024 GMT
🔒 Хочешь только дату окончания? Добавь
| grep notAfter📦 Убедись, что установлен
openssl💡 Подходит для мониторинга и ручной проверки валидности сертификатов.
❤3
KubePlumber проверяет работу сети Kubernetes изнутри кластера, тестируя:
* внутренний DNS,
* трафик между подами,
* внешний DNS,
* пропускную способность между нодами.
➤ https://github.com/David-VTUK/KubePlumber
* внутренний DNS,
* трафик между подами,
* внешний DNS,
* пропускную способность между нодами.
➤ https://github.com/David-VTUK/KubePlumber
This media is not supported in your browser
VIEW IN TELEGRAM
Как обученная AI-модель превращается в production API в Kubernetes?
KServe — это проект CNCF на стадии Incubating для развёртывания и обслуживания AI-моделей в Kubernetes.
Проще говоря, KServe берёт обученную модель и превращает её в масштабируемый inference-сервис в Kubernetes.
Он берёт на себя деплой, сеть, автоскейлинг и health checks модели.
Важно понимать, что KServe уже давно работает не только с классическими ML-моделями.
Как inference-платформа, он поддерживает две категории AI/ML-нагрузок:
- Predictive AI (классический ML): например, модели на scikit-learn, XGBoost, модели, упакованные через MLflow, и другие.
- Generative AI (LLM): например, запуск и обслуживание LLM через backend vLLM с поддержкой GPU.
Если хотите разобраться, как устроена inference-платформа KServe, можно прочитать свежий выпуск MLOps-рассылки.
В нём разбираются:
- Model Servers и runtimes в KServe
- Как KServe разворачивает AI-модели в Kubernetes
- Деплой MLflow-модели в KServe на практике
- Как выкатывать новые версии моделей
- Rolling Updates, Canary, A/B Testing и Shadow Deployments
И многое другое.
Читать здесь: https://newsletter.devopscube.com/p/kserve
KServe — это проект CNCF на стадии Incubating для развёртывания и обслуживания AI-моделей в Kubernetes.
Проще говоря, KServe берёт обученную модель и превращает её в масштабируемый inference-сервис в Kubernetes.
Он берёт на себя деплой, сеть, автоскейлинг и health checks модели.
Важно понимать, что KServe уже давно работает не только с классическими ML-моделями.
Как inference-платформа, он поддерживает две категории AI/ML-нагрузок:
- Predictive AI (классический ML): например, модели на scikit-learn, XGBoost, модели, упакованные через MLflow, и другие.
- Generative AI (LLM): например, запуск и обслуживание LLM через backend vLLM с поддержкой GPU.
Если хотите разобраться, как устроена inference-платформа KServe, можно прочитать свежий выпуск MLOps-рассылки.
В нём разбираются:
- Model Servers и runtimes в KServe
- Как KServe разворачивает AI-модели в Kubernetes
- Деплой MLflow-модели в KServe на практике
- Как выкатывать новые версии моделей
- Rolling Updates, Canary, A/B Testing и Shadow Deployments
И многое другое.
Читать здесь: https://newsletter.devopscube.com/p/kserve
Многие ли знают, что Helm хранит информацию о релизах в Kubernetes Secrets?
Когда вы запускаете
В Secret хранится, например:
- имя релиза;
- статус деплоя;
- применённые манифесты;
- использованные values;
- информация о chart и другие данные.
Данные в Secret сжимаются с помощью gzip, а затем кодируются в base64.
Имя Secret создаётся по следующему шаблону:
Когда вы запускаете
Helm не нужна внешняя база данных.
Вся информация хранится прямо в вашем кластере в виде нативных Kubernetes Secrets.
Примечание: также можно настроить внешнюю SQL-базу данных для хранения релизов, но эта возможность пока находится в beta
Когда вы запускаете
helm install или helm upgrade, Helm сохраняет данные о релизе в K8s Secrets в том же namespace.В Secret хранится, например:
- имя релиза;
- статус деплоя;
- применённые манифесты;
- использованные values;
- информация о chart и другие данные.
Данные в Secret сжимаются с помощью gzip, а затем кодируются в base64.
Имя Secret создаётся по следующему шаблону:
sh.helm.release.v1.[release-name].v[revision]Когда вы запускаете
helm rollback, Helm читает эти Secrets, чтобы восстановить приложение до предыдущей версии.Helm не нужна внешняя база данных.
Вся информация хранится прямо в вашем кластере в виде нативных Kubernetes Secrets.
Примечание: также можно настроить внешнюю SQL-базу данных для хранения релизов, но эта возможность пока находится в beta
❤2
VPN, который просто работает.
RuSolv — подключение за несколько минут, 50+ серверов и современные протоколы для стабильного доступа к интернету.
✓ 10 ГБ каждый месяц бесплатно
✓ Без привязки карты
✓ Без логов
✓ Телефон, компьютер и другие устройства
Попробуйте бесплатно → https://rusolv.com
RuSolv — подключение за несколько минут, 50+ серверов и современные протоколы для стабильного доступа к интернету.
✓ 10 ГБ каждый месяц бесплатно
✓ Без привязки карты
✓ Без логов
✓ Телефон, компьютер и другие устройства
Попробуйте бесплатно → https://rusolv.com
👍2👎1
Kubernetes HPA не ограничивается только CPU и памятью
Ворклоады можно скейлить и по кастомным метрикам, например
- количество запросов в секунду (RPS)
- длина очереди
- количество активных соединений
- latency приложения
Для этого можно использовать связку HPA + Prometheus + Prometheus Adapter.
Prometheus Adapter прокидывает метрики через Kubernetes Custom Metrics API, после чего HPA использует их для автоскейлинга.
Но выбрать метрику — это только часть настройки автоскейлинга. Нужно ещё контролировать, как HPA будет скейлить ворклоад при изменении значений метрики.
В этой рассылке разобрали, как работает HPA tolerance.
Читать здесь:
https://newsletter.devopscube.com/p/kubernetes-hpa-tolerance-levels
Ворклоады можно скейлить и по кастомным метрикам, например
- количество запросов в секунду (RPS)
- длина очереди
- количество активных соединений
- latency приложения
Для этого можно использовать связку HPA + Prometheus + Prometheus Adapter.
Prometheus Adapter прокидывает метрики через Kubernetes Custom Metrics API, после чего HPA использует их для автоскейлинга.
Но выбрать метрику — это только часть настройки автоскейлинга. Нужно ещё контролировать, как HPA будет скейлить ворклоад при изменении значений метрики.
В этой рассылке разобрали, как работает HPA tolerance.
Читать здесь:
https://newsletter.devopscube.com/p/kubernetes-hpa-tolerance-levels
SSH-туннели, или как стать магом сетевой связности
10 практических челленджей, чтобы прокачать port forwarding через SSH-туннели — от простого локального/удалённого проброса портов до продвинутых сценариев с bastion- и jump-хостами:
Приятного хакинга!
10 практических челленджей, чтобы прокачать port forwarding через SSH-туннели — от простого локального/удалённого проброса портов до продвинутых сценариев с bastion- и jump-хостами:
- Получить доступ к внутреннему debug-порту через SSH-туннель
https://labs.iximiuz.com/challenges/ssh-local-port-forwarding
- Достучаться до приватного сервиса в VPC через SSH-бастион
https://labs.iximiuz.com/challenges/ssh-local-port-forwarding-bastion
- Получить доступ к удалённому loopback-порту через SSH jump host
https://labs.iximiuz.com/challenges/ssh-local-port-forwarding-jump-host
- Ограничить доступ к SSH-бастиону в зависимости от роли пользователя
https://labs.iximiuz.com/challenges/ssh-local-port-forwarding-bastion-hardened
- Получить доступ к внутренним серверам через SSH-бастион без shell-доступа
https://labs.iximiuz.com/challenges/ssh-jump-host-internal-servers
- Получить доступ ко всей VPC через SSH SOCKS-прокси
https://labs.iximiuz.com/challenges/ssh-socks-proxy
- Пробросить локальный сервис наружу через обратный SSH-туннель
https://labs.iximiuz.com/challenges/ssh-remote-port-forwarding
- Пробросить устройство из домашней сети через обратный SSH-туннель
https://labs.iximiuz.com/challenges/ssh-remote-port-forwarding-home-network
- Пробросить всю домашнюю сеть через обратный SSH SOCKS-прокси
https://labs.iximiuz.com/challenges/ssh-reverse-socks-proxy
- Заменить root-доступ по паролю на админский логин по SSH-ключу
https://labs.iximiuz.com/challenges/ssh-harden-new-server
Приятного хакинга!
🔥2
Как собирать компактные образы контейнеров
Подробный разбор того, из-за чего production-образы обычно раздуваются и как этого избежать с помощью multi-stage builds и грамотного выбора базовых образов.
С практическими примерами для Node.js, Go, Rust, Java и PHP:
https://labs.iximiuz.com/tutorials/docker-multi-stage-builds
Подробный разбор того, из-за чего production-образы обычно раздуваются и как этого избежать с помощью multi-stage builds и грамотного выбора базовых образов.
С практическими примерами для Node.js, Go, Rust, Java и PHP:
https://labs.iximiuz.com/tutorials/docker-multi-stage-builds