Ответ
Обращение происходит через единую точку входа — внешний IP или DNS-имя LoadBalancer-сервиса самого Ingress-контроллера. Внутри кластера Ingress-контроллер маршрутизирует трафик на соответствующие backend-сервисы на основе правил, описанных в ресурсах Ingress.
Типичная архитектура:
- Ingress-контроллер (например, ingress-nginx) развернут как Deployment.
- К этому Deployment'у привязан Service типа LoadBalancer.
- Облачный провайдер (AWS ELB, GCP Load Balancer, Azure LB) или MetalLB в on-prem среде назначают этому сервису внешний IP-адрес.
- Пользователь или DNS обращается к этому внешнему IP.
- Ingress-контроллер анализирует HTTP-запрос (Host header, путь) и направляет его на внутренний ClusterIP-сервис вашего приложения, указанный в правиле Ingress.
Пример манифестов:
Сервис Ingress-контроллера (LoadBalancer):
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
type: LoadBalancer
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
- name: https
port: 443
targetPort: 443
protocol: TCP
selector:
app.kubernetes.io/name: ingress-nginx
Ресурс Ingress для приложения:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx # Указываем класс контроллера
rules:
- host: app.mycompany.com # Домен, по которому доступно приложение
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: backend-api-service # Внутренний сервис приложения
port:
number: 8080
- path: /
pathType: Prefix
backend:
service:
name: frontend-web-service
port:
number: 80
Как это работает на практике:
- После применения манифестов получаем внешний IP:
kubectl get svc -n ingress-nginx ingress-nginx-controller # NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) # ingress-nginx-controller LoadBalancer 10.96.45.211 203.0.113.100 80:32678/TCP,443:31484/TCP - Настраиваем DNS-запись
app.mycompany.com, указывающую на IP203.0.113.100. - Запрос
http://app.mycompany.com/api/usersпопадает на IP203.0.113.100:80, его принимает ingress-nginx. - Контроллер, видя Host
app.mycompany.comи путь/api, перенаправляет запрос на порт 8080 внутреннего сервисаbackend-api-service.
Важно: Для HTTPS необходимо настроить TLS-терминацию на Ingress-контроллере, указав секрет с сертификатом в спецификации Ingress (tls секция).
Ответ 18+ 🔞
Давай разберём эту схему, а то с первого взгляда выглядит как ёперный театр. Представь, что у тебя есть кластер — это типа охраняемый посёлок, куда просто так не зайдёшь. А твоё приложение — это хата внутри этого посёлка. Как к нему попасть извне? Вот тут и появляется наш главный по тарелкам — Ingress-контроллер.
Этот контроллер — он как швейцар в дорогом отеле, только вместо ливреи у него под капотом nginx или какой-нибудь другой движок. Разворачивается он внутри кластера как обычный Deployment, но у него есть особая фишка — к нему прикручен Service типа LoadBalancer.
И вот тут начинается магия, блядь. Когда ты накатываешь этот сервис, твой облачный провайдер (AWS, GCP, Azure) или, если ты на своём железе, MetalLB — видят его и говорят: «О, чуваку нужна точка входа!». И выдают ему внешний IP-адрес. Это типа номер телефона твоего швейцара, по которому ему можно позвонить с улицы.
Вот как вся эта карусель крутится:
- У швейцара (Ingress-контроллера) появляется этот самый внешний IP.
- Ты настраиваешь DNS, чтобы твой домен
app.mycompany.comвёл на этот IP. Типа прописываешь номер швейцара в телефонной книге. - Пользователь стучится по адресу
http://app.mycompany.com/api/users. - Запрос прилетает на внешний IP, его ловит наш швейцар-контроллер.
- А этот швейцар — хитрая жопа. У него есть инструкция (ресурс Ingress), где расписано: «Если пришёл гость с визиткой
app.mycompany.comи путь у него начинается на/api— веди его в коридор номер 8080 к службеbackend-api-service. Если же путь просто/— тогда это в другую комнату, кfrontend-web-serviceна порт 80». - И контроллер маршрутизирует трафик внутрь кластера на нужный внутренний сервис приложения. Всё, довольный пользователь получил ответ.
А теперь смотри на примеры, чтобы вообще ни хуя не осталось непонятного.
Вот манифест сервиса для самого контроллера. Это и есть его «номер телефона» типа LoadBalancer:
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
type: LoadBalancer # Вот эта приписка заставляет облако выдать внешний IP
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
- name: https
port: 443
targetPort: 443
protocol: TCP
selector:
app.kubernetes.io/name: ingress-nginx
А вот сама инструкция для швейцара — ресурс Ingress для твоего приложения. Здесь чётко сказано, куда кого пускать:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx # Говорим, что эту инструкцию читает именно nginx-швейцар
rules:
- host: app.mycompany.com # Если гость представился этим именем...
http:
paths:
- path: /api # ...и путь у него /api
pathType: Prefix
backend:
service:
name: backend-api-service # ...то веди его сюда
port:
number: 8080
- path: / # А если путь просто корень
pathType: Prefix
backend:
service:
name: frontend-web-service # ...то веди его уже сюда
port:
number: 80
Как это выглядит на практике? Очень просто.
-
После деплоя смотришь, какой IP выдали:
kubectl get svc -n ingress-nginx ingress-nginx-controller # NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) # ingress-nginx-controller LoadBalancer 10.96.45.211 203.0.113.100 80:32678/TCP,443:31484/TCPВидишь этот
EXTERNAL-IP?203.0.113.100? Вот он, звездец! Это и есть твоя дверь в кластер. -
Наводишь DNS на этот IP.
-
Всё, работает. Запрос летит по цепочке: Пользователь -> DNS -> Внешний IP (203.0.113.100) -> Ingress-контроллер -> Внутренний сервис приложения.
Важный момент на посошок: Если хочешь HTTPS (а ты хочешь, иначе пидарас шерстяной), то нужно настроить TLS. Делается это прямо в ресурсе Ingress, в секции tls, где указываешь секрет с твоим сертификатом. Контроллер сам разгрузит SSL, и внутрь кластера пойдёт уже обычный HTTP-трафик. Без этой настройки будет у тебя не шифрованное соединение, а просто пизда рулю.