Библиотека девопса | DevOps, SRE, Sysadmin
10.2K subscribers
1.57K photos
74 videos
4 files
2.82K links
Все самое полезное для девопсера в одном канале.

По рекламе: @proglib_adv

Учиться у нас: https://proglib.io/w/25874ec4

Для обратной связи: @proglibrary_feeedback_bot

РКН: https://gosuslugi.ru/snet/6798b4e4509aba56522d1787
Download Telegram
🔭 Долгоживущие флаги

Разработчик создаёт флаг для плавного выката новой фичи. Две недели максимум — думает он. Три месяца спустя флаг всё ещё живёт в кодовой базе. Теперь там две логики работы: старая и новая. Если что-то сломается, непонятно, что именно. Никто не удаляет флаг, потому что вдруг кто-то им пользуется.

Как это решить

Добавляем в каждый флаг срок жизни — дату, после которой он должен исчезнуть. Не данные флага, а сам код его обработки. И конвейер CI останавливает сборку, если срок прошёл.
new_feature_flag:
owner: web-platform
created: 2025-09-08
expires: 2025-11-01


После даты expires случается одно из двух:

• CI выдаёт предупреждение на третий день просрочки
• CI ломает сборку, если просрочка больше недели

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

Проводите flag burn-down — 15-минутный митинг, где смотрите, какие флаги уже 100% включены в прод.

🐸 Библиотека devops'a

#арсенал_инженера
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍1
😊 Dev и prod — разные миры, но у вас одинаковые манифесты

Команды копируют манифесты из dev в prod, чтобы было проще. Но в деве 2 реплики и 128Mi памяти хватает. В продц нужно 20 реплик и 2Gi памяти.

Что происходит

В dev запустили 10 реплик для теста — кластер упал. В prod оставили 2 реплики — сервис не держит нагрузку. Или забыли поменять ConfigMap с URL базы — prod подключился к dev-базе.

Как исправить

Используйте kustomize. Создайте base с общими настройками, а окружения описывайте в overlays:
base/
deployment.yaml
service.yaml
overlays/
dev/
kustomization.yaml
prod/
kustomization.yaml


В overlay переопределяете replicas, resources, ConfigMap, Secrets. В dev можете вообще не использовать Secrets — подойдёт mock-конфиг. В prod — настоящий Secret из Sealed Secrets или внешнего Vault.

🐸 Библиотека devops'a

#арсенал_инженера
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍1
⚡️ Devuan 6 Excalibur

Devuan выпустил шестую версию своего дистрибутива. Это операционная система для тех, кто предпочитает OpenRC или runit вместо systemd. Новая версия основана на Debian 13 Trixie и получит поддержку до конца жизненного цикла Debian — в течение нескольких лет.

Главное изменение — теперь обязателен merged-/usr, то есть директория /usr сливается с корневой директорией. Если обновляетесь со старых версий, нужно сначала установить пакет usrmerge в Daedalus, а потом уже переходить на Excalibur.

➡️ Анонс обновления

🐸 Библиотека devops'a

#пульс_индустрии
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍1
⚙️ Окружение работает локально, но падает в CI

Знакомая ситуация: код запускается на ноутбуке, а в CI он сразу же ломается. Причина почти всегда в окружении — где-то не хватает переменной, токен истёк, или указан неправильный регион.

Перед тем как запустить джоб, убедитесь, что все критичные переменные на месте и имеют смысл:
# Проверяем, что все нужные переменные заданы
required=(DB_URL OAUTH_CLIENT_ID OAUTH_SECRET REGION)
for v in "${required[@]}"; do
[ -n "${!v}" ] || { echo "::error::$v missing"; exit 78; }
done


Добавьте это в начало вашего скрипта CI. Код проходит по списку переменных и падает, если какая-то не установлена.

🐸 Библиотека devops'a

#арсенал_инженера
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍1
🕷 Забытые ресурсы едят деньги и место

Kubernetes не удаляет ресурсы автоматически. Создали тестовый Deployment, Service, LoadBalancer — забыли удалить. Через месяц в кластере 50 неиспользуемых объектов.

Что происходит

Service с типом LoadBalancer создаёт внешний балансировщик в облаке. Вы платите за него каждый день. PersistentVolumeClaim держит диск, даже если под давно удалён. ConfigMap и Secret захламляют namespace.

Как исправить

Добавьте лейблы всем ресурсам:
metadata:
labels:
owner: team-backend
purpose: experiment
expires: 2025-11-15


Теперь можно найти всё, что создала команда: kubectl get all -l owner=team-backend. Или всё, что просрочено.

Настройте сборку мусора. Kubernetes удалит зависимые объекты, если удалить владельца.
Используйте Kyverno для автоматического удаления ресурсов.

Делайте аудит раз в неделю: kubectl get all --all-namespaces. Ищите незнакомые имена, странные namespace. Удаляйте то, что не нужно.

🐸 Библиотека devops'a

#арсенал_инженера
Please open Telegram to view this post
VIEW IN TELEGRAM
3
🍭 Топ-вакансий для девопсов за неделю

SRE/DevOPS инженер до 500 000 ₽

Senior DevOps-инженер от 4700 до 5700 $

DevOps-инженер до 400 000 ₽

AppSec инженер на удалёнку

Бустер — Офис у вас дома.

➡️ Еще больше топовых вакансий — в нашем канале Devops Jobs
Please open Telegram to view this post
VIEW IN TELEGRAM
🔄 LXQt 2.3.0: больше поддержки Wayland и удобства в работе с файлами

Вышла новая версия LXQt — лёгкого десктопного окружения на основе Qt. Основной фокус релиза на улучшение работы с Wayland, протоколом, который постепенно заменяет X11.

В файловом менеджере PCManFM-Qt появилась функция Safely Remove для безопасного извлечения съёмных носителей, и теперь можно отключить подсказки при наведении на файлы на рабочем столе.

В целом это релиз для тех, кто работает на Wayland или просто хочет больше удобства в повседневной работе с ОС.

➡️ Release notes

🐸 Библиотека devops'a

#пульс_индустрии
Please open Telegram to view this post
VIEW IN TELEGRAM
🎁 И мозг прокачать, и макбук утащить!

Proglib.academy разыгрывает MacBook Pro 14 (M3 Pro, 36 GB, 1 TB SSD) 💻

Условия:

1️⃣ Покупаешь любой курс Proglib до 15 ноября.
2️⃣ Проходишь минимум 2 учебные недели (можно осилить за два вечера).
3️⃣ Пишешь куратору в чат своего курса: #розыгрыш.

Что за курсы?

Математика для Data Science (6 месяцев боли и просветления).
Основы Python, ML, алгоритмы, AI-агенты и даже курс для тех, кто в IT, но не кодит.

👉 Участвовать в розыгрыше
🤨 Service mesh в проекте на трёх подах — это перебор

Команды сразу ставят Istio, Cilium, кастомные CNI. Хотят mTLS, продвинутый роутинг, observability из коробки. Но не понимают, как работает базовая сетка Kubernetes.

Что происходит

Под не может достучаться до другого пода. Вы не знаете, это проблема в CNI, в service mesh, в DNS, или в самом Kubernetes. Дебажите три дня, гуглите ошибки Istio. Потом удаляете Istio — всё работает.

Service mesh добавляет sidecar в каждый под, свой control plane, свои CRD. Каждый слой — новая точка отказа.

Как исправить

Начните с простого:
apiVersion: v1
kind: Service
metadata:
name: backend
spec:
selector:
app: backend
ports:
- port: 80
targetPort: 8080


Разберитесь, как поды находят друг друга через DNS. Как ClusterIP балансирует запросы. Как работает Ingress.

Когда поймёте базу, добавьте Ingress-NGINX для внешнего трафика.

🐸 Библиотека devops'a

#арсенал_инженера
Please open Telegram to view this post
VIEW IN TELEGRAM
3
🛠 Состав systemd

systemd — это современная система инициализации и управления службами в Linux, которая значительно упрощает и ускоряет запуск и управление системой.

Сделали инфографику с составом systemd. В следующих постах разберём кто за что отвечает.

🐸 Библиотека devops'a

#архитектура_на_салфетке
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🙏2👍1
🧑‍💻 Ошибка неуязвимого

Kubernetes по умолчанию не строгий. Можно запустить контейнер от root, использовать image:latest, дать всем cluster-admin. Кластер работает — зачем что-то менять?

Что происходит

Контейнер от root может сбежать на ноду через уязвимость. Тег :latest означает, что в prod может задеплоиться любая версия — вчера работало, сегодня нет. Роль cluster-admin даёт права удалить весь кластер.

Как исправить

Настройте RBAC. Создайте роли с минимальными правами:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]


Добавьте Pod Security Standards:
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted


Теперь в namespace нельзя запустить контейнер от root, с privileged, без securityContext.

Если нужна более гибкая политика — Kyverno или OPA Gatekeeper. Напишете правило один раз — оно будет работать для всех подов.

🐸 Библиотека devops'a

#арсенал_инженера
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🔄 Обновления недели

Неделя была богата на релизы, вспомним её богатства:

Consul 1.22

Wine 10.18

Grafana Mimir 3.0

Devuan 6 Excalibur

LXQt 2.3.0

🐸 Библиотека devops'a

#дайджест_недели
Please open Telegram to view this post
VIEW IN TELEGRAM
💻 ВАЖНО: макбук ещё не забрали!

Proglib.academy продолжает розыгрыш MacBook Pro 14» (M3 Pro, 36 Гб, 1 Тб SSD).

Что нужно для участия?

— Берёшь любой курс Академии до 15 ноября.
— Проходишь хотя бы 2 недели обучения (можно за два дня).
— Пишешь куратору #розыгрыш. Всё — ты в игре!

Что за курсы?

▫️Алгоритмы и структуры данных — если хочешь готовиться к собесам в Яндекс, FAANG и не сидеть на джуне вечно.

▫️Архитектуры и шаблоны проектирования — учат думать как senior, а не просто писать код.

▫️ Python, математика для DS, основы IT и другие темы — можно стартовать с нуля или усилить то, что уже знаешь.

👉 Влетай, не думай!
👨‍💻 Как добить поды, если они зависли

Вы удалили ReplicationController с дюжиной подов. Большинство исчезли. Но несколько упрямцев остались висеть в состоянии Terminating, игнорируя ваши попытки удаления.

Когда Kubernetes удаляет под, kubelet выполняет аккуратное завершение: отправляет SIGTERM, ждёт до истечения terminationGracePeriodSeconds, останавливает контейнеры, размонтирует тома и сетевые пространства имён. Финальный шаг — удаление пода с ноды и из API.

Но если размонтирование не удаётся из-за ошибки "device or resource busy", процесс завершения зависает. API-объект остаётся в лимбо состояния Terminating навсегда.

Корень проблемы обычно один: рантайм контейнера оставил утечку — смонтированный том или процесс, который по-прежнему держит файловые дескрипторы.

Быстрая диагностика

Посмотреть есть ли на поде финализаторы:
kubectl get pod <POD> -o jsonpath='{.metadata.finalizers}'


Если они есть — не рубите их сплеча. Это обычно finalizer-ы хранилища (PVC, CSI), которые блокируют удаление до завершения очистки.

Нет финализаторов? Тогда ищем утечку монтирования на уровне хоста.

Подключитесь к ноде, где запускался под:
POD=pod-186o2
NS=default
UID=$(kubectl get pod $POD -n $NS -o jsonpath='{.metadata.uid}')

# На ноде смотрим, что смонтировано
grep -F "$UID" /proc/mounts || true
findmnt | grep "$UID" || true


Если видите записи типа /var/lib/kubelet/pods/<UID>/volumes/... — это ваш виновник.

Теперь узнаем, кто держит монтирование:
lsof +D /var/lib/kubelet/pods/$UID 2>/dev/null | head


Чистим руками

Для Docker:
docker ps --no-trunc | grep $POD
docker stop <containerID>
# Если совсем ничего не помогает (лаха!):
systemctl restart docker


Для containerd:
crictl ps | grep $POD
crictl stopp <containerID>
crictl rmp <containerID>
# Последняя линия защиты:
systemctl restart containerd


Если контейнер мёртв, но монтирование остаётся:
umount -l /var/lib/kubelet/pods/$UID/volumes/<driver>/<vol> || true


Теперь, когда освободили держание:
kubectl delete pod $POD -n $NS


Если всё ещё не уходит:
kubectl delete pod $POD -n $NS --grace-period=0 --force


Это API-уровневый молот. Безопасен для очистки зависшей записи, но используйте только после того, как разобрались с утечками на ноде. С особой осторожностью для StatefulSet.

Видите Terminating, который не уходит? Не спешите с --force. В девяти случаях из десяти kubelet вам что-то говорит: что-то остаётся смонтированным или используется.

🐸 Библиотека devops'a

#арсенал_инженера
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
🔄 Обновление firewalld

Вышел релиз firewalld версии 2.4.0 — динамически управляемого межсетевого экрана для Linux.

Основные новшества:

• Добавлен набор правил gateway, обеспечивающий функциональность типового домашнего маршрутизатора: NAT, обработка conntrack и перенаправление трафика между зонами.

• Введён флаг disable, который можно применять в XML-конфигурациях, через командную строку и D-Bus для отключения отдельных правил и наборов правил.

• Максимальная длина имён правил увеличена с 17 до 128 символов.

➡️ Release notes

🐸 Библиотека devops'a

#пульс_индустрии
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
▶️ Запуск CI из Jira

Часто нужно запустить специфичную джобу для конкретной задачи: пересчитать метрики, перепроверить безопасность, прогнать дополнительные тесты. Обычно мы идём в Jenkins или GitHub Actions, ищем нужную джобу, вводим параметры.

Информация о нужном действии находится в Jira, но инструмент для его выполнения — отдельно. Хочется проще: добавил лейбл к задаче и всё запустилось автоматически.

Что можно сделать:

Jira отправляет вебхук с информацией о лейблах в GitHub через repository_dispatch. GitHub Actions ловит это событие, парсит лейблы и запускает нужные шаги. На примере ниже: если в Jira добавили лейбл rebuild-docker, GitHub Actions пересобирает Docker образ. После выполнения можно написать результат комментарием обратно в Jira.

name: Jira Triggered Job

on:
repository_dispatch:
types: [jira-trigger]

jobs:
handle-trigger:
runs-on: ubuntu-latest
steps:
# Парсим labels из payload'a
- name: Parse Jira event
id: parse
run: |
LABELS="${{ fromJSON(github.event.client_payload).labels }}"
ISSUE="${{ fromJSON(github.event.client_payload).issueKey }}"

echo "issue=$ISSUE" >> $GITHUB_OUTPUT
echo "labels=$LABELS" >> $GITHUB_OUTPUT
echo "Получены labels: $LABELS для issue: $ISSUE"

# Если в labels есть 'rebuild-docker', запускаем пересборку
- name: Rebuild Docker
if: contains(steps.parse.outputs.labels, 'rebuild-docker')
run: |
echo "🐳 Пересобираем Docker для ${{ steps.parse.outputs.issue }}"
docker build -t myapp:latest .
docker push myapp:latest
echo "DOCKER_STATUS= Docker образ успешно пересобран" >> $GITHUB_ENV

# Если в labels есть 'run-tests', запускаем тесты
- name: Run Tests
if: contains(steps.parse.outputs.labels, 'run-tests')
run: |
echo " Запускаем тесты для ${{ steps.parse.outputs.issue }}"
npm test
echo "TESTS_STATUS= Тесты пройдены успешно" >> $GITHUB_ENV

# Если в labels есть 'security-scan', запускаем проверку безопасности
- name: Security Scan
if: contains(steps.parse.outputs.labels, 'security-scan')
run: |
echo "🔒 Security scan для ${{ steps.parse.outputs.issue }}"
npm audit
echo "SECURITY_STATUS= Security scan завершен" >> $GITHUB_ENV

# Пишем результаты комментарием в Jira
- name: Comment in Jira
if: always()
uses: actions/github-script@v7
with:
script: |
const issue = context.payload.client_payload.issueKey;
const labels = context.payload.client_payload.labels;

let comment = '🤖 Автоматизированные действия:\n\n';

if (labels.includes('rebuild-docker')) {
comment += ' rebuild-docker: Docker образ пересобран\n';
}
if (labels.includes('run-tests')) {
comment += ' run-tests: Тесты запущены\n';
}
if (labels.includes('security-scan')) {
comment += ' security-scan: Проверка безопасности завершена\n';
}


Затем добавьте триггер в Jira, который будет отправлять пейлод:
{
"event_type": "jira-trigger",
"client_payload": {
"issueKey": "{{issue.key}}",
"labels": "{{issue.labels}}"
}
}


на урл:
https://api.github.com/repos/ВАШ_НИК/ВАШ_РЕПО/dispatches


с headers:
Authorization: token ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
Accept: application/vnd.github.v3+raw+json
Content-Type: application/json


Замените ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxx на ваш GitHub токен, который можно получить по пути GitHub → Settings → Developer settings → Personal access tokens → Tokens.

Это особенно полезно в больших командах, где не все имеют доступ к GitHub Actions, но все работают с Jira. QA может добавить security-scan — и проверка запустится автоматически.

🐸 Библиотека devops'a

#арсенал_инженера
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
💻 Хочешь MacBook Pro? Просто начни учиться!

Да-да, вы не ослышались: Proglib.academy дарит макбук за учёбу!

Всё просто:

— купи любой курс Академии до 15 ноября;
— пройди 2 недели обучения (можно за два дня);
— напиши куратору в чате курса хэштег #розыгрыш.

📚 Выбирай свой курс:

▫️ «Математика для DS» — для тех, кто хочет уверенно работать с данными;
▫️ «Основы Python» — чтобы начать писать код с нуля;
▫️ «Алгоритмы и структуры данных» — для будущих инженеров;
▫️ «AI-агенты» или «Машинное обучение» — для тех, кто хочет прокачаться в ИИ.

👉 Участвовать в розыгрыше
🥱1
🛒 Black Friday от Proglib.academy!

Только до 30 ноября — скидка 40% на ВСЕ курсы.

Пора добавить в корзину не носки, а новые скиллы: Python, математика для Data Science, AI, алгоритмы и структуры данных, ML.

🎓 Выбирай курс, который реально двинет тебя в карьере, и учись со скидкой.

👉 Учиться со скидкой