---
title: "Migrating from Ingress to Gateway API"
sidebar_label: "Migrating from Ingress to Gateway API"
sidebar_position: 3
description: "Differences between Ingress and Gateway API, migration principle, and migration example from Ingress to Envoy Gateway"
---

import Formbricks from '@theme/MDXComponents/Formbricks'
import Tabs from '@theme/Tabs'
import TabItem from '@theme/TabItem'
import {TabItemLabel} from '@selectel/docux/components'

# Migrating from Ingress to Gateway API

Gateway API is a modern alternative to Ingress. In Ingress, the functions of a load balancer and routing rule management are combined in a single Service object of the LoadBalancer type. In Gateway API, two separate objects are used for this:

* Gateway — defines network entry points and traffic routing rules to the cluster;
* HTTPRoute — defines traffic routing rules to services.

This separation makes infrastructure easier to maintain. For more details on the differences between Ingress and Gateway API, see the [Key Differences Between Ingress API and Gateway API](https://gateway-api.sigs.k8s.io/guides/getting-started/migrating-from-ingress/#key-differences-between-ingress-api-and-gateway-api) guide in the [Migrating from Ingress](https://gateway-api.sigs.k8s.io/guides/getting-started/migrating-from-ingress/#migrating-from-ingress) section of the Gateway API documentation.

## Migration principle \{#migration-principle}

When working with Ingress and Gateway API, different Kubernetes objects are used. Main objects:

* Ingress — IngressClass and Ingress;
* Gateway API — GatewayClass, Gateway and HTTPRoute.

To migrate, you need to replace Ingress objects with Gateway API objects.

To simplify migration, some objects can be converted automatically using a utility:

* `ingress2gateway` — an official utility. It converts Ingress objects to Gateway API objects. For example, a Service object of the LoadBalancer type into Gateway and HTTPRoute objects;
* or `ingress2eg` — an unofficial experimental version of the `ingress2gateway` utility. Additionally, it generates objects from NGINX annotations that are specific to Envoy Gateway CRD (Custom Resource Definition). For example, BackendTrafficPolicy and SecurityPolicy.

Objects that cannot be converted automatically must be added manually. For example, a GatewayClass object.

## Migration example from Ingress NGINX to Envoy Gateway \{#example-migration-from-nginx-to-envoy-gateway}

1. [Check quotas](#check-quotas).
2. [Install Envoy Gateway](#install-envoy-gateway).
3. [Create an EnvoyProxy object](#create-envoyproxy).
4. [Create a GatewayClass object](#create-gatewayclass).
5. [Convert Ingress objects to Gateway API](#transform-objects-into-gateway-api).

### 1. Check quotas \{#check-quotas}

Ensure that the pool has a [quota](/access-control/projects/quotas.mdx) for at least one public floating IP address and cloud load balancer. To do this, [view your cloud platform quota consumption](/access-control/projects/quotas.mdx#view-consumption).

### 2. Install Envoy Gateway \{#install-envoy-gateway}

Follow the instructions on how to [install Envoy Gateway](/managed-kubernetes/networks/loadbalancing-with-envoy-gateway/envoy-gateway.mdx#install-envoy-gateway).

### 3. Create an EnvoyProxy object \{#create-envoyproxy}

1. Create a YAML file `envoyproxy.yaml` with the manifest for the EnvoyProxy object.

   EnvoyProxy manifest example:

   ```yaml
   apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: EnvoyProxy
   metadata:
     name: custom-proxy-config
     namespace: default
   spec:
     provider:
       type: Kubernetes
       kubernetes:
         envoyDaemonSet: {}
         envoyService:
           externalTrafficPolicy: Cluster
   ```

   Where:

   * `externalTrafficPolicy: Cluster` indicates that all nodes will participate in traffic balancing;
   * `envoyDaemonSet: {}` indicates that Envoy replicas will be launched on all nodes.

2. Apply the manifest:

   ```bash
   kubectl apply -f envoyproxy.yaml
   ```

   Here, `envoyproxy.yaml` is the name of the YAML file with the manifest for creating the EnvoyProxy object.

3. Ensure that the EnvoyProxy object is created:

   ```bash
   kubectl get envoyproxy -n default
   ```

### 4. Create a GatewayClass object \{#create-gatewayclass}

To use HTTPRoutes, you need a GatewayClass that will be associated with the Envoy Gateway controller.

1. Create a YAML file `gatewayclass.yaml` with the manifest for the GatewayClass object.

   GatewayClass manifest example:

   ```yaml
   apiVersion: gateway.networking.k8s.io/v1
   kind: GatewayClass
   metadata:
     name: eg
   spec:
     controllerName: gateway.envoyproxy.io/gatewayclass-controller
     parametersRef:
       group: gateway.envoyproxy.io
       kind: EnvoyProxy
       name: custom-proxy-config
       namespace: default
   ```

2. Apply the manifest:

   ```bash
   kubectl apply -f gatewayclass.yaml
   ```

   Here, `gatewayclass.yaml` is the name of the YAML file with the manifest for creating the GatewayClass object.

3. Ensure that the GatewayClass object is created:

   ```bash
   kubectl get gatewayclass
   ```

### 5. Convert Ingress objects to Gateway API \{#transform-objects-into-gateway-api}

If you are using NGINX with annotations, use the `ingress2eg` utility.

<Tabs queryString="utility-for-migration">
  <TabItem value="ingress2gateway" default>
    <TabItemLabel>
      ingress2gateway
    </TabItemLabel>

    1. Install the [ingress2gateway](https://github.com/kubernetes-sigs/ingress2gateway/blob/main/README.md#installation) utility.

    2. Convert Ingress objects to Gateway API objects. All changes will only be printed to the console and will not be applied automatically. For example:

       ```bash
       ingress2gateway print -A --providers ingress-nginx > gateway-resources.yaml
       ```

       Where:

       * `--providers ingress-nginx` — a flag for the controller you are migrating from;
       * `-A` — a flag indicating that Ingress manifests should be looked up in all namespaces (namespaces);
       * `gateway-resources.yaml` is the name of the YAML file with the manifests for the new objects.

    3. Open the saved file `gateway-resources.yaml`.

    4. If a Gateway manifest was generated:

       4.1. In the `gatewayClassName` field, replace `nginx` with `eg`.

       4.2. If you are using HTTPS, specify the path to the secret containing the domain certificate.

       Gateway manifest example for HTTPS protocol:

       ```yaml
       apiVersion: gateway.networking.k8s.io/v1
       kind: Gateway
       metadata:
         name: example-gateway
         namespace: default
       spec:
         gatewayClassName: eg
         listeners:
           - name: https
             hostname: "*.example.com"
             port: 443
             protocol: HTTPS
             allowedRoutes:
               namespaces:
                 from: All
             tls:
               mode: Terminate
               certificateRefs:
                 - name: wildcard-certname-tls
                   namespace: secret-namespace
                   kind: Secret
       ```

    5. Create the objects specified in the manifests:

       ```bash
       kubectl apply -f gateway-resources.yaml
       ```

    6. Ensure that all objects are created:

       ```bash
       kubectl get gateways -A
       kubectl get httproutes -A
       ```

    7. Ensure that your services are available via the new IP address that was automatically assigned to the new cloud load balancer. You can view the load balancer IP address in the [Control Panel](https://my.selectel.ru/vpc/default/lbaas/load-balancers/): in the top menu, click **Products** and select **Cloud Servers** → **Load Balancers** section → **Load Balancers** tab → load balancer card.
  </TabItem>

  <TabItem value="ingress2eg">
    <TabItemLabel>
      ingress2eg
    </TabItemLabel>

    1. Install [ingress2eg](https://github.com/kkk777-7/ingress2eg?tab=readme-ov-file#installation).

    2. Check the original Ingress object with NGINX annotations.

       Example of an Ingress object with NGINX annotations for rate limiting and CORS:

       ```bash
       apiVersion: networking.k8s.io/v1
       kind: Ingress
       metadata:
         name: example-ingress-nginx
         namespace: default
         annotations:
           nginx.ingress.kubernetes.io/limit-rps: "10"
           nginx.ingress.kubernetes.io/enable-cors: "true"
           nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, OPTIONS"
           nginx.ingress.kubernetes.io/cors-allow-origin: "https://example.com"
       spec:
         rules:
         - host: example.com
           http:
             paths:
             - path: /api
               pathType: Prefix
               backend:
                 service:
                   name: api-service
                   port:
                     number: 80
       ```

    3. Convert Ingress objects to Gateway API objects and save them to the `gateway-resources.yaml` file:

       ```bash
       ingress2eg print --namespace default > gateway-resources.yaml
       ```

    4. Open the saved file `gateway-resources.yaml`.

    5. In the `gateway-resources.yaml` file, check the generated objects. The `ingress2eg` utility can generate the following objects:

       * Gateway;
       * HTTPRoute;
       * objects specific to Envoy Gateway CRD (Custom Resource Definition). For example, BackendTrafficPolicy and SecurityPolicy.

       <details>
         <summary>BackendTrafficPolicy object example formed from the `limit-rps` annotation</summary>

         ```bash
           apiVersion: gateway.envoyproxy.io/v1alpha1
           kind: BackendTrafficPolicy
           metadata:
             name: rate-limit-policy
             namespace: default
           spec:
             targetRefs:
             - group: gateway.networking.k8s.io
               kind: HTTPRoute
               name: example-httproute
             rateLimit:
               type: Local
               local:
                 rules:
                 - clientSelectors:
                   - sourceCIDR:
                       type: Distinct
                       value: 0.0.0.0/0
                   limit:
                     requests: 10
                     unit: Second
         ```
       </details>

       <details>
         <summary>SecurityPolicy object example formed from CORS annotations `enable-cors`, `cors-allow-methods`, and `cors-allow-origin`</summary>

         ```yaml
         apiVersion: gateway.envoyproxy.io/v1alpha1
         kind: SecurityPolicy
         metadata:
           name: cors-policy
           namespace: default
         spec:
           targetRefs:
           - group: gateway.networking.k8s.io
             kind: HTTPRoute
             name: example-httproute
           cors:
             allowOrigins:
             - "https://example.com"
             allowMethods:
             - GET
             - POST
             - OPTIONS
         ```
       </details>

    6. Create the objects specified in the manifests:

       ```bash
       kubectl apply -f gateway-resources.yaml
       ```

    7. Ensure that all objects are created:

       ```bash
       kubectl get gateways -A
       kubectl get httproutes -A
       kubectl get backendtrafficpolicies -A
       kubectl get securitypolicies -A
       ```

    8. Check the status of BackendTrafficPolicy and SecurityPolicy objects:

       ```bash
       kubectl describe backendtrafficpolicy rate-limit-policy
       kubectl describe securitypolicy cors-policy
       ```

       In the response, the status will appear in the `Status.Conditions` field. For example:

       ```bash
       Status:
         Conditions:
         - LastTransitionTime:  2025-04-05T10:30:22Z
           Message:           Policy applied successfully
           Reason:            Applied
           Status:            True
           Type:              Accepted
         - LastTransitionTime:  2025-04-05T10:30:22Z
           Message:           Policy is ready
           Reason:            Ready
           Status:            True
           Type:              Programmed
         ObservedGeneration:  1
       ```

    9. Ensure that your services are available via the new IP address that was automatically assigned to the new cloud load balancer. You can view the load balancer IP address in the [Control Panel](https://my.selectel.ru/vpc/default/lbaas/load-balancers/): in the top menu, click **Products** and select **Cloud Servers** → **Load Balancers** section → **Load Balancers** tab → load balancer card.
  </TabItem>
</Tabs>

<Formbricks />
