Make. Build. Break. Reflect.
908 subscribers
115 photos
1 video
119 links
Полезные советы, всратые истории, странные шутки и заметки на полях от @kruchkov_alexandr
Download Telegram
Сейчас на этом проекте всё работает как часы, инстансы совсем не жирные, а у разработчиков даже есть дашборда, куда они бегут, получив алёрты (их несколько разных).
Получив алёрт, ребята самостоятельно анализируют запросы, которые роняют базу и тут же пилят пулл-реквесты с безжалостным выпиливанием таких косяков. Поезд едет дальше.
#AWS #RDS #MySQL
🔥53👍1
Для последнего проекта для AWS EKS использовал AMI на базе bottlerocket.
https://aws.amazon.com/bottlerocket/
Название амишки и версию в голове и коде не держу, смелости и дурости у меня много, так что у меня идёт latest (на самом деле там почти хардкод, просто выглядит пугающе). Сбоев не было никогда из-за последнего в ssm.
С точки зрения кода там просто:
locals {
aws_ami_name = "bottlerocket"
aws_ami_architecture = "x86_64"
aws_ami_type = "${upper(local.aws_ami_name)}_${local.aws_ami_architecture}"
}

data "aws_ssm_parameter" "eks_ami_image_version" {
name = "/aws/service/${local.aws_ami_name}/aws-k8s-${aws_eks_cluster.eks.version}/${local.aws_ami_architecture}/latest/image_version"
}

resource "aws_eks_node_group" "blue-green-group" {
...
ami_type = local.aws_ami_type
release_version = data.aws_ssm_parameter.eks_ami_image_version.value
...

Если пугает такое обновление версий, то можно залепить такое и обновлять раз в месяц/квартал вручную.
  lifecycle {
ignore_changes = [release_version]
...
}


Стратегий у меня несколько:
- event-driven
- load-driven

Ноды готовы очень быстро. При тюнинге в основном секунд 15.
В самых худших кейсах 2 минут 24 секунды. Такое было раз 5 по наблюдениям.
Зависит от типа инстанса, региона и спот ли.

Например типичный сценарий. Есть сервис в десятках подов, кто читает SQS. Они разные и цели у них разные.
- всего 2 ноды, 0 подов с без рабочей нагрузки.
- прилетели тонны мессаджей в AWS SQS, секунд за 5-15 на бурст в 100000+ сообщений
- KEDA через 5 секунд после threshold поднимается пару десятков подов
- кластер-автоскейлер/карпентер (зависит от проекта) поднимает одну или несколько нод в нод группу.
* Кластер автоскейлер мгновенно триггерит, если видит, что не хватает ресурсов и хоть что-то в Pending статусе из POD-ов
- сами ноды на ботлрокете поднимаются секунд за 12-15, каждая из нод. то есть через 15 секунд в основном уже ready.
- поды на новых нодах шедулятся, проходят 2 пробы(startup, readiness), ещё 8-15 секунд.
- приложение готово к работе и разбирает мессаджи в sqs (+20 секунд к таймингам, если на этой SQS long polling)
- после разбора sqs всё тушится к нулям через KEDA, чтобы не платить

Ради теста повторил, лог такой:
ip-10-1-33-89.ec2.internal    NotReady   <none>   0s      v1.30.5-eks-baa6d11
ip-10-1-33-89.ec2.internal NotReady <none> 0s v1.30.5-eks-baa6d11
ip-10-1-33-89.ec2.internal NotReady <none> 0s v1.30.5-eks-baa6d11
ip-10-1-33-89.ec2.internal NotReady <none> 1s v1.30.5-eks-baa6d11
ip-10-1-33-89.ec2.internal NotReady <none> 1s v1.30.5-eks-baa6d11
ip-10-1-33-89.ec2.internal NotReady <none> 1s v1.30.5-eks-baa6d11
ip-10-1-33-89.ec2.internal NotReady <none> 1s v1.30.5-eks-baa6d11
ip-10-1-33-89.ec2.internal NotReady <none> 10s v1.30.5-eks-baa6d11
ip-10-1-33-89.ec2.internal Ready <none> 13s v1.30.5-eks-baa6d11

ip-10-1-34-52.ec2.internal NotReady <none> 0s v1.30.5-eks-baa6d11
ip-10-1-34-52.ec2.internal NotReady <none> 0s v1.30.5-eks-baa6d11
ip-10-1-34-52.ec2.internal NotReady <none> 0s v1.30.5-eks-baa6d11
ip-10-1-34-52.ec2.internal NotReady <none> 0s v1.30.5-eks-baa6d11
ip-10-1-34-52.ec2.internal NotReady <none> 0s v1.30.5-eks-baa6d11
ip-10-1-34-52.ec2.internal NotReady <none> 0s v1.30.5-eks-baa6d11
ip-10-1-34-52.ec2.internal NotReady <none> 0s v1.30.5-eks-baa6d11
ip-10-1-34-52.ec2.internal NotReady <none> 5s v1.30.5-eks-baa6d11
ip-10-1-34-52.ec2.internal NotReady <none> 10s v1.30.5-eks-baa6d11
ip-10-1-34-52.ec2.internal Ready <none> 14s v1.30.5-eks-baa6d11

Как видно ноды очень быстро стартуют. Это самый главный плюс.

Почему bottlerocket:
- крайне быстрый старт нод, основная причина
- чуть более удобная(для меня) кастомизация kubelet, хоть там и не любимый мной TOML
- ну а как же без пункта best-CV-project, надо и новые вещи изучать
#AWS #EKS #bottlerocket
🆒31
Я ещё буду писать про bottlerocket для AWS EKS и, особенно, про его тюнинг, там много любопытного.
👍10
Мне уже двое написали про bottlerocket, так что не теряя времени, пока смелые духом не запустили это в прод, продолжу.

Немного теории:
В Kubernetes существует два типа эвикции (выселения) подов:
Soft Eviction (Мягкое выселение):
- Kubernetes сначала посылает сигнал SIGTERM поду, давая ему время корректно завершить работу
- Pod получает grace period (период отсрочки) для завершения работы
- По умолчанию grace period составляет 30 секунд
Можно настроить через параметр --eviction-soft-grace-period /--eviction-soft

Hard Eviction (Жёсткое выселение):
- Происходит немедленное удаление пода
- Pod получает сигнал SIGKILL
- Используется когда нужно срочно освободить ресурсы
Настраивается через параметр --eviction-hard

Основные триггеры эвикции:
- memory.available: доступная память
- nodefs.available: место на диске ноды
- nodefs.inodesFree: свободные иноды
- imagefs.available: место для образов контейнеров
Пороговые значения можно задавать как в процентах, так и в абсолютных величинах (например, 100Mi для памяти).

Дефолтные значения ванильного k8s можете посмотреть тут:
https://kubernetes.io/docs/concepts/scheduling-eviction/node-pressure-eviction/
Для AL2023 вот такие дефолт значения:
memory.available: "100Mi" 
nodefs.available: "10%"
nodefs.inodesFree: "5%"
imagefs.available: "15%"


Выше была общая теория, ниже практика.

#AWS #EKS #bottlerocket
🤔1
У bottlerocket нет дефолтных значений.
Вы это можете проверить командой на ноде
apiclient -u /settings | jq

Ну или же посмотреть в конфиге:
https://github.com/bottlerocket-os/bottlerocket/blob/1.20.x/packages/kubernetes-1.29/kubelet-kubeconfig
Там пусто.

Что же это значит?
Это значит, что по дефолту если у вас:
- под(ы) с эфемерным хранилищем сожрёт все место на ноде
- под(ы) без лимитов цпу сожрёт всё процессорное время на ноде
- под(ы) без лимитов памяти сожрёт всю память на ноде
- диск заполнится имаджами под(а/ов) и гарбадж коллектор не успеет отработать
Ваша нода умрёт. Системные компоненты перестанут работать, кублету не хватит памяти и нода умрёт.
Нода не защищена от неконтролируемых действий со стороны подов.

Давайте это исправим:
- создадим темплейт/конфиг bottlerocket.tpl в нашем репозитории
- внутри добавим нечто типа такого
[settings.kubernetes]
api-server = "${endpoint}"
cluster-certificate = "${cluster_auth_base64}"
cluster-name = "${cluster_name}"
pod-pids-limit = 1024
image-gc-high-threshold-percent = 85
image-gc-low-threshold-percent = 80
container-log-max-files = 50
container-log-max-size = "100Mi"
[settings.kubernetes.system-reserved]
cpu = "200m"
ephemeral-storage = "1Gi"
memory = "1Gi"
[settings.kubernetes.kube-reserved]
memory = "893Mi"
[settings.kernel]
lockdown = "integrity"
[settings.host-containers.admin]
enabled = ${enable_admin_container}
[settings.host-containers.control]
enabled = ${enable_control_container}
[settings.kubernetes.eviction-hard]
"memory.available" = "1Gi"
"nodefs.available" = "20%"
"nodefs.inodesFree" = "5%"
"imagefs.available" = "15%"
[settings.kubernetes.eviction-soft]
"memory.available" = "10%"
[settings.kubernetes.eviction-soft-grace-period]
"memory.available" = "30s"

- добавить этот конфиг через юзердату
resource "aws_launch_template" "node-launch-template" {
...
user_data = base64encode(templatefile("${path.module}/../../templates/bottlerocket.tpl",
{
"cluster_name" = aws_eks_cluster.eks.name #обязательный параметр!!!
"endpoint" = aws_eks_cluster.eks.endpoint #обязательный параметр!!!
"cluster_auth_base64" = aws_eks_cluster.eks.certificate_authority[0].data #обязательный параметр!!!
"aws_region" = var.AWS_DEFAULT_REGION #обязательный параметр!!!
"enable_admin_container" = false
"enable_control_container" = true
}
))
}


Не буду описывать все параметры, они описаны тут:
https://bottlerocket.dev/en/os/1.20.x/api/settings/kubernetes/#eviction-hard
https://github.com/bottlerocket-os/bottlerocket/blob/develop/README.md#description-of-settings
Цифры можете брать из дефолта(выше писал), в моём примере цифры ровно под те требования, которые есть у меня в моим кластерам и приложениям. Не обязательно использовать все параметры, что есть в моём примере, можете только 4 параметра использовать.

* если вы хотите выдать доступ к вашим нодам, то в моем конфиге надо false поменять на true и дальше по инструкции
https://github.com/bottlerocket-os/bottlerocket?tab=readme-ov-file#control-container

#AWS #EKS #bottlerocket
🤩2
Коллеги запилили фронтенд сервис для инфры. Тупо страничка с ссылками на инфра ресурсы с SSO авторизацией.
На скрине объединил вид нескольких вкладок для демо.
В нем сделаны ссылки на бОльшую часть инфры по окружениям.
Оказалось очень удобно переходить по линкам, чем помнить адреса на память или держать 100500 вкладок.
Для онбординга тоже топ.

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

Просто поделился мелким удобством идеей.
🔥4👍1
* старый репост

"Как я проетерял полдня, но понял что не всегда свежая версия это хорошая версия..."

Switched terragrunt to version "0.72.3" 
time terragrunt plan
Acquiring state lock. This may take a few moments...

No changes. Your infrastructure matches the configuration.

real 0m54.200s
user 0m28.351s
sys 0m2.390s

Switched terragrunt to version "0.54.15"
time terragrunt plan
Acquiring state lock. This may take a few moments...

No changes. Your infrastructure matches the configuration.

real 0m43.498s
user 0m31.284s
sys 0m4.366s

Switched terragrunt to version "0.56.0"
time terragrunt plan
Acquiring state lock. This may take a few moments...

No changes. Your infrastructure matches the configuration.

real 3m29.356s
user 2m27.303s
sys 0m14.885s


Утомили постоянные circular dependency hell на terragrunt, но ничего не поделать, каждые 5-15 версий это говно вылезает, приходится просто подбирать вариант "и багов немного, и время выполнения не больше 50 секунд(по "эталонному" модулю).

#terragrunt
🤔2
"Вернись обратно"
Именно такую фразу я сказал на стриме своему интерну и он, само собой, её ни черта не понял.
Да чего я выделываюсь, я бы и сам её не понял без контекста😅

Переключиться в предыдущую рабочую директорию
cd -
Переключиться на предыдущий контекст Kubernetes
kubectx -
Переключиться на предыдущий namespace в Kubernetes
kubens -
Переключиться на предыдущую ветку в git
git checkout -

Возможно есть что-то ещё c похожим поведением, но я, в основном, использую только это в работе.

#devops #очевидное #вероятное
👍102
Не амазоном едины.

Айти развивается очень быстро.
Каждый день появляется много новых практик, инструментов, подходов и всё новое устаревает уже через пару лет.
Индустрия не успевает сама за собой.
Давайте поговорим о метриках.
У нас есть миллионы метрик.
Для нод, для кубера, для PV, для контейнеров, виртуальных машин и даже баз данных в кубере, для приложений.

Однако мы живём в современном мире гетерогенных сетей и несовершенстве observability.
Те метрики и подходы, которые были в 2011 году, в 2019 году и, особенно, 2025 году, безнадёжно отстали и редко показывают актуальную информацию.

Пример.
для одного только Azure у нас есть целая матрица IOPS дисков, которая зависит от размера и сторадж класса + бёрстабл мод по времени.
https://learn.microsoft.com/en-us/azure/virtual-machines/disks-types#standard-ssd-size
Штатные метрики есть, но они слишком убоги и отсталые:
- сколько осталось айнод
- сколько осталось места на диске(в нашем случае PV)
Как оперативно отслеживать нет ли где в кубернетисе ситуации, когда мы упираемся в предел по IOPS дискам?
PVC у нас несколько СОТЕН и десятки кластеров.
Везде разные классы и размеры.
Вручную прописывать это бред.
Штатно метрик у нас нет.

На помощь нам приходят records.
На стеке victoria metrics(да вообще и в прометиусе тоже на самом деле) мы легко можем создавать такую сущность как vmalert и vmrule.
ВМалёрт просто берёт правила алёртов и отправляет на ручку алёртменеджера.
У vmrule есть две функции:
- создавать rule для алёртов
- создавать новые records

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

Идея тут какая была:
- делаем матчинг между разными видами метрик(у них не матчатся лейблы)
- делаем ещё раз чтобы потом можно было матчить
- создаем матрицу "тип стораджа = максимальный IOPS для него"
- выводим новую метрику "текущий IOPS"
- выводим новую метрику "коэффициент IOPS" где 0 это 0%, а 1 это 100%.
Новую метрику можно использовать как для графиков в графане, так и для алёртов.

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

Например pvc_iops_utilization_percent = 80 говорит о том, что мы для этого кластера/неймспейса/пода упирираемся в 80% от возможностей этого диска, использующего этот тип стораджа класса.
И нам не важно какой там сторадж класс. мы просто знаем, что считаеся всё внутри Victoria metrics и мы просто на выходе получаем готовую метрику с лейблами (cluster namespace po etc) и мы дальше это где угодно используем:
- графана дашборды
- алёрты

Важно понимать, что это пока мой около MVP, в арифметике или логике могут быть мои ошибки, опечатки, неточности и в будущем я буду планировать это анализировать и актуализировать реальным данным.
Я могу по своему не знанию чего-то не учитывать и обязательно это поправлю в будущем.

#azure #metrics #victoriametrics
👏3👍1
---
apiVersion: operator.victoriametrics.com/v1beta1
kind: VMAlert
metadata:
name: ${NAME}
namespace: ${NAMESPACE}
spec:
replicaCount: 1
datasource:
url: ${URL_DATASOURCE}
notifier:
url: ${URL_NOTIFIER}
evaluationInterval: "30s"
selectAllByDefault: true
remoteWrite:
url: http://vminsert-victoria-metrics-cluster.service:8480/insert/0/prometheus/

---
apiVersion: operator.victoriametrics.com/v1beta1
kind: VMRule
metadata:
name: vmrule-storage-iops
namespace: ${NAMESPACE}
spec:
groups:
- name: storage_monitoring
interval: 30s
rules:
- record: storage_class_iops_limits
expr: |
sum by(persistentvolume, storageclass, cluster) (
(kube_persistentvolume_info{storageclass=~"azureblob-fuse-premium|azureblob-nfs-premium"} * 15000) or
(kube_persistentvolume_info{storageclass=~"managed-premium|managed-csi-premium|managed-premium-burstable"} * 20000) or
(kube_persistentvolume_info{storageclass=~"managed|managed-csi|default"} * 6000) or
(kube_persistentvolume_info{storageclass="managed-csi-os-warm-nodes"} * 6000) or
(kube_persistentvolume_info{storageclass=~"azurefile-premium|azurefile-csi-premium|azurefile-nonroot|azurefile-sc-fips|sc-rwm"} * 100000) or
(kube_persistentvolume_info{storageclass=~"azurefile|azurefile-csi|azurefile-standart-nonroot"} * 10000) or
(kube_persistentvolume_info * 500)
)

- record: pod_pvc_info
expr: |
max by(cluster, exported_namespace, pod, persistentvolumeclaim) (
kube_pod_spec_volumes_persistentvolumeclaims_info
)
- record: pvc_storage_info
expr: |
max by(cluster, exported_namespace, persistentvolumeclaim, storageclass) (
kube_persistentvolumeclaim_info
)

- record: pvc_current_iops
expr: |
sum by(cluster, pod, namespace, persistentvolumeclaim, storageclass) (
(
rate(container_fs_reads_total{
device!~"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)",
device=~"/dev/sd[b-z].*"
}[5m]) +
rate(container_fs_writes_total{
device!~"(/dev/)?(mmcblk.p.+|nvme.+|rbd.+|vd.+|xvd.+|dm-.+|md.+|dasd.+)",
device=~"/dev/sd[b-z].*"
}[5m])
)
)
* on(cluster, pod) group_left(persistentvolumeclaim, exported_namespace)
pod_pvc_info
* on(cluster, exported_namespace, persistentvolumeclaim) group_left(storageclass)
pvc_storage_info

- record: pvc_iops_utilization_percent
expr: |
sum by(cluster, namespace, pod, persistentvolumeclaim, storageclass) (pvc_current_iops)
* 100
/ on(cluster, storageclass) group_left()
max by(cluster, storageclass) (storage_class_iops_limits)
---
- alert: HighIOPSUtilization
expr: round(pvc_iops_utilization_percent) > 85
for: 40m
labels:
severity: warning
annotations:
summary: "IOPS is `{{ $value }}%` on `{{ $labels.cluster }}`/`{{ $labels.namespace }}`/`{{ $labels.pod }}`."
1
Ну вот и график в графане.
Максимум IOPS(из документации Ажура) и текущая нагрузка.

#azure #metrics #victoriametrics
😁2👍1
Утро началось с осознания, что:
- кросс-кластер алертинг нужен иногда (и он сработал)
- частоту верещания этого, пусть и важнейшего алерта, можно уменьшить
- киверно это пздц ублюдочная хйня, уронил весь кластер. Точнее он и Харбор.

Про киверно отдельно напишу всратую стори, это просто глупо как он работает. 🙈

* Кросс-кластер алертинг это когда есть система мониторинга и алертинга и есть где-то далеко в стороне система наблюдающая за ней. И обе друг за другом. Чтобы если вообще всё упало, то было кому сообщать, что всё упало. Про него тоже отдельно напишу пост, как раз материал для шеринга 😅
🔥8
#victoriametrics

Итак, кросс-алёртинг.
Название мною выдуманное, я не знаю как такие вещи должны называться, может давно уже другое официальное слово есть.

Допустим у вас есть система мониторинга, трейсинга и алёртинга.
Это может быть kube-prometheus-stack или victoria-metrics-k8s-stack или любой другой стек или оператор.
Она работает в кластере или нескольких.
Оповещает по алёртам ваш Slack/PagerDuty/telegram etc.
Всё работает и всё отлично.
А что делать, если POD с Alertmanager упал? Что делать, если у вас накрылся весь кластер?
Вы ведь даже не узнаете об этом - некому сообщить о том, что всё упало.

Есть готовые реализации, но нам не подошло большинство из-за цены, способа интеграции или недостаточного для меня функционала. А что это значит? Прааааавильно, пишем свой велосипед😅.

У Alertmanager есть механизм, который называется Watchdog.
Этот алёрт горит ВСЕГДА.
То есть "если у алёртменеджера всё хорошо" - значит горит алерт.
Если "если вочдог не горит" - алертменеджер умер/конфиг с ошибкой/недоступен и так далее.
Логика наоборот.

В зависимости от вашей системы обсервабилити и способа установки он может быть включен по умолчанию, но если его нет, то вы его легко можете добавить(пример для VM стека):
apiVersion: operator.victoriametrics.com/v1beta1
kind: VMRule
...
spec:
groups:
...
- name: "alertmanager"
rules:
- alert: Watchdog
expr: vector(1)
for: 5m
labels:
severity: info
annotations:
summary: "This is an Watchdog alert that is always firing."
...

Итак, алёрт у нас есть.
Дальше что?

А дальше идея такая:
- мы пишем новый микросервис, пусть будет на Python, все переменные в хардкоде для удобства этого демо
https://github.com/kruchkov-alexandr/cross-alerting/blob/main/main.py
- пишем докерфайл для запуска в кубах (я вообще не заморачивался с оптимизацией тут)
https://github.com/kruchkov-alexandr/cross-alerting/blob/main/Dockerfile
- деплоим его в ДРУГОЙ/ДРУГИЕ кластера кубернетиса, можно хоть хелм чарт на него написать, если есть желание, у меня сделано через ArgoCD - путь к имаджу и переменные и всё
- в конфиг алертменеджера добавляем новый route и receiver чтобы watchdog alert отправлялся в новый микросервис
route:
...
routes:
##############################################################
# Watchdog #
##############################################################
# DO NOT REMOVE THIS ROUTE!!!
# DO NOT ADD ROUTES ABOVE!!!
- receiver: 'webhook-receiver'
group_wait: 10s
group_interval: 30s
repeat_interval: 30s
matchers:
- alertname = "Watchdog"
continue: true
...
receivers:
...
- name: 'webhook-receiver'
webhook_configs:
- url: 'https://cross-alerting.domain.io/api/alert'
send_resolved: true
....
3
Собственно и всё:
- алертменеджер каждые 5 минут отправляет вебхуки на URL cross-alerting
- скрипт запускает веб-сервер, который слушает POST-запросы на /api/alert.
- каждый раз, когда приходит запрос на этот endpoint, обновляется время последнего вебхука.
- в фоновом режиме работает тред, который проверяет, как давно приходил последний вебхук.
- если вебхук не приходил дольше, чем WEBHOOK_CHECK_INTERVAL(2 минуты), система считается "упавшей", и отправляется уведомление в Slack.
- если система была "упавшей", но вебхук пришел, отправляется уведомление о восстановлении.
- если pod был перезапущен в течение последних 30 секунд, отправляется уведомление о восстановлении.


* Давайте ток не душнить про овнокод на питоне и докерфайл, задачи по оптимизации не стояло.
Надо было просто написать так, чтобы перекрёстный мониторинг и алёртинг работал, он работает, а значит задача решена. Для себя можете писать Свой Идеальный Божественный Код.
👍3
Да, обсервабилити сейчас выглядит достаточно запутанно, мне явно требуется пересмотреть свой подходы к рисованию диаграмм😅
👍2👏1
Ночь, бессонница.
Горение.

Читаю комментарии к разным статьям про развитие UI/UX, про размеры приложений на телефон в 1300 мегабайт для чтения pdf файлов без редактирования.
Про максимально ставший абсолютным рекордсменом говна - ноушн. Я словно Нео в драке с мистером Андерсоном отбиваюсь каждый день от новых всплывающих окон с НУ ВОТ ТЕПЕРЬ ТОЧНО НОВАЯ ПОЛЕЗНАЯ ФИЧА ХОТЬ ТЫ И НЕ ПРОСИЛ НА ВОТ СОРТИРУЙ СВОИ СЧЕТА ЗА АПРЕЛЬ ПО НОВОМУ AI В ЗАМЕТКАХ.
Не менее всратый слак - джигурдаллион фичей ежедневно, половина из них умерло до их релиза и, особенно, использования реальными людьми.
Везде AI. Везде pop-up, бесячая джира и конфлюенс каждый день(!) высирает новые окошки с новой абсолютно бесполезной херней.
Мы уже даже привыкли их закрывать, многим реально понасрать что там у вас вышло.
Ноушн, банк клиент, стриминг плеер. Открыл Яндекс музыку - автоматически оформил ипотеку в Перми.
Люди, разработчики, аналитики, корпорации - все они/мы перестали делать ПРОСТО ПРИЛОЖЕНИЕ.
То, ради чего к ним пришли и пользуются/платят.
Не добавляя сторизы в калькулятор, не добавляя предложение о кредите в фотоальбом.
Все наши телефоны от 50 баксов с Али до топов за 3000, умеют на Марс летать и рассчитывать орбиту геостационарных спутников за 0.00001наносекунд, но ослиное приложение по просто вызову такси тормозит так, что я уже пешком дошёл, потому что у нас ЭКОСИСТЕМА СУПЕРАПП.
😂
Я реально прекратил пользоваться около 25 приложениями, потому что вместо простого и обещанного функционала оно превратилось в ишачий кал с AI и сторизами от курьеров-случайных-контактов из Узбекистана.
Кое-кто даже перестал выполнять свою изначальную функцию, что печалит.

Бог с ним, с размером, благо у нас больше не дискетки, что произошло с главным - функционалом?

Что не так с индустрией? Почему мы начали делать говно?
Не соглашусь, что мы всегда делали говно, ещё есть приложения, которые всё ещё просто делают свою работу.
Кто виноват? Зумеры айтишники? AI проклятый век? Эффективные менеджеры?
Старые пердуны сишники?
Вкатуны(как я)? Или всё испортили статьи про аджайл и влажные маня фантазии инвесторов?

Кому разбить лицо?


* Возгорание произошло из-за обновления Spotify, он мне на ПК вертикальные сторизы-тизеры-песен-без-способности-прослушать-весь-трек выдал😂. На ПК🤭.
Зачем это дерьмо вообще релизили?
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8💯4🤣3
Самая удивительная особенность, которая обнаружилась после перехода RDS(8.0.mysql_aurora.3.08.0) на Gravitron v2, это способность на высокий утилизации CPU не снижать эффективность/производительность.
А я не знаю как это точнее назвать, пусть будет слово эффективность.
Давайте к примерам.

Когда был db.r5.2xlarge, при CPU usage 85-100% длительностью больше 10-15 минут начиналась небольшая, но деградация работы с базой данных.
Из замеченного мной:
- небольшое отставание лага у read реплик
- timeout со стороны приложения к бд(для новых коннекшнов)
- slow query (честно говоря они появлялись примерно после 22-24 минут непрерывного CPU usage 85-100%)
- очереди запросов (самое больное по бизнес аппликейшн, почти везде real-time)
- binary log писался с небольшим лагом(используется для Debezium+Kafka для реалтайма)

Когда переключили на db.r6g.2xlarge при ровно таких же жёстких нагрузках:
- регулярные миграции
- по расписанию какие-то профилактические работы
- онбординг новых очень крупных клиентов (там прям DP-MySQL series в этот момент)
- запуск snowflake
- запуск retool,
база свободно выдерживает 85-100% в течении длительного времени 15-30 минут без снижения эффективности.
Никаких диких таймаутов, никаких слоулогов, даже репликация проходит без лагов.

Какая-то удивительная магия для меня.
Заставляет задуматься и даже скорректировать алёрты на такое поведение.
И да, я не знаю причина тому смена c5->r6 или же невероятная магия ARM у Gravitron.

* К сожалению графики Grafana, графики и логи у NewRelic в качестве доказательств не могу предоставить:
там если замазать, то будет совсем непонятно, а без замазки полный NDA, а потому без картиночек.
Trust me, Neo.


#AWS #CostOptimization
👍4
Реальность 2025:
- удалил 3 игры из Стима, которые занимали много места на двух-терабайтном диске, чтобы установить модели типа https://ollama.com/library/deepseek-r1, потому как все паблик AI сервисы(чатгпт,дипсик,копайлот,клаудия) достаточно серьёзно часто тормозят/висят(даже с PRO), а мне работать надо и нейронки помогают писать юнит тесты.🚬
Пока сижу локально гоняю модельки, терпимо.

* у вас может и не получиться скачать, сам качал долго, постоянно EOF😭
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3👍1
#devops

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

~/.bashrc (или любой другой шелл)
function kvs() {
kubectl get secret "$1" -o json | jq '.data | map_values(@base64d)'
}


Пример использования:
> kvs grafana-monitoring

{
"admin-password": "pupupu",
"admin-user": "pupupu@pupupu.ded",
"ldap-toml": ""
}


Особенности:
- для тех, кто не любит тяжёлые плагины с kubectl или k9s
- эта функция-пример не учитывает неймспейс, но я всегда юзаю kubens и свичусь всегда, так что для меня ок

*kvs - kube view secret
👍10
#пятница

Не, ну а какой ещё может быть мой ответ при росте бизнеса и утроению количества клиентов. Вечно накидывать ресурсы не выйдет.
😁7🤣5💯3