DEV Community

Cover image for Goodbye Ingress, Hello Gateway API: Migrating the Right Way
Sergio Méndez
Sergio Méndez

Posted on

Goodbye Ingress, Hello Gateway API: Migrating the Right Way

Hi, dear community of readers, continuing with this blog posts to learn called Learning Kubernetes, this time is the time to learn about how to use the Gateway API. Now all the teams are looking to migrate, so my goal with this post is to help you with a quick start guide to understand and use the Gateway API with the implementation created by NGINX. I know that a lot of people used the NGINX Ingress Controller in their clusters, so makes sense to continue in that way but using the Gateway API. So let's summarize my goals:

  • Start using Gateway API and deprecate your Ingress Controller
  • Setup a functional Gateway API with NGINX for your services So let's start with this content, I know you want to now how to use the Gateway API.

What you will learn

In this blog post you will learn how to:

  • Install the Gateway API & NGINX Gateway Fabric
  • Create and use Gateways and HTTP Routes
  • Configure Cert-Manager for TLS for your Gateways

Requirements

  • A Kubernetes Cluster
  • Access to the cluster using kubectl

Install the Gateway API & NGINX Gateway Fabric

To install the Gateway API & NGINX Gateway Fabric follow these steps:
1. Install Gateway API & NGINX Gateway Fabric CRDs:

kubectl kustomize "https://github.com/nginx/nginx-gateway-fabric/config/crd/gateway-api/standard?ref=v2.4.2" | kubectl apply -f -
Enter fullscreen mode Exit fullscreen mode

2. Install the NGINX Gateway Fabric using Helm

helm install ngf oci://ghcr.io/nginx/charts/nginx-gateway-fabric --create-namespace -n nginx-gateway
Enter fullscreen mode Exit fullscreen mode

Create and use Gateways and HTTP Routes

Now let's create a simple deployment wiht a Gateway and HTTP Route by following the next steps:
1. Install the following application waiting for the Public api created by the Gateway :

kubectl apply -f - <<EOF
apiVersion: v1
kind: Namespace
metadata:
  creationTimestamp: null
  name: mynamespace
spec: {}
status: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: myapp
  name: myapp
  namespace: mynamespace
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: myapp
    spec:
      containers:
      - image: nginx
        name: nginx
        resources: {}
status: {}
---
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    app: myapp
  name: myapp
  namespace: mynamespace
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: myapp
  type: ClusterIP
status:
  loadBalancer: {}
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: mygateway
  namespace: mynamespace
spec:
  gatewayClassName: nginx
  listeners:
  - name: http
    port: 80
    protocol: HTTP
EOF
Enter fullscreen mode Exit fullscreen mode

2. Get the IP assigned to the Gateway using the following command:

export GW=$(kubectl get svc mygateway-nginx -n mynamespace -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
Enter fullscreen mode Exit fullscreen mode

Note: You have to wait for some minutes in order that the cloud provider assign an external IP to the Gateway created.
3. Create the route to expose the application:

kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: approute
  namespace: mynamespace
spec:
  parentRefs:
  - name: mygateway
  hostnames:
  - "$GW.nip.io"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: myapp
      port: 80
EOF
Enter fullscreen mode Exit fullscreen mode

4. Test the Application by using curl as follows:

curl http://$GW.nip.io
Enter fullscreen mode Exit fullscreen mode

And that's it now it works, now let's move on using TLS.

Configure Cert-Manager for TLS for your Gateways

Now let's configure the Cert-Manage to generate a certificate for your app by following these steps:
0. (Optional) Delete the previous gateway and route as follows:

kubectl delete gateway mygateway -n mynamespace
kubectl delete httproute approute -n mynamespace
Enter fullscreen mode Exit fullscreen mode

1. Add the cert-manager helm chart

helm repo add jetstack https://charts.jetstack.io
helm repo update
Enter fullscreen mode Exit fullscreen mode

2. Add the cert-manager helm chart
Install the cert-manager, and enable the GatewayAPI feature gate:

helm install \
  cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --set config.apiVersion="controller.config.cert-manager.io/v1alpha1" \
  --set config.kind="ControllerConfiguration" \
  --set config.enableGatewayAPI=true \
  --set crds.enabled=true
Enter fullscreen mode Exit fullscreen mode

3. Create a ClusterIssuer to use to generate your certicate:

export EMAIL="your_name@domain.tld"
kubectl apply -f - <<EOF
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    email: $EMAIL
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: issuer-account-key
    solvers:
    - http01:
        gatewayHTTPRoute:
          parentRefs:
          - name: gateway
            namespace: default
            kind: Gateway
EOF
Enter fullscreen mode Exit fullscreen mode

4. Change your current Gateway as follows:

kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: mygateway
  namespace: mynamespace
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  gatewayClassName: nginx
  listeners:
  - name: http
    port: 80
    protocol: HTTP
  - name: https
    hostname: "$GW.nip.io"
    port: 443
    protocol: HTTPS
    tls:
      mode: Terminate
      certificateRefs:
      - kind: Secret
        name: tls-secret
EOF
Enter fullscreen mode Exit fullscreen mode

Note: Use the previous GW value the first time, then check for the service called mygateway-nginx using the following command:

kubectl get svc -n mynamespace
Enter fullscreen mode Exit fullscreen mode

Then update the value GW with the following command:

export GW=$(kubectl get svc mygateway-nginx -n mynamespace -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
Enter fullscreen mode Exit fullscreen mode

And apply the YAML again to point to the correct URL.
5. Now modify your HTTP Route as follows:

kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: approute
  namespace: mynamespace
spec:
  parentRefs:
  - name: mygateway
    sectionName: https
  hostnames:
  - "$GW.nip.io"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: myapp
      port: 80
EOF
Enter fullscreen mode Exit fullscreen mode

6. Now test your application by running the following command:

curl https://$GW.nip.io
Enter fullscreen mode Exit fullscreen mode

And that's it, now you have learned how to use the Gateway API with the NGINX Fabric Gateway implementation using also TLS with Cert-Manager. Take a look to the Links in the references for more theory and examples, of course if you need something more complicated :).

References

Conclusion about the Gateway API with NGINX

Well, a lot of companies are getting into chaos because of deprecated their previous Ingress Controller, but it seems that its not as complicated for simple configuration like the one I showed in the post. I hope this can help as an initial configuration that you can expand for your needs. Well this Gateway API is the future for Kubernetes to have something more stable to manage. I am curious to test another implementations. But it seems that works, maybe the documentation is not as well designed but you can find the necessary parts that you need in the links before.

So what implementation of Gateway API are you going to use, write a comment below :).

That a lot for me this time, see you the next one. I hope so hehehe.

Follow me

These are my social networks:

https://www.linkedin.com/in/sergioarmgpl
https://sergiops.xyz
https://x.com/sergioarmgpl
https://www.instagram.com/sergioarmgpl/

Top comments (0)