<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Cleura on Backend Engineering Strategy Tools</title><link>https://backend-engineering-strategy-tools.github.io/site/tags/cleura/</link><description>Recent content in Cleura 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/cleura/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><item><title>Gardener on Cleura</title><link>https://backend-engineering-strategy-tools.github.io/site/public-notes/kubernetes/gardener/</link><pubDate>Tue, 16 Jun 2026 00:00:00 +0000</pubDate><guid>https://backend-engineering-strategy-tools.github.io/site/public-notes/kubernetes/gardener/</guid><description>&lt;p&gt;&lt;a class="link" href="https://gardener.cloud/" target="_blank" rel="noopener"
 &gt;Gardener&lt;/a&gt; is a Kubernetes-as-a-Service framework that runs on Kubernetes and manages the lifecycle of other clusters declaratively. Rather than managing control planes by hand, Gardener treats clusters as a resource — defined, created, upgraded, and deleted via the Gardener API.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="concepts"&gt;Concepts
&lt;/h2&gt;&lt;p&gt;Gardener uses three layers:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Layer&lt;/th&gt;
 &lt;th&gt;What it is&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Garden cluster&lt;/td&gt;
 &lt;td&gt;Runs Gardener itself — the management control plane&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Seed cluster&lt;/td&gt;
 &lt;td&gt;Hosts the control planes of shoot clusters (as pods)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Shoot cluster&lt;/td&gt;
 &lt;td&gt;The cluster you actually use — nodes run on the target cloud&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The shoot cluster&amp;rsquo;s API server does not run on the shoot nodes. It runs as a pod inside the seed cluster. From the outside it behaves like any other Kubernetes cluster; internally the control plane is isolated from the data plane.&lt;/p&gt;
&lt;p&gt;Shoot clusters are defined as &lt;code&gt;Shoot&lt;/code&gt; resources applied to the garden cluster:&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-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;core.gardener.cloud/v1beta1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Shoot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;my-cluster&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;namespace&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;garden-my-project&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;cloudProfileName&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;openstack&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;region&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;sto2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;provider&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;type&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;openstack&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;workers&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;worker-pool&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;machine&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;type&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;l2.c2r4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;minimum&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;maximum&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;kubernetes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;version&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;1.30&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;networking&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;type&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;calico&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;pods&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;100.128.0.0&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;/11&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;nodes&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;10.250.0.0&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;/16&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;services&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;100.112.0.0&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;/13&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="shoot-cluster-on-cleura"&gt;Shoot cluster on Cleura
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://cleura.com/" target="_blank" rel="noopener"
 &gt;Cleura&lt;/a&gt; is a European OpenStack provider. Gardener provisions shoot nodes as OpenStack VMs via the OpenStack machine controller.&lt;/p&gt;
&lt;p&gt;Key integrations:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Component&lt;/th&gt;
 &lt;th&gt;Implementation&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Node provisioning&lt;/td&gt;
 &lt;td&gt;OpenStack VMs via Gardener machine controller&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Load balancers&lt;/td&gt;
 &lt;td&gt;Octavia via cloud-controller-manager&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Block storage&lt;/td&gt;
 &lt;td&gt;Cinder via CSI driver&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;DNS&lt;/td&gt;
 &lt;td&gt;Manual or external-dns&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;CNI&lt;/td&gt;
 &lt;td&gt;Calico (default) or configurable&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Gardener on Cleura does not provide an ingress controller or API gateway — these are brought in separately.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="networking"&gt;Networking
&lt;/h2&gt;&lt;p&gt;Gardener manages the cluster network configuration as part of the shoot spec. Pod, node, and service CIDRs are defined at cluster creation and must not overlap with the OpenStack network.&lt;/p&gt;
&lt;p&gt;On Cleura, nodes get OpenStack floating IPs for egress. Pod-to-pod traffic stays within the cluster overlay network (Calico by default). Traffic entering from outside the cluster goes through a &lt;code&gt;LoadBalancer&lt;/code&gt; service — either directly for raw TCP, or via a gateway controller for HTTP.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="ingress--classic-vs-gateway-api"&gt;Ingress — classic vs Gateway API
&lt;/h2&gt;&lt;p&gt;The classic Kubernetes &lt;code&gt;Ingress&lt;/code&gt; resource is HTTP-only, has no TCP support, and its feature set varies across implementations via non-standard annotations. The NGINX Ingress Controller — the most widely used implementation — is deprecated; NGINX now focuses on their &lt;a class="link" href="https://github.com/nginxinc/nginx-gateway-fabric" target="_blank" rel="noopener"
 &gt;Gateway API implementation&lt;/a&gt; instead.&lt;/p&gt;
&lt;p&gt;The &lt;a class="link" href="https://gateway-api.sigs.k8s.io/" target="_blank" rel="noopener"
 &gt;Kubernetes Gateway API&lt;/a&gt; is the forward path — a set of CRDs (&lt;code&gt;Gateway&lt;/code&gt;, &lt;code&gt;HTTPRoute&lt;/code&gt;, &lt;code&gt;TCPRoute&lt;/code&gt;, &lt;code&gt;TLSRoute&lt;/code&gt;) with a standardized spec and first-class support for both HTTP and TCP.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Resource&lt;/th&gt;
 &lt;th&gt;Protocol&lt;/th&gt;
 &lt;th&gt;API&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;&lt;code&gt;Ingress&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;HTTP only&lt;/td&gt;
 &lt;td&gt;Kubernetes&lt;/td&gt;
 &lt;td&gt;Stable, legacy&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;HTTPRoute&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;HTTP/HTTPS&lt;/td&gt;
 &lt;td&gt;Gateway API&lt;/td&gt;
 &lt;td&gt;Stable&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;TCPRoute&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Raw TCP&lt;/td&gt;
 &lt;td&gt;Gateway API&lt;/td&gt;
 &lt;td&gt;Experimental&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;TLSRoute&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;TLS passthrough&lt;/td&gt;
 &lt;td&gt;Gateway API&lt;/td&gt;
 &lt;td&gt;Experimental&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="envoy-gateway"&gt;Envoy Gateway
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://gateway.envoyproxy.io/" target="_blank" rel="noopener"
 &gt;Envoy Gateway&lt;/a&gt; is the CNCF implementation of the Kubernetes Gateway API using &lt;a class="link" href="https://www.envoyproxy.io/" target="_blank" rel="noopener"
 &gt;Envoy&lt;/a&gt; as the data plane. It supports &lt;code&gt;HTTPRoute&lt;/code&gt;, &lt;code&gt;TCPRoute&lt;/code&gt;, and &lt;code&gt;TLSRoute&lt;/code&gt; through a single &lt;code&gt;Gateway&lt;/code&gt; resource — one entry point, both protocols.&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;Octavia LB ← one LoadBalancer service per Gateway listener
&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 pod
&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 → ClusterIP pods TCPRoute → ClusterIP pods
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Envoy Gateway is deployed into the shoot cluster and exposes a &lt;code&gt;LoadBalancer&lt;/code&gt; service via Octavia, the same as any other service. The Gateway API resources then declare what routes through it.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="tcproute--declaring-tcp-services"&gt;TCPRoute — declaring TCP services
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;TCPRoute&lt;/code&gt; attaches to a &lt;code&gt;Gateway&lt;/code&gt; listener and routes raw TCP traffic to a backend service. This is how a non-HTTP workload (e.g. a game server, a database proxy, a custom protocol service) gets exposed through the Gateway API rather than a standalone &lt;code&gt;LoadBalancer&lt;/code&gt; service.&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-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;gateway.networking.k8s.io/v1alpha2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;TCPRoute&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;my-tcp-service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;namespace&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;my-app&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;parentRefs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;my-gateway&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;sectionName&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;tcp-listener&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;rules&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;backendRefs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;my-service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;port&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1234&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The corresponding &lt;code&gt;Gateway&lt;/code&gt; listener:&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-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;gateway.networking.k8s.io/v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Gateway&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;my-gateway&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;namespace&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;my-app&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;gatewayClassName&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;envoy-gateway&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;listeners&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;tcp-listener&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;protocol&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;TCP&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;port&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1234&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;http-listener&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;protocol&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;HTTP&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;port&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;80&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;One Gateway, both protocols declared explicitly. The &lt;code&gt;TCPRoute&lt;/code&gt; API is in the experimental channel and requires opting in when installing Envoy Gateway.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="httproute--http-services"&gt;HTTPRoute — HTTP services
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;HTTPRoute&lt;/code&gt; handles HTTP and HTTPS traffic with routing by hostname, path, header, or method — without annotations.&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-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;gateway.networking.k8s.io/v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;HTTPRoute&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;my-http-service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;namespace&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;my-app&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;parentRefs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;my-gateway&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;sectionName&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;http-listener&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;hostnames&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;my-app.example.com&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;rules&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;matches&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;path&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;type&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;PathPrefix&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;value&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;backendRefs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;my-service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;port&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="loadbalancer--direct-tcp-via-octavia"&gt;LoadBalancer — direct TCP via Octavia
&lt;/h2&gt;&lt;p&gt;For cases where a &lt;code&gt;TCPRoute&lt;/code&gt; is not appropriate (or the Gateway API experimental channel is not enabled), a &lt;code&gt;LoadBalancer&lt;/code&gt; service provisions an Octavia LB directly:&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-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;Service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;my-tcp-service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;namespace&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;my-app&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;type&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;LoadBalancer&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;selector&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;app&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;my-app&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ports&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#f92672"&gt;port&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1234&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;targetPort&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;1234&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;protocol&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;TCP&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Annotations control Octavia behaviour — timeouts, health check parameters, internal vs external. These are provider-specific and not standardised across OpenStack deployments.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="storage"&gt;Storage
&lt;/h2&gt;&lt;p&gt;Cinder block volumes are available via the CSI driver. A &lt;code&gt;PersistentVolumeClaim&lt;/code&gt; provisions a Cinder volume automatically using the cluster&amp;rsquo;s default storage class.&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-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;apiVersion&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;v1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;kind&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;PersistentVolumeClaim&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;metadata&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;my-data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;spec&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;accessModes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;ReadWriteOnce&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;resources&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;requests&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;storage&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;20Gi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Cinder volumes are &lt;code&gt;ReadWriteOnce&lt;/code&gt; — they attach to a single node. For stateful workloads, use &lt;code&gt;StatefulSet&lt;/code&gt; rather than &lt;code&gt;Deployment&lt;/code&gt; to get stable volume binding across pod restarts.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="provisioning-a-shoot-cluster-on-cleura"&gt;Provisioning a shoot cluster on Cleura
&lt;/h2&gt;&lt;p&gt;Cleura wraps Gardener behind their own REST API at &lt;code&gt;rest.cleura.cloud&lt;/code&gt;. The garden cluster kubeconfig is not exposed — &lt;code&gt;gardenctl&lt;/code&gt; does not work directly. Cluster lifecycle is managed through HTTP calls.&lt;/p&gt;
&lt;h3 id="authentication"&gt;Authentication
&lt;/h3&gt;&lt;p&gt;Every call requires a token obtained once per session:&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;curl -s -X POST https://rest.cleura.cloud/auth/v1/tokens &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -H &lt;span style="color:#e6db74"&gt;&amp;#34;Content-Type: application/json&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -d &lt;span style="color:#e6db74"&gt;&amp;#39;{&amp;#34;auth&amp;#34;: {&amp;#34;login&amp;#34;: &amp;#34;you@example.com&amp;#34;, &amp;#34;password&amp;#34;: &amp;#34;yourpass&amp;#34;}}&amp;#39;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; | jq &lt;span style="color:#e6db74"&gt;&amp;#39;{token: .token}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Pass &lt;code&gt;X-AUTH-LOGIN&lt;/code&gt; and &lt;code&gt;X-AUTH-TOKEN&lt;/code&gt; headers on all subsequent calls.&lt;/p&gt;
&lt;h3 id="bootstrap-once-per-projectregion"&gt;Bootstrap (once per project/region)
&lt;/h3&gt;&lt;p&gt;Before creating any clusters, the project must be bootstrapped — this wires up the OpenStack credentials that Gardener uses to provision nodes:&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;curl -X POST &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; https://rest.cleura.cloud/gardener/v1/public/secret/kna1/&lt;span style="color:#f92672"&gt;{&lt;/span&gt;projectId&lt;span style="color:#f92672"&gt;}&lt;/span&gt;/bootstrap &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -H &lt;span style="color:#e6db74"&gt;&amp;#34;X-AUTH-LOGIN: ...&amp;#34;&lt;/span&gt; -H &lt;span style="color:#e6db74"&gt;&amp;#34;X-AUTH-TOKEN: ...&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Safe to call repeatedly; idempotent.&lt;/p&gt;
&lt;h3 id="create-a-shoot-cluster"&gt;Create a shoot cluster
&lt;/h3&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;curl -X POST &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; https://rest.cleura.cloud/gardener/v1/public/shoot/kna1/&lt;span style="color:#f92672"&gt;{&lt;/span&gt;projectId&lt;span style="color:#f92672"&gt;}&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -H &lt;span style="color:#e6db74"&gt;&amp;#34;X-AUTH-LOGIN: ...&amp;#34;&lt;/span&gt; -H &lt;span style="color:#e6db74"&gt;&amp;#34;X-AUTH-TOKEN: ...&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -H &lt;span style="color:#e6db74"&gt;&amp;#34;Content-Type: application/json&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -d &lt;span style="color:#e6db74"&gt;&amp;#39;{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;shoot&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;name&amp;#34;: &amp;#34;my-cluster&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;kubernetes&amp;#34;: {&amp;#34;version&amp;#34;: &amp;#34;1.31.0&amp;#34;},
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;provider&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;infrastructureConfig&amp;#34;: {&amp;#34;floatingPoolName&amp;#34;: &amp;#34;ext-net&amp;#34;},
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;workers&amp;#34;: [{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;name&amp;#34;: &amp;#34;default&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;machine&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;type&amp;#34;: &amp;#34;4C-8GB-50GB&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;image&amp;#34;: {&amp;#34;name&amp;#34;: &amp;#34;ubuntu&amp;#34;, &amp;#34;version&amp;#34;: &amp;#34;22.4.20230301&amp;#34;}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;minimum&amp;#34;: 1,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;maximum&amp;#34;: 3,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; &amp;#34;volume&amp;#34;: {&amp;#34;size&amp;#34;: &amp;#34;50Gi&amp;#34;}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; }]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt; }&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="poll-until-ready"&gt;Poll until ready
&lt;/h3&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;curl https://rest.cleura.cloud/gardener/v1/public/shoot/kna1/&lt;span style="color:#f92672"&gt;{&lt;/span&gt;projectId&lt;span style="color:#f92672"&gt;}&lt;/span&gt;/my-cluster &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -H &lt;span style="color:#e6db74"&gt;&amp;#34;X-AUTH-LOGIN: ...&amp;#34;&lt;/span&gt; -H &lt;span style="color:#e6db74"&gt;&amp;#34;X-AUTH-TOKEN: ...&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; | jq &lt;span style="color:#e6db74"&gt;&amp;#39;.lastOperation | {state, description, progress}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Poll until &lt;code&gt;lastOperation.state == &amp;quot;Succeeded&amp;quot;&lt;/code&gt;. Takes roughly 10–15 minutes on first provision.&lt;/p&gt;
&lt;h3 id="fetch-kubeconfig"&gt;Fetch kubeconfig
&lt;/h3&gt;&lt;p&gt;The Cleura docs reference two kubeconfig paths — &lt;code&gt;GET /kubeconfig&lt;/code&gt; (lowercase) and &lt;code&gt;POST /Kubeconfig&lt;/code&gt; (uppercase, different casing). Neither worked reliably in practice. The endpoint that actually returns a kubeconfig is:&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;curl -s -X POST &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; https://rest.cleura.cloud/gardener/v1/public/shoot/kna1/&lt;span style="color:#f92672"&gt;{&lt;/span&gt;projectId&lt;span style="color:#f92672"&gt;}&lt;/span&gt;/my-cluster/adminkubeconfig &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -H &lt;span style="color:#e6db74"&gt;&amp;#34;X-AUTH-LOGIN: ...&amp;#34;&lt;/span&gt; -H &lt;span style="color:#e6db74"&gt;&amp;#34;X-AUTH-TOKEN: ...&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -H &lt;span style="color:#e6db74"&gt;&amp;#34;Content-Type: application/json&amp;#34;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; -d &lt;span style="color:#e6db74"&gt;&amp;#39;{&amp;#34;config&amp;#34;: {&amp;#34;expirationSeconds&amp;#34;: 3600}}&amp;#39;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; | jq -r &amp;gt; my-cluster-kubeconfig.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;expirationSeconds&lt;/code&gt; field controls credential lifetime. A bug report has been filed with Cleura about the endpoint inconsistency — the &lt;code&gt;adminkubeconfig&lt;/code&gt; path is not documented.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Path&lt;/th&gt;
 &lt;th&gt;Method&lt;/th&gt;
 &lt;th&gt;Documented&lt;/th&gt;
 &lt;th&gt;Works&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;/kubeconfig&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;GET&lt;/td&gt;
 &lt;td&gt;yes&lt;/td&gt;
 &lt;td&gt;unclear&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;/Kubeconfig&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;POST&lt;/td&gt;
 &lt;td&gt;yes&lt;/td&gt;
 &lt;td&gt;unclear&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;/adminkubeconfig&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;POST&lt;/td&gt;
 &lt;td&gt;no&lt;/td&gt;
 &lt;td&gt;yes&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;→ &lt;a class="link" href="https://github.com/cleura/docs/issues/534" target="_blank" rel="noopener"
 &gt;Cleura docs issue #534 — kubeconfig endpoint inconsistencies in Gardener REST API&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="script"&gt;Script
&lt;/h3&gt;&lt;p&gt;A bash script wrapping the full workflow (list, create, wait, kubeconfig, delete) is available: &lt;a class="link" href="https://backend-engineering-strategy-tools.github.io/site/scripts/cleura-shoot.sh" &gt;cleura-shoot.sh&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;export CLEURA_LOGIN&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;you@example.com&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;export CLEURA_PASSWORD&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;yourpass&amp;#34;&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;./cleura-shoot.sh list
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./cleura-shoot.sh create my-cluster
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./cleura-shoot.sh wait my-cluster
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./cleura-shoot.sh kubeconfig my-cluster
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;./cleura-shoot.sh delete my-cluster
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="iac-options"&gt;IaC options
&lt;/h3&gt;&lt;p&gt;No native Terraform provider exists for Cleura&amp;rsquo;s Gardener REST API. The Gardener Terraform provider (&lt;code&gt;registry.terraform.io/providers/gardener/gardener&lt;/code&gt;) requires the garden cluster kubeconfig, which Cleura does not expose. Options:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Approach&lt;/th&gt;
 &lt;th&gt;Notes&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Bash + curl&lt;/td&gt;
 &lt;td&gt;Minimal deps — just &lt;code&gt;curl&lt;/code&gt; and &lt;code&gt;jq&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Crossplane &lt;code&gt;provider-http&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;Declarative, Kubernetes-native, reconciliation loop&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Custom Terraform provider&lt;/td&gt;
 &lt;td&gt;Full &lt;code&gt;plan&lt;/code&gt;/&lt;code&gt;apply&lt;/code&gt; semantics — requires Go provider development&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Pulumi custom dynamic provider&lt;/td&gt;
 &lt;td&gt;Python/TypeScript, similar effort to custom Terraform provider&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;</description></item></channel></rss>