Jump to content
View in the app

A better way to browse. Learn more.

T.M.I IThub

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

IThub

Administrators
  • Joined

  • Last visited

Blog Entries posted by IThub

  1. Есть команды, которые надо вводить с холодной головой и полным осознанием последствий. rm -rf / — очевидный пример. Но среди разработчиков и DevOps есть своя версия этой русской рулетки — git push --force.
    Я работал тогда в продуктовой компании — делали SaaS-платформу для управления проектами. Небольшая команда, человек двенадцать, хороший продукт, живые клиенты, нормальный процесс разработки. Мы использовали GitHub, feature-ветки, pull requests, code review — всё как у взрослых.
    Репозиторий был защищён: ветка main заблокирована от прямых пушей, обязательный PR с одобрением от двух ревьюеров. Всё серьёзно. Но была одна маленькая деталь, которую мы упустили: ветка develop — наша основная рабочая ветка, куда мерджились все фичи перед выходом в main — была защищена только от обычного push. Не от push --force.
    Это упущение жило полтора года. До того утра.
    Антон — старший разработчик, умный, опытный, пять лет в команде — в среду утром пришёл на работу в слегка раздражённом состоянии. Накануне вечером работал из дома, что-то переделывал в своей feature-ветке, несколько раз rebase'ил на свежий develop, история коммитов запуталась. Он хотел сделать красиво — squash коммиты, причесать историю, залить обратно.
    Он сделал git rebase -i HEAD~15. Причесал. Сделал git push origin feature/my-branch. Получил ошибку — ветка расходилась с remote из-за rebase. Это нормально. Написал git push --force origin feature/my-branch.
    И тут автодополнение в его терминале сыграло злую шутку.
    Он не заметил. Нажал Enter. Терминал отработал молниеносно.
    git push --force origin develop
    Ветка develop теперь содержала только его пятнадцать причёсанных коммитов. Полгода работы двенадцати разработчиков — восемьсот с лишним коммитов, десятки смёрджённых feature-веток — перестали существовать в remote.
    Первым заметил Кирилл — он в это время делал git pull origin develop и увидел странное сообщение о том, что его локальная ветка «впереди» remote на 847 коммитов. Написал в слак: «ребят, что-то странное с develop».
    Я в это время пил кофе. Зашёл в GitHub. Посмотрел на историю develop. Увидел пятнадцать коммитов за подписью Антона.
    Поставил кружку. Написал в общий чат: «стоп, никто не делайте git pull и не трогайте develop».
    Антон в этот момент только что дошёл до своего рабочего места — потому что через тридцать секунд в чате появилось его сообщение: «ребята, кажется, я что-то сломал».
    Восстановление заняло примерно двадцать минут и было почти триумфальным.
    Git — распределённая система. Это означает, что у каждого разработчика в локальном репозитории была актуальная копия develop на момент последнего git fetch. У Кирилла — который как раз делал git pull в момент инцидента — локальная ветка содержала все 847 коммитов.
    # На машине Кирилла: git log origin/develop..develop --oneline | wc -l # 847 # Пришлось временно снять все защиты с ветки в GitHub # и залить обратно правильную историю git push --force origin develop Через двадцать минут develop снова содержал все 847 коммитов. Все локальные репозитории сделали git fetch. Ничего не потерялось.
    Антон написал мне в личку: «Максим, я понимаю что случилось. Хочу объяснить». Мы созвонились. Он рассказал про автодополнение, про то, как перепутал ветки. Голос у него был как у человека, который ещё не понял, уволен он или нет.
    Я сказал ему три вещи. Первое: никто ничего не потерял, всё восстановлено, все живы. Второе: это системная ошибка, не личная — защита ветки была настроена неправильно, и это моя ответственность как DevOps. Третье: мы немедленно это исправим.
    В тот же день мы включили защиту от force push на develop. Добавили в onboarding раздел «Никогда не используй git push --force без явного указания feature-ветки». Везде заменили --force на --force-with-lease — он проверяет что remote не изменился с момента вашего последнего fetch, и отказывает если кто-то уже запушил.
    Антон остался в команде. Ещё через полгода стал тимлидом.
    Самый важный вывод из этой истории не технический. Технический прост: защищайте все ветки от force push, используйте --force-with-lease, настройте алиасы.
    Важный вывод другой: реакция команды на инцидент определяет культуру команды. Можно было устроить показательную порку. Вместо этого мы исправили систему — и получили разработчика, который с тех пор параноидально аккуратен с git и научил этому ещё троих новых.
    Ошибки надо исправлять в системе. Не в людях.
    А git push --force без явного указания ветки — это как ходить с заряженным пистолетом без предохранителя. Рано или поздно что-то нажмётся не то.
  2. Эта история не о катастрофе — она о тех моментах, когда система работает именно так, как ты настроил, но совсем не так, как ты хотел.
    Мы запускали новый высоконагруженный сервис — рекомендательный движок. Перед запуском нужно было провести нагрузочный тест: убедиться что сервис держит планируемые 500 rps.
    Я накануне настроил nginx с rate limiting: 100 rps с одного IP, burst 200. Это защита от DDoS. Всё правильно, всё продуманно.
    На следующий день Вася из QA запустил нагрузочный тест с помощью k6 с офисного сервера. Офисный сервер имеет один внешний IP-адрес.
    Тест начался. Вася смотрел на метрики k6 — ошибки сыпались сразу: 503 Service Unavailable. Он написал мне: «Максим, сервис не выдерживает нагрузку, уже при 150 rps всё падает».
    Я зашёл в логи nginx. Увидел километры строк:
    [error] limiting requests, excess: 102.840 by zone "api_limit" Наш офисный сервер, с которого шёл тест, получил rate limit — и все 500 запросов в секунду, начиная со 101-го получали 503. Сервис при этом работал абсолютно нормально — его никто по-настоящему не нагружал.
    Я минуту просто смотрел в экран. Потом засмеялся — впервые за долгое время по-настоящему засмеялся в рабочее время.
    Мы добавили IP офисного нагрузочного сервера в whitelist. Провели нормальный тест. Сервис держал 800 rps без проблем. Все были довольны.
    Но главный урок этой истории не технический. Главный урок — это то, что перед тем как диагностировать проблему, надо убедиться что смотришь в нужное место. Вася видел ошибки и думал что сервис не справляется. Я видел ошибки и знал что это rate limit. Разница — в том, что смотрели на разные части системы.
    Коммуникация между QA и DevOps о том, с каких IP будет идти нагрузочный тест — теперь обязательный пункт в чеклисте перед любым нагрузочным тестированием. На ithub.uno есть хорошая статья про то, как правильно организовать этот процесс — рекомендую.
  3. Есть комментарии в коде, которые являются либо руководством к действию, либо тихим криком о помощи. Комментарии с «TODO» — это обещания, которые редко выполняются.
    Денис, бэкенд-разработчик с которым я пересекался на одном проекте, рассказал мне эту историю как предупреждение. История произошла на его предыдущем месте работы.
    Был endpoint /api/debug/users — он возвращал список всех пользователей с email, именами и датами регистрации. Без всякой авторизации. Создан во время разработки, чтобы фронтенд-разработчик мог быстро проверять данные.
    В коде стоял комментарий:
    # TODO: УБРАТЬ ПЕРЕД ДЕПЛОЕМ В ПРОД!!! # Только для разработки, не для продакшна @app.route('/api/debug/users') def debug_users(): users = User.query.all() return jsonify([u.to_dict() for u in users]) Три восклицательных знака. Заглавные буквы. Всё честно.
    Разработчик сделал деплой. TODO не убрал — дедлайн, «потом». Потом не наступило.
    Endpoint жил в проде тихо и незаметно два года. Через два года при проведении security audit penetration tester обнаружил его за тридцать секунд работы с Burp Suite. База данных на тот момент содержала информацию о 340,000 пользователей. Всё это время данные были доступны любому, кто знал URL.
    Конца истории Денис не знает — его к тому времени уже не было в той компании. Знает только что был большой скандал и несколько уволенных.
    В нашей команде после этой истории появился CI-шаг: grep по всему коду на паттерны TODO.*прод, TODO.*prod, REMOVE BEFORE, DEBUG ONLY. Если находит — пайплайн падает с ошибкой. Работает без единого ложного срабатывания уже полтора года.
  4. Самый коварный вид отказа систем — когда всё выглядит как работает, но не работает. Бэкап-система в этом смысле особенно опасна: вы никогда не проверяете её по-настоящему, пока не нужно восстановиться.
    Мой коллега Паша — педантичный и аккуратный инженер — настраивал резервное копирование для CRM-системы. Написал скрипт на bash: каждую ночь mysqldump, gzip, upload на S3. Всё логируется. При успехе в Slack приходит уведомление «Backup completed: 2.3GB».
    Скрипт работал восемь месяцев. Каждую ночь в Slack приходило: «Backup completed: 2.3GB». Красиво. Надёжно. Профессионально.
    Потом упал продакшн-сервер. Физически — сгорел диск. Паша пошёл восстанавливаться из бэкапа.
    Достал последний архив с S3. Распаковал. Открыл. Внутри был SQL-дамп базы данных information_schema. Не crm_production. А information_schema — системная база MySQL с метаданными: список таблиц, колонок, индексов. Никаких реальных данных.
    Паша открыл скрипт. Нашёл строку:
    mysqldump -u backup -p$PASS $DATABASE | gzip > backup.sql.gz Переменная $DATABASE. Посмотрел где она определяется:
    DATABASE=${DB_NAME:-information_schema} Переменная DB_NAME должна была передаваться через environment. Но при настройке cron-job он забыл добавить эту переменную. Cron запускал скрипт без переменной — скрипт использовал дефолтное значение information_schema — дамп создавался, весил 2.3GB (много метаданных за восемь месяцев), улетал на S3. Полное видимое благополучие.
    Восемь месяцев данных CRM были потеряны безвозвратно.
    После этого у нас появилось правило: бэкап-скрипт обязан проверять содержимое архива после создания. Не просто «файл существует» — а «внутри есть CREATE TABLE для нужных таблиц, INSERT строк больше нуля». И раз в месяц — тестовое восстановление в отдельную базу с проверкой количества записей.
    Если вы сейчас читаете это и у вас есть бэкап-система, которую вы ни разу не проверяли восстановлением — сделайте это сегодня. Не завтра. Сегодня.
  5. Это история о том, почему production дашборды должны быть красного цвета, а staging — зелёного. И почему вкладки браузера надо называть.
    Пятница. Последний рабочий день перед длинными майскими. Я чистил старый staging кластер Kubernetes — там скопился мусор за несколько месяцев. Namespace за namespace, удаляю deployment'ы, PVC, сервисы. Всё идёт хорошо. В соседней вкладке открыт продакшн дашборд — краем глаза поглядываю на метрики.
    Не помню точно как это случилось — кажется, я переключился между вкладками не обратив внимания. Увидел список namespace в дашборде. Увидел namespace с именем legacy-services — его я и собирался удалить в staging. Нажал Delete. Подтвердил (да, там был confirm dialog — и я его подтвердил, потому что только что двадцать раз делал то же самое).
    Через тридцать секунд в слаке началось:
    #alerts: CRITICAL: payment-service down #alerts: CRITICAL: auth-service down #alerts: CRITICAL: user-service down
    Я перевёл взгляд на адресную строку. Там был URL продакшн кластера.
    legacy-services в продакшне — это было название, которое выбрал кто-то три года назад. В нём жило восемь критических сервисов.
    Дальше начался самый быстрый деплой в моей карьере. ArgoCD хранил все манифесты, кластер был жив — я удалил только namespace с содержимым, но не сам кластер. Запустил sync для всех приложений через ArgoCD.
    Kubernetes начал поднимать поды. Stateless сервисы встали за две-три минуты. Payment-service — за пять, потому что у него была initContainer-миграция. Auth-service — за четыре.
    Общее время даунтайма: семь минут двадцать секунд.
    Что изменилось: все дашборды теперь имеют цветовую маркировку — продакшн красным, staging жёлтым, dev зелёным. Это реализовано через плагин kubie — при переключении в prod-контекст терминал меняет цвет prompt на красный. И главное — удаление namespace теперь требует ввода имени namespace вручную. Никаких кнопок «Delete» без явного подтверждения текстом.
  6. Есть баги, которые тихо портят данные и обнаруживаются через месяцы. А есть такие, которые существуют годами, всех раздражают, но никто не может их воспроизвести — потому что они зависят от часового пояса.
    Та система занималась планированием задач. Пользователь создаёт задачу на «завтра в 10:00» — система её выполняет в нужное время. Казалось бы, простейшая логика.
    Жалобы начались в марте. Клиенты из Екатеринбурга писали: «задачи выполняются не вовремя, иногда с опозданием на два часа». Я смотрел на логи — по нашим данным задачи выполнялись точно в срок. Поддержка закрывала тикеты: «не воспроизводится». Клиенты злились.
    Я взялся за это в начале апреля. Провёл два дня, читая код планировщика. Нашёл несколько мест где работа с временем выглядела подозрительно, отрефакторил — баг остался. Третий день — ревью всех datetime операций в системе. Ничего.
    На четвёртый день Игорь из поддержки сказал фразу, которая сразу всё объяснила:
    — Слушай, я заметил, что жалуются только пользователи из Екатеринбурга, Омска и вот этих городов...
    Он показал список. Я посмотрел на карту. Это были города в часовых поясах UTC+5 и восточнее.
    Зашёл на продакшн-сервер. Ввёл date. Увидел: Thu Apr 4 14:23:11 UTC 2024. Сервер работал в UTC. Это нормально. Проблема была в другом: когда пользователь из Екатеринбурга (UTC+5) создавал задачу на «завтра 10:00» через браузер, фронтенд отправлял строку 2024-04-05 10:00:00 — без timezone offset. Backend принимал её как UTC и сохранял в базу. Потом выполнял задачу в 10:00 UTC — что для пользователя в UTC+5 было 15:00 по местному времени.
    Пять часов разницы. Это проявилось только когда начали приходить пользователи из регионов — потому что первые клиенты и команда разработки были из Москвы (UTC+3), и у них разница была три часа, а не пять.
    Фикс: фронтенд теперь всегда отправляет datetime с timezone offset. Backend парсит только aware datetime объекты. На Хабре есть статья «Никогда не используйте naive datetime» — я её знал. Просто не я писал тот фрагмент. Теперь у нас есть линтер-правило, которое не даёт мержить код с naive datetime объектами.
  7. Автоматизация — это прекрасно. Автоматизация без ограничений — это финансовая катастрофа. Я усвоил этот урок очень конкретным способом: через счёт от AWS на $23,000 за четыре ночных часа.
    Мы настраивали горизонтальный автоскейлинг для API сервиса. Логика была простая: если CPU выше 70% — добавляем инстансы. Работало замечательно в рабочие часы. Что мы не предусмотрели — верхний лимит. Мы установили minReplicas: 2 и забыли про maxReplicas. В Kubernetes HPA это означает «масштабируй сколько нужно».
    В 2:47 ночи наш сервис получил DDoS-атаку. Не особо сложную — просто поток запросов, каждый из которых немного нагружал CPU. Автоскейлер увидел рост CPU и начал добавлять поды. Поды поднимались, нагрузка на каждый снижалась — но общий поток атаки оставался постоянным. Автоскейлер видел всё ещё высокую нагрузку и добавлял ещё. И ещё.
    В 4:15 у нас работало 847 инстансов одного сервиса. Нода-группа в AWS автоматически масштабировала EC2 — тоже без ограничений. Именно в этот момент сработал billing alert и разбудил меня.
    Я зашёл в AWS console полусонный. Увидел цифру. Проснулся мгновенно.
    Мы остановили атаку через WAF (пришлось поднять и настроить с нуля, потому что «руки не доходили» раньше — за десять минут). Потом убили лишние инстансы. Написали в AWS поддержку — они вернули около $18,000 как «goodwill credit», потому что это был явно аномальный spike. $5,000 мы всё же заплатили.
    Что изменили: maxReplicas в каждом HPA, budget alerts с автоматическим отключением при превышении, WAF с базовыми rate-limit правилами — теперь это первое, что поднимается для нового сервиса. И чеклист «Перед включением автоскейлинга», который мы опубликовали в нашей вики и в комьюнити на ithub.uno.
  8. Я долго не понимал, почему Kubernetes такой педантичный. Зачем все эти liveness probes, resource limits, PodDisruptionBudget — когда можно просто запустить контейнер и пусть работает? Потом был один день, который изменил моё отношение радикально.
    Мы деплоили крупное обновление — новая версия API с переработанной системой авторизации. Дата релиза была согласована с бизнесом, пресс-релиз готов, маркетинг ждёт. Всё тщательно проверено на стейджинге. Я жму deploy.
    Kubernetes начинает rolling update. Первые поды поднимаются — и тут Kubernetes останавливает деплой. Просто стоп. Ни один новый под не создаётся, старые не удаляются.
    Открываю kubectl describe pod — там написано: Readiness probe failed. Злюсь. Открываю логи пода. Вижу ошибку подключения к базе данных. Думаю: ну и что, это временная ошибка при старте, он бы сам восстановился. Хочу вручную форсировать деплой.
    Но что-то заставляет меня сначала проверить само соединение с базой. Открываю dashboard PostgreSQL — и вижу, что на новой версии приложения миграция схемы прошла неправильно. Один из индексов создался с ошибкой, из-за чего конкретный запрос в /api/v2/auth/check — тот самый, который проверяет readiness probe — возвращал 500.
    Если бы Kubernetes не остановил деплой, то старые поды с рабочей авторизацией были бы убиты, а новые — со сломанной — встали бы вместо них. Все пользователи получили бы 500 при попытке войти. Прямо в день анонса.
    Kubernetes оказался умнее меня. Его педантичность — которая меня так раздражала — спасла релиз.
    Мы откатили миграцию, исправили скрипт, прогнали ещё раз на стейджинге, задержали деплой на два часа. Бизнес поворчал — потом сказал спасибо, когда я объяснил альтернативу.
    С того дня я стал большим фанатом readiness probes. Не просто /healthz с ответом 200 — а настоящая проверка: соединение с базой, доступность зависимостей, корректность конфигурации.
  9. Это история о том, как можно делать всё правильно — и всё равно облажаться. Потому что правильные действия, направленные не туда — это хуже бездействия.
    Два года назад мы запускали новый микросервис — агрегатор данных для аналитики. Я настроил мониторинг: Prometheus, Grafana, alertmanager, всё по классике. Дашборд выглядел прекрасно. Зелёный. Живой. Метрики бежали в реальном времени.
    Через неделю аналитики начали жаловаться: данные в отчётах иногда выглядят странно, какие-то пропуски. Я смотрел на дашборд — сервис работает, ошибок нет, очередь обрабатывается.
    Ещё через неделю жалобы участились. Я снова смотрел на мониторинг. Снова — всё хорошо. Начал думать, что проблема в данных источника.
    На четырнадцатый день Саша из аналитики подошла ко мне с конкретным примером: вот событие, которое должно было попасть в базу вчера в 14:32 — его нет. Вот ещё пять таких событий за последние две недели.
    Я зашёл непосредственно на сервер, посмотрел логи — и увидел сотни ошибок коннекта к базе данных. Каждую минуту. Все последние две недели.
    Но мониторинг показывал зелёный!
    Через десять минут я нашёл причину. При настройке мониторинга я указал IP-адрес сервера вручную. Потом — за день до запуска — инфраструктурная команда переехала на новые машины и IP поменялся. Я обновил конфиг сервиса, но забыл обновить конфиг Prometheus. Prometheus две недели радостно скрейпил метрики другого сервера, которому достался старый IP.
    Все эти две недели я смотрел на графики совершенно нормально работающего чужого сервера. Пока наш тихо терял данные.
    Пропущенные события восстановить не удалось. После этого я перешёл на service discovery в Prometheus — никаких статических IP. Только DNS-имена или автоматическое обнаружение. И добавил тест: alertmanager должен прислать тестовый алерт при старте — чтобы убедиться, что нотификации реально доходят.
  10. Есть категория менеджеров, которые искренне верят, что перезагрузка решает все проблемы. Эту веру они несут через годы опыта работы с Windows на домашнем компьютере. Столкновение этой веры с реальностью продакшн-сервера — зрелище одновременно трагическое и поучительное.
    Эту историю рассказал мне Антон — DevOps в среднем онлайн-ретейлере — в баре, после второго бокала, с видом человека, который прошёл терапию, но ещё не полностью.
    Была пятница, около шести вечера. Их основной сервер начал подтормаживать — latency выросла раза в три. Антон уже нашёл проблему: утечка соединений в пуле базы данных, накопившаяся за неделю. Требовалось примерно двадцать минут на аккуратный фикс без рестарта.
    Тут появился продакт-менеджер Геннадий Витальевич.
    — Антон, у нас тормозит. Долго ещё? У меня через час встреча с клиентом.
    — Геннадий Витальевич, я нашёл проблему, фикс займёт минут двадцать, перезагрузка не нужна—
    — Просто перезагрузите сервер. Всегда помогает.
    — Нет, правда, в данном случае лучше не надо, потому что после перезагрузки будет несколько минут простоя—
    — Антон. Перезагрузите. Сервер.
    Антон перезагрузил сервер.
    Что он не знал — и что Геннадий Витальевич знать не мог — так это то, что накануне ночью обновился GRUB через автоматические обновления Ubuntu. Обновление прошло нормально, но файл конфигурации GRUB получил неверный UUID для корневого раздела. Система прекрасно работала — до первой перезагрузки.
    Сервер ушёл на перезагрузку. И не вернулся.
    Антон пять минут смотрел на консоль Hetzner с ошибкой Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0). Потом ещё пять минут просто сидел, не двигаясь.
    Дальнейшее — двухчасовая спасательная операция через rescue mode, ручное восстановление GRUB, три созвона с поддержкой хостинга и один звонок от директора с вопросом «что происходит». Геннадий Витальевич на встречу с клиентом опоздал на час пятнадцать.
    После этого в их компании появилось официальное правило: любая перезагрузка продакшн-сервера должна быть согласована с дежурным инженером, который проверяет чеклист из восьми пунктов. Геннадий Витальевич правило подписал. Говорят, без энтузиазма.
  11. Эту историю я долго не хотел рассказывать. Не потому что она страшная — потому что она embarrassing. Но потом я прочитал пост на ithub.uno о том, что культура безопасности строится на открытости, а не на замалчивании. И решился.
    Было это в 2019-м. Я настраивал GitLab CI для небольшого проекта — сервис рассылки уведомлений. В процессе отладки пайплайна мне нужен был быстрый тест. Я создал файл .env.test с заглушками: DB_PASSWORD=test123, API_KEY=dummy_key_for_testing, SMTP_PASSWORD=test123. Потом написал .gitlab-ci.yml, который деплоил приложение, и указал в нём cp .env.test .env — чтобы для CI это работало.
    Commit. Push. Пайплайн прошёл. Всё работает.
    Я написал нормальный продакшн конфиг, залил через GitLab Secrets как положено — и на этом моя работа с тем проектом закончилась. Меня перевели на другой.
    Проект жил своей жизнью. Рассылки уходили. Никто не проверял, откуда именно берутся credentials.
    Через три года я вернулся на тот проект для аудита. Открыл конфиг на сервере. Увидел DB_PASSWORD=test123. Мне понадобилось секунд тридцать, чтобы понять что произошло.
    Оказывается, команда cp .env.test .env в пайплайне выполнялась после загрузки GitLab Secrets и перезаписывала их. Три года подряд, при каждом деплое, на сервер улетал файл с паролем test123.
    Самое парадоксальное: база данных была доступна только изнутри приватной сети, поэтому этот пароль де-факто ни на что не влиял. Но это — счастливое стечение обстоятельств, а не правильная архитектура.
    Я провёл полный security audit. Нашёл ещё две похожих проблемы — других инженеров, таких же «временных» решений, ставших постоянными. Написал документ «Как мы храним секреты» и внедрил pre-commit hook, который ищет в коде паттерны типа password=test, key=dummy, secret=123.
    Но test123 в том конфиге я помню с фотографической точностью.
    Три восклицательных знака. Заглавные буквы. Всё честно.
    Разработчик сделал деплой. TODO не убрал — дедлайн, «потом». Потом не наступило.
    Endpoint жил в проде тихо и незаметно два года. Через два года при проведении security audit penetration tester обнаружил его за тридцать секунд работы с Burp Suite. База данных на тот момент содержала информацию о 340,000 пользователей. Всё это время данные были доступны любому, кто знал URL.
    Конца истории Денис не знает — его к тому времени уже не было в той компании. Знает только что был большой скандал и несколько уволенных.
    В нашей команде после этой истории появился CI-шаг: grep по всему коду на паттерны TODO.*прод, TODO.*prod, REMOVE BEFORE, DEBUG ONLY. Если находит — пайплайн падает с ошибкой. Работает без единого ложного срабатывания уже полтора года.
  12. В этой индустрии есть негласный закон: если что-то может сломаться в самый неподходящий момент — оно сломается именно тогда. Новогодняя ночь — идеальный момент для проверки этого закона.
    Я работал в финтех-компании. Мы делали платёжный шлюз. Нагрузка в новый год — одна из пиковых: все переводят деньги, покупают подарки в последний момент, пьют шампанское и одновременно пытаются провести транзакцию.
    31 декабря, примерно в 22:00 я сидел у родителей. Оливье, телевизор, ощущение что ты наконец человек, а не придаток к ноутбуку. Дежурство официально было у Димы. Я был «вторым уровнем».
    В 23:58 мне позвонил Дима. Голос у него был такой, что я сразу встал из-за стола и вышел в коридор.
    — Макс, у нас лежит. Всё. Payment gateway не отвечает. Метрики нормальные, сервисы запущены, но транзакции не проходят.
    Я открыл ноутбук прямо в коридоре, на тумбочке с телефонным аппаратом эпохи СССР. Зашёл в Grafana — всё зелёное. CPU нормальный, память нормальная, сетевой трафик... стоп. Входящий — есть. Исходящий — ноль. Абсолютный ноль. Сервисы запущены, слушают порты, принимают соединения — но ничего не отправляют в ответ.
    В это время в телевизоре начали бить куранты. Моя мама заглянула в коридор с бокалом шампанского. Я сделал жест «одну минуту» — что в нашей профессии означает «от тридцати минут до нескольких часов».
    Нашёл проблему через двадцать две минуты нового года. Оказалось, в 23:55 сработал cron-job, который запускался раз в год 31 декабря для «очистки годовых логов». Скрипт удалял log-файлы старше 365 дней — разумная идея. Но через glob-паттерн он также захватывал конфигурационный файл SSL-сертификатов. Сертификаты физически никуда не делись, но конфиг, который указывал на них — исчез. Nginx перечитал конфигурацию и тихо перестал устанавливать TLS-соединения с upstream банковским API, требовавшим mutual TLS.
    Фикс занял четыре минуты: восстановить конфиг из git, перезапустить nginx, убедиться что транзакции пошли.
    Я вернулся к столу в 00:31. Шампанское было тёплым. Оливье съели без меня.
    А тот cron-job мы заменили нормальным logrotate с явными паттернами. И добавили тест: после каждого cron-задания запускается smoke-test платёжной цепочки. Каждую ночь. Включая 31 декабря.ии. Знает только что был большой скандал и несколько уволенных.
    В нашей команде после этой истории появился CI-шаг: grep по всему коду на паттерны TODO.*прод, TODO.*prod, REMOVE BEFORE, DEBUG ONLY. Если находит — пайплайн падает с ошибкой. Работает без единого ложного срабатывания уже полтора года.
  13. Это был мой второй месяц на новом месте. Я ещё не до конца понимал архитектуру системы, но уже вполне уверенно держался — учился быстро, читал документацию запоем, задавал правильные вопросы. Тогда я считал, что всё идёт хорошо.
    Было обычное утро вторника. Технический директор Андрей зашёл ко мне с просьбой, которая казалась абсолютно невинной:
    — Макс, у нас заканчивается место на prod-db-01. Там где-то есть временные файлы от старых бэкапов, почисти, пожалуйста.
    — Хорошо, посмотрю.
    Я зашёл на сервер. Открыл df -h. Действительно — диск забит под 94%. Начал смотреть, где место. du -sh /* — ничего подозрительного. Тогда запустил find / -name "*.tmp" -type f — и вот оно, целая папка /var/backup/temp/ с файлами с расширением .tmp общим весом около 180 гигабайт.
    Временные файлы. Именно то, о чём говорил Андрей.
    Я выполнил rm -rf /var/backup/temp/. Получил ошибку прав. Повторил с sudo. Команда отработала молниеносно — что меня немного удивило: для 180 гигабайт это подозрительно быстро. Но я не придал этому значения.
    Через двадцать минут ко мне подошёл бэкенд-разработчик Слава с характерным выражением лица человека, которому только что сообщили о смерти любимого питомца:
    — Макс, у нас приложение упало. API не отвечает вообще. База говорит «connection refused».
    Я зашёл на сервер. Попробовал сделать простейший SELECT — и тут у меня похолодело внутри:
    ERROR: could not open file "base/16384/1259": No such file or directory Через три минуты до меня дошло: папка /var/backup/temp/ — это была не папка с временными бэкапами. Это был симлинк. Симлинк на /var/lib/postgresql/14/main/base/. Кто-то, видимо в процессе миграции полгода назад, создал символическую ссылку с историческим названием, и она там тихо жила. А я, такой молодец, удалил через неё всю директорию с данными PostgreSQL. Всю. До последнего файла.
    База данных была жива. Процесс работал. Но данных больше не существовало физически.
    Следующие два часа я провёл в состоянии, которое сложно описать словами. Это не паника — паника это когда хаотично двигаешься. Я наоборот — сидел совершенно неподвижно и методично восстанавливал базу из последнего бэкапа. Бэкап был. Слава богу, бэкап был. Последний — в 03:00 ночи. Мы потеряли восемь часов транзакций.
    Потом было долгое молчаливое совещание с Андреем. Он не кричал. Он вообще почти не говорил. Это было хуже крика.
    Я написал подробный post-mortem. Ввёл правило: перед любым rm на проде обязательно проверять ls -la и file — убедиться, что это не симлинк. Добавил в онбординг пункт о том, как работают симлинки в Linux.
    Восемь часов данных так и не восстановили. Клиенты получили извинения. Я остался работать — Андрей оказался человеком, который верит в то, что ошибки надо исправлять, а не наказывать за них. Но ту папку с симлинком я помню до сих пор.
  14. Карьера в IT: роли, задачи и возможности

    Мир IT огромен и многогранен: здесь нужны специалисты самых разных направлений, от продуктовой аналитики до DevOps и дизайна. Разберём ключевые роли, чтобы понять, кто за что отвечает и какие задачи выполняет.
    🔹 Продукт и аналитика
    1. Product Manager (PM)
    Роль: отвечает за продукт целиком — от идеи до метрик.
    Задачи:
    формировать стратегию продукта и ставить цели;
    проводить исследования, интервью с пользователями и анализ конкурентов;
    описывать функциональность (PRD, User Stories);
    расставлять приоритеты: что делаем сейчас, что откладываем;
    работать с командами разработки, дизайна и маркетинга;
    анализировать метрики, управлять ростом и оптимизировать продукт.
    Дополнительно: PM часто взаимодействует с бизнес-аналитиками и UX-командой, чтобы продукт был не только функциональным, но и востребованным.
    2. Business Analyst (BA)
    Роль: связывает бизнес-задачи с технической реализацией.
    Задачи:
    формализует требования бизнеса;
    анализирует процессы и выявляет узкие места;
    помогает команде разработки понять цели и приоритеты;
    участвует в тестировании и оценке фичей.
    Варианты: иногда BA объединяет функции PM или Data Analyst в небольших командах.
    🔹 Разработка
    3. Frontend Developer
    Роль: создаёт интерфейс — всё, что видит пользователь.
    Задачи:
    реализовывать дизайн в коде;
    создавать интерактивные элементы;
    подключать API и работать с данными;
    оптимизировать скорость загрузки страниц;
    поддерживать кроссбраузерность и адаптивность.
    Дополнительно: участвует в уточнении требований и тестировании UI.
    4. Backend Developer
    Роль: отвечает за серверную часть — «мозги» приложения.
    Задачи:
    разрабатывать API и бизнес-логику;
    работать с базами данных;
    создавать системы авторизации, уведомлений, платежей;
    обеспечивать безопасность данных;
    оптимизировать производительность серверов.
    5. Mobile Developer
    Роль: работает над мобильными приложениями.
    Задачи:
    создавать приложение под iOS и Android;
    реализовывать дизайн и бизнес-логику;
    оптимизировать работу под разные устройства;
    интегрировать API, пуш-уведомления, авторизацию и оплату;
    выпускать обновления и фиксить баги.
    6. Full-stack Developer
    Роль: закрывает фронтенд и бэкенд.
    Задачи:
    вести разработку «от интерфейса до базы данных»;
    быстро создавать прототипы;
    поддерживать продукт в малых командах;
    координировать взаимодействие между частями.
    7. QA Engineer (тестировщик)
    Роль: отвечает за качество продукта.
    Задачи:
    писать тест-кейсы и чек-листы;
    искать баги и оформлять отчёты;
    проверять фичи перед релизом;
    автоматизировать тесты (QA-автоматизатор);
    контролировать стабильность продукта после обновлений.
    🔹 Архитектура и инфраструктура
    8. System Architect
    Роль: проектирует структуру продукта.
    Задачи:
    выбирать архитектурные паттерны;
    проектировать взаимодействие сервисов;
    обеспечивать масштабируемость и надёжность;
    консультировать разработчиков по сложным задачам;
    решать, какие технологии использовать.
    9. DevOps / SRE
    Роль: отвечает за стабильность, инфраструктуру и автоматизацию.
    Задачи:
    настраивать и поддерживать серверы, контейнеры, облака;
    автоматизировать CI/CD;
    мониторить систему и устранять сбои;
    обеспечивать безопасность сервисов;
    оптимизировать стоимость инфраструктуры.
    10. Data Engineer
    Роль: работает с потоками данных.
    Задачи:
    строить ETL-пайплайны;
    настраивать хранилища, базы данных, Data Lakes;
    обеспечивать качество и доступность данных;
    оптимизировать процессы передачи данных.
    🔹 Аналитика и ML
    11. Data Analyst
    Роль: отвечает за анализ данных и выводы для бизнеса.
    Задачи:
    собирать данные из разных источников;
    строить дашборды и отчёты;
    искать аномалии, паттерны, точки роста;
    проводить A/B-тесты;
    отвечать на вопросы бизнеса цифрами.
    12. Data Scientist
    Роль: создаёт модели машинного обучения.
    Задачи:
    разрабатывать модели (рекомендации, прогнозы, классификация);
    готовить датасеты;
    обучать и тестировать модели;
    внедрять модели в продукт;
    анализировать качество моделей и корректировать алгоритмы.
    🔹 Дизайн и пользовательский опыт
    13. UX/UI Designer
    Роль: отвечает за интерфейсы и визуальную часть продукта.
    Задачи:
    исследовать пользователей и сценарии;
    строить CJM и проектировать логику экранов;
    создавать прототипы и макеты;
    работать с дизайн-системами;
    передавать макеты разработчикам.
    14. UX Researcher
    Роль: связывает продукт с реальными потребностями пользователей.
    Задачи:
    проводить интервью и исследования;
    устраивать юзабилити-тесты;
    формировать гипотезы и проверять их;
    давать рекомендации по улучшению продукта;
    подтверждать продуктовые решения данными.
    🔹 Контент и коммуникации
    15. Technical Writer
    Роль: создаёт документацию для пользователей и разработчиков.
    Задачи:
    писать инструкции, гайды, мануалы;
    описывать API и технические процессы;
    обновлять документацию после релизов;
    работать с разработчиками для уточнений.
    16. Community Manager
    Роль: выстраивает отношения с пользователями и сообществом.
    Задачи:
    отвечать на вопросы в чатах и соцсетях;
    собирать обратную связь;
    формировать лояльность пользователей;
    помогать пользователям решать проблемы;
    эскалировать важные запросы команде.
    🔹 Управление процессами
    17. Project Manager (PM / PMO)
    Роль: следит за тем, чтобы задачи выполнялись вовремя, а команда работала слаженно.
    Задачи:
    ставить задачи и планировать спринты;
    контролировать сроки и ресурсы;
    поддерживать коммуникацию между командами;
    снимать блокеры у специалистов;
    управлять рисками и таймлайнами.
  15. Представьте: вы сидите за монитором, на экране уже есть кнопки, текст, картинки. Всё вроде работает. И тут менеджер кидает новую фичу: «Сделай модалку с формой для отзывов». Казалось бы — мелочь. Но как это сделать так, чтобы не сломать весь фронтенд? Давайте разберём, что реально происходит, когда фронтенд-разработчик «ковыряет» код на React.
    💻 Фронтенд – это то, что видит пользователь
    Фронтенд — это интерфейс, всё, что юзер видит и трогает: кнопки, меню, формы, анимации.
    Фронтенд-разработчик не просто «рисует сайт». Он создаёт UX, разбивает интерфейс на компоненты, следит за рендерингом, а ещё иногда сражается с багами, которые появляются из ниоткуда.
    ⚛️ React – библиотека для сборки UI
    React — это как конструктор LEGO, только в мире фронтенда. Каждый компонент — это независимая деталь: кнопка, форма, карточка товара.
    Используя React, мы можем комбинировать эти кубики, создавать реактивные интерфейсы и управлять их состояниями (state).
    🧩 Фича – это новая функция, не меньше
    Когда фронтендер говорит «прикрутить фичу», это не просто «добавить элемент». Это продумать:
    структуру компонентов,
    state management,
    логику валидации,
    а иногда и асинхронные запросы к серверу через API.
    В нашем примере фича — это модалка с формой отзывов.
    🪟 Модальное окно – всплывающее окно поверх сайта
    Модалка — это UI overlay, который блокирует взаимодействие с остальной страницей до закрытия.
    Каждый фронтендер знает, что модалки могут стать хаотичными: неправильное состояние, баги с z-index, проблемы с focus trap — и вот уже страница ведёт себя как капризный робот.
    Компоненты, state и хуки
    Компонент — это атом интерфейса. Вместо монолитного кода у нас маленькие, тестируемые и переиспользуемые куски.
    State — внутренняя память компонента. Открыт модал или закрыт? Какие данные ввёл пользователь? Это всё хранится в state.
    useState — встроенный React Hook, который позволяет создавать и менять state. Ошибки с ним приводят к странному перерендеру или багам, которые тяжело отловить.
    🧾 Разметка и стили
    HTML = структура страницы
    CSS/SCSS = как эта структура выглядит
    JS/TS = как она реагирует на действия юзера
    «Накидать разметку» — это не просто вставить теги. Нужно учитывать accessibility, semantic HTML, а ещё то, как всё будет работать с React и его виртуальным DOM.
    ✅ Валидация формы
    Валидация проверяет, корректно ли пользователь заполняет поля.
    Для фронтендера это значит:
    подключить либы типа Yup или Zod,
    написать кастомные валидаторы,
    позаботиться о UX ошибок: показать подсказки, подсветить поля, не дать юзеру сломать приложение.
    ⚙️ Логика и дебаг
    Логика — это последовательность действий кода: что происходит при клике, при вводе, при отправке формы.
    Дебаг — это целая философия. Консоль браузера, React DevTools, breakpoints, network tab, иногда даже прямой просмотр state в Redux.
    Типичная ошибка фронтендера:
    TypeError: Cannot read property 'value' of nullОзначает: «Ты пытаешься достучаться до элемента, которого нет». Скорее всего, забыл добавить id или неправильно прокинул ref.
    🧪 Тестирование
    После исправления багов наступает этап QA на фронтенде:
    кликаем все кнопки,
    вводим разные данные,
    проверяем в разных браузерах,
    убеждаемся, что модалка не ломает остальной UI.
    Только после этого можно быть уверенным: фича рабочая.
    🌐 Итог
    Даже маленькая задача вроде модалки включает десятки понятий: компоненты, state, рендеринг, хуки, валидацию, дебаг, логику, тесты.
    И чем больше ковыряешь фронтенд, тем больше начинаешь ценить эти термины.
    Главное — не бояться лезть в код и разбираться, почему что-то ломается. Потому что именно так становится настоящим фронтендером.
  16. Технические интервью пугают не сложностью задач, а неопределённостью. Кажется, что могут спросить абсолютно всё — и поэтому многие начинают готовиться хаотично: читают десятки статей, пересматривают сотни видео, зубрят определения. Результат? Знаний больше, а уверенности — меньше.
    На самом деле, техническое собеседование устроено гораздо проще и предсказуемее, чем кажется. Если понимать, что проверяют на самом деле, подготовка превращается из хаотичного марафона в точечный и эффективный процесс.
    Что реально проверяют на техническом интервью
    Смотря на разные компании, подход почти всегда одинаковый:
    База и понимание, а не зубрёжка.
    Интервьюера интересует не «знаешь ли ты все методы массива», а понимаешь ли, как работает код. Часто просят объяснить понятие своими словами или разобрать на примере. И сразу видно, где теория заучена, а где есть настоящее понимание.
    Умение думать, а не угадывать.
    Даже если точного ответа нет, логическая цепочка рассуждений и умение задавать уточняющие вопросы сильно выигрывают у молчания или попыток вспомнить «правильную формулировку».
    Опыт применения знаний.
    Коммерческий проект, учебный проект — не важно. Главное, чтобы ты мог рассказать, где и как применял то, о чём говоришь. Пустые слова сразу считываются.
    Почему большинство проваливается
    Готовятся как к экзамену.
    Заученные ответы срабатывают до первого уточняющего вопроса. Как только интервьюер меняет формулировку или просит пример — «картонная» подготовка разваливается.
    Перекос в теорию.
    Можно часами объяснять, что такое замыкания или REST, но теряться при вопросе «покажи, как это выглядит в реальном проекте». Для работодателя это сигнал: знания не применялись на практике.
    Страх сказать «не знаю».
    Многие пытаются выкрутиться и уходят в общие слова, а честное «не знаю, но могу подумать» выглядит сильнее и честнее.
    Как готовиться правильно
    Ориентируйся на вакансии.
    Реальные описания вакансий показывают, что повторяется из раза в раз. Разбирай эти темы глубоко, не поверхностно.
    Объясняй вслух.
    Пока знания живут в голове, кажется, что всё понятно. Попробуй проговаривать темы — сразу видно пробелы. Это один из самых эффективных способов подготовки.
    Проекты как опора разговора.
    Проект нужен не для резюме, а как база для диалога. Ты должен уметь рассказать, что делал, почему выбрал подход и с какими трудностями столкнулся. Даже учебный проект может выглядеть убедительно, если ты понимаешь его.
    Тренируй сам формат интервью.
    Стресс, паузы, прямые вопросы — к этому нужно привыкнуть. Те, кто имитировал собеседования или уже проходил их, почти всегда выглядят сильнее.
    Итог
    Техническое интервью — это не тест на идеальность, а способ понять, можно ли с тобой работать как с инженером.
    Если ты:
    понимаешь базу,
    умеешь рассуждать,
    не боишься признавать пробелы,
    можешь рассказать про свой код —
    …то ты уже на практически стопроцентной дороге к успеху.
  17. Если ты начинающий frontend-разработчик, рано или поздно сталкиваешься с вечным вопросом: «Знаний много, а опыта работы нет. Что делать?»
    Ответ простой — делать pet-проекты.
    Что такое pet-проект и зачем он нужен
    Pet-проект — это личный или учебный проект, который ты создаешь самостоятельно, чтобы:
    Закрепить знания HTML, CSS, JavaScript.
    Показать, что умеешь работать с фреймворками (чаще всего React).
    Продемонстрировать мышление разработчика, а не просто умение сверстать экран.
    Для работодателя pet-проект — это возможность увидеть, как ты думаешь и решаешь реальные задачи.
    Почему большинство pet-проектов не помогают найти работу
    Типичные ошибки новичков:
    Слишком простые проекты. Todo-листы, калькуляторы или прогноз погоды без архитектуры и логики — это разминка, а не портфолио.
    Проекты не похожи на реальные задачи. Работодателю важно увидеть работу с состоянием, API, формами, ошибками, а не просто «сделал экран».
    Невозможно объяснить проект. Если ты не можешь рассказать, что и зачем сделал, проект не работает на собеседовании.
    Какой pet-проект действительно работает
    Хороший проект для junior frontend-разработчика:
    Заменяет коммерческий опыт.
    Показывает, как ты думаешь.
    Демонстрирует, что умеешь доводить задачи до конца.
    Характеристики:
    Решает понятную задачу.
    Использует современный стек (JavaScript / React / API).
    Имеет структуру, а не набор файлов.
    Содержит состояния, обработку ошибок, пользовательские сценарии.
    И главное — проект можно разобрать и защитить на собеседовании.
    Идеи pet-проектов, которые реально ценятся
    1. Упрощённый интернет-магазин
    Один из лучших вариантов для новичка.
    Что важно реализовать:
    Каталог товаров.
    Фильтры и сортировку.
    Корзину и работу с состоянием.
    Загрузку данных через API или mock-сервер.
    Такой проект показывает, что ты понимаешь, как выглядят реальные frontend-задачи.
    2. Личный кабинет пользователя
    Проект ближе к реальным продуктам.
    Можно добавить:
    Регистрацию и авторизацию.
    Формы с валидацией и обработку ошибок.
    Редактирование профиля.
    Работа с токенами на базовом уровне.
    3. Дашборд с данными
    Сильный проект, если сделан грамотно:
    Аналитика продаж или статистика пользователей.
    Трекинг задач и прогресса.
    Показывает умение работать с графиками, таблицами, состояниями.
    4. Сервис с поиском и фильтрами
    Отличная идея для демонстрации frontend-навыков:
    Работа с API и асинхронность.
    Отображение состояний: loading / error / empty.
    Базовая архитектура компонентов.
    Примеры: каталог фильмов, база книг, список курсов или вакансий.
    Сколько pet-проектов нужно junior frontend-разработчику
    Частый вопрос: «Сколько проектов достаточно?»
    Ответ: 2–4 продуманных проекта лучше, чем 10 слабых.
    Идеальный набор:
    1 крупный проект.
    1–2 средних.
    1 экспериментальный, где видно твой рост.
    Как оформить pet-проект для портфолио
    Чтобы проект реально работал на трудоустройство:
    Выложи код на GitHub.
    Напиши понятный README.
    Опиши, какие задачи решал.
    Добавь деплой (GitHub Pages, Vercel).
    Будь готов объяснить архитектурные решения.
    Помни: работодатели оценивают не только результат, но и ход мысли.
    Итог
    Pet-проекты — это не формальность и не «галочка». Это главный инструмент, который заменяет коммерческий опыт на старте.
    Если хочешь работать frontend-разработчиком:
    Делай проекты, похожие на реальные продукты.
    Думай как инженер, а не ученик.
    Используй проекты как повод для диалога с работодателем.
  18. DevOps — это не профессия.
    Это состояние души, когда ты одновременно чинишь прод, объясняешь, что он «не падал», и пишешь постмортем, в котором виноват «непредсказуемый внешний фактор».
    Если программисты шутят про код, то DevOps шутят про боль.
    Про ночь без сна. Про алерты всюду. Про «всё работало на стейдже».
    Ниже — подборка самых смешных и одновременно правдивых DevOps-шуток, которые любят люди из индустрии. Если ты смеёшься — значит, ты в теме. Если не смеёшься — подожди, скоро дойдёт.
    1. DevOps — это когда ты знаешь, почему всё упало
    …но не знаешь, кто именно это сделал.
    2. «У нас ничего не менялось»
    — последняя фраза перед инцидентом.
    3. Прод не упал
    Он просто временно перешёл в режим обучения пользователей терпению.
    4. DevOps не ломают прод
    Они проверяют отказоустойчивость в боевых условиях.
    5.
    — Почему сервис упал?
    — Потому что он был жив.
    6. Лучший мониторинг — это Twitter
    Пользователи всегда узнают первыми.
    7. Если у тебя нет бэкапа —
    значит, ты веришь в себя.
    8. DevOps — это человек,
    который может исправить проблему за 5 минут,
    но будет объяснять, почему она произошла, две недели.
    9. Всё автоматизировано
    …кроме того момента, когда горит прод.
    10. «Это не баг, это фича»
    В DevOps-версии звучит так:
    «Это временное архитектурное решение».
    11.
    — Можно задеплоить в пятницу?
    — Можно.
    — А вы смелый.
    12. Kubernetes решает все проблемы
    …кроме тех, которые он создаёт.
    13. DevOps — это когда ты знаешь,
    что алерт сработал правильно,
    но всё равно его ненавидишь.
    14. Самый надёжный сервер —
    тот, к которому никто не прикасался.
    15. Если сервис работает —
    не трогай его.
    Если не работает —
    не трогай его ещё сильнее.
    16. «Мы просто обновили одну маленькую зависимость»
    — историческая причина 90% аварий.
    17. Хороший DevOps не тот,
    у кого ничего не падает,
    а тот, кто знает, где лежит кофе в 3 ночи.
    18. Infrastructure as Code —
    пока не нужно срочно починить одну мелочь в проде.
    19.
    — Почему алерты не пришли?
    — Потому что алерты тоже лежат.
    20. Самый опасный человек в компании —
    DevOps с правами администратора
    и хорошим настроением.
    21. «Мы воспроизвели проблему»
    — и она исчезла.
    22. Если DevOps молчит —
    значит, либо всё идеально,
    либо он уже принял неизбежное.
    23. Документация — это то,
    что обязательно появится после инцидента.
    24. DevOps — это когда ты одновременно
    инженер, психолог и громоотвод.
    25. Всё можно починить
    …если у тебя есть доступы и rollback.
    Вместо вывода
    DevOps-шутки смешные не потому, что они черный юмор.
    А потому что они слишком правдивые.
    Если ты узнал себя хотя бы в половине — поздравляю, ты настоящий DevOps.
    Если во всех — пожалуйста, возьми выходной.
  19. Многие уверены, что программисты — замкнутые интроверты, которые разговаривают только с монитором и питаются кофе.
    На самом деле это не так.
    Программисты — это люди с богатым внутренним миром, высокой концентрацией на цели и очень специфическим чувством юмора 🤓
    Да, их шутки не всегда понятны тем, кто далёк от IT, но именно в этом и суть — они смешные, болезненно правдивые и иногда пугающе точные.
    Итак, встречайте: топ-30 шуток о программистах, после которых вы либо засмеётесь, либо задумаетесь, либо уволитесь.
    1. Не переживай, если что-то не работает как надо.
    Если бы всё работало идеально — тебя бы здесь давно не было 😌
    2. С программистами есть одна проблема:
    ты не понимаешь, что он делает… пока не становится слишком поздно 😐
    3. Настоящий программист всегда смотрит налево и направо,
    даже переходя улицу с односторонним движением 🚦
    4. Плохо написанный код одного —
    это стабильная работа и хлеб другого 🍞
    5. Если девушка просит починить компьютер — не радуйся.
    Возможно, там уже ничего не спасти 💀
    6. Пиши код так, будто человек, который будет его поддерживать,
    — психопат…
    и он знает, где ты живёшь 🔪
    7. Не получилось написать хорошую программу с первого раза?
    Назови её «Версия 1.0».
    Все так делают 👍
    8. Придя на работу, не торопись начинать.
    Дай компьютеру прогреться минут 20.
    Он тоже не жаворонок ☕💤
    9. Никогда нет времени сделать всё правильно…
    Зато всегда хватает времени сделать ещё больше неправильно 🤦‍♂️
    10. Компьютер — это зло 😈
    Но стоит его выключить, как появляются два новых зла:
    телевизор 📺 и холодильник 🥪
    11. 90% кода занимают 90% времени проекта.
    Оставшиеся 10% кода требуют ещё 90–100% времени.
    Магия ✨
    12. Существует два типа языков программирования:
    на одни все жалуются,
    а другими никто не пользуется 🤷‍♂️
    13. Всегда не хватает времени на разработку,
    но его почему-то хватает, чтобы сделать вдвое больше багов 🐞🐞
    14. Если бы появился язык программирования на разговорном английском,
    выяснилось бы, что большинство программистов его не знают 🇬🇧❌
    15. Если в Java добавят функцию очистки мусора,
    большинство Java-приложений удалят себя сразу после установки 🗑️
    16. В теории между теорией и практикой нет разницы.
    На практике — есть 😬
    17. Компьютерам можно доверять…
    пока они не научились думать самостоятельно 🤖
    18. Сходство между Java и JavaScript
    примерно как между Сомали и сомом 🐟
    19. Плохого кода не существует.
    Есть код, который неправильно поняли 🙃
    20. Перед тем как удалить файл, убедись, что он твой.
    Самые надёжные компоненты — те, которых нет ❌
    21. Если айтишник пришёл на работу вовремя —
    значит, он просто не уходил 🌙
    22. Слишком много мыслей в голове?
    Попробуй… заархивировать 📦
    23. Хотел задать вопрос:
    IT — это ориентация или всё-таки диагноз? 🤔
    24. Вы даже не представляете,
    сколько психической энергии разработчики потратили,
    пытаясь понять разницу между алгоритмом и программой 🧠🔥
    25. Бог создал мир за 6 дней по одной простой причине —
    у него не было предыдущих версий 🌍
    26. Хотите получать от программирования только пользу?
    Ответ прост:
    не программируйте 😎
    27. Главная задача разработки —
    сделать что-то, что доживёт хотя бы до релиза 🏗️
    28. Компьютер отлично выполняет инструкции,
    но, к сожалению, не читает ваши мысли 🧠❌
    29. Финальной версии не будет,
    пока жив хотя бы один пользователь 👀
    30. Баг — это не ошибка.
    Это ещё не задокументированная фича 🐞✨

  20. Top DevOps Jokes That Hit Way Too Close to Home

    DevOps is not a profession.
    It’s a state of mind where you’re fixing prod, explaining that it “never actually went down,” and writing a postmortem blaming an “unpredictable external factor” — all at the same time.
    If programmers joke about code, DevOps joke about pain.
    About nights. About alerts. About “it worked fine on staging.”
    Below is a collection of the funniest and at the same time painfully accurate DevOps jokes loved by people in the industry.
    If you’re laughing — you’re one of us.
    If you’re not — give it time. It will hit you.
    DevOps is when you know why everything went down
    …but you don’t know who did it.
    “Nothing has changed”
    —the last sentence before an incident.
    Prod didn’t go down.
    It temporarily entered user patience training mode.
    DevOps don’t break prod.
    They test fault tolerance in real combat conditions.

    — Why did the service go down?
    — Because it was alive.
    The best monitoring system is Twitter.
    Users always find out first.
    If you don’t have backups —
    it means you believe in yourself.
    A DevOps engineer is someone
    who can fix an issue in 5 minutes,
    but will spend two weeks explaining why it happened.
    Everything is automated
    …except the moment when prod is on fire.
    “It’s not a bug, it’s a feature.”
    In DevOps language, that’s:
    “It’s a temporary architectural decision.”

    — Can we deploy on Friday?
    — We can.
    — You’re a brave person.
    Kubernetes solves all problems
    …except the ones it creates.
    DevOps is when you know
    the alert fired correctly,
    but you still hate it.
    The most reliable server
    is the one nobody touched.
    If a service works —
    don’t touch it.
    If it doesn’t work —
    don’t touch it even harder.
    “We just updated one small dependency”
    —the historical cause of 90% of outages.
    A good DevOps engineer isn’t the one
    whose systems never go down,
    but the one who knows where the coffee is at 3 a.m.
    Infrastructure as Code —
    until you urgently need to hotfix one tiny thing in prod.

    — Why didn’t the alerts fire?
    — Because the alerts are down too.
    The most dangerous person in a company
    is a DevOps engineer with admin rights
    and a good mood.
    “We reproduced the issue”
    —and it disappeared.
    If a DevOps engineer is silent —
    either everything is perfect,
    or they’ve already accepted the inevitable.
    Documentation is something
    that will definitely appear after the incident.
    DevOps is when you are simultaneously
    an engineer, a psychologist, and a lightning rod.
    Everything can be fixed
    …if you have access and a rollback.
    Final Thoughts
    DevOps jokes aren’t funny because they’re mean.
    They’re funny because they’re too true.
    If you recognized yourself in at least half — congratulations, you’re a real DevOps engineer.
    If in all of them — please take a day off.
  21. Top 30 Programmer Jokes (ENG Ver)

    Many people believe that programmers are socially awkward introverts who only talk to their monitors and survive on coffee.
    That’s not entirely true.
    Programmers are people with rich inner worlds, extreme focus on goals, and a very specific sense of humor 🤓
    Yes, their jokes aren’t always clear to those far from IT — but that’s the point. They’re funny, painfully honest, and sometimes frighteningly accurate.
    So here it is: the top 30 programmer jokes that will make you either laugh, think… or quit your job.
    Don’t worry if something doesn’t work as expected.
    If everything worked perfectly, you wouldn’t be here 😌
    There’s one problem with programmers:
    you don’t understand what they’re doing… until it’s too late 😐
    A real programmer always looks left and right,
    even when crossing a one-way street 🚦
    Bad code written by one developer
    is job security and daily bread for another 🍞
    If a girl asks you to “fix her computer,” don’t get excited.
    There might be nothing left to save 💀
    Write code as if the person who will maintain it
    is a psychopath…
    and knows where you live 🔪
    Didn’t manage to write a good program on the first try?
    Call it “Version 1.0.”
    Everyone does 👍
    When you get to work, don’t rush to start coding.
    Give the computer 20 minutes to warm up.
    It’s not a morning person either ☕💤
    There’s never enough time to do things right…
    But there’s always enough time to do them wrong again 🤦‍♂️
    A computer is evil 😈
    But turn it off and two new evils appear:
    the TV 📺 and the fridge 🥪
    90% of the code takes 90% of the project time.
    The remaining 10% takes another 90–100%.
    Magic ✨
    There are only two kinds of programming languages:
    those everyone complains about,
    and those nobody uses 🤷‍♂️
    There’s never enough time for development,
    but somehow there’s always time to create twice as many bugs 🐞🐞
    If a programming language were invented in plain spoken English,
    it would turn out that most programmers don’t actually know English 🇬🇧❌
    If Java ever gets a “clean garbage” function,
    most Java apps will delete themselves right after installation 🗑️
    In theory, there’s no difference between theory and practice.
    In practice — there is 😬
    You can trust computers…
    until they learn to think for themselves 🤖
    The similarity between Java and JavaScript
    is about the same as between Somalia and a salmon 🐟
    There is no bad code.
    There is only code that was misunderstood 🙃
    Before deleting a file, make sure it’s yours.
    The most reliable components are the ones that don’t exist ❌
    If an IT guy shows up to work on time,
    it means he never went home 🌙
    Too many thoughts in your head?
    Try… compressing them 📦
    Serious question:
    is IT an orientation or a medical condition? 🤔
    You have no idea
    how much mental energy developers have wasted
    trying to understand the difference between an algorithm and a program 🧠🔥
    God created the world in six days for one simple reason —
    there were no previous versions 🌍
    Want to get only benefits from programming?
    The answer is simple:
    don’t program 😎
    The main goal of development
    is to build something that survives at least until release 🏗️
    A computer follows instructions perfectly,
    but unfortunately, it doesn’t read your mind 🧠❌
    There will never be a final version
    as long as at least one user is still alive 👀
    A bug is not a mistake.
    It’s just an undocumented feature 🐞✨

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.