惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
News and Events Feed by Topic
V
V2EX
博客园 - 【当耐特】
Vercel News
Vercel News
雷峰网
雷峰网
爱范儿
爱范儿
WordPress大学
WordPress大学
云风的 BLOG
云风的 BLOG
S
Securelist
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Microsoft Azure Blog
Microsoft Azure Blog
F
Full Disclosure
有赞技术团队
有赞技术团队
Hugging Face - Blog
Hugging Face - Blog
NISL@THU
NISL@THU
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Attack and Defense Labs
Attack and Defense Labs
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
Microsoft Security Blog
Microsoft Security Blog
腾讯CDC
P
Proofpoint News Feed
B
Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
K
Kaspersky official blog
I
InfoQ
Google Online Security Blog
Google Online Security Blog
L
LINUX DO - 最新话题
Project Zero
Project Zero
Engineering at Meta
Engineering at Meta
V
Visual Studio Blog
AI
AI
Schneier on Security
Schneier on Security
B
Blog RSS Feed
T
Tor Project blog
H
Help Net Security
H
Hackread – Cybersecurity News, Data Breaches, AI and More
L
LINUX DO - 热门话题
阮一峰的网络日志
阮一峰的网络日志
S
Security @ Cisco Blogs
T
Threat Research - Cisco Blogs
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
C
Cyber Attacks, Cyber Crime and Cyber Security
G
Google Developers Blog
Google DeepMind News
Google DeepMind News
V2EX - 技术
V2EX - 技术
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
A
Arctic Wolf
Webroot Blog
Webroot Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main

Stack Overflow Blog

Paging Charity! How can engineering leaders avoid becoming Bond villains? Code isn’t the only thing causing your production failures Your AI shipped a backend that boots. That is the whole problem. The 2026 Developer Survey is now open (for human developers only)! Oh the places you’ll go with spatial data Dispatches from O'Reilly: From capabilities to responsibilities You don’t understand DNS like you think you do The new bottleneck - Stack Overflow AI agents are a confused deputy with the keys to your kingdom If context is king, architecture is the castle Selenium vs Cypress vs Playwright: Choosing Your Test Automation Framework AI agents expose the security checks you never actually wrote Designing CherryScript: Optimizing Data-Driven Workflows via Custom Python-Based Interpreters Paging Charity? How do I get my leaders to stop running teams Into the ground? Developers are emotionally attached to their tools When the cost of code approaches zero, what does engineering leadership look like? Announcing Stack Overflow for Agents Creating checkpoints by gaslighting a Postgres database What can 500 years of journalism teach developers about AI trustworthiness? Making the OWASP top ten in the vibe code era What it takes to be a player in the international AI game Best of the Heap: First post of the past The find out stage of AI is just supply chain and password protection In an AI world, the most valuable developers will be both artisans and builders Agents on a leash: Agentic AI remains mostly single-agent and monitored at work Do you have what it takes to run AI in production? Dispatches from O'Reilly: The accidental orchestrator Breaking your AI storage bottlenecks Coding agents are giving everyone decision fatigue Pack your agentic stack in Slack Your fridge could be a threat to national security Interviews aren’t about you (sorry) “You can't vibe code scale”: What the AI hype gets wrong about software engineering No Dumb Questions: What is cloud computing and why is everyone doing it? Observability and human intuition in an AI world How Braze’s CTO is rethinking engineering for the agentic area You shipped it fast. But did you ship it right? Building a Google Drive Sync Engine that Survives MV3 Service Workers Connecting the dots for accurate AI When the Sensor Starts Thinking: SnortML, Agentic AI, and the Evolving Architecture of Intrusion Detection OAuth 2.0 – Device flow explained for Engineers, especially for Backend Engineers Introducing the Heap, the software engineering blog for everyone Compile-Time Map and Compile-Time Mutable Variable with C++26 Reflection No Dumb Questions: What is an MCP server and why do I care? AI giveth and AI taketh CPU What (un)exactly do you mean by semantic search? Dispatches from O'Reilly: Fast paths and slow paths Time is a construct but it can still break your software The Worst Coder in the World goes agentic: building a leaderboard cracking AI Turning scattered knowledge into trusted intelligence: Stack Internal 2026.3 Your LLM issues are really data issues Welcome to the “find out” stage of AI Lights, camera, open source! - Stack Overflow Black box AI drift: AI tools are making design decisions nobody asked for How to get multiple agents to play nice at scale We still need developer communities No country left behind with sovereign AI Human input needed: take our survey on AI agents Why AI hasn't replaced human expertise—and what that means for your SaaS stack Who needs VCs when you have friends like these? The messy truth of your AI strategies Gen Z needs a knowledge base (and so do you) He designed C++ to solve your code problems Seizing the means of messenger production What the AI trust gap means for enterprise SaaS How can you test your code when you don’t know what’s in it? Prevent agentic identity theft - Stack Overflow Building shared coding guidelines for AI (and people too) Multi-stage attacks are the Final Fantasy bosses of security After all the hype, was 2025 really the year of AI agents? AI is becoming a second brain at the expense of your first one Building a global engineering team (plus AI agents) with Netlify Keeping the lights on for open source Domain expertise still wanted: the latest trends in AI-assisted knowledge for developers Open source for awkward robots The context problem: Why enterprise AI needs more than foundation models Even the chip makers are making LLMs Organizing productive platform teams - Stack Overflow Building brains for bulldozers - Stack Overflow DeveloperWeek 2026: Making AI tools that are actually good AI-assisted coding needs more than vibes; it needs containers and sandboxes No need for Ctrl+C when you have MCP What’s new at Stack Overflow: March 2026 To live in an AI world, knowing is half the battle Beyond block or allow: How pay-per-crawl is reshaping public data monetization Your sneak peek at the redesigned Stack Overflow Dogfood so nutritious it’s building the future of SDLCs Defense against uploads: Q&A with OSS file scanner, pompelmi Even GenAI uses Wikipedia as a source Why Stack Overflow and Cloudflare launched a pay-per-crawl model Mind the gap: Closing the AI trust gap for developers Data is the new oil, and your database is the only way to extract it Even your voice is a data problem How everyone and anyone can use AI for good Is anyone using AI for good? The logos, ethos, and pathos of your LLMs Why demand for code is infinite: How AI creates more developer jobs AI attention span so good it shouldn’t be legal Code smells for AI agents: Q&A with Eno Reyes of Factory Generating text with diffusion (and ROI with LLMs)
How we replaced Ingress-NGINX at Stack Overflow
Michael Frank · 2026-05-07 · via Stack Overflow Blog

Back in November of last year when the announcement was made that Ingress-NGINX was being retired, we, like many others, were caught a bit off guard. Ingress-NGINX had been handling our traffic routing since moving to Kubernetes. There were some discussions about the new Gateway API that supersedes Ingress, and whether it might be useful to move to it, but no serious amount of energy was invested. Ingress-NGINX was working fine, and we had plenty of other work to do. Now, with our hand being forced by the retirement, we needed to make a plan and fit it into the near term road map.

With a vast landscape of options, we needed to limit the possibilities before we started installing some implementations and testing them. We were pretty sure we’d like to use this opportunity to move to Gateway API, rather than another Ingress controller, and take advantage of the new features and better role separation. We also needed to get this done quickly however, so moving to another Ingress implementation could also be an option, if there were headwinds moving to Gateway API.

With some initial research, we established some criteria to narrow the playing field to three Gateway implementations and two Ingress options as a backup.

  • NGINX Gateway fabric
  • Traefik
  • Istio
  • F5 NGINX ingress
  • Traefik

Our first criteria was that our replacement had to be on the list of fully-conformant implementations. This would give us a good baseline for comparison. We run in GCP and Azure, so that eliminated any cloud specific solutions. From there, we looked at the 1.4 feature matrix, a third-party benchmark, and some of the unique features of each implementation. This left us with the three aforementioned options.

Sadly, our old friend HAProxy was on the list of stale implementations when we started this project. We used HAProxy in the data center reliably for many years, before moving Stack Overflow to GKE. It definitely would have made the cut for testing. At the time of writing, it’s moved to fully conformant.

As far as backup options for sticking with Ingress, Traefik made a compelling case with its annotation compatibility with NGINX. In practice, most of the annotations we were using weren’t covered, so that option lost its luster. The F5 NGINX ingress implementation looked to potentially be a safe bet, but we found the advanced routing relied on implementation-specific resources rather than the standard Kubernetes types. This causes problems when you try to integrate other controllers that rely on the standard interfaces being used.

Ultimately, we couldn’t make the case for switching to another ingress, so we dropped these from testing pretty early.

In order to build out our use cases for testing, we dumped all of the ingress objects on our main production clusters to YAML files, and used Claude to analyze and sort them into different use case buckets. Most of our routing was very straightforward, with a few outliers. This left us with roughly half a dozen use case tests to write, along with two different scalability benchmarks to run.

For the test setup, the main backend was an HTTPBin deployment. It’s a great tool for testing anything HTTP related, allowing you to introspect both the request and response from a test client. A good example of this: we have a case where we need to dynamically overwrite host headers for some specific traffic. HTTPBin has a /headers endpoint that will return the request headers back as a JSON response. That allows us to write a test case where we send host header X, and expect the server to get host header Y.

A second backend was deployed at perf.This was a very simple Go web server that should be able to respond to a large number of requests very quickly. This will allow us to push the request rate of the gateway very high to see where the performance limitations are. A parameter was added to the web server to allow us to pass in a latency value to simulate slower responses, in order to test performance where the number of connections and active requests begin to pile up. I was unaware, but HTTPBin has an endpoint with this same capability. I was unsure about the performance of HTTPBin under heavy load so the tests use the Go server instead. The testing setup looked like this.

A detailed flowchart illustrating the architecture of external traffic routing through various gateways, ingress controllers, and backend services. 

- External Traffic: Client requests are routed through gateways such as Istio Gateway, Traefik Gateway, and NGINX Gateway Fabric, each handling HTTP (port 80) and HTTPS (port 443) traffic with 301 redirects.
- Ingress Controllers: Includes ingress-nginx, traefik-ingress, and f5-nginx-ingress, each associated with specific domains.
- Routing Rules: Traffic is directed based on paths such as /, /perf, and /{random_id}.
- Backend Services: Requests are routed to services like ingresstest-httpbin (port 80), perf-test (port 8080), and path-test (port 8080).
- Deployments: Backend services are deployed with specific images, such as kennethreitz/httpbin:latest and go-server.

The diagram uses color-coded boxes and arrows to represent the flow of traffic and connections between components.

Setup for the three implementations was fairly simple, though one initial annoyance I found with Traefik was the need to configure a Traefik “entrypoint”. This is a Traefik specific piece of configuration that sets up a TCP listener. If you don’t add this and create a gateway, the listeners you add to the gateway will throw an error. This breaks the gateway abstraction to some degree.

All three implementations were able to handle our use cases. Of the Gateway API features that were interesting to us, Istio checked the most boxes and Traefik the least. One thing we found out quickly is some of the Gateway API features looked good on paper, but lacked the depth we needed. For example, the header modification feature in HTTPRoute only handles static values. In the aforementioned case where we needed a dynamic regex, we had to fall back to each implementation’s extension points. These were all flexible enough to meet our needs and allowed referencing different behavior from the context of an xRoute or Gateway depending on your needs and the function performed. For the cases we tested, the Istio filters were significantly more complex syntactically than the NGINX or Traefik equivalent.

In some cases, implementation-specific behavior changed enough that we had to modify our applications to get it working. We’re currently using ngx_http_auth_request_module to forward requests to an authentication service. The other implementations have similar functionality, but Istio’s external authorization has significantly different behavior. Complex integrations like these are pain points and slow things down considerably when you have to migrate to a new solution.

I love performance analysis, so it’s very easy for me to go down rabbit holes and collect very detailed information. In this instance, with time and resources very limited, I had to be sure I was keeping things simple and practical. It’s likely at some scale, there would be very clear winners and losers. But we weren’t trying to perform a generic benchmark comparison. We simply needed to know if these implementations would meet our current scalability requirements.

We had two primary scaling factors we needed to test. For our public Stack Exchange network of sites, we needed to verify that each implementation could handle some multiple of our daily traffic with a reasonable number of replicas. For our enterprise product, each customer currently gets eight Ingress resources, so we want to test scaling the number of HTTPRoutes.

For the RPS benchmark against the gateways, we chose a target of 10,000 RPS, which would leave us some headroom above our normal steady state traffic. After some experimental rounds of testing, we set the test environment to have four replicas of each gateway, each on a separate node. These were e2-standard-4 GCP compute nodes. For the test client, we run K6 on a machine configured to handle the high number of connections. The client ran on an Azure Standard_DC8as_cc_v5 instance.

We ran the tests with 0, 150, and 350ms of simulated server latency. All three implementations handled these initial tests without issue. The results from all the tests are relatively similar. Here are the results of the 150ms latency test run.

http_req_duration..............: avg=188.27ms min=176ms

med=180.22ms max=820.56ms p(90)=195.11ms p(95)=219.31ms

http_req_duration..............: avg=205.34ms min=176.15ms

med=183.13ms max=1.83s p(90)=244.14ms p(95)=297.59ms

http_req_duration..............: avg=186.73ms min=176.03ms

med=180.52ms max=3.48s p(90)=194.34ms p(95)=216.32ms

Initially, we ran this test with a target of 5000 HTTPRoutes. While all three successfully handled converging on this number of routes, we find out later that our practical limit is much lower. I read in this third-party benchmark about a few problems with Traefik and NGINX and their handling of routing changes. We set up a similar test that created 5000 HTTPRoutes, each with a single path rule, and concurrently sent requests to those paths until they returned the correct response. This allowed us to see that they were all being routed correctly.

While we didn’t see the exact issues from the third-party tests where Traefik didn’t load all the routes, we did see it take significantly longer than the other two implementations. You can see here the original test failing for Traefik since it timed out after five minutes. Traefik did load all the routes, taking only slightly longer than the five minute timeout.

=== RUN TestRoutedPaths

=== RUN TestRoutedPaths/gw-nginx

gateway_test.go:443: 5000/5000 paths pending, retrying in 5s

gateway_test.go:443: 105/5000 paths pending, retrying in 5s

gateway_test.go:443: 105/5000 paths pending, retrying in 5s

gateway_test.go:443: 87/5000 paths pending, retrying in 5s

gateway_test.go:335: applied 5000 HTTPRoutes

gateway_test.go:443: 3/5000 paths pending, retrying in 5s

gateway_test.go:431: all 5000 routes converged in 42.047s

=== RUN TestRoutedPaths/gw-istio

gateway_test.go:443: 5000/5000 paths pending, retrying in 5s

gateway_test.go:443: 1167/5000 paths pending, retrying in 5s

gateway_test.go:443: 93/5000 paths pending, retrying in 5s

gateway_test.go:443: 93/5000 paths pending, retrying in 5s

gateway_test.go:443: 32/5000 paths pending, retrying in 5s

gateway_test.go:443: 32/5000 paths pending, retrying in 5s

gateway_test.go:335: applied 5000 HTTPRoutes

gateway_test.go:431: all 5000 routes converged in 41.981s

=== RUN TestRoutedPaths/gw-traefik

gateway_test.go:443: 5000/5000 paths pending, retrying in 5s

gateway_test.go:443: 4939/5000 paths pending, retrying in 5s

gateway_test.go:443: 4921/5000 paths pending, retrying in 5s

gateway_test.go:335: applied 5000 HTTPRoutes

gateway_test.go:443: 4871/5000 paths pending, retrying in 5s

gateway_test.go:443: 4856/5000 paths pending, retrying in 5s

gateway_test.go:443: 4833/5000 paths pending, retrying in 5s

gateway_test.go:443: 4827/5000 paths pending, retrying in 5s

gateway_test.go:443: 4823/5000 paths pending, retrying in 5s

gateway_test.go:443: 4820/5000 paths pending, retrying in 5s

gateway_test.go:443: 4816/5000 paths pending, retrying in 5s

gateway_test.go:443: 4811/5000 paths pending, retrying in 5s

...

--- FAIL: TestRoutedPaths (441.53s)

--- PASS: TestRoutedPaths/gw-nginx (56.68s)

--- PASS: TestRoutedPaths/gw-istio (79.96s)

--- FAIL: TestRoutedPaths/gw-traefik (304.88s)

--- FAIL: TestRoutedPaths (410.94s)

--- PASS: TestRoutedPaths/gw-nginx (60.82s)

--- PASS: TestRoutedPaths/gw-istio (46.98s)

--- FAIL: TestRoutedPaths/gw-traefik (303.13s)

Once we had the gateway loaded with 5000 routes, we discovered this was too ambitious a target. Running the previous K6 benchmark that generated 10k RPS through the gateway failed miserably. Latency times were incredibly high and the number of active requests would climb until the test client exploded. Since we’d probably never need more than 1,000 routes on a single gateway, we revised this target down and reran the K6 benchmark again. This time response times were similar to our original results.

We also tested modifying the routes while the K6 traffic test ran. Istio and Traefik remained unaffected, but NGINX saw significant latency spikes when even a single HTTPRoute was updated, when there were 1,000 routes configured. You can see in the graph the two large latency spikes that occurred during route updates.

A dashboard from k6, a performance testing tool, displaying four graphs:

1. Virtual Users: A line chart showing the number of virtual users over time, peaking at around 3,500 users between 17:45 and 17:46.
2. HTTP Request Duration: A line chart showing the duration of HTTP requests in seconds, with noticeable spikes around 17:45.
3. Requests Per Second: A line chart showing the number of requests per second, peaking at around 10,000 requests between 17:45 and 17:46.
4. Response Timings (95th Percentile): A bar chart showing response times in seconds, with significant spikes around 17:45.

The graphs provide insights into system performance during a load test.

After performing all of our testing and analyzing the features and characteristics of these three implementations, we have decided to move forward with Istio. The primary factor being Istio’s stability and performance through all of the testing. I believe we could be successful with any of the options, but in the end Istio seemed the most solid of the three. The fact that it has many advanced features beyond our current use case is also interesting.

In the coming weeks we’ll be performing the migration. If we run into anything of note I’ll be glad to write a follow-up post to share what we found.