<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Ingress on Backend Engineering Strategy Tools</title><link>https://backend-engineering-strategy-tools.github.io/site/tags/ingress/</link><description>Recent content in Ingress on Backend Engineering Strategy Tools</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Tue, 16 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://backend-engineering-strategy-tools.github.io/site/tags/ingress/index.xml" rel="self" type="application/rss+xml"/><item><title>Gardener on Cleura</title><link>https://backend-engineering-strategy-tools.github.io/site/projects/gardener/</link><pubDate>Tue, 16 Jun 2026 00:00:00 +0000</pubDate><guid>https://backend-engineering-strategy-tools.github.io/site/projects/gardener/</guid><description>&lt;p&gt;Getting hands-on with &lt;a class="link" href="https://gardener.cloud/" target="_blank" rel="noopener"
 &gt;Gardener&lt;/a&gt; on &lt;a class="link" href="https://cleura.com/" target="_blank" rel="noopener"
 &gt;Cleura&lt;/a&gt; — a European OpenStack cloud — ahead of using it professionally. The focus is on the networking and traffic ingress side: how does a Gardener shoot cluster on OpenStack expose services, what does the LoadBalancer path actually look like, and when does ingress apply versus when it does not.&lt;/p&gt;
&lt;p&gt;The test application is a &lt;a class="link" href="https://backend-engineering-strategy-tools.github.io/site/projects/minecraft/" &gt;Minecraft server with Velocity proxy&lt;/a&gt; — useful precisely because it is raw TCP rather than HTTP, which forces the full LoadBalancer path rather than an ingress shortcut.&lt;/p&gt;
&lt;p&gt;→ &lt;a class="link" href="https://backend-engineering-strategy-tools.github.io/site/public-notes/kubernetes/gardener/" &gt;Gardener on Cleura — technical notes&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="steps"&gt;Steps
&lt;/h2&gt;&lt;h3 id="1--shoot-cluster"&gt;1 — Shoot cluster
&lt;/h3&gt;&lt;p&gt;Provision a Gardener shoot cluster on Cleura. Cleura wraps Gardener behind their own REST API — &lt;code&gt;gardenctl&lt;/code&gt; and the Gardener Terraform provider require the garden cluster kubeconfig, which Cleura does not expose. Cluster lifecycle goes through their REST API instead.&lt;/p&gt;
&lt;p&gt;→ &lt;a class="link" href="https://backend-engineering-strategy-tools.github.io/site/public-notes/kubernetes/gardener/#provisioning-a-shoot-cluster-on-cleura" &gt;Provisioning via Cleura REST API&lt;/a&gt;&lt;br&gt;
→ &lt;a class="link" href="https://github.com/cleura/docs/issues/533" target="_blank" rel="noopener"
 &gt;Cleura docs issue #533 — IaC and gardenctl access&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="2--minecraft-via-standard-loadbalancer"&gt;2 — Minecraft via standard LoadBalancer
&lt;/h3&gt;&lt;p&gt;Deploy &lt;a class="link" href="https://github.com/itzg/docker-minecraft-server" target="_blank" rel="noopener"
 &gt;&lt;code&gt;itzg/minecraft-server&lt;/code&gt;&lt;/a&gt; as a StatefulSet with a plain &lt;code&gt;LoadBalancer&lt;/code&gt; service for TCP 25565 — the direct Octavia path, no Gateway involved. Gets the server running quickly and confirms TCP exposure works on Cleura independently.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Internet
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;TCP 25565
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Octavia LB (direct LoadBalancer service)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Minecraft Pod (itzg/minecraft-server)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PVC (Cinder)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Manifests: &lt;a class="link" href="https://backend-engineering-strategy-tools.github.io/site/scripts/mc/stateful_set.yaml" &gt;stateful_set.yaml&lt;/a&gt; · &lt;a class="link" href="https://backend-engineering-strategy-tools.github.io/site/scripts/mc/service.yaml" &gt;service.yaml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Apply directly from this repo:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl apply -k &lt;span style="color:#e6db74"&gt;&amp;#34;https://github.com/Backend-Engineering-Strategy-Tools/site//static/scripts/mc?ref=main&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Check the rollout and grab the external IP:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl get all -l app&lt;span style="color:#f92672"&gt;=&lt;/span&gt;mc-example
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl get svc mc-example &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -o jsonpath&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;{.status.loadBalancer.ingress[0].ip}:{.spec.ports[0].port}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="25--migrate-to-helm-chart"&gt;2.5 — Migrate to Helm chart
&lt;/h3&gt;&lt;p&gt;Swap the raw manifests for the &lt;a class="link" href="https://github.com/itzg/minecraft-server-charts" target="_blank" rel="noopener"
 &gt;&lt;code&gt;itzg/minecraft-server-charts&lt;/code&gt;&lt;/a&gt; Helm chart — actively maintained, covers server type, persistence, RCON, backups, and extra ports (BlueMap, Dynmap). The raw YAML stays useful as a reference for the underlying shape.&lt;/p&gt;
&lt;p&gt;Manifests: &lt;a class="link" href="https://backend-engineering-strategy-tools.github.io/site/scripts/mc-helm/values.yaml" &gt;values.yaml&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm repo add minecraft-server-charts https://itzg.github.io/minecraft-server-charts/
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;helm upgrade --install mc minecraft-server-charts/minecraft &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -f https://backend-engineering-strategy-tools.github.io/site/scripts/mc-helm/values.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Check the rollout and grab the external IP:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl get all -l app.kubernetes.io/instance&lt;span style="color:#f92672"&gt;=&lt;/span&gt;mc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;kubectl get svc mc-example -o jsonpath&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;{.status.loadBalancer.ingress[0].ip}:{.spec.ports[0].port}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="3--envoy-gateway"&gt;3 — Envoy Gateway
&lt;/h3&gt;&lt;p&gt;Deploy &lt;a class="link" href="https://gateway.envoyproxy.io/" target="_blank" rel="noopener"
 &gt;Envoy Gateway&lt;/a&gt; into the shoot cluster — the CNCF implementation of the &lt;a class="link" href="https://gateway-api.sigs.k8s.io/" target="_blank" rel="noopener"
 &gt;Kubernetes Gateway API&lt;/a&gt;. The NGINX Ingress Controller is deprecated; Gateway API is the forward path with a standardised spec for both HTTP and TCP.&lt;/p&gt;
&lt;p&gt;Envoy Gateway exposes a single &lt;code&gt;LoadBalancer&lt;/code&gt; service via Octavia. Everything routes through it.&lt;/p&gt;
&lt;h3 id="4--httproute-certificates-and-bluemap"&gt;4 — HTTPRoute, certificates, and BlueMap
&lt;/h3&gt;&lt;p&gt;Deploy &lt;a class="link" href="https://bluemap.bluecolored.de/" target="_blank" rel="noopener"
 &gt;BlueMap&lt;/a&gt; — a Minecraft mod that renders the world as a live 3D web map served over HTTP. Route it through the Gateway with a &lt;code&gt;HTTPRoute&lt;/code&gt; and wire &lt;a class="link" href="https://cert-manager.io/" target="_blank" rel="noopener"
 &gt;cert-manager&lt;/a&gt; to provision a Let&amp;rsquo;s Encrypt certificate.&lt;/p&gt;
&lt;p&gt;A real HTTP service with a real use, not a throwaway test page. Validates the full HTTP + TLS path before touching the game server.&lt;/p&gt;
&lt;h3 id="5--migrate-to-tcproute"&gt;5 — Migrate to TCPRoute
&lt;/h3&gt;&lt;p&gt;Migrate the TCP service to a &lt;code&gt;TCPRoute&lt;/code&gt; through Envoy Gateway. &lt;code&gt;TCPRoute&lt;/code&gt; is in the Gateway API experimental channel — this step validates that a single Gateway handles both HTTP and raw TCP.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Internet
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Octavia LB (one Gateway LoadBalancer)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Envoy Gateway
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;+------------------------------+------------------------------+
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;| |
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;HTTPRoute → BlueMap TCPRoute → Minecraft
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="6--velocity-if-needed"&gt;6 — Velocity (if needed)
&lt;/h3&gt;&lt;p&gt;Add &lt;a class="link" href="https://papermc.io/software/velocity" target="_blank" rel="noopener"
 &gt;Velocity&lt;/a&gt; as a TCP proxy in front of the Minecraft server if multi-server routing becomes relevant — lobby, modded, survival as separate backends. Skip if a single server is enough.&lt;/p&gt;
&lt;p&gt;→ &lt;a class="link" href="https://backend-engineering-strategy-tools.github.io/site/projects/minecraft/" &gt;Minecraft project&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="7--plugin-pipeline"&gt;7 — Plugin pipeline
&lt;/h3&gt;&lt;p&gt;A colleague is building a Minecraft plugin. The goal is a &lt;a class="link" href="https://dagger.io/" target="_blank" rel="noopener"
 &gt;Dagger&lt;/a&gt; pipeline with GitHub Actions — the same build running locally and in CI, covering the JVM toolchain and packaging steps.&lt;/p&gt;
&lt;h3 id="8--ai"&gt;8 — AI
&lt;/h3&gt;&lt;p&gt;Something with NPC behaviour, a bot, or plugin-side automation. Low priority, high fun.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="iac-gap"&gt;IaC gap
&lt;/h2&gt;&lt;p&gt;Cleura does not expose the garden cluster kubeconfig. That one limitation closes off the entire Gardener tooling ecosystem: &lt;code&gt;gardenctl&lt;/code&gt; requires it, the &lt;a class="link" href="https://registry.terraform.io/providers/gardener/gardener" target="_blank" rel="noopener"
 &gt;Gardener Terraform provider&lt;/a&gt; requires it, and any Crossplane provider built on the Gardener API would require it too. There is no HCL path here.&lt;/p&gt;
&lt;p&gt;What remains is Cleura&amp;rsquo;s own REST API — which is fine for interactive use but falls short the moment you want to drive cluster lifecycle from a pipeline. A bash script wrapping &lt;code&gt;curl&lt;/code&gt; and &lt;code&gt;jq&lt;/code&gt; works, and that is what &lt;a class="link" href="https://backend-engineering-strategy-tools.github.io/site/scripts/cleura-shoot.sh" &gt;cleura-shoot.sh&lt;/a&gt; does, but it is a workaround rather than a solution. No state, no plan, no diff — just imperative API calls.&lt;/p&gt;
&lt;p&gt;Options if this needs to graduate beyond a script:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Crossplane &lt;code&gt;provider-http&lt;/code&gt;&lt;/strong&gt; — can wrap the REST API declaratively, but has no native polling or deletion hooks, so the reconciliation story is awkward&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Custom Terraform provider&lt;/strong&gt; — full &lt;code&gt;plan&lt;/code&gt;/&lt;code&gt;apply&lt;/code&gt; semantics, but requires writing a Go provider from scratch&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pulumi dynamic provider&lt;/strong&gt; — similar effort, Python or TypeScript&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A feature request for gardenctl access or a native IaC provider has been filed with Cleura (→ &lt;a class="link" href="https://github.com/cleura/docs/issues/533" target="_blank" rel="noopener"
 &gt;cleura/docs#533&lt;/a&gt;). Until something changes there, the bash script is as good as it gets.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="status"&gt;Status
&lt;/h2&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Step&lt;/th&gt;
 &lt;th&gt;Status&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;1 — Shoot cluster on Cleura&lt;/td&gt;
 &lt;td&gt;done&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;2 — Minecraft via LoadBalancer (itzg)&lt;/td&gt;
 &lt;td&gt;planned&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;2.5 — Migrate to Helm chart&lt;/td&gt;
 &lt;td&gt;planned&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;3 — Envoy Gateway&lt;/td&gt;
 &lt;td&gt;planned&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;4 — HTTPRoute + cert-manager + BlueMap&lt;/td&gt;
 &lt;td&gt;planned&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;5 — Migrate to TCPRoute&lt;/td&gt;
 &lt;td&gt;planned&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;6 — Velocity&lt;/td&gt;
 &lt;td&gt;planned&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;7 — Plugin pipeline (Dagger)&lt;/td&gt;
 &lt;td&gt;planned&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;8 — AI&lt;/td&gt;
 &lt;td&gt;planned&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Building this out — notes will expand as each step lands.&lt;/em&gt;&lt;/p&gt;</description></item></channel></rss>