Vasiliy Ozerov – Telegram
Vasiliy Ozerov
3.4K subscribers
14 photos
1 file
77 links
Обожаю настраивать, траблшутить и помогать другим!

Youtube: youtube.com/@sysopslab

Founder - rebrainme.com
exFounder - fevlake.com

Для фидбека и вопросов - @vasiliyozerov
Download Telegram
# ctr -n k8s.io container ls
CONTAINER IMAGE RUNTIME
093dd176a51cd2aa69ad7a052130dd8f73bc76a638bf3e4ee3a4b62e613e9e90 keycloak:latest io.containerd.runc.v2



6. А теперь взглянем какие задачи запущены в этом контейнере:


# ctr -n k8s.io tasks ps 093dd176a51cd2aa69ad7a052130dd8f73bc76a638bf3e4ee3a4b62e613e9e90
PID INFO
51028 -



Из вывода видно, что в данном контейнере у нас запущен процесс с PID = 51028 ну и дальше можно посмотреть что это за процесс.

7. Так же можно вывести список всех задач:


# ctr -n k8s.io tasks list
TASK PID STATUS
b6d79f43dde30d226af1c7b7bcf59188eed7661c0e6fd094a7c3d25d9ac0cf9b 50975 RUNNING
a59661db743f5a6deae2dd2292b0085853f94adc58f4a9d07d76ca9ba1ae433f 46053 RUNNING
f0840a9b8d70889a957cb082d4cf752cebef555d6d66da458944fdcd39013d9e 48139 RUNNING



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

Ну и напоследок важная информация по поводу sandbox_image. Я думаю вы замечали, что kubernetes запускает какой-то непонятный pause контейнер, который крутится внутри пода:


# ctr -n k8s.io container ls | grep pause
330dd58e20efbeff2c2e2c5a688a4ac26ba8ca1c07f8c0e4806f602b2dafe94a k8s.gcr.io/pause:3.6 io.containerd.runc.v2



Pause контейнер выполняет важную задачу - он держит сетевой namespace для пода в случае если все ваши контейнеры внутри него умрут. Он запускается первым, чтобы containerd создал сетевой namespace, к которому впоследствии будут подключаться контейнеры из пода. То есть когда вы стартуете любой под в kubernetes (даже с одним контейнером), kubelet через CRI дергает containerd и запускает RunPodSandbox, который запускает sandbox image и настраивает сеть с помощью CNI плагинов. Если все контейнеры в поде умрут, то pause останется и соответственно сетевой namespace будет сохранен.

В общем когда вы разворачиваете kubernetes внутри приватной сети без доступа в интернет, то вам потребуется указать параметр sandbox_image в containerd config.toml, который будет смотреть на приватный registry:


# containerd config default | grep sandbox
sandbox_image = "k8s.gcr.io/pause:3.2"
🔥58👍192💩1
Собственно на этом все - всем хорошей ночи! 🙂
👍49💩1🐳1
Вообще очень странно, что я ничего не писал про wireguard до сегодняшнего дня, поскольку это решение одно из лучших для быстрой организации защищенных vpn туннелей (по моему, чисто субъективному мнению).

В двух словах. Wireguard работает поверх udp и заворачивает внутрь зашифрованные ip пакеты. В отличие от IPSEC, wireguard не устанавливает соединение, поэтому перемещение клиентов выглядит очень просто - нет никаких переподключений - просто отправляем udp датаграмму на сервер и все работает. Наконец-то никаких проблем с фаерволами и прочей фигней (как было с IPSec).

С точки зрения безопасности у wireguard все тоже хорошо. Поскольку wireguard’у не требуется поддерживать всякое старое, то в него не включали устаревшие методы шифрования. А исходники wireguard прошли аудит. В общем про криптографию можно почитать здесь - https://books.google.com/books?id=UKJfDwAAQBAJ&pg=PA3&redir_esc=y#v=onepage&q&f=false.

И по скорости wireguard опережает тот же openvpn, поскольку реализован на уровне ядра. Хотя справедливости ради стоит отметить, что в последнем релизе openvpn разработчики также добавили модуль ядра для повышения производительности.

Итак, если вы хотите настроить wireguard сервер на ubuntu, то нет ничего проще:


# Устанавливаем wireguard
apt-get install wireguard

# Генерируем приватный и публичный ключ для нашего сервера
cd /etc/wireguard && wg genkey | tee privatekey | wg pubkey > publickey

# Создаем конфигурацию wireguard
cat > wg0.conf <<EOF
# Наш интерфейс на котором слушаем входящие пакетики
[Interface]
# Адрес, который будет назначен нашему интерфейсу
Address = 10.8.0.1/24
# Сохраняем конфигурацию, если вносим изменения через wg утилиту
SaveConfig = true
# Слушаем на 51820 порту
ListenPort = 51820
# Наш приватный ключ - берем из ранее сгенерированного файла privatekey
PrivateKey = <private key>
EOF

# Добавляем wireguard в автозагрузка и поднимаем интерфейс
systemctl enable wg-quick@wg0
systemctl start wg-quick@wg0

# Проверяем статус интерфейса
wg show
interface: wg0
public key: <server public key>
private key: (hidden)
listening port: 51820


Для подключения клиента, к примеру на маке, устанавливаем wireguard тулзу из appstore. После запуска и создания туннеля, клиент сам сгенерирует свой приватный ключ и отобразит его публичную часть - это потребуется нам в будущем - когда мы будем добавлять клиента на сервере. А пока составляем конфигурацию для клиента:

jsx
# Интерфейс на клиенте
[Interface]
# Приватный ключ, который сгенерировала утилитка wireguard. Если хотите - можете сами сгенерировать ключи с помощью wg.
PrivateKey = <private key client>
# Наш адрес, который будет настроен на интерфейсе
Address = 10.8.0.5/24

[Peer]
# Публичный ключ нашего сервера из файла publickey
PublicKey = <public key>
# AllowedIPs решает две задачи:
# 1. Ограничивает доступ из туннеля только для апйпишников, указанных здесь - то есть если из туннеля пойдет трафик из подсети 10.9.0.0/24, то wireguard его отбросит.
# 2. Wireguard добавляет маршруты до этой сети через туннель - то есть если вы захотите обратиться к узлу 10.8.0.127, то система отправит пакеты в данный туннель. Через запятую можно указывать несколько сеток. А если указать 0.0.0.0/0, то весь трафик пойдет через защищенный канал.
#
AllowedIPs = 10.8.0.0/24
# Адрес и порт нашего wireguard сервера
Endpoint = 169.254.1.1:51820
# Как часто посылать keepalive пакеты. Поскольку wireguard работает по udp, то есть клиент находится за NAT, то через 30 секунд (зависит от настроек PAT / NAT), маршрутизатор оборвет сессию и сервер не сможет обратиться к клиенту, так что данные keepalive'ы нужны, чтобы поддерживать запись в таблице трансляции на маршрутизаторе.
PersistentKeepalive = 15


Отлично! Практически все готово. Теперь осталось добавить нашего клиента на сервер. Для этого на сервере выполняем:
👍54🔥10👏3
jsx
# Добавляем клиента, указывая его публичный ключ и какие сети / айпишники находятся за ним. Логика такая же - все сети, указанные в allowed-ips будут маршрутизироваться сервером в данный туннель
wg set wg0 peer <client public key> allowed-ips 10.8.0.5/32


Теперь можно подключаться и проверять соединение!

jsx
wg show
interface: wg0
public key: <server public key>
private key: (hidden)
listening port: 51820

peer: <client public key>
endpoint: 169.254.99.99:28280
allowed ips: 10.8.0.5/32
latest handshake: 2 seconds ago
transfer: 180 B received, 92 B sent


Вообще для управления всеми этими конфигами можно использовать какой-нибудь web ui, например [https://www.firezone.dev/](https://www.firezone.dev/). Но вообще лучше погуглите - наверняка найдете что-нибудь интересное. Тем более тот же pritunl позволяет генерировать wireguard профили.

Теперь немного минусов:

1. К сожалению, вы не можете указать что-то типа disallowed-ips и исключить из маршрутизации какой-то айпишник. Чтобы это сделать необходимо добавить в allowed-ips все остальные, за исключением нужного. Для этого ребята даже написали allowed-ips калькулятор - https://www.procustodibus.com/blog/2021/03/wireguard-allowedips-calculator/. Можете пользоваться 🙂
2. Поскольку у wireguard нет сессий, то организация каких-либо аудит логов становится немного затруднительна - по факту нельзя сказать когда пользователь подключился - можно только сказать когда он начал отправлять данные. А так если для вашей системы безопасности требуются аудит логи, то можно посмотреть на https://www.procustodibus.com/blog/2021/03/wireguard-logs/, или на гошечке - https://github.com/nikaro/wirelogd.

Ну и конечно же надо затестировать какую-нибудь отказоустойчивую ферму из wireguard хостов. На openvpn с централизованным хранилищем пользователей было круто - поставили десяток openvpn серверов и юзеры коннектятся куда захотят. Упал сервер, убрали из dns и клиент переподключился без проблем.
👍497🔥51
В общем, всем wireguard, народ!
👍74🔥5💩4
Что-то давненько не писал - работки привалило. Но на днях мы наконец-то разрулили одну историю - вытащили сайтик из черного списка. И я бы хотел высказаться про все эти списки дурацкие.

Предыстория. Есть у нас доменчик. И с некоторых сеток он перестал быть доступен - выдавалась заглушка cisco umbrella, типа сайт фишинговый и все дела. Посидели, почитали, изучили. В общем и целом выходило, что сайтик наш добавили в блеклист и теперь надо оттуда вылезать. Пока читал, наткнулся на какие-то форумы, где писали, что сайты проверяют по spfbl, а он проверяет по reverse dns name и если его нет, то привет пока - в список. Ну типа как почтовые сервачки проверяют так же и тут. Как это к вебу относится правда - хрен его знает.

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

По сути ситуация разрешилась хорошо, НО! В этой истории есть одно большое и сильное НО! Даже не одно.

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

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

Во-третьих. Сама ситуация странная. Какая-то компания, создала какой-то свой список, как-то сама его менеджерит и сама решает кому куда можно ходить, а кому куда нельзя. Дальше осталось бы только деньги брать за исключение из списка и бизнес готов. Вон, из spfbl можно выйти платно - https://spfbl.net/en/delist/. Понятно, что там еще условия есть, но просто зацените - черный список и за деньги из него можно выйти. Ну такое себе.

Я в своей истории проходил черные списки только однажды - когда настраивал почтовые системы. Тогда это было мега популярно проверять отправителя по черным спискам. И знаете что? Туда попадали абсолютно все и вообще непонятно по каким причинам. То есть с включенной блокировкой по черным спискам почта не ходила от слова совсем. Ну и я сделал очень простой вывод на всю жизнь - нельзя блочить по черным спискам. Никогда и никого. Черт его знает как кто-то туда попал. Может айпишник старый меченным оказался, а сейчас там вполне валидный сервер располагается. Блочить можно только по совокупности факторов. Типа helo не прислал - вот тебе балл. Отправитель левый - вот тебе еще 5 баллов. В блеклистах есть - вот тебе еще 3 балла. Больше 7 баллов набрал? Идешь лесом.

В истории с их системой можно так же было поступить. Чекаем сайт, он набирает баллы - набрал меньше 50 - в whitelist, набрал от 50 до 70 - на ручную проверку модератором, набрал больше 70 - в бан с уведомлением. А если мы сразу набрали больше 70, то очевидна проблем каллибровки. Если вы вручную потом проверяете и исключаете из списка тут же - значит что-то не так с вашей системой распознования.

Короче раздолбал бы черные списки если б мог. Ах да, черный список в телефоне я регулярно пополняю, а то повадились звонить в одно и тоже время все кому ни лень.
👍596👎3🔥2
Ох, забыл. В догонку сразу - хочу задачку вам задать, не относящуюся к предыдущему посту.

Итак, нужно придумать самый быстрый способ выкрутиться из ситуации.

Ситуация такая. У вас есть виртуалка с айпшником из РФ. И у Вас еще есть виртуалка зарубежная. Между ними связь кайф - все работает. С виртуалки из РФ вы делаете curl -D - https://packages.gitlab.com и получаете 403 - gitlab заблочил доступ из РФ.

Как быстрее всего получить доступ к гитлабу с виртуалке из РФ? Типа за минуту. Ответы кидайте на vasiliyozerov@gmail.com - самый крутой ответ запощу сюда и упомяну автора (при желании). А может еще чего подарю 🙂 Ну и составим топ ответов и сюда закинем.

P.S. Вторую виртуалку зарубежную использовать необязательно - если знаете способ как без нее, но мега быстро - закидывайте.
😁14🔥82🆒2
Так, в последний раз я задал задачку и ушел в неизвестность. Исправляюсь.

Топ вариант номер 1 по ответам - это socks5 proxy в ssh. Я вообще забыл про эту штуку, поскольку практически никогда ее не юзал (АХАХА). Но действительно в ssh есть socks5 и таким образом можно быстро создавать проксики. Очень удобно и очень круто - вы большие молодцы! Выглядит способ так:


ssh -D 127.0.0.1:9999 <ipaddr>
curl -x socks5://127.0.0.1:9999 …


Еще были варианты с использованием squid, wireguard, openvpn и любыми прокси / vpn решениями на удаленных узлах. Но эти варианты я не брал, поскольку, они требуют установки софта, что навряд ли уложится в 1 минуту. Хотя тот же wireguard ставится быстро 🙂

Мой вариант сводился к настройке iptables на второй машинке в таком виде:


iptables -t nat -I PREROUTING -p tcp -m tcp --dport 443 -j DNAT --to-destination 188.114.98.224:443
iptables -t nat -I POSTROUTING -d 188.114.98.224 -p tcp -m tcp --dport 443 -j MASQUERADE


То есть мы меняем назначение для трафика, направленного на 443 порт на packages.gitlab.com и обязательно вторым правилом делаем маскарадинг на наш адрес, чтобы гитлаб не начал отвечать на реальный айпишник. Ну и на исходной машинке добавляем в /etc/hosts айпишник нашей машинки для packages.gitlab.com.

Я видел предложения сделать также в некоторых вариантах (если вариант через iptables подразумевал именно это :). Этот путь конечно не такой универсальный, как с socks5 proxy, поскольку требует чтобы на нашем внешнем хосте 443 был не занят. И он не позволяет проксировать несколько адресов через наш внешний хост - только один. Хотим больше - надо ставить что-то умное типа nginx с сертификатами и proxy_pass, либо прокси сервер, либо wireguard, либо что-то еще.

В общем делаю простой вывод - вы победили - socks5 proxy намного приятнее и быстрее чем мои iptables правила. Поздравлямба!

Самый нестандартный ответ был по поводу использования google translate в качестве proxy. Я честно немного попробовал загрузить файл packages.gitlab.com/gitlab/gitlab-ee/packages/ubuntu/jammy/gitlab-ee_15.11.3-ee.0_amd64.deb через google translate, но у меня не получилось - валю на свои кривые ручки 🙂

Всем хорошей ночки!
🔥49👍14👏41
Если вы, как и я, апгрейдите кубернетес через несколько версий, то в один прекрасный момент helm может сказать вам что-то типа:


Error: UPGRADE FAILED: unable to build kubernetes objects from current release manifest: resource mapping not found for name: "service" namespace: "" from "": no matches for kind "Ingress" in version "extensions/v1beta1"
ensure CRDs are installed first
helm.go:84: [debug] resource mapping not found for name: "service" namespace: "" from "": no matches for kind "Ingress" in version "extensions/v1beta1"


Что в переводе на русский означает, что в предыдущем релизе был ресурс Ingress в “extensions/v1beta1”, но теперь такой версии не существует и извините, я не могу нифига обновить.

Чтобы направить хельм на путь истинный, можно заюзать утилитку [https://github.com/helm/helm-mapkubeapis](https://github.com/helm/helm-mapkubeapis) - она ищет удаленные апишки в прошлом релизе и исправляет их на правильные. Возможно кому-то пригодится.
👍105🫡114👎4
Если вы используете argocd, а конкретно applicationSet, то знайте - вы можете столкнуться с проблемой обновления параметров через сам argocd (app set).

Я использую примерно следующую структуру для своих проектов:

core - корневой репозиторий, в котором я описываю terraform манифесты и параметры бутстрапа кластеров кубера (типа service accounts, cert-manager, etc…).
При развертывании argocd я сразу же создаю корневой проект и добавляю в него root application )https://argo-cd.readthedocs.io/en/stable/operator-manual/cluster-bootstrapping/#app-of-apps-pattern), которое смотрит на этот же core репозиторий, только в директорию apps. Задача этого приложения - создать еще приложения, но уже для отдельных продуктовых команд.
К примеру, там я могу создать приложение auth-root-app для команды аутентификации или email-root-app для команды, которая занимается всем что связано с email’ами. Каждое из этих приложений уже будет смотреть на отдельный репозиторий с манифестами для команды. Для auth-root-app - это gitlab.com/company/auth-team/manifest, а для email-root-app - gitlab.com/company/email-team/manifests.

manifests - это уже репозитории с манифестами для каждой отдельной команды, где описываются их приложения и параметры для них. Здесь каждая команда вольна добавлять какие-то параметры, удалять деплойменты, использовать helm, kustomize, jsonnet и так далее.

Так вот. Если вы приложения для команд создаете с помощью ApplicationSet, то при обновлении параметров приложения команды вы можете столкнуться с такой ошибкой (из логов):

time="x" level=info msg="received unary call /application.ApplicationService/UpdateSpec" grpc.method=UpdateSpec grpc.request.content="%!v(PANIC=String method: reflect.Value.Bytes of non-byte slice)" grpc.service=application.ApplicationService grpc.start_time="x" span.kind=server system=grpc

Подробнее можно посмотреть здесь: https://github.com/argoproj/argo-cd/issues/12151. Вообще есть похожая known issue - https://github.com/argoproj/argo-cd/pull/13061#discussion_r1199279829, но я не уверен что она исправит мою проблему при обновлении.

Поэтому совет - используйте пока только App of apps, а сами приложеньки генерируйте с помощью kustomize. Ну ладно. Или с помощью helm 🙂
👍222
Ох, читал тут статейку про ExternalSecrets Operator - https://hackernoon.com/cooking-helm-with-the-external-secrets-operator-and-reloader и у меня есть что сказать по этому поводу!

Вообще вы можете использовать кучу разных вариантов, чтобы хранить секретные данные в вашем репозитории. Некоторые из них:

1. ExternalSecretsOperator - https://external-secrets.io/v0.8.2/. Логика такая. Ставим его в кубер, настраиваем подключение к внешнему источнику секретов (vault, lockbox, etc..). Далее ESO периодически синкает секреты из внешних источников и сохраняет их в Secret в кубере, который вы можете использовать.
2. SealedSecrets - https://github.com/bitnami-labs/sealed-secrets - решение от битнами. Суть такая. В кубере запускается sealed secrets, который отдает наружу только public key. С помощью kubeseal cli вы можете трансформировать любой Secret в зашифрованный SealedSecret и положить его в git репозиторий. После применения в кубе, SealedSecrets трансформирует SealedSecret обратно в Secret, который вы можете использовать.
3. SOPS - https://github.com/mozilla/sops - sops / ksops / helm secrets - все идет сюда. Суть такая - мы шифруем yaml’ики локально и закидываем в git. Дальше наша ci система с помощью приватного ключа расшифровывает их и передает kustomize / helm или кому-то другому.
4. Argo Vault Plugin - https://argocd-vault-plugin.readthedocs.io/ - суть примерно как у скрещенного sops и external secrets operator, но только если вы используете argocd (хотя можно его и локально запускать на самом деле). Суть такая. Вы внутри secret или других yaml файлов ставите placeholders: <password>, которые заменит vault plugin. Взять данные для подстановки vault plugin может из sops файла, из kms или еще откуда-то. В общем удобно 🙂

Из всех вариантов выше мне нравится sops, поскольку он позволяет хранить секреты рядом с приложением (манифестами), а так же позволяет их легко менять при необходимости. То есть вам не надо придумывать а как же закинуть секретную строку в hashicorp vault (с помощью “ClickOps-Way”), при этом не положив ее в гит.

С ним бы мог поспорить только kubeseal, но тот не позволяет редактировать секреты локально. То есть вы можете их только зашифровать. Расшифровывать нельзя. И это реально неудобно - вам каждый раз придется пересоздавать секрет. А если учесть что в секрете может быть несколько переменных, а вам надо поменять только одну - то привет пока приехали.
👍17🔥10
Vasiliy Ozerov
Ох, читал тут статейку про ExternalSecrets Operator - https://hackernoon.com/cooking-helm-with-the-external-secrets-operator-and-reloader и у меня есть что сказать по этому поводу! Вообще вы можете использовать кучу разных вариантов, чтобы хранить секретные…
Небольшое дополнение к секретами, да и вообще в целом к безопасности.

После этого поста мне написали в личку примерно такое:

"Чем ближе ты расшифровываешь секрет к месту его использования, теб безопаснее система" (с) Дмитрий

Полностью поддерживаю! В моем примере я в конце написал что мне нравится использовать sops и это действительно так, но с точки зрения безопасности самым правильным вариантом является использование SealedSecrets, поскольку он уменьшает поверхность атаки на нашу систему. С сопсом как минимум наша CI система владеет приватным ключом и имеет возможность получить расшифрованные данные. А если предположить что в качестве CI вы используете облачный сервис, то можно вообще считать что вы отдали внешнему сервису данные в открытом виде. И даже если сам сервис не имеет дурных намерений, то он сам может подвергнуться атаке. В общем возможнох вариантов масса.

Это нехитрое размышление приводит нас к очень простому выводу: В каждой ситуации необходимо рассматривать и обсуждать возможные риски. На каком-то проекте вы можете использовать sops, а на каком-то - железные токены, которые выдаются сотрудникам под расписку. Но вы должны самостоятельно продумать эти варианты и принять взешенное решение. Не стоит тут полагаться на Васяна и его мнение 🙂

Я со своей стороны могу сказать, что когда вы настраиваете любую систему вы всегда выбираете между безопасностью и удобством. Чем удобнее - тем менее безопасно. И наоборот. Поэтому я всегда придерживаюсь стандартных гигиенических правил из серии - все ресурсы храним внутри за vpn (gitlab'ы, куберы и тд), все сервисы общаются между собой по внутренней сети, желательно с каким-нибудь istio & mtls, вход на устройства по ключам ограниченному кругу лиц, разработчики не имеют доступа к системам - только к панелькам типа grafana (logs & metrics) и тд. Из вне доступны только те порты, которые используют пользователи - http & https. Для некоторых проектов правила могут быть намного жестче - например вообще отсутствие доступа из интернета. Но в каждой конкретной ситуации надо смотреть и оценивать риски - это главное.

Всем хороших выходных и отдельное спасибо Дмитрию за комментарий 🙂
🔥38👍29🙏1👨‍💻1👀1
Всем привет!

Тысячу лет не писал сюда, потому что просто не знал, что надо писать 🙂 Но теперь у меня появился повод. И этот повод позволит писать сюда намного чаще.

Как-то на вебинарчике я сказал: "Ща через пару недель будет Youtube". И вот, спустя 4 года, я наконец-то его сделал 😂 Вообще, конечно, я прямо долго мечтал и думал про это, и прикидывал как да что. Но все не доходили руки. И вот. Наконец-то! Встречайте - первый ютуб видос - https://youtu.be/kC1g1Z9G_XM.

Как записывался этот видос. Ох... Честно признаюсь - было тяжело. Я думал, что ща сядем и запишем. Записал. Посмотрел. Херня. Пошел читать про сценарии, смотреть, как что делать. Записал еще вариант. Херня. Пошел ресерчить тему глубже и переписывать сценарий. Записал еще вариант. Херня. Попросил помочь друзей-инженеров. Переписали сценарий, переделали структуру. Записал еще вариант. О! Вроде нормас получилось. Да, есть некоторые моменты, которые надо исправить, но они всегда будут! Все! Публикуемся! Собственно, как-то так и получилось 🙂

Да, еще сделал отдельный телеграм-канал, где буду публиковать анонсы видосов и скидывать ссылки на используемые конфигурации - подписывайтесь - t.me/sysopslab. Думаю, туда же буду закидывать всякие интересности про инфраструктуру, а в остальных местах буду менее официальным.

Ну что! Смотрите и наслаждайтесь. Надеюсь, что вам понравится 🙂

P.S. В списке идей для сценариев 48 пунктов 🙂
🔥103👍23🫡94🎉3🥴3
Forwarded from SysOpsLab
Друзья, всем привет! Новости с полей.

Последние две недели писал сценарий про ssl сертификаты. Изначально думал сделать видос на 30 минут, чтобы повеселее было, но в итоге написалось 48 953 знаков 😂 В общем было принято трудно решение разбить этот сценарий на 3 части. Первая - про приватный CA и структуру сертификатов, вторая - про публичные центры сертификации и протокол acme. Ну а третья - про страх и боль отзыва сертификатов. Первую часть записываю сегодня - так что в начале следующей недели ждите на экранах :)

Чтобы вы не подумали что я только про сертификаты буду рассказывать - следующий видос будет про кубер. Self-hosted. Уже закупаю оборудование для лабы - надеюсь вам понравится. Но в 30 минут мы там навряд ли уложимся 😂

Ну а пока сценарии пишутся, оборудование закупается, а видосы монтируются у меня к вас есть просьба. Точнее просьба и предложение - “Давайте знакомиться!”. Вас в канале уже достаточно много, а я даже не знаю кто вы и чем занимаетесь, поэтому предлагаю заполнить данный опросик (на 2-3 минуты) - https://forms.gle/8RpWxuWWASxCYvnBA. Это позволит мне лучше понимать какие темы выбирать для роликов и в каком формате их делать. Спасибо всем кто пройдет! Кстати, внутри есть поле с комментарием - так что можете написать туда абсолютной любой фидбек. Опрос анонимный - почту и контакты оставлять не надо :)

Ах да, чуть не забыл. Мне тут предложили сделать формат random coffee. Сначала я отнесся к этому скептически, но потом поразмыслив понял что вообще прикольная идея. Не знаю правда нужна ли она кому-то, но если вдруг вы хотите познакомиться, поболтать, задать какие-то вопросы или высказать что-то лично, то я сделал два утренних слота в календарике - любой желающий может назначить нам встречу - https://calendly.com/vasiliyozerov/oneonone. Если вдруг затея окажется удачной - то возможно добавлю слотов в субботу или по вечерам.

Всех обнимаю, желаю хорошего дня и напоминаю про опрос - до встречи!
P.S. Фотка отсюда - https://soundbox.pro/hronometr/ (хоть и не читаю с суфлера, но все равно примерно оцениваю время)
🔥69👍64🐳2🫡2
Друзья, всем привет! Давно не виделись!

У меня сегодня будет небольшая просьба ко всем CTO и Тимлидам инфраструктурных команд, кто меня читает. А потом начнем постить всякие интересности.

Ребята в Февлейке сейчас пилят прикольную штуку, связанную с мониторингом. Если в двух словах - это про root cause analysis. Оно позволяет получать контекст и аналитику по алерту еще до момента, как вы откроете дашбоард в графане.

Решение само собирает контекст и подсказывает где стоит искать причину, тем самым позволяя быстрее восстановить сервис. Под капотом — LLM и интеграции через MCP, которые собственно и решают вопросы сбора контекста и рекомендаций.

Сейчас ребятам нужно провести 5-10 кастдевов с СТО и Тимлидами Девопсов, за это они дадут доступ на пол года, после релиза! У кого есть возможность выделить 10-15 минут на вопросы, заполните форму, и ребята с вами свяжутся.

Форма тут - https://forms.yandex.ru/u/6900a32c4936392a4e9377e5/
👍12👀10🤡8🔥31🤣1🤝1
Читал тут RFC по Model Context Protocol (MCP) и откопал интересную штуку. Там есть требование чтобы oAuth сервера, используемые для MCP должны поддерживать стандарт динамической регистрации клиентов (Dynamic Client Registration). Где-то я такое видел до этого, но не сталкивался. Поэтому пошел быстренько изучить, чтобы рассказать вам.

Начнем со статической регистрации. Обычно мы создаем OAuth-клиента вручную - идём в консоль разработчика, создаём приложение, указываем redirect_uri и другие параметры, а после - получаем client_id и client_secret. Эти креды мы можем использовать чтобы обменять пользовательский код (по authorization code flow) на токен. Вроде все просто и понятно.

А теперь - динамическая регистрация. Это когда клиент может сам себя зарегистрировать через API oauth сервера. То есть вместо того, чтобы идти в админку и создавать приложение, ты просто отправляешь POST-запрос на специальный url, описываешь параметры (редиректы, типы грантов, скопы и т.д.), а сервер возвращает тебе client_id, а иногда и client_secret.

Где взять этот url для регистрации и вообще понять поддерживает ли сервер этот стандарт? Оно описывается в http://.../.well-known/openid-configuration - параметры конфигурации openid, по которым клиент может получить все необходимые данные. Внутри есть параметр - registration_endpoint, который и указывает url, на котором можно зарегистрировать клиентов.

В общем это все подробно описано в RFC 7591. Есть даже надстройка — RFC 7592 — которая описывает, как клиент может обновлять или удалять свою регистрацию.

Теперь к вопросу нафига это нужно - ведь живем же сейчас и все отлично. Это конечно да. Но вот проблема в том, что клиент и oauth сервер знают друг о друге заранее. Пример. У вас есть мобильное приложение Spotify в appstore. Вы его скачали и внутри нажали кнопку Войти через Google. В Spotify зашит client_id, который они получили от гугла перед публикацией приложения. Собственно и все - все друг о друге знают и все отлично.

А теперь представим себе клиента для LLM, который так же находится в AppStore. Вы его скачиваете и точно так же входите через гугл - все работает по предыдущей схеме. Но дальше, вы хотите подключить MCP сервер, который ничего не знает про вашего клиента, а ваш клиент ничего не знает про него. Да и невозможно будет заранее разработчику LLM клиента зарегистрироваться во всех MCP серверах мира. И именно в этот момент и нужна динамическая рагистрация. Ваш клиент сначала сам регистрируется на oAuth провайдере, который обслуживает данный MCP (получает client_id), а уже после этого он может запустить стандартный OAuth flow. В рамках этого flow пользователь сможет спокойно залогиниться.

В общем полезная и нужная штука получается.
👍30🔥146🤯3😁1
Разбирали тут на вебчике service discovery у prometheusа - в целом как работает, зачем нужен и тд. Я показывал как можно использовать kubernetes_sd_configs, который позволяет собирать таргеты через Kubernetes API.

Я аж всплакнул если честно. Ну как же эта схема выглядит красиво. Вы просто настраиваете kubernetes_sd_configs:


scrape_configs:
# Задача для обнаружения подов
- job_name: 'kubernetes-pods'

# Конфигурация обнаружения сервисов Kubernetes
kubernetes_sd_configs:
- role: pod
# Конфигурация перемаркировки (Relabeling)
relabel_configs:
# Проверяем аннотацию prometheus.io/scrape
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: true


И все! Остается только добавить аннотации на нужные поды 'prometheus.io/scrape: true' и все готово. Ну да, конечно - если промик запущен во вне, то надо еще api_server указать и token. И убедиться, что промик увидит ваши поды во внутренней сети кубера. Но если запускать внутри кубера, то никаких токенов настраивать не надо - промик будет использовать токен сервисного аккаунта, который ему подкинет кубер.

Но просто зацените схему. Prometheus стартует, подрубается к апи, вытаскивает все поды, фильтрует нужные по relabel_configs и начинает мониторить свои таргеты. Просто и красиво.

Kube-Prometheus-Stack добавляет некоторую обвязку к этому делу. Ну точнее Prometheus Operator, который в него входит. добавляет кастомные ресурсы - PodMonitor, ServiceMonitor и тд, которые вы можете использовать для настройки Prometheus. Например, вы создаете отдельный ресурс PodMonitor примерно такого вида:


apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: app
spec:
selector:
matchLabels:
app: app
podMetricsEndpoints:
- port: metrics
path: /metrics
interval: 30s
scrapeTimeout: 10s


Что происходит дальше. Когда вы добавляете PodMonitor из примера выше, Prometheus Operator видит это и генерируюет новую конфигурацию для Prometheus, в которой указываются kubernetes_sd_configs, relabel_configs и другие параметры. После этого он обновляет соответствующий ConfigMap. Дальше в дело вступает Sidecar config-reloader, который запущен в поде с prometheus сервером. Он видит обновление конфига и делает POST /reload на prometheus, чтобы тот перечитал конфигурацию.

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

Но это в общем я так - ностальгирую. Еще, кстати, откопал интересную штуку, которую как-то упустил - Agent Mode в Prometheus. В следующем посте расскажу.
🔥37👍235🐳2👏1🗿1
Рассказывал тут про Thanos и наткнулся на фичу для remote-write протокола в Clickhouse. Не спрашивайте как наткнулся. Случайно 🙂

Суть такая: у ClickHouse есть встроенные хендлеры для протокола Prometheus remote-write и remote-read. То есть промик может писать метрики прямо в ClickHouse, а при запросе старых данных — читать их обратно.

Включается это в конфиге ClickHouse примерно так:


<prometheus>
<port>9363</port>
<handlers>
<remote_write>
<url>/write</url>
<handler>
<type>remote_write</type>
<database>default</database>
<table>metrics</table>
</handler>
</remote_write>
<remote_read>
<url>/read</url>
<handler>
<type>remote_read</type>
<database>default</database>
<table>metrics</table>
</handler>
</remote_read>
</handlers>
</prometheus>


Подробнее вот тут - https://clickhouse.com/docs/interfaces/prometheus#remote-write.

И дальше в Prometheus надо накинуть эти настройки:


remote_write:
- url: http://host:9363/write
basic_auth:
username: user
password: pass
remote_read:
- url: http://host:9363/read
basic_auth:
username: user
password: pass


И все! Долгосрочное хранение в вашем промике у вас в карман - осталось только создать таблицу. А если еще учесть, что кликхаус позволяет сбрасывать холодные партиции на S3 (storage policies) (https://clickhouse.com/docs/integrations/s3#creating-a-storage-policy), то получается совсем хорошо.

Как работает эта штука? Prometheus отправляет все собранные данные по http на remote_write endpoint, а clickhouse складывает их в указанную таблицу. Когда клиент запрашивает у Prometheus период которого локально уже нет, Prometheus сам лезет через remote_read endpoint в clickhouse, а clickhouse возвращает исторические данные. Даже графану перенастраивать не придется.

К сожалению, такая схема никак не решает вопрос отказоустойчивости - тут все равно нужен Thanos. Ну или Victoria Metrics сразу. Но это решение явно более красивое, чем то, которое я использовал лет 7 назад с внешним сервером на golang.
🔥34👍204🙏1🤡1
Всем привет!

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

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

Ну и в общем я точно так же поступил в начале этого года, когда на одном из созвонов мне сказали, что у Yandex Cloud оказывается есть экзамен по облаку. С созвона я вышел сразу. И пошел записываться на сдачу. Я много и часто работаю с облаком, поэтому для подготовки я пробежался по документации, а в частности перечитал все разделы "Концепции", которые там были. Ну и удача мне улыбнулась и я успешно сдал экзамен (именно поэтому я люблю экзамены - чисто когда сдаю).

После этого мы еще запилили совместные вебинары с Яндексом по подготовке к сертификации и нараздавали промо кодов на сдачу. В общем прикольно получилось - мне понравилось.

Экзамен был большой. Реально большой. Там были основы облаков - типа стандартные базовые сервисы - VPC, Compute, IAM и так далее. Там были вопросы ближе к DevOps части - контейнеризация, кубернетесы, registry и так далее. Там было много вопросов про данные - postgresql, opensearch, redis и так далее. И даже serverless с AI не обошли стороной. Короче тем для изучения было достаточно много. Такой универсальный солдат получается.

И вот, ребята из клауда переработали экзамен и выкатывают обновленную версию, ориентированную чисто на DevOps инженеров. Список тем стал более компактным и нацеленным именно на девопсов. Вот тут можно глянуть список компетенций, которые подтверждает экзамен. Я, кстати, чуть-чуть поучаствовал в создании данной сертификации (совсем чуть чуть). Так что мне вдвойне приятно видеть эту новую версию.

И самое главное! Сейчас Yandex проводит пилотные экзамены, которые проходят абсолютно бесплатно! Больше информации можно найти здесь

Рекомендую всем, кто готов принять участие - скорее записываться. Для участия обязательно заполните вот эту форму (берут не всех).

Всем желаю удачи в прохождении! Закидывайте серты, которые вы получали 🙂
🔥19👍43🐳3
👍30🔥176👨‍💻1
День падений. Сегодня не работает Cloudflare. А еще говорят, что понедельник день тяжелый!

На самом деле это второе крупное падение за последнее время. В прошлый раз интернет положил AWS. У них там были хитрые проблемы с гонками, связанные с их внутренними DNS записями в Route53. Подробнее можно почитать вот здесь - https://aws.amazon.com/message/101925/.

Судя по Status Page от Cloudflare (https://www.cloudflarestatus.com/) у них возникли проблемы с WARP сервисом и его даже пришлось отключать в некоторых регионах. Суть сервиса простая - он позволяет защитить клиентские устройства с помощью VPN. Вы ставите WARP клиента, он подрубается к ближайшему дата центру Cloudflare и направляет весь трафик через него. Дальше вы через админку CF можете управлять правилами доступа и фильтрацией контента. Подробнее тут - https://developers.cloudflare.com/cloudflare-one/team-and-resources/devices/warp/.

Пока конечно не очень понятно как это связано с глобальным падением если честно. Возможно в деле замешан сервис фильтрации и просто из-за WARP на него пошла большая нагрузка. А возможно еще был затронут Zero Trust. С его помощью можно строить красивые сетевые схемы. В чем суть? Представьте что у вас есть Kubernetes или какой-то закрытый контур. И вы хотите пустить на него трафик из вне. Раньше приходилось получать внешний айпишник, роутить его на свой балансировщик и прокидывать запросы. Даже если вы в облаке - вы все равно создаете какой-нибудь Network Load Balancer и пропускаете трафик.

С Zero Trust все работает наоборот. Вы просто ставите в свой кубер или в свою инфраструктуру cloudflare tunnel (https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/), который подключается к ближайшему дата центру Cloudflare и дальше вы можете роутить трафик через cloudflare на свои внутренние ресурсы. То есть у вас может не быть никаких внешних адресов или чего-то такого. Cloudflare сам примет запрос из вне, затерминирует TLS и дальше по этому внутреннему туннелю отправит запрос к вам. Такой VPN наоборот.

И схема реально выглядела красиво. Ставим какой-нибудь контроллер ingress / gateway api в Kubernetes. Так же ставим cloudflared tunnel (можно через оператор - https://github.com/adyanth/cloudflare-operator). И в cloudflare настраиваем какую-нибудь запись в DNS: "www CNAME <uuid>.cfargotunnel.com". И все! Теперь пользователь, при обращении к www попадет на cloudflare, а тот в свою очередь направит трафик через cloudflare туннль на ваш контроллер в kubernetes. Никаких тебе cert-managerов.

Короче не знаю что там происходит с Cloudflare, но зато я вам рассказал немного про Zero Trust! И ждем итогового постмортема - будет интересно.
👍45🔥15🌚6🫡4