Migrate from Ingress NGINX

This page describes the step-by-step migration from Ingress NGINX to Airlock Microgateway using the Kubernetes Gateway API. It focuses on the practical migration steps, converting the Ingress NGINX resources to Gateway API resources with the ingress2gateway tool.

Prerequisites

General conversion approach

Converting Ingress NGINX resources follows the following approach:

  1. Convert manifest files
    1. Convert a single manifest file
    2. Run the conversion against your existing Ingress manifest and write the output to a new file:

    3.  
      Terminal box
      ingress2gateway print \
        --providers=ingress-nginx \
        --input-file ingress.yaml \
        > gateway-api-resources.yaml
    4. Convert a directory of manifests
    5. To convert all Ingress manifests in a directory at once:

    6.  
      Terminal box
      ingress2gateway print \
        --providers=ingress-nginx \
        --input-dir ./manifests \
        --output-dir ./gateway-api-manifests
  2. Review the conversion report
  3. The tool prints a warning for every annotation or field it could not translate to a standard Gateway API resource. Review these carefully before proceeding. Each warning requires a manual decision.

  4. Example output:

  5.  
    Example
    ┌─ WARN  ────────────────────────────────────────
    │  Gateway API does not support configuring URL normalization (RFC 3986, Section 6). Please check if this matters for your use case and consult implementation-specific details.
    │  source: STANDARD_EMITTER
    └─
  6. Validate before applying
  7. Before applying the generated resources to the cluster, run a dry-run to catch any syntax or API errors:

  8.  
    Terminal box
    kubectl apply --dry-run=client -f gateway-api-resources.yaml
  9.  
    Notice

    A successful dry-run validates the resource structure but does not confirm that your routes behave identically to the original Ingress. Always test connectivity after applying.

Example migration

The following example shows a typical multi-path Ingress resource and its equivalent Gateway API configuration.

Ingress NGINX configuration

The Ingress NGINX configuration to be migrated looks as follow:

 
Example
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - app.company.com
      secretName: app-company-com-tls
  rules:
    - host: app.company.com
      http:
        paths:
          - path: /foo
            pathType: Prefix
            backend:
              service:
                name: foo-svc
                port:
                  number: 80
          - path: /bar
            pathType: Prefix
            backend:
              service:
                name: bar-svc
                port:
                  number: 80

Convert the configuration

Run the following command to convert the Ingress NGINX configuration:

 
Terminal box
ingress2gateway print \
  --providers=ingress-nginx \
  --input-file my-app-ingress.yaml \
| yq '
  (select(.kind == "Gateway") | .spec.gatewayClassName) = "airlock-microgateway" |
  (select(.kind == "Gateway") | .metadata.name) = "my-ingress" |
  (select(.kind == "HTTPRoute") | .spec.parentRefs[].name) = "my-ingress"
' - \
> my-app-gateway-api.yaml

You may have noticed the yq command used to update the GatewayClassName, Gateway and parentRefs[].name values.

Generated Gateway API configuration

The ingress2gateway tool generates a Gateway and an HTTPRoute, which looks as follow:

 
Example
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  annotations:
    gateway.networking.k8s.io/generator: ingress2gateway-1.1.0
  name: my-ingress
spec:
  gatewayClassName: airlock-microgateway
  listeners:
    - hostname: app.company.com
      name: app-company-com-http
      port: 80
      protocol: HTTP
    - hostname: app.company.com
      name: app-company-com-https
      port: 443
      protocol: HTTPS
      tls:
        certificateRefs:
          - group: ""
            kind: Secret
            name: app-company-com-tls
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  annotations:
    gateway.networking.k8s.io/generator: ingress2gateway-1.1.0
  name: example-app-company-com
spec:
  hostnames:
    - app.company.com
  parentRefs:
    - name: my-ingress
      port: 443
      sectionName: app-company-com-https
  rules:
    - backendRefs:
        - name: foo-svc
          port: 80
      matches:
        - path:
            type: PathPrefix
            value: /foo
    - backendRefs:
        - name: bar-svc
          port: 80
      matches:
        - path:
            type: PathPrefix
            value: /bar
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  annotations:
    gateway.networking.k8s.io/generator: ingress2gateway-1.1.0
  name: example-app-company-com-http
spec:
  hostnames:
    - app.company.com
  parentRefs:
    - name: my-ingress
      port: 80
  rules:
    - filters:
        - requestRedirect:
            scheme: https
            statusCode: 308
          type: RequestRedirect
      matches:
        - path:
            type: PathPrefix
            value: /foo
    - filters:
        - requestRedirect:
            scheme: https
            statusCode: 308
          type: RequestRedirect
      matches:
        - path:
            type: PathPrefix
            value: /bar

Deploy and test

Apply the Gateway API resources

Before applying the generated resources to the cluster, run a dry-run to catch any syntax or API errors:

 
Terminal box
kubectl apply --dry-run=client -f my-app-gateway-api.yaml

After the dry-run has completed successfully, you can apply the generated resources alongside your existing Ingress. Both can run in parallel during the transition.

 
Terminal box
kubectl apply -f my-app-gateway-api.yaml

Verify the Gateway status

Confirm the Gateway has been accepted and programmed by the Airlock Microgateway Operator before sending any traffic to it:

 
Terminal box
gwctl get gateway my-ingress -o wide

Example output:

 
Example
NAMESPACE  NAME        CLASS                 ADDRESSES     PORTS   PROGRAMMED  AGE   POLICIES  HTTPROUTES
default    my-ingress  airlock-microgateway  192.168.64.2  80,443  True        6m9s  0         2

A Programmed condition set to False, or an unexpected number of listed policies or accepted HTTPRoutes, indicates that something is wrong.

Use gwctl describe gateway my-ingress for detailed information on the status of the gateway, its listeners, the attached routes, and their back-ends. Refer to the troubleshooting guide Analyze Configuration Issues to investigate further what went wrong.

Test connectivity

Use gwctl get gateway my-ingress to obtain Gateway's external IP address and verify that requests are routed correctly:

Example output:

 
Example
NAMESPACE  NAME        CLASS                 ADDRESSES     PORTS   PROGRAMMED  AGE
default    my-ingress  airlock-microgateway  192.168.64.2  80,443  True        6m53s

Use curl to send test requests to your application:

 
Terminal box
curl -H "Host: app.company.com" http://<GATEWAY_IP>:<GATEWAY_PORT>/foo
curl -H "Host: app.company.com" http://<GATEWAY_IP>:<GATEWAY_PORT>/bar

Further information and links