Привет, Хабр!
Недавно я столкнулся с задачей, требующей доступа к одному из сервисов внутри кластера 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
— все еще мощный инструмент.
Больше практических навыков по инфраструктуре приложений вы можете получить в рамках практических онлайн-курсов от экспертов отрасли.