How to Migrate from Istio Ingress Gateway to Kubernetes Gateway API


Why?

Before the last Istio upgrade I did with Sail Operator, there was Istio 1.19 running in my Kubernetes lab. And the Istio Ingress Gateway has worked very well for years, after I migrated from Kubernetes Ingress Controller. Now with Istio 1.23, Kubernetes Gateway API became an option along side with Istio Ingress Gateway.

What the Kubernetes Gateway API appeals to me is that it kind of has the best of two worlds:

  • It’s an API, like the Ingress Controller it can have multiple implementations, including the Istio one
  • It has almost all features of the mighty Istio Ingress Gateway, and probably will surpass Istio in features later

And How?

First, the API is not included in a normal Kubernetes installation. I grabbed its YAML from its offical release here. And it can be applied right away. I saved the YAML into my git-ops repo and let ArgoCD to handle the installation.

Here’s the Gateway resource to configure an ingress gateway. Unlike an Istio Gateway resource, the actual gateway, eg. service and deployment will be deployed by declaring this resource.

---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  annotations:
    # there's no load balancer in my bare metal cluster
    "networking.istio.io/service-type": NodePort
  name: kubernetes-gateway
  namespace: istio-system
spec:
  # use istio ingress gateway under the hood
  gatewayClassName: istio
  listeners:
    - name: raynix-https
      protocol: HTTPS
      port: 443
      hostname: "raynix.info"
      # only allow traffic to go to specific namespace
      allowedRoutes:
        kinds:
          - kind: HTTPRoute
        namespaces:
          from: Selector
          selector:
            matchLabels:
              kubernetes.io/metadata.name: wordpress-raynix
      tls:
        certificateRefs:
          - kind: Secret
            group: ""
            name: wordpress-raynix-cert
    # omitted other listeners

Then the HTTPRoute resource, just like an HTTP only Istio VirtualService

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  labels:
    app.kubernetes.io/instance: wordpress-raynix
  name: wordpress
  namespace: wordpress-raynix
spec:
  hostnames:
  - raynix.info
  parentRefs:
  - group: gateway.networking.k8s.io
    kind: Gateway
    name: kubernetes-gateway
    namespace: istio-system
  rules:
  - backendRefs:
    - kind: Service
      name: wordpress
      port: 8080
      weight: 1
    matches:
    - path:
        type: PathPrefix
        value: /

The last thing to do is to update my reverse proxy to route traffic though the new node port of this new gateway

$ k get -n istio-system pods
...
kubernetes-gateway-istio   NodePort    10.106.13.62   <none>        15021:30201/TCP,443:31044/TCP           8m

So the port 31044 is the new HTTPS port. Now this blog is served by Kubernetes Gateway API 🙂

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