Привет, Хабр!
Недавно я столкнулся с задачей, требующей доступа к одному из сервисов внутри кластера Kubernetes. Работая над отладкой сложной микросервисной структуры, нужно было проверить работоспособность одного из компонентов, но доступ к нему был возможен только изнутри кластера. Я нашел подходящее решение — переадресация портов с помощью kubectl.
Переадресация портов — это процесс перенаправления сетевого трафика с одного порта на другой, что позволяет получать доступ к внутренним сервисам кластера Kubernetes из внешней сети.
Команда kubectl port-forward позволяет перенаправлять трафик с локального компьютера на определенный порт внутри пода
Рассмотрим подробней.
Работа команды kubectl port-forward
Команда kubectl port-forward позволяет устанавливать туннель между локальным портом и портом ресурса (пода, службы и т.д.) в кластере.
Общий синтаксис команды:
kubectl port-forward [resource-type]/[resource-name] [local-port]:[resource-port]
-
[resource-type]: тип ресурса (например, pod, svc). -
[resource-name]: имя ресурса. -
[local-port]: локальный порт на вашем компьютере. -
[resource-port]: порт на ресурсе Kubernetes.
Примеры использования:
Переадресация порта пода
kubectl port-forward pod/my-pod 8080:80
Здесь перенаправляем локальный порт 8080 на порт 80 пода с именем my-pod.
Переадресация порта службы
kubectl port-forward svc/my-service 8080:80
Пример перенаправляет локальный порт 8080 на порт 80 службы с именем my-
Когда задействована команда kubectl port-forward, происходит следующее:
-
Инициализация команды: пользователь вводит команду в терминале.
-
Аутентификация и авторизация: CLI связывается с API-сервером Kubernetes для аутентификации пользователя и проверки его прав доступа.
-
Получение информации о поде: CLI отправляет запрос на получение данных о целевом поде.
-
Установка сессии порт-форвардинга: CLI инициирует соединение с API-сервером для установления сессии порт-форвардинга.
-
Конфигурация iptables: Kubelet на узле, где запущен под, настраивает iptables для перенаправления трафика.
-
SPDY сессия для передачи данных: Данные передаются через WebSocket/SPDY соединение между локальной машиной и подом.
Пример установки соединения до передачи данных
Предположим, есть под с именем my-pod, который слушает на порту 80, и хочется перенаправить этот порт на локальный порт 8080:
kubectl port-forward pod/my-pod 8080:80
Пользователь вводит команду kubectl port-forward pod/my-pod 8080:80. CLI начинает выполнение команды.
CLI отправляет запрос на API-сервер Kubernetes для аутентификации пользователя. Этот запрос включает Bearer Token для проверки подлинности пользователя. API-сервер проверяет токен и авторизует доступ к указанному поду.
После успешной аутентификации CLI отправляет GET-запрос на API-сервер для получения информации о целевом поде. Сервер возвращает необходимые данные, такие как имя пода, IP-адрес и порты.
CLI инициирует POST-запрос на API-сервер для установления сессии порт-форвардинга. Сервер API переключает протокол на WebSocket/SPDY, устанавливая постоянное соединение между локальной машиной и подом.
# пример кода в питоне для выполнения запроса import requests from requests.auth import AuthBase class BearerAuth(AuthBase): def __init__(self, token): self.token = token def __call__(self, r): r.headers["authorization"] = "Bearer " + self.token return r url = "https://<api-server>/api/v1/namespaces/default/pods/my-pod/portforward" token = "<token>" headers = {"Content-Type": "application/json"} response = requests.post(url, headers=headers, auth=BearerAuth(token)) if response.status_code == 101: # switching Protocols print("Connection established") else: print("Failed to establish connection", response.status_code)
API-сервер инструктирует Kubelet на узле, где запущен под, настроить iptables для перенаправления трафика. Kubelet создает правила iptables, чтобы направить трафик с локального порта 8080 на порт пода 80.
После успешного установления соединения данные передаются через WebSocket/SPDY соединение. Пользовательские запросы оборачиваются в кадры WebSocket/SPDY и направляются через API-сервер к Kubelet, который затем пересылает их на под:
import websocket def on_message(ws, message): print(f"Received message: {message}") def on_error(ws, error): print(f"Error: {error}") def on_close(ws): print("Connection closed") def on_open(ws): ws.send("Hello Pod") ws = websocket.WebSocketApp("wss://<api-server>/api/v1/namespaces/default/pods/my-pod/portforward", on_message=on_message, on_error=on_error, on_close=on_close) ws.on_open = on_open ws.run_forever()
Полезные опции
Запуск в фоновом режиме
Для запуска команды в фоновом режиме можно добавить символ & в конец команды:
kubectl port-forward pod/my-pod 8080:80 &
Для остановки процесса есть команда kill с идентификатором процесса:
ps -ef | grep port-forward kill -9 [PID]
Можно позволить Kubernetes выбрать случайный локальный порт:
kubectl port-forward svc/my-service :80
Локальный порт будет указан в выводе команды.
Для прослушивания на любом локальном IP-адресе есть команда:
kubectl port-forward --address 0.0.0.0 pod/my-pod 8080:80
Это позволяет перенаправлять трафик с любого IP-адреса на локальной машине.
Финальные слова
kubectl port-forward — простой и безопасный способ доступа к внутренним сервисам кластера. Однако, не все так радужно. Есть пару минусов:
-
Отсутствие балансировки нагрузки: переадресация портов работает на уровне пода, минуя механизмы балансировки нагрузки Kubernetes.
-
Единовременный доступ одного пользователя: в одно время только один пользователь может установить соединение.
Тем не менее,kubectl port-forward — все еще мощный инструмент.
Больше практических навыков по инфраструктуре приложений вы можете получить в рамках практических онлайн-курсов от экспертов отрасли.
ссылка на оригинал статьи https://habr.com/ru/articles/829866/
Добавить комментарий