Make. Build. Break. Reflect.
909 subscribers
115 photos
1 video
119 links
Полезные советы, всратые истории, странные шутки и заметки на полях от @kruchkov_alexandr
Download Telegram
#бытовое

Мечтал я о столе.
Рабочий стол.
Чтоб был чуть выше обычного(мне так хочется).
Не шатался как припадочный при любом касании(95% столов в масс маркете).
Полочки были выдвижные 6-7 сантиметров высотой внутри, не больше, не меньше, убрать все мелкие вещи, от часов, проводов и документов до приставки и джойстика.
Глубокая столешница 80 см(беречь глаза) и длина 160 см(постоянно приходит кот и занимает всё пространство при столе 120-140см).
Поверхность не шершавая, чтобы локти не были как у бабушки.

После долгих поисков в продаже не нашёл, в итоге пришлось делать на заказ в несколько этапов:
- подбор макетов (pinterest.com)
- сварка конструкции
- покраска порошковой краской
- заказ столешницы (ну там, обрез, шпон все дела и так далее) на заводе при магазине столешниц
- сбор и монтаж столешницы, полочек и фасадов
Вообще пальцем не касался в процессе, всё делали специалисты за деньги.

Денег ушло море, времени тоже море, но результат мне пока нравится.
Пока, безусловно, непривычно сидеть, но я надеюсь на положительный результат и одни плюсы от такого опыта.
Со временем быть может добавлю дополнительный монитор или кронштейн заменю(мне не нравится текущая низкая высота). Может и кабель менеджмент запилю.
Стул La Deshman' меня пока тоже устраивает, но присматриваюсь через пару зарплат к ErgoChair Pro
👍17🔥5💊32
#aws #azure #finops #fuckup

Ну что ж, истории про мои всратости и заоблачные прайсы в облаках..
Критикал счетов не было, все терпимые и, к сожалению, за дело.
Ниже перечислены ошибки со стороны команды или девопс/инфра инженера.

1) Datadog + все(!) ивенты AWS EKS + все(!) логи приложений в AWS EKS.
~$11600 за 4 дня из-за кинконглионов событий и метрик.

2) AWS RDS + зачем-то general log + CloudWatch + unlimited retention.
~$2600 за несколько дней(пятница-понедельник утро).

3) Нескончаемое количество раз все ML/DWH/AI сервисов.
Например использование мультирегион дисков с репликацией для кеша в Trino.
~$4300 за месяц.
Или, например ЗАЧЕМ-ТО запуск AWS Kendra раз в сутки(30 баксов в день) вместо запуска 2 раза в месяц
~$150, за 5 дней

4) CloudFront(все настройки по дефолту) + s3 бакетом с файлами дистрибутивами программы + "клиент решил массово установить наш софт по всем компьютерам своей локальной сети через планировщик задач. Однако, как оказалось, прав на установку не хватило, задача вошла в цикл и выкачала несколько десятков терабайт с нашего s3 (файл вроде около 15 мегабайт).
~$450 за 2 дня.
Зато узнали много нового про WAF + код ответа 429 после этого.

5) AWS MSK + огромная цифра на макс сторадж скейлере + изначально большой сторадж + отсутствие алёртов на эти события и нет аномали детекшн + анлимитед ретеншн тайм у топика. Бинго как обычно. Бинго на максималке.
Разработчики начали писать годзиллионы событий в один топик. Нечто типа уровень дебага. Дев энвайронмент.
Каждые 4 часа сторадж скейлился на 10%.
Могу соврать, то там формула будет нечто такого:
Vn = V0 × (1.1)^n

где:
- V0 = 1000 (начальный объем),
- n = 180 (число увеличений за месяц, каждое через 4 часа),
- 1.1 = коэффициент роста (10% увеличение).
Короче как бы там не было, но из 1000 гигабайт, недели через 3-4 (не уследили) уперелось в максимум 16 терабайт и кластер превратился в тыкву.
~$4100 за сторадж отдали.

6) AWS EKS + большое значение макс нод + cluster autoscaler + неверные аффинити/антиафинити. Вместо динамического увеличения нод получили неприлично большое количество нод.
ну типа
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- {{ .Release.Name }}
topologyKey: kubernetes.io/hostname

вместо
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- {{ .Release.Name }}
topologyKey: kubernetes.io/hostname

Вроде всего ~$700 за сутки за EC2 инстансы. Никаких алёртов на количество нод не было, спасло аномали детекшн.

7) Кто-то разместил ссылку на s3 бакет напрямую на веб-портале.
Не срабатывал WAF от CloudFront и снова траты при циклическом запуске со стороны клиента.
~$180 за сутки

8) Какая-то галочка в Azure OpenAI в балансировке.
Честно не помню параметр, но при частом использовании OpenAI в аппликейшн + этот параметр в API Management service сожрал много.
~$11300 за три недели🤡

Были и более мелкие, тысяча стори🤦🏽, но там уровня "девопс инженер пошёл в бар и потратил больше".
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14😨43🔥1🤡1
#aws #vanta #ai #azure

На этом моём скриншоте прекрасно всё.
Добро пожаловать в 2025 год.

Vanta, компания, которая за огромные деньги позволяет проходить аудит от SOC2 до PCIDSS, при помощи AI генерирует рекомендации с несуществующими ресурсами терраформ.

У меня всё.
😁41👏4🤡1
#kubernetes

Настройка пула соединений для базы данных в Kubernetes.

А как же правильно настроить пул соединений при работе с приложениями в Kubernetes?
У нас же много nodes, PODs, всё динамически, везде скейлинг количества подов.
Не будет ли проблем с тем, что закончились коннекшны к базе и новые поды не смогут подключится?
Проблемы будут, надо считать.

Для начала нам надо понять какая база данных у нас.
Допустим реляционная база данных MySQL.
В зависимости от железа(CPU/Memory) у нас есть разное значение параметра max_connections
Сам параметр этот динамический, значение можно рассчитать и установить самому, либо взять дефолтное(например в облачной базе данных).
Для простоты расчётов будем считать, что у нас max_connections = 1000. Вы берёте свою цифру своего сервера.
- Первым делом нам надо зарезервировать 5 коннекшнов под административные нужды.
Например в случае проблем у нас будет шанс, что мы(инженеры/SRE) сможем к базе подключение сделать.
max_connections_db = max_connections - 5
max_connections_db = 1000 - 5 = 995

- У нас так же включен скейлинг приложений-клиентов через KEDA/HPA со значениями
min PODs = 2, max PODs = 30.

- Для расчета размера пула соединений на под (pool_size_per_pod) используется формула
pool_size_per_pod = floor(max_connections_db / N)

где N текущее количество подов (2 ≤ N ≤ 30).
pool_size_per_pod = floor(995 / 30) ≈ 33 соединения на под

Можно было бы на этом остановится, но это будет ошибка.

У нас время от времени проходит деплой и поднимаются новые реплики, которые тоже занимают пул соединений.
Предположим, что у нас Rolling Update + maxSurge = 25%.
Это означает, что во время деплоя может быть создано до 25% дополнительных подов сверх текущего количества.
Максимальное количество подов с учетом maxSurge
N_max_with_surge = ceil(N × (1 + 0.25)) = ceil(N × 1.25)

и для худшего случая в режиме максимальной нагрузки N=30
N_max_with_surge = ceil(30 × 1.25) = ceil(37.5) = 38

Тогда размер пула соединений на под с учетом maxSurge:
pool_size_per_pod = floor(max_connections_db / N_max_with_surge) = floor(995 / 38) ≈ 26

Итак, мы получили цифру 26.
Теперь мы можем добавить её в переменные окружения нашего golang аппликейшна.
poolSizeStr := os.Getenv("DB_POOL_SIZE")

и в ваш yaml/values файл типа
env:
- name: DB_POOL_SIZE
value: "26"


Итого: расчет пула соединений это простая арифметика, которая не зависит напрямую от Kubernetes, но требует учета его особенностей (KEDA, maxSurge, несколько дата центров например - не рассматривал в примере выше). Настройка пула соединений обеспечивает стабильную работу системы без превышения лимита соединений даже при максимальном масштабировании и деплое.
Наш расчёт пула соединений на POD (26) учитывает maxSurge = 25%, KEDA (2–30 подов) и резерв в 5 соединений, гарантируя стабильность системы.

* традиционно я мог забыть о чём то и не учесть, могут быть специфичные случаи(например несколько разных микросервисов к одной единой для них БД), я лишь рассматриваю базовый, чтобы вам ну хоть от чего-то отталкиваться в расчётах.
🔥14👍31
#docker #devsecops #paranoia #devops

Что у нас есть в пайплайнах?
Линтер питон скриптов, валидация YAML, tflint для терраформа, checkov для безопасности, git-leaks, sonarqube, скоринг кода, sast, dast и многое другое. Миллионы всего.
Всем и всё это знакомо.

А что по Dockerfile?
Есть великолепный проект для простых проверок:
https://github.com/hadolint/hadolint

Его можно добавить в pre-commit hook
https://github.com/hadolint/hadolint/blob/master/.pre-commit-hooks.yaml
Можно добавить в pipeline.
Что он умеет?
- проверка и анализ Docker на соответствие лучшим практикам
- интеграция с ShellCheck (моя любовь ❤️), но нужно не для всех
- гибкий конфиг через .hadolint.yaml
- поддержка игнора
- интеграция с CICD

Всё-всё, хватит пустых слов, что он умеет можно почитать и в документации, давайте к практике и примеру.

Добавляем его в наш основной канико(да когда ж ты умрёшь?!) имадж, используемый для сборок:
FROM gcr.io/kaniko-project/executor:v1.23.1-debug

ENV TRIVY_VERSION=0.61.0 \
CRANE_VERSION=0.19.0 \
HADOLINT=v2.12.0

RUN wget --no-verbose https://github.com/aquasecurity/trivy/releases/download/v${TRIVY_VERSION}/trivy_${TRIVY_VERSION}_Linux-64bit.tar.gz && \
tar -zxvf trivy_${TRIVY_VERSION}_Linux-64bit.tar.gz -C /kaniko && \
rm -f trivy_${TRIVY_VERSION}_Linux-64bit.tar.gz

RUN wget --no-verbose https://github.com/google/go-containerregistry/releases/download/v${CRANE_VERSION}/go-containerregistry_Linux_x86_64.tar.gz && \
tar -zxvf go-containerregistry_Linux_x86_64.tar.gz -C /kaniko && \
rm -f go-containerregistry_Linux_x86_64.tar.gz && \
rm -f /kaniko/LICENSE /kaniko/README.md

RUN wget --no-verbose https://github.com/hadolint/hadolint/releases/download/${HADOLINT}/hadolint-Linux-x86_64 && \
mv hadolint-Linux-x86_64 /kaniko/hadolint && \
chmod +x /kaniko/hadolint


Ок, базовый имадж есть.
Теперь добавляем его в основной общий пайплайн.
Например запускать можно так на этапе сборки имаджа.
# Lint the Dockerfile
echo "Executing hadolint check on $dockerfilePath"
/kaniko/hadolint $dockerfilePath --error DL3006 --error DL3007 --failure-threshold error

Что тут проверяем?
- чтобы всегда стоял тег бейз имаджа
https://github.com/hadolint/hadolint/wiki/DL3006
- чтобы тег бейз имаджа был НЕ latest
https://github.com/hadolint/hadolint/wiki/DL3007

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

Ещё один инструмент в нашем бесконечном списке бесконечных инструментов.
👍17
#azure #metrics #aks

А какие же есть преимущества у ажура?
Всратость❤️.

Взять, к примеру, метрики контрол плейна.
На одном кластере оно может показать нормальную метрику apiserver_request_total - ожидаемое около 30 рпс.
На другом кластере показать 500.000 рпс.
А на третьем кластере прыгать от 30 до 300.000 рпс.
Завтра везде будет уже по нулям.

Добро пожаловать в ажур❤️.

* реальное значение около 50-60
😁10😱4🤡1
#пятница

Я:
Выйду, пожалуй, на улицу.
Потрогать траву, посмотреть на людей и стены, подышать воздухом.
Лишь бы ничего не напоминало о работе. Забыть обо всём.

Улица:
Ага, ну давай 🤣
Please open Telegram to view this post
VIEW IN TELEGRAM
🤣11🐳1💯1
#caddy #nginx

Какой же веб/прокси/реверс-прокси сервер выбрать в 2025 для мелких/простых/пет задач?
Я люблю Caddy последние месяцы. У него много вещей "из коробки" - по дефолту.
Caddy автоматически настраивает HTTPS через Let's Encrypt, в отличие от Nginx, где нужны ручные настройки сертификатов и поддерживает WebSocket без явного указания.
Сильно упрощает жизнь.

Спросите меня, а чем же упрощение?
Отвечу вам просто двумя файлами конфигурацией с идентичной функциональностью.

- конфиг на Nginx
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://127.0.0.1:5003;
proxy_set_header Host $host;
# websockets
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
server {
listen 80;
server_name example.com;
if ($host = example.com) {
return 301 https://$host$request_uri;
}
return 404;
}


- конфиг на Caddy
example.com {
reverse_proxy 127.0.0.1:5003
}


Выбор за вами что вам удобнее и проще.

* не является рекомендацией.
** не тестировалось на хайлоаде, где Nginx обычно эффективнее.
*** Caddy может потреблять больше ресурсов, чем с Nginx (go-based vs С-based)
👍17
#curl #troubleshooting

История из жизни.


Как-то переводили с одного домена на другой проект.
Доменов много, рулсов много, в одном из пунктов плана перехода была организация редиректов.
Ну типа запилили новый домен, а со старого домена прямо в CloudFlare сделали редирект (+ rules).
Сильно застрял при проверке старого домена с редиректом на новый.
Ну не проходят POST запросы с пейлоад до конечного бекэнда при помощи curl.
Признаюсь честно - долго просидел и тогда не было нейронок, чтобы попробовала бы помочь при дебагинге.
Сейчас бы я сам себя тогда уволил дал леща за тупость и бессмысленную трату времени.
Копал в редиректы, новый домен, неверную архитектуру, терраформ, DNS клауд провайдера и многое другое.

Оказалось дело было не в самом редиректе или домене, а в curl.
То есть всё итак работало, но сами тесты при помощи curl были неправильными.
Ведь обидно, всё облазил, все интернеты, а ответ, как всегда, был на видном месте - в документации
В моем случае надо было добавить два флага:
- --location (чтобы курл последовал за редиректом)
- --post302 (not convert POST requests into GET requests when following a 302 redirection)

Source:
https://curl.se/docs/manpage.html#--post301
https://curl.se/docs/manpage.html#--post302

Почему так?
Согласно RFC 7231, при 302 редиректе клиент (например, curl) может по умолчанию изменить метод с POST на GET.
И ваш пейлоад просто аннигилируется, тесты не проходят.🚶‍♀
Чтобы избежать этого, нужно явно указывать --post302 или же использовать 307 редирект* , который сохраняет метод запроса.
Source:
https://www.ietf.org/rfc/rfc7231.txt
Note: For historical reasons, a user agent MAY change the request
method from POST to GET for the subsequent request. If this
behavior is undesired, the 307 (Temporary Redirect) status code
can be used instead.


Вывод: Перед переключением доменов читайте документацию и проверяйте, как редиректы влияют на запросы и разные методы.

* Некоторые DNS/CDN провайдеры имеют лишь ограниченный список поддерживаемых кодов редиректа.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16🔥71
#мысли

В DevOps-практиках не хватает* термина alert fatigue.

Это состояние, когда инженеры и операторы перегружены тысячами уведомлений от систем мониторинга, observability-инструментов, инфраструктурных алертов и метрик приложений.
В 2025 году, с обилием инструментов и тестов, поток алертов превращается в шум.
Даже тщательно настроенные системы мониторинга со временем становятся неуправляемыми: уведомления поступают непрерывно, теряют ценность, и команды начинают их игнорировать или отключать.
Это не просто раздражение - это угроза надежности систем, когда критические сигналы теряются в потоке бесполезных сообщений.
Смартфон с отдельным приложением, слак, почта, звонки, смс, голуби и совы бьются в окна, доставляя уведомления.

Что с этим делать?
Пока точного решения нет.
Есть общие идеи, которые кажутся очевидными всем:
- Сократить количество алертов, настраивая их на основе SLA/SLO, чтобы фокусироваться только на метриках, - влияющих на бизнес-цели и пользовательский опыт.
- Группировать связанные уведомления в единые инциденты.
- Регулярно пересматривать и удалять устаревшие алерты.
- Автоматизировать рутинные действия для низкоприоритетных проблем.

Мне кажется, что наше будущее - за группировкой алертов в единые инциденты.

Рассмотрим пару примеров.
Представьте ситуацию: на одном из подов с базой данных закончилось место на диске (PV).
В результате мы получаем множество алертов:
- Ошибка репликации между нодами кластера.
- Нехватка места на PV.
- Рестарт проб на поде (не всегда).
- Ошибки от приложений, подключающихся к базе данных (до 50 алертов).
- Высокий IOPS (честно говоря не понимаю природу почему IOPS растёт, когда диск резко в 0 уходит, возможно, из-за интенсивных попыток записи при заполненном диске).
- Ошибки самого приложения (около 4-6 алертов), не связанные с инфраструктурой.
- Status Page тоже сигнализирует о проблеме.
И это далеко не всё.

Добавим вторую ситуацию.
Выпустили новую версию приложения и допустили ошибку в работе с API.
В результате мы видим алерты:
- Повышенная латентность API (ответы >500 мс)
- Увеличение количества HTTP 500 ошибок
- Превышение лимита времени ожидания (timeout) на стороне клиента
- Высокая загрузка CPU на серверах приложения из-за бесконечного цикла в коде
- Ошибки в логах приложения, связанные с некорректной обработкой запросов(opensearch monitor).
- Status page сервиса пишет о деградации

В единичном случае такая картина полезна: мы видим полную информацию и быстро понимаем источник проблемы. Но при масштабировании или повторении подобных инцидентов количество алертов становится неуправляемым, и мы начинаем их игнорировать.
При группировке алертов, например, в Slack, логично создавать отдельный тред для каждого инцидента.
Все связанные алерты отправляются в этот тред. Внутрь одного инцидента
Если в компании есть дежурный (on-call), он автоматически подписывается на тред (современные инструменты, такие как PagerDuty или Opsgenie, это поддерживают) и видит все уведомления в контексте.
Остальные инженеры и продакт-оунеры не отвлекаются на шум.

Как это реализовать?
Пока идей немного.
Можно разработать собственную систему управления инцидентами(Incident Management System) или использовать готовое решение с поддержкой AI, таких как PagerDuty или Splunk On-Call, которые уже умеют коррелировать алерты.

Чего ждать в будущем?
Думаю мы всё же должны прийти к группировке алёртов в единые инциденты.
Что получится в итоге мы узнаем лишь спустя время.

* Скорее всего этот термин уже есть, возможно его придумали миллиард лет до моего рождения, но во всяком случае мы в компании и все мои коллеги/приятели уделяем ему слишком мало времени и не понимаем реальной угрозы бизнесу.
🤔6👍43😱1🤡1🙈1
#docker #troubleshooting #одинденьизжизни

"Тревога-тревога, волк унёс зайчат!"
"Алекс, не работает VPN"

И сразу от нескольких человек.

Ну не работает, ну ладно.
Чего хоть не работает? Спрашиваем.
Ага, с ресолвами.
Ага, с доступом до ресурсов. Снова днс.
Пробую сам сделать коннект - ошибка.
Захожу в аминку впн - ошибка в UI.
Ладно.

Хер знает как у нас работает впн, сам никогда не лез.
Сам только тыкал мышкой в "коннект" на клиенте и всё.
Заходим в репозиторий с VPN/infra.
Ага, виртуальная машина, внутри докеры-полупокеры, юзердата шелл скрипт и tailscale админка.

Ну в целом понятно.
Всё на виртуалке, никаких кубернетисов.
Логи вряд ли мне, несведущему, чему-то помогут, пойдём сперва попроще.
Что может быть? Может диск заполнился.
Графана, дашборд node exporter - всё ок. Ни скачков по диску, ни по IOPS, ни по сети.
Эм, ну ок.
Может ажур поднасрал? Ни автоапдейтов, ни ивентов, ничего по ажуру.
Жаль, а так хотелось поху*сосить ажур снова.

Ну чо, впн это блокер для команды, нет времени разбираться.
Семь бед - один ресет.
Захожу в ажур, выбираю VM, делаю рестарт.
Помогло, но лишь частично - админка UI заработала и начали работать коннекты, но проблема с днс осталась.
Копаем дальше.
Дальше нырнув в код, вижу есть и пара других VM в инфре для впн.
У них так же явный трабл с DNS.
Ну я же синёр - повторяем семь бед - один ресет обеих тачек.
После рестарта всё заработало, клиенты довольны, команда больше не в блокере, днс ресолвит.

Теперь можно налить чай и дебажить "а чо было", да и надо куда-то часы трекера списать.
На час окунулся в логи приложения - ничего особо не понял, я половины терминов и компонентов даже не знаю, ну так же про днс что-то.
Пошли на виртуалки. Джампхост, ссш, шелл.
Смотрим какие у нас services есть, доступны ли все.
Все есть, все доступны.
Однако логи докера(компоуз) дали наводку.
~$ sudo journalctl -u docker
...
****** 02 14:41:32 ******-vm-us-3 dockerd[1989830]: time="20**-06-02T14:41:32.495924354Z" level=error msg="[resolver] failed to query external DNS server" client-addr="udp:127.0.0.1:57484" dns-server="udp:12>
****** 05 05:43:42 ******-vm-us-3 dockerd[1989830]: time="20**-06-05T05:43:42.432809963Z" level=error msg="[resolver] failed to query external DNS server" client-addr="udp:127.0.0.1:60244" dns-server="udp:12>

И так по кругу на миллион сообщений.
Значит проблема не со стороны аппликейшна в докере(компоузе), а с сетью - уровень докер лейера или операционной системы(скорее всего).
Ладно, а чо у нас с остальными логами.
Видим, что утром начался авто апдейт (unattended-upgrades в убунту).
То есть авто апдейт не на уровне ажура, а самой операционке.
******-06-10 06:17:03,994 INFO Starting unattended upgrades script
******-06-10 06:17:03,995 INFO Allowed origins are: o=Ubuntu,a=jammy, o=Ubuntu,a=jammy-security, o=Docker,a=jammy, o=UbuntuESMApps,a=jammy-apps-security, o=UbuntuESM,a=jammy-infra-security
******-06-10 06:17:03,995 INFO Initial blacklist:
******-06-10 06:17:03,995 INFO Initial whitelist (not strict):
******-06-10 06:17:09,777 INFO Packages that will be upgraded: apport libnss-systemd libpam-systemd libsystemd0 libudev1 python3-apport python3-problem-report systemd systemd-sysv udev
******-06-10 06:17:09,777 INFO Writing dpkg log to /var/log/unattended-upgrades/unattended-upgrades-dpkg.log
******-06-10 06:18:00,563 INFO All upgrades installed

И.. и всё, компонент systemd-resolved не захотел подниматься после апдейта.
****** 10 06:17:24 ******-vm-us-3 systemd-resolved[2663737]: Positive Trust Anchors:
****** 10 06:17:24 ******-vm-us-3 systemd-resolved[2663737]: . IN DS 20326 8 2 e06d44b80b8f1d3457104237c7f8ec8d
****** 10 06:17:24 ******-vm-us-3 systemd-resolved[2663737]: Negative trust anchors: home.arpa *.in-addr.arpa *.172.in-addr.arpa ***.192.in-addr.arpa d.f.ip6.arpa corp home internal intranet lan local private test
****** 10 06:17:24 ******-vm-us-3 systemd-resolved[2663737]: Using system hostname '******-vm-us-3'.
****** 10 06:17:24 ******-vm-us-3 systemd-resolved[2663737]: Failed to connect to system bus: Permission denied
****** 10 06:17:24 ******-vm-us-3 systemd-resolved
🔥8👍3👀3😨21😁1
* аригато Павел Дуров, половина сообщения пропала в предыдущем посте, но ладно.😭


****** 10 06:17:24 ******-vm-us-3 systemd-resolved[2663737]: Positive Trust Anchors:
****** 10 06:17:24 ******-vm-us-3 systemd-resolved[2663737]: . IN DS 20326 8 2 e06d44b80b8f1d39a95c0b0d7c65d08458e880409bbc683457104237c7f8ec8d
****** 10 06:17:24 ******-vm-us-3 systemd-resolved[2663737]: Negative trust anchors: home.arpa *.in-addr.arpa *.172.in-addr.arpa ***.192.in-addr.arpa d.f.ip6.arpa corp home internal intranet lan local private test
****** 10 06:17:24 ******-vm-us-3 systemd-resolved[2663737]: Using system hostname '******-vm-us-3'.
****** 10 06:17:24 ******-vm-us-3 systemd-resolved[2663737]: Failed to connect to system bus: Permission denied
****** 10 06:17:24 ******-vm-us-3 systemd-resolved[2663737]: Could not create manager: Permission denied
****** 10 06:17:24 ******-vm-us-3 systemd[1]: systemd-resolved.service: Main process exited, code=exited, status=1/FAILURE
****** 10 06:17:24 ******-vm-us-3 systemd[1]: systemd-resolved.service: Failed with result 'exit-code'.
****** 10 06:17:24 ******-vm-us-3 systemd[1]: Failed to start Network Name Resolution.
****** 10 06:17:24 ******-vm-us-3 systemd[1]: systemd-resolved.service: Scheduled restart job, restart counter is at 1.



В общем что у нас есть:
- пришёл автоапдейт пакетов операционной системы unattended-upgrades
- после апдейта не поднялся systemd-resolved
- на вм начались проблемы, впн не работает
- все кричат про неработающий впн

Что будем делать? А ничего.
Это такой уровень шизы контроля, что делать ничего не будем.
Автоапдейты не хочется отключать.
Ставить какие-то алерты, автофайловеры, отслеживание логов - всё это бред.
Бизнес никогда не примет и не поймет все часы, которые уйдут на превентивные меры подобной задачи.
За два года аптаймов этих ВМ это впервые. Маловероятно, что это повторится ещё года два.
Поэтому просто пишем коллегам о кейсе, пишем postmortem и идём дальше жить и работать.
Трекаем часы и возвращаемся к своим кубернетисам.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13🔥3💯3🤡1
#security #git #devops

Часть 1 из 2.

Рано или поздно все инженеры начинают расти профессионально.
Мы узнаем лучшие практики, оптимизируем существующий стек или инфру, внедряем новые технологии.
В какой-то момент мы даже следуем бест практис по security.
Добавление сканеров, проверки на бесящие всех CVE, пайплайны, pre-commit hooks и selinux/securitycontext.
Перечислять всё не буду, это невероятно огромная область.

Но интернет git всё помнит.
Git is the source of truth, как говорит мой коллега.
Это сейчас мы внедрили все практики и больше нет утечек паролей и токенов в гит, а храним всё в vault/aws sm/azure sa.
А что же в истории git?
В гите у нас могут остаться:
- токены
- private keys
- пароли

Давайте проверим и почистим за собой в репозитории.

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

Предварительная подготовка
- установить gitleaks https://github.com/gitleaks/gitleaks
Эта штука позволяет найти секреты во всех ветках всех файлах всей гит истории.
Описание есть в ридми.
- устанавливаем java
- устанавливаем bfg https://rtyley.github.io/bfg-repo-cleaner/
я просто сделал так
wget https://repo1.maven.org/maven2/com/madgag/bfg/1.14.0/bfg-1.14.0.jar

Эта штука помогает удалить лишнее найденное из гита.
- устанавливаем jq https://github.com/jqlang/jq
эта штука нам нужна для разового парсинга
- ну и git

Приступаем к поиску и очистке.
- форкаем себе рандом популярный проект, а почему бы и да
Ищём тут https://github.com/trending?since=monthly
есть какой-то microsoft/qlib
- клонируем себе форкнутый проект (у вас путь другой будет само собой)
git clone git@github.com:kruchkov-alexandr/qlib.git

- запускаем сканер утечки чувствительных данных не меняя директорию
>gitleaks detect --source qlib --log-opts="--all" --report-path findings.json


│╲
│ ○
○ ░
░ gitleaks

12:23PM INF 1790 commits scanned.
12:23PM INF scan completed in 696ms
12:23PM WRN leaks found: 1

Результатом будет джейсон файл с детальным описанием кто, когда, что и за тип секретов.
Можете открыть и посмотреть, что там утек 1 токен от разработчика(он может быть и реальным и фейком).
- Для удобства очищаем его от всего лишнего
cat findings.json | jq -r '.[].Secret' > passwords.txt

Для чего мы это делаем?
Чтобы сгенерить и проверить содержимое файла passwords.txt и ЕСЛИ в нём есть то, чего НЕ НАДО удалять из гита и оно бы осталось в гите, надо убрать из этого файла.
В этом файле то, что будет в последствии удалено из гита.
- заходим в гит репозиторий
cd qlib

- запускам bfg
>java -jar ../bfg-1.14.0.jar --replace-text ../passwords.txt

Видим длинную простыню текста, типа
Commit Tree-Dirt History
------------------------
Earliest Latest
| |
.........................................................DDm
D = dirty commits (file tree fixed)
m = modified commits (commit message or parents changed)
. = clean commits (no changes to file tree)

Before After
-------------------------------------------
First modified commit | 21f0b394 | b3d34764
Last dirty commit | 63021018 | abf5a1bf
Changed files
-------------
Filename Before & After
---------------------------------------------------
data.py | 8de32f3f ⇒ 82298fe3, f6bd7809 ⇒ 8bd16038
In total, 159 object ids were changed. Full details are logged here:
/home/***/GIT/INTERNET/qlib.bfg-report/2025-06-12/12-24-52

- ещё раз смотрим чего же мы там меняем(если есть хоть любые сомнения, прерывайте процесс! операция без бекапов не поддаётся восстановлению!!!)
cat /home/***/GIT/INTERNET/qlib.bfg-report/202*-0*-**/12-24-52/changed-files.txt
8de32f3f6c0373ca1b41fe6d3f4dbd4c23685d71 82298fe3811f0c36aa982a1ff23ee92289cc9346 data.py
f6bd780905649d8d004c13bd98a91044958b9573 8bd160386147b2007172e618dbe049b02cd4bcc3 data.py
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6😨2
#security #git #devops

Часть 2 из 2.

- теперь мы выдыхаем, принимаем решение и чистим
git reflog expire --expire=now --all && git gc --prune=now --aggressive

Это мы почистили ЛОКАЛЬНО гит, пока на ремоут сервер не заливали.
- проверяем, что локально всё чисто
cd ..
>gitleaks detect --source qlib --log-opts="--all" --report-path findings.json


│╲
│ ○
○ ░
░ gitleaks

12:29PM INF 1790 commits scanned.
12:29PM INF scan completed in 722ms
12:29PM INF no leaks found

То есть проверка показала, что все токены и пароли были удалены.
- крестимся и пушим в ремоут
cd qlib
git push origin --force

Всё, история в нашем форке почищена.
Можно ещё раз проверить всё
- удаляем локальный репозиторий
cd ..
sudo rm -r qlib

- клонируем с ремоута
git clone git@github.com:kruchkov-alexandr/qlib.git

- проверяем на утечки
gitleaks detect --source qlib --log-opts="--all" --report-path findings.json


│╲
│ ○
○ ░
░ gitleaks

12:33PM INF 1790 commits scanned.
12:33PM INF scan completed in 731ms
12:33PM INF no leaks found

- радуемся, что даже в истории гита нет утечек

Инструкция написана максимально подробно, чтобы те, кто подобного раньше никогда не делали, не допустили бы глупых ошибок. Сперва потренируйтесь на паблик репозиториях, отточите все действия до полного понимания и только потом надо чистить реальные репозитории на работе.
На реальных боевых репозиториях в идеале сделать бекап, прям gzip файлом, до всех изменений, если опыта мало и только потом приступать.

Инструкция длинная, кажется сложно, но на самом деле это лишь 5 команд и всё.
Не бойтесь. Вы - инженер.
👍16
#docker #troubleshooting #одинденьизжизни

Иногда нам всем нужна Лицензия на Убийство Костыль.
Как в одном из фильмов про Бонда.

Ситуация: резко к вам прибегают и говорят "У НАС ПРОБЛЕЕЕМА".
Нырнув внутрь "проблемы", понимаю, что 19 из 20 разных микросервисов на разных стеках начали ругаться на один из веб-сайтов партнёров. Что-то не так с сертификатом.
Проверяем изнутри пода
> curl https://*******.com/
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.haxx.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

Проверяю локально - всё ок с сайтом(он не наш).
Ладно.
Лезем в гугл спрашиваем в чате девопс_ру чего есть ныне для анализа SSL.
Дали рекомендацию - https://www.ssllabs.com/
Проверяю сайт - ранг B, в целом всё ок, но есть вопросики.
Они обновили новый серт, у нового серта новый УЦ(я так понял).

Созвон с коллегами, говорю так и так, сайт чужой, проблема с ним, у нас вроде всё ок.
Однако бизнес не согласен со мной(и, наверное, прав на 100%).
Говорят "да, мы знаем, что проблема скорее всего не у нас. Да, мы поняли, что это надо им писать. Но у нас бизнес и денежки, Пока они(владельцы сайта-партнёра) отреагируют, у нас не ок работает НАШ бизнес.
А где НАШ бизнес - там проблема у нас. Возможно ли быстро решить нашими средствами эту проблему?
"
Чуток поэкспериментировал локально, за пять минут нашёл пару очевидных решений.
Спрашиваю лицензию на костыль, мне дают карт-бланш.

Ну ок, лицензия получена, пилим фиксы.
В одном имадже (где старые from имаджи)
FROM node:*****
...
# temporary fix for https://*****.com/
RUN wget https://sectigo.tbs-certificats.com/SectigoPublicServerAuthenticationRootR46.crt -O /usr/local/share/ca-certificates/sectigo-root.crt && update-ca-certificates
...

В другом имадже залепить, если ещё нет, и пересобрать
...
RUN update-ca-certificates
...

(показываю одним слоём, но вообще он был добавлен к один длинный run).
Да, было добавление ca-certificates, но не было команды на апдейт 🐒

И так далее.

Пересобираем, деплоим, проблема ушла.
Ура, бизнес ликует.

Выводы:
А кто тут виноват? Я не знаю.
Владелец сайта и новый УЦ?
Наши "устаревшие сервисы" со старым списком со старыми сертами?
Отсутствие регулярных пересборок имаджей и скачивание всех новых сертов?
Чёрт его знает.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍141🤡1
#одинденьизжизни

Факапы и сроки.

А вот мало когда мне удавалось в своей жизни спланировать сроки.
Задача А - 2 часа, задача Б - 2 дня.
Ну не, к сожалению, у меня так не работает.

Допустим задача "установить впн сервер".
Казалось бы простая задача. Возьми да установи.
Для начала мы сравниваем что есть на рынке, смотрим фичи(платные, бесплатные), потом спрашиваем бизнес чего он сам хочет, какие есть требования аудитов сейчас и в будущем. Количество сотрудников, кто будет пользоваться.
В общем составляем картину задачи. На это уходит время.
Все требования собраны, все софты сведены в табличку(опенсорс и платные).
По ходу принято решение руководства/коллег/заказчика/лида, что опенсорс не для нас, потому как если не будет того, кто это поддерживает, то такое решение никому не нужно.
Допустим выбираем два решения - потестировать.
Пока идём по плану времени на задачу.
Приступаем к тестам. тестируем оба решения на базовые вещи из требований - SSO, routing, monitoring, audit etc.
На это снова уходит время, уже начинаю отклонятся от плана.
Опустим требования, которые были от компании/коллег/заказчика, но в итоге выбрали совместными усилиями pritunl.
Ок, он так он.
Начинаю пилить боевую инфру - терраформ, днс, секьюрити груп и прочие компоненты для инсталляции.
Почти всё готово (базовая инсталляция, без настройки).
Несколько раз гоняю планы/апплаи, то сперва работало, то теперь не работает.
Начал ковыряться в логах - оказывается у встроенного certbot с ssl сертификатом есть ограничения.
https://letsencrypt.org/docs/rate-limits/#new-certificates-per-exact-set-of-hostnames
И следующая регистрация только через сутки🤦‍♂️
Ок, хочется настроить уже с нормальным сертом (+ ажур аппликейшн адрес), ждём сутки.
Пулл реквест не стал пилить, оставил на завтра, ушел спать.
Пришёл утром - сервера нет. Ночью была авария, коллеги с другого часового пояса делали срочные изменения инфры, перетерли стейт с моей ветки. Проблемы терраформа и одного стейта.
Ладно. Мержим с мастера, снова апплаим с ветки, настроили, с сертом уже проблем нет.
Однако всплыла другая проблема - при вводе лицензии мы видим, что у нас УЖЕ используется одна лицензия.
С удаленного сервера.
Ну типа и платить двое больше, пробуем поиграться с кнопочкой удаления лицензии, кнопка есть, а лицензия не удаляется из аккаунта.
Ладно, потом разберёмся. ПР, аппрув, мерж в мастер, всё раскатывается.
Хочу уже на "боевом" сервере начать вносить правки, но теперь активны две лицензии, и если введу в третий раз - будет третья лицензия и будет прайс х3.
Пишу имейл в саппорт, жду ответа.
Снова ждать.

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

Вот так задача в условные 8 часов превратилась в 20+ часов и ещё не закончена.
Не все 20 часов её делал, и трекать надо меньше, но финальный срок "когда впн будет готов для всех" сильно отличается от первоначальной оценки.

Не знаю как у других, но планирование у меня частенько хромает. Увы.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍202😁1🤡1