#longread #grafana #kubernetes #troubleshooting #одинденьизжизни
Три дашборда на границе Grafana
Часть 3 из 3.
Жду 30 секунд (updateIntervalSeconds в provisioning конфиге).
Проверяю:
Одна запись. Правильный title. Правильный UID.
Иду в UI - работает. Никаких дублей, никаких "Draft", никакого Loki.
Победа! 🎉
Если provisioning не срабатывает автоматически, можно вызвать reload через API (выше был пример курлом) или перезапустить pod Grafana (не мой вариант).
Подробнее про provisioning: https://grafana.com/docs/grafana/latest/administration/provisioning/
На всё ушло часа два.
Могло бы - минут пятнадцать, если бы сразу глянул в логи.
Выводы, а куда без них.
- Grafana provisioning не перезаписывает существующие записи в БД, если они созданы из другого источника. Он кидает ошибку в лог и оставляет старую версию.
- ошибка "A dashboard with the same uid already exists" - это про запись в PostgreSQL, не про файл. Файл может быть идеальным, но если в базе мусор - ничего не заработает.
- логи первым делом. Там обычно всё написано. Но не во всех версиях Grafana логи достаточно информативны.
- удаление из БД работает, но это неофициальный подход. Я не нашёл другого способа. Для provisioned dashboards безопасно - они автоматически пересоздаются из файлов. Главное - делать на primary ноде PostgreSQL и иметь бэкап.
- миграции дашбордов - это не "поменять пару строк". Особенно если UID менялся несколько раз. Особенно, если я баран.
Как избежать этой проблемы (предполагаю):
- не меняйте UID после первого деплоя. Если нужна миграция - создайте новый дашборд с новым UID, а старый удалите полностью (включая запись в БД).
- используйте стабильные UID с префиксами:
- не используйте один UID для дашбордов в разных папках - это создаёт race condition.
- документируйте миграции в changelog или README.
- используйте
Пример конфигурации провижининга
Альтернативный подход, без прямого доступа к БД - когда его нет или страшно (предполагаю, что это правильный путь, но я не проверял):
- временно переименовать ConfigMap (например добавить суффикс
- дождаться, пока Grafana удалит дашборды (если
- вернуть ConfigMap с правильным именем и новым UID
- provisioning создаст дашборды заново
Этот способ медленнее, но безопаснее.
Для зануд:
- - -
- https://github.com/grafana/grafana/issues/12411
- https://github.com/grafana/grafana/issues/41085
- https://github.com/grafana/grafana/issues/73043
Три дашборда на границе Grafana
Часть 3 из 3.
Жду 30 секунд (updateIntervalSeconds в provisioning конфиге).
Проверяю:
kubectl exec -n grafana pg-monitoring-2 -c postgres -- psql -U postgres -d grafana -c "SELECT id, uid, title FROM dashboard WHERE uid LIKE '%service-metrics%';"
id | uid | title
------+-----------------------------+--------------------------------------------
3838 | service-metrics-overview | Service Metrics Overview [VictoriaLogs]
Одна запись. Правильный title. Правильный UID.
Иду в UI - работает. Никаких дублей, никаких "Draft", никакого Loki.
Победа! 🎉
Если provisioning не срабатывает автоматически, можно вызвать reload через API (выше был пример курлом) или перезапустить pod Grafana (не мой вариант).
Подробнее про provisioning: https://grafana.com/docs/grafana/latest/administration/provisioning/
На всё ушло часа два.
Могло бы - минут пятнадцать, если бы сразу глянул в логи.
Выводы, а куда без них.
- Grafana provisioning не перезаписывает существующие записи в БД, если они созданы из другого источника. Он кидает ошибку в лог и оставляет старую версию.
- ошибка "A dashboard with the same uid already exists" - это про запись в PostgreSQL, не про файл. Файл может быть идеальным, но если в базе мусор - ничего не заработает.
- логи первым делом. Там обычно всё написано. Но не во всех версиях Grafana логи достаточно информативны.
- удаление из БД работает, но это неофициальный подход. Я не нашёл другого способа. Для provisioned dashboards безопасно - они автоматически пересоздаются из файлов. Главное - делать на primary ноде PostgreSQL и иметь бэкап.
- миграции дашбордов - это не "поменять пару строк". Особенно если UID менялся несколько раз. Особенно, если я баран.
Как избежать этой проблемы (предполагаю):
- не меняйте UID после первого деплоя. Если нужна миграция - создайте новый дашборд с новым UID, а старый удалите полностью (включая запись в БД).
- используйте стабильные UID с префиксами:
myteam-service-metrics-overview
myteam-app-logs-dashboard
- не используйте один UID для дашбордов в разных папках - это создаёт race condition.
- документируйте миграции в changelog или README.
- используйте
allowUiUpdates: false в provisioning конфиге - это предотвращает дрейф конфигурации.Пример конфигурации провижининга
apiVersion: 1
providers:
- name: 'sidecarProvider'
orgId: 1
type: file
disableDeletion: false
allowUiUpdates: false # запрет редактирования в UI
updateIntervalSeconds: 30 # интервал сканирования файлов
options:
foldersFromFilesStructure: true
path: /tmp/dashboards
Альтернативный подход, без прямого доступа к БД - когда его нет или страшно (предполагаю, что это правильный путь, но я не проверял):
- временно переименовать ConfigMap (например добавить суффикс
-old)- дождаться, пока Grafana удалит дашборды (если
disableDeletion: false)- вернуть ConfigMap с правильным именем и новым UID
- provisioning создаст дашборды заново
Этот способ медленнее, но безопаснее.
Для зануд:
Прямое изменение базы данных Grafana - неофициальная практика!
Это не является моим советом или рекомендацией!
Просто поделился своей историей.
- - -
- https://github.com/grafana/grafana/issues/12411
- https://github.com/grafana/grafana/issues/41085
- https://github.com/grafana/grafana/issues/73043
🔥8❤1
#kubernetes
Пока я спал там взломали все инторнеты и все кубернетисы.
Источник на английском с глубоким разбором.
- https://grahamhelton.com/blog/nodes-proxy-rce
Хорошие ребята, кого не жалко репостнуть:
- https://xn--r1a.website/tech_b0lt_Genona/6101
- https://labs.iximiuz.com/tutorials/nodes-proxy-rce-c9e436a9
Хорошо, что все кубернетисы (кроме моих личных лабораторий) на предыдущих и нынешней работах это приватные сетки (что спасает от внешних негодяев, но не спасает от внутренних, но таких у нас нет).
Как проверить, подвержен ли ваш кластер/SA? А легко!
Копи-паст скрипта в своем кластере:
Да, такие дела. Ну и порт 10250 должен быть доступен.
Пока я спал там взломали все инторнеты и все кубернетисы.
Источник на английском с глубоким разбором.
- https://grahamhelton.com/blog/nodes-proxy-rce
Хорошие ребята, кого не жалко репостнуть:
- https://xn--r1a.website/tech_b0lt_Genona/6101
- https://labs.iximiuz.com/tutorials/nodes-proxy-rce-c9e436a9
Хорошо, что все кубернетисы (кроме моих личных лабораторий) на предыдущих и нынешней работах это приватные сетки (что спасает от внешних негодяев, но не спасает от внутренних, но таких у нас нет).
Как проверить, подвержен ли ваш кластер/SA? А легко!
Копи-паст скрипта в своем кластере:
kubectl get serviceaccounts --all-namespaces -o json | \
jq -r '.items[] | "\(.metadata.namespace)\t\(.metadata.name)"' | \
while IFS=$'\t' read -r ns sa; do
if kubectl auth can-i get nodes/proxy --as="system:serviceaccount:${ns}:${sa}" -n "$ns" >/dev/null 2>&1; then
echo -e "${ns}\t${sa}\tyes"
fi
done
Да, такие дела. Ну и порт 10250 должен быть доступен.
🔥2
#kubernetes #golang #troubleshooting
Снова про операторы.
У ресурса
-
-
Как это работает на самом деле:
Когда ты создаёшь или обновляешь секрет, API-сервер мержит
В etcd хранилке и в ответе API сохраняется только
При чтении секрета из кластера поле
А теперь типичнейшая ошибка, на которую я снова попался.😭
Код оператора с ошибкой:
В реконсайлере проверка "изменился ли секрет?":
Видите проблему?
При создании desired-секрета мы используем
Но в Go-структуре этого объекта поле
Что происходит:
- оператор создаёт секрет с
- при следующем reconcile оператор читает секрет - там
- оператор строит desired-секрет - там
- сравнение видит разницу:
(потому что nil)
- оператор решает обновить секрет и делает
записывая nil в поле данных!
- теперь в кластере секрет с
(0 ключей)
- в следующем reconcile сравнение
оба пустые? Да!
- оператор думает: "секрет актуален", и никогда не восстанавливает данные🤡
Результат: секрет живёт,
Поды падают с:
Фикс очевиден: использовать
Теперь
🎉🎉🎉
Мораль:
-
-
- в client-go структуре
- если используешь
- сравнивай и применяй то, что реально используешь
Потерял на этом баге часа два, пока не дошло. Сука.
Секрет создавался, лейблы были,
Классика - симптомы в одном месте (падающие поды), причина в другом (nil вместо мапы в билдере).
Снова про операторы.
У ресурса
Secret в Kubernetes есть два поля для данных:-
Data map[string][]byte - бинарные данные, в YAML выглядят как base64-
StringData map[string]string - строковые данные, plain text в YAMLКак это работает на самом деле:
StringData - write-only поле для удобства. Когда ты создаёшь или обновляешь секрет, API-сервер мержит
StringData в Data (ключи из StringData перезаписывают Data при совпадении). В etcd хранилке и в ответе API сохраняется только
Data. При чтении секрета из кластера поле
StringData всегда пустое - его там просто нет.Поэтому StringData - для людей и YAML-манифестов, а Data - для кода операторов.
А теперь типичнейшая ошибка, на которую я снова попался.
Код оператора с ошибкой:
func BuildCredentialsSecret(instance *v1alpha1.MyApp) *corev1.Secret {
return &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: instance.Name + "-credentials",
Namespace: instance.Namespace,
},
Type: corev1.SecretTypeOpaque,
StringData: map[string]string{
"API_HOST": instance.Spec.Config.API.Host,
"API_TOKEN": instance.Spec.Config.API.Token,
},
}
}В реконсайлере проверка "изменился ли секрет?":
func secretDataEqual(a, b map[string][]byte) bool {
if len(a) != len(b) {
return false
}
for k, v := range a {
if !bytes.Equal(v, b[k]) {
return false
}
}
return true
}
// в reconcile:
if !secretDataEqual(found.Data, secret.Data) {
// обновляем секрет
found.Data = secret.Data // ВОТ ТУТ ПРОБЛЕМА
return r.Update(ctx, found)
}Видите проблему?
При создании desired-секрета мы используем
StringData. Но в Go-структуре этого объекта поле
Data равно nil, потому что мы его не заполняли!!!Что происходит:
- оператор создаёт секрет с
StringData > API сервер конвертирует в Data, в кластере всё ок- при следующем reconcile оператор читает секрет - там
Data заполнен- оператор строит desired-секрет - там
Data = nil, StringData заполнен- сравнение видит разницу:
len(found.Data) != 0, а len(secret.Data) == 0
(потому что nil)
- оператор решает обновить секрет и делает
found.Data = secret.Data
записывая nil в поле данных!
- теперь в кластере секрет с
data: {}(0 ключей)
- в следующем reconcile сравнение
secretDataEqual(found.Data, nil)
оба пустые? Да!
(len(nil) == 0, len(map{}) == 0)- оператор думает: "секрет актуален", и никогда не восстанавливает данные
Результат: секрет живёт,
ownerReference на месте, лейблы есть, а данных - ноль. Поды падают с:
MountVolume.SetUp failed for volume "credentials":
references non-existent secret key: API_TOKEN
Фикс очевиден: использовать
Data в коде оператора:func BuildCredentialsSecret(instance *v1alpha1.MyApp) *corev1.Secret {
return &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: instance.Name + "-credentials",
Namespace: instance.Namespace,
},
Type: corev1.SecretTypeOpaque,
Data: map[string][]byte{
"API_HOST": []byte(instance.Spec.Config.API.Host),
"API_TOKEN": []byte(instance.Spec.Config.API.Token),
},
}
}Теперь
secret.Data заполнен, сравнение работает корректно, и ты случайно не затираешь данные nil-ом.🎉🎉🎉
Мораль:
-
stringData - для YAML и kubectl, где удобно писать plain text-
data - для кода операторов на Go- в client-go структуре
StringData и Data - разные поля; API сервер не синхронизирует их при чтении- если используешь
StringData в коде, помни: secret.Data == nil в этой структуре- сравнивай и применяй то, что реально используешь
Потерял на этом баге часа два, пока не дошло. Сука.
Секрет создавался, лейблы были,
ownerReference был, а данных - ноль. Классика - симптомы в одном месте (падающие поды), причина в другом (nil вместо мапы в билдере).
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6👍6
#kubernetes #aws #eks #helm
Тихо и незаметно вышла мажорная версия AWS Load Balancer Controller - 3.0.0.
https://github.com/kubernetes-sigs/aws-load-balancer-controller
Вместе с ней и Helm-чарт тоже прыгнул на 3.x.
https://github.com/aws/eks-charts/tree/master/stable/aws-load-balancer-controller
Как я понял по заявлению мейнтейнеров, breaking changes в пользовательском API (Ingress, Service, Gateway) они не предполагают.
Но issue на GitHub уже висят, так что посмотрим.
Что важного и интересного (для меня):
- Gateway API объявлен GA (production ready) - теперь можно смело использовать в бою, а не в тестовых проектах 🔥
- Версия Helm-чарта выровнена с версией контроллера - раньше было 2.x контроллер с чартом 1.x, теперь 3.0.0 = 3.0.0. Наконец-то! ❤️
- Новые фиксы NLB target groups, порядка сабнетов, AZ mismatch и webhook-сертификатов
- CRD ListenerRuleConfiguration добавлен, но пока экспериментальный - не использовать в проде
- Минимальная версия Kubernetes - теперь официально требуется 1.24+ (интересно, кто ещё на таком старье сидит😁 )
- IPv6 для internet-facing ALB/NLB - теперь нативно поддерживается без костылей, раньше были ограничения 🎉
Нюансы с апгрейдом:
- перед helm upgrade до 3.0.0 нужно вручную обновить CRD'ы. Issue #4555 прямо про это - люди натыкаются на проблемы, потому что в release notes это не очень явно прописано.
Но как по мне так это и очевидно, так как мы все знаем, что при хелм апгрейде CRD не обновляется никогда и ни у кого, архитектурная особенность самого хелма.
- для Gateway API нужны не только CRD самого контроллера, но и базовые Gateway API CRD (HTTPRoute, GatewayClass и т.д.), если их ещё нет в кластере
Сам, конечно же, я пока обновляться не буду.
Почитаю issues ещё недельку, потом с командой решим - стоит ли сразу или подождать патч-релиз.
Better safe than sorry, особенно с ингресс-контроллерами, которые держат весь трафик.
Тихо и незаметно вышла мажорная версия AWS Load Balancer Controller - 3.0.0.
https://github.com/kubernetes-sigs/aws-load-balancer-controller
Вместе с ней и Helm-чарт тоже прыгнул на 3.x.
https://github.com/aws/eks-charts/tree/master/stable/aws-load-balancer-controller
Как я понял по заявлению мейнтейнеров, breaking changes в пользовательском API (Ingress, Service, Gateway) они не предполагают.
Но issue на GitHub уже висят, так что посмотрим.
Что важного и интересного (для меня):
- Gateway API объявлен GA (production ready) - теперь можно смело использовать в бою, а не в тестовых проектах 🔥
- Версия Helm-чарта выровнена с версией контроллера - раньше было 2.x контроллер с чартом 1.x, теперь 3.0.0 = 3.0.0. Наконец-то! ❤️
- Новые фиксы NLB target groups, порядка сабнетов, AZ mismatch и webhook-сертификатов
- CRD ListenerRuleConfiguration добавлен, но пока экспериментальный - не использовать в проде
- Минимальная версия Kubernetes - теперь официально требуется 1.24+ (интересно, кто ещё на таком старье сидит
- IPv6 для internet-facing ALB/NLB - теперь нативно поддерживается без костылей, раньше были ограничения 🎉
Нюансы с апгрейдом:
- перед helm upgrade до 3.0.0 нужно вручную обновить CRD'ы. Issue #4555 прямо про это - люди натыкаются на проблемы, потому что в release notes это не очень явно прописано.
Но как по мне так это и очевидно, так как мы все знаем, что при хелм апгрейде CRD не обновляется никогда и ни у кого, архитектурная особенность самого хелма.
- для Gateway API нужны не только CRD самого контроллера, но и базовые Gateway API CRD (HTTPRoute, GatewayClass и т.д.), если их ещё нет в кластере
Сам, конечно же, я пока обновляться не буду.
Почитаю issues ещё недельку, потом с командой решим - стоит ли сразу или подождать патч-релиз.
Better safe than sorry, особенно с ингресс-контроллерами, которые держат весь трафик.
Please open Telegram to view this post
VIEW IN TELEGRAM
💯4🎃1
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7🤣4🤯3💔2👍1
Там
Прям с графиками, картиночками, наглядно.
В целом годно, как и многие его другие ресурсы/статьи. Никакого рокетсайнса и кишочков - просто база-дополнение к официальной документации.
Рекомендую как для общего развития начинающим специалистам, так и в качестве подготовки к собеседованиям на тему кубернетиса.
https://learnkube.com/kubernetes-api-explained
Daniele Polencic обновил статью про k8s API.Прям с графиками, картиночками, наглядно.
В целом годно, как и многие его другие ресурсы/статьи. Никакого рокетсайнса и кишочков - просто база-дополнение к официальной документации.
Рекомендую как для общего развития начинающим специалистам, так и в качестве подготовки к собеседованиям на тему кубернетиса.
https://learnkube.com/kubernetes-api-explained
🔥12👍2
#gitlab #troubleshooting #одинденьизжизни
На новом проекте дали задачу: небольшие изменения в гошном операторе Kubernetes.
Секреты, cluster-scoped объекты, ничего космического.
Покрутил код, разобрался в архитектуре, поднял локальный kind-кластер, погонял тесты.
Makefile на месте, всё зелёное. Красота.
Коммичу, пушу MR.
Тесты падают. 🙃
Ну ладно, думаю. Я серьёзно менял логику, наверное поломал что-то. Бывает.
Возвращаюсь, перепроверяю. Локально гоняю - всё проходит.
Коммичу, пушу - снова падает.
Ок, уже интересно.
Открываю
Повторяю ровно то же самое локально - make test, всё зелёное.
В GitLab - красное.
Смотрю логи джобы внимательнее.
Один из тестов падает на скачивании image из container registry соседнего репозитория. Не хватает авторизации. Ага.
Проверяю:
- мой GitLab токен - валидный✅
- доступ в соседние репозитории (сайдкар-образы для тестов) - есть✅
- образы в registry - на месте✅
- пайплайн до моих изменений - зелёный, тесты проходили✅
Всё на месте, а не работает.🤡
Перепроверяю ещё тысячу раз.
Локально - 100% то же самое - работает.
В GitLab - нет.
Тут приходит мысль: а может дело не в коде, а в правах?
Пайплайн-то запускается от моего имени.
А у тех, кто запускал до меня, может быть что-то другое.
Иду смотреть настройки репозитория.
Settings - нет доступа.
Access Tokens - нет доступа.
Deploy Tokens - нет доступа.
У меня Developer, без права заглянуть хоть куда-то в настройки.
Пишу в личку коллеге, который точно Admin:
- Слушай, можешь по этой ссылке просто нажать Retry на джобе тестов?
Он жмёт.
Тесты проходят. ✅Сука.
Я жму Retry.
Тесты падают. ❌Сука.
Пишу главной команде DevOps (да, оксюморон - девопс пишет девопсам "спасити-памагити").
Объясняю ситуацию: так и так, тесты падают только когда пайплайн запускает мой юзер, предполагаю, что
Ну, после некоторых усилий удалось донести мысль. Ребята берут таймаут.
Через несколько дней/часов:
- Ретрай.
Ретраю.
Зелёное. 🎉
- А что было?
- Мы тоже долго дебажили, скормили все токены в Claude, но нашли.
У тебя в профиле GitLab стояла галочка External User.
External. User. Сука.
Галочка. В профиле. Которую я не ставил. Которую даже не видел (у меня нет доступа к админ-панели). Которую кто-то когда-то поставил при создании моего аккаунта. Или не снял. Или поставил по дефолту в LDAP/SAML/SCIM-маппинге. Или просто потому что.
Что делает External User в GitLab:
- https://docs.gitlab.com/administration/external_users/
- внешний пользователь не имеет доступа к internal-репозиториям
- CI_JOB_TOKEN наследует ограничения профиля
- даже если у тебя есть явный Developer-доступ к проекту, некоторые internal-ресурсы (включая container registry соседних проектов) могут быть недоступны
- в логах пайплайна это выглядит как обычная 401/403 при pull image - ни слова про external user
Всё работает. Везде. Кроме одного места.
И это место - галочка в чужой админ-панели, которую ты даже увидеть не можешь.
Потрачено:
- ~6-7 часов моего времени на дебаг
- N часов времени DevOps-команды
- массу нервных клеток
- массу токенов в Claude
Выводы:
- если пайплайн падает только у вашего юзера, а у коллег - нет, проблема не всегда в коде.
Проблема иногда в правах. Не в правах репозитория, а в правах профиля.
- External User в GitLab - это тихий убийца. Никаких предупреждений в UI, никаких баннеров "вы external". Просто
- вы не увидите эту галочку сами - она в Admin Area, доступ только у администраторов GitLab.
- при онбординге на новый проект спросите: "А мой аккаунт точно не external?" Серьёзно. Одна галочка - полдня жизни.
- локальные тесты != CI тесты. Даже если команды идентичны. Контекст авторизации разный.
- и как обычно: во всём виноваты девопсы. Даже когда девопс - это ты сам.😢
Тихий убийца времени.
На новом проекте дали задачу: небольшие изменения в гошном операторе Kubernetes.
Секреты, cluster-scoped объекты, ничего космического.
Покрутил код, разобрался в архитектуре, поднял локальный kind-кластер, погонял тесты.
Makefile на месте, всё зелёное. Красота.
Коммичу, пушу MR.
Тесты падают. 🙃
Ну ладно, думаю. Я серьёзно менял логику, наверное поломал что-то. Бывает.
Возвращаюсь, перепроверяю. Локально гоняю - всё проходит.
Коммичу, пушу - снова падает.
Ок, уже интересно.
Открываю
.gitlab-ci.yml, читаю джобу тестов строчка за строчкой.Повторяю ровно то же самое локально - make test, всё зелёное.
В GitLab - красное.
Смотрю логи джобы внимательнее.
Один из тестов падает на скачивании image из container registry соседнего репозитория. Не хватает авторизации. Ага.
Проверяю:
- мой GitLab токен - валидный✅
- доступ в соседние репозитории (сайдкар-образы для тестов) - есть✅
- образы в registry - на месте✅
- пайплайн до моих изменений - зелёный, тесты проходили✅
Всё на месте, а не работает.
Перепроверяю ещё тысячу раз.
Локально - 100% то же самое - работает.
В GitLab - нет.
Тут приходит мысль: а может дело не в коде, а в правах?
Пайплайн-то запускается от моего имени.
А у тех, кто запускал до меня, может быть что-то другое.
Иду смотреть настройки репозитория.
Settings - нет доступа.
Access Tokens - нет доступа.
Deploy Tokens - нет доступа.
У меня Developer, без права заглянуть хоть куда-то в настройки.
Пишу в личку коллеге, который точно Admin:
- Слушай, можешь по этой ссылке просто нажать Retry на джобе тестов?
Он жмёт.
Тесты проходят. ✅Сука.
Я жму Retry.
Тесты падают. ❌Сука.
Пишу главной команде DevOps (да, оксюморон - девопс пишет девопсам "спасити-памагити").
Объясняю ситуацию: так и так, тесты падают только когда пайплайн запускает мой юзер, предполагаю, что
CI_JOB_TOKEN моего профиля не имеет нужных прав, он передаётся в кубер как image pull secret, а там авторизация не проходит.Ну, после некоторых усилий удалось донести мысль. Ребята берут таймаут.
Через несколько дней/часов:
- Ретрай.
Ретраю.
Зелёное. 🎉
- А что было?
- Мы тоже долго дебажили, скормили все токены в Claude, но нашли.
У тебя в профиле GitLab стояла галочка External User.
External. User. Сука.
Галочка. В профиле. Которую я не ставил. Которую даже не видел (у меня нет доступа к админ-панели). Которую кто-то когда-то поставил при создании моего аккаунта. Или не снял. Или поставил по дефолту в LDAP/SAML/SCIM-маппинге. Или просто потому что.
Что делает External User в GitLab:
- https://docs.gitlab.com/administration/external_users/
- внешний пользователь не имеет доступа к internal-репозиториям
- CI_JOB_TOKEN наследует ограничения профиля
- даже если у тебя есть явный Developer-доступ к проекту, некоторые internal-ресурсы (включая container registry соседних проектов) могут быть недоступны
- в логах пайплайна это выглядит как обычная 401/403 при pull image - ни слова про external user
Всё работает. Везде. Кроме одного места.
И это место - галочка в чужой админ-панели, которую ты даже увидеть не можешь.
Потрачено:
- ~6-7 часов моего времени на дебаг
- N часов времени DevOps-команды
- массу нервных клеток
- массу токенов в Claude
Выводы:
- если пайплайн падает только у вашего юзера, а у коллег - нет, проблема не всегда в коде.
Проблема иногда в правах. Не в правах репозитория, а в правах профиля.
- External User в GitLab - это тихий убийца. Никаких предупреждений в UI, никаких баннеров "вы external". Просто
CI_JOB_TOKEN молча получает урезанные права.- вы не увидите эту галочку сами - она в Admin Area, доступ только у администраторов GitLab.
- при онбординге на новый проект спросите: "А мой аккаунт точно не external?" Серьёзно. Одна галочка - полдня жизни.
- локальные тесты != CI тесты. Даже если команды идентичны. Контекст авторизации разный.
- и как обычно: во всём виноваты девопсы. Даже когда девопс - это ты сам.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍25🤡2💔1
#longread #troubleshooting #operators #kubectl #kubernetes #одинденьизжизни
Внезапный и незапланированный лонгрид.
Разбирал по работе задачу, узнал новое про фичу
Теперь делюсь историей и знаниями с вами.
Приятного прочтения.
https://teletype.in/@kruchkov_alexandr/wWa-INvQvJH
Внезапный и незапланированный лонгрид.
Разбирал по работе задачу, узнал новое про фичу
kubectl cache discovery.Теперь делюсь историей и знаниями с вами.
Приятного прочтения.
https://teletype.in/@kruchkov_alexandr/wWa-INvQvJH
Teletype
Когда kubectl врёт
Сегодня мне для нашего кубернетис оператора надо было поменять Namespaced scope на Cluster scope у одного CRD.
15👍28🔥1
#devops
Просто делюсь последними находками.
- https://system-design.space/
Нечто типа русскоязычного справочника по system design.
Большой и объёмный. Начал почитывать, весьма годно.
За один присест всё не осилить, буду продолжать как книгу читать ближайшие месяцы.
Достойный аналог известному https://github.com/donnemartin/system-design-primer
Оцениваю как 9.5/10.
- https://endoflife.date/
А где-же, а где-же я смотрю когда что протухнет?
Не руками/глазами же смотрю на сайте каждого облака/ продукта/ компонента/ девайс/ операционка/ имадж/ фремворка/ либы.
Если надо глазами глянуть, то этот сайт просто топ.
Для обычных библиотек софта есть dependabot/Renovatebot (кстати, кто-то из них с этого же сайта берёт инфо).
А для всего остального этот ресурс.
Может даже у него MCP есть, но я не искал, я быстрее глазами найду, чем заряжать на это LLM.
Оцениваю как 9/10 (есть не всё).
- https://thenewstack.io/
Невероятно захватывающие и очень интересные мне истории, случаи, опыт, рассказы, postmortems.
DevOps, k8s, cloud и вот это вот всё.
Читаю те топики, что мне интересны, часть пропускаю (есть и маркетинг буллшит).
Оцениваю в 8.5/10.
- https://awesome-llmops.inftyai.com/
- https://github.com/InftyAI/Awesome-LLMOps
Неплохая таблица как у https://landscape.cncf.io/, но по LLM/LLMOps.
Курируемый список (awesome list) инструментов для LLMOps, он охватывает инференс, оркестрацию, RAG, агентов, fine-tuning и мониторинг LLM.
Короче очередной неплохой awesome список.
В мире AI, когда каждый день всё меняется, это неплохой источник.
А надо быть в курсе всего этого, иначеуволят будешь не в теме.
Оценка 8/10.
- https://resources.anthropic.com/hubfs/The-Complete-Guide-to-Building-Skill-for-Claude.pdf?hsLang=en
Крутой мануал по скиллам. Сразу запилил себе кучу всего полезного.
Нет смысла рассказывать, что себе сделал, так как эта инфа устареет уже завтра, когда выйдет очередная новая модель и обновление курсора с новыми фичами.
Имеет смысл ознакомится и попробовать либо сейчас, либо сразу скипнуть.
- https://agentsmd.io/agents-md-best-practices
Бест практисы с AGENTS.md файлом.
Ровно как и предыдущая ссылка будет актуально лишь короткое время.
Имеет смысл ознакомится и попробовать либо сейчас, либо сразу скипнуть.
- https://github.com/metalbear-co/mirrord
Очень интересная задумка. Конечно же у него есть аналоги, но мне понравилась эта реализация.
Потыкал на лабораторном кластере с go-шным и php стеком - прикольно!
В отличии от telepresence/gefyra/nocalhost невероятно низкий входной порог и буквально в три клика развернуть.
Простота в наше переусложнённое время дорогого стоит.
Однозначно лайк, надеюсь они не умрут через полгода.
Оценка 10/10.
Было ещё много прочитанного, изученного, но в общем и целом это, скорее, белый шум, чем что-то, чем хочется поделится.
Просто делюсь последними находками.
- https://system-design.space/
Нечто типа русскоязычного справочника по system design.
Большой и объёмный. Начал почитывать, весьма годно.
За один присест всё не осилить, буду продолжать как книгу читать ближайшие месяцы.
Достойный аналог известному https://github.com/donnemartin/system-design-primer
Оцениваю как 9.5/10.
- https://endoflife.date/
А где-же, а где-же я смотрю когда что протухнет?
Не руками/глазами же смотрю на сайте каждого облака/ продукта/ компонента/ девайс/ операционка/ имадж/ фремворка/ либы.
Если надо глазами глянуть, то этот сайт просто топ.
Для обычных библиотек софта есть dependabot/Renovatebot (кстати, кто-то из них с этого же сайта берёт инфо).
А для всего остального этот ресурс.
Может даже у него MCP есть, но я не искал, я быстрее глазами найду, чем заряжать на это LLM.
Оцениваю как 9/10 (есть не всё).
- https://thenewstack.io/
Невероятно захватывающие и очень интересные мне истории, случаи, опыт, рассказы, postmortems.
DevOps, k8s, cloud и вот это вот всё.
Читаю те топики, что мне интересны, часть пропускаю (есть и маркетинг буллшит).
Оцениваю в 8.5/10.
- https://awesome-llmops.inftyai.com/
- https://github.com/InftyAI/Awesome-LLMOps
Неплохая таблица как у https://landscape.cncf.io/, но по LLM/LLMOps.
Курируемый список (awesome list) инструментов для LLMOps, он охватывает инференс, оркестрацию, RAG, агентов, fine-tuning и мониторинг LLM.
Короче очередной неплохой awesome список.
В мире AI, когда каждый день всё меняется, это неплохой источник.
А надо быть в курсе всего этого, иначе
Оценка 8/10.
- https://resources.anthropic.com/hubfs/The-Complete-Guide-to-Building-Skill-for-Claude.pdf?hsLang=en
Крутой мануал по скиллам. Сразу запилил себе кучу всего полезного.
Нет смысла рассказывать, что себе сделал, так как эта инфа устареет уже завтра, когда выйдет очередная новая модель и обновление курсора с новыми фичами.
Имеет смысл ознакомится и попробовать либо сейчас, либо сразу скипнуть.
- https://agentsmd.io/agents-md-best-practices
Бест практисы с AGENTS.md файлом.
Ровно как и предыдущая ссылка будет актуально лишь короткое время.
Имеет смысл ознакомится и попробовать либо сейчас, либо сразу скипнуть.
- https://github.com/metalbear-co/mirrord
Очень интересная задумка. Конечно же у него есть аналоги, но мне понравилась эта реализация.
Потыкал на лабораторном кластере с go-шным и php стеком - прикольно!
В отличии от telepresence/gefyra/nocalhost невероятно низкий входной порог и буквально в три клика развернуть.
Простота в наше переусложнённое время дорогого стоит.
Однозначно лайк, надеюсь они не умрут через полгода.
Оценка 10/10.
Было ещё много прочитанного, изученного, но в общем и целом это, скорее, белый шум, чем что-то, чем хочется поделится.
10👍20🔥16
Перешёл на Ask every time в Cursor IDE.
Устал разгребать дерьмо от агента.
Прям утомился и устал.
Реалии февраля 2026:
- игнорирует allow list в README.md
- игнорирует allow list в настройках Cursor IDE
- игнорирует файл(ы) rules Cursor IDE
- игнорирует allow для MCP серверов
- игнорирует явные запреты в AGENTS.md
- игнорирует рут сандбокс (может легко выходить из песочницы)
- при моих запретах средствами операционной системы начинает писать питон скрипты, чтобы обойти запреты доступа к файловой системе и просить аппрув на выполнение🤨
Каждый раз без зазрения совести использует опасные команды без аппрува, если ему захотелось
-
-
-
-
и многое другое. Печаль.
Модели:
- Claude-4.5-sonnet
- 4.6 Opus
Четырёх сильных ошибок мне хватило.
Благо git всё помнит и можно ревертнуть руками, а косяк был без персистент даты.
Мне нравится этот новый поезд LLM и агентов.
Однако слишком быстро стремящийся поезд.
Предпочитаю быть за рулем, или хотя бы быть в вагоне с кабиной управления, а не ехать в заднем вагоне с закрытыми глазами.
- - -
На скрине часть моей драмы-переписки.
В итоге у меня сейчас 0 MCP серверов, пустые allow list, пару костыль-ограничений средствами операционки и Ask every time.
Печаль.
Устал разгребать дерьмо от агента.
Прям утомился и устал.
Реалии февраля 2026:
- игнорирует allow list в README.md
- игнорирует allow list в настройках Cursor IDE
- игнорирует файл(ы) rules Cursor IDE
- игнорирует allow для MCP серверов
- игнорирует явные запреты в AGENTS.md
- игнорирует рут сандбокс (может легко выходить из песочницы)
- при моих запретах средствами операционной системы начинает писать питон скрипты, чтобы обойти запреты доступа к файловой системе и просить аппрув на выполнение
Каждый раз без зазрения совести использует опасные команды без аппрува, если ему захотелось
-
terraform apply -target -auto-approve-
kubectl delete/apply-
terragrunt run-all -auto-approve-
aws .. modify ..и многое другое. Печаль.
Модели:
- Claude-4.5-sonnet
- 4.6 Opus
Четырёх сильных ошибок мне хватило.
Благо git всё помнит и можно ревертнуть руками, а косяк был без персистент даты.
Мне нравится этот новый поезд LLM и агентов.
Однако слишком быстро стремящийся поезд.
Предпочитаю быть за рулем, или хотя бы быть в вагоне с кабиной управления, а не ехать в заднем вагоне с закрытыми глазами.
- - -
На скрине часть моей драмы-переписки.
В итоге у меня сейчас 0 MCP серверов, пустые allow list, пару костыль-ограничений средствами операционки и Ask every time.
Печаль.
Please open Telegram to view this post
VIEW IN TELEGRAM
😁20❤5👍5🥴2😢1
Ямлоделие
О, дивный мир, на работе я узнал об ограничении GitLab на парсинг YAML файла с пайплайном.
Проскочила ошибка, уронила всё.
Документация привела к
https://docs.gitlab.com/administration/instance_limits/#maximum-size-and-depth-of-cicd-configuration-yaml-files
Интереса ради спуллил их репу https://gitlab.com/gitlab-org/gitlab
Аригато, кстати, что git репозиторий весит всего 2.79 GiB, просто невероятное удобство 😊 .
Затем спросил нейронку сколько памяти/ресурсов экономится при парсинге 2 или 4 мегабайтных файлов и какие причины такого ограничения.
Самое интересное -
То есть 2 MB YAML может жрать больше 2 MB RAM в зависимости от структуры.
Зачем вообще лимит?
Погуглил, почитал документацию, посмотрел код.
- DoS защита
один огромный YAML может положить весь Sidekiq (классная архитектура😀 )
- OOM превенция
память пре-аллоцируется, условно 100 пайплайнов по 100 MB =изда RIP серверу
- производительность
парсинг гигантских YAML тормозит всех (чужие проекты, пайплайны)
- code smell детектор (это я/мы)
если у вас 2+ MB YAML, что-то пошло не так в архитектуре
Ну штош, значит пора оптимизировать содержимое пайплайнов.😭
О, дивный мир, на работе я узнал об ограничении GitLab на парсинг YAML файла с пайплайном.
Проскочила ошибка, уронила всё.
Unable to run pipeline
`gitlab-ci.yml`: The parsed YAML is too big
Документация привела к
https://docs.gitlab.com/administration/instance_limits/#maximum-size-and-depth-of-cicd-configuration-yaml-files
Интереса ради спуллил их репу https://gitlab.com/gitlab-org/gitlab
Затем спросил нейронку сколько памяти/ресурсов экономится при парсинге 2 или 4 мегабайтных файлов и какие причины такого ограничения.
Самое интересное -
max_yaml_size_bytes это не физический размер файла, а память, выделяемая на объекты при парсинге. То есть 2 MB YAML может жрать больше 2 MB RAM в зависимости от структуры.
Зачем вообще лимит?
Погуглил, почитал документацию, посмотрел код.
- DoS защита
один огромный YAML может положить весь Sidekiq (классная архитектура
- OOM превенция
память пре-аллоцируется, условно 100 пайплайнов по 100 MB =
- производительность
парсинг гигантских YAML тормозит всех (чужие проекты, пайплайны)
- code smell детектор (это я/мы)
если у вас 2+ MB YAML, что-то пошло не так в архитектуре
Ну штош, значит пора оптимизировать содержимое пайплайнов.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7👌3❤1
#aws #rds #troubleshooting
Приходят как-то коллеги, говорят - нет прав включить Enhanced Logging на RDS Proxy.
Для дебага очень надо на пару часов.
Ок, смотрю политику, а там
Говорю - всё есть, всё должно работать.
Хоть дропайте всё к херам (stage account).
Возвращаются - нет, всё равно не работает.
Проверяю глазами ещё раз полиси.
Да вроде всё ок.
Говорю сделайте релогин и попробуйте ещё, все права есть.
Снова возвращаются, сделав релогин.
Говорят "включаем, а оно не включается".
Делаю невозмутимое лицо, хотя внутри уже кривлюсь как хурма: описание проблемы уровня "включаем, а не включается, ошибок нет" звучит слишком уныло, чтобы воспринимать его всерьёз.
Прошу объяснить подробнее.
Мне показывают по шагам:
- зашли в консоль
- зашли в RDS
- нашли нужный proxy
- нажали Edit/Modify (я не помню название кнопки)
- поставили галочку "Activate enhanced logging"
- нажали "Modify proxy"
- видят надпись "Modifying proxy ..."
- видят зелёный баннер "Successfully modified proxy ..."
- выходят, заходят снова - галочки нет
Нигде ни одной ошибки.
Всё выглядит как успех.
Но изменение не применяется.
В ивентах пусто.
Повторяю сам под своим admin пермишнсетом - у меня работает, галочка стоит.
В ивентах изменения появились.
Ладно, добавляю себя временно в эту группу и начинаю воспроизводить.
Захожу под их пермишнсетом, повторяю их действия.
Та же история - "Successfully modified", а галочка не стоит.
Думаю что не так.
Выхожу из SSO, захожу снова - галочки нет.
Сбрасываю кеш браузера - галочки нет.
Пробую другой браузер - галочки нет.
Смотрю в developer tools в браузере - никаких ошибок, никаких 403, всё 200.
Смотрю в сам UI консоли - ни единого красного баннера, ни единого намёка на проблему.
Само собой инкогнито мод браузера не помог.
Ивентов нет.
Потратил на это ещё чуть времени, пока до меня наконец не дошло.
Дурачок, - думаю я, - а CloudTrail-то ты проверил?
Иду в CloudTrail, фильтрую по
Нахожу событие. И там:
Вот оно.
AWS при вызове
Для этого нужно право передать (
В политике группы
Про
Добавляем в политику:
Применяем, перелогиниваемся.
Галочка встаёт и остаётся стоять.
Ивенты пишутся.
Итоги:
- "Successfully modified" в AWS консоли не гарантирует, что изменение применилось🥲
-
- Консоль эту ошибку не показывает совсем. Молча глотает. Никакого красного баннера. Никаких ошибок. Никаких ивентов.😎
- CloudTrail - первое место, куда надо смотреть, когда "всё работает, но не работает"
-
- нехер снова кривить свою морду, коллеги всё же солнышки-зайчики и правы, даже если пояснение проблемы тупорылое
Приходят как-то коллеги, говорят - нет прав включить Enhanced Logging на RDS Proxy.
Для дебага очень надо на пару часов.
Ок, смотрю политику, а там
rds:* на Resource = "*".Говорю - всё есть, всё должно работать.
Хоть дропайте всё к херам (stage account).
Возвращаются - нет, всё равно не работает.
Проверяю глазами ещё раз полиси.
Да вроде всё ок.
Говорю сделайте релогин и попробуйте ещё, все права есть.
Снова возвращаются, сделав релогин.
Говорят "включаем, а оно не включается".
Делаю невозмутимое лицо, хотя внутри уже кривлюсь как хурма: описание проблемы уровня "включаем, а не включается, ошибок нет" звучит слишком уныло, чтобы воспринимать его всерьёз.
Прошу объяснить подробнее.
Мне показывают по шагам:
- зашли в консоль
- зашли в RDS
- нашли нужный proxy
- нажали Edit/Modify (я не помню название кнопки)
- поставили галочку "Activate enhanced logging"
- нажали "Modify proxy"
- видят надпись "Modifying proxy ..."
- видят зелёный баннер "Successfully modified proxy ..."
- выходят, заходят снова - галочки нет
Нигде ни одной ошибки.
Всё выглядит как успех.
Но изменение не применяется.
В ивентах пусто.
Повторяю сам под своим admin пермишнсетом - у меня работает, галочка стоит.
В ивентах изменения появились.
Ладно, добавляю себя временно в эту группу и начинаю воспроизводить.
Захожу под их пермишнсетом, повторяю их действия.
Та же история - "Successfully modified", а галочка не стоит.
Думаю что не так.
Выхожу из SSO, захожу снова - галочки нет.
Сбрасываю кеш браузера - галочки нет.
Пробую другой браузер - галочки нет.
Смотрю в developer tools в браузере - никаких ошибок, никаких 403, всё 200.
Смотрю в сам UI консоли - ни единого красного баннера, ни единого намёка на проблему.
Само собой инкогнито мод браузера не помог.
Ивентов нет.
Потратил на это ещё чуть времени, пока до меня наконец не дошло.
Дурачок, - думаю я, - а CloudTrail-то ты проверил?
Иду в CloudTrail, фильтрую по
ModifyDBProxy. Нахожу событие. И там:
"errorCode": "AccessDenied",
"errorMessage": "User: ... is not authorized to perform: iam:PassRole
on resource: arn:aws:iam::ACCOUNT_ID:role/rds-proxy-wanker
because no identity-based policy allows the iam:PassRole action"
Вот оно.
AWS при вызове
ModifyDBProxy передаёт IAM роль прокси в Secrets Manager.Для этого нужно право передать (
PassRole) именно эту роль.rds:* тут ни при чём - это отдельное действие на отдельный ресурс.В политике группы
iam:PassRole был разрешён только для одной конкретной роли.Про
rds-proxy-* никто не подумал.Добавляем в политику:
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::ACCOUNT_ID:role/rds-proxy-*"
}Применяем, перелогиниваемся.
Галочка встаёт и остаётся стоять.
Ивенты пишутся.
Итоги:
- "Successfully modified" в AWS консоли не гарантирует, что изменение применилось
-
AccessDenied может прилетать не на само действие, а на зависимое - в данном случае на iam:PassRole- Консоль эту ошибку не показывает совсем. Молча глотает. Никакого красного баннера. Никаких ошибок. Никаких ивентов.
- CloudTrail - первое место, куда надо смотреть, когда "всё работает, но не работает"
-
rds:* не равно "всё для RDS". Некоторые операции тащат за собой зависимости на другие сервисы- нехер снова кривить свою морду, коллеги всё же солнышки-зайчики и правы, даже если пояснение проблемы тупорылое
Please open Telegram to view this post
VIEW IN TELEGRAM
🤯18❤2😭1
#ai #kubernetes
Удивительно, как быстро развивается мир моделек.
Понадобилось, внезапно, по работе посмотреть большое количество логов.
Да-да, есть под рукой VMui/OpenSearch/Grafana и так далее, но логов много и подов много, веб не поможет в моем дотошном осмотре. Немного специфичная задача была.
Надо было прям в моменте глянуть чо там чо там на нескольких десятках подов, да ещё и с дебаг левелом.
Думаю "блин, ну я вроде сам это относительно недавно делал через node proxy, даже заметку писал, дай повторю".
https://xn--r1a.website/makebreakreflect/205
Нашёл, зашёл, а там уныло - много команд, мне лень.
Не, ну там десяток нод, десятка 4 подов, не буду же я на каждую ноду по SSH/SSM залезать, это тупо.
В общем скормил мой же текст поста нейронке, говорю дай мне универсальный скрипт/команду, чтобы выкачать все файлы по фильтру неймспейса/пода, чтобы локально это исследовать.
Та-да! Пару минут и у меня есть готовый скрипт.
На самом деле их два - выбирайте под задачу.
Мне нужен был первый вариант файлов с диска без ротации.
Вариант 1: через файловую систему ноды
Этот вариант ходит напрямую в /var/log/containers/ через Node Proxy API и выкачивает raw-файлы логов.
Полезен, если нужно получить именно файлы с диска (например, для анализа ротации или когда нужен точный формат файла).
Вариант 2: Через официальный API containerLogs
Этот вариант использует документированный endpoint kubelet API.
Работает с namespace/pod/container напрямую, не требует знания внутренней структуры файловой системы ноды.
аутпут
Ограничения обоих вариантов
Это не стандартный документированный способ получения логов контейнеров (хотя второй вариант использует документированный endpoint kubelet, это всё равно обходной путь через nodes/proxy).
Оба скрипта только для первого (индекс [0]) контейнера в поде, но мне ок по задаче.
Не заработает, если:
- у вашего пользователя нет прав nodes/proxy
- кластер имеет ограничения на node proxy access
- используется нестандартный путь для логов контейнеров (для варианта 1)
- для варианта 1, если у вас не containerd, а cri-o, поправьте sed на нечто типа:
У меня крио нет, так что я хз сработает ли эта регулярка.
Получилась заметка по заметке, но зато у меня есть под рукой оба скрипта - выбираю в зависимости от задачи.
Файловая система, когда нужно покопаться в истории логов, официальный API - когда нужно быстро выкачать актуальное состояние (скорее всего не пригодится никогда).
Забавно обучать/получать ответы от нейронки по своей же заметке. 😅
Удивительно, как быстро развивается мир моделек.
Понадобилось, внезапно, по работе посмотреть большое количество логов.
Да-да, есть под рукой VMui/OpenSearch/Grafana и так далее, но логов много и подов много, веб не поможет в моем дотошном осмотре. Немного специфичная задача была.
Надо было прям в моменте глянуть чо там чо там на нескольких десятках подов, да ещё и с дебаг левелом.
Думаю "блин, ну я вроде сам это относительно недавно делал через node proxy, даже заметку писал, дай повторю".
https://xn--r1a.website/makebreakreflect/205
Нашёл, зашёл, а там уныло - много команд, мне лень.
Не, ну там десяток нод, десятка 4 подов, не буду же я на каждую ноду по SSH/SSM залезать, это тупо.
В общем скормил мой же текст поста нейронке, говорю дай мне универсальный скрипт/команду, чтобы выкачать все файлы по фильтру неймспейса/пода, чтобы локально это исследовать.
Та-да! Пару минут и у меня есть готовый скрипт.
На самом деле их два - выбирайте под задачу.
Мне нужен был первый вариант файлов с диска без ротации.
Вариант 1: через файловую систему ноды
Этот вариант ходит напрямую в /var/log/containers/ через Node Proxy API и выкачивает raw-файлы логов.
Полезен, если нужно получить именно файлы с диска (например, для анализа ротации или когда нужен точный формат файла).
NAMESPACE="kube-system"
POD_PATTERN="kube-proxy"
for POD in $(kubectl get pods -n $NAMESPACE | grep $POD_PATTERN | awk '{print $1}'); do
NODE=$(kubectl get pod $POD -n $NAMESPACE -o jsonpath='{.spec.nodeName}')
CONTAINER_ID=$(kubectl get pod $POD -n $NAMESPACE -o jsonpath='{.status.containerStatuses[0].containerID}' | sed 's|containerd://||')
CONTAINER_NAME=$(kubectl get pod $POD -n $NAMESPACE -o jsonpath='{.spec.containers[0].name}')
LOG_FILE="${POD}_${NAMESPACE}_${CONTAINER_NAME}-${CONTAINER_ID}.log"
echo "⬇️ Downloading: $POD → $NODE"
kubectl get --raw "/api/v1/nodes/${NODE}/proxy/logs/containers/${LOG_FILE}" > "./${POD}.log"
echo "✓ Saved: ./${POD}.log"
done
Вариант 2: Через официальный API containerLogs
Этот вариант использует документированный endpoint kubelet API.
Работает с namespace/pod/container напрямую, не требует знания внутренней структуры файловой системы ноды.
NAMESPACE="kube-system"
POD_PATTERN="kube-proxy"
for POD in $(kubectl get pods -n $NAMESPACE | grep $POD_PATTERN | awk '{print $1}'); do
NODE=$(kubectl get pod $POD -n $NAMESPACE -o jsonpath='{.spec.nodeName}')
CONTAINERS=$(kubectl get pod $POD -n $NAMESPACE -o jsonpath='{range .spec.containers[*]}{.name}{"\n"}{end}')
for CONTAINER in $CONTAINERS; do
OUTPUT_FILE="./${POD}_${CONTAINER}.log"
echo "⬇️ Downloading: $POD/$CONTAINER from $NODE"
kubectl get --raw "/api/v1/nodes/${NODE}/proxy/containerLogs/${NAMESPACE}/${POD}/${CONTAINER}" > "$OUTPUT_FILE"
echo "✓ Saved: $OUTPUT_FILE"
done
done
аутпут
⬇️ Downloading: kube-proxy-brpfm → aks-1
✓ Saved: ./kube-proxy-brpfm.log
⬇️ Downloading: kube-proxy-bt6fp → aks-2
✓ Saved: ./kube-proxy-bt6fp.log
Ограничения обоих вариантов
Это не стандартный документированный способ получения логов контейнеров (хотя второй вариант использует документированный endpoint kubelet, это всё равно обходной путь через nodes/proxy).
Оба скрипта только для первого (индекс [0]) контейнера в поде, но мне ок по задаче.
Не заработает, если:
- у вашего пользователя нет прав nodes/proxy
- кластер имеет ограничения на node proxy access
- используется нестандартный путь для логов контейнеров (для варианта 1)
- для варианта 1, если у вас не containerd, а cri-o, поправьте sed на нечто типа:
sed -E 's/^(containerd:\/\/|cri-o:\/\/)//'
У меня крио нет, так что я хз сработает ли эта регулярка.
Получилась заметка по заметке, но зато у меня есть под рукой оба скрипта - выбираю в зависимости от задачи.
Файловая система, когда нужно покопаться в истории логов, официальный API - когда нужно быстро выкачать актуальное состояние (скорее всего не пригодится никогда).
Забавно обучать/получать ответы от нейронки по своей же заметке. 😅
👍16👎3❤1
#AWScommunity #aws
Какие интересные письма порой приходят.
И это отлично.
Впереди будет много интересного и, надеюсь, полезного.
Наконец-то я смогу весь свой неиссякаемый энтузиазм и энергию потратить на пользу сообщества.
Какие интересные письма порой приходят.
И это отлично.
Впереди будет много интересного и, надеюсь, полезного.
Наконец-то я смогу весь свой неиссякаемый энтузиазм и энергию потратить на пользу сообщества.
10🔥50👏10❤2⚡1
#opensearch #kubernetes #troubleshooting #одинденьизжизни
"Алекс, у нас пропали логи.
Но только на стейдже."
Иду смотреть.
Куб живой, метрики зелёные, поды в норме, а в OpenSearch тишина.
Ни одного алёрта. Ладно.
Пошёл проверять по классике:
- не упал ли агент сбора логов
- не отвалились ли права
- не умер ли endpoint
- не сломали ли что-то свежими коммитами
Первый заход:
Никаких коммитов, которые могли это поломать нет.
Ок, идём в куб.
fluent-bit живой, все реплики
всё раннит
И вот там уже не тишина.
В логах:
- validation_exception
- this action would add [4] total shards
- cluster currently has [1000]/[1000] maximum shards open
Красота.
Значит не "логов нет", а "логгер не может писать".
Дальше мысль идёт так:
куб живой, агенты живые, опенсёрч живой, с pvc всё ок.
но если шардов в потолок, значит retention не чистит старые индексы.🤔
И тут флешбек:
несколько месяцев назад мигрировали с filebeat на fluent-bit.
Индексный префикс поменяли.
Ну там было нечто типа
А retention policy, как это обычно бывает в суровой реальности, осталась смотреть на старое имя индекса☔️ .
Итог:
- новые индексы копились
- старые правила их не трогали
- шардов стало 1000/1000
- OpenSearch начал отвечать 400 на bulk insert
- fluent-bit ретраил, потом сдавался
- в UI ощущение, что "логи пропали только на stage"
То есть виноват не новый деплой, не "вчерашний коммит", не магия.
Просто policy смотрела не туда.
И да, жаль, что эта policy была не в IaC, а когда-то сделана руками в консоли.
Именно поэтому при миграции её и проглядели.
Что проверил и что сработало:
- поправил index pattern в retention/ISM policy на актуальный префикс
- подчистил лишние старые индексы вручную (
- освободились шарды
- проверил повторно логи fluent-bit -> ошибки по maximum shards open ушли
- в OpenSearch новые логи снова пошли
Короткий вывод:
- миграция агента логирования = почти всегда миграция index naming
- если не обновить retention под новый pattern, инцидент это вопрос времени
- всё, что не в IaC, рано или поздно теряется в памяти любой команды
- алерт на долю открытых шардов нужен заранее (80-85%), а не в момент 1000/1000 (а алёрта и не было)
Постмортем одной строкой:
Логи не пропали. Мы сами забили OpenSearch старыми индексами, потому что retention policy жила в прошлом и смотрела на имя эпохи filebeat.
"Алекс, у нас пропали логи.
Но только на стейдже."
Иду смотреть.
Куб живой, метрики зелёные, поды в норме, а в OpenSearch тишина.
Ни одного алёрта. Ладно.
Пошёл проверять по классике:
- не упал ли агент сбора логов
- не отвалились ли права
- не умер ли endpoint
- не сломали ли что-то свежими коммитами
Первый заход:
Никаких коммитов, которые могли это поломать нет.
Ок, идём в куб.
kubectl get ds -n kube-system
fluent-bit живой, все реплики
Readykubectl get pods -n kube-system | grep fluent-bit
всё раннит
kubectl logs -n kube-system daemonset/fluent-bit --since=30m
И вот там уже не тишина.
В логах:
- validation_exception
- this action would add [4] total shards
- cluster currently has [1000]/[1000] maximum shards open
Красота.
Значит не "логов нет", а "логгер не может писать".
Дальше мысль идёт так:
куб живой, агенты живые, опенсёрч живой, с pvc всё ок.
но если шардов в потолок, значит retention не чистит старые индексы.🤔
И тут флешбек:
несколько месяцев назад мигрировали с filebeat на fluent-bit.
Индексный префикс поменяли.
Ну там было нечто типа
eks-filebeat-* на eks-fluentbit-*, не помню уже.А retention policy, как это обычно бывает в суровой реальности, осталась смотреть на старое имя индекса
Итог:
- новые индексы копились
- старые правила их не трогали
- шардов стало 1000/1000
- OpenSearch начал отвечать 400 на bulk insert
- fluent-bit ретраил, потом сдавался
- в UI ощущение, что "логи пропали только на stage"
То есть виноват не новый деплой, не "вчерашний коммит", не магия.
Просто policy смотрела не туда.
И да, жаль, что эта policy была не в IaC, а когда-то сделана руками в консоли.
Именно поэтому при миграции её и проглядели.
Что проверил и что сработало:
- поправил index pattern в retention/ISM policy на актуальный префикс
- подчистил лишние старые индексы вручную (
DELETE /indexname* предыдущих лет/месяцев)- освободились шарды
- проверил повторно логи fluent-bit -> ошибки по maximum shards open ушли
- в OpenSearch новые логи снова пошли
Короткий вывод:
- миграция агента логирования = почти всегда миграция index naming
- если не обновить retention под новый pattern, инцидент это вопрос времени
- всё, что не в IaC, рано или поздно теряется в памяти любой команды
- алерт на долю открытых шардов нужен заранее (80-85%), а не в момент 1000/1000 (а алёрта и не было)
Постмортем одной строкой:
Логи не пропали. Мы сами забили OpenSearch старыми индексами, потому что retention policy жила в прошлом и смотрела на имя эпохи filebeat.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍20❤2
#longread #бытовое #troubleshooting #одинденьизжизни
Ещё один не запланированный лонгрид для вечернего чтения.
Нули.
https://teletype.in/@kruchkov_alexandr/--Mo_yGq58L
Ещё один не запланированный лонгрид для вечернего чтения.
Нули.
https://teletype.in/@kruchkov_alexandr/--Mo_yGq58L
Teletype
Нули
#бытовое #troubleshooting #одинденьизжизни
3🔥17😁2
Впервые запустил apple music на новом железе.
Да-да, я теперь снова владелец MacBook pro, но уже на M5, и скоро буду писать свои позитивные и негативные, никому не нужные , отзывы.
Штош, заманчивая цена после триала, но, пожалуй, воздержусь.
Пожалуй я буду и дальше слушать музыку в браузере или у сторонних приложений за 3,5 гроша в год.
Да-да, я теперь снова владелец MacBook pro, но уже на M5, и скоро буду писать свои позитивные и негативные
Штош, заманчивая цена после триала, но, пожалуй, воздержусь.
Пожалуй я буду и дальше слушать музыку в браузере или у сторонних приложений за 3,5 гроша в год.
🔥11😁9😱3🎉2
#devops #troubleshooting
Из всего невообразимого и бесконечного потока, любимого и одновременно ненавистного всеми, AIAIAIA со всех углов, мне больше всего понравились skills.
Вообще ничего больше не впечатлило за последние года два - как скиллы.
Ну да, ну эйая, ну вайбкодинг. Это даже все бабушки знают и слышали.
Но, господи, как же скиллы охрененно работают в траблшутинге.
Вот пишу я это и понимаю, что скиллы сейчас - топ артефакт в работе девопса и SRE.
Во всяком случае, как я это использую - прям рекомендация 1000000 из 1.
Я готов прыгать от счастья, осознавая сколько времени они мне экономят.
Если вы не знаете как их использовать - попробуйте.
Начните с любого простого примера.
Как использую у себя в двух словах:
- создал несколько SKILLS.md файлов (на самом деле у меня их иерархия, уже 29 скиллов)
- замапил скиллы для Cursor IDE. Можно и в Claude Code, скиллы будут работать и там и там, просто путь разный
- в скиллах и основном ридми файле описал структуру проекта(ов)
- - где ArgoCD (UI, API, git repos)
- - какой нейминг у кластеров кубернетис (AKS, EKS, GCP), нейминг неймспейсов
- - где вообще все гит репозитории и иерархию
- - адрес гитлаба и зеркало, локальные склонированные репозитории
- - что контекст переключается локально через kubectl
- - есть утилиты kubectx, jq и многое другое
- указываю все ключевые адреса репозиториев и ендпойнтов (виктория метрикс, виктория логс, алертменеджер, гитлаб и многое многое другое)
- если где есть сверхтяжелая авторизация, то говорю используй port-forward на внутренние service, там авторизации нет
В общем указал все, что надо для траблшутинга.
Как происходит процесс с моей стороны:
- прилетает алерт
- я копирую текст алерта в агент-ассистент (сейчас у меня курсор)
- жду
- агент смотрит что за кластер, неймспейс, под, контейнер
- лезет в гит, смотрит таймлайн когда кто что релизил, когда коммитили и где менялись какие версии или конфиги
- лезет в нужный кластер кубернетиса, смотрит в нужном неймспейсе, под, логи, дескрайб, ивенты кубера
- при необходимости лезет в логи виктория логс, метрики виктория метрикс (прям через curl)
- если надо, то лезет в арго
- если надо, то лезет в гит репозитории бекенда и фронтенда
- строит гипотезы, проверяет, уточняет
- при сомнениях что-то сам проверяет (ну типа если ему кажется, что проблема нехватки нод - нехватка ip адресов, то иди и проверь метрики сети в AWS и EKS CNI)
- если надо, лезет с рид правами в azure, gcp, aws cli
- выводит мне удобный формат по инциденту и вариант(ы) решений
С вероятностью 90 процентов это точный результат.
Чрезвычайно убого замазанные примеры на скриншотах.
Дальше я уже либо сам чиню, либо передаю другим командам, если дело в них.
Это только кажется, что это сложно, непонятно, магически. Нет.
Только представьте себя на месте агента: знаешь на 99 процентов структуру всей инфры, проектов, процессов.
Ты же как-то сам логически идешь по траблшутингу? Вот так и агент.
Да, это потребовали изначально колоссальной работы, скиллы постоянно обновляю и добавляю новые, но это просто топ находка последних трех, не побоюсь этого слова, лет.
- - -
А вот теперь грустная правда этого позитивного отзыва по скиллам.
Честно говоря это первый артефакт моей работы, который я не хочу отдавать коллегам или боссам.
Скиллы это просто сильвербаллет в 2026 и я буду тянуть до последнего, делясь с командами.
На полном серьезе не хочу шарить на команду🚬
Даже если кто из команды это читает.
Господи, кому я вру, если скажут - отдам уже завтра. ☔️
Я ведь ровно так же понимаю, что написав свои 100500 скиллов, которые уже сейчас, на сотнях алертов и десятке инцидентов на 100 процентов точно дали ответ и удобный аутпут для команд, можно пошарить самостоятельному агенту или условному мидлу с зарплатой три копейки.
И я вылечу на помойку.
Вот такая грустная правда.
Скиллы - это прекрасно.
Скиллы - это главный мой артефакт работы в 2026.
Скиллы - это грустно, они на 10000 процентов подсократят работы нам, инженерам.☔️
Из всего невообразимого и бесконечного потока, любимого и одновременно ненавистного всеми, AIAIAIA со всех углов, мне больше всего понравились skills.
Вообще ничего больше не впечатлило за последние года два - как скиллы.
Ну да, ну эйая, ну вайбкодинг. Это даже все бабушки знают и слышали.
Но, господи, как же скиллы охрененно работают в траблшутинге.
Вот пишу я это и понимаю, что скиллы сейчас - топ артефакт в работе девопса и SRE.
Во всяком случае, как я это использую - прям рекомендация 1000000 из 1.
Я готов прыгать от счастья, осознавая сколько времени они мне экономят.
Если вы не знаете как их использовать - попробуйте.
Начните с любого простого примера.
Как использую у себя в двух словах:
- создал несколько SKILLS.md файлов (на самом деле у меня их иерархия, уже 29 скиллов)
- замапил скиллы для Cursor IDE. Можно и в Claude Code, скиллы будут работать и там и там, просто путь разный
- в скиллах и основном ридми файле описал структуру проекта(ов)
- - где ArgoCD (UI, API, git repos)
- - какой нейминг у кластеров кубернетис (AKS, EKS, GCP), нейминг неймспейсов
- - где вообще все гит репозитории и иерархию
- - адрес гитлаба и зеркало, локальные склонированные репозитории
- - что контекст переключается локально через kubectl
- - есть утилиты kubectx, jq и многое другое
- указываю все ключевые адреса репозиториев и ендпойнтов (виктория метрикс, виктория логс, алертменеджер, гитлаб и многое многое другое)
- если где есть сверхтяжелая авторизация, то говорю используй port-forward на внутренние service, там авторизации нет
В общем указал все, что надо для траблшутинга.
Как происходит процесс с моей стороны:
- прилетает алерт
- я копирую текст алерта в агент-ассистент (сейчас у меня курсор)
- жду
- агент смотрит что за кластер, неймспейс, под, контейнер
- лезет в гит, смотрит таймлайн когда кто что релизил, когда коммитили и где менялись какие версии или конфиги
- лезет в нужный кластер кубернетиса, смотрит в нужном неймспейсе, под, логи, дескрайб, ивенты кубера
- при необходимости лезет в логи виктория логс, метрики виктория метрикс (прям через curl)
- если надо, то лезет в арго
- если надо, то лезет в гит репозитории бекенда и фронтенда
- строит гипотезы, проверяет, уточняет
- при сомнениях что-то сам проверяет (ну типа если ему кажется, что проблема нехватки нод - нехватка ip адресов, то иди и проверь метрики сети в AWS и EKS CNI)
- если надо, лезет с рид правами в azure, gcp, aws cli
- выводит мне удобный формат по инциденту и вариант(ы) решений
С вероятностью 90 процентов это точный результат.
Чрезвычайно убого замазанные примеры на скриншотах.
Дальше я уже либо сам чиню, либо передаю другим командам, если дело в них.
Это только кажется, что это сложно, непонятно, магически. Нет.
Только представьте себя на месте агента: знаешь на 99 процентов структуру всей инфры, проектов, процессов.
Ты же как-то сам логически идешь по траблшутингу? Вот так и агент.
Да, это потребовали изначально колоссальной работы, скиллы постоянно обновляю и добавляю новые, но это просто топ находка последних трех, не побоюсь этого слова, лет.
Алерт - копипаст - ждешь пару минут (автоаппрув или каждую команду аппрув) - ответ и решение(гипотезы).
- - -
А вот теперь грустная правда этого позитивного отзыва по скиллам.
Честно говоря это первый артефакт моей работы, который я не хочу отдавать коллегам или боссам.
Скиллы это просто сильвербаллет в 2026 и я буду тянуть до последнего, делясь с командами.
На полном серьезе не хочу шарить на команду
Даже если кто из команды это читает.
Я ведь ровно так же понимаю, что написав свои 100500 скиллов, которые уже сейчас, на сотнях алертов и десятке инцидентов на 100 процентов точно дали ответ и удобный аутпут для команд, можно пошарить самостоятельному агенту или условному мидлу с зарплатой три копейки.
И я вылечу на помойку.
Вот такая грустная правда.
Скиллы - это прекрасно.
Скиллы - это главный мой артефакт работы в 2026.
Скиллы - это грустно, они на 10000 процентов подсократят работы нам, инженерам.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
10🔥23❤6🤡3🫡1
Please open Telegram to view this post
VIEW IN TELEGRAM
😁23