Make. Build. Break. Reflect.
1.31K subscribers
146 photos
4 videos
1 file
156 links
Полезные советы, всратые истории, странные шутки и заметки на полях от @kruchkov_alexandr
Download Telegram
#devops #certificate

Простая напоминалка (в том числе и себе) на 2026-2027 годы про TLS‑сертификаты.

Надеюсь, все избегут инцидентов с "протухшими" сертификатами в продакшене:
сроки жизни постепенно режут, и первая большая итерация начинается уже сейчас.

Кратко по таймлайну (публичные TLS, CA/B Forum):
398 > 200 дней (с марта 2026) > 100 дней (с 2027) > 47 дней (с 2029).

Параллельно сокращают сроки повторного DCV, к 2029 остаётся до ~10 дней на переиспользование проверки домена.

CA (официальные анонсы и FAQ):
- DigiCert - переход на 199‑дневные сертификаты:
https://knowledge.digicert.com/alerts/public-tls-certificates-199-day-validity
- DigiCert - FAQ по срокам валидности:
https://www.digicert.com/faq/tls-ssl-certificate-validity
- Sectigo - про риски и 200‑дневную валидность:
https://www.sectigo.com/blog/200-day-ssl-certificate-expiration-risk
- GlobalSign - 199‑дневные сертификаты с марта 2026:
https://www.nicsrs.com/blog/globalsign-199-day-ssl-certificate-validity-2026

ACME / Let’s Encrypt и короткоживущие серты (думаю такое у многих):
- Let’s Encrypt: с 90 до 45 дней, общий план:
https://letsencrypt.org/2025/12/02/from-90-to-45.html
- Разбор перехода на 45‑дневные серты:
https://www.certkit.io/blog/45-day-certificates
- Let’s Encrypt: 6‑дневные и IP‑сертификаты (интересно в контексте мира с 47 днями):
https://www.helpnetsecurity.com/2026/01/20/lets-encrypt-6-day-tls-certificates
https://letsencrypt.org/2026/03/11/shorter-certs-certbot

Инструменты и автоматизация:
- cert-manager (релизы, где можно отслеживать поддержку коротких сроков, ACME и т.д.):
https://cert-manager.io/docs/releases/

Хорошие обзоры по общему таймлайну 398 > 47 дней и подготовке:
- Гайд по адаптации к 47‑дневным сертификатам:
https://www.centralnicreseller.com/47-day-ssl-certificates-validity-adaptation-guide-for-businesses
- Обзор сокращения сроков и влияния на процессы:
https://www.eginnovations.com/blog/ssl-tls-certificate-lifetimes-to-reduce-to-47-days

Эпоха "раз в год продлил и забыл" заканчивается.

Владельцам приватных внутренних УЦ в изолированных контурах можно пока расслабиться 😬 - эти правила касаются именно публичных TLS.
Please open Telegram to view this post
VIEW IN TELEGRAM
😢8👍4🙏41
#пятница #всратость

Если давно не чувствовали себя неловко - есть проверенный способ взбодриться.

В попытке синхронизировать календари разных систем и отметить свой отпуск (и UPTO), я вместо добавления события в рабочий календарь случайно разослал ВСЕМ в компании приглашение на ивент "Алекс в отпуске".

Классный ивент.
Примите, пожалуйста, и распишитесь.

Я просто сгораю со стыда.😦
Please open Telegram to view this post
VIEW IN TELEGRAM
😁43👏6
#aws #байки

Вторниковая байка.

У AWS SM, если по‑простому, два варианта хранения:
строковый секрет и бинарный.
Строковый в консоли можно редактировать либо как key/value (оно само собирается в JSON), либо как "сырой текст", где ты сам пишешь строку или JSON.

Однажды прилетает ошибка на проде - поды не стартуют.
После деплоя.
Начинаю разбираться - нет кубер‑секрета.
Секрета нет, потому что external secrets не смог подтянуть значение из AWS SM, ругался на какую‑то несовместимость.
Пробую ручной синк - те же ошибки.

Лезу в AWS SM - а там, блять, нет UI‑формы key/value.
Вместо привычной таблички - какой‑то поломанный сырой секрет.
Пришлось ковырять историю, спрашивать разработчиков. Оказалось вот что.

Разработчик добавил новую переменную, значением которой был JSON с множеством вложенностей.
Разумеется, без всякого экранирования, ведь это "никому не надо", а внутри - креды, пароли, спецсимволы😬.
В результате секрет перестал выглядеть как аккуратный JSON‑объект key/value, и консоль перестала показывать его в виде формы - только raw‑строка. Авс конвертнул его из строки в бинарный тип.

External secrets ожидал нормальный JSON, а получил вот эту бинарную кашу,
не смог её распарсить и отказался синхронизировать.
Новые поды без актуального секрета не стартуют, всё висит на старом релизе, который чудом ещё жив.

Ну, короче, разработчик с того времени узнал, что такое экранирование
и почему "просто запихнуть JSON как есть" - это не самое лучшее архитектурное решение.

А я на память, как медальку, сохранил скрин с этой ебалой.

- - -
Воспоминание навеяно обсуждением в кубер‑чате про .NET проблемы.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7🥰3
#kubernetes #tools

Я не фанат UI интерфейсов для работы с кубами, мне привычнее сношения с kubectl и алиасами баша.
Быстро, четко и по делу, но понимаю, что многим ближе визуальные инструменты.
Когда-то сделал подборку UI для коллег - решил поделиться и здесь.
Вдруг кому пригодится.

Инструменты для работы с Kubernetes (UI и терминальные клиенты):


Терминал-UI:
- k9s - https://github.com/derailed/k9s ❤️ (мой фаворит)
- kdash-rs - https://github.com/kdash-rs/kdash
- lazyk8s - https://github.com/berge472/lazyk8s (не понял в чем его прикол)
- kubetui - https://github.com/sarub0b0/kubetui
- kubeterm - https://github.com/kbterm/kubeterm

Desktop GUI:
- Seabird - https://github.com/getseabird/seabird ❤️(отличное UX и активное развитие)
- Freelens - https://github.com/freelensapp/freelens
- Jet-Pilot - https://github.com/unxsist/jet-pilot
- Aptakube - https://github.com/aptakube/aptakube (многие разработчики пересели в тот раз именно на него)
- Lens - https://github.com/lensapp/lens
- Headlamp - https://github.com/kubernetes-sigs/headlamp

Веб-UI и панели управления:
- kite - https://github.com/zxh326/kite
- Devtron - https://github.com/devtron-labs/devtron
- KubeClipper - https://github.com/kubeclipper/kubeclipper (не проверял лично)
- Karpor - https://github.com/KusionStack/karpor (не проверял лично)
- Cyclops - https://github.com/cyclops-ui/cyclops (не проверял лично)

Не гарантирую, что что-то из этого не стало платным или наоборот бесплатным - лицензии и платформенная поддержка MacOS/Win постоянно меняются, так что лучше проверять актуально на момент задачи.
👍10🔥3
#troubleshooting #aws #azure #kubernetes #одинденьизжизни

Пришёл алерт ранним утром. Ровно после начала рабочего дня в 10.01.
Чёткий. Конкретный. С именем сервиса, неймспейсом и метрикой.
Не что-то не то с подами, а прям: HighMemoryUsage, payment-service, namespace production, порог 85%, текущее значение 91%.

Открыл дашборд - всё выровнено, таймлайн читается, spike начался ровно в момент последнего деплоя.
Зашёл в ArgoCD, посмотрел diff последнего релиза.
Разработчик увеличил replicas с 3 до 5, но не тронул resources.limits.memory.
Всё сошлось.

Написал разработчику. Он ответил сразу.
Сказал да, моя ошибка и прислал PR через 10 минут.
В PR было описание: что изменил, почему, как проверял локально, какой эффект ожидается.
Коммиты по делу: fix(payment-service): set memory limits and requests after OOM incident.
Не fix, не wip, не asdfgh.
Поправил лимиты, добавил requests заодно.

Пока ждал PR, попросил Cursor посмотреть helm values на предмет других неоптимальных лимитов.
Нашёл два места. Предложил изменения. Ничего лишнего не тронул.

Я заапрувил, ArgoCD задеплоил. Память упала. Алерт закрылся сам.
CI прошёл с первого раза. Без flaky tests. Без "ой, retry нажмите, оно иногда так".

Разработчик после апрува написал в PR: спасибо за ревью, понял, учту.
Следующий его PR пришёл уже с нормальными лимитами. Без напоминания.
В Slack за всё это время никто ничего не написал.

Кстати, на прошлой неделе коллективно договорились не писать @here и @channel в каналах с людьми, если это не реальный прод-инцидент. Все согласились и все соблюдают.

Параллельно пришло письмо от AWS: они самостоятельно обнаружили, что у нас один из инстансов работает в неоптимальном режиме, и предложили конкретный тип на замену - дешевле на 15%.
Написал в саппорт уточнить детали, ответили за полчаса, классные ребята из лондонского офиса, поболтали за жизнь на английском.

Ещё с утра был запланирован автоапдейт AKS - security patch.
Прошёл сам, пока я занимался инцидентом.
Все ноды обновились по очереди, ни одна не упала в NotReady.
API не дёргался. Поды не пересоздавались хаотично.
kubectl get nodes после апдейта вернул всё Ready. С первого раза.
Странно, что я удивляюсь этому, ведь так было всегда, это стабильный и любимый всеми Ажур.

Коллеги наконец перестали спорить что лучше - Windows или Mac.
Все пересели на MacBook. Тихо. Без срачей. Без "но у меня Visual Studio".

Перед обедом написал PM.
Он ответил, что предлагает отменить ежедневный стендап на этой неделе - нет открытых топиков, нет смысла тратить время.

Ещё PM сказал, что руководство приняло решение: гонка за AI - не наша история.
Главное - люди, процессы и спокойная работа.
Никаких срочных внедрений, никакого "а вы уже используете агентов?", никаких OKR про AI-трансформацию до конца квартала.
Ведь главное, чтобы у всех были рабочие места и зарплата вовремя, а не это ваше ИИ.

Весь день занял 40 минут рабочего времени.
Остальное время занимался самообразованием и гладил кота.

Написал постмортем.
Никто не переспрашивал.
Кто-то из команды сам обновил страницу в Notion по итогам инцидента.
Без задачи. Без напоминания. Просто взял и обновил.

NewRelic прислал автоматический отчёт: data ingestion за месяц снизился на 12%. Сам.
Пообедал в 13:00. Целый час, как положено.
Статус в Slack стоял 🍕 Lunch.
Никто не написал. Никто не позвонил. Никто не "быстрый вопрос".

Хороший день.
Может, когда-нибудь так и будет.😀
Please open Telegram to view this post
VIEW IN TELEGRAM
😁4510😢6🔥3
#guardduty #aws #eks #security #troubleshooting

Guardduty, фишинг. Часть 1 из 2.

Никого не трогаю. Прилетает алёрт от AWS GuardDuty.
Backdoor:EC2/C&CActivity.B!DNS

Продакшн нода в EKS делает DNS-запрос к x****.cn - по базам GuardDuty это известный фишинговый/DGA домен.
Серьёзность - High. В слаке шум, все смотрят на меня.
Блин, почему в мою смену секьюрити инциденты 😬

Окей. Поехали.
Cмотрим что за нода
aws ec2 describe-instances \
--instance-ids i-0xxxxxxxxxxxxxxxxx \
--region us-east-1 \
--query 'Reservations[0].Instances[0].{IP:PrivateIpAddress,State:State.Name,LaunchTime:LaunchTime}'

Нода уже terminated. Karpenter убил её раньше, чем я добрался до расследования.
Живого форензика (digital forensics) нет.
Прекрасное начало.
kubectl get nodes -o wide
# ноды нет

Ладно, живыми данными не поработать, идём в логи.

Cмотрим что вообще крутилось на ноде
Хорошо, что у нас включено всё логирование control plane EKS. Идём в CloudWatch, смотрим логи шедулера - кто и когда был назначен на эту ноду.
aws logs start-query \
--log-group-name /aws/eks/my-cluster/cluster \
--start-time $(date -v-83H +%s) \
--end-time $(date +%s) \
--query-string 'fields @timestamp, @message | filter @logStream like "scheduler" | filter @message like "ip-10-0-25-132" | sort @timestamp asc | limit 50' \
--region us-east-1

Первая попытка падает с MalformedQueryException. Оказывается, ретеншн у лог группы EKS - 84 часа. Нода жила 4 дня. Часть ранних данных уже недоступна. Запоминаем это на потом.

За те данные, что есть, видим волну деплоя примерно за час до алёрта: новые ReplicaSet хеши, несколько сервисов прокатились роллинг апдейтом. Подозрительно по тайминингу. Ухожу копать туда.

Cмотрим образы, которые пушились незадолго до инцидента
aws ecr describe-images \
--repository-name my-ecr-repo \
--region us-east-1 \
--query 'sort_by(imageDetails, &imagePushedAt)[-10:].[imagePushedAt,imageTags[0],imageDigest]' \
--output table

Вижу два образа, которые запушились за ~30-60 минут до алёрта GuardDuty. Первая гипотеза: кто-то накатил заражённый образ.

Лезу в git, смотрю коммиты.
Один коммит - это Dependabot, обновил grpc. Проверяю go.sum - стандартные пакеты, нормальные хеши. Второй коммит - двухфайловый вайтспейс-фикс в SQL query builder, strings.TrimSpace в одном файле.

Всё это вообще не то. Red herring, мать ее.

Исключаем DaemonSet
kubectl get daemonsets -A

DaemonSet крутится на всех нодах кластера - их там под 44 штуки. Если бы DaemonSet был заражён, GuardDuty бы полыхал по всем нодам разом. Сработало только на одну. Значит, не DaemonSet.

Базовый образ Dockerfile смотрю - официальный golang bookworm, мультистейдж, всё чисто.

Смотрю дополнительные файндинги GuardDuty
aws guardduty list-findings \
--detector-id $(aws guardduty list-detectors --query 'DetectorIds[0]' --output text) \
--finding-criteria '{"Criterion":{"type":{"Eq":["Backdoor:EC2/C&CActivity.B!DNS","Trojan:EC2/DNSDataExfiltration","DefenseEvasion:EC2/UnusualDoHActivity"]}}}' \
--region us-east-1

Нашлось ещё пара файндингов - не игнорируем, но пока продолжаем копать основное.

Наконец-то заглядываю в логи приложения (когда же я, бл, научусь это смотреть первым 🤡)
Открываю OpenSearch, ищу по домену x********.cn , в индексе EKS-логов.
8 записей. Все - из одного контейнера. Смотрю на таймстемпы:
12:51:19 - PaymentWebhookProcessor: starting to parse note
12:51:19 - PaymentWebhookProcessor: no images found in note
...
13:21:38 - PaymentWebhookProcessor: starting to parse note <- ВОООТ ОНО
13:21:38 - PaymentWebhookProc...

13:21:38 UTC - точь-в-точь время алёрта GuardDuty.

Попался!
Please open Telegram to view this post
VIEW IN TELEGRAM
😁3👍1
#guardduty #aws #eks #security #troubleshooting

Guardduty, фишинг. Часть 2 из 2.


Что произошло на самом деле
Схема простая до слёз:
Пользователь отправил сообщение с URL -> x*****.cn
|
Сервис обработки контента внутри кубера получил вебхук(?)
|
Функция(?) PaymentWebhookProcessor внутри POD-а попыталась резолвить домен
(логика: ищет превью/изображения по URL-ам в тексте)
|
DNS-запрос к x*****.cn с EKS ноды, на которой запущен под
|
GuardDuty: ALARM


Никакой малвари. Нода не скомпрометирована. Credentials не угнаны.
Просто сервис резолвит любой домен из пользовательского контента - а юзер прислал фишинговую ссылку.
Фишинг не удался (дополнительно логи смотрел).

Несколько часов расследования, CloudTrail, CloudWatch, ECR history, git blame - ответ лежал в логах приложения и нашёлся бы за 15 минут, если бы я туда полез первым делом.

Что реально плохо и надо починить
Само расследование закончилось словами "малвари нет", но по ходу вскрылись настоящие проблемы 🚬.

- SSRF
PaymentWebhookProcessor резолвит произвольные URL из пользовательского контента без какой-либо валидации.
Это означает, что любой клиент может прислать:
http://169.254.169.254/latest/meta-data/
И сервис спокойно попробует его резолвнуть - прямо с production ноды, у которой есть IAM-роль со повышенными правами (это вообще, бл, отдельный разговор какого рожна нода имела доступ к некоторым AWS ресурсам).

Фикс очевидный - блокировать приватные диапазоны перед любым исходящим запросом:
169.254.0.0/16  (AWS metadata endpoint)
10.0.0.0/8
172.16.0.0/12
192.168.0.0/16
127.0.0.0/8

- GuardDuty будет шуметь вечно
Пока сервис зачем-то резолвит пользовательские URL без фильтрации - каждый раз, когда кто-то пришлёт фишинговую ссылку, GuardDuty будет стрелять алёртом. Это шум, который убивает доверие к алёртингу.

Решение: AWS Route 53 Resolver DNS Firewall с managed threat lists.
- AWSManagedDomainsMalwareDomainList
- AWSManagedDomainsAggregateThreatList
Известные вредоносные домены блокируются до DNS-резолва автоматически, без ручных списков.
https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resolver-dns-firewall-managed-domain-lists.html

- URL-резолвинг в основном процессе
Длиннее задача, но правильная: вынести резолвинг URL в изолированный асинхронный воркер с ограниченным egress.
Без доступа во внутреннюю сеть. Без IAM-роли с правами на всё.

Выводы и итоги:
- в логи приложения надо идти первым. Не после нескольких часов инфра-форензики.☔️
- ретеншн CloudWatch-логов для EKS control plane 84 часа - маловато. Нода жила 4 дня, ранние события уже недоступны. Надо поднять. Не критикал, но надо бы.
- сервисы, которые резолвят URL из пользовательского контента, будут встречать фишинг. Это не вопрос если, это вопрос когда. Надо документировать и обрабатывать проактивно, а не разбираться в панике с High severity алёртом.
- SSRF - это не гипотетическая угроза, это прямая дыра в production при текущей архитектуре.
- кто дает права EKS нодам на доступ к AWS ресурсам, то негодяй, нельзя так
- с одной стороны я переживал тогда, что потратил много времени на расследование, копая изначально не туда, с другой стороны рад, ведь без полной картины происходящего я не смог бы понять были ли скомпроментированы креды или нет, был ли хак или нет, а так вроде и пополнил знания
- используйте сервисы AWS, многие из них хорошо помогают в траблшутинге, пусть и стоят денег

False positive закрыт, но работы добавилось.

- - -
В последствии все косяки были закрыты, все Security/AWS бест практисы внедрены.
Все потенциальные известные "дыры" закрыты, PII защищены, даже инвесторы спали спокойно после детальнейшнего постмортема.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍17
#devops #github

GitHub объявил, что с 24 апреля 2026 года данные взаимодействий Copilot (prompts, ответы, сниппеты и контекст) начинают использоваться для обучения моделей по умолчанию, если пользователь явно не отключит это в настройках для тарифов Copilot Free/Pro/Pro+.
https://github.blog/news-insights/company-news/updates-to-github-copilot-interaction-data-usage-policy/

Как и водится в маленьких инди компаниях, даже сроки они не стали соблюдать, залепили раньше, нарушая сроки объявленого дедлайна. Сейчас 7 апреля и у меня уже стоит эта галочка.
Возможно уже и данные коллектят, кто знает, верить уже тяжело.

Кто-то может, конечно, возразить, что "галочка включена != сбор данных", но я не очень согласен с этим.
Галочка стоит, текст честно написан, значит так оно и есть.
Allow GitHub to collect and use my Inputs, Outputs, and associated context to train and improve AI models.


Кто еще боится в век AI утилит лишиться приватности или заставляют условия работы в компаниях, спешите снять галочку:
- Идите по ссылке на свой профиль https://github.com/settings/copilot/features
- Settings -> Copilot -> Features -> Privacy -> Allow GitHub to use my data for AI model training,
9
#opensource #alertmanager #devops

Новости opensource мира.

У продукта Alertmanager есть неприятная недоработка.
Все уведомления в Slack он отправляет двумя сообщениями:
- проблема (firing)🔴
- проблема решена (resolved)🟢

Наверняка видели.

В мире шумных уведомлений даже этого много.
По сути 100 алертов порождают 200 сообщений (после их решения), что не очень удобно.
API самого Slack позволяет изменять сообщения, но алертменеджер не умел в это.

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

При этом аналоги умеют менять сообщение (меняя красный firing на зелёный resolved):
- grafana oncall / IRM
- pagerduty

С появлением GenAI инструментов я захотел исправить эту досадную оплошность, сделал форк алертменеджера, локально всё потестировал и примерно с полгода гонял у себя - работает идеально. (Март 2025)

Затем осмелился и запилил пулл реквест:
https://github.com/prometheus/alertmanager/pull/4682 (Ноябрь 2025)

Не скрою, пользовался GenAI, но основная идея была моя.
Я на 90% понимаю изменённый код и поведение.

После вялого обсуждения другие, более активные участники, реализовали это в два пулл реквеста:
- https://github.com/prometheus/alertmanager/pull/4899 (Январь 2026)
- https://github.com/prometheus/alertmanager/pull/5007 (Февраль 2026)

Само собой после этого мой PR не имеет смысла, я закрыл его. (Февраль 2026)

Вчера, 8 апреля 2026 выпущен новый релиз v0.32.0.
https://github.com/prometheus/alertmanager/releases/tag/v0.32.0

Теперь алертменеджер умеет хранить стейт алертов для слака и менять сообщения - что очень удобно. 🎉

Всех, кто использует алертменеджер, поздравляю.
Можете обновлять и радоваться меньшему количеству сообщений и меньшему шуму алертов.

---
Но вам же интересно глянуть, как это работает перед обновлением прода?

Нужен Bot Token Slack (xoxb-...) со скоупами chat:write и chat:update.
Важно: работает только с токеном, не с webhook URL.

Положить конфиг в /tmp/am-test/alertmanager.yml
global:
resolve_timeout: 1m

route:
receiver: slack
group_by: [alertname]
group_wait: 10s
group_interval: 10s
repeat_interval: 12h

receivers:
- name: slack
slack_configs:
- send_resolved: true
api_url: https://slack.com/api/chat.postMessage
http_config:
authorization:
credentials: xoxb-YOUR-BOT-TOKEN
channel: '#your-channel'
update_message: true # <-- вот эта опция
title: '{{ .GroupLabels.alertname }} - {{ .Status | toUpper }}'
text: |
{{ if eq .Status "firing" }}🔥 *{{ .Alerts.Firing | len }} alert(s) FIRING*{{ else }} *All alerts RESOLVED*{{ end }}

{{ range .Alerts }}• {{ if .Annotations.summary }}{{ .Annotations.summary }}{{ else }}{{ .Labels.alertname }}{{ end }}
{{ end }}
color: '{{ if eq .Status "firing" }}danger{{ else }}good{{ end }}'


Запустить alertmanager v0.32.0 через Docker:
mkdir -p /tmp/am-test

docker run -d \
--name am-test \
-p 9093:9093 \
-v /tmp/am-test/alertmanager.yml:/etc/alertmanager/alertmanager.yml \
-v /tmp/am-test/data:/alertmanager \
prom/alertmanager:v0.32.0


Стрельнуть алертом:
curl -X POST http://localhost:9093/api/v2/alerts \
-H 'Content-Type: application/json' \
-d '[{
"labels": {"alertname": "TestAlert", "severity": "warning"},
"annotations": {"summary": "This is a test alert - will resolve in the same message"}
}]'


Подождать ~10–15 секунд - в Slack появится сообщение с 🔴.

Зарезолвить:
curl -X POST http://localhost:9093/api/v2/alerts \
-H 'Content-Type: application/json' \
-d '[{
"labels": {"alertname": "TestAlert", "severity": "warning"},
"annotations": {"summary": "This is a test alert - will resolve in the same message"},
"endsAt": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"
}]'


Подождать ~10 секунд - то же самое сообщение изменится на 🟢.
Нового сообщения не будет!

Поздравляю всех с таким мелким, но приятным обновлением.
🔥462
#devops #ai #mcp #skills #troubleshooting

MCP, скиллы, ИИ, *уи.


Последние месяцы отказываюсь от MCP серверов.
Прям вот по минимуму оставляю и только от безысходности.
Slack, Linear, Jira, Grafana, VM (Victoria metrics), VL (victoria logs) и так далее.
Им замены мало, без них сложно.

Все MCP для Kubernetes, GitHub, GitLab - все это очень плохо работает в боевых условиях.

Распишу основные минусы из моего опыта:

- трата токенов
Вопреки описанию "да просто мсп сервер ничего не жрет в фоне", это лукавство.
Жрет токены и это видно по логу и трате их по обычным запросам.
Постоянно включать/выключать их я пробовал, но это банально неудобно даже если повесить скиллы/алиасы на это.

- они навайбкожены
Давайте быть честными - больше половины этих серверов это вайбкод вайбкода и работает он ровно так же.
Никаких гарантий, что ИИ агент идет четко по REST API/gRPC, из моей практики они просто хаотично по всем ендпойнтам лезут в надежде найти ответ на вопрос/задачу.

- функционал обрезан. Самый главный и основной минус.
Очень часто натыкался на то, что CLI утилита продукта имеет 99.9% функционала UI, а MCP от силы 60-70% по моим наблюдениям и оценке.
Пример на скриншоте.
Контекст скриншота: обучаю скилл/агента трабшутить упавшие пайплайны гитлаба, и mcp тут не подходит, он даже не может смотреть лог джобы, лол. 😬 Пришлось переписать на glab cli.

- происхождение сомнительное
Большинство MCP‑реализаций сейчас - сторонние, не от официальных вендоров, и часто не строго следуют контракту API или gRPC.
Я пробовал делать "доверительные списки", даже обращался к https://archestra.ai/mcp-catalog, но результат все равно для меня сомнительный.

Мне этого хватило, чтобы со временем отключить почти все MCP сервера там, где есть альтернатива - CLI tool + Skills.
Тут нет речи о том, что MCP - говно.
Тут речь лишь о том, что если есть CLI tool, то MCP не нужен.

Есть glab + TOKEN? MCP GitLab не нужен.
Есть gh + TOKEN? MCP GitHub не нужен.
Есть kubectl + auth? MCP Kubernetes не нужен.
И так далее.

Из плюсов подхода Skills +CLI tool:
- трата меньше токенов
- больший функционал, чем у MCP

Я пробовал заменить MCP VM/VL на "cURL + Skills", это работает и работает отлично, но трата токенов выше примерно на 18-22% по моим графикам и данным. Нерационально, поэтому оставил MCP MV/VL.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍143
#ai #devops

Совершенно ожидаемо и неожиданно одновременно Nvidia выпустила бесплатные эндпойнты к популярным LLM моделям.
https://build.nvidia.com/models?filters=nimType%3Anim_type_preview&orderBy=weightPopular%3ADESC

А давайте-ка глянем, так ли оно.

- прошел регистрацию (мой gmail аккаунт)
- прошел верификацию (номер телефона НЕ РФ, другие страны не проверял само собой)
- выбрал рандомную модель
https://build.nvidia.com/moonshotai/kimi-k2-instruct
- нажал view code
- нажал в окошке generate API key
- скопировал код к себе локально в файл 1.py , добавил context простой вопрос про хокку
from openai import OpenAI

client = OpenAI(
base_url = "https://integrate.api.nvidia.com/v1",
api_key = "nvapi-m3_bqO98rY-а-зачем-вам-мой-токен-BAMIGI-tLbz3VQ20MpwyTbU-"
)

completion = client.chat.completions.create(
model="moonshotai/kimi-k2-instruct",
messages=[{"role":"user","content":"Write a haiku about infrastructure as code."}],
temperature=0.6,
top_p=0.9,
max_tokens=4096,
stream=True
)

for chunk in completion:
if not getattr(chunk, "choices", None):
continue
if chunk.choices and chunk.choices[0].delta.content is not None:
print(chunk.choices[0].delta.content, end="")

- установил пакет опенаи (если нет)
pip3 install openai

- сохранил код и запустил его
python3 1.py

Lines of code define
bridges spun from pure intent—
infrastructure breathes.


Работает! 🎉

Забирайте себе и тренируйтесь с разными моделями бесплатно. ❤️

- - -
Update для самых быстрых и невнимательных.

Не забывайте, что там:
"Privacy. Your input and output will be recorded to provide you with this trial experience and to improve NVIDIA products and services, including AI models, in accordance with our Privacy Policy.
Do not upload any confidential information or personal data unless expressly permitted. Your use is logged for security, fraud or abuse monitoring and shared with third party service providers for this purpose. If the demo necessarily requires the input of personal data, logging for product development purposes will be turned off."
8
#terraform #AWS #IaC #devops

Все мы живём в привычках.
Как однажды научили - так и делаем, словно котики, повторяющие одно и то же всю жизнь.

Учили поднимать руку, чтобы постучать в дверь.
А можно стучать кистью, не поднимая руку.
Мелочь, но никто не задумывается, потому что "так делается".

Когда у нас с супругой появилась посудомоечная машина, я внимательно читал инструкции - и от самой техники, и от капсул.
Тогда были капсулы со специальным покрытием, которое нужно было срывать перед загрузкой.
Потом она купила новые капсулы с плёнкой, которая растворяется от воды сама, и положила их в старую коробку - удобная была.
Я об этом не знал.
И каждый раз, словно дурачок, аккуратно срывал плёнку перед загрузкой.
Ну скажем сильно больше одного дня я так делал) Сильно больше)
Ведь меня так научили. Да и коробка - та же самая.

Вот так и в нашем айти.

Когда меня учили Terraform и в проекте были накликанные руками ресурсы, объясняли процесс примерно так: пишешь код ресурса, потом идёшь на registry.terraform.io, находишь нужный ресурс, листаешь вниз до секции Import - там написано в каком формате передавать ID (у каждого ресурса свой синтаксис, угадай с первого раза).
Потом идёшь в AWS консоль за нужным ARN или именем ресурса. Возвращаешься, запускаешь команду:
terraform import aws_iam_role.eks_node_role eks-node-role-production

Делаешь план, убираешь дрифт. Следующий ресурс - снова на сайт, снова читаешь синтаксис, снова в консоль за ARN:
terraform import aws_iam_role_policy_attachment.eks_worker_node_policy \
eks-node-role-production/arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy

И так для каждого накликанного ресурса, по одному.

Ну я как обезьянка и повторял.
IAM роль? terraform import.
Политика? terraform import.
Node group? terraform import.
Пять ресурсов - пять итераций, пять заходов на сайт.

Оказывается, с Terraform 1.5 (лето 2023, и да, я снова не знал 🚬) есть блок import прямо в коде.
Без отдельных команд.
Без итераций.
Без "а я точно не забыл что-то запустить".
import {
to = aws_iam_role.eks_node_role
id = "eks-node-role-production"
}
resource "aws_iam_role" "eks_node_role" {
name = "eks-node-role-production"
...
}

import {
to = aws_iam_role_policy_attachment.eks_worker_node_policy
id = "eks-node-role-production/arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy"
}
resource "aws_iam_role_policy_attachment" "eks_worker_node_policy" {
role = aws_iam_role.eks_node_role.name
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy"
}


Запускаешь обычный terraform apply - он сам всё импортирует.
Это в коде, видно в PR, и при потере стейта не нужно вспоминать, что и как импортировать.
Документация прямо внутри конфига.

Import block не избавляет от необходимости знать ID формат, он просто убирает CLI-танцы.
Важно: import block выполняется только если ресурса нет в state.
После успешного импорта его можно удалить - он больше не нужен.

А если совсем не хочется писать конфиг руками - можно ещё и сгенерировать его через
terraform plan -generate-config-out=generated.tf


Так и живём.
Срываем саморастворяющуюся плёнку с капсул, хотя давно этого делать не нужно.
Please open Telegram to view this post
VIEW IN TELEGRAM
18🫡4👍2👏2
Media is too big
VIEW IN TELEGRAM
#aws #всратость

Спасибо тебе, маленькая инди компания Амазон!

Случайная сортировка аккаунтов при каждом входе на страницу SSO это очень удобно!
😁23🤣6🍌1
#пятница #байки #всратость

Давно не было баек.

Когда-то давно я работал в банке синего цвета.
Или красного. Или жёлтого. А уже и не важно, может и не работал вовсе.

В банках всё строго регламентировано: отдельный контур для дева, отдельный для стейджа, препрод и прод. Свои отдельные аккаунты, свои отдельные CI/CD системы, свои раннеры, только под проект. Те, кто работал в банках, наверняка знают, как всё урезано и изолировано.

Однажды сложилась ситуация, когда надо было шарить между командами и библиотеки, и раннеры.
Это был настоящий прорыв: общие раннеры конвейера позволяли получать пакеты из общего реджистри, и больше не надо было страдать с изоляцией на каждый чих.
Спасибо команде поддержки конвейера ❤️.

И вот тут выяснилось кое-что неприятное.
Не все инженеры из продуктовых команд после работы на шаренном раннере чистили за собой кеш и конфиг.
А oc login, как это принято, пишет конфиг сессии прямо на диск.
И этот конфиг никуда не девается, если явно не выйти.

То есть следующий инженер, который запускал свою джобу на том же раннере, мог просто подобрать чужой опеншифт конфиг и зайти в чужой неймспейс.
А оттуда все секреты кубера, пароли к БД и так далее. Дев, конечно, но тем не менее.

Я писал команде поддержки конвейера - разводили руками. Писал команде поддержки опеншифтов - тоже ничего. Хотя решений было полно: запретить запись этого файла на раннере, чистить конфиг после каждого старта, да хоть просто добавить logout в шаблон джобы. Сотни вариантов. Ни один не взлетел.

Тогда я решил действовать сам. Решение получилось, скажем так, воспитательное.
Я создал пайплайн, который раз в пять минут по крону проверял незавершённые сессии. Если находил, то скейлил все деплойменты и деплойментконфиги в ноль, поднимал десять реплик фейкового пода с говорящим именем и чистил конфиг за нерадивым инженером.
Добавил, так сказать, немного пассивной агрессии в инфраструктуре. 😀

Вот примерно так это выглядело:
object CheckOrphanSessions : BuildType({
name = "check-shared-runner-sessions"

steps {
script {
scriptContent = """
#!/usr/bin/env bash

oc=/path/to/oc

whoami=${'$'}(${'$'}oc whoami)

if [[ ${'$'}whoami == *"deploy-sa"* ]]; then

${'$'}oc scale deployment --all --replicas=0
${'$'}oc scale deploymentconfig --all --replicas=0

${'$'}oc new-app \
--name add-oc-logout-command-after-deploy-on-omni-agents \
--docker-image=registry.example.internal/fakeimage:latest \
--allow-missing-images

${'$'}oc scale deployment/add-oc-logout-command-after-deploy-on-omni-agents --replicas=10

${'$'}oc logout
echo "##ci[buildStatus text='caught you. ${'$'}whoami did not logout']"
else
echo "##ci[buildStatus text='agent is clean']"
fi
""".trimIndent()
}
}

triggers {
schedule {
schedulingPolicy = cron {
minutes = "*/5"
}
branchFilter = ""
triggerBuild = always()
withPendingChangesOnly = false
}
}
})

Помогло ли это? Конечно же нет.😬

Народ просто ходил по чатам и спрашивал, что это такое и откуда взялось.
Поды с говорящим именем, деплойменты в нуле - это не вызывало никаких мыслей, только один вопрос: а это вообще что и зачем здесь. 🐒
Я же просто гиенил с ситуации.

Не знаю, как насчёт импортозамещения, возможно сфера влияния поменялась, сейчас уже ничего этого не существует.

А может и существует, и мой пайплайн, словно герой в маске, до сих пор каждые пять минут обнуляет чьи-то деплойменты и пытается научить людей выходить из сессии.
Безуспешно, конечно.🤡
Please open Telegram to view this post
VIEW IN TELEGRAM
😁28🤡3
Никаких технических статей и заметок на этой неделе нет по причине моего отпуска.

Могу лишь горячо порекомендовать, в рамках общего развития, прекраснейшую статью-разбор, которую я дочитал лишь на этой неделе.
Раскладки, клавиатуры, "почему так".
Интереснейший квест-погружение в мир раскладок клавиатур.

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

https://optozorax.github.io/p/my-keyboard-layout/
8👍4💊2
#AWScommunity #troubleshooting #EKS #kubernetes #nodejs #aws #longread #SRE

Пока был в отпуске дописал свой лонгрид по дебаггингу 502 ошибок в приложении, запущенных в кубернетис.
Информация может быть полезна начинающим специалистам и мидлам по направлениям DevOps/SRE/VibeOps.
Более старшим и опытным товарищам заметка может показаться слабой.

Синёры сейчас все умные-преумные, так что, вероятно, они итак всё знают (особенно когда я так всё "разжевал") и без моих пояснений.

https://teletype.in/@kruchkov_alexandr/K-2Mql5Hsok
17👍10
This media is not supported in your browser
VIEW IN TELEGRAM
#пятница

Читаю я все эти новости про увольнения конца 2025 - начала 2026:
- оракл 30к
- амазон 30к
- интел 28к+
- ups 30к
- микрософт 18к
- куча менее известных компаний с 5-10к каждая

Что из этого стоит вынести?
Работать по выходным "в надежде на премию/опцион" - проклятая инвестиция.
Из последнего - https://finance.yahoo.com/markets/stocks/articles/oracles-cfo-got-26m-stock-184500098.html
Просто до хруста нагнули ребят и по-борцовски перекинули через себя на пол. Всё, что не успело вестнуться, просто сгорело - у людей улетели десятки и сотни тысяч долларов на бумаге.

Компании оптимизируют расходы быстро и без эмоций. И это норм.
Вчера ты перерабатывал, сегодня - строка в отчёте (сгенерированном ИИ, лол).
Премии могут не случиться, опционы - обесцениться (читайте про Oracle), а вот выгореть - вполне реально.

Мы, трудяги-работяги цифрового мира, у себя одни.
Не будьте оленями.
Завтра выходной - отдыхаем.
👍284😁2
#aws #eks #kubernetes #bottlerocket #troubleshooting #security #linux #CVE

Сорри за частые посты сегодня☔️

Пока я был в отпуске и спал, снова сломали все интернеты.

В мае 2026 вышла пара свежих уязвимостей ядра linux в ос
- первая: CVE-2026-31431, она же Copy Fail
https://copy.fail
- вторая: Dirty Frag, смежная к первой
https://github.com/V4bel/dirtyfrag

Обе уязвимости это локальное повышение привилегий (LPE).
То есть если кто-то запустил код на вашей ноде, он может стать рутом.
В контексте Kubernetes это означает выход из контейнера на хост.

Первым делом пошёл смотреть, а вообще мы уязвимы или нет.
Способ 1:
kubectl debug node/<имя_ноды> -it --image=busybox -- sh

Внутри:
chroot /host modprobe algif_aead


Если в ответ получаете:
modprobe: ERROR: could not insert 'algif_aead': Operation not permitted

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

Способ 2: через SSM напрямую на ноду (только для Bottlerocket)
Это нативный способ для Bottlerocket.
Я писал об этом не раз, искать по тегу #bottlerocket

Подключаемся к ноде и проверяем модули:
cat /proc/modules | grep -E 'algif_aead|esp4|esp6|rxrpc'

Если пусто, модули не загружены.
Пробуем загрузить принудительно:
modprobe algif_aead

Если Operation not permitted, не уязвимы.

Почему у нас не сработало, хотя версия ядра старая
У нас EKS с Bottlerocket AMI.
Bottlerocket по умолчанию запускается с
kernel.lockdown = integrity.

В этом режиме загрузка не подписанных модулей через modprobe из пространства пользователя запрещена.
То есть Copy Fail + Dirty Frag требуют загрузить модуль algif_aead (или esp4/esp6/rxrpc как обход), но lockdown просто не даёт это сделать.

Это не значит, что можно расслабиться.
Это значит, что есть один слой защиты.
Defence-in-depth требует добавить второй явный слой и всё равно обновить ядро.

Что делать в любом случае: явно блокируем модули
Независимо от того уязвимы вы или нет, правильнее явно запретить загрузку этих модулей.
Один lockdown это хорошо, но явный запрет лучше.

Bottlerocket (Terraform, launch template + user data):
Добавляем в bottlerocket.tpl:
[settings.kernel]
lockdown = "integrity"

[settings.kernel.modules.algif_aead]
allowed = false

[settings.kernel.modules.esp4]
allowed = false

[settings.kernel.modules.esp6]
allowed = false

[settings.kernel.modules.rxrpc]
allowed = false

Это работает на уровне Bottlerocket API.
Он сам создаст нужные записи в /etc/modprobe.d/ при старте ноды.

Если у вас Karpenter, то добавляете в NodeClass или EC2NodeClass в секцию userData аналогичный блок для вашего distro.
Если у вас самописные Terraform-модули для нод-групп, то смотрите где у вас формируется user_data для launch template.
Добавляете туда блок выше.
Паттерн один и тот же, разница только в синтаксисе шаблона.

Как проверить что всё применилось
Для Bottlerocket есть нативный способ: через apiclient прямо с ноды, без debug подов и без sheltie.
Работает через SSM send-command из любого места где есть aws cli.

Узнаём instance ID:
kubectl get node <имя_ноды> -o jsonpath='{.spec.providerID}' | sed 's|.*\/||'

Запускаем команду через SSM:
aws ssm send-command \
--instance-ids <instance-id> \
--document-name "AWS-RunShellScript" \
--parameters 'commands=["apiclient get settings.kernel"]' \
--region us-east-1


Смотрим результат:
aws ssm get-command-invocation \
--command-id <command-id> \
--instance-id <instance-id> \
--region us-east-1 \
--query 'StandardOutputContent' \
--output text

Если всё применилось, увидите:
{
"settings": {
"kernel": {
"lockdown": "integrity",
"modules": {
"algif_aead": { "allowed": false },
"esp4": { "allowed": false },
"esp6": { "allowed": false },
"rxrpc": { "allowed": false }
}
}
}
}


Если патч не применён, только lockdown, без modules:
{
"settings": {
"kernel": {
"lockdown": "integrity"
}
}
}


Это показывает конфиг именно так, как его видит сама OS.
Лучше чем смотреть файлы руками.
Можно спать дальше 🛌
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥21
Применять это в пятницу вечером на продакшне, я конечно же, не буду 😬
Please open Telegram to view this post
VIEW IN TELEGRAM
😁24
#devops #linux #security

Только-только отгремели два LPE
- https://copy.fail/
- https://github.com/V4bel/dirtyfrag

Не успели донести ещё до продакшна изменения-фиксы, так уже третья проблема прилетела.
- https://github.com/v12-security/pocs/tree/main/fragnesia

Какой ад, если честно 🤦‍♂️🤦‍♂️🤦‍♂️

Чот всё как-то проклято с этими LPE.
Ведь точно не последняя будет с такой-то волной интереса и доступностью AI агентов и ассистентов.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
внезапная #пятница

В 16.37 упала интеграция со Slack.

Сначала никто не придал значения: не грузятся картинки, не отправляются сообщения - бывает.
Но через несколько минут стало понятно, что вместе со Slack исчезло всё: алерты, уведомления, инциденты, интеграции с джира и другими системами.
Это была.. это была katastrofa!

Alertmanager и Grafana IRM продолжали честно, но грустно, стрелять событиями, но они уходили в пустоту.

Автономные AI-агенты, на которых недавно переложили реагирование на инциденты, перестали работать - им просто неоткуда было читать сигналы и некуда писать решения.

Прод уже начинал сыпаться: росла нагрузка, сервисы деградировали, поды уходили в рестарты.
Но в команде царила странная пауза.

Инженеры сидели в Slack и ждали, когда появится алерт.
Без него никто не понимал, куда смотреть и что именно сломалось.
Слишком многое теперь начиналось с уведомления.
Инженерам пришлось руками, РУКАМИ, писать в чаты Слака и телеги:
- "А у нас вообще есть инцидент?"
- "Кто on-call?"
- "Где это посмотреть, если нет алерта?"

- "А какой агент за это отвечает?"
- "а где хаддл?"
Ответа не было.

И только Валера, простой старый сисадмин, которого держали "на всякий случай", просто открыл Grafana и Прометиус в браузере. Без интеграций, без ботов, без AI.
Через пару минут он уже видел картину целиком.

Он зашёл в Alertmanager UI, сам прочитал алерты, потом пошёл в kubectl и начал разбираться, что происходит в кластере.
Без подсказок, без рекомендаций, без "предложенных действий" и MCP.
Просто как раньше.

Проблема нашлась быстро - кривой rollout положил часть прод-кластера.
Валера пофиксил деплой, проверил состояние, убедился, что метрики возвращаются в норму, и только после этого открыл Slack и сам, своими руками, без агентов, написал:
"Прод падал. Починил. Чекните."

Через несколько минут Slack ожил.
За ним - агенты.
Они прочитали тред, проанализировали данные и сгенерировали отчёт об инциденте.
А потом поставили Валере 👍
Потому что без интеграций они не умеют нихуя ничего.
А Валера - умеет.
😁48💯11🫡104👍2👏1