DevOps в тапках


Kanal geosi va tili: Rossiya, Ruscha


Канал про DevOps без галстуков. Jenkins, Kubernetes, Terraform, CI/CD, GitLab, Prometheus и всё, что можно настроить в тапках. Полезные штуки, фейлы и практика.

Bog‘liq kanallar

Kanal geosi va tili
Rossiya, Ruscha
Statistika
Postlar filtri


Сегодня поразмышляю про КВН, маршрутизацию и давай запихнём туда весь Интернет

Периодически меня спрашивают, откуда я беру списки доменов и IP-адресов для маршрутизации через КВН.

Есть замечательные готовые проекты, которые мне прислали, которые я изучил, вроде Antifilter.Download или V2Fly Domain List Community или keneetic-antifilter и ещё 100500 других которых на гитхабе полно.

Сразу скажу 〰️ я ничего не имею против самих проектов. Более того, это огромная работа, и тот же V2Fly прямо пишет, что его база не определяет, какой домен нужно блокировать или отправлять через прокси. Это набор данных, из которого предполагается строить собственные правила.

Проблема начинается тогда, когда подобный список скачивают целиком и говорят 📢

Ну всё. Вот это отправляем через КВН.

И тут у меня как у человека, который хоть немного дружит с сетями, начинает дёргаться глаз. 😨

В таких community-базах могут быть огромные категории сервисов, компаний, CDN, инфраструктурных доменов, подсетей и зависимостей. Например, одна только категория category-companies у V2Fly включает Apple, Amazon, Adobe, Cisco, Microsoft, NVIDIA, Oracle, Sony, Yahoo, Яндекс, МТС, Ростелеком, Selectel и ещё десятки компаний. 🤪

А дальше одна категория включает другую, та 〰️ третью, появляются domain, full, keyword, regexp, целые географические группы… 🙈

И в какой-то момент возникает закономерный вопрос ❓

А мы РКН обходим или строим альтернативный маршрут для половины Интернета? 😁

С IP-сетями история ещё веселее. Community-версия Antifilter на момент написания этого поста сама сообщает, что её список префиксов покрывает 884 541 IP-адрес.

И вот этого подхода я для себя принципиально не хочу.

Шурик, это же не наш метод!


Мне не нужен КВН для всего Интернета.

Мне нужно, чтобы через КВН работали конкретные ресурсы, которыми пользуюсь я, моя семья, родственники, друзья и коллеги. Всё остальное должно идти обычным маршрутом.

Поэтому мой принцип очень простой ❗️

не добавить всё, а потом разбираться, а добавить только то, необходимость чего я увидел сам.

И это немного сложнее.

Допустим, нужен какой-нибудь сервис. Добавил его основной домен 〰️ не заработало.

Почему ❓

Потому что современное приложение практически никогда не ходит только например, на google.com. У него могут быть API, авторизация, CDN, WebSocket, телеметрия, отдельные backend-сервисы, облачные хранилища и ещё пачка зависимостей.

И вот тут начинается самое интересное 〰️ смотреть сеть. 👀

Совсем недавно я таким способом разбирался с Google и его сервисами.

Вместо того чтобы взять очередной список ВСЕ ДОМЕНЫ GOOGLE!!!111 и отправить через КВН половину Google Cloud, я запускал приложение и смотрел РЕАЛЬНЫЙ ТРАФИК.

Обычный tcpdump довольно быстро показал обращения к нужным *.googleapis.com, *.run.app, ssl.gstatic.com и другим зависимостям.

Добавил необходимое ➡️ проверил.

Не работает ➡️ снова посмотрел трафик.

Нашёл следующий запрос ➡️ понял, зачем он нужен ➡️ добавил.

Перезапустил ➡️ проверил ещё раз.

Да, это ДОЛГО 〰️ то самое страшное слово, которое так не любят в компаниях PM, CEO и прочие уважаемые люди, когда нужно быстро, прямо сейчас, а желательно ещё вчера. 😁

Это дольше, чем просто скачать чей-нибудь domains.txt.

Зато в конце я хотя бы понимаю, почему каждая запись находится в моём списке маршрутизации.

И это правильный траблшутинг ❗️

На macOS для этого мне ещё очень нравится Little Snitch от Objective Development.

Это вообще прекрасная штука для тех, кому интересно, что на самом деле происходит у него на компе.

Little Snitch показывает, какой процесс к какому серверу подключается, домен, адрес сервера, протоколы, порты и историю соединений. Можно открыть нужное приложение и буквально наблюдать, куда оно пытается сходить.

И очень быстро выясняется, что условное app.google.com

на самом деле превращается в

auth.google.com
api.google.com
ssl.gstatic.com
oauth2.googleapis.com
backend.run.app

и ещё несколько совершенно неочевидных адресов.

Вот эти адреса я и предпочитаю находить самостоятельно. 😎

Есть ещё tcpdump, dig, nslookup, traceroute, curl, просмотр DNS-запросов 〰️ старые добрые инструменты, которые почему-то всё ещё прекрасно работают. 😁

Иногда, глядя на некоторые публичные списки, создаётся ощущение, что сегодня главное 〰️ побыстрее собрать очередной универсальный обход блокировок, выложить его, получить звёздочки и подписчиков, а вопрос что конкретно мы сейчас маршрутизируем и почему? оставить на потом. Всё равно никто не спрашивает если заработало то что нужно. 😁

А потом появляются списки, где можно встретить совершенно неожиданные вещи, вплоть до локальных/служебных адресов и категорий, которые конкретному пользователю вообще никогда не понадобятся.

Мой подход скучнее ❓ Да ❗️

нужен ресурс ➡️ смотрим его трафик ➡️ находим зависимости ➡️ проверяем ➡️ добавляем ➡️ документируем.

И да-да-да 〰️ документация. 😁

Та самая штука, которую никто не любит писать, потому что и так всё понятно.

А потом проходит полгода, ты открываешь список из сотни доменов и IP-адресов, видишь там какой-нибудь ssl.gstatic.com и задаёшь себе главный инженерный вопрос

А нафига я это сюда добавил?

И вот именно в этот момент та самая скучная документация, на которую когда-то пожалел -цать минут, внезапно становится очень нужна.

Поэтому добавил домен или подсеть 〰️ напиши хотя бы одной строкой в Obsidian или текстовичок для какого сервиса, зачем и при каких условиях это понадобилось.

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

И всё ❗️

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

Я знаю, зачем там находится каждый крупный домен или подсеть. Я могу удалить правило и понимаю, что перестанет работать. А обычный российский трафик, банковские приложения, локальные сервисы, CDN и всё, чему КВН совершенно не нужен, не отправляются путешествовать через полмира только потому, что кто-то когда-то добавил соответствующую сеть в огромный community-list.

Наверное, это профессиональная деформация.

Но я всё-таки за принцип

КВН должен маршрутизировать столько, сколько необходимо.
А не столько, сколько удалось найти в интернете. 😉

#КВН #маршрутизация #сети #Keenetic #LittleSnitch #tcpdump #DNS #DevOps


#пятничный_мемасик


Video oldindan ko‘rish uchun mavjud emas
Telegram'da ko‘rish
АКТУАЛЬНО и сейчас во всех сферах!
Фильм с Евгением Леоновым «Премия» 1974 год.
#смех_да_и_только


По мотивам сегодняшней встречи в Т1

#пятничный_мемасик


🛰 Как я протащил КВН через звонки ВК 〰️ и почему не вышло с Телемостом

Помните, я полез в кроличью нору с TURN Relay и хотел попробовать подружить инфраструктуру звонков с OCOS + OpenConnect❓

Так вот. Кроличья нора оказалась достаточно глубокой. 🐰

Но эксперимент заработал. 😈

В OCOS появился экспериментальный режим Relay 〰️ КВН-трафик идёт не напрямую на мой сервер, а через TURN-серверы видеозвонков ВК.

Схема примерно такая

📱 OCOS ➡️ TURN Relay ➡️ VPS ➡️ OpenConnect/ocserv ➡️ Интернет

Смысл эксперимента простой 〰️ если прямой доступ к VPS ограничен, но инфраструктура, необходимая для работы звонков, остаётся доступной, попробовать использовать её как транспорт. 😁

Начал я с двух вариантов.

❌ Яндекс Телемост

Удалось разобраться, как веб-клиент Телемоста получает временный доступ к TURN, и воспроизвести получение кредов.

Казалось бы 〰️ половина дела сделана.

А вот и нет. 😁

TURN Яндекса отвечает 403 Forbidden IP, если попытаться отправить данные на произвольный внешний адрес.

Проверял свой VPS, 8.8.8.8 и другие адреса.

Результат один.

Судя по экспериментам, relay разрешает пересылку только в сторону инфраструктуры самого Телемоста. Ограничение находится на стороне TURN-сервера, поэтому клиентом его не обойти.

Телемост пока вычёркиваем. ❌

✔️ ВК Звонки

А вот здесь стало гораздо интереснее.

TURN ВК позволяет пересылать трафик к внешнему адресу, поэтому удалось реально протащить через него соединение OCOS.

Правда, сначала оно работало примерно по принципу

Ну… может подключусь, а может и нет. 😁

Я уже начал подозревать троттлинг или какую-нибудь хитрую защиту ВК.

Оказалось интереснее. 😌

✅ Первый байт имеет значение

Экспериментально выяснил, что relay пропускает пакеты, похожие на медиатрафик 〰️ первый байт должен попадать в диапазон RTP 128–191.

Остальные пакеты просто исчезают.

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

Исправление оказалось почти смешным 〰️ буквально одна строка.

После этого соединение стало подниматься стабильно.

✅ Упёрся примерно в 2 Мбит/с

Следующий сюрприз 〰️ скорость.

Один TURN-канал давал примерно 2 Мбит/с.

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

Ну раз так… 😈

Сделал многоканальную передачу (multipath).

Теперь поток распределяется сразу по 8 активным каналам из пула в 10 каналов, а на сервере собирается обратно.

При этом скорость каждого отдельного канала держится немного ниже его лимита.

И вот тут стало уже действительно интересно.

✅ Пакеты начали обгонять друг друга

Когда данные полетели параллельно по нескольким TURN-каналам, они закономерно начали приходить в другом порядке.

Мой протокол видел дырки и думал 〰️ ПАКЕТ ПОТЕРЯН! СРОЧНО ПОВТОРИТЬ! 🚨

Хотя пакет не потерялся. Он просто ехал по соседней полосе и немного задержался.

В результате до четверти трафика могло уходить на ненужную повторную передачу (retransmit).

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

Стало заметно лучше.

✅ А потом пришёл настоящий iPhone

Как обычно в лабе 〰️ Всё работает.

На живом устройстве 〰️ Ага щас. 😂

Вылезло ещё несколько вещей.

Локальный прокси не принимал IPv4.

TURN ChannelBind жил ровно 10 минут и без продления тихо умирал.

А зависшее соединение могло ждать вечность, потому что никто не объяснил ему, что пора умереть.

Добавил автоматическое продление каналов, контроль и автоматический сброс зависших соединений (watchdog).

📶 Что получилось по скорости

Wi-Fi
TURN Relay 〰️ 14,1 / 11,9 Мбит/с
Прямой (Direct) до КВН-сервера 〰️ около 500 Мбит/с

МТС
TURN Relay 〰️ 13,3 / 2,36 Мбит/с

Причём отдачу режет уже сама мобильная сеть 〰️ без КВН в том же месте аплинк около 3,85 Мбит/с.

Мегафон
около 2 Мбит/с независимо от режима 〰️ TURN Relay, прямой UDP или TCP.

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

✅ Итого

Было

❌ около 2 Мбит/с
❌ подключение через раз
❌ лишние retransmit
❌ отвал через 10 минут
❌ вечные зависшие соединения

Стало

✅ 13–14 Мбит/с через TURN
✅ подключение с первой попытки
✅ multipath через несколько каналов
✅ автоматическое продление
✅ watchdog
✅ работа на реальном iPhone

И всё это через инфраструктуру, которая вообще-то предназначена для видеозвонков. 😈

🐰 Кроличья нора определённо оказалась глубже, чем я думал.

Следующий этап 〰️ адаптивное управление скоростью для мобильных сетей и пул временных кредов доступа к TURN, чтобы не плодить лишних гостей в звонке.

Пока TURN Relay остаётся экспериментальной функцией OCOS и в тестовые сборки TestFlight не попадёт. Увы 🤷‍♂️

Но сам факт, что схема

OCOS ➡️ TURN ➡️ VPS ➡️ OpenConnect

реально заработала 〰️ уже довольно забавный результат эксперимента. 🪄

#turn #stun #dtls #webrtc #networking #multipath #ocos #openconnect #квн #ios #devops


🤖 Ну что, помните, чем закончилась предыдущая серия про Android-версию OCOS ❓

Посмотрим, кто сдастся первым - мы или Google Play 😁

Спойлер 〰️ никто не сдался.

Но Google Play всё-таки моргнул первым. 😎

После смены аккаунта для публикации приложения, паспортов, платёжных профилей, подтверждения адреса и попыток доказать Google, что мы действительно существуем, Play Console наконец открыла двери. 🥳

Можно было переходить к главному 〰️ выкатывать OCOS на реальные Android-устройства. 🚀

И тут выяснилось первое интересное.

Изначально план был такой 〰️ AAB ➡️ Internal App Sharing ➡️ ссылка ➡️ телефон ➡️ тестируем.

Загружаем подписанный app-release.aab.

Google думает и отвечает 〰️ Чтобы использовать функцию внутреннего доступа, приложение com.itmisko.ocos нужно опубликовать.

😐

То есть чтобы воспользоваться способом раздачи приложения до нормальной публикации…

…сначала нужно приложение опубликовать. 😂

Ладно, Google. Уговорил.

Пошли другим путём 〰️ через Internal Testing.

Создали OCOS в Play Console, добавили первых тестировщиков, загрузили наш AAB

✅ OCOS 1.0.0
✅ Android 8.0+
✅ target SDK 36
✅ release подписан нашим upload key
✅ Google Play принял сборку без ошибок
✅ первый Internal Testing release опубликован

Получаем ссылку для тестировщиков.

Открываем.

Google Play говорит 〰️ Вы тестируете com.itmisko.ocos (не проверено).

Отлично! 🥳

Нажимаем Скачать тестовое приложение.

Файл не найден.

😂😂😂

Google, ну мы же почти договорились.

Оказалось, нужно было просто дать Google Play немного времени, чтобы первая сборка разъехалась по его инфраструктуре.

И вот сегодня…

📱 страница приложения открылась в Google Play
📥 OCOS установился на реальный Android-телефон
⚙️ конфигурация сохранилась
🔒 OpenConnect поднял соединение
🛡 VPN-туннель заработал
📊 адрес, MTU, DNS и трафик отображаются

То есть полный маршрут теперь реально пройден

Android 📱
⬇️
Google Play
⬇️
OCOS 🤖
⬇️
OpenConnect КВН-сервер
⬇️
Доступный Интернет 🌎

И это уже не классическое - Ну у меня в Android Studio всё работает. 😁

OCOS теперь устанавливается непосредственно из Google Play и работает на реальном устройстве.

Причём Internal Testing оказался даже удобнее первоначально задуманного Internal App Sharing.

Можно выкатывать новые версии OCOS, а тестировщики будут получать обновления через обычный Google Play 〰️ практически как мы уже делаем с iOS через TestFlight. 🍏🤝🤖

Так что статус проекта теперь официально такой

🍏 iOS - TestFlight, работает
🤖 Android - Google Play Internal Testing, работает
🛡 OCOS/OpenConnect/AnyConnect - работает
🌎 собственный КВН-сервер - работает
🐛 баги - обязательно будут и мы их найдём 😄

А значит, пора запускать нормальное тестирование Android-версии на разных устройствах.

Если у Вас Android и хочется бесплатно погонять OCOS 〰️ Добро пожаловать! 🤖

✅ Пишите в Telegram или в личку, кто меня знает.
✅ Предоставим не только доступ к приложению, но и бесплатный КВН.

Первые места в Android-тестировании уже открыты. 😉

А Google Play…

Спасибо за квест.

Было сложно и весело.

Давай больше так не будем. 😂

#Kotlin #Android #AndroidStudio #GooglePlay #OpenConnect #OCOS #КВН #PetProject #DevOps


#пятничный_мемасик


Уволили человека, потому что теперь есть ИИ. Через пару лет позвонили ему же и предложили вернуться. Только уже за другие деньги.

И это постепенно перестаёт быть шуткой.

Gartner опубликовал свежий Hype Cycle for the Future of Work и прогнозирует довольно интересную вещь: к 2029 году компаниям придётся вернуть примерно 30% сотрудников, которых до этого сократили из-за замены их работы ИИ. Причём повторный найм зачастую обойдётся заметно дороже. Gartner

На бумаге идея заменить людей ИИ выглядит красиво.

Убрали несколько ставок ➡️ сократили расходы ➡️ показали экономию ➡️ все довольны.

Проблема обнаруживается позже.

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

В IT это особенно хорошо знакомо.

Документация может лежать в Confluence. Код — в Git. Задачи — в Jira. Логи — в ELK.

А ответ на вопрос почему здесь вообще сделано именно так? иногда всё равно находится только в голове человека, который делал это семь лет назад.

И вот этого контекста у модели может просто не быть.

Gartner прямо пишет, что массовые сокращения способны дать краткосрочный финансовый эффект, одновременно разрушая кадровый резерв и институциональные знания компании. А потом начинается обратный процесс: поиск специалиста, рекрутмент, новая рыночная зарплата, онбординг и месяцы погружения в систему. Gartner

Есть ещё одна интересная цифра.

По прогнозу Gartner, уже к 2027 году 75% организаций, которые пытаются превращать рост производительности от ИИ преимущественно в сокращение расходов, рискуют отстать от конкурентов, которые ту же экономию вкладывают обратно — в новые продукты, модернизацию и обучение сотрудников. Gartner

То есть условно получили благодаря ИИ +20% производительности.

Можно убрать 20% людей.

А можно тем же составом попробовать сделать на 20% больше.

И Gartner явно смотрит в сторону второго варианта.

Есть и менее очевидная проблема — workslop.

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

В итоге один сотрудник сэкономил час с помощью ИИ, а трое коллег потратили по полчаса на разбор результата.

В отдельном исследовании Gartner кадровые риски ИИ разделены на три группы:

➡️ когда ИИ помогает человеку — возможны падение мотивации, workslop и усиление предвзятости;

➡️ когда ИИ перестраивает процессы — начинают теряться навыки, сокращается найм начинающих специалистов и ломается кадровая преемственность;

➡️ когда вокруг ИИ строят совершенно новые процессы — появляется риск чрезмерных сокращений, репутационных проблем и постепенного размывания корпоративной культуры. Gartner

При этом 76% CEO, по данным Gartner, ожидают, что именно ИИ окажет самое сильное влияние на их отрасли в ближайшие три года. Gartner

Поэтому вопрос уже давно не в том, внедрять ИИ или нет.

Вопрос — как его внедрять.

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

Гораздо интереснее другая модель: человек + ИИ должны стать сильнее, чем человек без ИИ.

Инженер с Codex/Claude Code/Antigravity не обязательно означает теперь нужен один инженер вместо трёх.

Возможно, это означает, что те же три инженера смогут наконец закрыть технический долг, автоматизировать рутину, быстрее разбирать инциденты и делать вещи, до которых раньше просто не доходили руки.

Именно поэтому четыре направления из свежего Gartner выглядят вполне здраво: ИИ как помощник человека, постоянное переобучение, сохранение человеческого контроля и контекста и создание общей AI-инфраструктуры, благодаря которой каждый следующий сценарий внедряется быстрее и дешевле предыдущего. Gartner

В общем, парадокс эпохи ИИ может получиться забавным: сначала компании будут платить деньги, чтобы заменить человека моделью. А потом — ещё больше денег, чтобы вернуть человека, который помнит, как всё это работает.

Потому что автоматизировать работу и заменить знания — всё-таки не одно и то же.

Источники: Gartner — 4 Shifts Shaping the Future of Work и Gartner — AI Talent Risks

#ИИ #AI #IT #Автоматизация #Разработка #КарьераВIT #БудущееРаботы #DevOps


Продолжаем сверлить дырочки в интернет. 🛠

Некоторое время назад я писал, как настроил на Keenetic/Netcraze выборочную маршрутизацию через свой OpenConnect КВН-сервер через КВН идут только нужные сервисы, а весь остальной интернет продолжает работать напрямую через провайдера.

С тех пор списки немного разрослись. Ладно, кого я обманываю 〰️ разрослись они прилично. 😄

Теперь в репозитории есть готовые списки для

🍏 Apple
💰 Bybit
😒 Claude
↗️ Cursor
🔵 Discord + отдельно Voice
💙 Facebook / Meta
🎨 Figma
🤖 Gemini / Antigravity
🐱 GitHub
🤗 Hugging Face
📡 Keenetic
🎥 Loom
🎬 Mux
🔆 OpenAI + IP Fallback + Voice IP
🎓 Skool
👻 Snapchat
✈️ Telegram
🔥 WhatsApp / Meta
🎥 YouTube

Где это имеет смысл, кроме доменов добавлены IP Fallback-списки. То есть если сервис внезапно решит сходить куда-нибудь напрямую по IP, шанс, что он убежит мимо нужного маршрута, становится заметно меньше.

Но самое интересное оказалось не в самих списках.

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

🐛 БАГ 1 KeeneticOS и пустая FQDN-группа

После перепривязки DNS-маршрута в группе (что-то удалил, что-то добавил) конфигурация внешне может выглядеть абсолютно нормально.

Но внутри Keenetic группа иногда остаётся пустой. Увидеть можно только через CLI.

В итоге сидишь, смотришь на конфиг 〰️ всё красиво. А трафик почему-то идёт не туда. 🙃

Лечится полным пересозданием группы с DNS-маршрутами.

Так что если после обновления группы Keenetic внезапно перестаёт маршрутизировать домены 〰️ первым делом пересоздаём группу.

🐛 БАГ 2 Ozon 🛒 который вообще оказался ни при чём

А вот здесь было веселее.

Приложение Ozon на мобилке иногда теряло сеть.

Его трафика вообще не было ни в одном моём списке.

То есть маршрутизация здесь изначально была ни при чём, хотя поначалу были мысли.

После раскопок выяснилась интересная цепочка.

Ozon использует QUIC 〰️ это HTTP/3 поверх UDP.

В некоторых случаях приложение отправляло UDP-пакеты размером около 1500 байт, а на пути через Ростелеком MTU оказался меньше 〰️ 1492 байта.

Дальше начиналась фрагментация.

И вот именно с этими фрагментами на iOS что-то шло не так, пакет нормально не собирался, запрос зависал до таймаута, а Ozon радостно сообщал Нет соединения.

✅ Хотя интернет есть.
✅ КВН работает.
✅ Маршруты работают.
✅ DNS работает.
✅ Да и вообще всё работает. Кроме Ozon. 😄

Решение получилось неожиданно простым 〰️ запретить Ozon использовать QUIC из домашней сети.

На Keenetic Сетевые правила ➡️ Межсетевой экран ➡️ Домашняя сеть

Добавил запрет UDP/443 для сетей Ozon

🔵 185.73.192.0/22
🔵 91.223.93.0/24
🔵 195.34.20.0/23
🔵 91.212.64.0/24
🔵 46.226.122.0/24

После них 〰️ обычное правило

🔵 Действие - Разрешить
🔵 IP-адрес источника - Любой
🔵 IP-адрес назначения - Любой
🔵 Протокол - IP
🔵 Переместить в - Конец
🔵 Расписание работы - Работает постоянно


QUIC перестаёт проходить, приложение делает fallback на HTTPS/TCP, где размер TCP-сегментов роутер уже может нормально подогнать под MTU канала.

И Ozon 🛒 внезапно оживает. 🥳

Причём эта история вообще не обязательно связана с моей схемой выборочной маршрутизации. Теоретически с похожим эффектом можно столкнуться и на обычном подключении через провайдера.

В итоге домашний роутер постепенно превращается уже не просто в YouTube отправляем через КВН.

А в довольно нормальный policy-based gateway, где отдельно маршрутизируются видеоплатформы, мессенджеры, соцсети, голосовой трафик и остальные сервисы.

И всё это работает прозрачно для устройств домашней сети.

✅ Телефону всё равно.
✅ Телевизору всё равно.
✅ Ноутбуку всё равно.

Они просто открывают приложение или сайт, а Keenetic сам решает, через какой выход отправить конкретный трафик. 🚀

Обновлённые списки лежат в том же репозитории ТУТА

Буду и дальше поддерживать репозиторий, и добавлять туда новые сервисы по мере необходимости.

Потому что дырочек в интернете, как выяснилось, нужно сверлить всё больше и больше. 😄

#Keenetic #Netcraze #OpenConnect #OCOS #КВН #DevOps


🤖 Ну что, яблочек поели? Теперь пришло время зелёного робота. Android Developer — погнали. 🚀

Не так давно я рассказывал, как решил быстренько зарегистрироваться в Apple Developer Program 🍏

И это быстренько превратилось в отменённый enrollment, зависшие $99, поддержку Apple, возврат денег, повторную оплату, проверку паспорта и ощущение, что мне выдают доступ к ядерному чемоданчику 😄

Казалось бы, после такого логичный вывод: Узбагойся. Пиши свой OCOS под iOS и радуйся жизни.

Но тут сын пошёл учиться на Android-разработчика, и появилась идея: а давай вместе с обучением попробуем сделать OCOS ещё и под Android? 🤖

Если одна платформа наконец заработала 〰️ самое время добавить вторую и снова устроить себе приключение. 😄

Поэтому…

🤖 OCOS теперь едет и на Android.

И началось всё, разумеется, с классического: Да что там делать? Сейчас Android Studio поставим, проект соберём и закинем в Google Play.

Ага. Конечно. 😄

На данный момент (спустя месяцы 🙈):

✅ Android Studio установлена и настроена
✅ Android SDK поднят
✅ OCOS успешно собирается под Android
✅ приложение уже запускается в Android Emulator и на тестовом Honor 30
✅ release-сборка собирается в .aab
✅ создан отдельный upload keystore
✅ release подписан своим 4096-bit RSA ключом
✅ подпись проверена через jarsigner — jar verified
✅ Google Play Developer Account зарегистрирован
✅ регистрационные $25 успешно принесены в жертву Google 😄

Казалось бы…

Всё. Загружай AAB и раздавай через Internal App Sharing.

Но тут Google такой: А давайте сначала узнаем, кто ты вообще такой. 😄

И начался новый квест.

🔵 подтверждение личности
🔵 паспорт
🔵 платежный профиль
🔵 внезапно обнаружил, что профиль разработчика зарегистрирован на страну ближнего зарубежья
🔵 а паспорт-то нашенский
🔵 меняю платежный профиль
🔵 перепривязываю Play Console на российский профиль
🔵 снова паспорт
🔵 Google говорит: А теперь докажи, что ты ещё и живёшь по этому адресу 😄
🔵 подтверждение адреса
🔵 документы отправлены
🔵 теперь жду, пока Google решит, достаточно ли я настоящий человек для публикации собственного КВН-клиента

В общем, Apple хотя бы сразу дала понять, что будет больно. 🍏

🛒 Google сначала такой: Регистрация всего $25, заходи, дружище!

А потом:

🔵 Паспорт покажи.
🔵 Адрес покажи.
🔵 Телефон покажи.
🔵 Android-телефон покажи.
🔵 А теперь подожди. 😄

Но техническая часть уже работает.

Самое приятное — OCOS реально живёт на Android. 🤖📞

Теперь цель такая:

🔵 дождаться верификации Google Play Developer
🔵 загрузить первую сборку через Internal App Sharing
🔵 погонять её на реальных Android-устройствах
🔵 потом Internal Testing
🔵 исправить всё, что обязательно вылезет 😄
🔵 и постепенно двигаться к полноценному релизу в Google Play

Получается, эволюция продолжается:

DevOps ➡️ iOS Developer ➡️ ну раз уж начал, давай ещё Android ➡️ человек, который добровольно поддерживает два мобильных приложения и всё ещё считает это pet-проектом. 😎

OCOS постепенно становится действительно кроссплатформенным.

🍏 iOS 〰️ есть
🤖 Android 〰️ уже оживает
😊 OpenConnect/AnyConnect 〰️ остаётся в центре всей этой истории
🐛 Ну и бонусом уже успели с сыном найти баг в Android-части OpenConnect 〰️ после выхода тестовой сборки подготовим патчи и попробуем отправить фикс в upstream. 😎

Так что после: Добро пожаловать в яблочный ад 🍏

Официально открываю следующую главу: Добро пожаловать в Android-ад — Gradle, keystore, AAB, signing, Play Console и проверки личности 🤖😊

Посмотрим, кто сдастся первым 〰️ мы или Google Play 😄

#Android #GooglePlay #Kotlin #OpenConnect #OCOS #PetProject #DevOps


Сегодня только ленивый не говорит про ИИ. Такое ощущение, что все разговоры только о нём 😊

На небе только и разговоров, что о ИИ море и о закате. Там говорят о том, как чертовски здорово наблюдать за огромным огненным шаром, как он тает в волнах. И еле видимый свет, словно от свечи, горит где-то в глубине…


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

А я решил пойти немного другим путём и посмотреть, что можно выжать из старого железа.

Нашёл у себя Mac mini Late 2012: старенький Intel Core i5, 16 ГБ оперативки, SSD на 512 ГБ. Выкидывать жалко, а для экспериментов — самое то.

macOS снёс. Поставил Ubuntu Server 26.04.1 LTS, поднял SSH — теперь это маленький headless-сервер, который можно убрать куда-нибудь на полку и забыть про монитор с клавиатурой.

Следующий этап — попробовать развернуть на нём свою локальную LLM.

План примерно такой:

llama.cpp ➡️ GGUF-модели ➡️ бенчмарк ➡️ выбираю то, что этот старичок реально способен переварить.

Хочу попробовать модели от совсем маленьких до 3B и посмотреть не на оно запустилось, а на реальные tokens/sec, потребление памяти, загрузку CPU и температуру.

А если всё это окажется хоть немного жизнеспособным — следующим этапом прикручу OpenClaw или Hermes и попробую превратить Mac mini уже не просто в локальную говорящую LLM, а в полноценного домашнего AI-агента.

Понятно, что ChatGPT/Claude на двухъядерном i5 2012 года я не построю 😁 Но тем интереснее посмотреть, на что в 2026 году реально способен компьютер, которому уже 14 лет.

✅ Mac mini есть.
✅ Ubuntu Server стоит.
✅ SSH работает.

Дело осталось за малым — заставить старичка думать. 🤖

Продолжение следует…

#AI #LLM #LocalLLM #MacMiniAI #llamacpp #UbuntuServer #Homelab #DevOps


#developerday


#пятничный_мемасик


✔️ startupProbe правильный способ пережить долгий старт приложения

В прошлом посте мы разбирали, как увеличить окно терпения у livenessProbe и readinessProbe через failureThreshold × periodSeconds, чтобы Pod пережил долгую Liquibase/Alembic-миграцию и не ушёл в бесконечные рестарты.

Способ рабочий, но у него есть один недостаток 〰️ пока действует большое окно терпения, livenessProbe перестаёт быстро реагировать на реальные зависания приложения.

Если долгий старт 〰️ обычная история, для этого в Kubernetes уже есть штатный механизм 〰️ startupProbe.

✅ Как же он работает❓

Пока startupProbe ни разу не прошёл успешно, livenessProbe и readinessProbe вообще не выполняются.

Как только startupProbe успешно проходит первый раз, он больше никогда не запускается. Дальше контейнер работает с обычными значениями livenessProbe и readinessProbe.

startupProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
periodSeconds: 5
failureThreshold: 720 # до 1 часа на миграцию
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
periodSeconds: 5
failureThreshold: 3 # обычные рабочие значения

✅ Почему это лучше ❓

🔵 Не нужно временно увеличивать failureThreshold перед раскаткой, а потом вспоминать, что его нужно вернуть обратно.
🔵 После успешного запуска начинает работать обычный livenessProbe с небольшими значениями failureThreshold, поэтому реальные зависания приложения после старта обнаруживаются быстро, а не спустя часы.
🔵 По манифесту сразу видно, что это отдельное окно для долгого запуска приложения, а не случайно огромное значение failureThreshold, происхождение которого через полгода уже никто не вспомнит.

✅ Но что точно стоит проверить, чтоб не словить проблему❗️

🔵 Admission-политики 〰️ не SCC, а именно policy-engine

Если в кластере используются Kyverno или OPA Gatekeeper, могут существовать политики, запрещающие определённые настройки проб.
В этом случае новый манифест просто не применится. Старые Pod продолжат работать, а проблему сразу покажет kubectl rollout status.

🔵 Размер окна

Если приложение запускается дольше, чем рассчитано окно failureThreshold × periodSeconds
то kubelet посчитает контейнер зависшим и начнёт его перезапускать.
Поэтому окно лучше закладывать с запасом 〰️ примерно в 1,5–2 раза больше максимального времени запуска.

🔵 Стратегию раскатки

Само по себе добавление startupProbe не приводит к даунтайму.
При стандартной стратегии RollingUpdate и нескольких репликах старые Pod продолжают обслуживать трафик, пока новые не станут Ready.
Риск появляется при одной реплике, стратегии Recreate, агрессивных настройках maxUnavailable или других особенностях раскатки.

✅ Итог

Если долгий старт 〰️ разовая история, например, тяжёлая миграция перед релизом, временно увеличить окно терпения у livenessProbe вполне допустимо.

Если же приложение регулярно долго запускается, startupProbe 〰️ более правильное решение. Он отделяет этап запуска от контроля живости приложения, поэтому после успешного старта livenessProbe продолжает работать с обычными, небольшими значениями.

Именно для таких сценариев startupProbe и появился в Kubernetes.

#startupProbe #k8s #Liquibase #Alembic #DevOps


💤 Как усыпить livenessProbe на время долгой миграции 〰️ и почему initialDelaySeconds для этого не подходит

Классическая ситуация 〰️ приложению на старте нужно прогнать миграции через Liquibase или Alembic. Заранее неизвестно, сколько это займёт 〰️ 10 минут, час или несколько часов.

А livenessProbe уже через пару минут начинает возвращать ошибки, и kubelet перезапускает контейнер прямо посреди миграции.

Разберёмся, почему простое увеличение initialDelaySeconds 〰️ не лучшее решение и какие параметры действительно позволяют пережить долгий старт.

✔️ readinessProbe 🆚 livenessProbe

✅ Провал readinessProbe

🔵 Pod остаётся работать
🔵 Kubernetes перестаёт направлять на него трафик
🔵 Pod никто не перезапускает

✅ Провал livenessProbe

🔵 превышен failureThreshold
🔵 kubelet перезапускает контейнер

Эти проверки полностью независимы друг от друга 〰️ изменение одной никак не влияет на вторую.

✔️ initialDelaySeconds 〰️ это просто пауза

Пока не истечёт initialDelaySeconds, kubelet вообще не выполняет проверку.

Если задать

initialDelaySeconds: 28800 # 8 часов до первой проверки

то даже если приложение полностью запустится через 5 минут, первая проверка всё равно произойдёт только через 8 часов.

То есть это не терпение, а обычная задержка перед началом проверок.

✔️ failureThreshold × periodSeconds 〰️ верхняя граница терпения

А вот это уже другое.

После окончания initialDelaySeconds проверки начинают выполняться регулярно.

Как только health-эндпоинт впервые отвечает успешно, счётчик ошибок сразу сбрасывается в ноль, и livenessProbe снова начинает успешно проходить. Неважно, произошло это через 10 минут или через 7 часов 〰️ никакого ожидания окончания окна не происходит.

Максимальное время до рестарта можно приблизительно оценить так

initialDelaySeconds + failureThreshold × periodSeconds

Например, нужно дать приложению до 8 часов на выполнение миграций, но не ждать эти 8 часов, если всё пройдёт быстрее.

livenessProbe:
path: /actuator/health/liveness
initialDelaySeconds: 150
periodSeconds: 5
failureThreshold: 5730 # (28800 - 150) / 5 ≈ 8 часов запаса

Получаем примерно 8 часов запаса, но если приложение станет готово раньше, livenessProbe сразу начнёт успешно проходить и никаких дополнительных ожиданий не будет.

✔️ Не забываем про readiness

Если увеличить только livenessProbe, а readinessProbe оставить со стандартными значениями, получится странная ситуация

🔵 Pod продолжит работать.
🔵 Рестартов контейнера не будет.
🔵 Kubernetes перестанет направлять на Pod трафик.

Поэтому на время долгих миграций обычно имеет смысл синхронизировать параметры обеих проверок, чтобы поведение было предсказуемым 〰️ пока приложение не готово, Kubernetes не направляет трафик на Pod, а livenessProbe не приводит к рестарту контейнера.

readinessProbe:
path: /actuator/health/readiness
timeoutSeconds: 5
periodSeconds: 5
initialDelaySeconds: 150
failureThreshold: 5730 # тоже 8 часов, чтобы не было рассинхрона с liveness

✔️ Важный компромисс

У такого решения есть цена.

Пока действует большое окно терпения, livenessProbe практически перестаёт защищать от настоящих зависаний приложения. Если приложение действительно зависнет или перестанет отвечать, контейнер может оставаться в таком состоянии до окончания настроенного окна.

Поэтому это не постоянная настройка, а временная мера на время долгих миграций. После успешной раскатки значения failureThreshold лучше вернуть к обычным.

✔️ ПЫСЫ Да, для подобных сценариев Kubernetes рекомендует использовать startupProbe. Но у нас их нет, да и если прямо перед ПРОД-релизом не хочется менять уже проверенную схему health checks, временное увеличение окна терпения у livenessProbe может быть вполне рабочим компромиссом.

#livenessProbe #readinessProbe #k8s #Liquibase #Alembic #DevOps


#пятничный_мемасик


Накипело 😡

Иногда кажется, что главная проблема в IT 〰️ не легаси, не Kubernetes и даже не Прод в пятницу.

Главная проблема 〰️ когда люди, ДАЛЁКИЕ от инженерной работы, начинают решать, какими инструментами должны пользоваться разработчики, DevOps-инженеры и поддержка.

— Сделайте чек-лист в Word. Так удобнее.


Удобнее кому❓

Word 〰️ отличный инструмент для договоров, приказов и служебных записок. Но когда в документе десятки bash-команд, SQL-запросов, YAML, JSON и конфигов 〰️ это уже не документ, а техническая инструкция.

Технические инструкции должны жить в технических форматах

✅ Markdown (.md)
✅ обычный текст (.txt)
✅ рядом с кодом в Git.

Почему❓

🔵 Команды копируются без сюрпризов (Ах, Вы не сталкивались? Ну так это Вы не сталкивались!)
🔵 Git показывает историю изменений построчно
🔵 Можно делать Pull Request и ревью
🔵 Работает в VS Code, Obsidian, GitHub, GitLab и терминале
🔵 Не нужно открывать тяжёлый офисный редактор ради одной команды

А что умеет Word❓

✅ Случайно заменить символы
✅ Сломать форматирование
✅ Сделать копирование команд менее предсказуемым
✅ Превратить дифф в головную боль

Самое печальное 〰️ не то, что кто-то любит Word.

Самое печальное 〰️ когда человек, не работающий с технической документацией ежедневно и с тем что находится в ней, начинает навязывать её формат тем, кто потом по этим инструкциям ночью поднимает Прод, ищет причину аварии или делает откат релиза.

Инструмент должен подбираться под задачу, а не под личные привычки!

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

Всем бобра! 👋

#Markdown #Документация #Runbook #DevOps


🪄 Изучаю немного магии с TURN Relay

Последние дни ковыряю два интересных проекта, которые используют TURN-релеи инфраструктуры VK

✅ proxy-turn-vk-android
✅ vk-turn-proxy-ios

Идея там очень интересная 〰️ TURN-серверы, которые обычно нужны для звонков и WebRTC, можно использовать как промежуточный релей для передачи трафика.

Грубо говоря

Клиент ➡️ TURN Relay ➡️ VPS-сервер ➡️ Интернет

Почему я вообще туда полез❓

Хочу попробовать встроить подобный механизм в свой OCOS + OpenConnect/ocserv.

В теории это может дать довольно любопытный сценарий 〰️ если в сети действует режим белых списков, но при этом доступна инфраструктура, необходимая для работы звонков, трафик потенциально можно передавать через разрешённый TURN relay.

То есть снаружи это уже не выглядит как обычное прямое подключение

OCOS ➡️ TURN/STUN/DTLS ➡️ Релей инфраструктура звонков ➡️ VPS-сервер ➡️ OpenConnect

Сейчас как раз изучаю

🔵 как проекты получают временные TURN credentials
🔵 как работает Allocate ➡️ Permission ➡️ ChannelBind
🔵 как гоняется трафик через ChannelData
🔵 как устроен DTLS transport
🔵 можно ли нормально подружить это с OpenConnect
🔵 что делать с собственным DTLS внутри OpenConnect
🔵 можно ли добавить несколько релей-провайдеров и резерв между ними.

Отдельно интересно посмотреть не только на VK, но и на другие инфраструктуры. Хотя там ещё большой вопрос, есть ли вообще воспроизводимый способ использовать релей без магии, костылей и фантазий.

Если эксперимент взлетит, хочется получить в OCOS примерно такие режимы

✅ Direct 〰️ обычное подключение
✅ TURN Relay 〰️ через релей
✅ Auto 〰️ direct ➡️ резерв через релей

Короче, пока изучаю матчасть и пытаюсь понять, насколько глубока эта кроличья нора. 🐇

Если получится подружить OpenConnect с TURN relay звонков, будет очень интересно. 😈

#turn #stun #dtls #webrtc #networking #openconnect #ocos #devops


Привет! 👋

Помните, я обещал вот такую магию? 🪄

Вы выходите из дома.
📶 iPhone отключается от домашнего Wi-Fi.

И➖

Вы вообще ничего не нажимаете.
Телефон сам понимает, что домашней сети больше нет, автоматически поднимает IKEv2 КВН и продолжает работать так, будто Вы всё ещё дома.

Вернулись домой❓

КВН так же автоматически отключается.

Никаких кнопок.
Никаких Connect.
Никаких Ой, забыл включить КВН.

Именно этого эффекта Вы добьётесь прочитав этот пост до конца и заглянув в мой Github-репозиторий.

❓ Как это работает

В iOS есть встроенная функция КВН On Demand.

Можно задать простые правила

🏠 если подключены к домашнему Wi-Fi 〰️ КВН отключить
📱 если переключились на LTE 〰️ КВН подключить
🌎 если подключились к любому другому Wi-Fi 〰️ тоже подключить

В результате телефон сам принимает решение, нужен КВН или нет.

Чтобы не пришлось всё писать вручную и учитывая ограничения Telegram.
Я подготовил два файла и выложил их в репозиторий.

📄 runbook.md

Подробная инструкция с объяснениями

🔵 зачем одновременно нужен свой домен и KeenDNS
🔵 почему Remote Address и Remote Identifier 〰️ это разные вещи
🔵 как настроить Keenetic/Netcraze
🔵 как проверить, что действительно работает Full Tunnel
🔵 какие ошибки встречаются чаще всего

📱 ios-ikev2-home.mobileconfig

Готовый шаблон профиля iPhone.

Остаётся только заменить

🔵 свой домен
🔵 логин
🔵 пароль
🔵 имя домашнего Wi-Fi

После установки профиль начинает автоматически включать и выключать КВН в зависимости от того, где находится телефон.

Самое приятное 〰️ это ощущение, что КВН просто перестаёт существовать как отдельное действие.

🔵 Подключились к домашнему Wi-Fi 〰️ всё работает.
🔵 Вышли из дома 〰️ всё работает.
🔵 Переключились на LTE 〰️ всё работает.

Именно так, на мой взгляд, и должен выглядеть современный КВН.

📱 Мой Github постепенно пополняется, поэтому если будете повторять 〰️ периодически заглядывайте за обновлениями.

#IKEv2 #Keenetic #Netcraze #iPhone #iOS #КВН #Linux #DevOpsInTapki


Привет! 👋

Помните, я обещал поделиться скриптами, которые автоматизируют деплой ocserv за несколько минут?

Так вот, обещание выполняю.

Я собрал всё в отдельный GitHub-репозиторий.

Что это решает❓

Когда поднимаешь свой OpenConnect руками, быстро начинается классика

🔵 поставить ocserv
🔵 настроить конфиг
🔵 выпустить сертификаты
🔵 прикрутить nginx
🔵 включить NAT
🔵 настроить UFW
🔵 не забыть про IP-форвардинг
🔵 добавить fail2ban
🔵 прописать SSH-ключ
🔵 не отстрелить себе доступ к серверу

Всё это можно сделать вручную.

Но если хочется поднять свой КВН-сервер быстро, аккуратно и без копипасты из десяти мест 〰️ лучше автоматизировать.

Что есть в репозитории❓

✅ автоматическая установка и настройка ocserv
✅ nginx-лендинг, который прикрывает КВН
✅ Let's Encrypt-сертификаты
✅ NAT, IP-форвардинг и UFW
✅ fail2ban для SSH
✅ добавление root SSH-ключа
✅ отдельный безопасный шаг для отключения парольного SSH
✅ установка ocservice для управления КВН-пользователями
✅ проверочный тест после установки

Есть два сценария запуска

1️⃣ с локальной машины, когда на VPS ещё только парольный root-доступ
2️⃣ прямо на сервере, если файлы уже скопированы

То есть берём новый Ubuntu/Debian VPS, заполняем env-файл, запускаем скрипт 〰️ и получаем готовую основу для собственного OpenConnect КВН.

Без магии, но с нормальной автоматизацией.

Отдельно сделал Runbook.md.

Там расписано

🔵 что подготовить до запуска
🔵 какие параметры заполнить
🔵 как запускать с локальной машины
🔵 как запускать прямо на VPS
🔵 что проверить после установки
🔵 как не закрыть себе SSH-доступ
🔵 где смотреть логи, если что-то пошло не так

Вся подробная инструкция 〰️ в runbook.

Проект рассчитан на простой сценарий

новый VPS ➡️ домены ➡️ env-файл ➡️ запуск ➡️ свой OpenConnect КВН-сервер.

Это не заменяет понимание Linux, сетей и файрвол, но сильно сокращает рутину.

Если давно хотели поднять свой КВН, но не хотелось руками собирать весь пазл 〰️ самое время попробовать.

Буду рад обратной связи

🔵 что не завелось
🔵 где инструкция непонятная
🔵 какие проверки стоит добавить
🔵 что можно сделать удобнее

Если репозиторий оказался полезен 〰️ поставьте ⭐️ на GitHub📱

#OpenConnect #ocserv #VPS #КВН #Linux #Ubuntu #DevOpsInTapki

20 ta oxirgi post ko‘rsatilgan.