Kubernetes-оператор Tuna — туннели, домены и Ingress ресурсами кластера
Чтобы открыть сервис из кластера наружу, обычно нужны LoadBalancer, публичный IP и ingress-контроллер. В облаке за это платят, а у многих кластеров публичного адреса нет вовсе: закрытый контур, kind на ноутбуке, k3s на Raspberry Pi за роутером провайдера.
Для таких кластеров мы сделали Kubernetes-оператор. Ставите его Helm-чартом, пишете обычный Ingress с классом tuna — и сервис доступен из интернета. Кластер ходит к Tuna только исходящими соединениями, входящие порты открывать не нужно.
- Настоящий Ingress-контроллер. Любой Helm-чарт, который умеет создавать Ingress, публикуется через Tuna одной строкой в values.
- Свой ключ у каждого туннеля. Он только запускает туннели, не ходит в API и отзывается вместе с ресурсом. Ключ самого оператора туннели не запускает.
- Домены и порты — манифестами. Поддомены, свои домены и TCP-порты резервируются ресурсами рядом с приложением и живут в git.
- Установка, настройка ключа и все ресурсы — в документации.
Было: под с tuna http
Опубликовать кластер через Tuna можно было и раньше: запустить tuna http в поде. Так один из наших пользователей выводил наружу ingress-nginx:
spec:
replicas: 1
strategy: {type: Recreate}
template:
spec:
containers:
- name: tuna
image: yuccastream/tuna:latest
args: [http, ingress-nginx-controller.ingress-nginx.svc.cluster.local:80, --inspect=false]
env:
- {name: TUNA_TOKEN, valueFrom: {secretKeyRef: {name: app-tuna, key: TUNA_TOKEN}}}
- {name: TUNA_SUBDOMAIN, valueFrom: {secretKeyRef: {name: app-tuna, key: TUNA_SUBDOMAIN}}}
Работает, но всё собрано руками: поддомен зарезервирован в кабинете, Secret создан вручную, перед туннелем стоит отдельный ingress-nginx. А TUNA_TOKEN — токен всего аккаунта: утёк из Secret — и с ним можно поднять сколько угодно туннелей на любые адреса.
Стало: обычный Ingress
С оператором Tuna — ещё один ingress-контроллер в кластере. Чарту не нужно ничего знать о Tuna: достаточно указать класс. Вот podinfo на зарезервированном поддомене:
ingress:
enabled: true
className: tuna
hosts:
- host: podinfo.a.2na.am
paths:
- path: /
pathType: Prefix
Пути внутри одного Ingress разводятся по разным Service: /api — на бэкенд, / — на фронтенд. На каждый хост оператор поднимает один туннель, а новые пути и бэкенды применяет без переподключения. Если в чарте нельзя задать класс, tuna можно сделать классом по умолчанию.
Сам поддомен тоже описывается манифестом — ресурсом Domain рядом с приложением. Так же резервируются свои домены и TCP-порты, а для одиночного сервиса есть короткий ресурс Tunnel без Ingress.
Ключ на каждый туннель
Главное, что мы закладывали в оператор, — чтобы утечка одного секрета не открывала весь аккаунт.
- У каждого туннеля свой временный ключ. Он умеет только запускать туннель: один протокол, не больше одного туннеля одновременно, без доступа к API. Удалили ресурс — ключ отозван. Ключи ресурсов, удалённых, пока оператор не работал, отзываются автоматически.
- Ключ оператора туннели не запускает. Ему нужно только право записи в «Эндпоинты и домены»: резервировать адреса и выпускать ключи туннелям.
- Только свой namespace. Tunnel и Ingress публикуют лишь Service своего namespace. IP-адреса, внешние хосты и чужие namespace отклоняются, иначе право создать Ingress в одном namespace давало бы доступ ко всему, что видит под оператора.
- Поды без лишних прав. Непривилегированный пользователь, корневая ФС только для чтения, без capabilities.
Удобно для GitOps
Если кластером управляет Argo CD или Flux, оператор не мешает:
- домен или порт, который уже есть в аккаунте, подхватывается под управление, а не падает с ошибкой;
- с
reclaimPolicy: Retainрезервация переживает удаление ресурса — пересоздали кластер, а домен на месте; - резервацию, удалённую в кабинете вручную, оператор создаст снова.
Как попробовать
Создайте API-ключ для оператора и поставьте чарт:
helm repo add tuna https://code.tuna.am/api/packages/tuna/helm
helm install tuna-operator tuna/tuna-k8s-operator \
--namespace tuna-system --create-namespace \
--set credentials.apiKey=<API-ключ>
Какие права дать ключу, как поставить оператор через Nelm и где хранить ключ, кроме --set, — в документации.
Что дальше
Это первая версия: API v1alpha1, поля ресурсов ещё могут поменяться. Трафик пока идёт через под оператора, а при его обновлении туннели переподключаются.
В ближайших планах:
- Туннели прямо из Service. Service типа LoadBalancer с
loadBalancerClass: tunaполучит туннель сам, без Ingress и без ресурсаTunnel. - Синхронизация секретов. Оператор будет переносить секреты Tuna в Secret кластера и обновлять их при изменениях.
- Маршрутизация на нодах Tuna. Правила Ingress переедут на наши ноды, трафик перестанет идти через под оператора, а следом появится Gateway API.
Не хватает какой-то возможности или оператор не заработал — напишите в поддержку.
Оставьте отзыв
Если вам нравится пользоваться Tuna, или наоборот вы недовольны чем-либо, то пожалуйста оставьте отзыв.
Новости
Анонсы новых функций и статей публикуем в Telegram-канале. Подписывайтесь, чтобы ничего не пропустить.
Помощь
Мы ценим наших пользователей и детально изучаем все обращения, если у вас возникли проблемы с tuna – обязательно свяжитесь с нами одним из способов: