linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Уроки
  • How it works
  • Симулятор
  • База знаний
  • Собеседование
Index
Categories
All entries
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
home/linux/kb/Контейнеры (бонус)/kubernetes-services-and-ingress

kb/containers ── Контейнеры (бонус) ── intermediate

Kubernetes Service и Ingress - сетевая публикация подов

Service - стабильный VIP перед группой подов (label selector). Типы: ClusterIP (внутри), NodePort (порт на каждой ноде), LoadBalancer (внешний LB облака), ExternalName (CNAME). Ingress - L7 reverse-proxy (nginx/traefik) для HTTP-роутинга.

view as markdownaka: k8s-service, k8s-ingress, kube-proxy, ingress-controller, service-types

Зачем Service

Pod в k8s, эфемерный. Killed/rescheduled, новый IP. Если другой pod хочет с ним общаться, по IP, гонка. Service, это стабильный VIP (ClusterIP) и DNS-имя (my-svc.my-ns.svc.cluster.local), за которым стоит динамическая группа подов, выбранных по label selector'у.

yaml
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  selector:
    app: web                         # выбрать поды с этой label
  ports:
  - port: 80                         # порт самого Service
    targetPort: 8080                 # порт в pod'е
  type: ClusterIP                    # default

Под капотом control-plane (kube-controller-manager) поддерживает Endpoints (или EndpointSlice с k8s 1.21+), список IP:port всех живых подов, прошедших readinessProbe. Это «живой DNS» Service.

Типы Service

ТипГде доступенКак работает
ClusterIPвнутри кластераVIP в service-CIDR, не маршрутится наружу
NodePort<node-IP>:<30000-32767>open-port на каждой ноде, форвардит на ClusterIP
LoadBalancerвнешний IP облачного LBNodePort + cloud-controller вешает LB перед нодами
ExternalNameDNS CNAMEService резолвится в внешнее DNS-имя, без VIP
Headless (clusterIP: None)DNS A-records на pod IPsDNS возвращает все pod IPs, балансирует клиент (StatefulSet, БД-кластеры)

NodePort в проде используют редко, некрасивые порты, не HTTPS. Обычно либо LoadBalancer (в облаке), либо за Ingress (для HTTP).

Headless Service

yaml
spec:
  clusterIP: None
  selector: { app: cassandra }

Полезен для stateful-кейсов где клиенту нужны конкретные pod'ы: Cassandra, Kafka, etcd. DNS-запрос отдаёт A-records на каждый pod, без балансировки на уровне kube-proxy. Часто пара с [[kubernetes-pod-lifecycle|StatefulSet]] (даёт стабильные имена cassandra-0.cassandra.default.svc).

kube-proxy, кто реализует Service

На каждой ноде живёт kube-proxy (DaemonSet или systemd-unit). Его задача, обеспечить, чтобы пакет на ClusterIP/NodePort долетел до одного из pod'ов из Endpoints. Делает это в data plane, без user-space-проксирования.

Три режима:

РежимЧто используетPerformanceГде default
iptablesDNAT-цепочки cmd-iptablesO(N) на правилобольшинство кластеров
ipvsLVS (Linux Virtual Server, kernel L4 LB)O(1), hash-basedEKS большие кластеры, kops
nftablescmd-nft (k8s 1.31+)как iptables, новееновый backend kube-proxy

При iptables на каждый Service-port создаётся chain типа KUBE-SVC-XXX, в нём random-DNAT (statistic mode random) на один из endpoints (KUBE-SEP-YYY). На 5000+ Service'ов начинаются тормоза, каждое iptables-update пересобирает всю таблицу.

ipvs масштабируется лучше: правила в hash-table, не в linear-chain. Включается флагом kube-proxy --proxy-mode=ipvs. Требует kernel-модулей ip_vs, ip_vs_rr, nf_conntrack.

Проверка режима:

bash
kubectl logs -n kube-system kube-proxy-xxxx | grep "Using"
# или
kubectl get cm -n kube-system kube-proxy -o yaml | grep mode

ExternalTrafficPolicy

У NodePort/LoadBalancer есть важный параметр:

  • Cluster (default), пакет может пойти на pod на ЛЮБОЙ ноде, через SNAT. Source IP теряется, balancing equal.
  • Local, только на pod'ы текущей ноды. Source IP сохраняется, но если на ноде нет pod'а, пакет дропается. Обычно используют с healthcheck облачного LB чтобы он перестал слать на пустые ноды.

Для серверов где нужен client IP (rate-limit, ban-list, geo) всегда Local. И добавить podAntiAffinity или DaemonSet чтобы pod'ы были на каждой ноде.

Ingress, L7-роутинг

Service работает на L4 (TCP/UDP). Для HTTP-приложений нужен reverse-proxy с роутингом по host/path, TLS-termination и т.д. Это Ingress.

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  tls:
  - hosts: [api.example.com]
    secretName: api-tls              # k8s Secret с cert+key
  rules:
  - host: api.example.com
    http:
      paths:
      - path: /v1
        pathType: Prefix
        backend:
          service:
            name: api-v1
            port: { number: 80 }
      - path: /v2
        pathType: Prefix
        backend:
          service: { name: api-v2, port: { number: 80 } }

Сам по себе Ingress, это просто декларация. Чтобы что-то заработало, нужен Ingress Controller, pod, который читает Ingress-объекты и конфигурирует реальный proxy.

Сравнение Ingress Controllers

ControllerПод капотомСильные стороныСлабые
ingress-nginxnginx + Luaде-факто стандарт, огромная база annotationsreload при каждом изменении, не для тысяч хостов
traefikGoавтоматический Let's Encrypt, K8s CRDs (IngressRoute)свой DSL, разная семантика с annotations
HAProxy ingressHAProxyмаксимальный throughput, runtime-API без reloadменьше комьюнити
Envoy-based (Contour, Emissary)EnvoyxDS, HTTP/2/gRPC first-classсложнее, больше ресурсов
cloud-native (AWS ALB, GKE GCLB)external LBинтеграция с облакомvendor lock-in

Для большинства команд, ingress-nginx. Если нужен auto-TLS без cert-manager, traefik. Для high-throughput API-gateway Envoy-based (Contour/Gloo/Istio).

Gateway API, следующее поколение

В k8s 1.25+ стандартизирован Gateway API, наследник Ingress с разделением ответственности:

  • GatewayClass (cluster-admin задаёт implementation: nginx/envoy/...)
  • Gateway (infra-team: «вот listener на 443, TLS, ACL»)
  • HTTPRoute / TCPRoute (app-team: «route /api на этот Service»)

Implementation: Istio, Contour, Cilium Service Mesh, kong. Ingress остаётся stable и поддерживается, но новые фичи (header modification, traffic split) идут в Gateway API.

Service Mesh, когда Ingress уже мало

Когда нужно между сервисами: mTLS, retry, circuit-break, observability, это уже не Service/Ingress, а service-mesh (Istio, Linkerd, Cilium). Sidecar Envoy/proxy в каждом pod'е плюс control-plane. Платишь complexity и CPU, получаешь zero-trust + tracing.

Когда что-то пошло не так

  • Service есть, pod'ы есть, но трафика нет kubectl get endpoints my-svc. Если пусто, selector не матчит (опечатка в label) или pod не прошёл readinessProbe.
  • connection refused изнутри кластера, pod слушает на 127.0.0.1, не на 0.0.0.0. Service шлёт на pod IP, не localhost.
  • NodePort недоступен снаружи, host firewall (firewalld, iptables INPUT chain) дропает 30000-32767. Нужно разрешить.
  • Ingress 503 Service Temporarily Unavailable, Endpoints пусты или backend Service неправильный (другой namespace, опечатка). Лог nginx-controller в kubectl logs -n ingress-nginx ....
  • TLS cert mismatch, secretName в Ingress есть, но Secret другого типа (надо kubernetes.io/tls) или хост в SAN не совпадает.
  • Source IP всегда node IP, externalTrafficPolicy: Cluster, включи Local или возьми X-Forwarded-For/PROXY-protocol на Ingress-уровне.
  • kube-proxy iptables CPU 100%, кластер 1000+ Service'ов, переключай на ipvs.
  • Кросс-namespace Service не резолвится, короткое имя my-svc работает только в своём namespace; используй FQDN my-svc.other-ns.svc.cluster.local.

Полезные диагностические команды

  • kubectl get svc -A, все Service в кластере
  • kubectl describe svc my-svc, selector, endpoints, ports
  • kubectl get endpoints my-svc, реальные pod IPs за Service
  • kubectl get endpointslice -l kubernetes.io/service-name=my-svc
  • kubectl run -it --rm debug --image=nicolaka/netshoot --, pod с curl/dig/tcpdump для тестов изнутри кластера

§ команды

bash
kubectl expose deploy web --port=80 --target-port=8080

Быстро создать ClusterIP Service для деплоймента - selector берётся из labels deploy

bash
kubectl get svc -o wide

Все Service с типом, ClusterIP, externalIP, портами и selector'ом

bash
kubectl get endpoints my-svc

Какие pod IP стоят за Service - быстрый sanity-check selector'а

bash
kubectl port-forward svc/my-svc 8080:80

Локальный туннель к Service в обход Ingress - для отладки

bash
kubectl get ingress -A

Все Ingress объекты в кластере с host/path/backend

bash
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx --tail=100

Логи ingress-nginx - первое место смотреть при 502/503

bash
kubectl exec -it some-pod -- nslookup my-svc.my-ns.svc.cluster.local

Проверить что DNS резолвится изнутри pod'а - частая причина 'не работает'

§ см. также

  • kubernetes-pod-lifecycleKubernetes pod lifecycle - от Pending до TerminatedPod проходит фазы Pending → Running → Succeeded/Failed/Unknown. Init-containers выполняются последовательно до основных. Probes: startup → readiness/liveness. SIGTERM + grace period при удалении.
  • cni-pluginsCNI plugins - сеть Kubernetes (calico, cilium, flannel)CNI - спека плагина: дай pod IP и сеть. Реализации: flannel (VXLAN L2-overlay), calico (BGP routing), cilium (eBPF в kernel). Каждая даёт NetworkPolicy для firewall'а между подами. IPAM - часть CNI, выделяет адреса.
  • grpc-basicsgRPC - HTTP/2 + Protobuf RPC frameworkgRPC = HTTP/2 + Protocol Buffers + кодогенерация. Четыре типа RPC: unary (как REST), server-stream, client-stream, bidirectional. Сильная типизация, бинарный wire format, multi-language. grpcurl как curl для gRPC.
  • natNAT и masqueradeNAT - переписывание src/dst адресов пакета на роутере. Masquerade - частный случай: src-IP заменяется на свой исходящий, для исходящих из приватной сети в публичную.
  • cmd-iptablesiptables - правила netfilter (legacy)iptables = userland для netfilter. 5 таблиц (filter/nat/mangle/raw/security), цепочки INPUT/OUTPUT/FORWARD/PRE/POSTROUTING, jump-targets ACCEPT/DROP/MASQUERADE. Legacy, но в проде ещё везде.
  • helm-chartsHelm charts - пакетный менеджер для KubernetesHelm - пакетный менеджер k8s. Chart - папка с Chart.yaml, values.yaml и templates/ (Go-templates над YAML). Releases хранятся в Secret namespace'а; upgrade/rollback атомарны. Альтернатива - kustomize (без templating, патчи).
  • service-discovery-prometheusService discovery в Prometheus: k8s, Consul, file_sd, relabelProm discoverит targets через k8s API, Consul, file_sd (static). relabel_configs - до scrape (filter+rewrite labels). metric_relabel - после scrape (drop bad metrics). Без relabel - cardinality из k8s взрывается.
Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки