Cloud-Native AI Kubernetes

Ingress2Gateway Tutorial: Migrating to Kubernetes Gateway API

ingress2gateway is a Kubernetes SIG-Network tool that helps you migrate from Ingress resources and provider-specific Custom Resource Definitions (CRDs) to the Gateway API. This tool is essential for organizations looking to adopt the next generation of Kubernetes traffic management.

What Does It Do?

ingress2gateway reads your existing:

  • Standard Kubernetes Ingress resources
  • Provider-specific annotations and CRDs (like ingress-nginx, Istio, Kong, etc.)

And converts them to:

  • Gateway API resources (Gateways and HTTPRoutes)
  • Standard, portable configuration that works across different implementations

Why Migrate to Gateway API?

The Gateway API is the evolution of Ingress and offers several advantages:

1. Role-Oriented Design

  • Separates concerns between infrastructure providers and application developers
  • Gateway: Managed by infrastructure/platform teams
  • HTTPRoute: Managed by application teams

2. Expressiveness

  • Support for advanced traffic routing (header-based, weighted routing)
  • First-class support for protocols beyond HTTP/HTTPS
  • Better support for TCP, UDP, and gRPC

3. Extensibility

  • Policy attachment mechanism for custom behavior
  • Vendor-specific features can be added without breaking compatibility

4. Portability

  • Standard API that works across different ingress controllers
  • Easier to switch between providers

Prerequisites

Before using ingress2gateway, ensure you have:

  1. Kubernetes Cluster: v1.19+ running with Ingress resources
  2. kubectl: Configured to access your cluster
  3. Go (optional): v1.21+ if building from source
  4. Existing Ingress Resources: Already deployed in your cluster

Installation

Option 1: Using Go Install

# Install latest version
go install github.com/kubernetes-sigs/ingress2gateway@latest

# Or install specific version
go install github.com/kubernetes-sigs/ingress2gateway@v0.4.0

# The binary will be in $(go env GOPATH)/bin
export PATH=$PATH:$(go env GOPATH)/bin

Option 2: Using Homebrew (macOS/Linux)

brew install ingress2gateway

Option 3: Download Binary from Releases

# For Linux
curl -LO https://github.com/kubernetes-sigs/ingress2gateway/releases/download/v0.4.0/ingress2gateway_0.4.0_linux_amd64.tar.gz
tar -xzf ingress2gateway_0.4.0_linux_amd64.tar.gz
sudo mv ingress2gateway /usr/local/bin/

# For macOS
curl -LO https://github.com/kubernetes-sigs/ingress2gateway/releases/download/v0.4.0/ingress2gateway_0.4.0_darwin_amd64.tar.gz
tar -xzf ingress2gateway_0.4.0_darwin_amd64.tar.gz
sudo mv ingress2gateway /usr/local/bin/

Option 4: Build from Source

# Clone the repository
git clone https://github.com/kubernetes-sigs/ingress2gateway.git
cd ingress2gateway

# Build
make build

# The binary will be in the current directory
./ingress2gateway version

Verify Installation

ingress2gateway --help

Basic Usage

Converting All Ingresses from a Provider

The simplest use case is converting all ingresses from a specific provider:

# Convert all ingress-nginx resources in current namespace
ingress2gateway print --providers=ingress-nginx

# Convert from multiple providers
ingress2gateway print --providers=ingress-nginx,istio

Using Different Namespaces

# Convert from specific namespace
ingress2gateway print --providers=ingress-nginx --namespace=production

# Convert from all namespaces
ingress2gateway print --providers=ingress-nginx --all-namespaces

Output to File

# Save output to YAML file
ingress2gateway print --providers=ingress-nginx > gateway-resources.yaml

# JSON output
ingress2gateway print --providers=ingress-nginx --output=json > gateway-resources.json

Converting from File

# Read from file instead of cluster
ingress2gateway print --providers=ingress-nginx --input-file=ingress-resources.yaml

# This is useful for:
# - Testing conversions without cluster access
# - CI/CD pipelines
# - Reviewing changes before applying

Understanding the Conversion

How Ingress Maps to Gateway API

ingress2gateway follows these conversion rules:

1. IngressClass โ†’ GatewayClass

# Before (Ingress)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
spec:
  ingressClassName: nginx  # โ† This becomes gatewayClassName

# After (Gateway)
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
  name: my-gateway
spec:
  gatewayClassName: nginx  # โ† Transferred here

2. Host-based Routing โ†’ Listeners and HTTPRoutes

# Before (Ingress)
spec:
  rules:
  - host: api.example.com    # โ† Creates a listener
    http:
      paths:
      - path: /users
        pathType: Prefix
        backend:
          service:
            name: user-service
            port:
              number: 80

# After (Gateway + HTTPRoute)
# Gateway
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
  name: example-gateway
spec:
  listeners:
  - name: http
    port: 80
    protocol: HTTP
    hostname: api.example.com  # โ† From Ingress host

---
# HTTPRoute
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: api-routes
spec:
  parentRefs:
  - name: example-gateway
  hostnames:
  - api.example.com
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /users
    backendRefs:
    - name: user-service
      port: 80

3. TLS Configuration โ†’ HTTPS Listeners

# Before (Ingress)
spec:
  tls:
  - hosts:
    - secure.example.com
    secretName: tls-secret

# After (Gateway)
spec:
  listeners:
  - name: https
    port: 443
    protocol: HTTPS
    hostname: secure.example.com
    tls:
      mode: Terminate
      certificateRefs:
      - name: tls-secret

4. Default Backend โ†’ Catch-all Route

# Before (Ingress)
spec:
  defaultBackend:
    service:
      name: default-backend
      port:
        number: 80

# After (HTTPRoute)
spec:
  rules:
  - backendRefs:
    - name: default-backend
      port: 80
  # No matches = catch-all

Provider-Specific Migrations

Supported Providers

Example: ingress-nginx with Canary





ingress-nginx’s canary annotations are preserved and converted to weighted routing:

# Original Ingress with canary annotations
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: production
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: app-v1
            port:
              number: 80
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: canary
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "20"
spec:
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: app-v2
            port:
              number: 80

Convert it:

ingress2gateway print --providers=ingress-nginx --input-file=canary-ingress.yaml

Result includes weighted backend refs:

apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: app-routes
spec:
  hostnames:
  - app.example.com
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: app-v1
      port: 80
      weight: 80  # 80% traffic
    - name: app-v2
      port: 80
      weight: 20  # 20% traffic (canary)

Example: Header-based Routing (ingress-nginx)

# Original Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-header: "X-Version"
    nginx.ingress.kubernetes.io/canary-by-header-value: "beta"

# Converts to HTTPRoute with header matching
spec:
  rules:
  - matches:
    - headers:
      - name: X-Version
        value: beta
        type: Exact
    backendRefs:
    - name: app-beta
      port: 80

Advanced Examples

Example 1: Multi-Host Application

Let’s say you have an application with multiple domains:

# Original structure
kubectl get ingress -n myapp
# NAME          CLASS   HOSTS                    ADDRESS   PORTS
# app-ingress   nginx   app.example.com          ...       80, 443
# api-ingress   nginx   api.example.com          ...       80, 443
# admin-ingress nginx   admin.example.com        ...       80, 443

Convert all at once:

ingress2gateway print --providers=ingress-nginx --namespace=myapp > gateway-conversion.yaml

This creates:

  1. One Gateway with multiple listeners (one per host)
  2. Multiple HTTPRoutes (one per domain)
  3. Proper parent references linking routes to gateway

Example 2: Migration Workflow

Here’s a safe migration workflow:

# Step 1: Generate Gateway API resources (don't apply yet)
ingress2gateway print --providers=ingress-nginx \
  --namespace=production \
  > production-gateway.yaml

# Step 2: Review the output
cat production-gateway.yaml

# Step 3: Test in staging first
kubectl create namespace staging-migration
kubectl apply -f production-gateway.yaml -n staging-migration

# Step 4: Install Gateway API controller (e.g., NGINX Gateway Fabric)
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.0.0/standard-install.yaml

# Step 5: Apply to production (run alongside existing Ingress)
kubectl apply -f production-gateway.yaml -n production

# Step 6: Verify traffic routing
curl -H "Host: app.example.com" http://your-gateway-ip/

# Step 7: Update DNS to point to Gateway
# (Implementation depends on your setup)

# Step 8: Monitor for a period

# Step 9: Remove old Ingress resources
kubectl delete ingress --all -n production

Example 3: Complex Path-Based Routing

# Original Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-ingress
spec:
  rules:
  - host: api.example.com
    http:
      paths:
      - path: /v1/users
        pathType: Prefix
        backend:
          service:
            name: users-v1
            port:
              number: 8080
      - path: /v2/users
        pathType: Prefix
        backend:
          service:
            name: users-v2
            port:
              number: 8080
      - path: /v1/orders
        pathType: Prefix
        backend:
          service:
            name: orders-v1
            port:
              number: 8080
      - path: /health
        pathType: Exact
        backend:
          service:
            name: health-check
            port:
              number: 8080

Convert with:

ingress2gateway print --providers=ingress-nginx --input-file=api-ingress.yaml

Results in HTTPRoute with multiple rules, proper path matching, and separate backends.

Example 4: Using OpenAPI Provider

The OpenAPI provider is unique – it converts OpenAPI 3.0 specifications to Gateway API:

# Convert OpenAPI spec to Gateway API
ingress2gateway print \
  --providers=openapi \
  --input-file=api-spec.yaml \
  --openapi3-backend=api-backend \
  --openapi3-gateway-class-name=nginx \
  --openapi3-gateway-tls-secret=api-tls

This is useful for:

  • API-first development
  • Generating infrastructure from API specs
  • Ensuring API definition and routing stay in sync

Best Practices

1. Start Small

Don’t convert your entire production infrastructure at once:

# Convert one namespace first
ingress2gateway print --providers=ingress-nginx --namespace=dev

# Then staging
ingress2gateway print --providers=ingress-nginx --namespace=staging

# Finally production
ingress2gateway print --providers=ingress-nginx --namespace=production

2. Review Before Applying

Always review generated resources:

ingress2gateway print --providers=ingress-nginx | less

Check for:

  • Correct gateway class names
  • Proper TLS configuration
  • Expected host names and paths
  • Backend service references

3. Test in Non-Production First

bash

# Convert and apply to test namespace
ingress2gateway print --providers=ingress-nginx \
  --namespace=production \
  | sed 's/namespace: production/namespace: test/' \
  | kubectl apply -f -

4. Preserve Original Ingress During Migration

Run Gateway API alongside existing Ingress:

# Don't delete Ingress resources immediately
# Apply Gateway API resources
kubectl apply -f gateway-resources.yaml

# Test thoroughly
# Only delete Ingress after validation
# kubectl delete ingress <name>

5. Use Version Control

# Always version control your conversions
git add gateway-resources.yaml
git commit -m "Add Gateway API resources converted from Ingress"

6. Document Provider-Specific Features

If you use provider-specific annotations, document which ones are converted and which need manual attention:

# Create a report
ingress2gateway print --providers=ingress-nginx > converted.yaml
grep -i "nginx.ingress.kubernetes.io" original-ingress.yaml > annotations-used.txt
# Compare to see what was handled

7. Consider Resource Names

# Generated resource names might be long or unclear
# You may want to rename them for clarity
kubectl get gateways
kubectl get httproutes

# Use meaningful names in production

8. Conflict Resolution

ingress2gateway handles conflicts by sorting resources by:

  1. Creation timestamp (oldest first)
  2. Namespace/name (alphabetically)

Understand this when multiple Ingresses might conflict:

# Check creation timestamps
kubectl get ingress --sort-by=.metadata.creationTimestamp

# The oldest takes precedence

9. Handle Limitations

Some features don’t translate directly:

  • Custom annotations may need manual conversion
  • Some provider-specific features might not have Gateway API equivalents
  • Review the conversion output for warnings

10. Performance Testing

After migration, run load tests:

# Example with Apache Bench
ab -n 1000 -c 10 http://your-gateway-endpoint/

# Compare results to Ingress baseline

Troubleshooting

Issue 1: “No ingress resources found”

Problem: The tool can’t find any Ingress resources.

Solutions:

# Check if Ingresses exist
kubectl get ingress --all-namespaces

# Verify namespace
kubectl get ingress -n <namespace>

# Check kubeconfig context
kubectl config current-context

# Specify kubeconfig explicitly
ingress2gateway print --providers=ingress-nginx --kubeconfig=/path/to/config

Issue 2: Gateway Class Not Found

Problem: Generated Gateway references a class that doesn’t exist.

Solution:

# Check available gateway classes
kubectl get gatewayclasses

# Install Gateway API CRDs
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.0.0/standard-install.yaml

# Install a Gateway controller (e.g., NGINX Gateway Fabric)
kubectl apply -f https://github.com/nginxinc/nginx-gateway-fabric/releases/download/v1.0.0/deploy.yaml

Issue 3: TLS Certificate Issues

Problem: HTTPS listeners not working.

Solutions:

# Verify secret exists in correct namespace
kubectl get secret <tls-secret-name> -n <namespace>

# Check secret type
kubectl get secret <tls-secret-name> -o yaml | grep type
# Should be: kubernetes.io/tls

# Verify certificate contents
kubectl get secret <tls-secret-name> -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -text -noout

Issue 4: Routes Not Matching Traffic

Problem: HTTPRoutes created but traffic doesn’t route correctly.

Debug:

# Check HTTPRoute status
kubectl describe httproute <name>

# Verify parent refs
kubectl get httproute <name> -o yaml | grep -A 5 parentRefs

# Check Gateway status
kubectl describe gateway <name>

# Verify listener configurations
kubectl get gateway <name> -o yaml | grep -A 10 listeners

Issue 5: Provider-Specific Annotations Lost

Problem: Some annotations didn’t convert.

Solution:

# Check supported annotations in provider README
cat pkg/i2gw/providers/ingress-nginx/README.md

# For unsupported features:
# 1. Open an issue on GitHub
# 2. Manually implement equivalent in Gateway API
# 3. Use policy attachments if available

Issue 6: Multiple Ingresses to Single Gateway

Problem: Unexpected consolidation of resources.

Explanation: ingress2gateway intelligently merges Ingresses that can share a Gateway:

# This is expected behavior
# Multiple Ingresses with same class โ†’ One Gateway with multiple listeners
# Each Ingress rule โ†’ Separate HTTPRoute

# To verify:
kubectl get gateways
kubectl get httproutes

Issue 7: Output Format Issues

Problem: YAML/JSON output is malformed.

Solutions:

# Try different output format
ingress2gateway print --providers=ingress-nginx --output=json

# Validate YAML
ingress2gateway print --providers=ingress-nginx | yamllint -

# Check for resource conflicts
ingress2gateway print --providers=ingress-nginx 2>&1 | grep -i error

Getting Help

If you encounter issues not covered here:

  1. Check the GitHub Issues: https://github.com/kubernetes-sigs/ingress2gateway/issues
  2. Gateway API Slack: Join #sig-network-gateway-api channel
  3. Community Meetings: Gateway API community meets regularly
  4. Documentation: https://gateway-api.sigs.k8s.io/

Additional Resources

Official Documentation

Example Implementations

Migration Guides


Conclusion

ingress2gateway is a powerful tool for organizations adopting the Gateway API. By following this tutorial, you should be able to:

  1. โœ… Install ingress2gateway
  2. โœ… Convert Ingress resources to Gateway API
  3. โœ… Handle provider-specific features
  4. โœ… Safely migrate production workloads
  5. โœ… Troubleshoot common issues

Remember:

  • Start small and test thoroughly
  • The Gateway API is the future of Kubernetes traffic management
  • Community support is available and active

Happy migrating! ๐Ÿš€


Quick Reference Card

# Basic conversion
ingress2gateway print --providers=ingress-nginx

# Specific namespace
ingress2gateway print --providers=ingress-nginx --namespace=prod

# From file
ingress2gateway print --providers=ingress-nginx --input-file=ingress.yaml

# Multiple providers
ingress2gateway print --providers=ingress-nginx,istio

# JSON output
ingress2gateway print --providers=ingress-nginx --output=json

# Save to file
ingress2gateway print --providers=ingress-nginx > gateway.yaml

# All namespaces
ingress2gateway print --providers=ingress-nginx --all-namespaces

Leave a Reply

Your email address will not be published. Required fields are marked *