#kubernetes #linux #база
Существует достаточно частая проблема: ошибки категории "
Когда копаешь в одно, а проблема в другом.
Инженеры Kubernetes иногда сталкиваются с крайне сбивающей с толку ошибкой при запуске пода:
Не зная причины этой ошибки, мы сперва тратим время на:
- просмотр что за PVC используются у деплоймента/пода.
- что за нода сейчас запустила этот под, нет ли нехватки места на самой ноде
- лезут в графану, в метрики и графики по нодам, подам, PV
- как разбиты разделы диска на нодах, что и сколько отдаётся эфемеркам
- чего там по айнодам (ну наконец-то пригодились эти знания!🕺 )
- и так далее
И это правильные мысли и план, это так же может быть причиной ошибки, но наш случай про другое.
Попытка найти строку "
Истинная причина кроется в тонком различии между единицами измерения CPU и памяти в спецификации ресурсов. Это особенно критично для Проецируемых томов (Projected Volumes), таких как Service Account Token (
https://kubernetes.io/docs/concepts/storage/projected-volumes/
Когда инженер по ошибке использует суффикс CPU (m) для лимита памяти, например:
-
-
- Ядро Linux получает запрос на монтирование
То есть в нашем случае ошибка "
❕Стоит понимать, что Kubernetes API сервер не считает "512m" для памяти ошибкой валидации.
Он принимает это как легальное значение (0.512 байта), что позволяет поду быть созданным, но приводит к сбою выполнения (runtime failure) при монтировании на ноде.
Решение очевидное:
всегда используйте бинарные единицы (IEC) для ресурсов памяти: Mi (мебибайты), Gi (гибибайты).
Может есть и другие, я только эти использовал всегда.
Чтобы превентивно избавляться от такой проблемы, используйте дополнительно:
- pre-commit hooks
- валидаторы cli в CI/CD процессе
Какие-то конкретные утилиты советовать не буду, оставлю ссылки для примера:
- https://github.com/instrumenta/kubeval (давно не обновлялся, но он работает ок)
- https://github.com/yannh/kubeconform
- https://github.com/kubernetes-sigs/kubectl-validate
Кстати, аналогичные ошибки встречаются при монтировании секретов, конфигмапов и других tmpfs-бэкендов, использующих лимиты памяти контейнера.
Существует достаточно частая проблема: ошибки категории "
misleading".Когда копаешь в одно, а проблема в другом.
Инженеры Kubernetes иногда сталкиваются с крайне сбивающей с толку ошибкой при запуске пода:
MountVolume.SetUp failed... no space left on device.
Не зная причины этой ошибки, мы сперва тратим время на:
- просмотр что за PVC используются у деплоймента/пода.
- что за нода сейчас запустила этот под, нет ли нехватки места на самой ноде
- лезут в графану, в метрики и графики по нодам, подам, PV
- как разбиты разделы диска на нодах, что и сколько отдаётся эфемеркам
- чего там по айнодам (ну наконец-то пригодились эти знания!
- и так далее
И это правильные мысли и план, это так же может быть причиной ошибки, но наш случай про другое.
Попытка найти строку "
no space left on device" в исходном коде Kubelet на GitHub также не дает результатов, потому что Kubelet не генерирует этот текст - он просто ретранслирует низкоуровневую ошибку, полученную от ядра Linux(или от рантайма, тут могу наврунькать).Истинная причина кроется в тонком различии между единицами измерения CPU и памяти в спецификации ресурсов. Это особенно критично для Проецируемых томов (Projected Volumes), таких как Service Account Token (
kube-api-access-*), которые монтируются как tmpfs (файловая система в RAM).https://kubernetes.io/docs/concepts/storage/projected-volumes/
Когда инженер по ошибке использует суффикс CPU (m) для лимита памяти, например:
resources:
limits:
memory: "512m" # Ошибка, должно быть "512Mi"!
-
Kubelet парсит "512m" для памяти как метрический милли, что равно 0.512 байта. Поскольку размер тома (tmpfs) должен быть целым числом, это значение округляется до 0 байт (или ничтожно малого значения). Kubelet использует этот 0 байт для установки максимального размера тома tmpfs.-
Kubelet использует этот лимит памяти для установки максимального размера тома tmpfs для Service Account токена- Ядро Linux получает запрос на монтирование
tmpfs с нулевым или ничтожно малым размером. Системный вызов mount завершается неудачей (из-за попытки выделить даже минимальный объём, обычно 1 страница = 4 KiB). и возвращает низкоуровневую ошибку ENOSPC ("No space left on device"), поскольку невозможно создать файловую систему (даже в RAM) с таким малым выделением ресурсов.То есть в нашем случае ошибка "
no space left on device" на самом деле означает: "Не удалось создать RAM-диск (tmpfs) требуемого объема, потому что выделенный размер (0 байт) некорректен".❕Стоит понимать, что Kubernetes API сервер не считает "512m" для памяти ошибкой валидации.
Он принимает это как легальное значение (0.512 байта), что позволяет поду быть созданным, но приводит к сбою выполнения (runtime failure) при монтировании на ноде.
Решение очевидное:
всегда используйте бинарные единицы (IEC) для ресурсов памяти: Mi (мебибайты), Gi (гибибайты).
Может есть и другие, я только эти использовал всегда.
Чтобы превентивно избавляться от такой проблемы, используйте дополнительно:
- pre-commit hooks
- валидаторы cli в CI/CD процессе
Какие-то конкретные утилиты советовать не буду, оставлю ссылки для примера:
- https://github.com/instrumenta/kubeval (давно не обновлялся, но он работает ок)
- https://github.com/yannh/kubeconform
- https://github.com/kubernetes-sigs/kubectl-validate
Кстати, аналогичные ошибки встречаются при монтировании секретов, конфигмапов и других tmpfs-бэкендов, использующих лимиты памяти контейнера.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤19👍9
#azure #aws
AWS:
- У нас авария, ничего не понятно, только не пишите в статус пейдже, в самом начале инцидента, что это DNS, пока пишите про что угодно, но не про DNS, ну не знаю, пусть будет свой собственный мониторинг и DynamoDB.
Azure:
- У нас авария, ничего не понятно, там у AWS недавно был DNS, давайте напишем в статус пейдже, что у нас тоже DNS, а потом поменяем на реальную причину, вдруг там AFD.
AWS:
- У нас авария, ничего не понятно, только не пишите в статус пейдже, в самом начале инцидента, что это DNS, пока пишите про что угодно, но не про DNS, ну не знаю, пусть будет свой собственный мониторинг и DynamoDB.
Azure:
- У нас авария, ничего не понятно, там у AWS недавно был DNS, давайте напишем в статус пейдже, что у нас тоже DNS, а потом поменяем на реальную причину, вдруг там AFD.
🤣26👍1😨1
#azure #devops #entra #powershell
Мелкая компания из трёх суетливых инженеров при удаче вырастает до большой организации в 150+ человек.
Люди уходят и приходят, а хорошего процесса оффбординга Entra ID иногда нет.
Иногда удаляют/выключают аккаунты, иногда нет. Иногда просто создают и не пользуются.
Чистка аккаунтов это крайне важный элемент девопс процессов.
Рано или поздно приходит любой аудит и очистка аккаунтов необходима.
И вот аудит пришёл.
Именно тогда прилетают странные задачки, типа "причесать каталог юзеров".
Захожу, а там 200+ аккаунтов, 85% которых я вижу впервые.
Хорошо, моя идея в общих чертах такая:
- найти всех пользователей
- отсортировать тех, у кого аккаунт включён (accountEnabled)
- собрать ключевые данные: Display Name, UPN/Email, дата создания и, главное, дата последнего входа
- отфильтровать по порогу неактивности (например, более 60 дней)
- сформировать таблицу (CSV-файл) с колонкой для решения ("Действие")
- отправить файл руководству (коллегам/боссу/СТО) на согласование, чтобы избежать удаления важных служебных аккаунтов или аккаунтов инвесторов
- удалить/выключить пользователей согласно утвержденному списку.
Как же это сделать? Ведь Microsoft Entra ID не предоставляет таких данных в удобном виде
Да и az cli такого не предоставляет.
На помощь приходит PowerShell и модули.
Поехали пошагово:
- запускаю PowerShell с правами администратора
- проверяю есть ли права на выполнение скриптов
- если рестриктед, то надо включить(не забыть выключить)
- теперь мне надо установить модуль
- импортирую модуль для этой сессии
- затем надо подключиться к Microsoft Graph с такими правами
На этом этапе откроется браузер, надо пройти авторизацию
- пилим скрипт(можно даже построчно вводить)
- на выходе получаю
- копирую, вставляю в Excel, добавляю новую колонку delete/don't touch
(или сразу пилить в CSV, как кому удобнее)
- отправляю руководству
- получаю ответ, выключаю/удаляю ненужных юзеров
Задача закрыта, в каталоге порядок.
Так. А почему именно я делаю эту задачу?
А нечего было всем в рабочих чатах говорить, что винда лучшая операционная система.
Вот и сиди, пиши пош-скрипты😭
Мелкая компания из трёх суетливых инженеров при удаче вырастает до большой организации в 150+ человек.
Люди уходят и приходят, а хорошего процесса оффбординга Entra ID иногда нет.
Иногда удаляют/выключают аккаунты, иногда нет. Иногда просто создают и не пользуются.
Чистка аккаунтов это крайне важный элемент девопс процессов.
Рано или поздно приходит любой аудит и очистка аккаунтов необходима.
И вот аудит пришёл.
Именно тогда прилетают странные задачки, типа "причесать каталог юзеров".
Захожу, а там 200+ аккаунтов, 85% которых я вижу впервые.
Хорошо, моя идея в общих чертах такая:
- найти всех пользователей
- отсортировать тех, у кого аккаунт включён (accountEnabled)
- собрать ключевые данные: Display Name, UPN/Email, дата создания и, главное, дата последнего входа
- отфильтровать по порогу неактивности (например, более 60 дней)
- сформировать таблицу (CSV-файл) с колонкой для решения ("Действие")
- отправить файл руководству (коллегам/боссу/СТО) на согласование, чтобы избежать удаления важных служебных аккаунтов или аккаунтов инвесторов
- удалить/выключить пользователей согласно утвержденному списку.
Как же это сделать? Ведь Microsoft Entra ID не предоставляет таких данных в удобном виде
*.Да и az cli такого не предоставляет.
На помощь приходит PowerShell и модули.
Поехали пошагово:
- запускаю PowerShell с правами администратора
- проверяю есть ли права на выполнение скриптов
Get-ExecutionPolicy
Restricted
- если рестриктед, то надо включить(не забыть выключить)
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process
Y
- теперь мне надо установить модуль
Install-Module Microsoft.Graph -Scope CurrentUser
- импортирую модуль для этой сессии
Import-Module Microsoft.Graph.Authentication
- затем надо подключиться к Microsoft Graph с такими правами
Connect-MgGraph -Scopes "User.Read.All", "AuditLog.Read.All"
На этом этапе откроется браузер, надо пройти авторизацию
- пилим скрипт(можно даже построчно вводить)
$InactiveDays = 60
$DateCutoff = (Get-Date).AddDays(-$InactiveDays)
$Users = Get-MgUser -All -Filter "accountEnabled eq true" -Property Id, DisplayName, UserPrincipalName, SignInActivity, AccountEnabled
$InactiveUsers = $Users | Where-Object {
$_.SignInActivity -ne $null -and
$_.SignInActivity.LastSignInDateTime -ne $null -and
$_.SignInActivity.LastSignInDateTime -lt $DateCutoff
} | Select-Object DisplayName, UserPrincipalName, @{Name="LastSignInDate"; Expression={$_.SignInActivity.LastSignInDateTime}}
#mock
$InactiveUsers | Format-Table
$NeverSignedInUsers = $Users | Where-Object {
$_.SignInActivity -eq $null -or
$_.SignInActivity.LastSignInDateTime -eq $null
} | Select-Object DisplayName, UserPrincipalName, @{Name="LastSignInDate"; Expression={"Never Signed In (or before Apr 2020)"}}
$InactiveUsers + $NeverSignedInUsers | Format-Table -AutoSize
- на выходе получаю
DisplayName UserPrincipalName LastSignInDate
----------- ----------------- --------------
Ivan Petrov ivan.petrov@contoso.com 2022-03-15 10:45:12
Maria Sidorova (Guest) m.sidorova_ext@contoso.com 2021-11-20 14:02:55
Alexey Smirnov a.smirnov@contoso.com 2022-04-01 08:10:30
New Folder(1) test.user@contoso.com Never Signed In (or before Apr 2020)
- копирую, вставляю в Excel, добавляю новую колонку delete/don't touch
(или сразу пилить в CSV, как кому удобнее)
($InactiveUsers + $NeverSignedInUsers) | Export-Csv -Path "C:\Users\alexk\InactiveUsers_Audit.csv" -NoTypeInformation
- отправляю руководству
- получаю ответ, выключаю/удаляю ненужных юзеров
Задача закрыта, в каталоге порядок.
Так. А почему именно я делаю эту задачу?
А нечего было всем в рабочих чатах говорить, что винда лучшая операционная система.
Вот и сиди, пиши пош-скрипты
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8😁5
- - -
В августе 2025 появилась эта фича https://learn.microsoft.com/en-us/entra/identity/users/users-bulk-download, теперь почти всё можно делать в UI. Однако доступны не все поля, нельзя сделать несколько фильтров последовательно, так что подход всё ещё актуален.
*Случай был 2023 году.В августе 2025 появилась эта фича https://learn.microsoft.com/en-us/entra/identity/users/users-bulk-download, теперь почти всё можно делать в UI. Однако доступны не все поля, нельзя сделать несколько фильтров последовательно, так что подход всё ещё актуален.
#troubleshooting #kubernetes #bottlerocket #aws # linux #база
Прилетает аномалия: клиенты(живые люди), при обращении к нашему UI, начинают видеть таймауты и ошибки (5xx), особенно при резком росте нагрузки.
Ну ничего необычного. Кроме того, что такого быть не должно.
Смотрю логи фронта - он получает пятисотки от бэкенда.
Иду к бэкендерам, показываю логи, тыкаю пальцем, говорю чините.
Проходит день, два, а ошибки всё идут.
Разработчики чего только не делали:
- включали дебаг
- смотрели логи
- добавляли метрики
- добавляли ресурсы CPU/Memory (хотя нагрузка была не высокой)
- did a barrel roll
Ничего не помогает. По всей статистике, логам и метрикам - всё отлично, но есть проблема с пятисотками.
Я бы может этим и не занимался, но на общем митинге мне ставят блокер и говорят "это ваша инфра и девопсы, чините, но мы, если честно, сами не знаем чо тут и почему".
Хлеб всему голова, как и девопс всем ишшуям затычка, поехали траблшутить.
Вспоминаю, что нечто подобное уже было, и иду читать у себя же https://xn--r1a.website/aws_ru/136623
Проверяю - не, все ок с ALB и настройками приложений.
При помощи фронта и бэка пишу скрипт нагрузочного тестирования, чтобы сымитировать это в stage (да кому он сдался этот ваш dev!). Запускаю, половину не понимая, и да, с*ка, пятисотки.
Ещё раз опускаюсь в логи, трейсы, метрики - не за что зацепиться.
Просидел дня три наверное, пока всё это ковырял как дурачок.
Может и правда мы, из отдела инфры, дурачки и что-то поломали?
Сижу ковыряю коммиты и MR в репозиториях инфраструктуры за последние 3 месяца - ничего критичного.
Ладно. Пошёл ковырять само приложение.
Есть!, Есть су*ка! Ребята меняли код, связанный немного с сетевым стеком и обработчиком на стороне сервера.
Даже спустя время не могу поделится хотя бы примерно что делало приложение и бизнес, так что опустим это.
Хорошо, допустим они что-то меняли, но в метриках и логах ведь ничего нет?
Стало интересно, переношу задачу на следующий спринт, ковыряю ещё несколько часов.
После детального ныряния есть зацепка, что у нас инфра сетевой стек говно и это уже проблема на нашей стороне.
Просидел ещё несколько часов.
Не буду ходить долгим путём как же я это выясни, где-то на грани безумства и безысходности пришла мысль, что проблема именно в том, что приложение стало создавать очень много короткоживущих TCP-сессий. Оно успевает ответить клиенту, но закрывает соединение так, что оно оставляет херню в ядре.
Первым делом иду на ноду, где размещён под, у которого проблема
Я выше писал как на ноду на ботлрокете заходить - https://xn--r1a.website/makebreakreflect/205
И ввожу команду:
И вот оно! Розовый слон в комнате:
Сразу же видна причина, можно было бы и раньше увидеть 🤡(нет)
Пакеты отбрасывает не приложение, не kube-proxy, не CNI - их отбрасывает само ядро Linux ноды, потому что его таблица сетевых состояний забита!
Далее я проверяю, насколько сильно таблица забита и каков ее лимит. Это прямое чтение файлов ядра.
Приложение-бэкенд, после изменений, стало генерировать аномально высокую частоту короткоживущих TCP-соединений. Система просто не успевает их забыть (таймаут 120 секунд слишком велик), и таблица переполняется.
Делаю нагрузочный тест - да, каррент каунт растёт.
Пробую фикс:
меняю таймаут с 120 на 60 на самой ноде и снова запускаю нагрузочный тест.
Тишина. Снова запускаю скрипт нагрузочного тестирования. Пятисотки исчезли! Красота!
Проконсультировался с коллегами - кто должен править:
- на стороне инфры
- на стороне приложения
Пару Очень Авторитетных Коллег Архитекторов сказали, что точно на стороне приложения и мы перекидываем мячик на сторону девелоперов. Они что-то там правят, тестируют этим же скриптом - всё отлично.
Выкатываем и фикс на прод, пятисоток больше нет, кастомеры довольны.
Белиссимо!
Не дай вселенная вам такое дебажить.😭
Прилетает аномалия: клиенты(живые люди), при обращении к нашему UI, начинают видеть таймауты и ошибки (5xx), особенно при резком росте нагрузки.
Ну ничего необычного. Кроме того, что такого быть не должно.
Смотрю логи фронта - он получает пятисотки от бэкенда.
Иду к бэкендерам, показываю логи, тыкаю пальцем, говорю чините.
Проходит день, два, а ошибки всё идут.
Разработчики чего только не делали:
- включали дебаг
- смотрели логи
- добавляли метрики
- добавляли ресурсы CPU/Memory (хотя нагрузка была не высокой)
- did a barrel roll
Ничего не помогает. По всей статистике, логам и метрикам - всё отлично, но есть проблема с пятисотками.
Я бы может этим и не занимался, но на общем митинге мне ставят блокер и говорят "это ваша инфра и девопсы, чините, но мы, если честно, сами не знаем чо тут и почему".
Хлеб всему голова, как и девопс всем ишшуям затычка, поехали траблшутить.
Вспоминаю, что нечто подобное уже было, и иду читать у себя же https://xn--r1a.website/aws_ru/136623
Проверяю - не, все ок с ALB и настройками приложений.
При помощи фронта и бэка пишу скрипт нагрузочного тестирования, чтобы сымитировать это в stage (да кому он сдался этот ваш dev!). Запускаю, половину не понимая, и да, с*ка, пятисотки.
Ещё раз опускаюсь в логи, трейсы, метрики - не за что зацепиться.
Просидел дня три наверное, пока всё это ковырял как дурачок.
Может и правда мы, из отдела инфры, дурачки и что-то поломали?
Сижу ковыряю коммиты и MR в репозиториях инфраструктуры за последние 3 месяца - ничего критичного.
Ладно. Пошёл ковырять само приложение.
Есть!, Есть су*ка! Ребята меняли код, связанный немного с сетевым стеком и обработчиком на стороне сервера.
Даже спустя время не могу поделится хотя бы примерно что делало приложение и бизнес, так что опустим это.
Хорошо, допустим они что-то меняли, но в метриках и логах ведь ничего нет?
Стало интересно, переношу задачу на следующий спринт, ковыряю ещё несколько часов.
После детального ныряния есть зацепка, что у нас инфра сетевой стек говно и это уже проблема на нашей стороне.
Просидел ещё несколько часов.
Не буду ходить долгим путём как же я это выясни, где-то на грани безумства и безысходности пришла мысль, что проблема именно в том, что приложение стало создавать очень много короткоживущих TCP-сессий. Оно успевает ответить клиенту, но закрывает соединение так, что оно оставляет херню в ядре.
Первым делом иду на ноду, где размещён под, у которого проблема
Я выше писал как на ноду на ботлрокете заходить - https://xn--r1a.website/makebreakreflect/205
И ввожу команду:
dmesg | grep conntrack
И вот оно! Розовый слон в комнате:
nf_conntrack: table full, dropping packet.
nf_conntrack: table full, dropping packet.
Сразу же видна причина, можно было бы и раньше увидеть 🤡
Пакеты отбрасывает не приложение, не kube-proxy, не CNI - их отбрасывает само ядро Linux ноды, потому что его таблица сетевых состояний забита!
Далее я проверяю, насколько сильно таблица забита и каков ее лимит. Это прямое чтение файлов ядра.
bash-5.1# cat /proc/sys/net/netfilter/nf_conntrack_count
192125
bash-5.1# cat /proc/sys/net/netfilter/nf_conntrack_max
262144
bash-5.1# cat /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_time_wait
120
Приложение-бэкенд, после изменений, стало генерировать аномально высокую частоту короткоживущих TCP-соединений. Система просто не успевает их забыть (таймаут 120 секунд слишком велик), и таблица переполняется.
Делаю нагрузочный тест - да, каррент каунт растёт.
Пробую фикс:
меняю таймаут с 120 на 60 на самой ноде и снова запускаю нагрузочный тест.
Тишина. Снова запускаю скрипт нагрузочного тестирования. Пятисотки исчезли! Красота!
Проконсультировался с коллегами - кто должен править:
- на стороне инфры
- на стороне приложения
Пару Очень Авторитетных Коллег Архитекторов сказали, что точно на стороне приложения и мы перекидываем мячик на сторону девелоперов. Они что-то там правят, тестируют этим же скриптом - всё отлично.
Выкатываем и фикс на прод, пятисоток больше нет, кастомеры довольны.
Белиссимо!
Не дай вселенная вам такое дебажить.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥26😱9👍3🤡1
#helm #kubernetes
Три прыжка.
Прыжок в воду 1.
Можно просто почитать официальную документацию на версию 3.19
Немного лукавит из-за нерегулярного обновления, но в целом 90% инженерам этого достаточно.
Мы теперь знаем, что перед деплойментом у нас есть секрет, перед ним PVC, а ещё раньше их неймспейс.
Это логично и не рождает проблем в стандартных чартах.
Прыжок в воду 2.
Так же можно посмотреть в исходном коде на версию 3.19
Там видно настоящий список, а так же указаны логические операторы про анноун ресурсам и сортировке.
Всякие CRD, хуки и весы.
Чуть точнее и глубже, этого достаточно ещё 5% людей.
Прыжок в воду 3.
Побудем сегодня любопытными инженерами и узнаем всё до конца, нырнув глубже.
В общем и целом есть несколько основных категорий:
-
-
-
-
-
При запуске
1)
Они не шаблонизируются, а применяются как есть.
https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/
2)
Если есть. (
Внутри группы хуков сначала сортируются по весу(
-
-
Внутри одного веса сортировка идёт по имени ресурса (алфавитно).
https://helm.sh/docs/topics/charts_hooks/
3)
Сортировка происходит после рендеринга шаблонов, но до их применения к кластеру.
Рендеринг -> сортировка -> применение.
-
-
..
-
..
-
..
4)
Так сказать всё остальное бесчисленное множество.
Важно понимать, что внутри группы
-
-
..
-
Этот алфавитный порядок зачастую не совпадает с требуемым логическим порядком зависимостей.
5)
Если есть. (
Внутри группы хуков сначала сортируются по весу(
-
-
Внутри одного веса сортировка идёт по имени ресурса (алфавитно).
https://helm.sh/docs/topics/charts_hooks/
Вот теперь картина полная и мы славные инженеры.
- - -
Для чего же мы ныряем так глубоко? Зачем нам это?
Иногда прилетают задачи о оптимизации имеющегося чарта.
Например (это. лишь. пример), у нас сложная технологическая платформа, а в чарте есть и
Все ресурсы категории
Нет ишшуера/не будет выпущен серт - не будет его куда запушить/примонтировать - не будет секрета/пушсикрета - проблема платформы. Да и серт не мгновенно выпускается. Нужно время. Как быть?
Тот же
Как раз тут и пригодятся нам эти глубокие знания.
Зная правила мы спокойно решаем задачу.
- Алекс, а что там с Арго?
Под капотом ArgoCD использует как раз
https://argo-cd.readthedocs.io/en/stable/user-guide/helm/
- А что там с хуками?
Argo CD автоматически конвертирует эту логику в свои Hooks и Waves, сохраняя ваш строгий контроль над порядком.
-
-
https://argo-cd.readthedocs.io/en/release-2.14/user-guide/resource_hooks/
https://argo-cd.readthedocs.io/en/stable/user-guide/sync-waves/
Занимательное:
- при
Три прыжка.
Как же идёт порядок генерации манифестов по шаблону, сортировка и применение в кластере при использовании Helm v3?
Прыжок в воду 1.
Можно просто почитать официальную документацию на версию 3.19
Немного лукавит из-за нерегулярного обновления, но в целом 90% инженерам этого достаточно.
Мы теперь знаем, что перед деплойментом у нас есть секрет, перед ним PVC, а ещё раньше их неймспейс.
Это логично и не рождает проблем в стандартных чартах.
Прыжок в воду 2.
Так же можно посмотреть в исходном коде на версию 3.19
Там видно настоящий список, а так же указаны логические операторы про анноун ресурсам и сортировке.
Всякие CRD, хуки и весы.
Чуть точнее и глубже, этого достаточно ещё 5% людей.
Прыжок в воду 3.
Побудем сегодня любопытными инженерами и узнаем всё до конца, нырнув глубже.
В общем и целом есть несколько основных категорий:
-
pre-* хуки-
post-* хуки-
Standard ресурсы-
CRD-
Unknown ресурсыПри запуске
helm install/helm upgrade --install у нас идёт такой порядок:1)
CRD. Всегда первым. Из директории <чарт>/crds/.Они не шаблонизируются, а применяются как есть.
https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/
2)
pre-install hooks. Если есть. (
"helm.sh/hook": *)Внутри группы хуков сначала сортируются по весу(
"helm.sh/hook-weight"):-
отрицательный -
ноль (по умолчанию)
- положительный
- по имениВнутри одного веса сортировка идёт по имени ресурса (алфавитно).
https://helm.sh/docs/topics/charts_hooks/
3)
standard ресурсы, по порядку в исходном коде в kind_sorter.goСортировка происходит после рендеринга шаблонов, но до их применения к кластеру.
Рендеринг -> сортировка -> применение.
-
PriorityClass-
Namespace..
-
ClusterRoleBinding..
-
Deployment..
4)
Unknown ресурсыТак сказать всё остальное бесчисленное множество.
Важно понимать, что внутри группы
Unknown ресурсов порядок детерминирован и следует правилу: сначала сортировка по Kind (алфавитно) (например, ApplicationSet перед PostgreSQL), а затем по имени ресурса (алфавитно).-
ApplicationsSet (ArgoCD)-
PostgreSQL (Zalando)..
-
ScaledObject (KEDA)Этот алфавитный порядок зачастую не совпадает с требуемым логическим порядком зависимостей.
5)
post-install хуки. Если есть. (
"helm.sh/hook": *)Внутри группы хуков сначала сортируются по весу(
"helm.sh/hook-weight"):-
отрицательный -
ноль (по умолчанию)
- положительный
- по имениВнутри одного веса сортировка идёт по имени ресурса (алфавитно).
https://helm.sh/docs/topics/charts_hooks/
Вот теперь картина полная и мы славные инженеры.
- - -
Для чего же мы ныряем так глубоко? Зачем нам это?
Иногда прилетают задачи о оптимизации имеющегося чарта.
Например (это. лишь. пример), у нас сложная технологическая платформа, а в чарте есть и
cert-manager с выпуском сертификатов, и externalsecrets и issuer, и многое другое.Все ресурсы категории
Unknown и нам нужен строгий порядок или, что хуже, тайминг(чтобы успело создаться что-то до следующего ресурса).Нет ишшуера/не будет выпущен серт - не будет его куда запушить/примонтировать - не будет секрета/пушсикрета - проблема платформы. Да и серт не мгновенно выпускается. Нужно время. Как быть?
Тот же
issuer по алфавиту идёт после certificate, хотя должно быть и иначе, а pushsecret ничего не сможет прокинуть, потому что серт ещё не выпущен. И всё обёрнуто через ArgoCD.Как раз тут и пригодятся нам эти глубокие знания.
Зная правила мы спокойно решаем задачу.
- Алекс, а что там с Арго?
Под капотом ArgoCD использует как раз
helm template.https://argo-cd.readthedocs.io/en/stable/user-guide/helm/
- А что там с хуками?
Argo CD автоматически конвертирует эту логику в свои Hooks и Waves, сохраняя ваш строгий контроль над порядком.
-
helm.sh/hook -> Resource Hooks-
helm.sh/hook-weight -> Sync Waveshttps://argo-cd.readthedocs.io/en/release-2.14/user-guide/resource_hooks/
https://argo-cd.readthedocs.io/en/stable/user-guide/sync-waves/
Занимательное:
- при
helm upgrade CRD из crds/ не обновляются (Helm не изменяет их содержимое, нужно делать вручную), только при helm install1👍19❤5🔥1👨💻1🆒1
#terragrunt
Волею случая и нового проекта надо было обновить террагрант.
Ну типа была версия старая, по привычке используемая везде - 0.54.15.
А тут и терраформ новее, и синтаксис подсвечивает модуль, что ошибка, и форматтера нет, и пре-коммит поставил, чтобы форматировал при коммитах.
А пре-коммит в свою очередь хочет минимум версию 0.77.22.
В общем надо было обновиться и я сделал это.
И тут, блин, началось. Мусор какой-то в аутпуте при плане и апплае.
Даже немного попсиховал.
Словно включен инфо/дебаг левел.
Сперва посмотрел в
По диагонали залез в мануал cli - ничего не нашёл.
Попробовал классические варианты типа
Тоже не помогает.
Херня какая, полез для скорости в AI (ох, и я попался на эту удочку снова).
Несёт хрень всякую, я гиеной заорал с советов, там и отключить это нельзя, и давай добавим local-exec с🤣
Делать нечего - полез в документацию, там, неожиданно для меня, произошли изменения касательно аутпута.
Начиная с версии v0.77.0 (вроде бы) террагрант вчистую выводит то, что даёт ему терраформ или другие утилиты типа opentofu.
https://terragrunt.gruntwork.io/docs/reference/logging/#log-levels
Чтобы "было как раньше" и "как привык" я пока нашёл одно решение - в
Ну либо использовать флаг (мне так очевидно неудобно).
Только так он выводит "как раньше", без лишнего мусора.
Предполагаю, что новые изменения удобнее всему комьюнити, кроме меня, ну либо для тех, у кого десятки, сотни модулей и при
Штош, ещё одна переменная в конфигах.
Волею случая и нового проекта надо было обновить террагрант.
Ну типа была версия старая, по привычке используемая везде - 0.54.15.
А тут и терраформ новее, и синтаксис подсвечивает модуль, что ошибка, и форматтера нет, и пре-коммит поставил, чтобы форматировал при коммитах.
---
repos:
- repo: https://github.com/gruntwork-io/pre-commit
rev: v0.1.30
hooks:
- id: terragrunt-hcl-fmt
А пре-коммит в свою очередь хочет минимум версию 0.77.22.
В общем надо было обновиться и я сделал это.
И тут, блин, началось. Мусор какой-то в аутпуте при плане и апплае.
Даже немного попсиховал.
Словно включен инфо/дебаг левел.
09:34:36.050 STDOUT terraform: ~ default_node_pool {
09:34:36.050 STDOUT terraform: ~ auto_scaling_enabled = false -> true
09:34:36.050 STDOUT terraform: ~ max_count = 0 -> 4
09:34:36.050 STDOUT terraform: ~ min_count = 0 -> 2
09:34:36.050 STDOUT terraform: name = "general"
09:34:36.050 STDOUT terraform: tags = {}
09:34:36.050 STDOUT terraform: # (28 unchanged attributes hidden)
09:34:36.050 STDOUT terraform: # (1 unchanged block hidden)
09:34:36.050 STDOUT terraform: }Сперва посмотрел в
env | grep -i terra / env | grep -i tf, но не вижу ничего критичного.По диагонали залез в мануал cli - ничего не нашёл.
Попробовал классические варианты типа
TF_LOG=ERROR TERRAGRUNT_LOG_LEVEL=error terragrunt plan
Тоже не помогает.
Херня какая, полез для скорости в AI (ох, и я попался на эту удочку снова).
Несёт хрень всякую, я гиеной заорал с советов, там и отключить это нельзя, и давай добавим local-exec с
export TF* Делать нечего - полез в документацию, там, неожиданно для меня, произошли изменения касательно аутпута.
Начиная с версии v0.77.0 (вроде бы) террагрант вчистую выводит то, что даёт ему терраформ или другие утилиты типа opentofu.
https://terragrunt.gruntwork.io/docs/reference/logging/#log-levels
Чтобы "было как раньше" и "как привык" я пока нашёл одно решение - в
~/.bashrc добавитьexport TG_LOG_FORMAT=bare
Ну либо использовать флаг (мне так очевидно неудобно).
terragrunt --log-format bare plan
Только так он выводит "как раньше", без лишнего мусора.
~ default_node_pool {
~ auto_scaling_enabled = false -> true
~ max_count = 0 -> 4
~ min_count = 0 -> 2
name = "general"
tags = {}
# (28 unchanged attributes hidden)
# (1 unchanged block hidden)
}Предполагаю, что новые изменения удобнее всему комьюнити, кроме меня, ну либо для тех, у кого десятки, сотни модулей и при
terragrunt run-all становится очень сложно понять, какое именно сообщение относится к какому именно модулю или к какому инструменту (Terragrunt или Terraform). Штош, ещё одна переменная в конфигах.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤1
#terragrunt
Интересную штуку подглядел у коллеги.
Ну с тегами окружения и менеджед бай террагрант меня не удивить.
Но путь до модуля! Это гениально!
Гениально и просто.
Почему я раньше об этом не знал? Это ведь так удобно, сразу видно откуда чего куда и как.
В эпоху модулей из модулей, внутри которых модули из модулей, со стаками, с композитными модулями - это чрезвычайно удобное мелкое дополнение.
Наверняка это придумали в мезозое и уже успели заменить на что-то другое, а я узнал только сегодня, ну да и ладно🤡
Интересную штуку подглядел у коллеги.
provider "aws" {
...
default_tags {
tags = {
environment = "${local.environment}"
managed_by = "terragrunt"
terragrunt_path = "${path_relative_to_include()}" <<<<<< this one
}
}
}
Ну с тегами окружения и менеджед бай террагрант меня не удивить.
Но путь до модуля! Это гениально!
Гениально и просто.
Почему я раньше об этом не знал? Это ведь так удобно, сразу видно откуда чего куда и как.
В эпоху модулей из модулей, внутри которых модули из модулей, со стаками, с композитными модулями - это чрезвычайно удобное мелкое дополнение.
Наверняка это придумали в мезозое и уже успели заменить на что-то другое, а я узнал только сегодня, ну да и ладно
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12👏1
Прям день интересных событий.
- то релиз helm 4 https://helm.sh/docs/overview/
- то nginx retirement https://kubernetes.io/blog/2025/11/11/ingress-nginx-retirement/
Всё же придётся ехать на k8s Gateway API?😭
- то релиз helm 4 https://helm.sh/docs/overview/
- то nginx retirement https://kubernetes.io/blog/2025/11/11/ingress-nginx-retirement/
To prioritize the safety and security of the ecosystem, Kubernetes SIG Network and the Security Response Committee are announcing the upcoming retirement of Ingress NGINX
Всё же придётся ехать на k8s Gateway API?
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7😭6
#kubernetes #troubleshooting #база
Просыпаюсь, иду работать, ничего не предвещает беды.
Хрен.
Через пару часов падает часть подов. UI - таймауты. Бэкенд - 5xx.
Приложение пишет, что не может создать файл.
Иногда не может прочитать файл.
Иногда "
Иногда "
Иногда просто падает - "
Короче, классический Kubernetes с его прозрачностью в траблшутинге.😀
Ну ладно. Открываю Grafana/VMlogs - ошибок море, но… никакой, блть, логики.
Все поды работают вроде бы одинаково, но часть подов стабильно отваливается примерно через минуту после старта.
Куда копать - сходу непонятно.
Иду в самое очевидное - Storage: PV, PVC
Потому что ошибки про файлы > проблемы с томами > ну значит PV/PVC где-то хромает, как старая лошадь.
Проверяю:
- PVC смонтировались? Да.
- PV healthy? Да.
- Нода здорова? Да.
- Место есть? Да.
- Inodes есть? (снова пригодились знания🕺 ) Да.
Да чтоб тебя, сука.
Пробую перезапустить под на другой ноде - та же история.
Смотрю в события пода - красиво, чисто, как будто всё хорошо.
А приложение продолжает ругаться.
Симптомы - про Storage, причина - явно что-то другое.
Чешу свой пельменоаннигилятор и иду смотреть
Разработчики говорят:
- Мы в PV почти ничего не пишем, у нас всё в /tmp, shared memory, и ещё парочка emptyDir
(я вообще не уверен, что они понимают разницу, наверняка спросили нейронку). Ладно.
Лезу в POD, смотрю
И тут интересное - папка есть, но файлы внутри иногда пропадают, иногда имеют странные владельцы, иногда пустые.
Жмурюсь, словно алкоголик с утра, перезапускаю под - то же самое.
Щёлкают мысли:
- race condition?
- или tmpfs не монтируется как надо?
- коричневая магия?
Проверяю:
Да, монтируется.
Проверяю параметры - тоже всё ок.
Чо ха херня.
Поехали к ноде. Захожу на ноду и смотрю логи kubelet
И тут - первый звоночек:
Вот оно.
Бл, но как так-то?!
Это странно:
* На самом деле этого уже достаточно, чтобы понять причину, но мне это станет ясно только позже.
Пока я этого не понимаю, иду дальше.
Пытаюсь понять, что у файла не так.
Смотрю
Иду в документацию приложения и к разработчикам, выясняю, что приложение должно работать от:
Но папки создаются с 1001, какие-то с root, какие-то с 2000.
Ошибка хаотичная.
При этом разработчики уверяют:
- Мы ничего такого не делали!
Ну да, конечно, лол.
Проверяю
И вот оно:
Ну, думаю, может фигня, мало ли. Но идём дальше.
По дороге читаю документацию к приложению, куберу (я чо, всё помнить должен что-ли? Конечно же я постоянно подсматриваю).
И тут я натыкаюсь на тот самый скрытый момент.
Как я понимаю, если в контейнере есть:
- tmpfs (например /tmp, shared memory, projected volumes)
- emptyDir
- securityContext с fsGroup
- и при этом runAsUser != fsGroup
- И ПРИ ЭТОМ, сука, приложение создаёт файлы при старте до того, как kubelet применил fsGroup, то...
...получаем race condition, когда kubelet пытается chown, но контейнер уже создал свои файлы - с другими UID/GID - и chown уже не проходит.
kubelet такой:
- Я меняю владельца папки!
контейнер такой:
- А я создаю файлы внутри неё!
девопс такой:
- А я в дурку еду от вас двоих!
И кто быстрее - тот и прав.
Результат:
- часть файлов принадлежит пользователю 1001
- часть - root
- часть - fsGroup (предполагаю)
- часть - остаётся как попало
- kubelet иногда пишет permission denied
- приложение иногда пишет permission denied
- иногда - no such file (потому что удаляется побочным процессом?)
- иногда - ломается tmpfs-шляпа полностью
Эти два идиота(кублет и контейнер) сражаются как два бомжа палками, измазанными в говне. Придурошные, лол.
Просыпаюсь, иду работать, ничего не предвещает беды.
Хрен.
Через пару часов падает часть подов. UI - таймауты. Бэкенд - 5xx.
Приложение пишет, что не может создать файл.
Иногда не может прочитать файл.
Иногда "
no such file or directory". Иногда "
permission denied". Иногда просто падает - "
error".Короче, классический Kubernetes с его прозрачностью в траблшутинге.
Ну ладно. Открываю Grafana/VMlogs - ошибок море, но… никакой, блть, логики.
Все поды работают вроде бы одинаково, но часть подов стабильно отваливается примерно через минуту после старта.
Куда копать - сходу непонятно.
Иду в самое очевидное - Storage: PV, PVC
Потому что ошибки про файлы > проблемы с томами > ну значит PV/PVC где-то хромает, как старая лошадь.
Проверяю:
- PVC смонтировались? Да.
- PV healthy? Да.
- Нода здорова? Да.
- Место есть? Да.
- Inodes есть? (снова пригодились знания
Да чтоб тебя, сука.
Пробую перезапустить под на другой ноде - та же история.
Смотрю в события пода - красиво, чисто, как будто всё хорошо.
А приложение продолжает ругаться.
Симптомы - про Storage, причина - явно что-то другое.
Чешу свой пельменоаннигилятор и иду смотреть
emptyDir/tmpfs и вот это вот всё.Разработчики говорят:
- Мы в PV почти ничего не пишем, у нас всё в /tmp, shared memory, и ещё парочка emptyDir
(я вообще не уверен, что они понимают разницу, наверняка спросили нейронку). Ладно.
Лезу в POD, смотрю
/tmp.И тут интересное - папка есть, но файлы внутри иногда пропадают, иногда имеют странные владельцы, иногда пустые.
Жмурюсь, словно алкоголик с утра, перезапускаю под - то же самое.
Щёлкают мысли:
- race condition?
- или tmpfs не монтируется как надо?
- коричневая магия?
Проверяю:
mount | grep tmpfs
Да, монтируется.
Проверяю параметры - тоже всё ок.
Чо ха херня.
Поехали к ноде. Захожу на ноду и смотрю логи kubelet
И тут - первый звоночек:
MountVolume.SetUp failed for volume "cache" : chown /var/lib/kubelet/pods/.../volumes/kubernetes.io~empty-dir/cache: permission denied
Вот оно.
Бл, но как так-то?!
Это странно:
emptyDir монтируется нормально, но kubelet не может сделать chown/chmod.* На самом деле этого уже достаточно, чтобы понять причину, но мне это станет ясно только позже.
Пока я этого не понимаю, иду дальше.
Пытаюсь понять, что у файла не так.
Смотрю
ls -la внутри контейнера:drwxr-xr-x 3 1001 root ...
Иду в документацию приложения и к разработчикам, выясняю, что приложение должно работать от:
runAsUser: 2000
runAsGroup: 2000
fsGroup: 2000
Но папки создаются с 1001, какие-то с root, какие-то с 2000.
Ошибка хаотичная.
При этом разработчики уверяют:
- Мы ничего такого не делали!
Ну да, конечно, лол.
Проверяю
git diff Helm-чарта.И вот оно:
securityContext:
runAsUser: 1001
runAsGroup: 1001
fsGroup: 1001
fsGroupChangePolicy: "OnRootMismatch"
Ну, думаю, может фигня, мало ли. Но идём дальше.
По дороге читаю документацию к приложению, куберу (я чо, всё помнить должен что-ли? Конечно же я постоянно подсматриваю).
И тут я натыкаюсь на тот самый скрытый момент.
Как я понимаю, если в контейнере есть:
- tmpfs (например /tmp, shared memory, projected volumes)
- emptyDir
- securityContext с fsGroup
- и при этом runAsUser != fsGroup
- И ПРИ ЭТОМ, сука, приложение создаёт файлы при старте до того, как kubelet применил fsGroup, то...
...получаем race condition, когда kubelet пытается chown, но контейнер уже создал свои файлы - с другими UID/GID - и chown уже не проходит.
kubelet такой:
- Я меняю владельца папки!
контейнер такой:
- А я создаю файлы внутри неё!
- А я в дурку еду от вас двоих!
И кто быстрее - тот и прав.
Результат:
- часть файлов принадлежит пользователю 1001
- часть - root
- часть - fsGroup (предполагаю)
- часть - остаётся как попало
- kubelet иногда пишет permission denied
- приложение иногда пишет permission denied
- иногда - no such file (потому что удаляется побочным процессом?)
- иногда - ломается tmpfs-шляпа полностью
Эти два идиота(кублет и контейнер) сражаются как два бомжа палками, измазанными в говне. Придурошные, лол.
Please open Telegram to view this post
VIEW IN TELEGRAM
2💊19❤10
#kubernetes #troubleshooting #база
Так какого рожна сломалось именно после обновления?
Вот тут самое вкусное.
Разработчики изменили не приложение, а🤡 :
То есть теперь контейнер стартует не как root, а как 1001.
Но в
fsGroup != runAsGroup и kubelet пытается менять владельцев!!!
А tmpfs создаётся уже внутри контейнера процессом с UID 1001!!!
Получается конфликт:
- kubelet хочет chown
- контейнер уже что-то пишет
- tmpfs/emptyDir получаются с разными владельцами
И Kubernetes начинает жрать собственную ногу.
Ну и чо делать?
- Вариант 1: отключить fsGroup, если он реально не нужен
- Вариант 2: поставить fsGroup = runAsGroup
- Вариант 3: включить legacy режим
Предполагаю, что третий вариант это костыль, пишу как вариант, но, я сделал вариант 2.
Но это не точно.
Какие итоги:
- снова нырнул в дебаггинг. Интересно, но снова потрачено время
- отмазкам "мы ничо не меняли" как обычно верить нельзя. Гит всё покажет
- я вообще не знаю как такое допускает архитектура куба, почему не сделать разумную валидацию где-то на это, ну бред же. Мы самолично стреляем себе в коленные чашечки и потом удивляемся "а чо не так то?"
Так какого рожна сломалось именно после обновления?
Вот тут самое вкусное.
Разработчики изменили не приложение, а
DockerfileUSER 1001
То есть теперь контейнер стартует не как root, а как 1001.
Но в
securityContext при этом осталось:fsGroup: 2000
runAsUser: 1001
runAsGroup: 1001
fsGroup != runAsGroup и kubelet пытается менять владельцев!!!
А tmpfs создаётся уже внутри контейнера процессом с UID 1001!!!
Получается конфликт:
- kubelet хочет chown
- контейнер уже что-то пишет
- tmpfs/emptyDir получаются с разными владельцами
И Kubernetes начинает жрать собственную ногу.
Ну и чо делать?
- Вариант 1: отключить fsGroup, если он реально не нужен
securityContext:
runAsUser: 1001
runAsGroup: 1001
fsGroup: null
- Вариант 2: поставить fsGroup = runAsGroup
securityContext:
runAsUser: 1001
runAsGroup: 1001
fsGroup: 1001
- Вариант 3: включить legacy режим
fsGroupChangePolicy: "Always"
Предполагаю, что третий вариант это костыль, пишу как вариант, но, я сделал вариант 2.
Но это не точно.
Какие итоги:
- снова нырнул в дебаггинг. Интересно, но снова потрачено время
- отмазкам "мы ничо не меняли" как обычно верить нельзя. Гит всё покажет
- я вообще не знаю как такое допускает архитектура куба, почему не сделать разумную валидацию где-то на это, ну бред же. Мы самолично стреляем себе в коленные чашечки и потом удивляемся "а чо не так то?"
Please open Telegram to view this post
VIEW IN TELEGRAM
💊19👍6❤2
Никогда такого не было, но кладуфлёр опять упал.
В статуспейдж пишут, что недоступен только саппорт и портал.
На самом деле он весь упал и у меня упал весь мой пет проект.
Печаль.
- https://www.cloudflarestatus.com/
- https://www.reddit.com/r/CloudFlare/comments/1p09n2i/cloudflare_issuesdown/
В статуспейдж пишут, что недоступен только саппорт и портал.
На самом деле он весь упал и у меня упал весь мой пет проект.
Печаль.
- https://www.cloudflarestatus.com/
- https://www.reddit.com/r/CloudFlare/comments/1p09n2i/cloudflare_issuesdown/
😁11
Из новостей мира AI.
1) Скачал тут IDE от Google и поработал пару часов. (да-да, там внутри всё равно VSCode style).
Первое впечатление - очень круто, в том числе за счет бесплатности моделей.
Даже новейшая Gemini 3 в комплекте🔥 .
Типичные сложнейшие таски по топикам террагрант/хелм/авс/секьюрити попросил - все отвечает ровно так, как я и хочу и код на 99% рабочий. Сами таски/вопросы написаны давно, часто на них проверяю новые IDE/модели.
После Kiro, Claude Code и Cursor всё выглядит на высшем уровне.
Рекомендация 10/10. *
* Особенно если нет возможности платить за альтернативный софт.
https://antigravity.google
2) Невероятно впечатлён моделью Kimi K2 Thinking на Perplexity (у меня прошка).
Если нужно очень глубоко нырнуть в задачу - самый сок и топ.
Таски:
- ресерч архитектуры
- сравнение подходов разработки и флоу
- глубочайшее(чуть ли не побайтовое) погружение в сорс код, чтобы понять где бага
Рекомендация 10/10.
Из минусов - ну вооооооооообще не быстро отвечает.
Подходит для задач, где не нужна спешка.
На сегодня это моя любимая модель для длительного ресёрча и подумать.
https://www.perplexity.ai
1) Скачал тут IDE от Google и поработал пару часов. (да-да, там внутри всё равно VSCode style).
Первое впечатление - очень круто, в том числе за счет бесплатности моделей.
Даже новейшая Gemini 3 в комплекте
Типичные сложнейшие таски по топикам террагрант/хелм/авс/секьюрити попросил - все отвечает ровно так, как я и хочу и код на 99% рабочий. Сами таски/вопросы написаны давно, часто на них проверяю новые IDE/модели.
После Kiro, Claude Code и Cursor всё выглядит на высшем уровне.
Рекомендация 10/10. *
* Особенно если нет возможности платить за альтернативный софт.
https://antigravity.google
2) Невероятно впечатлён моделью Kimi K2 Thinking на Perplexity (у меня прошка).
Если нужно очень глубоко нырнуть в задачу - самый сок и топ.
Таски:
- ресерч архитектуры
- сравнение подходов разработки и флоу
- глубочайшее(чуть ли не побайтовое) погружение в сорс код, чтобы понять где бага
Рекомендация 10/10.
Из минусов - ну вооооооооообще не быстро отвечает.
Подходит для задач, где не нужна спешка.
На сегодня это моя любимая модель для длительного ресёрча и подумать.
https://www.perplexity.ai
Please open Telegram to view this post
VIEW IN TELEGRAM
2🔥20❤1👎1🤔1
Чего только не пере изобретают.
Осуждаю.
Уволюсь, если кто такое внедрит на работе.
(нет, кого я обманываю, буду есть ложкой, если заставят 😭 )
https://github.com/toon-format/toon
Осуждаю.
Уволюсь, если кто такое внедрит на работе.
https://github.com/toon-format/toon
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
GitHub - toon-format/toon: 🎒 Token-Oriented Object Notation (TOON) – Compact, human-readable, schema-aware JSON for LLM prompts.…
🎒 Token-Oriented Object Notation (TOON) – Compact, human-readable, schema-aware JSON for LLM prompts. Spec, benchmarks, TypeScript SDK. - toon-format/toon
😁8💊4❤1
#aws #ecr #kubernetes
Представим себе, что у нас есть некий софт.
Он разрабатывается внутри компании и версионируется.
Результат сборки это готовый имадж в реджистри провайдера.
Затем мы этот софт предоставляете клиентам.
У софта есть версии и он разворачивается на одном регионе AWS.
Прям буквально клиенты тыкают в веб-интерфейсе, выбирают версию софта и регион(ы), в котором хотят видеть и дальше ваша, ну допустим назовём её "платформа" раскатывает софт нужной версии на нужных регионах.
Всё очень просто:
- собрали новый софт с новой версией
- готовый имадж положили в реджистри
- кастомер может задеплоить в доступный(е) регион(ы)
И всё бы хорошо, но как быть, когда у нас добавляются новые регионы?
Подняли новый регион, кастомер может задеплоить новую версию - всё работает.
Однако стоит выбрать старую версию продукта - поды падают с ошибкой пуллинга имаджа.
Старого имаджа в новом регионе ещё нет.
Варианты, которые сходу приходят в голову:
1)
Классная шутка, работает, но не покрывает кейс со "старыми имаджами", работает только для новых имаджей и всех последующих.
Да и она уже включена.
2)
Фича так же уже включена.
3) скрипт на питоне, которые будет синкать старые/имаджи при подключении нового региона
Только не в Слизерин! Лишь бы не скрипт, лишь бы не скрипт 🎩
4) не разрешать кастомеру деплоить на новые регионы старые версии
5) AWS event bridge + Lambda (не сработает, лямбда вроде не умеет работать с PTC)
6) схемы типа "
https://docs.aws.amazon.com/AmazonECR/latest/userguide/pull-through-cache-private.html (именно приват)
Pull-Through Cache для private-ECR-to-ECR-private работает (с 2023 года) с IAM аутентификацией.
Там есть пара ограничений, но для нашей задачи это подходит.
7) уход от парадигмы "один регион = имаджи только из регионального ECR", пуллить все из us-east-1
Смотрю
- как часто происходят релизы софта
- размер этих внутренних имаджа(ей)
- биллинг хранения и трафика ECR
- как часто будут разворачиваться новые регионы и как часто в новых регионах захотят старый софт
Дополнительно ресёрч:
- политики/доступы из других регионов в дефолт ECR из разных EKS
- kyverno policy (не будет ли перетирать путь)
- пулл секрет в новом регионе содержит правильный путь?
Минусы последнего решения понятны:
- цена: хранение/трафик (спойлер - увеличение на 13 баксов в месяц )
- latency на первый пулл
Мне нравятся оба варианта:
- Private Registry Upstream
- дефолт ECR для разных EKS
Дальше все факты, аргументы, расчёты, плюсы и минусы руководству.
Первый вариант это элегантность и оптимизация, второй это простота.
А какой уж вариант выберет руководство мы пока и не знаем. (знаем👍 )
Представим себе, что у нас есть некий софт.
Он разрабатывается внутри компании и версионируется.
Результат сборки это готовый имадж в реджистри провайдера.
Затем мы этот софт предоставляете клиентам.
У софта есть версии и он разворачивается на одном регионе AWS.
Прям буквально клиенты тыкают в веб-интерфейсе, выбирают версию софта и регион(ы), в котором хотят видеть и дальше ваша, ну допустим назовём её "платформа" раскатывает софт нужной версии на нужных регионах.
Всё очень просто:
- собрали новый софт с новой версией
- готовый имадж положили в реджистри
- кастомер может задеплоить в доступный(е) регион(ы)
И всё бы хорошо, но как быть, когда у нас добавляются новые регионы?
Подняли новый регион, кастомер может задеплоить новую версию - всё работает.
Однако стоит выбрать старую версию продукта - поды падают с ошибкой пуллинга имаджа.
Старого имаджа в новом регионе ещё нет.
Katastrofa!Варианты, которые сходу приходят в голову:
1)
ECR Replication - автоматическая репликация имаджей между регионами.Классная шутка, работает, но не покрывает кейс со "старыми имаджами", работает только для новых имаджей и всех последующих.
Да и она уже включена.
2)
Pull-Through Cache - великолепная штука, работает для всех внешних реджистри (ghcr.io, dockerhub, quay.io и тп). Фича так же уже включена.
3) скрипт на питоне, которые будет синкать старые/имаджи при подключении нового региона
4) не разрешать кастомеру деплоить на новые регионы старые версии
5) AWS event bridge + Lambda (не сработает, лямбда вроде не умеет работать с PTC)
6) схемы типа "
ECR-to-ECR PTC"https://docs.aws.amazon.com/AmazonECR/latest/userguide/pull-through-cache-private.html (именно приват)
Pull-Through Cache для private-ECR-to-ECR-private работает (с 2023 года) с IAM аутентификацией.
Там есть пара ограничений, но для нашей задачи это подходит.
7) уход от парадигмы "один регион = имаджи только из регионального ECR", пуллить все из us-east-1
Смотрю
- как часто происходят релизы софта
- размер этих внутренних имаджа(ей)
- биллинг хранения и трафика ECR
- как часто будут разворачиваться новые регионы и как часто в новых регионах захотят старый софт
Дополнительно ресёрч:
- политики/доступы из других регионов в дефолт ECR из разных EKS
- kyverno policy (не будет ли перетирать путь)
- пулл секрет в новом регионе содержит правильный путь?
Минусы последнего решения понятны:
- цена: хранение/трафик (спойлер -
- latency на первый пулл
Мне нравятся оба варианта:
- Private Registry Upstream
- дефолт ECR для разных EKS
Дальше все факты, аргументы, расчёты, плюсы и минусы руководству.
Первый вариант это элегантность и оптимизация, второй это простота.
А какой уж вариант выберет руководство мы пока и не знаем. (знаем
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6❤2
#aws #costoptimization #devops
А иногда вообще ничего из существующих финансовых алертов не помогает.
Нужен глубокий, живой человеческий анализ.
Был случай: проект, всё на AWS, стартап.
Постепенно рос, изменялся, но изначально у всех всюду был root-доступ (а как иначе в стартапе из 4 человек?). Набирались люди, улучшались процессы, разграничивались доступы, всё заносилось в IaC.
В целом стоимость услуг AWS была сравнительно небольшой, от 2к до 5к долларов, и держалась года полтора-два.
Раунд за раундом, компания выросла, трафика и сервиса стало больше, увеличился и счет.
Затем начали оптимизировать затраты: внедрили RI, SP (Reserved Instances, Savings Plans) и другие методы.
Обвешали обычным алертингом и FinOps-инструментами вроде Cost Anomaly Detection.
Каждые 1-3 месяца проводились Cost Review meetings, на которых обсуждались траты, предстоящий рост и многое другое. Каждая, повторюсь, позиция в биллинге детально разбиралась и для каждого участника команды и руководителя была очевидна, понятна и разумна.
Всё вышенаписанное лишь для того, чтобы подчеркнуть, что ничего нестандартного тут не было, всё как у всех.
Каждый месяц счет всё рос и рос. Где-то разумно за Compute - воркеры в EKS, где увеличилось количество реплик.
Где-то за RDS, потому как и размер БД увеличивается, и инстансы примерно раз в полгода-год увеличивали, да бэкапы (snapshots) также увеличивают стоимость хранения.
Где-то CloudFront, потому как количество клиентов и трафика стало больше.
Приходили и письма от Cost Anomaly Detection: "сервис А увеличился на 20% - теперь 21 доллар", "сервис Б увеличился на 47% и теперь 11 долларов".
И такие письма приходили регулярно.
Визуально - всё разумно и понятно:
- увеличивается количество кастомеров
- увеличивается трафик и нагрузка
- немного растет стоимость услуг
Однако пришел момент, когда счет за услуги CloudFront вырос до умопомрачительной отметки в 1000 долларов в месяц.
На очередном Cost meeting поставили задачу проверить корректность настроек, везде ли правильно включено кэширование, заголовки и так далее.
Триггернулись лишь потому, что на старте компании платили порядка 30 баксов, спустя год 150, затем 400 через два года, а тут сразу $1000 - слишком большой скачок.
Задачу поручили мне, и я начал копать.
Признаюсь - я ничего на тот момент не понял.
Ну ALB, CloudFront да API Gateway.
Много ресурсов, разные.
Поверхностно изучил еще раз - да, вроде очевиден рост как клиентов, так и трафика и биллинга.
Отписался "да всё норм", закрываю таску.
Спустя месяц счет стал уже 1250 долларов, и это напрягло всех.
Руководство попросило сделать анализ: как тут можно сэкономить, ведь ожидали рост клиентов x20, а это значит, что потенциально счет будет невероятно огромным.
Требовалось исследование альтернативных архитектурных решений.
Начал я повторно изучать, уже в процессе расписывая куда какой трафик идет, спрашивая разработчиков, смотря DNS, балансировщик, все файлы веб-страницы и многое другое.
Я это изучал лишь чтобы понять, как сейчас что работает, чтобы понять, как и на что мне надо заменить, чтобы снизить косты.
В процессе анализа для переноса архитектуры мне пришел неожиданный вопрос в голову:
а счет за CloudFront это с одного Distribution или с разных?
Начал включать аналитику и овервью.
Определились, что траты лишь с двух Distribution из 25.
Вопреки тому, что все думали изначально, что с 10-15.
Ок, копаю дальше, стало интересно, ведь именно у этих двух Distribution было несколько источников (Origins) и несколько правил поведения (Behaviors).
Мне же надо их на что-то менять, надо копнуть глубже.
А иногда вообще ничего из существующих финансовых алертов не помогает.
Нужен глубокий, живой человеческий анализ.
Был случай: проект, всё на AWS, стартап.
Постепенно рос, изменялся, но изначально у всех всюду был root-доступ (а как иначе в стартапе из 4 человек?). Набирались люди, улучшались процессы, разграничивались доступы, всё заносилось в IaC.
В целом стоимость услуг AWS была сравнительно небольшой, от 2к до 5к долларов, и держалась года полтора-два.
Раунд за раундом, компания выросла, трафика и сервиса стало больше, увеличился и счет.
Затем начали оптимизировать затраты: внедрили RI, SP (Reserved Instances, Savings Plans) и другие методы.
Обвешали обычным алертингом и FinOps-инструментами вроде Cost Anomaly Detection.
Каждые 1-3 месяца проводились Cost Review meetings, на которых обсуждались траты, предстоящий рост и многое другое. Каждая, повторюсь, позиция в биллинге детально разбиралась и для каждого участника команды и руководителя была очевидна, понятна и разумна.
Всё вышенаписанное лишь для того, чтобы подчеркнуть, что ничего нестандартного тут не было, всё как у всех.
Каждый месяц счет всё рос и рос. Где-то разумно за Compute - воркеры в EKS, где увеличилось количество реплик.
Где-то за RDS, потому как и размер БД увеличивается, и инстансы примерно раз в полгода-год увеличивали, да бэкапы (snapshots) также увеличивают стоимость хранения.
Где-то CloudFront, потому как количество клиентов и трафика стало больше.
Приходили и письма от Cost Anomaly Detection: "сервис А увеличился на 20% - теперь 21 доллар", "сервис Б увеличился на 47% и теперь 11 долларов".
И такие письма приходили регулярно.
Визуально - всё разумно и понятно:
- увеличивается количество кастомеров
- увеличивается трафик и нагрузка
- немного растет стоимость услуг
Однако пришел момент, когда счет за услуги CloudFront вырос до умопомрачительной отметки в 1000 долларов в месяц.
На очередном Cost meeting поставили задачу проверить корректность настроек, везде ли правильно включено кэширование, заголовки и так далее.
Триггернулись лишь потому, что на старте компании платили порядка 30 баксов, спустя год 150, затем 400 через два года, а тут сразу $1000 - слишком большой скачок.
Задачу поручили мне, и я начал копать.
Признаюсь - я ничего на тот момент не понял.
Ну ALB, CloudFront да API Gateway.
Много ресурсов, разные.
Поверхностно изучил еще раз - да, вроде очевиден рост как клиентов, так и трафика и биллинга.
Отписался "да всё норм", закрываю таску.
Спустя месяц счет стал уже 1250 долларов, и это напрягло всех.
Руководство попросило сделать анализ: как тут можно сэкономить, ведь ожидали рост клиентов x20, а это значит, что потенциально счет будет невероятно огромным.
Требовалось исследование альтернативных архитектурных решений.
Начал я повторно изучать, уже в процессе расписывая куда какой трафик идет, спрашивая разработчиков, смотря DNS, балансировщик, все файлы веб-страницы и многое другое.
Я это изучал лишь чтобы понять, как сейчас что работает, чтобы понять, как и на что мне надо заменить, чтобы снизить косты.
В процессе анализа для переноса архитектуры мне пришел неожиданный вопрос в голову:
а счет за CloudFront это с одного Distribution или с разных?
Начал включать аналитику и овервью.
Определились, что траты лишь с двух Distribution из 25.
Вопреки тому, что все думали изначально, что с 10-15.
Ок, копаю дальше, стало интересно, ведь именно у этих двух Distribution было несколько источников (Origins) и несколько правил поведения (Behaviors).
Мне же надо их на что-то менять, надо копнуть глубже.
👍9
#aws #costoptimization #devops
Затем я включил логирование (Standard log destinations) и положил все логи в S3 бакет.
Оставил на полдня, потом написал Bash-скрипт, который сделал простую выборку, например, top 20 requests by path с сортировкой по пути.
Тут меня ждало очередное удивление - в топе были не файлы S3, а балансировщик нагрузки (ALB) и поды Kubernetes🤡 .
То есть, у нас топ трафика - это НЕ кэшируемый трафик!🤬 Через клаудфронт! 🤬
Написал еще пару скриптов - да, у нас внезапно в этой схеме просто трафик шел в EKS и пару мест.
Собрали консилиум с коллегами, рассказал о своей, находке, чтобы спросить "а зачем так?".
Ответ был очевидным типа "ну так было исторически, нам надо было как-то роутить трафик по пути, мы в своё время сделали это через клаудфронт, чтобы не поднимать ещё один балансер или Nginx".
"Пздц" - подумал я и пошёл дальше изучать.
Да, действительно так и оказалось - часть трафика, и это 98% от всего в клаудфронте, шло НЕ для кеша.
Просто в поды кубернетиса.
Быстро напилил альтернативное решение, пару днс записей, проверили на dev - всё работает ок, без клаудфронта.
Дальше стейдж, прод, никаких проблем.
Сижу пишу
Понимаю, что надо сослаться на саппорт амазона, типа они негодяи не присылали кост аномали детекшн письма - но нет, присылали.
Думаю может не было реакции - нет, обсуждали повышения цен, даже текстов в чате.
Как так мы пропустили этот момент?
Подняли исторически все данные и за последние пару лет и только тогда картина полностью стала ясна.
- Изначально был временный костыль в одном из клаудфронтов - если путь /path1 то трафик отправлять в X, а если /-path2, то временно в Y.
- этого трафика была изначально мало и он вовсе попадал во free tier.
- затем его стало больше, стали платить 40 баксов, что было допустимо, затем 80 и так далее.
- пока не вырос до 1000 и 1250 долларов на момент кост инцидента.
Почему не обращали внимание раньше?
Потому что рост цены был медленным:
- кост аномали детекшн ловил рост цены примерно раз в неделю, и сумма каждый раз была небольшая
При постоянном медленном росте кост аномали детекшн начал отправлять всё реже и реже письма - это же очевидное поведение стало.
- все дефолт ссылки ведут на "cost and usage report" с коротким промежутком времени типа последние 30-40 дней
- на графиках и в письмах был небольшой рост - ну кто будет заниматься, если на прошлой недели мы платили 9 баксов день, а теперь 11 долларов в день, копейки же
Лишь взглянув на графики за полгода/год/два года/три года, стало ясно, что цена увеличивались постоянно.
Временный костыль начал в итоге вырабатывать 14 терабайт данных трафика.
Косяк девопса? Да.
Косяк костменеджера? Несомненно.
Косяк "временного решения"? Конечно.
Иногда, чтобы узнать, что проблема есть, надо нырнуть чуть глубже, чем "да вроде по делу списывают да не много же".
Иногда, чтобы узнать, что проблема есть, надо расширить графики больше, чем на две недели.
Суммарные потери последних 8 месяцев до этого кост инцидента - 4400 долларов.
Этот path в клаудфронте и не нужен был, просто поленились много лет назад сделать сразу нормально.
Затем я включил логирование (Standard log destinations) и положил все логи в S3 бакет.
Оставил на полдня, потом написал Bash-скрипт, который сделал простую выборку, например, top 20 requests by path с сортировкой по пути.
Тут меня ждало очередное удивление - в топе были не файлы S3, а балансировщик нагрузки (ALB) и поды Kubernetes
То есть, у нас топ трафика - это НЕ кэшируемый трафик!
Написал еще пару скриптов - да, у нас внезапно в этой схеме просто трафик шел в EKS и пару мест.
Собрали консилиум с коллегами, рассказал о своей, находке, чтобы спросить "а зачем так?".
Ответ был очевидным типа "ну так было исторически, нам надо было как-то роутить трафик по пути, мы в своё время сделали это через клаудфронт, чтобы не поднимать ещё один балансер или Nginx".
"Пздц" - подумал я и пошёл дальше изучать.
Да, действительно так и оказалось - часть трафика, и это 98% от всего в клаудфронте, шло НЕ для кеша.
Просто в поды кубернетиса.
Быстро напилил альтернативное решение, пару днс записей, проверили на dev - всё работает ок, без клаудфронта.
Дальше стейдж, прод, никаких проблем.
Сижу пишу
postmortem.Понимаю, что надо сослаться на саппорт амазона, типа они негодяи не присылали кост аномали детекшн письма - но нет, присылали.
Думаю может не было реакции - нет, обсуждали повышения цен, даже текстов в чате.
Как так мы пропустили этот момент?
Подняли исторически все данные и за последние пару лет и только тогда картина полностью стала ясна.
- Изначально был временный костыль в одном из клаудфронтов - если путь /path1 то трафик отправлять в X, а если /-path2, то временно в Y.
- этого трафика была изначально мало и он вовсе попадал во free tier.
- затем его стало больше, стали платить 40 баксов, что было допустимо, затем 80 и так далее.
- пока не вырос до 1000 и 1250 долларов на момент кост инцидента.
Почему не обращали внимание раньше?
Потому что рост цены был медленным:
- кост аномали детекшн ловил рост цены примерно раз в неделю, и сумма каждый раз была небольшая
При постоянном медленном росте кост аномали детекшн начал отправлять всё реже и реже письма - это же очевидное поведение стало.
- все дефолт ссылки ведут на "cost and usage report" с коротким промежутком времени типа последние 30-40 дней
- на графиках и в письмах был небольшой рост - ну кто будет заниматься, если на прошлой недели мы платили 9 баксов день, а теперь 11 долларов в день, копейки же
Лишь взглянув на графики за полгода/год/два года/три года, стало ясно, что цена увеличивались постоянно.
Временный костыль начал в итоге вырабатывать 14 терабайт данных трафика.
Косяк девопса? Да.
Косяк костменеджера? Несомненно.
Косяк "временного решения"? Конечно.
Иногда, чтобы узнать, что проблема есть, надо нырнуть чуть глубже, чем "да вроде по делу списывают да не много же".
Иногда, чтобы узнать, что проблема есть, надо расширить графики больше, чем на две недели.
Суммарные потери последних 8 месяцев до этого кост инцидента - 4400 долларов.
Этот path в клаудфронте и не нужен был, просто поленились много лет назад сделать сразу нормально.
Please open Telegram to view this post
VIEW IN TELEGRAM
🫡13👏3😢2❤1👍1