# Kubernetes туннель

к сведению

Доступно только по [подписке](https://tuna.am/#pricing).

## Обзор

Kubernetes туннель даёт коллеге или подрядчику временный доступ к вашему кластеру через обычный `kubectl`: без VPN, без открытия API-сервера наружу и без передачи ваших учётных данных.

Клиент читает локальный kubeconfig, поднимает reverse-proxy к API-серверу и HTTP-туннель к нему. Гость получает одноразовую ссылку на готовый kubeconfig. В нём адрес туннеля с валидным TLS-сертификатом и гостевой токен. Прокси проверяет этот токен и подставляет вместо него ваши настоящие учётные данные, поэтому они не покидают вашу машину.

## Быстрый старт

```shell
tuna kubernetes --context=staging --service-account=shop/debug --ttl=4h

```

Клиент откроет терминальный интерфейс: в шапке видны сервисный аккаунт, namespace, ограничения и срок действия, ниже — лента запросов гостя. Инструкция для гостя:

```shell
curl -sfO https://<адрес туннеля>/tuna/<секрет>/kubeconfig.yaml
KUBECONFIG=./kubeconfig.yaml kubectl get pods

```

Через туннель работают `get`, `list`, `watch`, `logs`, `exec` (включая stdin), `port-forward`, `pods/proxy` и запись: `scale`, `create`, `delete`. Запросы гостя видны в [инспекторе](https://tuna.am/docs/tunnels/http/inspect.md) как обычные HTTP-запросы.

У команды есть короткий алиас `tuna k8s`.

## Примеры

примечание

Все актуальные флаги, подсказки и примеры можно посмотреть вызвав справку:

```shell
tuna kubernetes --help

```

Почти для всех флагов есть аналогичные [переменные окружения](https://tuna.am/docs/guides/environment-variables.md).

### Kubeconfig и контекст

Клиент берёт один файл kubeconfig: из флага `--kubeconfig`, иначе из `$KUBECONFIG`, иначе `~/.kube/config`. Список файлов через `:` в `$KUBECONFIG` не поддерживается. Контекст по умолчанию — `current-context`:

```shell
tuna kubernetes --kubeconfig=./staging.yaml --context=staging

```

Поддерживаются клиентский сертификат, `token`, `tokenFile` и exec-плагины, которые выдают токен. Exec-плагины, выдающие сертификат, не поддерживаются. С `auth-provider` клиент завершится с ошибкой.

### Сервисный аккаунт

Без `--service-account` гость работает с **вашими** правами в кластере, клиент предупредит об этом. Создайте для гостя сервисный аккаунт с минимальными правами по RBAC и передайте его во флаге:

```shell
tuna kubernetes --service-account=shop/debug

```

Формат — `[namespace/]name`. Без namespace берётся namespace контекста, а если его нет — `default`. Токен сервисного аккаунта клиент выпускает сам через TokenRequest API и продлевает каждый час.

### Ограничения доступа

Ограничения ниже работают поверх RBAC и только сужают права, но не расширяют их.

| Флаг                                 | Что делает                                                                                                                                         |
| ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--namespace=shop`                   | Только один namespace. Кластерные ресурсы (`nodes`, список namespaces), `-A` и другие namespace запрещены. Сам namespace доступен только на чтение |
| `--read-only`                        | Только чтение (`GET`, `HEAD`, `OPTIONS`). Запрещены `exec`, `attach` и `port-forward`; логи и `pods/proxy` доступны                                |
| `--no-delete`                        | Запрещено удаление, остальная запись разрешена                                                                                                     |
| `--deny-resource=secrets,configmaps` | Запрещены указанные ресурсы, имя сравнивается без учёта регистра                                                                                   |
| `--deny-subresource=exec,attach`     | Запрещены субресурсы: `exec`, `attach`, `portforward`, `log`, `proxy`                                                                              |

С `--namespace` и `--read-only` не работают `kubectl auth whoami` и `kubectl auth can-i`: это POST-запросы к кластерным ресурсам.

Заголовки `Impersonate-*` прокси срезает, поэтому `kubectl --as` через туннель не работает.

### Пресеты

`--preset` включает готовый набор ограничений:

| Пресет     | Что разрешено                                                                           |
| ---------- | --------------------------------------------------------------------------------------- |
| `view`     | Только чтение, без `secrets`, без `exec`, `attach`, `portforward` и `proxy`             |
| `observer` | Только чтение подов и их логов, без `exec`, `attach`, `portforward` и `proxy`           |
| `debug`    | Всё, кроме удаления. `secrets` не скрыты: через `exec` до них всё равно можно добраться |
| `open`     | Без дополнительных ограничений                                                          |

```shell
tuna kubernetes --preset=debug --namespace=shop

```

Пресет и флаги суммируются и не ослабляют друг друга: `--preset=debug --read-only` даёт только чтение.

В пресете `observer` разрешены только ресурсы `pods`, поэтому `kubectl logs deploy/api` не сработает, нужно указывать под: `kubectl logs pod/api-7c9f8d6b5-x2k4q`.

### Срок действия и число скачиваний

```shell
tuna kubernetes --ttl=4h --download-limit=1

```

`--ttl` задаёт срок действия доступа, по умолчанию `0` — бессрочно. После истечения `kubectl` получит ответ `this access has expired, ask for a new link`.

`--download-limit` ограничивает число скачиваний kubeconfig, по умолчанию `1`, `0` снимает лимит. Сверх лимита ссылка отвечает `410`, а вы увидите в логе предупреждение о попытке скачивания. Если гость получил `410` при первом же скачивании, значит, конфиг до него забрал кто-то другой: остановите туннель и выдайте новую ссылку.

### Постоянный адрес

При переподключении с новым адресом клиент выпускает новый токен и новую ссылку, а срок действия и лимит скачиваний отсчитываются заново. Чтобы адрес не менялся, используйте зарезервированный поддомен или свой домен:

```shell
tuna kubernetes --subdomain=k8s-staging
tuna kubernetes --domain=k8s.example.com

```

Гостевые токены живут только в памяти процесса: после перезапуска клиента старые ссылки и kubeconfig перестают работать.

### С указанием токена

Можно указать специфичный токен через флаг `--token` или переменную окружения `TUNA_TOKEN`. Переопределение происходит в соответствии с политикой [очерёдности конфигурации](https://tuna.am/docs/guides/config-ordering.md).

```shell
tuna kubernetes --token=tt_***

```

### С указанием региона для подключения

Можно указать специфичный [регион](https://tuna.am/docs/tunnels/guides/locations.md) через флаг `--location`/`-l` или переменную окружения `TUNA_LOCATION`. Переопределение происходит в соответствии с политикой [очерёдности конфигурации](https://tuna.am/docs/guides/config-ordering.md).

```shell
tuna kubernetes --location=nl

```

### Запуск как сервис

Туннель можно запускать [сервисом](https://tuna.am/docs/tunnels/guides/service.md) или через [множественный запуск](https://tuna.am/docs/tunnels/guides/multi-tunnels.md):

```shell
tuna service install --name=k8s-staging -- tuna kubernetes --context=staging --service-account=shop/debug --subdomain=k8s-staging

```
