<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Alek&#x27;s Blog - networking</title>
    <subtitle>Production notes on Kubernetes, OpenShift, and OVHcloud: observability, log archiving, service mesh, LLM inference, and digital sovereignty.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://blog.none.at/tags/networking/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://blog.none.at"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-07-18T00:00:00+00:00</updated>
    <id>https://blog.none.at/tags/networking/atom.xml</id>
    <entry xml:lang="en">
        <title>ingress-nginx Annotation Compatibility Matrix</title>
        <published>2026-07-18T00:00:00+00:00</published>
        <updated>2026-07-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-07-18-ingress-nginx-annotation-matrix/"/>
        <id>https://blog.none.at/blog/2026/2026-07-18-ingress-nginx-annotation-matrix/</id>
        
        <summary type="html">&lt;p&gt;Part 2 built the inventory. This part answers the question that inventory exists to feed: for the
annotations that actually turn out to be hard cases — not every annotation, but the ones where the
answer isn’t obvious — does migration go cleanly, or does it silently break? The honest answer
changes row by row — and, in one case in this matrix, changes depending on the &lt;em&gt;value&lt;&#x2F;em&gt; of the
annotation, not just its name.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>ingress-nginx Replacement Candidates: Envoy, HAProxy, NGINX</title>
        <published>2026-07-18T00:00:00+00:00</published>
        <updated>2026-07-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-07-18-ingress-nginx-candidates/"/>
        <id>https://blog.none.at/blog/2026/2026-07-18-ingress-nginx-candidates/</id>
        
        <summary type="html">&lt;p&gt;Part 3 answered which annotations survive a migration and which don’t. This part answers the
question that matrix exists to feed into: given those findings, which target do you actually move
to? Five candidates get the same source-verified depth as Part 3’s matrix here — not because the other
seven considered for this series are less real, but because “tested with the same rigor” and
“worth a mention” are different claims, and this guide tries not to blur them.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>ingress-nginx Hard Cases: Auth, Rate Limits, gRPC, Snippets</title>
        <published>2026-07-18T00:00:00+00:00</published>
        <updated>2026-07-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-07-18-ingress-nginx-hard-cases/"/>
        <id>https://blog.none.at/blog/2026/2026-07-18-ingress-nginx-hard-cases/</id>
        
        <summary type="html">&lt;p&gt;Every earlier part of this series was research: read the source, read the docs, verify a claim
against a repo. This one is different. A real OVH Managed Kubernetes Service (MKS) cluster, a real
domain, one deliberately nasty sample application, and the exact same 10-request test script run
against ingress-nginx, then Envoy Gateway, then HAProxy Unified Gateway. Every result below is a
real HTTP response or a real line read out of a running pod, not a docs claim.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>ingress-nginx Inventory: Annotations, ConfigMaps, Flags</title>
        <published>2026-07-18T00:00:00+00:00</published>
        <updated>2026-07-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-07-18-ingress-nginx-inventory/"/>
        <id>https://blog.none.at/blog/2026/2026-07-18-ingress-nginx-inventory/</id>
        
        <summary type="html">&lt;p&gt;Most migration guides start by comparing replacement Ingress controllers. That’s the wrong first
step. The first step is finding out which &lt;code&gt;ingress-nginx&lt;&#x2F;code&gt; behaviours your own clusters actually
depend on — because the answer changes which controller (or Gateway API implementation) is even a
candidate, and it’s usually smaller than a full annotation reference makes it look.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>ingress-nginx Migration: A Field Guide</title>
        <published>2026-07-18T00:00:00+00:00</published>
        <updated>2026-07-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-07-18-ingress-nginx-migration-field-guide/"/>
        <id>https://blog.none.at/blog/2026/2026-07-18-ingress-nginx-migration-field-guide/</id>
        
        <summary type="html">&lt;p&gt;This is the index for a field guide to migrating away from &lt;code&gt;ingress-nginx&lt;&#x2F;code&gt;, the Kubernetes Ingress
controller that was archived and retired in March 2026. Each part stands on its own, but together
they cover the whole path: deciding whether to act, finding out what you actually depend on,
knowing which annotations translate cleanly, choosing a target, and doing the migration itself
without a flag day.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>ingress-nginx Migration Mechanics: ingress2gateway and Cutover</title>
        <published>2026-07-18T00:00:00+00:00</published>
        <updated>2026-07-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-07-18-ingress-nginx-migration-mechanics/"/>
        <id>https://blog.none.at/blog/2026/2026-07-18-ingress-nginx-migration-mechanics/</id>
        
        <summary type="html">&lt;p&gt;Parts 3 through 5 answered what migrates cleanly and to which target. This part answers the
question every migration guide owes its reader eventually: how do you actually move traffic without
a flag day? A converter tool, a coexistence window, a staged cutover, and — the section every
migration plan needs but few write down — an actual rollback plan.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>ingress-nginx Alternatives: Cilium, Traefik, Kong, AKS, GKE</title>
        <published>2026-07-18T00:00:00+00:00</published>
        <updated>2026-07-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-07-18-ingress-nginx-other-paths/"/>
        <id>https://blog.none.at/blog/2026/2026-07-18-ingress-nginx-other-paths/</id>
        
        <summary type="html">&lt;p&gt;Part 4 covered the five candidates source-verified with the same depth as the Part 3 matrix. This
part covers the rest of what this series set out to compare: three candidates this series tests but
doesn’t deep-dive — Cilium, Traefik, Kong — and a survey of what migrating off ingress-nginx looks
like on four managed Kubernetes platforms that were never part of the empirical lab at all.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>ingress-nginx Retirement: Four Ways Forward</title>
        <published>2026-07-18T00:00:00+00:00</published>
        <updated>2026-07-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-07-18-ingress-nginx-retirement-decision/"/>
        <id>https://blog.none.at/blog/2026/2026-07-18-ingress-nginx-retirement-decision/</id>
        
        <summary type="html">&lt;p&gt;The &lt;code&gt;ingress-nginx&lt;&#x2F;code&gt; Kubernetes controller is not “retiring soon.” It already has. The GitHub
repository was archived and made read-only on 2026-03-24, and its own description now reads in the
past tense: it &lt;em&gt;was&lt;&#x2F;em&gt; an Ingress controller. For a piece of software that reportedly still runs in
front of roughly half of all cloud-native workloads, that is a completed fact, not a countdown.&lt;&#x2F;p&gt;
&lt;p&gt;This is Part 1 of a field guide to migrating away from it. This part is deliberately
non-technical — it is for whoever has to decide &lt;em&gt;what to do&lt;&#x2F;em&gt;, not yet for whoever will do the
migration work. Parts 2 onward get concrete: inventorying what you actually depend on, an
annotation compatibility matrix, migration mechanics, and a reproducible lab.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>Istio AuthorizationPolicy &amp; HTTP&#x2F;2 Coalescing</title>
        <published>2026-07-13T00:00:00+00:00</published>
        <updated>2026-07-13T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-07-13-istio-authorizationpolicy-http2-coalescing/"/>
        <id>https://blog.none.at/blog/2026/2026-07-13-istio-authorizationpolicy-http2-coalescing/</id>
        
        <summary type="html">&lt;p&gt;Isolating an admin surface behind its own hostname and an IP-restricted
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;istio.io&quot;&gt;Istio&lt;&#x2F;a&gt; &lt;code&gt;AuthorizationPolicy&lt;&#x2F;code&gt; sounds like a Tuesday-afternoon change: add a
second &lt;code&gt;HTTPRoute&lt;&#x2F;code&gt;, add a &lt;code&gt;DENY&lt;&#x2F;code&gt; policy with an allowlist, done. Two non-obvious Envoy behaviors
turned it into a two-day debugging exercise instead — one in how &lt;code&gt;AuthorizationPolicy&lt;&#x2F;code&gt; resolves
“the client’s IP,” and one in how browsers reuse HTTP&#x2F;2 connections across hostnames that share a
certificate. Neither is specific to Keycloak or to this particular setup; both apply to any Istio
or Envoy Gateway API ingress sitting behind a cloud load balancer with a shared wildcard
certificate.&lt;&#x2F;p&gt;
&lt;p&gt;This post walks through both bugs, how they were root-caused, and the fix for each — so the next
person hitting either symptom can skip straight to the cause.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>Istio vs. Linkerd: Service Mesh on Kubernetes</title>
        <published>2026-05-12T00:00:00+00:00</published>
        <updated>2026-05-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-05-12-istio-vs-linkerd/"/>
        <id>https://blog.none.at/blog/2026/2026-05-12-istio-vs-linkerd/</id>
        
        <summary type="html">&lt;p&gt;Both &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;istio.io&quot;&gt;Istio&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;linkerd.io&quot;&gt;Linkerd&lt;&#x2F;a&gt; are CNCF Graduated service
meshes that provide automatic mTLS, traffic policy, and observability for Kubernetes
workloads. Both run in sidecar mode for this comparison — a proxy container injected into
every pod. The fundamental difference is the data plane: Istio uses
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.envoyproxy.io&quot;&gt;Envoy&lt;&#x2F;a&gt;, Linkerd uses its own Rust-based proxy
(&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;linkerd&#x2F;linkerd2-proxy&quot;&gt;&lt;code&gt;linkerd2-proxy&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;). That choice drives the differences in overhead, extensibility, and egress
control.&lt;&#x2F;p&gt;
&lt;p&gt;This post compares them on the dimensions that matter for a production deployment. For the
broader question of Istio vs. Envoy Gateway (ingress-only), ambient mode, and managed cloud
specifics (AKS, GKE, OVH MKS), see the companion post
&lt;a href=&quot;&#x2F;blog&#x2F;2026&#x2F;2026-04-30-istio-vs-envoy-gateway&#x2F;&quot;&gt;Istio vs. Envoy Gateway: Gateway API on Kubernetes&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>Istio vs. Envoy Gateway: Gateway API on Kubernetes</title>
        <published>2026-04-30T00:00:00+00:00</published>
        <updated>2026-06-25T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-04-30-istio-vs-envoy-gateway/"/>
        <id>https://blog.none.at/blog/2026/2026-04-30-istio-vs-envoy-gateway/</id>
        
        <summary type="html">&lt;p&gt;Both &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;istio.io&quot;&gt;Istio&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gateway.envoyproxy.io&quot;&gt;Envoy Gateway&lt;&#x2F;a&gt; implement the
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gateway-api.sigs.k8s.io&quot;&gt;Kubernetes Gateway API&lt;&#x2F;a&gt; and use Envoy as their data plane.
That is roughly where the similarity ends. Istio is a full service mesh that happens to
implement Gateway API; Envoy Gateway is a dedicated Gateway API controller with no mesh
ambitions. Choosing between them is mostly a question of scope.&lt;&#x2F;p&gt;
&lt;p&gt;This post starts with that comparison — architecture, mTLS, egress control, and resource
overhead — then broadens to cover &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;cilium.io&quot;&gt;Cilium&lt;&#x2F;a&gt; as a lighter alternative for
East-West security, how the choice plays out on managed Kubernetes offerings (AKS, GKE, and
OVH MKS including their cloud-native ingress and egress options), and finally how to get
the real client IP through a cloud load balancer to your application.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>haproxy-spoe-rs: A Rust SPOA Agent Library for HAProxy</title>
        <published>2026-04-12T00:00:00+00:00</published>
        <updated>2026-04-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-04-12-haproxy-spoa-rs/"/>
        <id>https://blog.none.at/blog/2026/2026-04-12-haproxy-spoa-rs/</id>
        
        <summary type="html">&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;git001&#x2F;haproxy-spoe-rs&quot;&gt;haproxy-spoe-rs&lt;&#x2F;a&gt; is a Rust library for writing
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;haproxy&#x2F;haproxy&#x2F;blob&#x2F;master&#x2F;doc&#x2F;SPOE.txt&quot;&gt;HAProxy SPOE&lt;&#x2F;a&gt; agents. This post
covers what SPOE is, the design decisions behind the library, and how its throughput compares
to the Go reference implementation.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>Running pdns_recursor as a root-independent validating resolver</title>
        <published>2026-04-06T00:00:00+00:00</published>
        <updated>2026-04-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-04-05-pdns-recursor-root-resolver/"/>
        <id>https://blog.none.at/blog/2026/2026-04-05-pdns-recursor-root-resolver/</id>
        
        <summary type="html">&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.powerdns.com&#x2F;recursor&#x2F;&quot;&gt;PowerDNS Recursor&lt;&#x2F;a&gt; is a mature, production-grade recursive DNS resolver. This post documents how to configure it to bootstrap directly from a local &lt;code&gt;root.zone&lt;&#x2F;code&gt; file — so it never needs to reach the root name servers at runtime — with full DNSSEC validation producing the &lt;code&gt;ad&lt;&#x2F;code&gt; flag in responses.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>Running a validating DNS recursor from the root zone with Hickory DNS</title>
        <published>2026-04-04T00:00:00+00:00</published>
        <updated>2026-04-05T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2026/2026-04-04-hickory-dns-root-resolver/"/>
        <id>https://blog.none.at/blog/2026/2026-04-04-hickory-dns-root-resolver/</id>
        
        <summary type="html">&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hickory-dns&#x2F;hickory-dns&quot;&gt;Hickory DNS&lt;&#x2F;a&gt; is a Rust-based DNS implementation that covers the full stack: resolver, recursor, authoritative server, and DNSSEC. This post documents how to run it as a &lt;strong&gt;full recursive resolver&lt;&#x2F;strong&gt; — starting directly from the root zone, with DNSSEC validation and encrypted upstream transport — based on the changes developed in the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;git001&#x2F;hickory-dns&#x2F;tree&#x2F;recurser-from-root-zone&quot;&gt;&lt;code&gt;recurser-from-root-zone&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; branch.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>tls-proxy-tunnel: Transparent TLS Tunnelling Through Corporate HTTP Proxies</title>
        <published>2024-07-02T00:00:00+00:00</published>
        <updated>2026-01-22T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2024/2024-07-02-tls-proxy-tunnel/"/>
        <id>https://blog.none.at/blog/2024/2024-07-02-tls-proxy-tunnel/</id>
        
        <summary type="html">&lt;p&gt;Many enterprise networks sit behind a corporate HTTP CONNECT proxy. Applications
that speak TLS natively — think &lt;code&gt;git&lt;&#x2F;code&gt;, &lt;code&gt;curl&lt;&#x2F;code&gt;, SSH-over-HTTPS, or any custom
binary — often have no built-in proxy support. Configuring every single tool is
tedious, fragile, and sometimes impossible when you don’t control the binary.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;tls-proxy-tunnel&lt;&#x2F;code&gt; (&lt;code&gt;tpt&lt;&#x2F;code&gt;) solves this at layer 4: it sits between your
application and the outside world, intercepts the TLS connection, extracts the
Server Name Indication (SNI) from the ClientHello, and tunnels the raw bytes
through your corporate HTTP CONNECT proxy — without ever terminating TLS.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>curl:&#x2F;&#x2F; for Network Debugging — curlup 2017</title>
        <published>2017-03-18T00:00:00+00:00</published>
        <updated>2017-03-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              aleks
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.none.at/blog/2017/2017-03-18-curl-meetup/"/>
        <id>https://blog.none.at/blog/2017/2017-03-18-curl-meetup/</id>
        
        <summary type="html">&lt;p&gt;Talk I gave at &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;curl.se&#x2F;docs&#x2F;videos&#x2F;&quot;&gt;curlup 2017&lt;&#x2F;a&gt; in Nürnberg. The slides cover three practical curl techniques that are useful for everyday network debugging.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a href=&quot;&#x2F;pdf&#x2F;2017&#x2F;Curl-meetup-2017.pdf&quot;&gt;slides are available as PDF&lt;&#x2F;a&gt; and the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;curl.se&#x2F;video&#x2F;curlup-2017&#x2F;2017-03-18_02_Aleksandar_Lazic_curl_for_network_debugging.mp4&quot;&gt;video recording (MP4)&lt;&#x2F;a&gt; is hosted on curl.se.&lt;&#x2F;p&gt;</summary>
        
    </entry>
</feed>
