<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Autoservicio on lo0 — Tech Blog</title><link>https://blog.lo0.es/en/tags/autoservicio/</link><description>Recent content in Autoservicio on lo0 — Tech Blog</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Mon, 31 Aug 2026 09:45:00 +0200</lastBuildDate><atom:link href="https://blog.lo0.es/en/tags/autoservicio/index.xml" rel="self" type="application/rss+xml"/><item><title>KubeVela and Score: handing over the platform by CLI without teaching the developer Kubernetes</title><link>https://blog.lo0.es/en/posts/kubevela-score-platform-cli-without-teaching-kubernetes/</link><pubDate>Mon, 31 Aug 2026 09:45:00 +0200</pubDate><guid>https://blog.lo0.es/en/posts/kubevela-score-platform-cli-without-teaching-kubernetes/</guid><description>&lt;blockquote>
&lt;p>Third and last article in the batch about rebuilding the cloud on-premise. The &lt;a href="https://blog.lo0.es/en/posts/public-cloud-to-private-what-you-lose-which-projects-fill-gap/">general map&lt;/a> placed the gaps for you and &lt;a href="https://blog.lo0.es/en/posts/crossplane-control-plane-private-cloud-api/">Crossplane&lt;/a> covered the infrastructure control plane. Here comes the layer above, the one your developer touches every day: application-centric self-service by CLI.&lt;/p>
&lt;/blockquote>
&lt;h2 id="tldr">TL;DR&lt;/h2>
&lt;p>Crossplane answers &amp;ldquo;give me a database&amp;rdquo;, from the infrastructure side. KubeVela and Score answer &amp;ldquo;deploy my application&amp;rdquo;, from the workload side, and they do it by CLI, which is precisely the friendly experience Crossplane deliberately does not give you. The two share an article because they cover the same layer from different angles. KubeVela is a complete delivery platform: it uses the OAM model, where your platform team writes some definitions in the CUE language once and the developer deploys their whole application with a fifteen-line file and a CLI (&lt;code>vela up&lt;/code>, &lt;code>vela status&lt;/code>, &lt;code>vela logs&lt;/code>) that feels like Heroku on the outside and is GitOps on the inside. Score is more modest and more portable: a workload specification in a single file that gets translated by CLI into Docker Compose locally and into Kubernetes in production, without running anything in the cluster.&lt;/p>
&lt;p>The honest part up front is the limits. Neither of the two appears in the &amp;ldquo;Adopt&amp;rdquo; section of the CNCF technology radar from early 2026, where Helm, Backstage and Argo CD do: they are niche against the mainstream. KubeVela version 1.11 is still in alpha, so the stable one is 1.10; its community is concentrated, with around 33 people contributing in 2025. Score is young, its Kubernetes implementation has few stars and its sponsor, Humanitec, was acquired by Akamai. And KubeVela&amp;rsquo;s power lives in CUE, an uncommon language that is hard to debug. The abstraction is real, but when it breaks, your developer ends up looking at Kubernetes YAML all the same.&lt;/p>
&lt;h2 id="the-analogy-the-order-form-against-the-shopping-list">The analogy: the order form against the shopping list&lt;/h2>
&lt;p>Deploying on raw Kubernetes is going to the wholesaler with a technical shopping list: you have to know that you want a Deployment, a Service, a HorizontalPodAutoscaler, an Ingress, a ConfigMap and a ResourceQuota, and how each one gets filled in. It works if you know the warehouse. But your data scientist, who just wants to serve their model, should not have to learn the warehouse.&lt;/p>
&lt;p>KubeVela is an order form. Instead of the technical list, you tick &amp;ldquo;I want to serve this application, with these replicas, with this gateway&amp;rdquo;, and behind it somebody who does know the warehouse (your platform team) has defined exactly what gets ordered for that to work. The developer fills in the form; the translation into the technical list was done by somebody else, once, for everyone.&lt;/p>
&lt;p>Score is the same form but designed so that it works for you in two different shops. You describe your order once and the same sheet serves the market next door (Docker Compose, your laptop) and the wholesaler (Kubernetes, production), without rewriting it. Whatever changes between one shop and the other is supplied by whoever translates, not by you. Both analogies point at the same thing: separating what the developer wants from how it materialises, so that they do not have to learn the warehouse.&lt;/p>
&lt;h2 id="kubevela-the-application-as-the-unit">KubeVela: the application as the unit&lt;/h2>
&lt;h3 id="what-it-is-and-what-state-it-reaches-2026-in">What it is and what state it reaches 2026 in&lt;/h3>
&lt;p>KubeVela is a CNCF project at incubation level since February 2023. It was born as an evolution of the OAM runtime on Kubernetes, with initial contributions from Alibaba Cloud, Microsoft and Upbound, and it rests on the Open Application Model, the specification Alibaba and Microsoft co-created to describe applications independently of the infrastructure.&lt;/p>
&lt;p>Here is a realism check on its community size. The official 2025 retrospective declares seven releases in the year, 124 commits and around 33 people contributing, on a little over 7,600 GitHub stars. It is not a project in decline, but it is a concentrated community, with a growth curve that has flattened compared to its early stage under Alibaba. And an important version warning: the stable branch is 1.10, with regular patches through 2026; 1.11 is still in alpha, so do not rely on its features as if they were available.&lt;/p>
&lt;h3 id="the-oam-model-in-five-pieces">The OAM model in five pieces&lt;/h3>
&lt;p>Your whole application is described in a single YAML file of type &lt;code>Application&lt;/code>, with four sections you need to know by name. The &lt;strong>components&lt;/strong> are the artefact you deploy, be it an image, a Helm chart or a service; the &lt;strong>traits&lt;/strong> are operational requirements you hang off each component, such as scaling, the gateway or storage; the &lt;strong>policies&lt;/strong> are global application strategy, such as multi-cluster topology or SLOs; and the &lt;strong>workflow&lt;/strong> is the step-by-step delivery process, which can include a manual approval pause or a notification.&lt;/p>
&lt;p>The key to the model is that component and trait types are not fixed: they are programmable modules maintained by your platform team, expressed as &lt;code>ComponentDefinition&lt;/code> and &lt;code>TraitDefinition&lt;/code>. The developer only consumes a type and its properties; they never see the Kubernetes YAML underneath. That is exactly the &amp;ldquo;do not expose raw Kubernetes&amp;rdquo; this is all about: your platform operator writes the definition once, your data scientist writes fifteen lines of &lt;code>Application&lt;/code>.&lt;/p>
&lt;h3 id="cue-the-power-and-the-toll">CUE, the power and the toll&lt;/h3>
&lt;p>The definitions are written in CUE, and here you have KubeVela&amp;rsquo;s strength and weakness at the same time. CUE lets you parameterise seriously: the definition declares which inputs it exposes to the developer and which Kubernetes resources it renders from them, with access to context variables such as the application name. The real flow starts from an existing YAML, which &lt;code>vela def init&lt;/code> turns into a CUE skeleton; you edit it, validate it with &lt;code>vela def vet&lt;/code> and publish it with &lt;code>vela def apply&lt;/code>, and it becomes available to all your developers.&lt;/p>
&lt;p>The toll is that CUE is an uncommon language, with few experts and hard to debug. The cost falls on your platform team, not on the developer, which is the correct distribution, but it is a real cost you have to sign up for before adopting. Nobody arrives already knowing CUE.&lt;/p>
&lt;h3 id="the-vela-cli-heroku-on-the-outside-gitops-on-the-inside">The vela CLI: Heroku on the outside, GitOps on the inside&lt;/h3>
&lt;p>Here is the answer to the question this blog has been dragging along about CLI provisioning. Day to day with KubeVela looks like Heroku: &lt;code>vela up&lt;/code> deploys the application from local files, &lt;code>vela status&lt;/code> shows you its state, &lt;code>vela ls&lt;/code> lists the applications, &lt;code>vela logs&lt;/code> follows the logs, &lt;code>vela exec&lt;/code> runs a command inside the container without you knowing the pod name, and &lt;code>vela port-forward&lt;/code> opens a tunnel for you. You even have &lt;code>vela dry-run&lt;/code>, which renders the Kubernetes resources without applying them, so you can see what is going to happen.&lt;/p>
&lt;p>The honest qualification is that it is &amp;ldquo;imperative on the surface, declarative underneath&amp;rdquo;. When you run &lt;code>vela up&lt;/code> you are not executing an imperative command like &lt;code>heroku scale&lt;/code>, you are applying a declarative &lt;code>Application&lt;/code> object that a controller reconciles. The CLI imitates Heroku&amp;rsquo;s comfortable flow, but the underlying model is GitOps, which means it fits with &lt;a href="https://blog.lo0.es/en/posts/gitops-inference-stack-flux/">your Flux stack&lt;/a> through the corresponding addon, instead of replacing it.&lt;/p>
&lt;h3 id="multi-cluster-which-is-what-matters-to-you">Multi-cluster, which is what matters to you&lt;/h3>
&lt;p>If you have a platform with several sites (site01 and site02, in my case) the multi-cluster part is the deciding one. KubeVela orchestrates from a central cluster and only the already rendered resources reach the managed clusters, with centralised governance. A &lt;code>topology policy&lt;/code> decides the destination by cluster list or by label selector (by region, for example); an &lt;code>override policy&lt;/code> adjusts images, replicas or traits per cluster without touching the component; and the deployment step in the workflow distributes, with the option of a phased rollout: first to the local cluster, then a manual approval gate, and only then to production. It is the kind of governance you have to build on-premise and that the cloud served you ready-made.&lt;/p>
&lt;h3 id="velaux-the-lightweight-portal-thrown-in">VelaUX, the lightweight portal thrown in&lt;/h3>
&lt;p>KubeVela comes with an optional web console, VelaUX, which you switch on as an addon and which gives you a dashboard, project management, environments and application lifecycle. If you want CLI first it is optional, more useful for giving operators visibility and access control than as the main route. It is a lightweight portal &amp;ldquo;thrown in&amp;rdquo; that does not aim to compete with &lt;a href="https://blog.lo0.es/en/posts/backstage-self-service-portal-llm-platform/">Backstage&lt;/a>, but it can save you from setting one up if your needs are modest.&lt;/p>
&lt;h2 id="score-describe-the-workload-once">Score: describe the workload once&lt;/h2>
&lt;h3 id="what-it-is-and-what-it-solves">What it is and what it solves&lt;/h3>
&lt;p>Score is an open workload specification, agnostic of platform and environment. The idea, in its own formulation, is that you define the workload once and use a Score implementation to translate it to several platforms: Docker Compose, Kubernetes, Fly.io or Cloud Run. The problem it attacks is concrete and familiar: the divergence between what you run on your laptop with Docker Compose and what gets deployed in production with Kubernetes, two descriptions that drift apart and cause you the classic &amp;ldquo;it worked on my machine&amp;rdquo;.&lt;/p>
&lt;p>In a &lt;code>score.yaml&lt;/code> file the developer declares their containers, the service ports and the resources they need as dependencies (a database, a DNS record, a route), and the environment-specific parameters are injected at deploy time. Score entered the CNCF sandbox in July 2024. It was created and donated by Humanitec, a developer platform company, some eighteen months before it joined the foundation.&lt;/p>
&lt;h3 id="the-two-implementations">The two implementations&lt;/h3>
&lt;p>Score does nothing on its own: it is a specification that needs an implementation to translate. You have two official ones. &lt;code>score-compose&lt;/code> generates Docker Compose for local development, with &lt;code>init&lt;/code> and &lt;code>generate&lt;/code> commands, and provisions on the order of fourteen resource types, from Postgres or Redis to S3 storage or queues. &lt;code>score-k8s&lt;/code> generates Kubernetes manifests ready for &lt;code>kubectl apply&lt;/code>, with flags for the image, the namespace and the provisioners. Humanitec&amp;rsquo;s commercial CLI, &lt;code>humctl&lt;/code>, also supports Score natively.&lt;/p>
&lt;p>The most important architectural fact is that &lt;strong>Score runs nothing in the target cluster&lt;/strong>. It is purely CLI translation: it generates manifests for you and steps aside. There is no controller, no CRD, no reconciliation. That is at once its virtue (it is lightweight, portable and without runtime lock-in) and its limit (it neither orchestrates nor deploys, it only translates).&lt;/p>
&lt;h3 id="score-against-kubevela-and-helm">Score against KubeVela and Helm&lt;/h3>
&lt;p>Score&amp;rsquo;s own official positioning clarifies the layers, and I will pin it down for you because they are easy to confuse. Score is the workload specification layer, developer-centric: it describes a workload and its dependencies and gets translated to N platforms by CLI, but it does not orchestrate or deploy. KubeVela is a complete continuous delivery platform, application-centric: it orchestrates multiple components, applies policies and workflows, does multi-cluster, and for that it needs its controller in the cluster; it is, in its own words, far richer in features than Score. Helm is the packaging and rendering of manifests, without the developer-centric abstraction or the portability to Compose.&lt;/p>
&lt;p>The clean synthesis is that they are complementary layers, not substitutes: Score generates, Helm or the manifests package, KubeVela orchestrates and deploys. If they are presented to you as rivals, somebody has confused the layers.&lt;/p>
&lt;h2 id="where-each-one-fits-the-cross-cutting-comparison">Where each one fits: the cross-cutting comparison&lt;/h2>
&lt;p>With Crossplane already in hand from the previous article, the comparison of the three self-service pieces sorts itself by the question each one answers.&lt;/p>
&lt;p>Score and KubeVela answer at the &lt;strong>application&lt;/strong> level: the workload a developer deploys, &amp;ldquo;deploy this app&amp;rdquo;. Crossplane answers at the &lt;strong>infrastructure&lt;/strong> level: the resource a developer asks for, &amp;ldquo;give me a managed Postgres&amp;rdquo;. And Backstage answers at the &lt;strong>portal&lt;/strong> level: the web catalogue and the golden paths, the discovery layer that neither deploys nor provisions by itself, but orchestrates the ones below.&lt;/p>
&lt;p>The interesting part is that they combine. A &lt;code>score.yaml&lt;/code> can declare its resources and delegate the provisioning of those resources to Crossplane through a provisioner, while KubeVela orchestrates the application deployment and Backstage acts as the façade. It is not an either-or; it is a stack where each layer does its job. If your team is small, you pick a single piece and that is that; the complete stack is for mature platforms.&lt;/p>
&lt;h2 id="the-fit-with-inference-a-pattern-not-an-official-recipe">The fit with inference: a pattern, not an official recipe&lt;/h2>
&lt;p>Just as with Crossplane, honesty is called for here: there is no official, maintained KServe definition in KubeVela&amp;rsquo;s default catalogue, nor an inference resource type in Score. What follows is a design pattern with pieces confirmed separately, not a documented recipe.&lt;/p>
&lt;p>The KubeVela pattern would be that your platform operator defines once, in CUE, a &lt;code>ComponentDefinition&lt;/code> called for example &lt;code>inference-service&lt;/code>, which underneath renders a KServe inference service with vLLM runtime, with the GPU limits, the namespace quotas and the autoscaling already wired in. Your data scientist then writes a fifteen-line &lt;code>Application&lt;/code> with the &lt;code>inference-service&lt;/code> type and its properties (the model, the replicas), without touching KServe, without knowing the GPU quotas or the runtime class, and operates with &lt;code>vela up&lt;/code>, &lt;code>vela status&lt;/code> and &lt;code>vela logs&lt;/code>. Multi-site is solved for you by the topology policy, which decides which GPU cluster it lands on, and the override policy, which adjusts replicas or model per site, with a manual approval in the workflow before production.&lt;/p>
&lt;p>The Score alternative would be a &lt;code>score.yaml&lt;/code> with a resource of type &lt;code>inference-endpoint&lt;/code> that &lt;code>score-k8s&lt;/code>, with a custom provisioner, emits as a KServe inference service. More portable, but today it requires that provisioner of your own, because KServe is not a default type. In both cases, the abstraction layer rests on pieces that are already standard (KServe moved to CNCF incubation at the end of 2025 and vLLM is its reference generative runtime), but the inference abstraction is built by you. Take it as a proposal, not as a proven case.&lt;/p>
&lt;p>A note for you: in 2026 KServe introduced a type dedicated to large models, &lt;code>LLMInferenceService&lt;/code>, still in alpha and with vLLM as its runtime, which is the brick a KubeVela definition or a Score provisioner would render underneath. And at the infrastructure layer, not this one, the Crossplane team published Modelplane, an inference control plane made of compositions that serves vLLM directly. Neither of the two is a KubeVela or a Score type, but both confirm for you that the brick underneath is standardising, which is what makes putting a self-service façade on top viable.&lt;/p>
&lt;h2 id="caveats-no-frills">Caveats, no frills&lt;/h2>
&lt;p>This is the section that separates the article from the brochure, and with these two projects you need it especially.&lt;/p>
&lt;p>&lt;strong>Adoption is niche, and there is a hard figure.&lt;/strong> The CNCF technology radar from early 2026, covering more than 400 developers, places Helm, Backstage and Argo CD in &amp;ldquo;Adopt&amp;rdquo;. Neither KubeVela, nor Score, nor Crossplane get a mention. They are niche tools against the mainstream, and choosing them means betting on an adoption curve that may not take off.&lt;/p>
&lt;p>&lt;strong>Score is young and its sponsor changed hands.&lt;/strong> Its Kubernetes implementation has few stars, the specification is at 0.x versions, and Humanitec, which sponsors it, was acquired by Akamai in 2025, so you have to watch the continuity of the investment in the open source part.&lt;/p>
&lt;p>&lt;strong>KubeVela has a concentrated community and v1.11 in alpha.&lt;/strong> The 33 people contributing in 2025 and the flat star curve are a sign of a plateau. Do not build on 1.11 features until it is stable.&lt;/p>
&lt;p>&lt;strong>The CUE curve is real.&lt;/strong> KubeVela&amp;rsquo;s power lives in CUE definitions, and CUE is hard. The cost falls on the platform, but it exists.&lt;/p>
&lt;p>&lt;strong>And the usual risk with abstractions: the leak.&lt;/strong> Both KubeVela and Score add an indirection over Kubernetes and KServe. When something fails underneath, the abstraction cracks and your developer ends up looking at the KServe YAML anyway, plus lock-in on your own definitions. An abstraction that does not hold up under failure hands you back exactly the complexity it promised to hide.&lt;/p>
&lt;h2 id="for-your-sovereign-inference-factory">For your sovereign inference factory&lt;/h2>
&lt;p>The practical decision sorts itself by the profile of your users. If your people live in the CLI and think in applications, KubeVela gives you the Heroku-style experience on your own iron, with real multi-cluster, in exchange for your platform team learning CUE. If what hurts most is the divergence between local and production, Score solves that with the bare minimum, without putting one more runtime in the cluster. And if you want both plus a portal, the Score, Crossplane, KubeVela and Backstage stack exists, but it is for a platform that already serves many teams, not for the start.&lt;/p>
&lt;p>The sobriety criterion is the same as throughout this batch: these tools plug a real gap left by the cloud you walked away from, but each one is one more system to operate. For two teams who know each other, good Helm and a tidy GitOps repository do the job without CUE or definitions of your own. Application-centric self-service starts paying you back when the number of people deploying exceeds the number of people who know Kubernetes, which is precisely the moment an inference factory stops being a project and starts being a platform.&lt;/p>
&lt;p>That closes the batch. The &lt;a href="https://blog.lo0.es/en/posts/public-cloud-to-private-what-you-lose-which-projects-fill-gap/">map&lt;/a> drew the gaps of leaving the cloud, &lt;a href="https://blog.lo0.es/en/posts/crossplane-control-plane-private-cloud-api/">Crossplane&lt;/a> covered the infrastructure control plane, and KubeVela with Score cover the face the developer touches. Your own house now looks quite a lot like the hotel, and the data stayed inside.&lt;/p>
&lt;h2 id="see-also">See also&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://blog.lo0.es/en/posts/public-cloud-to-private-what-you-lose-which-projects-fill-gap/">From the public cloud to the private one: the map&lt;/a> — the complete problem this batch breaks down.&lt;/li>
&lt;li>&lt;a href="https://blog.lo0.es/en/posts/crossplane-control-plane-private-cloud-api/">Crossplane: the private cloud control plane&lt;/a> — the infrastructure layer, complementary to this one.&lt;/li>
&lt;li>&lt;a href="https://blog.lo0.es/en/posts/backstage-self-service-portal-llm-platform/">Backstage as a self-service portal&lt;/a> — the third route to self-service, the web portal one.&lt;/li>
&lt;li>&lt;a href="https://blog.lo0.es/en/posts/kserve-open-inference-protocol-control-plane/">KServe and the open inference protocol&lt;/a> — what the inference definitions would materialise underneath.&lt;/li>
&lt;li>&lt;a href="https://blog.lo0.es/en/posts/gitops-inference-stack-flux/">GitOps for the inference stack with Flux&lt;/a> — the engine KubeVela lives alongside.&lt;/li>
&lt;/ul>
&lt;h2 id="sources">Sources&lt;/h2>
&lt;ul>
&lt;li>KubeVela, &lt;em>State of KubeVela 2025&lt;/em> — &lt;a href="https://kubevela.io/blog/2025/12/20/state-of-kubevela-2025/">https://kubevela.io/blog/2025/12/20/state-of-kubevela-2025/&lt;/a>&lt;/li>
&lt;li>CNCF, &lt;em>KubeVela brings software delivery control plane capabilities to the CNCF incubator&lt;/em> — &lt;a href="https://www.cncf.io/blog/2023/02/27/kubevela-brings-software-delivery-control-plane-capabilities-to-cncf-incubator/">https://www.cncf.io/blog/2023/02/27/kubevela-brings-software-delivery-control-plane-capabilities-to-cncf-incubator/&lt;/a>&lt;/li>
&lt;li>KubeVela Docs, &lt;em>Core Concept&lt;/em> — &lt;a href="https://kubevela.io/docs/getting-started/core-concept/">https://kubevela.io/docs/getting-started/core-concept/&lt;/a>&lt;/li>
&lt;li>KubeVela Docs, &lt;em>vela CLI reference&lt;/em> — &lt;a href="https://kubevela.io/docs/cli/vela/">https://kubevela.io/docs/cli/vela/&lt;/a>&lt;/li>
&lt;li>KubeVela Docs, &lt;em>Custom Component with CUE&lt;/em> — &lt;a href="https://kubevela.io/docs/platform-engineers/components/custom-component/">https://kubevela.io/docs/platform-engineers/components/custom-component/&lt;/a>&lt;/li>
&lt;li>KubeVela Docs, &lt;em>Multi-cluster delivery&lt;/em> — &lt;a href="https://kubevela.io/docs/case-studies/multi-cluster/">https://kubevela.io/docs/case-studies/multi-cluster/&lt;/a>&lt;/li>
&lt;li>KubeVela Docs, &lt;em>VelaUX addon&lt;/em> — &lt;a href="https://kubevela.io/docs/reference/addons/velaux/">https://kubevela.io/docs/reference/addons/velaux/&lt;/a>&lt;/li>
&lt;li>CNCF, &lt;em>Score accepted as a CNCF Sandbox Project&lt;/em> — &lt;a href="https://www.cncf.io/blog/2024/08/08/score-accepted-as-a-cncf-sandbox-project/">https://www.cncf.io/blog/2024/08/08/score-accepted-as-a-cncf-sandbox-project/&lt;/a>&lt;/li>
&lt;li>Score Docs, &lt;em>Overview&lt;/em> — &lt;a href="https://docs.score.dev/docs/">https://docs.score.dev/docs/&lt;/a>&lt;/li>
&lt;li>Score, &lt;em>Score vs the Open Application Model and KubeVela&lt;/em> — &lt;a href="https://score.dev/blog/score-vs-open-application-model-kubevela/">https://score.dev/blog/score-vs-open-application-model-kubevela/&lt;/a>&lt;/li>
&lt;li>GitHub, &lt;em>score-compose&lt;/em> — &lt;a href="https://github.com/score-spec/score-compose">https://github.com/score-spec/score-compose&lt;/a>&lt;/li>
&lt;li>GitHub, &lt;em>score-k8s&lt;/em> — &lt;a href="https://github.com/score-spec/score-k8s">https://github.com/score-spec/score-k8s&lt;/a>&lt;/li>
&lt;li>CNCF, &lt;em>KServe becomes a CNCF Incubating Project&lt;/em> — &lt;a href="https://www.cncf.io/blog/2025/11/11/kserve-becomes-a-cncf-incubating-project/">https://www.cncf.io/blog/2025/11/11/kserve-becomes-a-cncf-incubating-project/&lt;/a>&lt;/li>
&lt;li>KServe Docs, &lt;em>Understanding LLMInferenceService&lt;/em> — &lt;a href="https://kserve.github.io/website/docs/model-serving/generative-inference/llmisvc/llmisvc-overview">https://kserve.github.io/website/docs/model-serving/generative-inference/llmisvc/llmisvc-overview&lt;/a>&lt;/li>
&lt;li>Crossplane Blog, &lt;em>Building Modelplane on Crossplane&lt;/em> — &lt;a href="https://blog.crossplane.io/building-modelplane/">https://blog.crossplane.io/building-modelplane/&lt;/a> · &lt;a href="https://modelplane.ai">https://modelplane.ai&lt;/a>&lt;/li>
&lt;li>CNCF y SlashData, &lt;em>Technology Radar Q1 2026: Platform Engineering&lt;/em> — &lt;a href="https://www.cncf.io/announcements/2026/03/24/cncf-and-slashdata-report-finds-platform-engineering-tools-maturing-as-organizations-prepare-for-ai-driven-infrastructure/">https://www.cncf.io/announcements/2026/03/24/cncf-and-slashdata-report-finds-platform-engineering-tools-maturing-as-organizations-prepare-for-ai-driven-infrastructure/&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Crossplane: the control plane that turns your cluster into a private cloud API</title><link>https://blog.lo0.es/en/posts/crossplane-control-plane-private-cloud-api/</link><pubDate>Mon, 31 Aug 2026 09:30:00 +0200</pubDate><guid>https://blog.lo0.es/en/posts/crossplane-control-plane-private-cloud-api/</guid><description>&lt;blockquote>
&lt;p>Second article in the batch about rebuilding the cloud experience on-premise. The &lt;a href="https://blog.lo0.es/en/posts/public-cloud-to-private-what-you-lose-which-projects-fill-gap/">general map&lt;/a> placed the gaps for you; this one goes into the provisioning control plane, that API which on-premise does not come for free. The &lt;a href="https://blog.lo0.es/en/posts/kubevela-score-platform-cli-without-teaching-kubernetes/">third&lt;/a> moves up a layer, to application-centric self-service with KubeVela and Score.&lt;/p>
&lt;/blockquote>
&lt;h2 id="tldr">TL;DR&lt;/h2>
&lt;p>Crossplane solves the &amp;ldquo;open a ticket and wait&amp;rdquo; gap for you. In the cloud you ask for a database through an API and it appears with permissions, backups and monitoring; on-premise you do that provisioning by hand or with scripts. Crossplane brings the Kubernetes model of declarative APIs to infrastructure: your platform team defines an API of its own (a database, an inference endpoint) and the developer consumes it with a &lt;code>kubectl apply&lt;/code> of a few fields, while controllers inside the cluster reconcile the desired state against reality and correct drift continuously. It graduated from the CNCF in November 2025, with more than three thousand contributors and adopters such as Nike, SAP, IBM or NASA&amp;rsquo;s science cloud.&lt;/p>
&lt;p>The difference from Terraform is one of nature, not of features: Terraform applies a plan on demand and leaves; Crossplane is a control plane that lives inside the cluster and never stops reconciling. That gives you drift self-correction and native GitOps, and in exchange it takes away the safety net of &lt;code>plan&lt;/code> and forces you to operate the control plane itself, with providers that create hundreds of resource definitions and state that lives in etcd. And a warning about something awkward up front: Crossplane is not an imperative &lt;code>aws ...&lt;/code> style CLI, it is declarative first. On the fit with GPU inference, which until recently was only a pattern with no public case, you now have a real reference, Modelplane, from the Crossplane team itself, although at version 0.1 and composing vLLM directly without going through KServe. I go into the detail at the end.&lt;/p>
&lt;h2 id="the-analogy-the-thermostat-against-the-light-switch">The analogy: the thermostat against the light switch&lt;/h2>
&lt;p>Think of it this way: Terraform is a light switch. You flip it, the light comes on, and it stays there until you touch it again. If somebody else changes it, the light obeys whoever touched it last, and you do not find out until you go and look. It is provisioning by one-off action: you run it, it applies, it finishes.&lt;/p>
&lt;p>Crossplane is a thermostat. You do not tell it &amp;ldquo;turn the heating on&amp;rdquo;, you tell it &amp;ldquo;I want twenty-one degrees&amp;rdquo;, and from then on a mechanism watches the temperature and acts on its own, continuously, to hold it. If somebody opens a window and the thermometer drops, the thermostat reacts without you intervening. That is continuous reconciliation: you declare the desired state once and a controller takes care of reality not straying from it.&lt;/p>
&lt;p>The analogy also warns you about the cost. A thermostat is more convenient than a switch, but it is one more device you have to install, power and fix when it fails, and if you program it badly it adjusts the temperature to something you did not want, without asking. A switch almost never breaks and you always know what state it is in. Crossplane gives you the convenience of the thermostat in exchange for you operating the thermostat.&lt;/p>
&lt;h2 id="what-crossplane-is-and-what-state-it-reaches-2026-in">What Crossplane is and what state it reaches 2026 in&lt;/h2>
&lt;p>Crossplane was born at Upbound in 2018 and followed the CNCF maturity path without shortcuts: sandbox in 2020, incubation in 2021 and &lt;strong>graduation on 6 November 2025&lt;/strong>. Graduation matters because it is the seal the CNCF reserves for projects it considers production-ready, the same level as Kubernetes or Prometheus. The figures that came with the announcement are solid: more than three thousand contributors from more than 450 organisations, more than a thousand pull request authors (which puts it in the top 10 % of the foundation&amp;rsquo;s projects by that metric), more than a hundred releases and two completed security audits. Among the more than seventy public adopters you have Nike, Nokia, Grafana, NASA&amp;rsquo;s science cloud, SAP and IBM.&lt;/p>
&lt;p>The project&amp;rsquo;s official description is &amp;ldquo;the cloud native control plane&amp;rdquo;, and that phrase sums up exactly what it does. The main vendor behind it is still Upbound, which at graduation framed the project&amp;rsquo;s future towards &amp;ldquo;AI-native&amp;rdquo; infrastructure, a point I come back to when talking about inference, with the caveat that it is a vendor&amp;rsquo;s positioning, not a proven case.&lt;/p>
&lt;p>The release cadence is quarterly, with a nine-month support window and three actively maintained versions at any time. As of writing, the v2 branch is the current one, with v1.20 as the last close of the v1 branch.&lt;/p>
&lt;h2 id="the-v2-turn-which-changes-how-you-think-about-it">The v2 turn (which changes how you think about it)&lt;/h2>
&lt;p>Crossplane 2.0 reached general availability in August 2025 and brings four structural changes you need to know about, because a good deal of the old material describes a model that is no longer the recommended one.&lt;/p>
&lt;p>The first is that &lt;strong>resources are now namespaced by default&lt;/strong>. Both composite and managed resources, which used to be cluster-scoped, now live in a namespace, which enables fine-grained access control and natural multi-tenancy, exactly what you need in a sovereign platform with several teams.&lt;/p>
&lt;p>The second is that &lt;strong>a composition can include any Kubernetes resource&lt;/strong>, not only Crossplane resources. Previously a composition was limited to Crossplane&amp;rsquo;s own managed resources; now it can include Deployments, Services or third-party CRDs, so you can compose abstractions mixing application and infrastructure in a single object. This change is what makes the inference pattern you will see viable.&lt;/p>
&lt;p>The third is that &lt;strong>Claims disappear&lt;/strong>. In the v1 model there was a duality between the composite resource, cluster-scoped, and the Claim, its namespaced face which the developer consumed. Now that the composite resource is itself namespaced, that duality is redundant: the developer consumes the composite resource with no intermediary. If you come across documentation talking about Claims, it belongs to the earlier model.&lt;/p>
&lt;p>The fourth is a new type, &lt;code>Operations&lt;/code>, for one-off or scheduled operational tasks that run a pipeline of functions to completion, like a Kubernetes Job but inside the Crossplane model.&lt;/p>
&lt;p>There is one removal that deserves its own paragraph, because it is the most surprising: in v2 native patch-and-transform was withdrawn, the classic patching mechanism of compositions. It was not relegated, it was removed. Everything now goes through composition functions, and I get to that in a moment. Migration from v1 to v2 is mostly non-breaking and the v1 APIs still work, so adopting v2 is optional, but the new model is the one you have to learn.&lt;/p>
&lt;h2 id="the-model-piece-by-piece">The model, piece by piece&lt;/h2>
&lt;p>Crossplane has dense jargon and I will take it apart calmly, because once the pieces are placed the whole thing is coherent.&lt;/p>
&lt;p>&lt;strong>A provider&lt;/strong> is a package that installs controllers and resource definitions to talk to an external API, be it AWS, GCP, a remote Kubernetes cluster, Helm or Terraform. It is installed declaratively, by applying a &lt;code>Provider&lt;/code> object. The providers for the big cloud providers are generated with Upjet, a framework that produces the code from the Terraform providers, which explains why there are so many of them and also why some are enormous.&lt;/p>
&lt;p>&lt;strong>A managed resource&lt;/strong> is the one-to-one representation, inside Kubernetes, of a resource from the external provider: a bucket, an instance, a database. It is the unit the controller reconciles. When you create a managed resource of type bucket, the provider&amp;rsquo;s controller creates the real bucket and then watches that it keeps existing with the configuration you declared.&lt;/p>
&lt;p>On those bricks you build the abstraction, which is where the real value is, with three concepts:&lt;/p>
&lt;p>The &lt;strong>CompositeResourceDefinition&lt;/strong>, or XRD, defines the schema of your own API: which fields the user can ask for. It is what turns &amp;ldquo;a database&amp;rdquo; into a resource type with its parameters.&lt;/p>
&lt;p>The &lt;strong>Composition&lt;/strong> is the template and the logic that, given one of those resources, materialises the N managed resources needed underneath. The documentation says it bluntly: a composition is a pipeline of composition functions.&lt;/p>
&lt;p>The &lt;strong>Composite Resource&lt;/strong>, or XR, is the concrete instance: the object the developer creates with &lt;code>kubectl apply&lt;/code>, with the few fields the XRD exposes.&lt;/p>
&lt;p>The complete pattern is this: your platform operator publishes the abstraction (the XRD plus the Composition, which say &amp;ldquo;this is what a database means here&amp;rdquo;), and the developer only applies a composite resource with four fields. How it is built underneath stops mattering to them, just as in the cloud you do not care how AWS assembles your managed database.&lt;/p>
&lt;h2 id="composition-functions-the-real-logic">Composition functions: the real logic&lt;/h2>
&lt;p>The composition mechanism in v2, and the only one, is &lt;strong>composition functions&lt;/strong>. A composition is a pipeline of functions that Crossplane invokes over gRPC; each function receives the observed state, the desired state, its input and a shared context, and chains its output to the next one. The YAML in the examples is illustrative, but underneath it is not processed as YAML: it is executed as functions.&lt;/p>
&lt;p>The available functions cover several styles. You have &lt;code>function-patch-and-transform&lt;/code>, which reimplements the old model now as just another function. There is &lt;code>function-go-templating&lt;/code> for Helm-style templates, &lt;code>function-kcl&lt;/code> for the KCL language, &lt;code>function-python&lt;/code> for logic in Python and &lt;code>function-cue&lt;/code> for CUE.&lt;/p>
&lt;p>The reason for the change is what you want to understand. Classic patch-and-transform had no loops or conditionals, so an operation as simple as transforming an array of strings turned into dozens of lines of patching, and the community went as far as calling it outright bad. Functions give you full programming logic (loops, conditionals, external calls) in a real language. The honest flip side is that the complexity does not disappear: it shifts from &amp;ldquo;writing verbose patches&amp;rdquo; to &amp;ldquo;writing and operating functions&amp;rdquo;, which is a different kind of work, not less work.&lt;/p>
&lt;h2 id="crossplane-against-terraform-opentofu-and-pulumi">Crossplane against Terraform, OpenTofu and Pulumi&lt;/h2>
&lt;p>This is the comparison everybody makes, and I will make it properly because the difference is one of category. According to Pulumi&amp;rsquo;s own documentation, which compares honestly, Crossplane is a declarative control plane with continuous reconciliation inside Kubernetes, while Terraform and Pulumi are infrastructure as code executed one-off, client-side and on demand.&lt;/p>
&lt;p>The practical consequences line up along a few axes. Faced with configuration drift, Crossplane corrects it continuously and automatically, while Terraform and Pulumi only detect it when you run a refresh. Crossplane needs a cluster to run on, because it is controllers; Terraform and Pulumi do not. Crossplane is GitOps-native, applied with kubectl and fitting with &lt;a href="https://blog.lo0.es/en/posts/gitops-inference-stack-flux/">Flux&lt;/a> without an adapter; Pulumi needs its Kubernetes operator for the same thing. And as for language, Crossplane uses YAML and CRDs with logic in the functions, while Pulumi uses general-purpose programming languages.&lt;/p>
&lt;p>The point most often forgotten is that &lt;strong>you do not have to choose one or the other&lt;/strong>. There is a Terraform provider (and an OpenTofu one, recommended for new versions because the Terraform one was frozen at the last freely licensed version) that runs HCL &lt;em>inside&lt;/em> Crossplane, wrapping your existing modules as a managed resource. You can reuse your whole investment in Terraform and still gain continuous reconciliation for whatever needs it. If you already have Terraform in production, this hybrid pattern is usually your sensible route, not the rewrite.&lt;/p>
&lt;p>On comparative adoption you have to be sober: there is no official, reliable &amp;ldquo;Crossplane against Terraform&amp;rdquo; figure, and the most repeated documented criticism is that Crossplane lacks the mature module ecosystem Terraform has been accumulating for years. That is a real qualitative difference, not a detail.&lt;/p>
&lt;h2 id="the-awkward-question-is-it-an-aws-style-cli">The awkward question: is it an AWS-style CLI?&lt;/h2>
&lt;p>Since on this blog I have been pulling on the thread of CLI provisioning, I will answer directly: &lt;strong>no&lt;/strong>. Crossplane does not offer you an imperative &lt;code>aws s3 create-bucket&lt;/code> style experience. It is declarative first. You provision with a &lt;code>kubectl apply&lt;/code> of a resource, and the &lt;code>crossplane&lt;/code> binary is there to build, package, test and debug, not to &amp;ldquo;create a bucket&amp;rdquo; in one go.&lt;/p>
&lt;p>The subcommands make that clear. &lt;code>crossplane render&lt;/code> renders a composition and its functions locally, so you can test without a cluster. The &lt;code>crossplane xpkg build&lt;/code>, &lt;code>push&lt;/code>, &lt;code>install&lt;/code> family manages the OCI packages of providers, configurations and functions. And &lt;code>crossplane beta validate&lt;/code>, &lt;code>trace&lt;/code> and &lt;code>top&lt;/code> validate schemas, draw the resource tree and show consumption inside the cluster. It is the toolbox of whoever builds the platform, not of whoever consumes it day to day. Upbound&amp;rsquo;s &lt;code>up&lt;/code> CLI adds more, but oriented towards its commercial product.&lt;/p>
&lt;p>The conclusion matters for setting expectations: the imperative AWS-console-style experience, if you want it, gets built &lt;em>on top of&lt;/em> Crossplane, with Backstage, a portal or your own wrapper. Crossplane gives you the declarative API; the friendly face you put on separately. If what you are after is an imperative provisioning CLI, you fit better with the model of &lt;a href="https://blog.lo0.es/en/posts/kubevela-score-platform-cli-without-teaching-kubernetes/">KubeVela and Score&lt;/a>, which is precisely the subject of the next article.&lt;/p>
&lt;h2 id="on-premise-providers-provisioning-without-touching-aws">On-premise providers: provisioning without touching AWS&lt;/h2>
&lt;p>For a sovereign platform your question is what you can provision without setting foot in a public cloud, and the answer is more than it seems, with uneven maturity.&lt;/p>
&lt;p>The most versatile is &lt;code>provider-kubernetes&lt;/code>, which manages any Kubernetes object in remote clusters through an &lt;code>Object&lt;/code> resource. It is the basis of the multi-cluster on-premise pattern: from a central cluster you materialise resources in your secondary RKE2s. Alongside it, &lt;code>provider-helm&lt;/code> installs and manages Helm charts declaratively through a &lt;code>Release&lt;/code> resource, letting you deploy things like vLLM or KServe as part of a composition.&lt;/p>
&lt;p>For the identity and storage part you have concrete pieces: &lt;code>provider-keycloak&lt;/code> configures Keycloak realms, clients and roles declaratively, useful for the sovereign IAM we already set up in &lt;a href="https://blog.lo0.es/en/posts/mcp-grows-up-authentication-keycloak/">the article on authentication with Keycloak&lt;/a>; and &lt;code>provider-minio&lt;/code> manages buckets and policies of on-premise S3-compatible storage. For vSphere you do not have a first-class native provider, but you cover it by generating one from the Terraform provider, the usual pattern for VMware infrastructure.&lt;/p>
&lt;p>An honest warning: for KubeVirt, Harvester or CloudNativePG there are no mature, first-class native providers; in practice you manage them by applying their CRDs through &lt;code>provider-kubernetes&lt;/code> or by wrapping their Terraform. It works, but it is not the polished experience of a dedicated provider. With the combination of provider-kubernetes, provider-helm, provider-minio and provider-keycloak, plus provider-terraform for whatever is missing, you can assemble a one hundred per cent on-premise self-service catalogue, with the caveat that maturity varies piece by piece.&lt;/p>
&lt;h2 id="the-fit-with-gpu-inference-from-pattern-to-modelplane">The fit with GPU inference: from pattern to Modelplane&lt;/h2>
&lt;p>This is the section that in the first version of this text carried the most caution, because there was no public case of Crossplane orchestrating GPU and inference and it all remained a design pattern. Halfway through 2026 that changed, and the case was published by the very team that makes Crossplane.&lt;/p>
&lt;p>&lt;strong>Modelplane&lt;/strong> is an open source control plane for AI inference, Apache-licensed and with a first version 0.1 from June 2026, and the interesting thing is how it is built: entirely on Crossplane compositions and composition functions in Python, with no controllers of its own. It composes vLLM directly, with the &lt;code>vllm/vllm-openai&lt;/code> image, without going through KServe, and its self-service API for the ML teams is a &lt;code>ModelDeployment&lt;/code> resource where you declare the model, the engine, the topology and the hardware. Underneath, a &lt;code>ModelReplica&lt;/code> resource represents each replica, and the platform team declares its GPU pools with &lt;code>InferenceCluster&lt;/code> and &lt;code>InferenceClass&lt;/code> resources, using an attribute model and CEL expressions taken from Kubernetes dynamic resource allocation. Its most advanced piece is a two-level fleet scheduler written as a pure function, which places replicas across the whole infrastructure and delegates to each cluster&amp;rsquo;s scheduler. It is proof that the pattern works, with the warning that it is a version 0.1 under open development, not something to put into production blindly, and that adopting it ties your platform to its resource types.&lt;/p>
&lt;p>The other recent enabler is in KServe, which introduced a type dedicated to large models, &lt;code>LLMInferenceService&lt;/code>, still in alpha and built on the llm-d project, with prefill and decode separation and multi-node execution, and which runs vLLM as its runtime. It is different from the classic &lt;code>InferenceService&lt;/code>, reserved for predictive ML. That new type is your ideal brick if you prefer composing KServe instead of bare vLLM.&lt;/p>
&lt;p>With that, your own golden path stops being a hypothesis. You define an XRD, for example &lt;code>InferenceEndpoint&lt;/code>, with fields such as the model, the number and type of GPU and the replicas. Its composition, taking advantage of the fact that in v2 it can include any Kubernetes resource, materialises in a single pipeline the team&amp;rsquo;s namespace, the quota for &lt;code>nvidia.com/gpu&lt;/code> and a KServe &lt;code>LLMInferenceService&lt;/code> pointing at the model with vLLM runtime, and the developer only applies the &lt;code>InferenceEndpoint&lt;/code> with four fields, knowing nothing about KServe or the quotas underneath. KServe supports vLLM and GPU natively, as we saw in &lt;a href="https://blog.lo0.es/en/posts/kserve-open-inference-protocol-control-plane/">the article on KServe&lt;/a>.&lt;/p>
&lt;p>The honest reading is that you are at the frontier, not on well-trodden ground. Outside Modelplane, made by Upbound, there is still no body of independent cases assembling Crossplane with vLLM, and the KServe type is in alpha. It is a coherent architecture, with a real reference backing it and plenty of room for you to be among the first to document it on your own iron.&lt;/p>
&lt;h2 id="what-it-costs-you-to-operate-your-own-control-plane">What it costs you to operate your own control plane&lt;/h2>
&lt;p>No tool that gives you back control is free, and Crossplane has well-documented costs you need to budget for beforehand, not discover afterwards.&lt;/p>
&lt;p>&lt;strong>The learning curve is steep&lt;/strong>, acknowledged even in the coverage of its graduation. Adopters report debugging difficulties when a composition or a provider misbehaves, and they miss Terraform&amp;rsquo;s module ecosystem.&lt;/p>
&lt;p>&lt;strong>Compositions tend towards complexity.&lt;/strong> There are practitioners describing definitions spanning thousands of lines with poor navigation, and the absence of an integrated testing framework. Functions improve this, but as I said, they shift the complexity rather than remove it.&lt;/p>
&lt;p>&lt;strong>There is no &lt;code>plan&lt;/code>.&lt;/strong> Unlike Terraform&amp;rsquo;s &lt;code>plan&lt;/code> and &lt;code>apply&lt;/code> cycle, Crossplane applies changes immediately. You lose the safety net of reviewing what is going to happen before it happens, with the risk of modifications you did not want.&lt;/p>
&lt;p>&lt;strong>Operating the control plane itself costs.&lt;/strong> Big providers create hundreds of resource definitions (the GCP one reached 347), with a risk of API server unavailability and of leaving your cluster hanging. State lives in etcd, which complicates disaster recovery and migrating control between clusters. And there is one specific danger: accidental deletion of cloud resources when upgrading XRDs, providers or compositions, because of the ownership Crossplane keeps over what it created.&lt;/p>
&lt;p>Some have decided not to adopt it. The Masterpoint team ruled it out for the lack of data sources and &lt;code>ignore_changes&lt;/code>, for incomplete coverage of AWS services, and for the cost of abandoning their accumulated Terraform experience. It is a legitimate decision, and quoting it to you is part of an honest article.&lt;/p>
&lt;h2 id="how-it-lives-alongside-what-you-already-have">How it lives alongside what you already have&lt;/h2>
&lt;p>If you already run a platform, your question is not Crossplane yes or no, but Crossplane with what. Three relationships matter to you.&lt;/p>
&lt;p>With &lt;strong>Backstage&lt;/strong> they are complementary, not rivals. Backstage is the portal and the templates that generate manifests or pull requests, day zero; Crossplane provisions and reconciles the real state, day two. The usual pattern, which some call the golden triangle, is Backstage as the interface, Crossplane as the control plane and Argo CD or Flux as GitOps. Each one does a layer.&lt;/p>
&lt;p>With &lt;strong>Flux&lt;/strong>, which you probably already use, the relationship is additive. Flux reconciles manifests towards the clusters, but it does not give you a platform abstraction API: it does not know what &amp;ldquo;a database&amp;rdquo; is, it only applies the YAML you hand it. Crossplane adds exactly that abstraction layer, and the two coexist, with Flux deploying the composite resources and Crossplane materialising them. If you already have Flux, Crossplane&amp;rsquo;s value is precisely that self-service API layer, in exchange for the cost of operating the control plane I described above.&lt;/p>
&lt;p>With &lt;strong>KubeVela and Score&lt;/strong>, the subject of the next article, the boundary is one of layer: Crossplane answers &amp;ldquo;give me a Postgres&amp;rdquo;, from the infrastructure side; KubeVela and Score answer &amp;ldquo;deploy my application&amp;rdquo;, from the workload side. They do not compete, they stack.&lt;/p>
&lt;h2 id="for-your-sovereign-inference-factory">For your sovereign inference factory&lt;/h2>
&lt;p>The practical decision boils down to this. Crossplane makes sense when you want to expose a self-service API of your own over your on-premise infrastructure and you are willing to operate a control plane to get it. If your platform is used by two teams who know each other and you provision with a tidy Flux repository, Crossplane is cost without return for now. The trigger is scale: when manual provisioning turns into a ticket bottleneck, the declarative API starts paying back its cost.&lt;/p>
&lt;p>Your sensible entry route is not rewriting everything. It is starting with a provider that already serves you (provider-kubernetes and provider-helm cover a lot), wrapping your existing Terraform with the corresponding provider instead of throwing it away, and modelling a single abstraction of clear value, probably the &lt;code>InferenceEndpoint&lt;/code> we discussed, as a golden path. From there, you grow on demand. And always with a clear account of having traded the safety net of &lt;code>plan&lt;/code> and a handful of scripts for a thermostat you have to keep switched on.&lt;/p>
&lt;p>The next article moves up a layer, from the infrastructure resource to the application workload, with &lt;a href="https://blog.lo0.es/en/posts/kubevela-score-platform-cli-without-teaching-kubernetes/">KubeVela and Score&lt;/a>, which is where the friendly CLI that Crossplane deliberately does not give you finally appears.&lt;/p>
&lt;h2 id="see-also">See also&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://blog.lo0.es/en/posts/public-cloud-to-private-what-you-lose-which-projects-fill-gap/">From the public cloud to the private one: the map&lt;/a> — where this control plane fits in the whole.&lt;/li>
&lt;li>&lt;a href="https://blog.lo0.es/en/posts/kubevela-score-platform-cli-without-teaching-kubernetes/">KubeVela and Score: self-service by CLI&lt;/a> — the application layer, the CLI Crossplane does not offer.&lt;/li>
&lt;li>&lt;a href="https://blog.lo0.es/en/posts/backstage-self-service-portal-llm-platform/">Backstage as a self-service portal&lt;/a> — the interface built on top of the control plane.&lt;/li>
&lt;li>&lt;a href="https://blog.lo0.es/en/posts/gitops-inference-stack-flux/">GitOps for the inference stack with Flux&lt;/a> — the engine Crossplane lives with, not competes with.&lt;/li>
&lt;li>&lt;a href="https://blog.lo0.es/en/posts/kserve-open-inference-protocol-control-plane/">KServe and the open inference protocol&lt;/a> — what the inference golden path would materialise underneath.&lt;/li>
&lt;/ul>
&lt;h2 id="sources">Sources&lt;/h2>
&lt;ul>
&lt;li>CNCF, &lt;em>Announces Graduation of Crossplane&lt;/em> (6-nov-2025) — &lt;a href="https://www.cncf.io/announcements/2025/11/06/cloud-native-computing-foundation-announces-graduation-of-crossplane/">https://www.cncf.io/announcements/2025/11/06/cloud-native-computing-foundation-announces-graduation-of-crossplane/&lt;/a>&lt;/li>
&lt;li>Crossplane Blog, &lt;em>Announcing Crossplane&amp;rsquo;s CNCF Graduation&lt;/em> — &lt;a href="https://blog.crossplane.io/crossplane-cncf-graduation/">https://blog.crossplane.io/crossplane-cncf-graduation/&lt;/a>&lt;/li>
&lt;li>Crossplane Blog, &lt;em>Announcing Crossplane 2.0&lt;/em> — &lt;a href="https://blog.crossplane.io/announcing-crossplane-2-0/">https://blog.crossplane.io/announcing-crossplane-2-0/&lt;/a>&lt;/li>
&lt;li>Crossplane Docs, &lt;em>What&amp;rsquo;s New in v2&lt;/em> — &lt;a href="https://docs.crossplane.io/latest/whats-new/">https://docs.crossplane.io/latest/whats-new/&lt;/a>&lt;/li>
&lt;li>Crossplane Docs, &lt;em>Compositions&lt;/em> — &lt;a href="https://docs.crossplane.io/latest/composition/compositions/">https://docs.crossplane.io/latest/composition/compositions/&lt;/a>&lt;/li>
&lt;li>Crossplane Docs, &lt;em>Release Cycle&lt;/em> — &lt;a href="https://docs.crossplane.io/latest/learn/release-cycle/">https://docs.crossplane.io/latest/learn/release-cycle/&lt;/a>&lt;/li>
&lt;li>Crossplane Docs, &lt;em>Crossplane CLI&lt;/em> — &lt;a href="https://docs.crossplane.io/latest/cli/">https://docs.crossplane.io/latest/cli/&lt;/a>&lt;/li>
&lt;li>Upbound, &lt;em>Crossplane Graduates From CNCF, Upbound Redefines AI-Native Infrastructure&lt;/em> — &lt;a href="https://www.upbound.io/blog/crossplane-graduates-from-cncf-upbound-redefines-ai-native-infrastructure">https://www.upbound.io/blog/crossplane-graduates-from-cncf-upbound-redefines-ai-native-infrastructure&lt;/a>&lt;/li>
&lt;li>InfoQ, &lt;em>Crossplane Reaches Production Maturity by Graduating CNCF&lt;/em> — &lt;a href="https://www.infoq.com/news/2025/11/crossplane-grad/">https://www.infoq.com/news/2025/11/crossplane-grad/&lt;/a>&lt;/li>
&lt;li>Pulumi Docs, &lt;em>Pulumi vs. Crossplane&lt;/em> — &lt;a href="https://www.pulumi.com/docs/iac/comparisons/crossplane/">https://www.pulumi.com/docs/iac/comparisons/crossplane/&lt;/a>&lt;/li>
&lt;li>Upbound Marketplace, &lt;em>provider-terraform&lt;/em> — &lt;a href="https://marketplace.upbound.io/providers/upbound/provider-terraform/latest">https://marketplace.upbound.io/providers/upbound/provider-terraform/latest&lt;/a>&lt;/li>
&lt;li>GitHub, &lt;em>provider-kubernetes&lt;/em> — &lt;a href="https://github.com/crossplane-contrib/provider-kubernetes">https://github.com/crossplane-contrib/provider-kubernetes&lt;/a>&lt;/li>
&lt;li>GitHub, &lt;em>provider-helm&lt;/em> — &lt;a href="https://github.com/crossplane-contrib/provider-helm">https://github.com/crossplane-contrib/provider-helm&lt;/a>&lt;/li>
&lt;li>GitHub, &lt;em>provider-keycloak&lt;/em> — &lt;a href="https://github.com/crossplane-contrib/provider-keycloak">https://github.com/crossplane-contrib/provider-keycloak&lt;/a>&lt;/li>
&lt;li>VSHN, &lt;em>provider-minio&lt;/em> — &lt;a href="https://github.com/vshn/provider-minio">https://github.com/vshn/provider-minio&lt;/a>&lt;/li>
&lt;li>Masterpoint, &lt;em>Crossplane: Why it Didn&amp;rsquo;t Work for Us&lt;/em> — &lt;a href="https://masterpoint.io/blog/passing-on-crossplane/">https://masterpoint.io/blog/passing-on-crossplane/&lt;/a>&lt;/li>
&lt;li>CECG, &lt;em>Crossplane: the good, the bad and the ugly&lt;/em> — &lt;a href="https://www.cecg.io/blog/crossplane-the-good-the-bad-the-ugly">https://www.cecg.io/blog/crossplane-the-good-the-bad-the-ugly&lt;/a>&lt;/li>
&lt;li>Taloflow, &lt;em>Backstage vs Crossplane for Platform Engineering&lt;/em> — &lt;a href="https://www.taloflow.ai/guides/comparisons/backstage-vs-crossplane-platform-engineering">https://www.taloflow.ai/guides/comparisons/backstage-vs-crossplane-platform-engineering&lt;/a>&lt;/li>
&lt;li>Crossplane Blog, &lt;em>Building Modelplane on Crossplane&lt;/em> — &lt;a href="https://blog.crossplane.io/building-modelplane/">https://blog.crossplane.io/building-modelplane/&lt;/a>&lt;/li>
&lt;li>Modelplane — &lt;a href="https://modelplane.ai">https://modelplane.ai&lt;/a> · &lt;a href="https://github.com/modelplaneai/modelplane">https://github.com/modelplaneai/modelplane&lt;/a>&lt;/li>
&lt;li>KServe Docs, &lt;em>Understanding LLMInferenceService&lt;/em> — &lt;a href="https://kserve.github.io/website/docs/model-serving/generative-inference/llmisvc/llmisvc-overview">https://kserve.github.io/website/docs/model-serving/generative-inference/llmisvc/llmisvc-overview&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>From public cloud to private: what you really lose and which projects fill the gap</title><link>https://blog.lo0.es/en/posts/public-cloud-to-private-what-you-lose-which-projects-fill-gap/</link><pubDate>Mon, 31 Aug 2026 09:15:00 +0200</pubDate><guid>https://blog.lo0.es/en/posts/public-cloud-to-private-what-you-lose-which-projects-fill-gap/</guid><description>&lt;blockquote>
&lt;p>With this one I open a run about the biggest gap a sovereign platform leaves you: how to give your teams the self-service experience of a public cloud, without the public cloud. Here you have the map of the problem; the next two go down into the detail of the tools, &lt;a href="https://blog.lo0.es/en/posts/crossplane-control-plane-private-cloud-api/">Crossplane&lt;/a> as the infrastructure control plane and &lt;a href="https://blog.lo0.es/en/posts/kubevela-score-platform-cli-without-teaching-kubernetes/">KubeVela with Score&lt;/a> as application-centric self-service.&lt;/p>
&lt;/blockquote>
&lt;h2 id="tldr">TL;DR&lt;/h2>
&lt;p>Leaving the public cloud has a solid business case, and I am not making it up. 37signals declared savings of close to two million dollars in 2024 after repatriating, the classic a16z analysis puts cloud spend at around half of the cost of revenue of a software company, and the Barclays CIO survey of 2024 recorded the highest repatriation intent in its history. If your workload is a predictable, sustained base (which is exactly the continuous LLM inference this blog is about) the numbers work out, and in Europe the sovereignty reasons pile on top: the Data Act, the tension with the US CLOUD Act, and that dependence on three hyperscalers that control around 70 % of the European cloud market.&lt;/p>
&lt;p>But the problem is not the compute. Your on-premise GPU rack serves tokens just as well as a rented one. What the cloud was selling you and you now have to rebuild is something else: the elasticity of asking for a hundred machines at ten and handing them back at eleven, the catalogue of hundreds of managed services with an on-call team behind them, the unified provisioning API with fine-grained permissions, the multi-region network, the bill that arrives itemised, and that model where operating all of it was somebody else&amp;rsquo;s problem. All of that you rebuild piece by piece with open source projects, and the rebuild has a cost that the savings figures do not usually tell you about. What follows is the map of what you lose, which project fills each gap, and where a gap remains that nothing will close completely.&lt;/p>
&lt;h2 id="the-analogy-leaving-the-hotel-to-set-up-your-own-house">The analogy: leaving the hotel to set up your own house&lt;/h2>
&lt;p>Think of it like this: living in the public cloud is living in a hotel. You pay a lot per night, but you do not change light bulbs, reception is open at three in the morning, if you need another room you ask for it and it appears, and when you leave you take nothing with you to maintain. Setting up your own house works out much cheaper per square metre if you are going to stay for years, and on top of that you decide who comes in and where your things are kept. The problem arrives the day a pipe bursts: then you do not call reception, because reception is you.&lt;/p>
&lt;p>Repatriation is that move. The savings are real and so is data ownership, but what in the hotel came included in the price of the night is now your to-do list: the plumbing is your network, the boiler is your storage, the concierge who got you anything is the catalogue of managed services you no longer have, and the itemised bill they slid under your door is a cost model you have to build, because electricity and depreciation do not arrive broken down per tenant. The house pays off, but only if you count what it costs to furnish it and fix the pipes, not just the price per square metre against the hotel.&lt;/p>
&lt;p>The rest of the article walks through that to-do list and tells you, for each item, which open source tool does the job the hotel used to do for you.&lt;/p>
&lt;h2 id="why-this-conversation-belongs-to-2026-not-to-always">Why this conversation belongs to 2026, not to always&lt;/h2>
&lt;p>Repatriating is nothing new, but in 2026 three things come together that make it urgent if you run a European AI platform.&lt;/p>
&lt;p>The first is economic, and Andreessen Horowitz put it on the table in 2021 with &lt;em>The Cost of Cloud, a Trillion Dollar Paradox&lt;/em>. Their thesis, which you should read knowing that a16z has interests in the ecosystem it analyses, is that cloud spend averages around 50 % of the cost of revenue in a software company, and that recovering half of that spend would free up margins the market penalises. The cleanest case, and one you can verify, is 37signals: DHH published that their cloud bill dropped from 3.2 to 1.3 million dollars a year after repatriating, with an initial investment of about 700,000 dollars in Dell servers. Now the honest caveat, which the specialist press itself underlines: those savings figures did not include the extra operations staff, nor the energy, nor the cooling. I come back to it in the hidden costs section.&lt;/p>
&lt;p>The second is declared intent. The Barclays CIO survey from the first half of 2024 recorded that 83 % planned to repatriate some workload to private cloud or on-premise in the following twelve months, the highest reading in the series. But read that 83 % precisely: it is the proportion of managers who plan to move &lt;em>some&lt;/em> workload, not the percentage of workloads or of spend that moves. Flexera, in its 2025 report, gives you the more grounded figure: large companies have repatriated around 21 % of the workloads they had in the public cloud, and cost saving is priority number one for almost 60 %.&lt;/p>
&lt;p>The third is regulatory and European, and it is the one that turns repatriation into something more than a FinOps decision. The European Union Data Act came into force in January 2024 and has applied since September 2025; it mandates portability between providers and, from January 2027, bans the exit fees that today chain you to your provider. And underneath it beats a deeper legal tension: the US CLOUD Act allows United States authorities to demand data from an American provider even if it is stored in Frankfurt, which is exactly the argument for why a European region of a hyperscaler does not give you sovereignty. With AWS, Microsoft and Google controlling around 70 % of the European cloud market, the conversation about sovereign cloud stopped being theoretical. I developed this already in &lt;a href="https://blog.lo0.es/en/posts/sovereign-on-premise-vs-hyperscalers-data/">sovereign on-premise versus hyperscalers&lt;/a>.&lt;/p>
&lt;h2 id="what-you-lose-when-you-leave-the-cloud-specifically">What you lose when you leave the cloud, specifically&lt;/h2>
&lt;p>Let us get to the core, ordered by what is going to hurt you most. And one thing before starting: none of these gaps is about compute. They are all about what the cloud put around the compute.&lt;/p>
&lt;p>&lt;strong>Hardware elasticity disappears.&lt;/strong> On-premise, the GPU you did not buy does not exist. The cloud bills you by the hour precisely because it takes on the risk of idle capacity: it lets you ask for a peak and hand it back. With your own iron, you buy the peak up front and pay for it whether it is in use or not, so your profitability depends on high sustained utilisation. Below a certain usage threshold, the cloud beats you again. This is the irreducible gap, the one no tool fills, and if you repatriate a workload with extreme peaks you are making the wrong decision.&lt;/p>
&lt;p>&lt;strong>Managed services become your operations.&lt;/strong> Every box you took for granted (the database, the queue, the object storage, the load balancer, DNS, the secrets manager) stops being a checkbox you tick and becomes a system you install, update and watch yourself. The 37signals case teaches it well: getting out of S3 object storage was the last and hardest part, with petabytes of data and a contract they dragged along for years. Your managed Postgres turns into operating CloudNativePG; your S3 turns into operating MinIO; and so on with every service.&lt;/p>
&lt;p>&lt;strong>You have to build the provisioning control plane yourself.&lt;/strong> AWS gives you a unified API where you ask for a resource with fine-grained permissions and it appears. On-premise that does not come for free: you have to build the control plane that translates &amp;ldquo;I want a database&amp;rdquo; into real resources. It is exactly the gap that &lt;a href="https://blog.lo0.es/en/posts/crossplane-control-plane-private-cloud-api/">Crossplane&lt;/a> fills, and that is why it has its own article.&lt;/p>
&lt;p>&lt;strong>You replace the managed network piece by piece.&lt;/strong> The VPC, the security groups, NAT, the load balancer: every network abstraction in the cloud has its on-premise equivalent (Cilium for network policies on eBPF, MetalLB for the load balancer without ELB, Gateway API for L7 ingress), but they are pieces you assemble, not a service you switch on. A good part of this we already saw in the networking vertical with &lt;a href="https://blog.lo0.es/en/posts/network-numa-cilium-ebpf-dranet-fourth-leg-pinning/">Cilium and eBPF&lt;/a>.&lt;/p>
&lt;p>&lt;strong>Billing stops existing as such.&lt;/strong> In the cloud the cost reaches you broken down by service and by tag; you have a Cost Explorer that answers &amp;ldquo;how much does this team cost me&amp;rdquo;. On-premise there is no natural bill: there is hardware depreciation, an electricity bill and some payroll, and splitting that per workload is a model you have to build. OpenCost helps you with the split per workload inside the cluster, but the total physical cost (depreciation plus energy plus staff) you model separately, as we saw in &lt;a href="https://blog.lo0.es/en/posts/opencost-gpu-cost-allocation-kubernetes/">OpenCost and cost allocation&lt;/a>.&lt;/p>
&lt;p>&lt;strong>You design multi-zone availability yourself.&lt;/strong> The three availability zones the cloud gives you for free turn into several sites, several racks and several utility feeds that you have to plan. 37signals solved it with two datacenters and replication between them. It is neither free nor automatic.&lt;/p>
&lt;p>&lt;strong>And above all, the on-call is yours.&lt;/strong> The cloud was not selling you only compute: it was selling you operations included. When something falls over at three in the morning, in the cloud there is an on-call team at the provider; with open source, that team is you. This is the cost that savings spreadsheets almost never include, and it is the one that decides whether your repatriation was a good idea or a hidden bill.&lt;/p>
&lt;h2 id="the-map-of-projects-that-fill-each-gap">The map of projects that fill each gap&lt;/h2>
&lt;p>With the gaps ordered, the catalogue of substitutes reads itself. I group it by layer, from the lowest to the closest to the developer.&lt;/p>
&lt;p>In the &lt;strong>infrastructure substrate&lt;/strong>, what replicates EC2 virtual machines, virtual networking and disks, you have OpenStack as the classic standard for a complete private cloud, SUSE&amp;rsquo;s Harvester as bare-metal hyperconvergence on KubeVirt managed from Kubernetes, and emerging projects such as Spinifex that rebuild an AWS-compatible API on your own iron. It is the heaviest layer and the one I touch least in this blog, because I assume your cluster already exists.&lt;/p>
&lt;p>In the &lt;strong>provisioning control plane&lt;/strong>, what replicates the AWS IAM and resource API, there is Crossplane, graduated in the CNCF in November 2025, which brings the Kubernetes declarative API model to infrastructure. Alongside it, Cluster API for declarative cluster provisioning. And so you can see how far this reaches in our own field, the Crossplane team itself published Modelplane in mid-2026, an inference control plane built on compositions that serves models with vLLM. This layer is developed by the &lt;a href="https://blog.lo0.es/en/posts/crossplane-control-plane-private-cloud-api/">Crossplane article&lt;/a>.&lt;/p>
&lt;p>In the &lt;strong>developer self-service experience&lt;/strong>, what replicates the AWS console and CLI, you have three different approaches you should not confuse. Backstage is the web portal, the catalogue and the templates, and it already has &lt;a href="https://blog.lo0.es/en/posts/backstage-self-service-portal-llm-platform/">its own article&lt;/a>. KubeVela brings self-service to the application model with a friendly CLI. Score defines a workload specification that is portable between environments. KubeVela and Score share the &lt;a href="https://blog.lo0.es/en/posts/kubevela-score-platform-cli-without-teaching-kubernetes/">third article&lt;/a> because they cover the same layer from angles that complement each other.&lt;/p>
&lt;p>In &lt;strong>on-premise managed services&lt;/strong>, CloudNativePG operates Postgres for you with high availability and backups to object storage, MinIO gives you S3-compatible storage, and OpenCost covers that cost allocation you lost with Cost Explorer.&lt;/p>
&lt;p>The way to read this map is that none of these pieces is surplus if you want the cloud experience: they are the boxes the cloud ticked for you and that you now tick one by one.&lt;/p>
&lt;h2 id="the-gap-you-will-not-close">The gap you will not close&lt;/h2>
&lt;p>I will tell you plainly, because it is the part the &amp;ldquo;leave the cloud&amp;rdquo; brochures skip. No combination of open source projects reproduces 100 % of the public cloud for you, and not for lack of maturity, but by design.&lt;/p>
&lt;p>What you will not replicate is, first, instant hardware elasticity: you still buy the peaks up front. Second, the depth and breadth of the managed services catalogue, hundreds of services with a service level agreement and an on-call team behind them, which no internal team matches. Third, the global multi-region network the cloud gives you almost for free. And fourth, that model of transferred operational responsibility: with open source, operations come back home.&lt;/p>
&lt;p>The correct reading is not that repatriating is a bad idea, but that you swap a predictable operating expense and a delegated responsibility for a cheaper capital investment and a responsibility of your own. For sustained base load it works out. For everything else, think about it.&lt;/p>
&lt;h2 id="when-not-to-repatriate">When NOT to repatriate&lt;/h2>
&lt;p>This section has to be here, because repatriation badly applied is expensive. There are three clear signs that the cloud is still your right answer.&lt;/p>
&lt;p>The first is a workload with extreme peaks or very variable traffic. Most inference deployments operate between 40 and 65 % GPU utilisation, and below roughly 70 % sustained usage the cloud beats you on total cost. If your workload has long troughs, you are buying iron so it can sleep.&lt;/p>
&lt;p>The second is uncertainty or the start of a project. The break-even point in favour of buying only applies to you when utilisation is consistently high and, above all, measured and not projected. Buying GPUs against an optimistic forecast is the fastest way to end up with a warehouse of idle silicon. Sizing it properly is worth a whole article: &lt;a href="https://blog.lo0.es/en/posts/slo-to-number-of-gpus-sizing-justifying-inference-hardware/">sizing and justifying the GPU investment&lt;/a>.&lt;/p>
&lt;p>The third is the lack of an operations team. The total cost of ownership on-premise includes between half and one full-time engineer per GPU server. Without that team, your saving is illusory, because the on-call the cloud included is now covered by nobody. a16z itself frames its thesis as a hybrid approach, not as &amp;ldquo;leave the cloud&amp;rdquo; at all.&lt;/p>
&lt;h2 id="the-numbers-to-ground-it">The numbers, to ground it&lt;/h2>
&lt;p>So as not to leave you with the discussion in the abstract, here are the orders of magnitude, triangulating two sources with opposite biases, a cloud provider and a neutral FinOps tool. An H100 in the cloud runs you between 2.90 and almost 7 dollars per GPU-hour depending on provider; bought, an H100 card is around 31,000 dollars and an eight-way system between 250,000 and 320,000. At full utilisation, a rented H100 passes its purchase price in less than a year, and an eight-way system with second-hand hardware can pay for itself in about seven months. The three-year total cost of an eight-H100 system, counting staff, colocation, energy and cooling, is estimated at between 700,000 and 950,000 dollars, and the threshold where on-premise beats the hyperscalers is around 80 % sustained utilisation.&lt;/p>
&lt;p>The two sources disagree on the exact number, as you would expect, but they agree on the deciding factor: sustained utilisation, measured and not projected. The full working of this calculation is in &lt;a href="https://blog.lo0.es/en/posts/full-tco-on-premise-gpu-cluster-capex-gpu-hour-break-even/">the TCO of an on-premise GPU cluster&lt;/a>. Here the conclusion is enough for you: for continuous base load the numbers work out, and that is exactly the profile of an inference factory.&lt;/p>
&lt;h2 id="for-your-sovereign-inference-factory">For your sovereign inference factory&lt;/h2>
&lt;p>Everything above arranges itself into a practical decision. If you operate an LLM inference platform on your own iron, you are not deciding whether to repatriate (you already took that decision when you built the cluster), but how to rebuild the cloud experience your teams miss.&lt;/p>
&lt;p>The sensible sequence starts with the substrate, which you probably already have in the form of RKE2 and storage. It goes on to the provisioning control plane, where Crossplane turns &amp;ldquo;open a ticket and wait&amp;rdquo; into a declarative API. It continues with the developer experience, where you choose between the Backstage portal, the KubeVela application model or the portable Score specification, depending on whether your people prefer a web or a CLI. And do not forget the on-premise managed services or the cost allocation, because without a bill your platform loses the discipline the cloud imposed by default.&lt;/p>
&lt;p>The next two articles go down into the two layers least covered in this blog: &lt;a href="https://blog.lo0.es/en/posts/crossplane-control-plane-private-cloud-api/">Crossplane&lt;/a> for the infrastructure control plane, and &lt;a href="https://blog.lo0.es/en/posts/kubevela-score-platform-cli-without-teaching-kubernetes/">KubeVela with Score&lt;/a> for CLI self-service centred on the application. With them, the map of this layer is covered, and your own house starts to look like the hotel you left, with the difference that the data stays inside.&lt;/p>
&lt;h2 id="see-also">See also&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://blog.lo0.es/en/posts/sovereign-on-premise-vs-hyperscalers-data/">Sovereign on-premise versus hyperscalers, with data&lt;/a> — the business and sovereignty case, in detail.&lt;/li>
&lt;li>&lt;a href="https://blog.lo0.es/en/posts/full-tco-on-premise-gpu-cluster-capex-gpu-hour-break-even/">The TCO of an on-premise GPU cluster&lt;/a> — the full break-even calculation.&lt;/li>
&lt;li>&lt;a href="https://blog.lo0.es/en/posts/backstage-self-service-portal-llm-platform/">Backstage as a self-service portal&lt;/a> — the portal layer, the third route to self-service.&lt;/li>
&lt;li>&lt;a href="https://blog.lo0.es/en/posts/five-maturity-levels-platform-under-llm/">The five maturity levels of the platform&lt;/a> — at what point each of these pieces starts to pay off for you.&lt;/li>
&lt;li>&lt;a href="https://blog.lo0.es/en/posts/blog-map-from-utility-feed-to-token-served/">The map of the blog by layers&lt;/a> — where all of this fits in the complete stack.&lt;/li>
&lt;/ul>
&lt;h2 id="sources">Sources&lt;/h2>
&lt;ul>
&lt;li>Andreessen Horowitz (S. Wang, M. Casado), &lt;em>The Cost of Cloud, a Trillion Dollar Paradox&lt;/em> — &lt;a href="https://a16z.com/the-cost-of-cloud-a-trillion-dollar-paradox/">https://a16z.com/the-cost-of-cloud-a-trillion-dollar-paradox/&lt;/a>&lt;/li>
&lt;li>Data Center Dynamics, &lt;em>37signals claims it saved almost 2M USD last year from cloud repatriation&lt;/em> — &lt;a href="https://www.datacenterdynamics.com/en/news/37signals-claims-it-saved-almost-2m-last-year-from-cloud-repatriation/">https://www.datacenterdynamics.com/en/news/37signals-claims-it-saved-almost-2m-last-year-from-cloud-repatriation/&lt;/a>&lt;/li>
&lt;li>The Register, &lt;em>Developer pockets 2M USD in savings from going cloud-free&lt;/em> — &lt;a href="https://www.theregister.com/2024/10/21/37signals_aws_savings/">https://www.theregister.com/2024/10/21/37signals_aws_savings/&lt;/a>&lt;/li>
&lt;li>Barclays, &lt;em>Technology: 1H24 CIO Survey&lt;/em> (PDF) — &lt;a href="https://8198920.fs1.hubspotusercontent-na1.net/hubfs/8198920/Barclays_Cio_Survey_2024-1.pdf">https://8198920.fs1.hubspotusercontent-na1.net/hubfs/8198920/Barclays_Cio_Survey_2024-1.pdf&lt;/a>&lt;/li>
&lt;li>Channelnomics, &lt;em>Breaking Down the 83% Public Cloud Repatriation Number&lt;/em> — &lt;a href="https://channelnomics.com/breaking-down-the-83-public-cloud-repatriation-number/">https://channelnomics.com/breaking-down-the-83-public-cloud-repatriation-number/&lt;/a>&lt;/li>
&lt;li>The New Stack, &lt;em>Updated Stats on Cloud Sustainability, Repatriation and Cost Optimization&lt;/em> (Flexera 2025) — &lt;a href="https://thenewstack.io/updated-stats-on-cloud-sustainability-repatriation-and-cost-optimization/">https://thenewstack.io/updated-stats-on-cloud-sustainability-repatriation-and-cost-optimization/&lt;/a>&lt;/li>
&lt;li>Comisión Europea, &lt;em>Data Act | Shaping Europe&amp;rsquo;s digital future&lt;/em> — &lt;a href="https://digital-strategy.ec.europa.eu/en/policies/data-act">https://digital-strategy.ec.europa.eu/en/policies/data-act&lt;/a>&lt;/li>
&lt;li>EU Data Act, &lt;em>Article 29 — Gradual withdrawal of switching charges&lt;/em> — &lt;a href="https://www.eu-data-act.com/Data_Act_Article_29.html">https://www.eu-data-act.com/Data_Act_Article_29.html&lt;/a>&lt;/li>
&lt;li>Kiteworks, &lt;em>How the EU Data Act and GDPR Conflict with U.S. CLOUD Act&lt;/em> — &lt;a href="https://www.kiteworks.com/gdpr-compliance/eu-data-act-gdpr-cloud-conflict/">https://www.kiteworks.com/gdpr-compliance/eu-data-act-gdpr-cloud-conflict/&lt;/a>&lt;/li>
&lt;li>Computerworld, &lt;em>EU takes first steps to reduce reliance on US hyperscalers&lt;/em> — &lt;a href="https://www.computerworld.com/article/4181816/eu-takes-first-steps-to-reduce-reliance-on-us-hyperscalers.html">https://www.computerworld.com/article/4181816/eu-takes-first-steps-to-reduce-reliance-on-us-hyperscalers.html&lt;/a>&lt;/li>
&lt;li>CNCF, &lt;em>Announces Graduation of Crossplane&lt;/em> (6-nov-2025) — &lt;a href="https://www.cncf.io/announcements/2025/11/06/cloud-native-computing-foundation-announces-graduation-of-crossplane/">https://www.cncf.io/announcements/2025/11/06/cloud-native-computing-foundation-announces-graduation-of-crossplane/&lt;/a>&lt;/li>
&lt;li>CNCF, &lt;em>Score accepted as a CNCF Sandbox Project&lt;/em> — &lt;a href="https://www.cncf.io/blog/2024/08/08/score-accepted-as-a-cncf-sandbox-project/">https://www.cncf.io/blog/2024/08/08/score-accepted-as-a-cncf-sandbox-project/&lt;/a>&lt;/li>
&lt;li>Harvester HCI (SUSE) — &lt;a href="https://harvesterhci.io/">https://harvesterhci.io/&lt;/a>&lt;/li>
&lt;li>CloudNativePG — &lt;a href="https://cloudnative-pg.io/">https://cloudnative-pg.io/&lt;/a>&lt;/li>
&lt;li>Crossplane Blog, &lt;em>Building Modelplane on Crossplane&lt;/em> — &lt;a href="https://blog.crossplane.io/building-modelplane/">https://blog.crossplane.io/building-modelplane/&lt;/a> · &lt;a href="https://modelplane.ai">https://modelplane.ai&lt;/a>&lt;/li>
&lt;li>Spheron, &lt;em>LLM Inference On-Premise vs GPU Cloud: 2026 Cost and Break-Even Analysis&lt;/em> — &lt;a href="https://www.spheron.network/blog/llm-inference-on-premise-vs-cloud/">https://www.spheron.network/blog/llm-inference-on-premise-vs-cloud/&lt;/a>&lt;/li>
&lt;li>CloudZero, &lt;em>H100 GPU Cost in 2026: Buy, Rent, and Cloud Pricing Compared&lt;/em> — &lt;a href="https://www.cloudzero.com/blog/h100-gpu-cost/">https://www.cloudzero.com/blog/h100-gpu-cost/&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Backstage as a self-service portal: giving your teams the LLM platform without giving them the cluster</title><link>https://blog.lo0.es/en/posts/backstage-self-service-portal-llm-platform/</link><pubDate>Mon, 31 Aug 2026 09:00:00 +0200</pubDate><guid>https://blog.lo0.es/en/posts/backstage-self-service-portal-llm-platform/</guid><description>&lt;blockquote>
&lt;p>This article opens the platform and self-service layer: the one that decides how you hand everything underneath to the teams that are going to use it. The three articles in this batch are Backstage (the portal), &lt;a href="https://blog.lo0.es/en/posts/kubeflow-pieces-worth-it-on-premise-llm-platform/">Kubeflow&lt;/a> (the ML toolbox) and &lt;a href="https://blog.lo0.es/en/posts/knative-scale-to-zero-llm-inference/">Knative&lt;/a> (switching the GPU off when nobody is using it).&lt;/p>
&lt;/blockquote>
&lt;h2 id="tldr">TL;DR&lt;/h2>
&lt;p>Backstage solves a real problem of a platform that has grown: nobody knows what is there, who maintains it, or how to ask for a new one without opening a ticket. Its answer is three pieces, a software &lt;strong>catalogue&lt;/strong> that models every component and its relations, &lt;strong>templates&lt;/strong> that create new resources through a form instead of through copy and paste, and &lt;strong>TechDocs&lt;/strong> to keep documentation next to the code. On top of those three sits the concept that holds up everything else, the &lt;strong>golden path&lt;/strong>: the supported route made also the easiest one, so that people take it because it is paved, not because they are forced onto it.&lt;/p>
&lt;p>The price is high and it should be said plainly. Backstage is not a product you install, it is a Node and React application that you compile and maintain as your own code, at a declared cost of two to three full-time engineers, and with upgrades as its biggest pain point. As of August 2026 it is still a CNCF &lt;strong>incubating&lt;/strong> project, not graduated, and it has no native entity type for models, datasets or inference endpoints: that gets modelled by hand, or you wait for a proposal that is still open. The decision is not about features, it is about scale: below a certain organisation size, a portal costs more than it saves.&lt;/p>
&lt;h2 id="the-analogy-the-industrial-estate-directory">The analogy: the industrial estate directory&lt;/h2>
&lt;p>A single unit needs no sign. You know what is inside because you built it. An estate with two hundred units, on the other hand, needs a directory at the entrance: which company sits on each plot, what it does, who is responsible, and an office where you can request a new plot with the utility connections already in place instead of negotiating each one separately.&lt;/p>
&lt;p>An LLM platform starts out as a single unit. One cluster, one model, the team that built it. Six months later it is an industrial estate: fifteen models served, three RAG pipelines, LoRA adapters everywhere, and a question that comes back in every meeting, who maintains this? Backstage is the directory for that estate, with two additions an ordinary directory does not have: the office that hands over turnkey plots, and the archive of blueprints for each unit. The catalogue is the directory, the templates are the office, TechDocs is the archive.&lt;/p>
&lt;p>The analogy also warns about the cost. The directory does not maintain itself. Somebody has to update it when a company moves, and a directory with half the plots mislabelled is worse than no directory at all, because people stop trusting it. In Backstage that failure has a name, &lt;em>catalog rot&lt;/em>, and it is the leading cause of a portal being abandoned.&lt;/p>
&lt;h2 id="what-backstage-is-and-what-state-it-reaches-2026-in">What Backstage is and what state it reaches 2026 in&lt;/h2>
&lt;p>Backstage was born inside Spotify and donated to the CNCF, which accepted it in September 2020 and moved it to incubating level in March 2022. That is where it still is: as of August 2026 it is &lt;strong>incubating, not graduated&lt;/strong>, a detail that matters when someone sells it as a de facto standard. It is by far the most widely adopted developer portal (the official 2025 review declares more than 3,400 organisations using it, 31,000 GitHub stars and more than 250 plugins), but adoption is not governance maturity, and a large share of those plugins is maintained by the community, not by the core.&lt;/p>
&lt;p>The architecture has kept changing pieces under the feet of whoever operates it. The &lt;strong>New Backend System&lt;/strong> stabilised in 2024 and is now the standard. The &lt;strong>New Frontend System&lt;/strong> became the default mode for new applications in version 1.49, of March 2026. The cadence is one minor release a month, and that rhythm is precisely the origin of the biggest operational problem, which we will see further down.&lt;/p>
&lt;h2 id="the-three-pieces">The three pieces&lt;/h2>
&lt;h3 id="the-software-catalogue">The software catalogue&lt;/h3>
&lt;p>The heart of Backstage is an entity catalogue. Every piece of the platform is described in a &lt;code>catalog-info.yaml&lt;/code> file that lives next to its code, and Backstage discovers it by crawling the repository. The entity types are fixed: &lt;strong>Component&lt;/strong> (something that runs or compiles), &lt;strong>API&lt;/strong> (a contract that a component exposes), &lt;strong>Resource&lt;/strong> (infrastructure that a component needs), &lt;strong>System&lt;/strong> (a set of components that form a unit), &lt;strong>Domain&lt;/strong> (a set of systems), plus &lt;strong>Group&lt;/strong> and &lt;strong>User&lt;/strong> for ownership.&lt;/p>
&lt;p>The power is in the &lt;strong>relations&lt;/strong> rather than in the entities, which Backstage computes and navigates: &lt;code>ownedBy&lt;/code> connects each thing to its team, &lt;code>providesApi&lt;/code> and &lt;code>consumesApi&lt;/code> draw who depends on whom, &lt;code>partOf&lt;/code> groups components into systems, &lt;code>dependsOn&lt;/code> traces the dependency graph. With that, the meeting question (who maintains this, and what breaks if we touch it?) stops being answered from memory and starts being answered by query.&lt;/p>
&lt;p>There is a design decision that conditions everything that follows: &lt;strong>Backstage advises against creating new entity types&lt;/strong>. Plugins are compiled expecting the usual types, and an invented type leaves them blind. The supported route is to reuse an existing type and distinguish it with the &lt;code>spec.type&lt;/code> field (for example a &lt;code>Resource&lt;/code> with &lt;code>type: llm-model&lt;/code>), adding whatever custom fields you need to the &lt;code>spec&lt;/code>.&lt;/p>
&lt;h3 id="the-templates">The templates&lt;/h3>
&lt;p>The second piece is the &lt;strong>Scaffolder&lt;/strong>, the template engine. A template is an entity of type &lt;code>Template&lt;/code> with three parts: the &lt;code>parameters&lt;/code> requested through a form, the &lt;code>steps&lt;/code> that get executed, and the &lt;code>actions&lt;/code> that do the real work (create a repository, write the &lt;code>catalog-info.yaml&lt;/code>, register the component, trigger the GitOps pipeline). The developer goes to &lt;code>/create&lt;/code>, picks a template, fills in the form, and in a single operation has the resource created, catalogued and deploying.&lt;/p>
&lt;p>This is what turns a directory into an office. Without templates, Backstage only lists what already exists. With templates, it is the door through which new things are created, and that door is where the golden path materialises.&lt;/p>
&lt;h3 id="techdocs">TechDocs&lt;/h3>
&lt;p>The third piece is &lt;strong>TechDocs&lt;/strong>, documentation as code. Documents are written in Markdown next to the code, generated with MkDocs in the CI pipeline, and served inside the portal itself, linked from each component&amp;rsquo;s page. The advantage is in the incentives: documentation that lives far from the code rots; documentation that lives next to it and gets reviewed in the same &lt;em>pull request&lt;/em> has some chance of staying true.&lt;/p>
&lt;h2 id="the-golden-path-which-is-what-all-of-this-is-about">The golden path, which is what all of this is about&lt;/h2>
&lt;p>Spotify coined the term &lt;em>golden path&lt;/em> for the recommended and supported way to build something. It has two halves: the blessed tooling, visible in the portal, and a step-by-step tutorial in the documentation. The idea, in the formulation that platform reports keep repeating, is that nobody forces you to use the paved road; people take it because it is paved.&lt;/p>
&lt;p>The data supports the golden path being the deciding variable. The 2026 &lt;em>State of Platform Engineering&lt;/em> report, covering 518 professionals, puts voluntary adoption above 80 % where there is a well-designed golden path and below 20 % where there is not, and estimates that around 70 % of platform initiatives fail to reach significant adoption without one. It is a figure that reorders priorities: a portal without golden paths is a pretty catalogue nobody uses.&lt;/p>
&lt;p>In Backstage, a golden path is implemented as a Scaffolder template. For an LLM platform, a typical golden path would be &amp;ldquo;serve a new model&amp;rdquo;: the form asks for the model, the GPU size, the owning team and the SLO; the template creates the repository with the &lt;code>InferenceService&lt;/code>, writes the &lt;code>catalog-info.yaml&lt;/code>, registers it under the right system, and opens the &lt;em>pull request&lt;/em> against the GitOps repository you already have with &lt;a href="https://blog.lo0.es/en/posts/gitops-inference-stack-flux/">Flux&lt;/a>. What used to be half a day of copying a colleague&amp;rsquo;s YAML and guessing the values becomes a two-minute form with the correct defaults.&lt;/p>
&lt;h2 id="authentication-and-permissions">Authentication and permissions&lt;/h2>
&lt;p>For a sovereign platform the identity piece matters as much as the catalogue. Backstage ships connectors out of the box for GitHub, GitLab, Google, Microsoft, Okta, generic OIDC and SAML, among others. For on-premise the relevant one is &lt;strong>Keycloak&lt;/strong>, which fits in like any other OIDC provider, with one nuance worth keeping in mind: the Keycloak connector is maintained by the community, not by the core, so its maintenance and its tightness fall on a third-party plugin. Once you have set up Keycloak as we saw in &lt;a href="https://blog.lo0.es/en/posts/mcp-grows-up-authentication-keycloak/">the article on authenticating MCP&lt;/a>, the portal hooks into the same identity issuer.&lt;/p>
&lt;p>The permissions framework appears today as stable in the documentation and supports RBAC, ABAC and custom logic. The small print: by default the endpoints are not protected, and the permission policy is written by the integrator. The most widely used RBAC solution with a graphical interface comes with the Red Hat distribution, not with the core. In other words, serious access control means work on top of what comes in the box.&lt;/p>
&lt;h2 id="the-real-cost-no-frills">The real cost, no frills&lt;/h2>
&lt;p>This is where an honest article parts ways with the brochure. &lt;strong>Backstage is not an installable product, it is a framework that you compile and maintain as your own code.&lt;/strong> That has measurable consequences.&lt;/p>
&lt;p>The most quoted analysis, from the managed Backstage vendor Roadie, puts the effort at around three full-time engineers in the first year and two from the second onwards, with a time to production of six to twelve months in self-managed mode. The figure comes from a vendor with a commercial interest in you buying its managed version, so it should be taken as an order of magnitude and not as a neutral data point, but the direction is confirmed by independent sources: ongoing maintenance takes up around a fifth of engineering time, and &lt;strong>upgrades are the biggest pain point&lt;/strong>, cited by more than half of those who adopt it. With one minor release a month and architectural pieces shifting under your feet, keeping up to date is a permanent job.&lt;/p>
&lt;p>The other cost is about adoption, not engineering. A widely repeated critical analysis points out that many organisations settle at around 10 % internal usage, against the 99 % voluntary usage Spotify achieved at home, and attributes it to three recurring failures: the &lt;em>catalog rot&lt;/em> we already mentioned, the lack of a product owner treating the portal as a product, and the illusion that Backstage can be adopted over what already exists when in practice it only standardises new things well. The sentence that sums up the disenchantment is that Backstage is a free portal in the same way you would have a free car if somebody tipped all the parts of a Chevrolet onto your desk.&lt;/p>
&lt;h2 id="applied-to-an-llm-platform-what-is-there-and-what-is-not">Applied to an LLM platform: what is there and what is not&lt;/h2>
&lt;p>Here an expectation needs correcting. In 2026 &lt;strong>Backstage has no native entities for models, datasets or inference endpoints&lt;/strong>. There are three things and none of them is what you would hope for:&lt;/p>
&lt;p>An &lt;strong>open proposal&lt;/strong> (RFC 33060, from February 2026) to model model servers as entities of type &lt;code>API&lt;/code> with &lt;code>type: ai-model-server&lt;/code>. It is under discussion, not implemented.&lt;/p>
&lt;p>An official module that introduces an &lt;code>AiResource&lt;/code> type, which sounds like what we are after but &lt;strong>is for something else&lt;/strong>: governing the &lt;em>skills&lt;/em> and rules of coding assistants, not registering inference models.&lt;/p>
&lt;p>And one real pattern, the MLOps templates that AWS documents on top of SageMaker, where Backstage acts as the Scaffolder that creates environments and pipelines, not as the model registry. It is a cloud case, not on-premise, and it uses Backstage for its template half, not for its model catalogue.&lt;/p>
&lt;p>The practical conclusion for your own stack is twofold. First, what Backstage brings to an LLM platform today is above all the template half: the &amp;ldquo;create a new inference service&amp;rdquo; golden path wired into your GitOps. Second, if you want to catalogue models, today that is done by hand with custom &lt;code>spec.type&lt;/code> values, treating the model as a &lt;code>Resource&lt;/code> and its endpoint as an &lt;code>API&lt;/code>, until the proposal matures. Registering the model&amp;rsquo;s bytes remains the job of the &lt;a href="https://blog.lo0.es/en/posts/model-chain-of-trust-where-the-bytes-live-registry-oci-artefacts/">OCI registry&lt;/a>, not of the catalogue.&lt;/p>
&lt;p>The infrastructure plugins that are worth it in this stack do exist and are reasonably alive: the Kubernetes one (core), the Flux one for seeing GitOps state from the portal, the Grafana one for embedding dashboards in a component&amp;rsquo;s page, and the ArgoCD one for anyone using Argo instead of Flux.&lt;/p>
&lt;h2 id="alternatives-when-not-to-set-up-backstage">Alternatives: when not to set up Backstage&lt;/h2>
&lt;p>The honest decision is not which portal, but whether a portal. The SaaS-type alternatives (Port, Cortex, OpsLevel, Humanitec) win on time to first value, measured in days instead of months, and on not having to maintain the framework, in exchange for a per-user fee that scales badly and for giving up pure on-premise. Roadie offers managed Backstage, which removes the framework maintenance while keeping its extensibility, in exchange for a per-developer fee and for taking your catalogue outside.&lt;/p>
&lt;p>For a sovereign platform, where on-premise and data ownership are requirements, pure SaaS is usually ruled out by design, which leaves the real choice between self-managed Backstage and no portal at all. And there the criterion is size. Below a handful of teams, a well-maintained &lt;code>README&lt;/code> and a tidy GitOps repository do the same job as the catalogue, without the cost of two engineers. The portal starts paying off when the cognitive load of knowing what is there and how to ask for it exceeds the cost of maintaining the tool that answers it.&lt;/p>
&lt;h2 id="operational-traps-and-honest-scepticism">Operational traps and honest scepticism&lt;/h2>
&lt;p>&lt;strong>The catalogue rots if it is not automated.&lt;/strong> A &lt;code>catalog-info.yaml&lt;/code> written by hand and never updated is lying within a few weeks. The only defence is generating and validating those files in the pipeline, not trusting people to maintain them.&lt;/p>
&lt;p>&lt;strong>Without a product owner, the portal dies.&lt;/strong> Backstage is not infrastructure you install and forget, it is an internal product with users you have to understand. Without somebody treating adoption as an objective, it ends up as a catalogue nobody looks at.&lt;/p>
&lt;p>&lt;strong>Upgrades are a recurring tax.&lt;/strong> One release a month and architectural pieces mid-migration mean the portal is never finished. That maintenance has to be budgeted from the start, not discovered in the second quarter.&lt;/p>
&lt;p>&lt;strong>Backstage deploys nothing.&lt;/strong> It is a portal, not an engine. Behind each template there has to be your GitOps, your operators and your cluster doing the real work. If that base is not solid, the portal just puts a pretty façade over chaos.&lt;/p>
&lt;p>&lt;strong>The data model for AI does not exist yet.&lt;/strong> Anyone setting up Backstage expecting a ready-to-use model catalogue is going to find themselves modelling by hand. It is doable, but it is work, and you should know that beforehand.&lt;/p>
&lt;h2 id="for-an-inference-factory">For an inference factory&lt;/h2>
&lt;p>Backstage fits at the high maturity level of a platform, not at the start. In the &lt;a href="https://blog.lo0.es/en/posts/five-maturity-levels-platform-under-llm/">five maturity levels&lt;/a> it is a tool of the level where the platform already serves several teams and the bottleneck has stopped being technical and become one of coordination. Three concrete decisions follow from all of the above.&lt;/p>
&lt;p>The first is not setting it up too early. If the platform is used by two teams who know each other, the portal is cost without return. The trigger is cognitive load, not the calendar.&lt;/p>
&lt;p>The second is starting with the templates, not with the catalogue. The value you notice from day one is the golden path that turns half a day of copying YAML into a two-minute form. The complete catalogue, with all its relations, is a bigger job that can come later.&lt;/p>
&lt;p>The third is budgeting maintenance as a function, not as a project. Two part-time engineers indefinitely, an owner watching adoption, and automatic generation of the catalogue entries. Without that, the portal degrades until somebody asks why nobody uses it, and the answer is that it stopped being true.&lt;/p>
&lt;p>The portal is the face your platform shows to whoever uses it. It is worth it when there is enough platform behind it that showing it tidily saves more than maintaining the shop window costs. Before that, it is the shop window of a shop that has no stock yet. The other two articles in this batch go into that stock: the ML toolbox with &lt;a href="https://blog.lo0.es/en/posts/kubeflow-pieces-worth-it-on-premise-llm-platform/">Kubeflow&lt;/a> and the savings of switching the GPU off with &lt;a href="https://blog.lo0.es/en/posts/knative-scale-to-zero-llm-inference/">Knative&lt;/a>.&lt;/p>
&lt;h2 id="see-also">See also&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://blog.lo0.es/en/posts/gitops-inference-stack-flux/">GitOps for the inference stack with Flux&lt;/a> — the engine behind every portal template.&lt;/li>
&lt;li>&lt;a href="https://blog.lo0.es/en/posts/gpu-cluster-as-multi-tenant-platform/">The GPU cluster as a multi-tenant platform&lt;/a> — the base the portal presents to the teams.&lt;/li>
&lt;li>&lt;a href="https://blog.lo0.es/en/posts/five-maturity-levels-platform-under-llm/">Five maturity levels of the platform&lt;/a> — at which level a portal starts to pay off.&lt;/li>
&lt;li>&lt;a href="https://blog.lo0.es/en/posts/model-chain-of-trust-where-the-bytes-live-registry-oci-artefacts/">Model registry and distribution with OCI and ORAS&lt;/a> — where the bytes the catalogue only references live.&lt;/li>
&lt;/ul>
&lt;h2 id="sources">Sources&lt;/h2>
&lt;ul>
&lt;li>CNCF, &lt;em>Backstage (project page)&lt;/em> — &lt;a href="https://www.cncf.io/projects/backstage/">https://www.cncf.io/projects/backstage/&lt;/a>&lt;/li>
&lt;li>Backstage, &lt;em>Backstage Wrapped 2025&lt;/em> — &lt;a href="https://backstage.io/blog/2025/12/30/backstage-wrapped-2025/">https://backstage.io/blog/2025/12/30/backstage-wrapped-2025/&lt;/a>&lt;/li>
&lt;li>Backstage Docs, &lt;em>Software Catalog: descriptor format&lt;/em> — &lt;a href="https://backstage.io/docs/features/software-catalog/descriptor-format/">https://backstage.io/docs/features/software-catalog/descriptor-format/&lt;/a>&lt;/li>
&lt;li>Backstage Docs, &lt;em>Well-known relations&lt;/em> — &lt;a href="https://backstage.io/docs/features/software-catalog/well-known-relations/">https://backstage.io/docs/features/software-catalog/well-known-relations/&lt;/a>&lt;/li>
&lt;li>Backstage Docs, &lt;em>Extending the model&lt;/em> — &lt;a href="https://backstage.io/docs/features/software-catalog/extending-the-model/">https://backstage.io/docs/features/software-catalog/extending-the-model/&lt;/a>&lt;/li>
&lt;li>Backstage Docs, &lt;em>Software Templates&lt;/em> — &lt;a href="https://backstage.io/docs/features/software-templates/">https://backstage.io/docs/features/software-templates/&lt;/a>&lt;/li>
&lt;li>Backstage Docs, &lt;em>TechDocs&lt;/em> — &lt;a href="https://backstage.io/docs/features/techdocs/">https://backstage.io/docs/features/techdocs/&lt;/a>&lt;/li>
&lt;li>Backstage Docs, &lt;em>Authentication&lt;/em> — &lt;a href="https://backstage.io/docs/auth/">https://backstage.io/docs/auth/&lt;/a>&lt;/li>
&lt;li>Backstage Docs, &lt;em>Permissions overview&lt;/em> — &lt;a href="https://backstage.io/docs/permissions/overview/">https://backstage.io/docs/permissions/overview/&lt;/a>&lt;/li>
&lt;li>Backstage GitHub, &lt;em>RFC #33060: modeling AI model servers in the catalog&lt;/em> — &lt;a href="https://github.com/backstage/backstage/issues/33060">https://github.com/backstage/backstage/issues/33060&lt;/a>&lt;/li>
&lt;li>Roadie, &lt;em>Backstage: how much does it really cost?&lt;/em> — &lt;a href="https://roadie.io/blog/backstage-how-much-does-it-really-cost/">https://roadie.io/blog/backstage-how-much-does-it-really-cost/&lt;/a>&lt;/li>
&lt;li>Earthly, &lt;em>Backstage is at the peak of its hype&lt;/em> — &lt;a href="https://earthly.dev/blog/backstage-is-at-peak-hype/">https://earthly.dev/blog/backstage-is-at-peak-hype/&lt;/a>&lt;/li>
&lt;li>AWS Prescriptive Guidance, &lt;em>Accelerate MLOps with Backstage and SageMaker templates&lt;/em> — &lt;a href="https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/accelerate-mlops-with-backstage-and-sagemaker-templates.html">https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/accelerate-mlops-with-backstage-and-sagemaker-templates.html&lt;/a>&lt;/li>
&lt;li>Spotify Engineering, &lt;em>How we use golden paths to solve fragmentation&lt;/em> — &lt;a href="https://engineering.atspotify.com/2020/08/how-we-use-golden-paths-to-solve-fragmentation-in-our-software-ecosystem">https://engineering.atspotify.com/2020/08/how-we-use-golden-paths-to-solve-fragmentation-in-our-software-ecosystem&lt;/a>&lt;/li>
&lt;li>The New Stack, &lt;em>DORA 2024: AI and platform engineering fall short&lt;/em> — &lt;a href="https://thenewstack.io/dora-2024-ai-and-platform-engineering-fall-short/">https://thenewstack.io/dora-2024-ai-and-platform-engineering-fall-short/&lt;/a>&lt;/li>
&lt;li>bex.co, &lt;em>State of Platform Engineering Report Vol. 4: golden path&lt;/em> — &lt;a href="https://bex.co/blog/2026/08/06/platform-engineering-report-vol-4-golden-path">https://bex.co/blog/2026/08/06/platform-engineering-report-vol-4-golden-path&lt;/a>&lt;/li>
&lt;/ul></description></item></channel></rss>