DevOps Brain 🧠
1.21K subscribers
127 photos
16 videos
119 links
Пишу про kubernetes, terraform, linux, сети, автоматизации и полезные тулзы. Без спама и щитпостинга.

Хотите пообщаться? @devopsbrain_chat

Автор: @itcaat
Download Telegram
Котлеги, привет. Наткнулся вчера на решение для личного управления знаниями https://github.com/siyuan-note/siyuan. Думаю вот круто - 28000 звезд, написан на go и typescript, есть просто мощнейший редактор, есть расширения и API, интеграция с AI, есть готовые образы docker и активное коммьюнити.

Парни реально пишут крутое решение. Но есть пара минусов:

1. Нельзя заводить пользователей. Те доступ в workspace тупо по ключу. Ну оно и понятно оно же для личного управления знаниями все же.
2. SiYuan предоставляет большую часть функций бесплатно, даже для коммерческого использования. Однако есть платные возможности, которые доступны только членам Membership (платного тарифа). Например, синхронизация через облако.

Я сначала подумал, что мобильной прилке в настройках указываешь url где лежит твой поднятый siyuan. Но нет - оказывается это отдельное приложение со своим внутренним стораджем. Вот тут то и нужна синхронизация - ведь одна из фич, что документы можно редачить даже в offline. Но если это вам не нужно то достаточно будет открыть web url где развернут ваш персональный siyuan.

В целом видно, что ребята сосредоточились именно на core-фичах своего продукта и это здорово. Думаю на этом развитие не остановится и скоро мы увидим разные методы аутентификации для бизнеса и клаудовую версию, но будет это все скорее всего за денюжку. И мир увидит новый полноценный конкурент notion.

Подходит ли вам SiYuan? Как и с любым другим приложением, лучший способ понять, отвечает ли оно вашим задачам, — это попробовать. Так как оно бесплатное, вы ничего не теряете, кроме времени. В принципе и в рамках организации также можно его задействовать, прикрыв каким нибудь nginx + https://oauth2-proxy.github.io/oauth2-proxy/


mkdir -p siyuan/workspace && cd siyuan

cat <<EOF > compose.yml
services:
main:
image: b3log/siyuan
command: ['--workspace=/siyuan/workspace/', '--accessAuthCode=change-me']
ports:
- 6806:6806
volumes:
- ./workspace:/siyuan/workspace
restart: unless-stopped
EOF

docker compose up -d
👍6🔥3
Пока сидел и ждал ребенка с тренировки наткнулся на ntfy. Это простой бесплатный и опенсорсный HTTP-сервис для уведомлений. Он позволяет отправлять уведомления на ваш телефон через POST запрос.

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

curl -d "Backup successful 😀" ntfy.sh/devops-brain-test

Несмотря на свою простоту, он имеет очень хорошую документацию с кучей примеров использования https://docs.ntfy.sh/publish. Я честно пока не придумал зачем мне это может понадобиться, с учетом того, что нет никаких проблем в telegram создать канал под уведомления и через API-ключ также засылать в телегу.

curl -X POST \
-H 'Content-Type: application/json' \
-d '{"chat_id": "123456789", "text": "Backup successful 😀"}' \
https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage


Но может вам такой способ получение пушей покажется более интересным и вы найдете как применить этот сервис. Вот тут есть много интеграций из коробки https://docs.ntfy.sh/integrations/
2👍13🔥5🤔1
Бесконечно можно смотреть на 3 вещи: огонь, воду и симулятор kafka от softwaremill

🔗 https://softwaremill.com/kafka-visualisation.

Очень классная визуализация, которая позволяет понять принципы работы и покрутить разные ручки для разных сценариев 🔥

#kafka #simulators
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥154
🔑 Утечка секретов это всегда больно. Несу вам два решения, которые помогут обнаружить утекшие секреты и довольно легко интегрируются в cicd. (Методом pennis to nose интеграция в github actions займет минут 10 максимум).

Trufflehog (https://github.com/trufflesecurity/trufflehog) и Gitleaks (https://github.com/gitleaks/gitleaks) - оба решения очень похожи по своей сути, отличие только в алгоритмах поиска. Ну и Trufflehog - он более универсален и может искать утечки:

- git / github
- docker
- filesystem (files and directories)
- gitlab / circleci / travisci / jenkins
- gcs / s3
- postman
- syslog
- elasticsearch

Я не смог придумать кейсов когда надо постоянно проверять всю историю и при интеграции этих решений (если только вы не работаете в банке =) ). Кажется, достаточно проверить репозиторий один раз и дальше уже навешивать проверку просто на пул-реквесты ( с условием что у вас есть branch protection ). Ну и бонусом можно настроить git-хуки.

Подробные инструкции по использованию и установки я приводить нет смысла - они есть в github репах проектов. Единственное покажу как быстро потестить и запустить в докер проверку на файловой системе и репозиториях организации.

# проверяем текущий каталог
docker run --rm -it -v "$PWD:/pwd" trufflesecurity/trufflehog:latest filesystem

# проверяем github репы организации trufflesecurity на github
docker run --rm -it -v "$PWD:/pwd" trufflesecurity/trufflehog:latest github --org=trufflesecurity


Что в итоге выбрать?

- Trufflehog больше подходит для глубокого анализа, если вам нужно работать с разными источниками данных, но также может использоваться и для анализа пул-реквестов, ну и вашего кода.
- Gitleaks — если вы хотите быстро и просто проверять Git-репозитории с хорошей производительностью и минимальной настройкой.
🔥10
Dive in performance tools. Часть 3️⃣ [bmon / bandwhich / iptraf / iperf]

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

1. Разобрать детально все возможные проблемы с сетью, которые могут повлиять на производительность, в рамках одной данной серии постов нереально. Поэтому остановимся на тулах с прямым уклоном в определении что, куда и зачем утилизирует сеть.
2. Помимо перечисленных ниже тулзов существует огромное множество альтернатив. Я же хочу остановиться на тех, которые мне кажутся наиболее полезными и имеют вменяемый TUI.
3. Я не буду описывать способы установки тулзов под каждый дистрибутив, а остановлюсь на демонстрации основных возможностей. Установку гуглится за пару секунд — не будем тратить на это время.
4. Чтобы не спамить в канал буду выкладывать каждый день по 1 туле из списка.

3️⃣.1️⃣ bmon

https://github.com/tgraf/bmon — утилита для мониторинга сетевого трафика в реальном времени. Она показывает скорость передачи данных, ошибки, потери пакетов и общую статистику по интерфейсам.

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

Давайте посмотрим данные, на которые стоит обратить внимание.

▶️ Bytes — Показывает объем входящего и исходящего трафика в байтах.
▶️ Abort Error — Ошибки разрыва соединения между источником и получателем пакета.
▶️ Carrier Errors — Ошибки связи между устройствами, возникающие из-за несоответствия дуплекса или проблем с сигналом.
▶️ Collisions — Количество коллизий (конфликтов) при передаче данных между устройствами.
▶️ CRC Errors — Ошибки контрольной суммы (Cyclic Redundancy Check, CRC), возникающие из-за поврежденных пакетов.
▶️ Dropped — Количество пакетов, которые были отброшены из-за проблем с доставкой (например, перегрузка сети).
▶️ Errors — Общее количество ошибок в сети.
▶️ FIFO Errors — Ошибки очереди FIFO (First In, First Out) — возникают, когда сетевой интерфейс не успевает передавать данные и буфер заполняется.
▶️ Frame Error — Ошибки фрейма — поврежденные пакеты, вызванные сбоями в передаче данных.
▶️ Heartbeat Errors — Количество потерянных сигналов (heartbeat) между оборудованием или программными модулями, что может привести к проблемам синхронизации.
▶️ Length Error — Ошибки длины пакетов - когда длина в заголовке меньше минимально возможного размера.
▶️ Missed Error — Количество пакетов, пропущенных при передаче (обычно пакеты нумеруются для их восстановления).
▶️ No Handler — Количество пакетов, для которых не найден обработчик протокола.
▶️ Over Errors — Ошибки переполнения - когда буфер приема был переполнен или пакеты превышали максимальную длину фрейма.
▶️ Window Error — Количество пакетов, в которых размер окна (число октетов в заголовке) оказался некорректным и не может быть обработан.


💭 Анализ вывода bmon на примере из скриншота

В данном случае разберем конкретный сетевой интерфейс. На графике показано мы видим ходящий трафик (RX): примерно 780 KiBps. Исходящий трафик (TX): 3.76 MiBps. Вывод: сервер больше отправляет данных, чем получает. Это характерно для сервера - тут вопросов нет.

Явные проблемы:

- 18K потерянных пакетов (RX) — возможно, перегрузка интерфейса или дроп пакетов из-за политики очередей (QoS).
- 7.82K ошибок приема — проблемы могут быть на уровне сетевого оборудования или драйвера.

Из хороших новостей — нет ошибок передачи - сервер стабильно передает данные, но испытывает проблемы с приемом.

А на этом у меня все, а в следущих постах мы с вами детально разберем bandwhich, iptraf и iperf...stay tuned ⬇️
Please open Telegram to view this post
VIEW IN TELEGRAM
2🔥9👍7👌1
🆕 Как запустить публичный сайт на телефоне или экономим на спичках

Сейчас научу "плохому" — будем поднимать наше веб-приложение на телефоне с https, dns, cloudflared туннелями и прочей красотой.

Для этой цели я накидал приложение на go, которое определяет IP адрес, вычисляет город, отправляет запрос во внешний сервис и отдает страницу с данными о погоде в вашей локации. Я не стал упарываться - он просто нужен для демонстрации, исходники тут https://github.com/itcaat/what-is-the-weather-now.

Что нам нужно:
1️⃣ Само веб-приложение.
2️⃣ Установленный UserLAnd https://userland.tech/ ( root не потребуется )
3️⃣ GitHub Actions чтобы собрать приложение.
4️⃣ Аккаунт на CloudFlare с нашим подключенным доменом — у меня будет devopsbrain.ru (бесплатный тариф подойдет)

Итак, качаем UserLAnd https://play.google.com/store/apps/details?id=tech.ula. В списке операционных систем выбираем Ubuntu (Minimal → Terminal). На телефоне откроется терминал и сразу установим пароль пользователя userland. Не спрашивайте почему через sudo - просто поверьте, так надо. =)


$ sudo passwd userland


Теперь посмотрим в настройках wifi свой IP адрес и подключимся с компа по ssh (порт 2022). Ну и сразу установим пакетики.


$ ssh userland@192.168.1.75 -p2022
$ sudo apt update && sudo apt install ca-certificates nano jq unzip -y


Само приложение и его сборка у меня уже готовы. Я собираю сразу под все платформы и архитектуры и качу релиз из main бранчи. Подсмотреть как сделано можно тут https://github.com/itcaat/what-is-the-weather-now/blob/main/.github/workflows/release.yml. Но нам нужен только arm64.

Деплоить на телефон мы будем максимально просто - сделаем скрипт который будет находить последний релиз и разворачивать в userland.

Скрипт развертывания можно посмотреть тут: https://github.com/itcaat/what-is-the-weather-now/blob/main/install_and_run.sh. Там есть параметр —force, который убьет все процессы нашей прилки и заново скачает и запустит приложеньку. Также если скрипт обнаружит новый релиз, то также стопнет текущие процессы нашей прилки и раскатит новую версию. (Можно попробовать поставить github self-hosted runner и деплоить по красоте, но у меня памяти не хватило на него).

Просто кладем его в домашний каталог, chmod +x install_and_run.sh и запускаем. Он найдет последний релиз, скачает его под нашу платформу arm64 и запустит в фоне приложение. Приложение вешается на порт 8080. (см скриншот)

Дальше остается просто добавить туннель в cloudflare zerotrust. При активации вас попросит вбить карту - можно скипнуть этот шаг и сразу настроить туннель cloudflared. По сути нам надо просто выделить либо корневой домен, либо какой то поддомен. Логично что обслуживание домена у вас должно быть в cloudflare (напоминаю, что это бесплатно). (см скриншот)

Далее нам нужно выбрать нужную архитектуру и операционную систему. В нашем случае debian arm64 и запустить команду для установки cloudflared. (см скриншот)

После установки зароутим web трафик в туннель. (см скриншот)

По итогу туннель будет запущен и можно открывать наш супер сайт https://weather.devopsbrain.ru, который хостится прямо на нашем телефоне. SSL также будет из коробки. (см скриншот)


$ curl https://weather.devopsbrain.ru

<html>
<head>
<title>Weather</title>
<meta charset="UTF-8">
</head>
<body>
<h1>Your IP: 213.196.40.61</h1>
<h2>Weather in Amsterdam </h2>
<p>Partly cloudy +9°C</p>
</body>
</html>


Бонусом можно в Rules добавить редирект с http на https в пару кликов. Ну и как вы понимаете, запустить в принципе можно все что хотите (даже с бд-шками) при достаточном количестве памяти. А на этом все - всем хорошего вечерочка.

UPD Есть ненулевая вероятность, что демонстрационный сайт выйдет в окно, так как никакого кеширования там нет и выйти за рейты используемых API очень легко. И вообще это не продакшен-реди решение ;)

UPD2: все таки добавил in memory cache - а то без него грустно

habr: https://habr.com/ru/articles/879818/
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
1🔥14👍52💯1
Dive in performance tools. Часть 3️⃣.2️⃣ [bandwhich]

Мы уже познакомились с bmon тут https://t.me/devopsbrain/123. Сегодня максимально коротко - хочу познакомить с bandwhich.

bandwhich - это консольная тулза для отображения текущего использования сети по процессам, соединениям и удалённым IP-адресам.

Киллер-фича данной тулы в том, что она показывает суммарную утилизацию по remote IP-адресам (Панель utilization by remote address вверху справа). Есть много тузов которые показывают текущее состояние в разрезе процессов или установленных соединений, протоколов и портов - bandwhich же группирует по ip адресам. Это бывает очень полезно, если вы не хотите видеть шум а картину в целом, но с группировкой по IP-адресу.

Также интересно бывает посмотреть утилизацию сети в разрезе на каждое соединение, чтобы определить потенциальный источник проблемы как в целом системы, bandwhich также позволит это сделать.
Please open Telegram to view this post
VIEW IN TELEGRAM
6🔥5👏2👍1
DevOps Brain 🧠 pinned «📍 Карта канала Ламповый чатик для своих людей: @devopsbrain_chat Собрал в одном месте все самые полезные посты - изучайте, применяйте! --- 🔵Вредные советы начинающим специалистам в IT 🔵Говорим с TeamCity на одном языке с помощью MCP 🔵Делаем свой бесплатный…»
🆕 Как исправлять ошибки в Git, не оставляя улик

Кто не сталкивался с коммитами вроде "Remove debug log", "Fix" или "фикс фикса"?

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

К счастью, Git предлагает два супер-инструмента для того, чтобы история коммитов выглядела так, будто ты всегда знаешь, что делаешь: git commit --fixup и git rebase --autosquash.

⚠️ Важно! Не вздумайте применять rebase в main или stable-ветках, если не хотите, чтобы ваши коллеги не сделали вам больно. Эти штуки нужны для приведения feature-ветки в божеский вид перед слиянием.

# Использование fixup и autosquash

## Что делает fixup?

Команда git commit --fixup <commit> говорит Git: *"Я накосячил, но давай сделаем вид, что этого никогда не было"*. Она автоматически помечает коммит как исправление указанного коммита, чтобы позже их можно было объединить.

## Как работает autosquash?

Команда git rebase -i --autosquash делает всю грязную работу: находит fixup-коммиты и запихивает их обратно в родительский коммит, словно ничего и не происходило.

---

# Практический пример

## Шаг 1. Делаем коммиты (как обычно, неидеально)

Представьте, что вы работаете в своей фича-ветке mvp-server и коммитите две новые фичи:


$ git add main.go
$ git commit -m "feat: listen port 8080"
[mvp-server dc4efa9] feat: listen port 8080
1 file changed, 1 insertion(+)

$ git add main.go
$ git commit -m "feat: added handlers"
[mvp-server ab604f9] feat: added handlers
1 file changed, 1 insertion(+), 1 deletion(-)


## Шаг 2. Ой… нашлась ошибка в первом коммите

Оказывается, в коммите с feat: listen port 8080 была опечатка, и теперь сервер запускается не на 8080, а на 808 порту. Не беда, просто делаем fixup. Но для начала надо найти тот коммит, который будем фиксить. В нашем случае это будет dc4efa9


$ git log --oneline
ab604f9 (HEAD -> mvp-server) feat: added handlers
dc4efa9 feat: listen port 8080
df9f0ae (main) mvp

$ git add main.go
$ git commit --fixup dc4efa9
[mvp-server 62e7318] fixup! feat: listen port 8080


Git сам добавляет fixup! перед сообщением, как бы говоря: "Да-да, я понял, ты хотел исправить, но давай замнем эту тему".

Если же настроен git hook для добавления в начало сообщения ID-таска, то можно воспользоваться --no-verify , чтобы временно отключить хуки. В противном случае придется при ребейзе руками прописывать pick для fixup-коммита.


$ git commit --no-verify --fixup <commit_hash>


## Шаг 3. Проверяем, что нас ждёт


$ git log --oneline
62e7318 (HEAD -> mvp-server) fixup! feat: listen port 8080
ab604f9 feat: added handlers
dc4efa9 feat: listen port 8080
df9f0ae (main) mvp


## Шаг 4. Применяем rebase и делаем вид, что всё было идеально с самого начала

Важно, что надо передать в ребейз хеш последнего коммита, который вы хотите сохранить как есть, а не первого, который вы хотите поменять. В нашем случае это будет df9f0ae , так как git будет менять как раз dc4efa9 feat: listen port 8080 .


$ git rebase -i --autosquash df9f0ae


Редактор откроет вот такую картину:


pick dc4efa9 feat: listen port 8080
fixup 62e7318 fixup! feat: listen port 8080
pick ab604f9 feat: added handlers


Просто сохраняем, выходим и наслаждаемся магией.

## Шаг 5. Проверяем, что история коммитов идеальна


$ git log --oneline
a72151f (HEAD -> mvp-server) feat: added handlers
0441501 feat: listen port 8080
df9f0ae (main) mvp


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

habr: https://habr.com/ru/articles/881614/
1🔥181
🆕 Настройка самоподписных валидных ssl-сертификатов в локальном k8s. Часть 1.

В данном гайде мы настроим автоматический выпуск “валидных” сертификатов в локальном kubernetes кластере. В качестве примера запустим приложение grafana.

Что будем делать:

1. Развернем локально кластер локально. Установим MetalLB, cert-manager, ingress и поднимем тестовое приложение grafana.
2. Настроим нашу систему так, чтобы она доверяла выпущенным в кубе сертификатам.
3. Используем nip.io, чтобы не заморачиваться с hosts-файлом

# Поднимаем кластер

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

# MetalLB

MetalLB — это балансировщик нагрузки для Kubernetes, предназначенный для работы в средах, где нет встроенного облачного балансировщика, например, в bare-metal кластерах. Kubernetes изначально предполагает, что балансировка нагрузки будет предоставляться облачными провайдерами (AWS, GCP, Azure), но в локальных кластерах или в on-premise инфраструктуре такой возможности нет. MetalLB решает эту проблему, предоставляя LoadBalancer-сервисам реальные IP-адреса.

MetalLB поставим и сконфигурируем просто для удобства. Он выдаст сервису Ingress Load Balancer наш локальный IP-адрес.


# Для начала проверим что мы точно в нужном кластере
$ kubectl config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* docker-desktop docker-desktop docker-desktop

# Устанавливаем
$ kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/main/config/manifests/metallb-native.yaml

# Проверяем что подики поднялись
$ kubectl get pods -n metallb-system

# Найдем наш локальный ip адрес (у меня macos).
$ ifconfig | grep "inet " | grep -v 127.0.0.1
inet 192.168.1.52 netmask 0xffffff00 broadcast 192.168.1.255


Теперь сразу же настроим, чтобы выдавался только нужный нам IP адрес. Вы можете тоже самое сделать и для 127.0.0.1. Но я буду вешать на IP адрес в локальной сети, так как в дальнейшем планирую, что доступ понадобится из локальной сети. В моем случае это будет 192.168.1.52.


kubectl apply -f - <<EOF
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: ingress-ip-pool
namespace: metallb-system
spec:
addresses:
- "192.168.1.52-192.168.1.52"
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: advert
namespace: metallb-system
EOF



Продолжение далее ⬇️
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9👍2
🆕 Настройка самоподписных валидных ssl-сертификатов в локальном k8s. Часть 2.

# Сертификаты и ingress

Сначала нам надо выпустить корневой сертификат. Для этих целей будем использовать mkcert. Это утилита, которая позволяет легко создавать локальные SSL/TLS-сертификаты без необходимости подписывать их у внешнего удостоверяющего центра (CA). Основное преимущество mkcert — автоматическая генерация доверенного корневого сертификата и выпуск локальных сертификатов, которые сразу же распознаются браузерами и системами без дополнительных настроек. Процесс установки есть в https://github.com/FiloSottile/mkcert под вашу OS.


# Запустим утилиту. Это надо сделать один раз, она сгенерит CA и пропишет в нашу ОС.
$ mkcert --install


Далее установим наш cert-manager в kubernetes и добавим наш CA в кластер, чтобы мы могли выпускать сертификаты.


# Устанавливаем в namespace cert-manager
$ kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.17.1/cert-manager.crds.yaml
$ helm repo add jetstack https://charts.jetstack.io --force-update
$ helm install cert-manager --namespace cert-manager --version v1.17.1 jetstack/cert-manager --create-namespace

# cert-manager сможет использовать этот CA для автоматической выдачи сертификатов
$ kubectl create secret tls mkcert-ca-key-pair --key "$(mkcert -CAROOT)"/rootCA-key.pem --cert "$(mkcert -CAROOT)"/rootCA.pem -n cert-manager

# Создаем объект ClusterIssuer в Kubernetes, который будет использовать сертификаты из секрета mkcert-ca-key-pair
$ kubectl apply -f - <<EOF
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: mkcert-issuer
namespace: cert-manager
spec:
ca:
secretName: mkcert-ca-key-pair
EOF


Теперь установим ingress nginx.


$ helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx --force-update
$ helm install ingress-nginx ingress-nginx/ingress-nginx --namespace ingress-nginx --create-namespace


# Запускаем приложение

Возникает вопрос какой же домен использовать. Мы же не ограничены только одним приложением, а хотим просто в ingress задавать нужный домен и чтобы он был доступен на локальной машине. А каждый раз при поднятии нового приложения прописывать адрес в hosts - такая себе история. Чтобы сделать красиво и без боли воспользуемся таким классным сервисом как nip.io.

nip.io — это бесплатный сервис для динамического DNS, он позволяет использовать доменные имена, привязанные к IP-адресу, без необходимости иметь собственный DNS-сервер. Сервис автоматом подставляет IP-адрес при запросе <IP-адрес>.nip.io. Например:

- 192.168.1.52.nip.io → разолвится в 192.168.1.52
- demo.203.0.113.20.nip.io → резолвится в 203.0.113.20

У нас все готово и осталось запустить grafana. Применяем подготовленные манифесты с Deployment, Service и Ingress.


kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: grafana-deployment
labels:
app: grafana
spec:
replicas: 3
selector:
matchLabels:
app: grafana
template:
metadata:
labels:
app: grafana
spec:
containers:
- image: grafana/grafana:11.5.1
name: grafana
ports:
- containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
name: grafana-service
labels:
app: grafana
spec:
selector:
app: grafana
ports:
- protocol: TCP
port: 3000
targetPort: 3000
type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: grafana-ingress
annotations:
cert-manager.io/cluster-issuer: mkcert-issuer
spec:
ingressClassName: nginx
tls:
- hosts:
- grafana.192.168.1.52.nip.io
secretName: hello-ingress-cert
rules:
- host: grafana.192.168.1.52.nip.io
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: grafana-service
port:
number: 3000
EOF


Ну и получаем работающее приложение с валидным на локальной машине самоподписным сертификатом по адресу https://grafana.192.168.1.52.nip.io/

habr: https://habr.com/ru/articles/883428/
Please open Telegram to view this post
VIEW IN TELEGRAM
1🔥10👍5
Media is too big
VIEW IN TELEGRAM
Что-то скучный у меня сегодня вечер: жена уехала тусить с подругой, а дети сидят и играют в лего.
Штош, тогда надо сделать что-то полезное, но не скучное. Будем писать хацкерский скрипт - это ацкий комбайн из kubescape(k8s) и metasploit.

Идея очень простая: сканим кластер k8s через kubescape, сохраняем результаты в json, дергаем оттуда CVE и ищем в metasploit. По итогу получаем список эксплойтов, которые можно заюзать в metasploit.

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


#!/bin/bash

DEFAULT_SCAN_NAME=$(date +"%Y-%m-%d_%H-%M-%S")
read -p "Enter a name for this scan (leave empty for default: $DEFAULT_SCAN_NAME): " SCAN_NAME
SCAN_NAME=${SCAN_NAME:-$DEFAULT_SCAN_NAME}

SCAN_DIR="scans/$SCAN_NAME"
mkdir -p "$SCAN_DIR"
echo "[+] Scan results will be stored in: $SCAN_DIR"

echo "[+] Checking for required tools..."

if ! command -v kubescape &> /dev/null; then
echo "[-] Kubescape is not installed. Please install it first."
exit 1
fi

echo "[+] Checking current Kubernetes context..."
CURRENT_CONTEXT=$(kubectl config current-context)
if [ -z "$CURRENT_CONTEXT" ]; then
echo "[-] No active Kubernetes context found. Please configure your kubeconfig."
exit 1
fi
echo "[+] You are currently using Kubernetes context: $CURRENT_CONTEXT"

read -p "Do you want to continue with this context? (y/n): " CONTINUE
if [[ "$CONTINUE" != "y" && "$CONTINUE" != "Y" ]]; then
echo "[-] Exiting script."
exit 0
fi

read -p "Enter the namespace to scan (leave empty for all namespaces): " NAMESPACE
if [[ -z "$NAMESPACE" ]]; then
NAMESPACE_FLAG="--all-namespaces"
echo "[+] Scanning all namespaces..."
else
NAMESPACE_FLAG="-n $NAMESPACE"
echo "[+] Scanning namespace: $NAMESPACE"
fi

read -p "Do you want to check Metasploit for available exploits? (y/n): " CHECK_METASPLOIT
if [[ "$CHECK_METASPLOIT" == "y" || "$CHECK_METASPLOIT" == "Y" ]]; then
SEARCH_METASPLOIT=true
# Check if Metasploit is installed
if ! command -v msfconsole &> /dev/null; then
echo "[-] Metasploit is not installed. Exploit search will be skipped."
SEARCH_METASPLOIT=false
fi
else
SEARCH_METASPLOIT=false
echo "[+] Skipping Metasploit exploit search."
fi

echo "[+] Retrieving container images..."
kubectl get pods $NAMESPACE_FLAG -o json | jq -r '.items[].spec.containers[].image' | sort -u > "$SCAN_DIR/images.txt"

if [[ ! -s "$SCAN_DIR/images.txt" ]]; then
echo "[-] No container images found in the selected namespace(s)."
exit 1
fi

echo "[+] Found $(wc -l < "$SCAN_DIR/images.txt") unique images."

echo "[+] Scanning container images with Kubescape..."
mkdir -p "$SCAN_DIR/results"

while read -r image; do
echo "[*] Scanning $image..."
safe_name=$(echo "$image" | tr '/:' '_')
kubescape scan image "$image" --format json --output "$SCAN_DIR/results/${safe_name}.json"
done < "$SCAN_DIR/images.txt"

echo "[+] Extracting CVEs from Kubescape reports..."
jq -r '.matches[].vulnerability.id' "$SCAN_DIR/results/"*.json | grep CVE > "$SCAN_DIR/cve_list.txt"

if [[ ! -s "$SCAN_DIR/cve_list.txt" ]]; then
echo "[-] No CVEs found in container images."
exit 0
fi

echo "[+] Found $(wc -l < "$SCAN_DIR/cve_list.txt") CVEs."

if [[ "$SEARCH_METASPLOIT" == true ]]; then
echo "[+] Searching for exploits in Metasploit..."
rm -f "$SCAN_DIR/metasploit_results.txt"

while read -r cve; do
echo "[*] Searching for $cve in Metasploit..."
msfconsole -q -x "search $cve; exit" | tee -a "$SCAN_DIR/metasploit_results.txt"
done < "$SCAN_DIR/cve_list.txt"

echo "[+] Search completed. Found exploits:"
grep -E 'exploit/' "$SCAN_DIR/metasploit_results.txt" || echo "[-] No exploits found for detected CVEs."
else
echo "[+] Skipping Metasploit exploit search."
fi

echo "[+] Scan completed. Results are stored in: $SCAN_DIR"


https://devopsbrain.ru/posts/2025-02-16-metasploit-%D0%BAubescape/
🔥12😁42🍓2👍1👏1
Мои дети просто обожают играть в minecraft. Ну а я никогда не понимал смысла игры. Ходишь там что-то добываешь без конца и строишь, крафитишь, добываешь и так до бесконечности. Сейчас они обнаружили, что можно ставить моды. Иногда зовут меня смотреть, что у них там получается, а иногда зовут помочь с запуском модов. И тут я решил, что пора их с моими играми познакомить.

Вчера я предоложил им поиграть в Terraform. Они поискали и нашли что за игра в Steam https://store.steampowered.com/app/347790/Terraform. Но как вы понимаете играли мы в совершенно другую игру. 🧌

Результатом этого "геймплея" стал вот этот реп: https://github.com/itcaat/terraform-kubernetes-desktop-startkit. Помните, был пост про настройку локального куба и валидных ssl в нем(https://t.me/devopsbrain/135)? Так вот это почти тоже самое, но теперь все можно настроить за пару команд.

📌 Как играть в Terraform Kubernetes — Starter Kit for Docker Desktop?

1️⃣ Ставите Docker Desktop и активируйте в нем Kubernetes (или любой аналог)

2️⃣ Форкаете репу https://github.com/itcaat/terraform-kubernetes-desktop-startkit.

3️⃣ Запускаете по инструкции – и вот у вас есть локальный кластер с Ingress, Cert-Manager, MetalLB и Echo Server в качестве примера!

Цель игры в Terraform проста: накопать как можно больше модулей и собрать из них что-то прикольное.

Кстати, моим детям не понравилось играть в Terraform. Говорят, слишком мало криперов и слишком много непонятной ерунды. Ну и в чем они не правы?
🔥12😁9
🆕 На что влияет evaluation_interval и for в алертах prometheus
_
Если вы используете prometheus или victoria metrics для настройки алертов, то наверняка встречали функции анализа временных рядов. Их отличительной особенностью является то, что они на вход получают временной интервал ([X]).

- increase() — считает, на сколько увеличился счётчик.
- rate() — усреднённая скорость изменения в секунду.
- delta() — разница между начальным и конечным значением.
- deriv() — скорость изменения с учётом тренда.

Разберем на примере, где хотим получить все успешные заказы в окружении production.


increase(orders_total{environment="production", status="success"}[30m])


В данном примере increase(...) рассчитывает, насколько увеличился счётчик orders_total за последние 30 минут. Поскольку это счётчик counter (_total в имени как бы намекает), его значения могут только увеличиваться или сбрасываться на 0, если произошёл рестарт сервиса. Таким образом, increase(...[30m]) показывает, сколько успешных заказов (status="success") было обработано за последние 30 минут.

Теперь пришло время сделать алерт. Мы хотим знать, что конверсия (количество успешных заказов в данном случае) упала и бизнесу плохо. И тут некоторые ошибочно полагают, что не могут использовать for меньше чем 30 минут. Природа ошибки в принципе понятна, чаще всего мы используем в выражении меньший интервал, а for больший. Ну к примеру, increase(...[1m]) с for: 5m. В этом случает никаких вопросов нет и все просто. Но на самом деле все гораздо интереснее.

Механизм срабатывания алерта в Prometheus зависит от параметра evaluation_interval, который определяет частоту вычислений правил. По-умолчанию он evaluation_interval: 1m . Поэтому prometheus будет вычислять по такому алгоритму:

- В T0 (now) он считает increase(...[30m]), получая данные за диапазон [T-30m, T0].
- В T+1m он снова считает increase(...[30m]), теперь за [T-29m, T+1m].
- В T+2m — за [T-28m, T+2m].
- ...
- В T+5m — за [T-25m, T+5m].

Если значение выражения остаётся выше порога на всех 5 оценках (T0, T+1m, ..., T+5m), то алерт срабатывает.

Предположим, что для бизнеса нормально делать по 100 заказов за 30 минут, в противном случае нам нужен алерт. Пример в данном случае выдуман из головы и в реальной жизни нам был бы интересен for: 0m. Но мы предположим, что при for: 0m у нас будут ложные срабатывания. Ну, например, во время релизов допускается, что возможны просадки. Поэтому мы заложим туда 5 минут и опишем так:


- alert: NoSuccessOrders
expr: increase(orders_total{environment="production", status="success"}[30m]) < 100
for: 5m
labels:
severity: critical
annotations:
summary: "No Success Orders"
description: "Successful orders dropped below 100 in the last 30 minutes"


Разбор примера:
- Как мы говорили выше — функция increase(...[30m]) вычисляет изменение метрики за последние 30 минут.
- Это изменение пересчитывается каждый раз при выполнении запроса в зависимости от настройки evaluation_interval в Prometheus.
- Если условие алерта (expr) остаётся истинным в течение 5 минут подряд (на всех оценках), алерт сработает.
5🔥5👍2