Konrad Kowalski (rootsher)Principal Platform & Reliability Architect110001000001100101100001100010010111100011100000

Od Service do Gateway API: skąd wziął się problem

data
kategoria
Networking
także w
Containers
czytanie
1 min / 243 słów

Najpierw problem był prosty:

text
mam Service
chcę dostać się do niego spoza klastra

Service type: LoadBalancer pasuje do tego modelu.

yaml
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  type: LoadBalancer
  selector:
    app: web
  ports:
    - port: 80
      targetPort: 8080

To jest dobre API, jeśli myślimy o porcie i backendzie.

HTTP szybko dokłada pytania, których Service nie próbuje rozwiązać:

text
który host?
który path?
gdzie TLS?
co z redirectem?
co z rewrite?
co z timeoutem?

Dlatego pojawił się Ingress.

Ingress nazwał tylko część problemu

Najprostszy Ingress wygląda sensownie.

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web
spec:
  ingressClassName: nginx
  rules:
    - host: example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web
                port:
                  number: 80

Kontrakt jest czytelny:

text
example.com/
  -> Service web:80

Problem zaczyna się przy następnym wymaganiu.

yaml
metadata:
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/proxy-read-timeout: "30"
    nginx.ingress.kubernetes.io/proxy-body-size: "20m"

Formalnie nadal patrzymy na Ingress.

W praktyce patrzymy na konfigurację ingress-nginx.

Adnotacje były sygnałem

Adnotacje nie były przypadkowym bałaganem.

Były sposobem na dopisanie funkcji, których Ingress nie umiał wyrazić.

Produkcja potrzebowała:

text
redirectów
rewrite
timeoutów
limitów body
manipulacji nagłówkami
canary
niestandardowej autoryzacji

Specyfikacja Ingress była mniejsza niż realny problem.

Kontrolery wypełniły tę lukę po swojemu.

To działało, dopóki nie trzeba było zmienić kontrolera albo ujednolicić klastra.

Wtedy okazywało się, że przenośny zasób Kubernetes ma w sobie nieprzenośną część:

text
nginx.ingress.kubernetes.io/*

Gateway API rozdziela role

Gateway API nie jest jednym nowym proxy.

To model zasobów, który rozdziela rzeczy wcześniej upchnięte w Ingress.

text
GatewayClass
  |
  v
Gateway
  |
  v
HTTPRoute
  |
  v
Service

GatewayClass mówi, jaki kontroler i jaki typ infrastruktury obsłuży gatewaye.

Gateway mówi, gdzie ruch wchodzi: port, protokół, host, TLS, dozwolone route'y.

HTTPRoute mówi, jak ruch HTTP trafi do usług.

To jest ważniejsze niż sama składnia YAML-a.

Ingress mieszał decyzję platformową i trasę aplikacyjną w jednym zasobie.

Gateway API próbuje te decyzje rozdzielić.

Platforma może zarządzać:

text
GatewayClass
Gateway
listeners
TLS defaults
allowed namespaces

Aplikacja może zarządzać:

text
hostnames
paths
headers
backendRefs
traffic splitting

Co się naprawdę zmienia

Nie chodzi o to, że:

text
Ingress jest stary
Gateway API jest nowe

Chodzi o to, że Ingress miał zbyt mało języka.

Gateway API dodaje nazwy dla rzeczy, które i tak istniały w klastrach:

text
kto dostarcza load balancer
gdzie kończy się TLS
kto może podpiąć route do listenera
który zespół kontroluje routing aplikacji
które zachowania są standardowe
które zależą od implementacji

To nie usuwa potrzeby zrozumienia kontrolera.

Ale przenosi większą część kontraktu z adnotacji do API.