Как запустить TCP трафик в Kubernetes
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Развернутый ответ: запуск TCP-трафика в Kubernetes
Запуск TCP-трафика в Kubernetes — это базовая, но критически важная задача для любого DevOps-инженера. Она охватывает несколько слоев: от развертывания приложения, которое генерирует или принимает трафик, до настройки сетевой инфраструктуры для его маршрутизации. Я разберу ключевые подходы, от простых к более продвинутым, с практическими примерами.
1. Базовый уровень: kubectl port-forward для ад-hoc доступа
Самый простой способ — это проброс порта с локальной машины прямо на Pod или Service в кластере. Этот метод идеален для отладки, но не для production-трафика, так как создает туннель через API-сервер и зависит от активной сессии kubectl.
# Проброс TCP-порта 8080 локальной машины на порт 80 пода с меткой app=nginx
kubectl port-forward pod/<pod-name> 8080:80
# Или через Service
kubectl port-forward service/<service-name> 8080:80
После выполнения команды вы можете отправлять TCP-трафик (например, с помощью curl, telnet или клиента вашего приложения) на localhost:8080, и он будет перенаправлен в кластер.
2. Production-уровень: использование Service и Ingress
Для постоянного доступа к приложениям изнутри или извне кластера используются ресурсы Service и Ingress.
Service (ClusterIP, NodePort, LoadBalancer)
Service — это абстракция, которая определяет логический набор Pods и политику доступа к ним. Тип Service определяет, как будет экспортироваться TCP-трафик.
-
ClusterIP (по умолчанию): Создает внутренний IP-адрес для доступа к Pods изнутри кластера. Внешний трафик напрямую не проходит.
apiVersion: v1 kind: Service metadata: name: my-tcp-service spec: type: ClusterIP selector: app: my-tcp-app ports: - protocol: TCP port: 80 # Порт, на котором Service доступен внутри кластера targetPort: 8080 # Порт контейнера в Pod, куда направляется трафик -
NodePort: Открывает статический порт на каждой Node кластера. Трафик на
<NodeIP>:<NodePort>перенаправляется в Service, а затем в Pod. Подходит для простого внешнего доступа, когда нет внешнего балансировщика.apiVersion: v1 kind: Service metadata: name: my-nodeport-service spec: type: NodePort selector: app: my-tcp-app ports: - protocol: TCP port: 80 targetPort: 8080 nodePort: 30007 # (Опционально) Порт в диапазоне 30000-32767. Если не указан, будет выбран случайный. -
LoadBalancer: Стандартный способ в облачных средах (AWS, GCP, Azure). Kubernetes взаимодействует с облачным провайдером, чтобы создать внешний балансировщик нагрузки, который направляет трафик на Service. IP-адрес балансировщика становится точкой входа для внешнего TCP-трафика.
apiVersion: v1 kind: Service metadata: name: my-loadbalancer-service spec: type: LoadBalancer selector: app: my-tcp-app ports: - protocol: TCP port: 80 targetPort: 8080 # После применения облачный провайдер назначит внешний IP (EXTERNAL-IP в выводе `kubectl get svc`).
Ingress и Ingress Controller
Ingress — это API-объект, который управляет внешним доступом к сервисам в кластере, обычно по HTTP/HTTPS. Однако, для "сырого" TCP (или UDP) трафика (например, для баз данных, кастомных протоколов) стандартный Ingress Resource имеет ограничения. Решение — использование Ingress Controller с поддержкой TCP/UDP проксирования, такого как NGINX Ingress Controller.
Настройка передается через ConfigMap контроллера.
- Развертывание NGINX Ingress Controller (например, через Helm или манифесты).
- Настройка ConfigMap для проксирования TCP-портов. Вы указываете, какой порт на Service контроллера будет слушать внешний TCP-трафик и на какой Service:Port внутри кластера его перенаправлять.
# Пример ConfigMap для NGINX Ingress Controller apiVersion: v1 kind: ConfigMap metadata: name: tcp-services namespace: ingress-nginx # Пространство имен, где работает контроллер data: "3306": "default/mysql-service:3306" # Ключ: внешний порт. Значение: <namespace>/<service-name>:<service-port> "5432": "default/postgres-service:5432" - Запуск контроллера с примонтированным этим ConfigMap. Внешний трафик на порт 3306 балансировщика нагрузки контроллера будет направлен на Service
mysql-serviceна порт 3306.
3. Продвинутый уровень: Service типа LoadBalancer с сохранением исходного IP (ExternalTrafficPolicy) и NetworkPolicy
- ExternalTrafficPolicy: Для Service типов
NodePortиLoadBalancerкритически важна политикаexternalTrafficPolicy.
* `Cluster` (по умолчанию): Трафик может быть перенаправлен на Pod на любой ноде, что приводит к дополнительному хопу и потере исходного IP-адреса клиента (в Pod он будет виден как IP ноды).
* `Local`: Трафик направляется только на Pods, находящиеся на той же ноде, куда он пришел. Это сохраняет **исходный IP-адрес клиента** и уменьшает задержки, но требует равномерного распределения Pods.
```yaml
spec:
externalTrafficPolicy: Local
type: LoadBalancer
```
- NetworkPolicy: Для управления TCP-трафиком внутри кластера (микросервисная безопасность) используйте NetworkPolicy. Это "брандмауэр" на уровне Pod.
apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-db-access spec: podSelector: matchLabels: role: database policyTypes: - Ingress ingress: - from: - podSelector: matchLabels: app: api ports: - protocol: TCP port: 5432 # Разрешает входящий TCP-трафик на порт 5432 только от Pods с меткой app=api
Итог и рекомендации
Выбор метода зависит от контекста:
- Отладка/разработка:
kubectl port-forward. - Внутренняя связь микросервисов: Service типа
ClusterIP. - Публикация stateless HTTP/HTTPS приложений: Service
LoadBalancer+ Ingress. - Публикация stateful сервисов с кастомными TCP-протоколами (БД, Redis, RabbitMQ): Service
LoadBalancerсexternalTrafficPolicy: Localили TCP-прокси через Ingress Controller (если нужно экономить внешние IP). - Полный контроль и производительность: Рассмотрите шлюзы на уровне eBPF (Cilium) или облачные шлюзы приложений (Application Gateway, ALB).
Всегда проверяйте, что Pods имеют корректные readiness/liveness пробы, а Security Groups/Firewalls облачного провайдера разрешают необходимые порты.