> Markdown-версия страницы https://tuna.am/blog/kubernetes-operator/. Оглавление документации — [llms.txt](https://tuna.am/llms.txt), весь текст одним файлом — [llms-full.txt](https://tuna.am/llms-full.txt). Markdown-версия есть у любой страницы: добавьте `.md` к адресу без слеша на конце.

[Блог](https://tuna.am/blog.md)|[Новые возможности](https://tuna.am/blog/tags/features)

# Kubernetes-оператор Tuna — туннели, домены и Ingress ресурсами кластера

6 ноября · 4 мин

Чтобы открыть сервис из кластера наружу, обычно нужны LoadBalancer, публичный IP и ingress-контроллер. В облаке за это платят, а у многих кластеров публичного адреса нет вовсе: закрытый контур, kind на ноутбуке, k3s на Raspberry Pi за роутером провайдера.

Для таких кластеров мы сделали Kubernetes-оператор. Ставите его Helm-чартом, пишете обычный Ingress с классом `tuna` — и сервис доступен из интернета. Кластер ходит к Tuna только исходящими соединениями, входящие порты открывать не нужно.

![Анимация: оператор в кластере открывает исходящий туннель до ноды Tuna; запрос на my-app.a.2na.am/api приходит через туннель и уходит в Service api, запрос на корень — в Service web](/blog/img/2026-11-06-kubernetes-operator/how.svg)

Кластер сам открывает туннель до Tuna, а оператор разводит запросы по путям Ingress.

> **Коротко**
>
> * **Настоящий Ingress-контроллер.** Любой Helm-чарт, который умеет создавать Ingress, публикуется через Tuna одной строкой в values.
> * **Свой ключ у каждого туннеля.** Он только запускает туннели, не ходит в API и отзывается вместе с ресурсом. Ключ самого оператора туннели не запускает.
> * **Домены и порты — манифестами.** Поддомены, свои домены и TCP-порты резервируются ресурсами рядом с приложением и живут в git.
> * Установка, настройка ключа и все ресурсы — в [документации](https://tuna.am/docs/tunnels/kubernetes-operator.md).

## Было: под с `tuna http`

Опубликовать кластер через Tuna можно было и раньше: запустить [`tuna http` в поде](https://tuna.am/docs/tunnels/examples/kubernetes.md). Так один из наших пользователей выводил наружу ingress-nginx:

```yaml
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](https://github.com/stefanprodan/podinfo) на зарезервированном поддомене:

values.yaml

```yaml
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-ключ](https://my.tuna.am/api_keys?lang=ru) для оператора и поставьте чарт:

```shell
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`, — в [документации](https://tuna.am/docs/tunnels/kubernetes-operator.md).

## Что дальше

Это первая версия: API `v1alpha1`, поля ресурсов ещё могут поменяться. Трафик пока идёт через под оператора, а при его обновлении туннели переподключаются.

В ближайших планах:

* **Туннели прямо из Service.** Service типа LoadBalancer с `loadBalancerClass: tuna` получит туннель сам, без Ingress и без ресурса `Tunnel`.
* **Синхронизация секретов.** Оператор будет переносить [секреты Tuna](https://tuna.am/docs/secrets.md) в Secret кластера и обновлять их при изменениях.
* **Маршрутизация на нодах Tuna.** Правила Ingress переедут на наши ноды, трафик перестанет идти через под оператора, а следом появится Gateway API.

Не хватает какой-то возможности или оператор не заработал — напишите в [поддержку](https://tuna.am/docs/support.md).

## Оставьте отзыв

Если вам нравится пользоваться Tuna, или наоборот вы недовольны чем-либо, то пожалуйста [оставьте отзыв](https://my.tuna.am/?show_feedback=1&lang=ru).

![](/blog/img/2024-08-22/feedback.gif)

## Новости

Анонсы новых функций и статей публикуем в [Telegram-канале](https://t.me/tuna_am). Подписывайтесь, чтобы ничего не пропустить.

## Помощь

Мы ценим наших пользователей и детально изучаем все обращения, если у вас возникли проблемы с tuna – обязательно свяжитесь с нами одним из способов:

* [Электронная почта](mailto:info@tuna.am)
* [Telegram сообщество](https://telegram.me/+Kgbtt0_gJwI5ZmEy)

Категории: [Новые возможности](https://tuna.am/blog/tags/features)

[старее →🕸️ Tuna Mesh в бете — частная сеть для устройств](https://tuna.am/blog/tuna-mesh-beta.md)
