Daniel's Tech Blog

Cloud Computing, Cloud Native & Kubernetes

Configuring Istio using the Kubernetes Gateway API

The Kubernetes Gateway API is the successor of the Kubernetes Ingress API and is currently in beta state. More and more projects add support for the Gateway API like Istio.

-> https://istio.io/latest/blog/2022/gateway-api-beta/
-> https://istio.io/latest/blog/2022/getting-started-gtwapi/

In today’s blog post, I walk you through how to configure Istio using the Kubernetes Gateway API. At the time of writing, I am running my Azure Kubernetes Service cluster with Kubernetes version 1.25.6. The Istio version is 1.17.2 and the Gateway API version is 0.6.2.

 Scenario

I cover the following scenarios with my Gateway API configuration for Istio. First, the Istio ingress gateway gets created in the istio-system namespace. Same as with the standard Istio installation. Second, the routing configuration is placed into a dedicated namespace called istio-config to separate the Istio installation from the configuration of the service routing. The last scenario is the automatic redirection of HTTP traffic to HTTPS.

Install Kubernetes Gateway API CRDs

Before we can use the Gateway API on an Azure Kubernetes Service cluster, we must install the Gateway API CRDs. In total, we install four custom resource definitions, short CRDs. The GatewayClass, Gateway, HTTPRoute, and ReferenceGrant.

GATEWAY_API_TAG='v0.6.2'
 kubectl apply -f "https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/$GATEWAY_API_TAG/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml"
 kubectl apply -f "https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/$GATEWAY_API_TAG/config/crd/standard/gateway.networking.k8s.io_gateways.yaml"
 kubectl apply -f "https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/$GATEWAY_API_TAG/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml"
 kubectl apply -f "https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/$GATEWAY_API_TAG/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml"

When you follow the Istio documentation and use the kustomize command, you only install three CRDs. The ResourceGrant CRD is not part of the kustomize template but required to fulfill our second scenario.

-> https://istio.io/latest/docs/tasks/traffic-management/ingress/gateway-api/

Set up the Istio ingress gateway

After the CRD installation, we proceed with the definition to configure the Istio ingress gateway. The gateway configuration is kept simple and consists of the two required spec sections gatewayClassName and listeners.

apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
  name: gw-api
  namespace: istio-system
spec:
  gatewayClassName: istio
  listeners:
  ...

For the gatewayClassName, we use istio as this is the name of the GatewayClass resource in our case.

❯ kubectl get gatewayclasses.gateway.networking.k8s.io
NAME    CONTROLLER                    ACCEPTED   AGE
istio   istio.io/gateway-controller   True       9d

We define two listeners, one for HTTP and one for HTTPS traffic.

...
    - name: http
      hostname: "*.danielstechblog.de"
      port: 80
      protocol: HTTP
      allowedRoutes:
        namespaces:
          from: Same
        kinds:
          - group: gateway.networking.k8s.io
            kind: HTTPRoute
...

The one for HTTP traffic restricts the route configuration to the same namespace in which the Istio ingress gateway gets deployed. We will talk about the why in the section about the HTTP to HTTPS traffic redirection. Also, the route configuration is restricted to the kind HTTPRoute.

Allowed routes can be configured beside the value Same with two other values. All to allow route configuration from every namespace or Selector to allow them only from namespaces with a specific label as seen in the HTTPS listener configuration below.

...
    - name: https
      hostname: "*.danielstechblog.de"
      port: 443
      protocol: HTTPS
      allowedRoutes:
        namespaces:
          from: Selector
          selector:
            matchLabels:
              ingress-configuration: "true"
        kinds:
          - group: gateway.networking.k8s.io
            kind: HTTPRoute
      tls:
        mode: Terminate
        certificateRefs:
          - kind: Secret
            group: ""
            name: istio-ingress-cert
            namespace: istio-system

The HTTPS listener configuration has an additional tls section for the HTTPS configuration. Which mode should be used, Terminate or Passthrough? Furthermore, we specify at least one certificate reference. Per default, the certificate reference uses the same namespace as the ingress gateway.

Currently, the Istio ingress gateway deployed by the Kubernetes Gateway API runs only with one replica. We must deploy a horizontal pod autoscaler and a pod disruption budget resource having the same configuration as the default Istio ingress gateway.

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: gw-api
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: gw-api-istio
  minReplicas: 3
  maxReplicas: 6
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 80
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: gw-api
spec:
  minAvailable: 50%
  selector:
    matchLabels:
      istio.io/gateway-name: gw-api

Adding those additional resources ensures a highly available ingress gateway.

Configure HTTP routing

Let us start with the routing configuration for the HTTP to HTTPS redirect.

apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: http-to-https-redirect
  namespace: istio-system
spec:
  parentRefs:
    - name: gw-api
      namespace: istio-system
  hostnames:
    - "*.danielstechblog.de"
  rules:
    - filters:
        - type: RequestRedirect
          requestRedirect:
            scheme: https
            statusCode: 301
            port: 443

The routing configuration is attached with a parent reference to the respective ingress gateway. Under the rules section, the actual configuration happens how traffic is handled.

In the case of the redirect, we use a filter of type RequestRedirect. Even we use the scheme https, we must specify the port, 443, as otherwise, the redirect uses port 80.

HTTP redirect configuration error

❯ curl -sIL http://gwapi.danielstechblog.de
HTTP/1.1 301 Moved Permanently
location: https://gwapi.danielstechblog.de:80/
date: Thu, 18 May 2023 21:02:14 GMT
server: istio-envoy
transfer-encoding: chunked

Now the explanation of why we restrict the routing configuration of the HTTP listener to the istio-system namespace or in general, to a dedicated namespace. For instance, using All or placing the redirect routing configuration into the same namespace as the other configurations and using the Selector option would allow HTTP traffic to the services directly instead of redirecting traffic from HTTP to HTTPS.

❯ curl -sIL http://gwapi.danielstechblog.de
HTTP/1.1 200 OK
date: Thu, 18 May 2023 20:56:17 GMT
content-length: 107
content-type: text/html; charset=utf-8
x-envoy-upstream-service-time: 8
server: istio-envoy

Using a dedicated namespace lets the redirect work as intended.

❯ curl -sIL http://gwapi.danielstechblog.de
HTTP/1.1 301 Moved Permanently
location: https://gwapi.danielstechblog.de:443/
date: Thu, 18 May 2023 20:51:18 GMT
server: istio-envoy
transfer-encoding: chunked

HTTP/2 200
date: Thu, 18 May 2023 20:51:18 GMT
content-length: 107
content-type: text/html; charset=utf-8
x-envoy-upstream-service-time: 5
server: istio-envoy

After putting the redirect into place, we continue our routing configuration, enabling our application to receive traffic.

apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: go-webapp
  namespace: istio-config
spec:
  parentRefs:
    - name: gw-api
      namespace: istio-system
  hostnames:
    - "*.danielstechblog.de"
  rules:
    - backendRefs:
        - name: go-webapp-gw-api
          namespace: go-webapp
          port: 80

The routing configuration for our application is deployed, as mentioned in the scenarios, to a namespace called istio-config. We use a backend reference under the rules section to direct traffic to our application. Directing traffic to the root path / does not require anything else in this case.

Besides the routing configuration, we need a ReferenceGrant resource in the application namespace, as the routing configuration lives in a different namespace than our application.

apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: go-webapp
  namespace: go-webapp
spec:
  from:
    - group: gateway.networking.k8s.io
      kind: HTTPRoute
      namespace: istio-config
  to:
    - group: ""
      kind: Service
      name: go-webapp-gw-api

A reference grant allows the backend reference from a routing configuration that lives in a different namespace. We can specify in the to section if we want to allow the backend reference to all Kubernetes service objects or only a specific one like go-webapp-gw-api in the example above.

Can I run Istio in both modes in parallel?

Istio supports running both modes in parallel. As long as we have specified the Istio ingress gateway in our IstioOperator template, we will get it deployed and can add an Istio ingress gateway via the Kubernetes Gateway API besides the default one.

Istio using both modes. Default and Kubernetes Gateway API

In the screenshot above we see an Istio installation using both modes in parallel on the same Kubernetes cluster.

The application served by the Istio ingress gateway deployed via the Gateway API is presented on the left side and returns a red page. Vice versa, on the right side, we see the application served by the default Istio ingress gateway, returning a blue page.

Summary

Setting up and configuring the Istio ingress gateway via the Kubernetes Gateway API is straightforward. Yes, some quirks need to be considered like the horizontal pod autoscaler and the pod disruption budget. But the Gateway API looks very promising to be the standard in the future for ingress configuration as well as for the service mesh configuration which is currently driven by the GAMMA initiative. Hence, you should give it a try and get familiar with the Kubernetes Gateway API whether you are using Istio or not.

You can find my configuration examples in my GitHub repository.

-> https://github.com/neumanndaniel/kubernetes/tree/master/gateway-api

Additional resources about the Kubernetes Gateway API are linked below.

-> https://kubernetes.io/blog/2022/07/13/gateway-api-graduates-to-beta/
-> https://gateway-api.sigs.k8s.io/
-> https://gateway-api.sigs.k8s.io/contributing/gamma/
-> https://github.com/kubernetes-sigs/gateway-api


Posted

in

WordPress Cookie Notice by Real Cookie Banner