LINUX.ORG.RU

Как правильно организовать сетевой доступ к Kubernetes-кластеру

 , , ,


0

1

Планирую создание кластера. Столкнулся с тем, что не могу решить, как правильно организовать доступ в сетевом плане. Всё делаю сам, поэтому обладаю некоторой гибкостью.

У провайдера OpenStack. Для виртуальных машин выделяю отдельную подсеть. Для контрольных серверов создаю выделенный балансировщик нагрузки, создаю 3 контрольных сервера, у балансировщика нагрузки фиксированный IP, он распределяет запросы по этим контрольным серверам. Ну и сколько нужно рабочих серверов. Такая конфигурация даёт некоторую доступность в случае небольших аварий или обслуживания серверов, ну насколько это можно сделать в текущих условиях. Сразу скажу, что использую инкапсулированную сеть для pod-ов, без инкапсуляции мне не удалось настроить, bgp-анонсы роутер опенстаковской сети не принимает. То бишь из пода я могу достучаться до сервера, а вот из сервера до пода уже нет.

Собственно стоят следующие задачи, которые нужно решить:

  1. Доступ к этому балансировщику нагрузки, чтобы kubectl с локального компьютера использовать.

  2. Доступ непосредственно к серверам по ssh. Во-первых, конечно, начальный, чтобы настроить всё, ну и потом может быть нужда.

  3. В кластере будут работать ряд внутренних сервисы с единой авторизацией через работающий там же Keycloak, включая авторизацию для kubectl. Внутренние сервисы включают в себя gitlab, grafana, какие-то ещё средства мониторинга и управления вроде kubernetes dashboard. Не все пользователи технически подкованы, чтобы прокидывать туннели через kubectl proxy, поэтому нужен более простой доступ ко всем этим сервисам.

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

На текущий момент я вижу и частично опробовал три варианта.

Вариант один - всё публичное. Каждому серверу даём публичный IP помимо внутреннего (ну или одному даём и потом через ssh proxy jump ходим). Балансировщику нагрузки даём публичный IP. В итоге всё торчит нужными портами в интернет. Ну понятно, что фаерволом ненужное закрываем. kubectl просто работает.

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

Вариант два - создаём один бастион-сервер. На нём публичный адрес, ssh и wireguard. Далее на все внутренние серверы ходим либо через proxyjump, либо через wireguard. Обычные пользователи настраивают себе wireguard клиента и одним нажатием подключаются во внутреннюю сеть. А там уже или через колхозный балансировщик нагрузки на haproxy на том же бастионе (не смотрящий наружу), или через провайдерский балансировщик нагрузки получают доступ к внутренним сервисам, выставленным через ingress-ы.

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

Вариант три - создаём в кластере wireguard-сервер. Мне этот вариант сразу понравился больше всего. По сути запускаем pod, в котором запускается wireguard, настрен ip forwarding и masquerade. Имеем доступность - если какие-то проблемы, под перезапустится на другом сервере. Имеем доступ прям к внутренней сети кластера - напрямую можно подключаться хоть к любому поду, хоть к любому сервису. Тут тоже можно сэкономить на балансировщике нагрузки для внутренних сервисов: в кубернетесе любой сервис это балансировщик нагрузки.

Но есть некоторые проблемы. Во-первых если делать не думая, то для этого пода нужен привилегированный режим. А это плохо. Если делать думая, то поду надо выдать capability NET_ADMIN, без неё wireguard настраивать не получается, я точно не знаю, насколько это плохо. А также нужно в кластере добавить unsafe sysctl net.ipv4.ip_forward, чтобы можно было его проставить для пода, тут тоже у меня нет чёткого понимания, насколько это плохо, но в любом случае это лишние телодвижения при создании кластера.

Далее - доступ к сети подов, как уже писал, чуть подумав я пришел к выводу, что не такая уж и хорошая эта идея. Хотя это решается, можно делат nat только на выбранные адреса, а не на все.

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

И самое неприятное на мой взгляд - то, что судя по гайдам никто так не делает. Я собрал свой образ, сам набил все шишки. Это было полезно в любом случае, но я не люблю идти какими-то непроторёнными путями.

В общем на текущий момент я склоняюсь к варианту с отдельным бастион-сервером. Это кажется наиболее неинвазивным вариантом, если можно так выразиться и в целом решает основные задачи вроде как.

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

★★★

Последнее исправление: vbr (всего исправлений: 1)

Ответ на: комментарий от ugoday

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

Репозиторий git тоже будет в кластере, btw. Ну и некоторые другие внутренние сервисы. Так что вопрос в любом случае стоит.

vbr ★★★
() автор топика
Ответ на: комментарий от vbr

к которому он может цепляться, например, своим локально-запущенным фронтэндом, а это подразумевает полный сетевой доступ к сервисам в нужном namespace-е.

На самом деле вам нужен https://kubernetes.io/docs/concepts/services-networking/ingress/, ну https://kubernetes.io/docs/tasks/access-application-cluster/port-forward-access-application-cluster/ на крайний случай.

ugoday ★★★★★
()

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

George
()