Модуль 8 / 19
Ingress, TLS, маршрутизація трафіку та діагностика edge
Зміст
1. Цілі та результат модуля
Ви опублікуєте два HTTP backend через одну точку входу, налаштуєте TLS termination і локалізуватимете відмову між клієнтом, ingress controller, Service та Pod.
- Ingress описує L7-маршрути, але не обробляє пакети
- IngressClass пов’язує ресурс із controller
- Host і path обирають backend Service
- TLS Secret зберігає сертифікат і ключ
- 404 і 503 вказують на різні шари
2. Теорія: Service, Ingress і controller
Service дає стабільний L4 endpoint набору Pods. Ingress додає HTTP/HTTPS routing за host і path, але API-об’єкт не є proxy. Controller спостерігає Ingress, Service, EndpointSlice і Secret та будує реальну конфігурацію edge.
У лабораторії використовується підтримуваний Traefik. Community ingress-nginx завершив супровід у березні 2026 року, тому новий стенд на ньому не будуємо.
3. Теорія: host, path та IngressClass
Спочатку зіставляється Host, потім path. Prefix враховує сегменти, Exact вимагає точного збігу, ImplementationSpecific залежить від controller. Найдовший збіжний path пріоритетніший. ingressClassName має посилатися на наявний IngressClass.
Ingress не зобов’язаний переписувати URL: backend отримує початковий path. Rewrite — непереносима controller-specific функція.
4. Теорія: TLS termination і SNI
SNI повідомляє ім’я сайту під час TLS handshake. Controller обирає сертифікат із Secret kubernetes.io/tls, завершує TLS і спрямовує запит backend. Шифрування від edge до Pod налаштовується окремо.
- Перевіряйте SAN, issuer, строк і trust chain
- Secret міститься в namespace Ingress
- Закритий ключ не зберігається в Git
- Самопідписаний сертифікат — лише для лабораторії
5. Шлях запиту та модель відмов
DNS/Node address → NodePort controller → entrypoint → host/path router → Service → EndpointSlice → Ready Pod → застосунок.
- Timeout/refused: адреса, firewall, NodePort чи controller
- 404 edge: class, host або path не збігся
- 503 edge: route знайдено, backend недоступний
- 404 застосунку: backend досягнуто, застосунок не знає path
- TLS error: SNI, SAN, trust chain або строк
6. Ingress API та Gateway API
Ingress API стабільний, але функціонально заморожений. Нові можливості розвиваються в Gateway API: GatewayClass, Gateway і HTTPRoute розділяють ролі інфраструктури, cluster operator та application developer.
Fundamentals закріплює Ingress; Gateway API практикується в Advanced/HA частині на multi-node edge.
7. Методичні вказівки
- Під час перевірки за IP передавайте Host
- Перевіряйте controller та IngressClass до route
- Звіряйте backend name/port, Service та EndpointSlice
- TLS перевіряйте з CA та SNI
- Не вважайте curl -k доказом коректного TLS
- Не починайте з рестарту controller
- Відокремлюйте Ingress API від vendor annotations
8. Лабораторна робота: ingress controller
Установіть фіксовану версію chart. Dashboard вимкнено, HTTP/HTTPS відкрито через передбачувані NodePort.
helm repo add traefik https://traefik.github.io/charts
helm repo update traefik
helm upgrade --install traefik traefik/traefik \
--version 41.4.0 --namespace traefik-system --create-namespace \
--wait --timeout 5m --set api.dashboard=false \
--set ingressRoute.dashboard.enabled=false \
--set service.spec.type=NodePort \
--set ports.web.nodePort=30080 --set ports.websecure.nodePort=30443
kubectl -n traefik-system get deployment,pod,service
kubectl get ingressclass traefik -o yaml9. Лабораторна робота: два backend
Два Deployment і два ClusterIP Service повертають ім’я фактичного Pod.
mkdir -p /tmp/k8s-m08
kubectl create namespace k8s-m08
cat > /tmp/k8s-m08/app.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata: {name: web, namespace: k8s-m08}
spec:
replicas: 2
selector: {matchLabels: {app: web}}
template:
metadata: {labels: {app: web}}
spec:
containers:
- name: nginx
image: nginx:1.29-alpine
command: ["sh", "-c"]
args: ["printf 'web=%s\n' "$HOSTNAME" > /usr/share/nginx/html/index.html; exec nginx -g 'daemon off;'"]
ports: [{name: http, containerPort: 80}]
---
apiVersion: apps/v1
kind: Deployment
metadata: {name: api, namespace: k8s-m08}
spec:
replicas: 2
selector: {matchLabels: {app: api}}
template:
metadata: {labels: {app: api}}
spec:
containers:
- name: nginx
image: nginx:1.29-alpine
command: ["sh", "-c"]
args: ["mkdir -p /usr/share/nginx/html/api; printf 'api=%s\n' "$HOSTNAME" > /usr/share/nginx/html/api/index.html; exec nginx -g 'daemon off;'"]
ports: [{name: http, containerPort: 80}]
---
apiVersion: v1
kind: Service
metadata: {name: web, namespace: k8s-m08}
spec: {selector: {app: web}, ports: [{name: http, port: 80, targetPort: http}]}
---
apiVersion: v1
kind: Service
metadata: {name: api, namespace: k8s-m08}
spec: {selector: {app: api}, ports: [{name: http, port: 80, targetPort: http}]}
EOF
kubectl apply --dry-run=server -f /tmp/k8s-m08/app.yaml
kubectl apply -f /tmp/k8s-m08/app.yaml
kubectl -n k8s-m08 wait --for=condition=Available deployment/web deployment/api --timeout=180s
kubectl -n k8s-m08 get service,endpointslice,pod -o wide10. Лабораторна робота: routing і TLS
Корінь іде в web, /api — в api. Потім додайте лабораторний сертифікат і перевірте довіру, SNI та SAN без вимкнення перевірки.
cat > /tmp/k8s-m08/ingress.yaml <<'EOF'
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: course
namespace: k8s-m08
annotations: {traefik.ingress.kubernetes.io/router.entrypoints: "web,websecure"}
spec:
ingressClassName: traefik
rules:
- host: app.course.test
http:
paths:
- path: /api
pathType: Prefix
backend: {service: {name: api, port: {name: http}}}
- path: /
pathType: Prefix
backend: {service: {name: web, port: {name: http}}}
EOF
kubectl apply --dry-run=server -f /tmp/k8s-m08/ingress.yaml
kubectl apply -f /tmp/k8s-m08/ingress.yaml
kubectl -n k8s-m08 describe ingress course
node_ip=$(hostname -I | awk '{print $1}')
curl -fsS -H 'Host: app.course.test' "http://$node_ip:30080/"
curl -fsS -H 'Host: app.course.test' "http://$node_ip:30080/api/"openssl req -x509 -nodes -newkey rsa:2048 -days 30 \
-keyout /tmp/k8s-m08/tls.key -out /tmp/k8s-m08/tls.crt \
-subj '/CN=app.course.test' -addext 'subjectAltName=DNS:app.course.test'
kubectl -n k8s-m08 create secret tls edge-tls --cert=/tmp/k8s-m08/tls.crt --key=/tmp/k8s-m08/tls.key
kubectl -n k8s-m08 patch ingress course --type=merge -p \
'{"spec":{"tls":[{"hosts":["app.course.test"],"secretName":"edge-tls"}]}}'
node_ip=$(hostname -I | awk '{print $1}')
curl --resolve "app.course.test:30443:$node_ip" --cacert /tmp/k8s-m08/tls.crt https://app.course.test:30443/
openssl s_client -connect "$node_ip:30443" -servername app.course.test </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates -ext subjectAltName11. Діагностика: 404 і 503
Неіснуючий IngressClass залишає запит default handler і дає 404. За правильного class, але порожнього EndpointSlice route збігається й очікується 503.
kubectl -n k8s-m08 patch ingress course --type=merge -p '{"spec":{"ingressClassName":"missing"}}'
curl -sS -o /dev/null -w 'status=%{http_code}\n' -H 'Host: app.course.test' "http://$(hostname -I | awk '{print $1}'):30080/"
kubectl get ingressclass; kubectl -n k8s-m08 describe ingress course
kubectl -n k8s-m08 patch ingress course --type=merge -p '{"spec":{"ingressClassName":"traefik"}}'
kubectl -n k8s-m08 patch service api --type=merge -p '{"spec":{"selector":{"app":"missing"}}}'
curl -sS -o /dev/null -w 'status=%{http_code}\n' -H 'Host: app.course.test' "http://$(hostname -I | awk '{print $1}'):30080/api/"
kubectl -n traefik-system logs deployment/traefik --since=2m | tail -40
kubectl -n k8s-m08 patch service api --type=merge -p '{"spec":{"selector":{"app":"api"}}}'12. Контроль, критерії засвоєння та cleanup
- Чому Ingress потребує controller?
- Чим Ingress відрізняється від Service?
- Як працює ingressClassName?
- Prefix проти Exact?
- Чому backend бачить /api?
- Що обирає SNI?
- Де зберігається TLS Secret?
- Чому -k небезпечний?
- Що розрізняє 404 і 503?
- Навіщо Gateway API?
kubectl delete namespace k8s-m08 --wait=true
rm -rf /tmp/k8s-m08
# Traefik остаётся инфраструктурой следующих лабораторий.
# Полное удаление: helm uninstall traefik -n traefik-systemМодуль засвоєно, якщо обидва backend працюють за host/path, TLS перевіряється з CA, а route та upstream помилки розрізняються за evidence.