Introduction To Gateway Api
- Regarding Ingress, this is usually two services sharing the same Ingress resource.
- What if services are managed by completely different organisations (for example with
/watchand/wear, these are controlled by different groups). - Underlying Ingress resource is still a single resource.
- Can only be managed by one team at a time.
- Ingress has no support for:
- Multi-tenancy.
- Namespace isolation
- No RBAC for Features
- No Resource Isolation
- Ingress only supports HTTP-based rules.
- host matching
- path matching
- Ingress does not support:
- TCP/UDP routing
- Traffic splitting / weighting
- Header manipulation
- Authentication
- Rate limiting
- Redirects
- Rewriting
- Middleware
- WebSocket support
- Custom error pages
- Session affinity
- Cross-origin resource sharing (CORS)
- Example Ingress configuration file: ``` apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress-wear-watch annotations: wear.my-online-store.com nginx.ingress.kubernetes.io/ssl-redirect: “true” nginx.ingress.kubernetes.io/force-ssl-redirect: “true”
spec:
rules:
- host: wear.my-online-store.com
http:
paths:
- path: /foo backend: serviceName: wear-service servicePort: 80
- host: watch.my-online-store.com
http:
paths:
- backend: serviceName: watch-service servicePort: 80 ```
Annotationsare considered this part from the above config:annotations: wear.my-online-store.com nginx.ingress.kubernetes.io/ssl-redirect: "true" nginx.ingress.kubernetes.io/force-ssl-redirect: "true"Host Matchingis considered the following: ```- host: watch.my-online-store.com ```
Path Matchingwould be: ```- path: /foo ```
HTTP Onlywould be set under:http:- Differences in rules can also be seen in the following:
- NGINX:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: cors-ingress annotations: nginx.ingress.kubernetes.io/enable-cors: "true" nginx.ingress.kubernetes.io/cors-allow-methods: "GET, PUT, POST" nginx.ingress.kubernetes.io/cors-allow-origin: "https://allowed-origin.com" nginx.ingress.kubernetes.io/cors-allow-credentials: "true" - traefik
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: traefik-ingress annotations: # CORS Configuration traefik.ingress.kubernetes.io/headers/customresponseheaders: | Access-Control-Allow-Origin: '*' Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS Access-Control-Allow-Headers: Content-Type, Authorization Access-Control-Allow-Credentials: true Access-Control-Max-Age: 3600 - Gateway API is an official Kubernetes project - focuses on Layer 4 and Layer 7 routing.
- Ingress has a lack of support for multi-tenancy.
- Example ingress yaml file:
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress-wear-watch spec: rules: - host: wear.my-online-store.com http: paths: - backend: serviceName: wear-service servicePort: 80 - host: watch.my-online-store.com http: paths: - backend: serviceName: watch-service servicePort: 80 - In the above example, Team A would own: ```
- host: wear.my-online-store.com http: paths: - backend: serviceName: wear-service servicePort: 80 ```
- Then Team B would own: ```
- host: watch.my-online-store.com http: paths: - backend: serviceName: watch-service servicePort: 80 ```
- Gateway API introduces three separate objects managed by three separate personas.
- Infrastructure Providers configure the
GatewayClass.GatewayClassdefines what the underlying network infrastructure would be.
- Cluster Operators then configure the
Gateway- these are instances of theGatewayClass. - Finally for the Application Developers, we have
HTTPRoute. We also haveTCPRouteandGRPCRoute. - How is the
GatewayClassconverted:apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: example-class spec: controllerName: example.com/gateway-controller - Similarly to
Ingress, need to deploy a controller for the gateway as well. - Next we have the
Gatewayobject: ``` apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: example-gateway spec: gatewayClassName: example-class listeners:- name: http protocol: HTTP port: 80 ```
- Finally we have the HTTP Route:
```
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: example-httproute
spec:
parentRefs:
- name: example-gateway hostnames:
- “www.example.com” rules:
- matches:
- path: type: PathPrefix value: /login backendRefs:
- name: example-svc port: 8080 ```
- parentRefs matches requests with the hostname.
- HTTP traffic from example-gateway with the host header set to www.example.com and it will be routed to example-svc on port 8080.
- HTTPRoute is a Layer 7 protocol.
- Ingress vs. Gateway API:
```
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: secure-app
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: “true”
nginx.ingress.kubernetes.io/force-ssl-redirect: “true”
spec:
tls:
- hosts:
- secure.example.com secretName: tls-secret ```
- hosts:
- The above is a basic TLS configuration. This is the native Ingress way.
- To ensure all traffic uses HTTPS, need to redirect that using the following:
nginx.ingress.kubernetes.io/ssl-redirect: "true" - In contract, the
GatewayAPIapproach is much more structured. An example is below: ``` apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: secure-gateway spec: gatewayClassName: example -gc listeners:- name: https
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- kind: Secret name: tls-secret allowedRoutes: kinds:
- kind: HTTPRoute ```
- name: https
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- Listeners clearly shows setting up HTTPS endpoint port 443, Specific on TLS and killing those on the gateway.
- Here is another example - a canary deployment and send 80% of the traffic to here with Ingress:
```
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: canary-ingress
annotations:
nginx.ingress.kubernetes.io/canary: “true”
nginx.ingress.kubernetes.io/canary-weight: “20”
spec:
rules:
- http:
paths:
- path: / pathType: Prefix backend: service: name: app-v2 port: number: 80 ```
- http:
paths:
- The above config only works with Nginx, other controllers may not understand.
- Here is the GatewayAPI version:
```
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: split-traffic
spec:
parentRefs:
- name: app-gateway rules:
- backendRefs:
- name: app-v1 port: 80 weight: 80
- name: app-v2 port: 80 weight: 20 ```
- In the above, no hidden primary config needed.
- Easily see traffic which is split. 80% is app-v1 and 20% is app-v2.
- Another HTTPRoute example:
```
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: cors-route
spec:
parentRefs:
- name: my-gateway rules:
- matches:
- path:
type: PathPrefix
value: /api
filters:
CORS configuration using response header modification
- type: ResponseHeaderModifier
responseHeaderModifier:
add:
- name: Access-Control-Allow-Origin value: “*”
- name: Access-Control-Allow-Methods value: “GET,POST,PUT,DELETE,OPTIONS”
- name: Access-Control-Allow-Headers value: “Content-Type, Authorization”
- name: Access-Control-Allow-Credentials value: “true”
- name: Access-Control-Max-Age value: “3600” backendRefs:
- name: api-service ```
- path:
type: PathPrefix
value: /api
filters:
- Most Controllers have implemented this - Amazon EKS, Google Kubernetes Engine,