Open-source project
kubernetes-sigs/ingress2gateway avatar
kubernetes-sigs/ingress2gateway

ingress2gateway translates Ingress into Gateway API resources

Convert Ingress resources to Gateway API resources

1,054 stars164 forksGoApache-2.0

At a glance

What is it?
ingress2gateway is a Kubernetes SIG project that reads Ingress objects and provider specific CRDs and prints the equivalent Gateway API resources, with nine input providers and six output emitters. It is a translation tool rather than a controller, it warns about anything it cannot map, and it deliberately refuses to copy Ingress annotations across.
Who is it for?
ingress2gateway suits a platform team that has a large Ingress estate and wants to see what the Gateway API equivalent looks like before committing to a migration, and it suits anyone who wants to check which of their provider specific annotations will survive the move.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 108 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A translator, not a controller

ingress2gateway helps translate Ingress and provider-specific resources, which are CRDs, into Gateway API resources. It is managed by the Gateway API SIG-Network subproject, which means its governance sits with the people who define the API it targets.

The tool's shape is important and is stated in the usage section. It reads Ingress resources and provider-specific CRDs from a Kubernetes cluster or from a file, and it outputs the equivalent Gateway API resources in a YAML, JSON or KYAML format to stdout. It prints. It does not apply, it does not watch, and it does not run as a controller in the cluster.

That makes it a very different kind of tool from the migration controllers people usually reach for. There is no state to reconcile and nothing to keep running. You run it, you read the output, and you decide what to do with it. For a team that wants to know what a migration would look like before anyone commits to it, that is exactly the right shape.

The scope is stated with the same bluntness in the overview. The project is primarily focused on translating Ingress and provider-specific resources to Gateway API resources, and widely used provider-specific annotations and CRDs may still not be supported. Contributions for provider-specific annotations and CRDs are mostly welcomed, as long as they can be translated to Gateway API directly.

And then there is the note that explains a design decision many people would otherwise question. Ingress2gateway is not intended to copy annotations from Ingress to Gateway API. Annotations that have no equivalent in the target API are dropped rather than carried across in a form that nothing would read.

Providers produce an IR, emitters write the output

The architecture has two main components, providers and emitters, and the split is the reason the tool can serve nine different ingress controllers and six different Gateway API projects without becoming nine different tools.

Providers read Ingress resources and provider-specific CRDs and convert them into a generic intermediate representation, the IR. The IR is the shared vocabulary: once an ingress-nginx annotation has been turned into an IR node, it no longer knows anything about ingress-nginx.

Emitters take that IR and produce the final Gateway API output. The default `standard` emitter outputs the core Gateway API resources, such as `Gateway` and `HTTPRoute`. Other emitters can additionally output resources tailored to a specific Gateway API project, and the two examples given are the `EnvoyGateway` `BackendTrafficPolicy` and the `GKE` `HealthCheckPolicy`.

That distinction matters. A provider describes where the configuration came from, and an emitter describes which ecosystem the output belongs to. A cluster running Envoy Gateway needs the core resources plus the Envoy extension, and a cluster running kgateway needs the core resources plus kgateway's own. The IR in the middle is what makes the combination work.

The documentation says a detailed look at the architecture is in `docs/emitters.md`, and the repository layout matches the description, with `pkg/i2gw/providers/` holding a directory per provider and each carrying its own README, and the emitter and shared logic alongside them in `pkg/`.

The Go module shows how heavy the provider support is. The dependencies include the ingress-gce library, the Kong Kubernetes ingress controller, the Istio API, the Envoy Gateway project, the GKE Gateway API project, kgateway and the Helm v4 libraries, along with the Gateway API itself at version 1.5.0. Most of those are client libraries for the resources the providers have to read.

Nine providers, six emitters, and an explicit list of both

The supported providers are apisix, cilium, ingress-nginx, istio, gce, kong, nginx, openapi and traefik. The supported emitters are standard, which is the default, plus agentgateway, airlock-microgateway, envoy-gateway, gce and kgateway.

The documentation is explicit that this list is the current state and that if your provider or a specific feature is not supported, you should open an issue and describe the use case. Contributing a new provider means reading the contributing guide first.

That combination of lists is the honest core of the project. A conversion tool is only as good as the coverage of the annotations it understands, and a provider that is on the list may still not support every annotation, because each provider has its own README documenting what is handled.

The openapi provider is worth singling out, because it is not an ingress controller at all. It reads an OpenAPI 3 description and produces Gateway API resources with a backend service pointing at it, which is the case of a team that has an API description and wants a gateway in front of it without writing ingress by hand.

The project also says contributions are mostly welcomed as long as they can be translated to Gateway API directly. That is the rule that keeps the IR honest. A provider annotation that has no Gateway API equivalent cannot be carried across, and a contribution that tries is not the shape the project can accept.

Four ways to install it, one command to run it

Installation is covered in four ways, which is generous for a tool this size.

With a Go development environment, the documented command is:

bash
go install github.com/kubernetes-sigs/[email protected]

which puts the `ingress2gateway` binary in `$(go env GOPATH)/bin`. Alternatively you can download the binary from the releases page. On macOS and Linux, Homebrew is supported:

bash
brew install ingress2gateway

And the build from source path requires Git and Go 1.25.5 or later, then a clone, a build and an install.

bash
git clone https://github.com/kubernetes-sigs/ingress2gateway.git && cd ingress2gateway
make build
go install .

The version in the go install command is pinned to v1.0.0 in the README even though the current release is v1.2.0, which is a small trap for anyone who copies the line without reading it. The releases are v1.0.0 from 2026-03-20, v1.1.0 from 2026-05-12 and v1.2.0 from 2026-07-07, and the last push was on 2026-07-07, the same day as the newest tag.

The Makefile shows how the binary knows its own version. It runs `git describe --tags --always --dirty` and injects the result into the `pkg/i2gw` package with a linker flag, so the version string in the binary reflects the exact tree it was built from, including a dirty suffix for local builds. The Makefile also pins a kind version for the end to end tests and sets the default `go test` arguments for those tests to include the race detector.

The print command has the flags you would expect

The simplest invocation converts every ingress from one provider, in the example ingress-nginx.

bash
ingress2gateway print --providers=ingress-nginx

The documentation describes what that does in four steps. It reads your kube config file to extract the cluster credentials and the current active namespace, it searches for ingress-nginx resources in that namespace, it converts them to Gateway API resources, and it warns you of any untranslated fields or unsupported features.

The flags on `print` cover the obvious axes. `providers` is the only required one and takes a comma-separated list. `output` with `-o` selects between yaml, json and kyaml, defaulting to yaml. `namespace` with `-n` scopes the invocation, and `all-namespaces` with `-A` lists across all namespaces, in which case the namespace in the current context is ignored even if specified. `emitter` picks the output target and defaults to standard. `kubeconfig` sets the file to use, and if it is not set a set of standard locations are searched. `input-file` reads manifests from files instead of the cluster, supporting YAML and JSON and accepting the flag multiple times. `no-color` disables ANSI colour codes, and `allow-experimental-gw-api` includes experimental Gateway API fields such as URLRewrite in the output.

There are also provider-specific flags, and their presence tells you what each provider needs. There is `gce-gateway-class-name` for the GatewayClass to use, `ingress-nginx-ingress-class` which selects the ingress class and defaults to nginx, and for openapi3 a `openapi3-backend` naming the backend service to use in the HTTPRoutes and an `openapi3-gateway-class-name` for the Gateways.

Reading a file rather than a cluster is the mode that matters for review. With `input-file` you can put a manifest in front of the tool, get the translation, and put the result in a pull request, which makes the conversion reviewable in the way a live controller is not.

It warns instead of guessing

The fourth step of the print command, warning about untranslated fields and unsupported features, is the part that makes this tool usable as a migration aid rather than a curiosity.

A translator that silently drops a field is worse than no translator, because the output looks plausible. The project states its position on this twice. The scope section says that widely used provider-specific annotations and CRDs may still not be supported, and the note says the tool is not intended to copy annotations from Ingress to Gateway API.

Together those two statements mean the output is deliberately a subset. What you get is what can be expressed in the target API, and what you do not get is a list of things to look at.

The `allow-experimental-gw-api` flag is the escape valve in the other direction. By default the output sticks to the standard fields of the Gateway API, and that flag lets experimental fields such as URLRewrite through when a provider's configuration needs them. Since the Gateway API moves between channels as features graduate, that flag is a way to try a feature before it is stable, at the cost of depending on an API that can change.

The KYAML output format is worth a mention for anyone who intends to pipe the result somewhere. YAML, JSON and KYAML are all supported, and KYAML is the Kubernetes-aware YAML variant that keeps the structure of the source objects rather than flattening everything into plain maps, which matters when the output is going to be diffed against the input or processed by another Kubernetes tool.

Where the translation stops

The limits of this project are all consequences of what Gateway API can and cannot express, and of the fact that a translation is a one-time operation rather than a running system.

The first limit is annotation coverage. A provider annotation that configures something Gateway API has no concept of simply cannot be translated, and the project's answer is to warn about it rather than to invent an extension. That is the correct behaviour, but it means an estate that leans heavily on provider specific features will not convert cleanly, and the warnings are the deliverable in that case.

The second limit is that the tool does nothing to the cluster. It prints. It is not a controller, it does not take over routing, and it does not run in the cluster. That is a feature for a review tool and a limitation for a migration, because a real migration also involves moving DNS, changing the load balancer that fronts the ingress controller, and deciding what happens to the annotations that did not convert. ingress2gateway covers the translation step and nothing else.

The third is the emitter coverage. The default standard emitter produces core resources, and the specialised emitters exist for five specific ecosystems. A cluster running a Gateway implementation that is not on the emitter list has the standard output and nothing more, and the project cannot produce, for example, an implementation specific health check policy.

The alternative approach, and the difference in approach is real, is doing the conversion by hand, or with the provider's own migration tooling if it has any. Hand conversion gives you full control over what the Gateway API resources look like and lets you restructure routes rather than translate them one for one, at the cost of a great deal of work and of losing the mechanical comparison. What ingress2gateway gives you is the mechanical comparison, quickly, for the whole namespace at once, with a list of what did not survive, and that is a genuinely hard thing to produce by hand.

Editorial conclusion

ingress2gateway suits a platform team that has a large Ingress estate and wants to see what the Gateway API equivalent looks like before committing to a migration, and it suits anyone who wants to check which of their provider specific annotations will survive the move. It is the wrong tool for a cluster where the Ingress controller stays in charge, because the tool prints YAML and does nothing to the cluster, and it is the wrong tool for annotations that have no Gateway API equivalent, which the project says outright it will not copy. Check first that your provider appears in the supported list and read the warnings the tool prints, because an untranslated field is the output you most need to know about.

Frequently asked questions

What does ingress2gateway do?

It translates Ingress resources and provider-specific CRDs into Gateway API resources, printing the result as YAML, JSON or KYAML to stdout. It can read from a Kubernetes cluster or from manifest files, and it warns about untranslated fields and unsupported features.

Which ingress providers does ingress2gateway support?

The documented list is apisix, cilium, ingress-nginx, istio, gce, kong, nginx, openapi and traefik, each with its own README under `pkg/i2gw/providers/`. The supported emitters are standard, which is the default, plus agentgateway, airlock-microgateway, envoy-gateway, gce and kgateway.

How do I install ingress2gateway?

With `go install github.com/kubernetes-sigs/[email protected]`, by downloading a binary from the releases page, with `brew install ingress2gateway`, or by building from source, which needs Git and Go 1.25.5 or later followed by `make build` and `go install .`.

Does ingress2gateway copy Ingress annotations to the Gateway API resources?

No, and the project states that explicitly. It is not intended to copy annotations from Ingress to Gateway API, and contributions are welcomed as long as they can be translated to Gateway API directly, so annotations with no equivalent are dropped and reported rather than carried across.

Official sources

  1. Issues
  2. kubernetes-sigs/ingress2gateway on GitHub
  3. License: Apache-2.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/kubernetes-sigs-ingress2gateway.svg)](https://hysenlabs.com/projects/kubernetes-sigs-ingress2gateway)

Was this useful?