Каждый Service типа LoadBalancer создаёт отдельный облачный балансировщик. При 20 сервисах — 20 балансировщиков, каждый со своим IP и ценой. Ingress решает это: один балансировщик, маршрутизация HTTP/HTTPS трафика к разным Service по hostname и пути.
source: kubernetes.io/docs/concepts/services-networking/ingress/
Что такое Ingress
Ingress — объект Kubernetes, определяющий правила маршрутизации HTTP/HTTPS трафика на уровне L7. Позволяет:
- Маршрутизировать по hostname (
api.example.com→ Service A,web.example.com→ Service B) - Маршрутизировать по пути (
/api→ Service A,/web→ Service B) - Терминировать TLS
Статус API. Ingress остаётся стабильным и широко используемым, но Kubernetes помечает его как frozen — новые возможности добавляются только в Gateway API. Для базового HTTP/HTTPS-routing Ingress по-прежнему подходит; для новых инсталляций с богатыми требованиями к traffic policy — смотри Gateway API.
Ingress Controller
Сам по себе Ingress-ресурс ничего не делает. Нужен Ingress Controller — компонент, который читает Ingress-объекты и настраивает прокси. Kubernetes не поставляет его по умолчанию — нужно установить отдельно.
source: kubernetes.io/docs/concepts/services-networking/ingress-controllers/
| Controller | Описание |
|---|---|
| NGINX Ingress Controller | Самый распространённый, на базе NGINX |
| Traefik | Встроенная поддержка Let's Encrypt, dashboard |
| HAProxy Ingress | Высокая производительность |
| AWS Load Balancer Controller | Интеграция с AWS ALB и NLB в EKS |
Манифест Ingress
Маршрутизация по пути
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: myapp.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
- path: /web
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
Маршрутизация по hostname
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: multi-host-ingress
spec:
ingressClassName: nginx
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
- host: web.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-service
port:
number: 80
pathType
| Значение | Поведение |
|---|---|
Prefix | Совпадение по элементам пути: /api совпадёт с /api и /api/users, но не с /apiv2 |
Exact | Точное совпадение: /api совпадёт только с /api |
ImplementationSpecific | Поведение определяет Ingress Controller |
TLS-терминация
# Создать Secret с TLS-сертификатом
kubectl create secret tls my-tls-secret \
--cert=tls.crt \
--key=tls.key
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-ingress
spec:
ingressClassName: nginx
tls:
- hosts:
- myapp.example.com
secretName: my-tls-secret
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-service
port:
number: 80
cert-manager автоматически выпускает и обновляет TLS-сертификаты (Let's Encrypt) и записывает их в Secret. Стандартное решение для production.
Default Backend
Обрабатывает запросы, не совпавшие ни с одним правилом:
spec:
ingressClassName: nginx
defaultBackend:
service:
name: default-service
port:
number: 80
rules:
- host: myapp.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
IngressClass
IngressClass (introduced 1.18 alpha/beta, GA в 1.19) определяет, какой Ingress Controller обрабатывает конкретный Ingress-ресурс. Позволяет использовать несколько контроллеров в одном кластере.
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: nginx
annotations:
ingressclass.kubernetes.io/is-default-class: "true"
spec:
controller: k8s.io/ingress-nginx
Если is-default-class: "true" установлен, Ingress без явного ingressClassName будет обработан этим контроллером.
Service (L4) vs Ingress (L7)
| Критерий | Service (NodePort/LB) | Ingress |
|---|---|---|
| Уровень OSI | L4 (TCP/UDP) | L7 (HTTP/HTTPS) |
| Маршрутизация | По IP и порту | По hostname и пути |
| TLS-терминация | Нет | Да |
| Один IP для нескольких сервисов | Нет | Да |
| Требует доп. компонент | Нет | Да (Ingress Controller) |
Gateway API
Почему Gateway API
Ingress API заморожен (frozen) — новые возможности в него не добавляются. Весь активный roadmap — в Gateway API. Стабильные (v1) ресурсы Gateway API — GatewayClass, Gateway, HTTPRoute, GRPCRoute — доступны в группе gateway.networking.k8s.io/v1.
source: kubernetes.io/docs/concepts/services-networking/gateway/
Важный нюанс: Gateway API — это НЕ встроенные в kube-apiserver типы, а набор CRD. Их нужно установить отдельно (kubectl apply манифестов проекта) и запустить реализацию (Istio, Cilium и т.д.). CRD поставляются двумя каналами:
| Канал | Что содержит | Пример |
|---|---|---|
standard | GA-ресурсы (v1) + прошедшие graduation | GatewayClass, Gateway, HTTPRoute, GRPCRoute |
experimental | alpha/beta-поля и ресурсы | TCPRoute, TLSRoute, BackendTLSPolicy и экспериментальные поля |
Соответствие реализации спецификации проверяется conformance-тестами — «поддерживает Gateway API» не значит «поддерживает всё»; всегда сверяйся с conformance-профилем конкретной реализации.
Ролевая модель
| Роль | Ресурс | Ответственность |
|---|---|---|
| Infrastructure Provider | GatewayClass | Определяет реализацию (Envoy, Istio, Cilium и т.д.) |
| Cluster Operator | Gateway | Listeners, TLS, allowedRoutes |
| Application Developer | HTTPRoute / GRPCRoute | Правила маршрутизации, matches, backendRefs |
Пример: Gateway + HTTPRoute с canary
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: prod-gateway
spec:
gatewayClassName: istio
listeners:
- name: https
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- name: prod-cert
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
gateway-access: "true"
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: app-route
spec:
parentRefs:
- name: prod-gateway
hostnames:
- "app.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /api
backendRefs:
- name: api-svc
port: 8080
weight: 90
- name: api-svc-canary
port: 8080
weight: 10
weight в backendRefs — нативный traffic split для canary без нестандартных аннотаций. В Ingress это требует vendor-специфичных annotations.
Ingress vs Gateway API
| Аспект | Ingress | Gateway API |
|---|---|---|
| Статус | Frozen | GA, активная разработка |
| Canary / Traffic Split | Через аннотации (нестандартно) | Нативный weight в backendRefs |
| Header-based routing | Через аннотации | Нативный matches |
| gRPC | Нет | GRPCRoute |
| Cross-namespace | Нет | Да (через allowedRoutes) |
| Ролевая модель | Один ресурс | Разделение по ролям |
Реализации Gateway API: Istio, Cilium, Envoy Gateway, Kong, NGINX Gateway Fabric, Contour.
Типичные ошибки
Создать Ingress без Ingress Controller. Ingress останется в подвешенном состоянии — ADDRESS не появится, трафик не пойдёт. Всегда проверять: kubectl get ingressclass.
Не указать ingressClassName. Если в кластере несколько Ingress Controller и нет дефолтного класса, Ingress не будет обработан никем.
Перепутать port: в backend.service.port. Там должен быть порт Service, не контейнера. Service уже занимается маршрутизацией до targetPort контейнера.
TLS Secret не в том namespace. Ingress и Secret должны быть в одном namespace.
rewrite-target без escaping. При использовании nginx.ingress.kubernetes.io/rewrite-target: /$2 с capture groups в path нужно правильно задавать регулярку в path. Пропустить — получить 404.
Альтернативы
Service LoadBalancer напрямую — если один сервис и не нужна L7-маршрутизация. Дороже при масштабировании.
Cloudflare Tunnel / ngrok — для доступа к локальному кластеру без публичного IP.
Service Mesh с ingress gateway (Istio Ingress Gateway, Linkerd Ingress) — если mesh уже есть, его ingress gateway может заменить отдельный Ingress Controller.