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

Часть 1 из 2.

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

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

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

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

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

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

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

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


│╲
│ ○
○ ░
░ gitleaks

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

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

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

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

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

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

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

Часть 2 из 2.

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

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


│╲
│ ○
○ ░
░ gitleaks

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

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

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

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

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


│╲
│ ○
○ ░
░ gitleaks

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

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

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

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

Валидации, проверки, линтеры.
Как много мы о них говорим, но и как это иногда важно.

У меня есть helm chart.
После изменения любых параметров или темплейтов я его проверяю.
- unit tests (ооооооочень редко и не всем нужно)
helm unittest ./helm-chart

- linter
helm lint helm-chart

Дальше публикация и куда-то релиз.
helm package helm-chart


Чарт готов, чарт проверен в пайплайне и пре-коммит хуками.

А что с values файлами на стороне приложений?
У меня же есть прекрасные коллеги с ровными руками.
Они могут в values файлах своих репозиториев при использовании нашего общего чарта допустить ошибку.
Ну так бывает, все ошибаются.
Могут написать "true" вместо true, могут не там сделать indent или вообще половину indent(1/3).
Которые при любых проблемах обвиняют девопсов 😮🫵😮.
Как быть тут?

На помощь мне приходит schema validation.
То есть на базе template мы генерируем schema.yaml файл, по которому будет идти сравнение values.yaml файлов у коллег.

Для начала я потренируюсь на кошках и возьму классный чарт отличного продукта
https://github.com/cloudnative-pg/charts
Клонирую его себе
git clone git@github.com:cloudnative-pg/charts.git


Затем мне надо написать схему.
Буду ли я просить нейронки?
👎Да пошли они в хер, с ними голова вообще перестала работать.🐒
Буду ли я сам писать схему?
Да щас 🤣.

Иду в awesome helm репу, ищу есть ли чего у нас там для скима валидейшн.
https://github.com/cdwv/awesome-helm
Нахожу поиском там генератор (второй депрекейтед)
https://github.com/dadav/helm-schema
Читаю - всё ок, отлично подходит под мою задачу.
Качаю, распаковываю и так далее
wget https://github.com/dadav/helm-schema/releases/download/0.18.1/helm-schema_0.18.1_Linux_x86_64.tar.gz
tar -xvf helm-schema_0.18.1_Linux_x86_64.tar.gz
chmod +x helm-schema
sudo cp helm-schema /usr/local/bin/


Теперь иду в свой склонированный cnpg репозиторий
cd ~/GIT/INTERNET/cnpg/  #(у вас путь другой будет само собой)

и просто запускаю бинарь
helm-schema

Результатом будет json файл(ы) в каждом чарте.
Один из файлов выглядит так
https://gist.github.com/kruchkov-alexandr/dc4cf3e4ac9af5719fb435d42e1873e6

Чарт есть, генератор схема валидейшн есть, схема есть.
Осталось научиться проверять.

У меня есть три основных варианта использования схемы:
- подсунуть комментарии-аннотации в values.yaml
- в VSCode мышкой клацнуть на схему и сам vscode будет подсвечивать ошибки
- команда в терминале в CICD

Мне больше нравится последний вариант автоматизации.
Немного душноты:
- команда helm template генерирует(рендерит) YAML манифесты.
- если есть файл JSON со схемой, то helm template проверяет ещё и схему!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13
#helm #devops

Поехали проверять.
helm template alexk-test charts/cluster/

Всё ок, нет проблем, куча манифестов срендерилось.
Теперь иду в файл charts/cluster/values.yaml
и меняю
  endpointCA:
create: false

на
  endpointCA:
create: "false"

Снова запускаю и получаю ошибку
helm template alexk-test charts/cluster/
Error: values don't meet the specifications of the schema(s) in the following chart(s):
cluster:
- recovery.endpointCA.create: Invalid type. Expected: boolean, given: string


Отлично, у меня есть
- мой чарт/чарты
- автоматическая генерация схемы путем pre-commit и/или CICD команды схемы для чарта до релиза чарта
То есть когда мы что-либо меняем в своём чарте, то у нас и автоматическая проверка идёт и автоматически генерируется и в гите обновляется схема.

Дальше я свой общий pipeline для приложений коллег добавляю шаг helm template и он до релиза проверяет values.yaml файлы пользователей и коллег.

Так, а что у нас с GitOps ArgoCD подходом?
Ведь мы там не используем helm в чистом виде и нет понятия релиза.
Читаю документацию
https://argo-cd.readthedocs.io/en/stable/user-guide/helm/
Ура, под капотом ArgoCD использует как раз helm template, а значит мы при syncing увидим не просто ошибку, а ошибку в каком конкретно месте у нас ошибка.

Итог:
- в самом чарте появилась схема, к тому же она автоматически обновляется при каждом изменении чарта
- при использовании helm для релизов в моём pipeline я добавляю helm template для проверки корректности values.yaml файлов разработчиков
- в случае работы с ArgoCD у меня так же проверяется схема, снижая количество человеческих ошибок
- и со стороны чарта и со стороны репозиториев разработчиков есть pre-commit hooks (если на них забивают🐒)

Поздравляю - мы снова добавили какую-то очередную хероту автоматизацию и валидацию 🤣
Please open Telegram to view this post
VIEW IN TELEGRAM
9🔥61
#aws #devops #EKS #IRSA

На одном проекте пришла задача избавиться от IAM-кредов в подах и перейти на роли.

Есть три давно созданных EKS-кластера. Я написал Terraform-код: полиси, роль, policy attachment, service account, OIDC и всё остальное. Поправил Helm-чарт, добавив service account. Прокатил изменения по всем кластерам - всё ок.

На DEV я убрал IAM-креды из секретов, чтобы CDK перешёл на роль - всё ок. Сто раз всё проверил: секреты почистил, аппликейшены передеплоил, в AWS-консоли видно, что роль используется, IAM-креды - нет. Удалил IAM для DEV - всё работает. Повторил на STAGE - тоже всё ок.

И тут прод. Удалил креды - и всё рухнуло к чертям. Поды начали использовать роль ноды 🤡, у которой, естественно, нет доступа ко всем ресурсам AWS. Вернул креды, откатил, прод поднял, получил по щщам и начал дебажить.

Сто раз перепроверил Terraform-код - всё идентично. Проверил OIDC, IRSA, роли - всё совпадает, проблем нет. Но почему-то на проде поды не берут нужную роль.

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

Проверил mutatingwebhookconfigurations:
dev
kubectl get mutatingwebhookconfigurations | grep pod-identity-webhook
pod-identity-webhook

stage
kubectl get mutatingwebhookconfigurations | grep pod-identity-webhook
pod-identity-webhook

prod
kubectl get mutatingwebhookconfigurations | grep pod-identity-webhook
hui

Кто-то (или что-то) когда-то как-то удалил pod-identity-webhook на проде. Как так вышло - история умалчивает, это останется тайной. Жаль только часов дебага, когда я матчил код, роли, OIDC и IRSA, не подозревая, что мутейшн хука просто нет. 🚶‍♀
Что делает этот вебхук? (текст украден из чата кубера):
- Добавляет переменные среды:
AWS_WEB_IDENTITY_TOKEN_FILE=/var/run/secrets/eks.amazonaws.com/serviceaccount
AWS_ROLE_ARN (значение берётся из аннотации к SA)

Добавляет в волумы:
- name: aws-iam-token
projected:
defaultMode: 420
sources:
- serviceAccountToken:
audience: sts.amazonaws.com
expirationSeconds: 86400
path: token
...
- mountPath: /var/run/secrets/eks.amazonaws.com/serviceaccount
name: aws-iam-token
readOnly: true

И всё. Дальше куб сам выписывает SA-токен с aud: sts.amazonaws.com.

Принял быстрый фикс:
Установил cert-manager (если его не было):
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.18.2/cert-manager.yaml

Склонировал и развернул:
git clone https://github.com/aws/amazon-eks-pod-identity-webhook
cd amazon-eks-pod-identity-webhook
make cluster-up IMAGE=amazon/amazon-eks-pod-identity-webhook:latest

Проверил логи:
kubectl logs -n default -l app=pod-identity-webhook

Запустил тест:
kubectl run irsa-test --image=amazon/aws-cli -n production --overrides='{"spec":{"serviceAccountName":"new-sa"}}' --command -- sh -c "aws sts get-caller-identity && sleep 3600"

Получил:
{
"UserId": "54252523:botocore-session-2345452354",
"Account": "2345452345",
"Arn": "arn:aws:sts::234534524:assumed-role/expected-new-role/botocore-session-345235"
}

Ура, теперь поды используют новую роль. Убил тестовый под. Удалил IAM-креды, накатил снова - всё ок.
Задача решена.🎉

.....
Прошло пару дней.
.....

Сижу, значит, пишу этот текст-заметку, пока не забыл, и задумался: неужели такое возможно в 2025? Зачем? Зачем, мистер Андерсон, вообще руками что-то ставить в кластер, kubectl apply -f??

Читаю за утренним кофе документацию, пока жена не видит:
- https://docs.aws.amazon.com/eks/latest/userguide/eks-add-ons.html
- https://docs.aws.amazon.com/eks/latest/userguide/pod-id-agent-setup.html
Дошёл до:
- https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_pod_identity_association
.
..
...
Прочитал, промолчал, набычился, посмотрел на пол, закатил глаза, надел kubectl apply -f клоунский нос 🤡 и отправил пост в телеграм.
Please open Telegram to view this post
VIEW IN TELEGRAM
😁16👍2😨2
#github #devops

Заметка капитана очевидности.

Когда мне надо что-то найти для задачи/работы, но "я пока не знаю что", то я начинаю запрос с awesome.
Иногда ищу в Google, иногда сразу на GitHub.
99.9% результата поиска в Google всё равно ведёт в GitHub.

Это может быть что угодно:
- алёрты alertmanager
https://samber.github.io/awesome-prometheus-alerts/
- хуки гита
https://github.com/compscilauren/awesome-git-hooks#readme
- cheat sheets гита
https://github.com/arslanbilal/git-cheat-sheet#readme
- утилиты Kubernetes
https://github.com/vilaca/awesome-k8s-tools
https://github.com/ksoclabs/awesome-kubernetes-security
https://github.com/magnologan/awesome-k8s-security
https://github.com/calvin-puram/awesome-kubernetes-operator-resources
- системные утилиты
https://github.com/luong-komorebi/Awesome-Linux-Software
https://github.com/cuongndc9/awesome-linux-apps
- чего-то для баша
https://github.com/awesome-lists/awesome-bash
- фреймворки go
https://github.com/avelino/awesome-go
- правила для Cursor IDE
https://github.com/PatrickJS/awesome-cursorrules
- либы питона
https://github.com/uhub/awesome-python
- платные и бесплатные статуспейджи, селдфхостед и менеджед
https://github.com/ivbeg/awesome-status-pages
- MSP
https://github.com/guardzcom/awesome-msp
- для Helm
https://github.com/cdwv/awesome-helm
- MCP сервера
https://github.com/punkpeye/awesome-mcp-servers

Список почти бесконечный.
Утилиты, книги, плагины, tips&tricks, темплейты.
🔥193
#aws #devops #longread #longstory #msk #apigateway #cloudfront

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

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

https://telegra.ph/My-maiden-magnum-opus-08-01
🔥18👍53
#devops #sql #index

Индексы.

Сегодня слишком жарко и погулять не удалось.
А значит надо накидаться алкоголем и играть в стимдеку сделать что-то полезное для разминки ума.
Открыл в браузере папку с закладками "Почитать на потом" (думаю, она есть у каждого) и выбрал случайную ссылку:
https://use-the-index-luke.com

Думал, почитаю минут 10-15, но зачитался надолго с большим интересом.
По ощущениям, закрыл целый пласт знаний: от понимания, что такое индексы и как они устроены, до более сложных тем, вроде оптимизации запросов.
На сайте масса информации, я читал выборочно то, что было полезно для работы.
Особенно понравились разделы про структуру индексов и их использование в "WHERE".

Рекомендация всем, кто:
- не знает, что такое индексы
- слышал, что "если БД тормозит - смотри индексы", но не понимает, как это работает (как я 😁)
- хочет укрепить знания или закрыть пробелы

Ресурс подходит всем инженерам, независимо от роли - администратора баз данных, DevOps или разработчика.
Текст доступен даже новичкам, можно читать на английском или через автопереводчик браузера.
Разделов много, можно изучать всё подряд или выборочно, как я.

Обязательно к прочтению, если хочется разобраться в индексах.
Рекомендация 💯.

* предполагаю, что впереди меня ждет не одна всратая история, связанная с обновлёнными знаниями по индексам и анализу "что у меня на работе у коллег" 😀
Please open Telegram to view this post
VIEW IN TELEGRAM
👍224👌1
#azure #finops #devops

Меня вдохновили одной историей-задачей от коллеги, но расскажу всё от своего имени, а что вы мне сделаете, заметки то мои 🤣
На мой личный взгляд это потрясающая работа сильного, профессионального и изобретательного инженера.

Была подзадача "перетащить часть проекта с Azure stack на Bare metal".
С платформой и стеком выбор был уже почти сделан, надо было лишь развернуть инфру и перетащить данные.
Инфру развернули за 0.0001мс - мы же все гитопсы теперь.
С данными вышла засада - их было 330+ терабайт. И это лишь в одном блобе. Блобов много.
Мы были не готовы к таким цифрам в bare metal и это пахло проблемами.
И капасити и скорость передачи данных в бар метал - это сколько недель ждать?
Решили вообще узнать - а все ли данные нужны?
Зашли к девелоперам по datawarehouse стеку, они сказали нечто типа "ну мы, конечно же, компания, специализирующая на данных, данных у нас ОЧЕНЬ много, но цифра не похожа на настоящую".
Это отличный пойнт, а значит время для анализа.
Базово ажур ничего не даёт по аналитике, либо за деньги, а потому надо всё включать.
Первым делом включили Inventory - специальный инструмент, позволяющий получать отчёт о всех данных внутри блоба. Запустили, сутки ждали, он сформировался в CSV файле, вроде около 150 мегабайт.

Ок, у нас есть миллионы строчек, но сами же мы не будем глазами считать.
Создаём локально базу данных PostgreSQL.
Затем создаём табличку типа (тут есть ошибки, но это не влияет на саму задачу)
https://gist.github.com/kruchkov-alexandr/9f1210db954c92b059113835e950562e
Запускаем DBeaver и импортируем CSV файл в это локальную базу данных PostgreSQL.

Данные по объектам в блобе, а значит пора мучать любимый AI ассистент SQL запросами, нечто типа
https://gist.github.com/kruchkov-alexandr/73096e1a8a78274944dcb3c02c45f090
Оба запроса собирают статистику по контейнерам blob, считая количество файлов и их суммарный размер в GiB, также выводят общий итог по всем контейнерам.

Возвращаемся к девелоперам, показываем статистику, анализ, все в шоке, срочный колл, разбор полётов.
Не буду опускаться в суть бизнес процессов, почему и где была логическая проблема, но в общем у нас был сбой
и данные дублировались. Трижды всё проверили, расписали план и двинулись дальше:
- удалили часть данных
- включили лайфсайкл полиси на 1 день
- выключили safe delete или как это называется
- что-то ещё, но я уже не помню

В общем на момент истории блоб весит 44 терабайта, удалено больше 280 терабайт.

Какие же потери мы понесли с момента бага с дублированием?
- чтение/перечтение данных каждый день
- операции
- хранение
Итого $3500+ в месяц. За один только блоб.
Просто три с половиной шутки за мусорную дату каждый месяц....

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

Да, компания специализируется на дате, её очень много, и само собой никто уже с огромными объемами не мониторил банальный сбой и дублирование / версионирование / сейфделиты / редубликацию трафика на ингрессе и так далее. Когда данных петабайты, особо не следишь где чего и сколько. Всем кажется, что это нормально.

Итоги:
- коллега я, крутой и мощщный синёр помидор, показал всем, как делать аналитику сотен миллионов объектов в блобе
- узнали о величайшем(нет) провале по мониторингу биллинга и размера даты
- на момент стори снизили косты на $3500+ в месяц 😭 Точная сумма будет известно потом, когда завершаться все работы по всем стораджам, а их не мало.
- отчасти сняли блокер по переносу даты в барметал (нет, но это другая история)
Please open Telegram to view this post
VIEW IN TELEGRAM
👍20🔥51😁1
#azure #devops #entra #powershell

Мелкая компания из трёх суетливых инженеров при удаче вырастает до большой организации в 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
#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).
Мне же надо их на что-то менять, надо копнуть глубже.
👍9
#aws #costoptimization #devops

Затем я включил логирование (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😢21👍1
#kubernetes #devops

Последнюю неделю на работе игрался с KRO, AWS ACK и CrossPlane.
- https://github.com/crossplane/crossplane
- https://github.com/aws-controllers-k8s/community
- https://github.com/kubernetes-sigs/kro

Ну что я могу сказать.
Мне одновременно и очень понравилось - инструменты хороши.
Это потрясающие инструменты, выводящие инфраструктурную часть и операционную на совершенно иной уровень.
Не плохой, не хороший, он новый. Не буду приводить аналогий, это просто иной уровень для меня.
Да охрененный, если честно, буду честен.
И одновременно не понравилось - самостоятельно, в одиночку, в одно лицо, без помощи AI ассистентов я разобрался бы в лучшем случае через недели 3-4. Возможно бы и через месяц.

Сложность в том, что эти инструменты создают десятки уровней абстракций - от CRD в Kubernetes до специфических API провайдеров (AWS, GCP). Чтобы отладить ошибку, нужно пройти путь от kubectl describe до логов ACK controller, а потом до настоящего события в облаке. Рисуешь сперва диаграммы, зависимости, порядки деплоя - это колоссальная работа.

Вообще прикольно, конечно, один манифест и фигак, у тебя целые регионы, кластера, роли, рут таблицы, натгейтвеи и миллион сущностей в кубернетисах. Миллионы объектов и сущностей на сотнях уровней абстракций.
Круто. Мне понравилось.

Про KRO/ACK/CrossPlane я ещё напишу не одну глубокую техническую заметку/отзыв, а пока лишь общий отзыв - они хороши.
👍151👏1
Приветствую всех.

Поскольку все читатели здесь ради контента, а не моей биографии, сразу перейду к сути.
Этот блог - мои заметки на полях.
Почти не делаю репосты, пишу для души и лишь когда на это есть время/желание.
Обычно это 2-4 поста в неделю.

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

Интересные, на мой взгляд, сообщения я публикую с тегами:
- пример основных тем канала:
#aws #azure  #kubernetes  #troubleshooting  #costoptimization  #longread  #devops
- пример второстепенных категорий:
#terragrunt  #victoriametrics  #git #docker  #одинденьизжизни  #helm
- для того, чтобы на работе не поехать кукухой, у меня есть:
#пятница  #всратость  #байки

Сообщения без тегов это просто шутка-минутка или мысль, которая была актуальна лишь на момент написания.

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

Буду рад, если мои заметки помогут кому-то узнать что-то новое, избежать повтора чужих ошибок или просто улыбнуться.
На крайний случай, самоутвердиться за счёт моих факапов или незнания 🐒
Всем привет и желаю приятного чтения.
Please open Telegram to view this post
VIEW IN TELEGRAM
10👍31👨‍💻1