Хмельной Девопс


Гео и язык канала: Россия, Русский
Категория: Технологии


Будничный хаос и мрак при поддержке ИТ систем.
Канал об эксплуатации ИТ систем от действующего DevOps
Для фидбека и вопросов - @vasiliyozerov

Связанные каналы  |  Похожие каналы

Гео и язык канала
Россия, Русский
Категория
Технологии
Статистика
Фильтр публикаций


Репост из: 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/ (хоть и не читаю с суфлера, но все равно примерно оцениваю время)


Всем привет!

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

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

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

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

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

P.S. В списке идей для сценариев 48 пунктов 🙂


Небольшое дополнение к секретами, да и вообще в целом к безопасности.

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

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

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

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

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

Всем хороших выходных и отдельное спасибо Дмитрию за комментарий 🙂


Ох, читал тут статейку про 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: , которые заменит vault plugin. Взять данные для подстановки vault plugin может из sops файла, из kms или еще откуда-то. В общем удобно 🙂

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

С ним бы мог поспорить только kubeseal, но тот не позволяет редактировать секреты локально. То есть вы можете их только зашифровать. Расшифровывать нельзя. И это реально неудобно - вам каждый раз придется пересоздавать секрет. А если учесть что в секрете может быть несколько переменных, а вам надо поменять только одну - то привет пока приехали.


Если вы используете 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 🙂


Если вы, как и я, апгрейдите кубернетес через несколько версий, то в один прекрасный момент 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) - она ищет удаленные апишки в прошлом релизе и исправляет их на правильные. Возможно кому-то пригодится.


Так, в последний раз я задал задачку и ушел в неизвестность. Исправляюсь.

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


ssh -D 127.0.0.1:9999
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, но у меня не получилось - валю на свои кривые ручки 🙂

Всем хорошей ночки!


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

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

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

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

P.S. Вторую виртуалку зарубежную использовать необязательно - если знаете способ как без нее, но мега быстро - закидывайте.


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

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

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

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

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

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

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

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

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

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


В общем, всем wireguard, народ!


jsx
# Добавляем клиента, указывая его публичный ключ и какие сети / айпишники находятся за ним. Логика такая же - все сети, указанные в allowed-ips будут маршрутизироваться сервером в данный туннель
wg set wg0 peer allowed-ips 10.8.0.5/32


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

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

peer:
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 и клиент переподключился без проблем.


Вообще очень странно, что я ничего не писал про 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


Собственно на этом все - всем хорошей ночи! 🙂


# 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"


Containerd - runtime для запуска контейнеров, который используется, например docker’ом. Также containerd предоставляет Container Runtime Interface, который использует Kubelet для запуска контейнеров. Часто встречается ситуация, когда на хосте установлен только containerd и было бы неплохо иметь возможность посмотреть что же запущено внутри и как оно работает.

Вообще, containerd представляет 3 утилиты для собственного управления:

- ctr - утилита входит в поставку containerd и позволяет получать отдебажить containerd
- netdctl - утилита с человеческим лицом для управления containerd - [https://github.com/containerd/nerdctl](https://github.com/containerd/nerdctl)
- crictl - утилита для дебага CRI совместимых runtime - [https://github.com/kubernetes-sigs/cri-tools/blob/master/docs/crictl.md](https://github.com/kubernetes-sigs/cri-tools/blob/master/docs/crictl.md)

Мы же сегодня немного посмотрим на ctr:

1. У containerd есть namespaces, по которым можно разделять образы, запущенные контейнеры и так далее, вывести список namespaces можно так:


# ctr ns list
NAME LABELS
default
k8s.io


Как видно, kubelet создает свой собственный namespace k8s.io, в котором запускаются все контейнеры.

2. Мы можем посмотреть на список образов контейнеров в том или ином namespace:


# ctr -n k8s.io images ls | head -2
REF TYPE DIGEST SIZE PLATFORMS LABELS
docker.io/library/alpine:latest application/vnd.docker.distribution.manifest.list.v2+json sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 3.2 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x io.cri-containerd.image=managed


3. Так же мы можем скачать нужный нам образ:


# ctr -n default image pull docker.io/library/postgres:14
docker.io/library/postgres:14: resolved |++++++++++++++++++++++++++++++++++++++|
index-sha256:cfd6203fc331bdf87ddf8c0ae91d9a6a6eacd5f2037c8178b644f1bbc369fafe:

... skipped ...
elapsed: 5.7 s total: 101.6 (17.8 MiB/s)


Это часто бывает нужно для проверки возможности скачивания образов из приватных репозиториев - проверить что containerd принимает самоподписанный сертификат и так далее. К слову, аутентификацию в приватном registry можно настроить на уровне containerd и тогда не придется пихать всюду image pull secrets 🙂

4. Помимо этого вы можете подмонтировать образ контейнера в какую-нибудь директорию без запуска:


# ctr image mount docker.io/library/postgres:14 /mnt/
sha256:e242dad2cf72e07da948e090eb0f4cfd2a5e2820336ffc952afef4500a7ad117
/mnt/

[root@gis-s-app01 admin]# ls -la /mnt/
total 92
drwxr-xr-x. 1 root root 4096 Nov 30 21:10 .
dr-xr-xr-x. 18 root root 4096 Nov 27 21:06 ..
drwxr-xr-x. 2 root root 4096 Nov 14 03:00 bin
... skipped ...


5. Теперь самое главное! Контейнеры и задачи. Containerd разделяет эти две сущности. Суть в чем - контейнер (container) - это объект, который описывает окружение, что должно быть запущено и так далее. А вот задача (task) - это непосредственно процесс, который запускается в контейнере. Давайте посмотрим какие контейнеры у нас есть:




Возвращаемся к Kerberos!

В прошлый раз мы обсудили теорию, а сейчас попробуем поднять свой собственный KDC. В качестве реализации можно использовать MIT Kerberos или Heimdal. Я буду приводить примеры на базе MIT Kerberos, но если где-то в статьях вы увидите Heimdal больших проблем возникнуть не должно - поскольку вы уже знаете механизм работы протокола. Также вы уже можете понять как windows active directory аутентифицирует клиентов в своих сервисах.

Итак, какой кейс мы будем делать? Давайте попробуем реализовать вход по ssh через kerberos тикеты.

У нас будет три сервера - kdc.krb.kis.im - на нем будет располагаться наш KDC, включающий в себя AS (authentication server) и TGS (ticket granting server). Второй хост - ssh.krb.kis.im - на нем запустим sshd с аутентификацией через kerberos. Ну и наш клиент - client.krb.kis.im, на котором мы будем получать kerberos тикеты и проходить аутентификацию на ssh.krb.kis.im.

Помимо этого домен Kerberos у нас будет KIS.IM - все пользователи и сервисы будут создаваться в этом домене.

В этот раз я решил не писать заметку в самое телеге, закинуть в виде pdf, а то телега бьет сообщения и получается не очень красиво. Приятного чтения!




Отлично, с теорией разобрались, в следующей заметке будем настраивать SSH!


3. Клиент обращается к TGS (Ticket Granting Server) со своим TGT тикетом, полученным на предыдущем этапе и запрашивает тикет для сервиса Server. TGS убеждается что TGT пользователя валиден и создает тикет для сервиса Server, который шифруется ключом Server (то есть пользователь не сможет его расшифровать).

4. Клиент передает серверу тикет для него. Server с помощью своего ключа расшифровывает тикет и тем самым убеждается, что тикет был выдан KDC, поскольку секретный ключ сервера есть только у самого сервера и у KDC. После проверки тикета сервис разрешает пользователю доступ.

Примерно вот так и работает Kerberos. Естественно я пытался описать весь процесс верхнеуровнево и опустил множество деталей (и возможно где-то накосячил). Но основные моменты я постарался подсветить:

1. Клиент получает TGT тикет от AS (Authentication Server). При этом пароль пользователя не передается на сервер.
2. После получения TGT клиент меняет его на тикет для нужного сервера / сервиса через TGS (Ticket Granting Server). При этом TGS шифрует тикет для сервиса секретным ключом этого сервиса.
3. Клиент отправляет тикет сервису / серверу, который расшифровывает его своим секретным ключом. Отсюда следует вывод, что на сервере вам необходимо как-то указать его секретный ключ, который вы создали в KDC.

Показано 20 последних публикаций.