<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Cloud Native Architecture – Public Sector</title><link>https://deploy-preview-35--cncfarchitecture.netlify.app/industries/public-sector/</link><description>Recent content in Public Sector on Cloud Native Architecture</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Thu, 11 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://deploy-preview-35--cncfarchitecture.netlify.app/industries/public-sector/index.xml" rel="self" type="application/rss+xml"/><item><title>Architectures: GitOps-Native Multi-Cluster Kubernetes Platform for EU Data Sovereignty</title><link>https://deploy-preview-35--cncfarchitecture.netlify.app/architectures/obmondo/</link><pubDate>Thu, 11 Jun 2026 00:00:00 +0000</pubDate><guid>https://deploy-preview-35--cncfarchitecture.netlify.app/architectures/obmondo/</guid><description>
&lt;h2 id="relevant-projects">Relevant Projects&lt;/h2>
&lt;div class="row row-cols-1 row-cols-md-3 mb-4">
&lt;div class="col mb-4">
&lt;div class="card h-100">
&lt;div class="card-header">
Kubernetes
&lt;/div>
&lt;div class="card-body">
&lt;p class="card-text">
&lt;p>&lt;a href="https://www.cncf.io/projects/kubernetes/">&lt;img src="https://raw.githubusercontent.com/cncf/artwork/main/projects/kubernetes/icon/color/kubernetes-icon-color.svg" alt="kubernetes logo">&lt;/a>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Using since:&lt;/strong> 2019&lt;/li>
&lt;li>&lt;strong>Current version:&lt;/strong> 1.33.x&lt;/li>
&lt;/ul>
&lt;p>The runtime substrate for all workloads. Cluster API manages the lifecycle of every cluster across Hetzner bare metal, AWS, and Azure declaratively from Git. No cloud console required.&lt;/p>
&lt;/p>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="col mb-4">
&lt;div class="card h-100">
&lt;div class="card-header">
Argo CD
&lt;/div>
&lt;div class="card-body">
&lt;p class="card-text">
&lt;p>&lt;a href="https://www.cncf.io/projects/argo/">&lt;img src="https://github.com/cncf/artwork/raw/main/projects/argo/horizontal/color/argo-horizontal-color.svg" alt="argo logo">&lt;/a>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Using since:&lt;/strong> 2021&lt;/li>
&lt;li>&lt;strong>Current version:&lt;/strong> v3.x&lt;/li>
&lt;/ul>
&lt;p>The reconciliation engine for the entire fleet. A fix committed once to the shared KubeAid chart library propagates to every cluster on the next ArgoCD sync no manual per-cluster patching.&lt;/p>
&lt;/p>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="col mb-4">
&lt;div class="card h-100">
&lt;div class="card-header">
Prometheus
&lt;/div>
&lt;div class="card-body">
&lt;p class="card-text">
&lt;p>&lt;a href="https://www.cncf.io/projects/prometheus/">&lt;img src="https://raw.githubusercontent.com/cncf/artwork/main/projects/prometheus/icon/color/prometheus-icon-color.svg" alt="prometheus logo">&lt;/a>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Using since:&lt;/strong> 2020&lt;/li>
&lt;li>&lt;strong>Current version:&lt;/strong> v3.x&lt;/li>
&lt;/ul>
&lt;p>Generated per-cluster from a single Jsonnet vars file using kube-prometheus. Custom alerting rules for TLS expiry forecasting, backup SLIs, database replication lag, and Kubernetes ListWatch failures compose with upstream rule libraries without YAML merge conflicts.&lt;/p>
&lt;/p>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="col mb-4">
&lt;div class="card h-100">
&lt;div class="card-header">
Cilium
&lt;/div>
&lt;div class="card-body">
&lt;p class="card-text">
&lt;p>&lt;a href="https://www.cncf.io/projects/cilium/">&lt;img src="https://raw.githubusercontent.com/cncf/artwork/main/projects/cilium/icon/color/cilium_icon-color.svg" alt="cilium logo">&lt;/a>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Using since:&lt;/strong> 2022&lt;/li>
&lt;li>&lt;strong>Current version:&lt;/strong> v1.17.x&lt;/li>
&lt;/ul>
&lt;p>Network policies are embedded alongside every workload manifest in KubeAid. FQDN egress rules for every external API dependency ship with the chart. Operators do not write network policies — KubeAid writes them once and applies them to every cluster.&lt;/p>
&lt;/p>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="col mb-4">
&lt;div class="card h-100">
&lt;div class="card-header">
cert-manager
&lt;/div>
&lt;div class="card-body">
&lt;p class="card-text">
&lt;p>&lt;a href="https://www.cncf.io/projects/cert-manager/">&lt;img src="https://raw.githubusercontent.com/cncf/artwork/main/projects/cert-manager/icon/color/cert-manager-icon-color.svg" alt="cert-manager logo">&lt;/a>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Using since:&lt;/strong> 2021&lt;/li>
&lt;li>&lt;strong>Current version:&lt;/strong> v1.17.x&lt;/li>
&lt;/ul>
&lt;p>Defaults to DNS-01 ACME challenge validation with cloud-specific IAM scoping: IRSA on AWS, Workload Identity on Azure, API tokens on Hetzner. A CertificateNotReady alerting rule and external TLS expiry probe ship as KubeAid defaults added after a silent TLS expiry failure in production.&lt;/p>
&lt;/p>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="col mb-4">
&lt;div class="card h-100">
&lt;div class="card-header">
Velero
&lt;/div>
&lt;div class="card-body">
&lt;p class="card-text">
&lt;p>&lt;a href="https://www.cncf.io/projects/velero/">&lt;img src="https://raw.githubusercontent.com/cncf/artwork/main/projects/velero/icon/color/velero-icon-color.svg" alt="velero logo">&lt;/a>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Using since:&lt;/strong> 2021&lt;/li>
&lt;li>&lt;strong>Current version:&lt;/strong> v1.15.x&lt;/li>
&lt;/ul>
&lt;p>Backup schedules, IAM policies, and object storage (S3, GCS, Azure Blob) are provisioned at cluster bootstrap. Velero also exports the Sealed Secrets private key to external object storage at bootstrap — making DR proven at provision time, not during a drill.&lt;/p>
&lt;/p>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="col mb-4">
&lt;div class="card h-100">
&lt;div class="card-header">
Cluster API
&lt;/div>
&lt;div class="card-body">
&lt;p class="card-text">
&lt;p>&lt;a href="https://cluster-api.sigs.k8s.io/">&lt;img src="https://raw.githubusercontent.com/kubernetes-sigs/cluster-api/main/logos/icons/cluster.svg" alt="cluster api logo">&lt;/a>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Using since:&lt;/strong> 2022&lt;/li>
&lt;li>&lt;strong>Current version:&lt;/strong> v1.10.x&lt;/li>
&lt;/ul>
&lt;p>Manages cluster lifecycle declaratively across Hetzner bare metal, AWS, and Azure. MachineHealthChecks detect and replace unhealthy nodes automatically. Cluster topology is version-controlled in Git.&lt;/p>
&lt;/p>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="col mb-4">
&lt;div class="card h-100">
&lt;div class="card-header">
Helm
&lt;/div>
&lt;div class="card-body">
&lt;p class="card-text">
&lt;p>&lt;a href="https://www.cncf.io/projects/helm/">&lt;img src="https://raw.githubusercontent.com/cncf/artwork/main/projects/helm/icon/color/helm-icon-color.svg" alt="helm logo">&lt;/a>&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Using since:&lt;/strong> 2019&lt;/li>
&lt;li>&lt;strong>Current version:&lt;/strong> v3.x&lt;/li>
&lt;/ul>
&lt;p>Over 100 curated Helm charts form the KubeAid chart library. Each chart ships with pre-wired Cilium network policies, Prometheus alerting rules, and ArgoCD ignoreDifferences configurations. Customers override only genuine differences.&lt;/p>
&lt;/p>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;h2 id="tldr-synopsis">TLDR; Synopsis&lt;/h2>
&lt;p>This reference architecture describes how Obmondo operates production Kubernetes for dozens of customer clusters across four cloud providers and bare metal with a team of under 10 engineers using a two-repo GitOps pattern built entirely on CNCF projects.&lt;/p>
&lt;p>The core insight: every production failure fixed once in the shared platform repo (KubeAid) propagates to every cluster on the next ArgoCD sync. No cluster is ever patched manually. No cluster becomes a snowflake.&lt;/p>
&lt;p>This architecture targets:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Zero snowflake clusters&lt;/strong> — a fix committed once applies everywhere within hours via ArgoCD&lt;/li>
&lt;li>&lt;strong>Full EU data sovereignty&lt;/strong> — identical stack on Hetzner bare metal in Germany, on-premises datacentres, and EU-region cloud VMs, with no vendor control plane, no proprietary APIs, and full auditability&lt;/li>
&lt;li>&lt;strong>Disaster recovery by default&lt;/strong> — backup schedules, IAM, and Sealed Secrets key export are automated at cluster bootstrap; if a cluster can be created, it can be recovered&lt;/li>
&lt;li>&lt;strong>Sub-10-engineer fleet operations&lt;/strong> — platform-level abstractions that scale cluster count without scaling headcount&lt;/li>
&lt;/ul>
&lt;h2 id="organization">Organization&lt;/h2>
&lt;p>Obmondo (EnableIT ApS) is a Danish Managed Kubernetes provider. It builds and operates production Kubernetes platforms for customers in financial services, healthcare, and public sector organizations across Denmark and the EU. All infrastructure must satisfy GDPR, NIS2, and in many cases ISO 27001 — by architecture, not by policy.&lt;/p>
&lt;p>KubeAid, the open-source platform that powers Obmondo&amp;rsquo;s managed service, is available at &lt;a href="https://github.com/Obmondo/KubeAid">https://github.com/Obmondo/KubeAid&lt;/a> under the Apache 2.0 license.&lt;/p>
&lt;h2 id="teams">Teams&lt;/h2>
&lt;p>&lt;strong>Platform Engineering&lt;/strong> maintains KubeAid the shared chart library, Jsonnet monitoring templates, and ArgoCD application definitions that apply uniformly to every cluster. A fix here reaches every customer automatically.&lt;/p>
&lt;p>&lt;strong>SRE / Customer Operations&lt;/strong> handles day-2 operations: incident response, capacity planning, and customer-specific overrides in per-customer config repos. With KubeAid abstracting the platform layer, this team focuses exclusively on the ~10% that is genuinely different per customer.&lt;/p>
&lt;h2 id="architecture">Architecture&lt;/h2>
&lt;h3 id="goals">Goals&lt;/h3>
&lt;p>&lt;strong>Eliminate snowflake clusters.&lt;/strong> Every production failure becomes a KubeAid default. The silent TLS expiry became DNS-01 + external probe + alert. The duplicate Prometheus timestamp alert became a scrape-level relabeling rule. The RBAC gap became a ClusterRole fix. Each fix landed once; every cluster received it automatically.&lt;/p>
&lt;p>&lt;strong>EU data sovereignty without vendor lock-in.&lt;/strong> No proprietary control plane. No per-node SaaS fees. No APIs that cannot be audited. The entire stack runs on CNCF projects identically on Hetzner bare metal in Germany, on-premises in Danish datacentres, and in EU-region cloud VMs. Customers can move it, fork it, and audit every component.&lt;/p>
&lt;p>&lt;strong>Disaster recovery proven at provision time.&lt;/strong> Backup schedules, IAM policies, object storage, and Sealed Secrets private key export are automated at bootstrap. The DR gap was discovered simultaneously on every cluster during a planned drill and made impossible to miss on any future cluster.&lt;/p>
&lt;p>&lt;strong>Observability without per-cluster overhead.&lt;/strong> Monitoring configuration is generated from a single Jsonnet vars file. One engineer maintains alerting for the entire fleet. Custom rules compose with upstream libraries without merge conflicts.&lt;/p>
&lt;h3 id="architecture-overview">Architecture Overview&lt;/h3>
&lt;p>&lt;img src="images/obmondo-architecture.png" alt="Obmondo Platform Architecture">&lt;/p>
&lt;p>The architecture follows a strict two-repo pattern:
&lt;strong>Repo 1 — KubeAid (shared platform defaults)&lt;/strong>
Over 100 curated Helm charts with pre-wired integrations. ArgoCD ApplicationSets deploy these charts to every cluster. Monitoring is generated per-cluster from a single Jsonnet vars file using kube-prometheus. Cilium network policies ship alongside workload manifests. DR configuration is provisioned at bootstrap. Every production failure becomes a default here.&lt;/p>
&lt;p>&lt;strong>Repo 2 — Customer config (genuine differences only)&lt;/strong>
Each customer config repo holds only what is genuinely different: cloud provider, node sizes, alerting thresholds, compliance scope. If a value matches the KubeAid default, it does not exist in the config repo. ArgoCD reconciles both repos continuously across every cluster.&lt;/p>
&lt;p>&lt;strong>Per-cluster stack (all CNCF projects):&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Layer&lt;/th>
&lt;th>Project&lt;/th>
&lt;th>Role&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Lifecycle&lt;/td>
&lt;td>Cluster API&lt;/td>
&lt;td>Declarative cluster provisioning across all providers&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Networking&lt;/td>
&lt;td>Cilium&lt;/td>
&lt;td>CNI + FQDN egress policies + Hubble metrics&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>TLS&lt;/td>
&lt;td>cert-manager&lt;/td>
&lt;td>DNS-01 ACME with cloud IAM scoping&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>GitOps&lt;/td>
&lt;td>ArgoCD&lt;/td>
&lt;td>Continuous reconciliation from both repos&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Observability&lt;/td>
&lt;td>Prometheus + Alertmanager&lt;/td>
&lt;td>Generated from Jsonnet per cluster&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Ingress&lt;/td>
&lt;td>Traefik&lt;/td>
&lt;td>Wildcard TLS, HTTP→HTTPS redirect&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Backup / DR&lt;/td>
&lt;td>Velero&lt;/td>
&lt;td>Scheduled backups + Sealed Secrets key export&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Secrets&lt;/td>
&lt;td>Sealed Secrets (Bitnami)&lt;/td>
&lt;td>Encrypted secrets in Git, key exported at bootstrap&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="infrastructure-layer">Infrastructure Layer&lt;/h3>
&lt;p>Cluster API manages cluster lifecycle across all providers. The same declarative topology definition works on Hetzner bare metal (HCloud provider), AWS, and Azure. MachineHealthChecks detect unhealthy nodes and trigger automatic replacement. Node removal by CAPI is tracked and DaemonSet ghost pods are handled via alerting.&lt;/p>
&lt;p>On Hetzner bare metal, clusters run on dedicated physical servers with ZFS and Ceph storage. Network isolation is enforced by Cilium at the pod level. No hypervisor, no shared infrastructure with other tenants.&lt;/p>
&lt;h3 id="networking-layer">Networking Layer&lt;/h3>
&lt;p>Cilium is the CNI for every cluster. Every KubeAid Helm chart ships with a &lt;code>CiliumNetworkPolicy&lt;/code> alongside the workload manifest. FQDN egress rules for every external API dependency are pre-written and applied by ArgoCD. Operators do not write network policies they are a platform default.&lt;/p>
&lt;p>FQDN policy enforcement is critical for compliance: customers need to attest that workloads only communicate with approved external endpoints. Cilium&amp;rsquo;s Hubble metrics feed into Prometheus for network observability.&lt;/p>
&lt;h3 id="tls-and-certificate-management">TLS and Certificate Management&lt;/h3>
&lt;p>cert-manager defaults to DNS-01 ACME challenge validation. The switch from HTTP-01 was forced by a production failure: Traefik&amp;rsquo;s global HTTP→HTTPS redirect for HSTS compliance made HTTP-01 ACME validation permanently impossible every challenge request was redirected before reaching the solver pod. Certificates failed to renew silently for up to 90 days.&lt;/p>
&lt;p>DNS-01 with cloud-specific IAM scoping (IRSA on AWS, Workload Identity on Azure, API tokens on Hetzner) is now the only supported challenge type. An external TLS expiry probe and a &lt;code>CertificateNotReady&lt;/code> Alertmanager rule ship as KubeAid defaults.&lt;/p>
&lt;h3 id="observability-layer">Observability Layer&lt;/h3>
&lt;p>Prometheus and Alertmanager are generated per-cluster from a single Jsonnet vars file using kube-prometheus. Custom alerting rules compose with upstream rule libraries using Jsonnet merging semantics no YAML merge conflicts.&lt;/p>
&lt;p>Custom rules added after production failures:&lt;/p>
&lt;ul>
&lt;li>&lt;code>CertificateNotReady&lt;/code> — 30-day TLS expiry warning&lt;/li>
&lt;li>&lt;code>VeleroBackupMissed&lt;/code> — backup age SLI&lt;/li>
&lt;li>&lt;code>PrometheusKubernetesListWatchFailures&lt;/code> — RBAC-induced scrape gaps&lt;/li>
&lt;li>&lt;code>KubeDaemonSetMisScheduled&lt;/code> — CAPI node removal detection&lt;/li>
&lt;li>Database replication lag alerts per database type&lt;/li>
&lt;/ul>
&lt;p>One engineer maintains monitoring configuration for the entire fleet.&lt;/p>
&lt;h3 id="disaster-recovery">Disaster Recovery&lt;/h3>
&lt;p>Velero backup schedules, IAM policies, and object storage configuration are provisioned at cluster bootstrap. DR is not a follow-up task it is a bootstrap invariant.&lt;/p>
&lt;p>The Sealed Secrets private key gap was discovered during a planned DR drill: a key that exists only inside the cluster cannot survive cluster loss, and every sealed secret in Git becomes permanently unrecoverable ciphertext. The private key is now automatically exported to external object storage via Velero at bootstrap. This protection is mandatory it is impossible to create a new KubeAid cluster without it.&lt;/p>
&lt;p>Velero backup completion metrics are scraped by Prometheus. An alert fires if a backup has not succeeded within its scheduled window.&lt;/p>
&lt;h2 id="can-you-expand-on-why-you-are-using-those-projectsservices">Can you expand on why you are using those projects/services?&lt;/h2>
&lt;p>&lt;strong>ArgoCD over Flux:&lt;/strong> ApplicationSets allow a single ArgoCD instance to manage an arbitrary number of clusters from a centralized config. ArgoCD&amp;rsquo;s multi-source application support maps cleanly to the two-repo pattern — one source for KubeAid defaults, one for customer overrides. The ArgoCD UI provides fleet-wide visibility into sync status and drift.&lt;/p>
&lt;p>&lt;strong>Cilium over Calico/Flannel:&lt;/strong> FQDN-based egress policies are a hard compliance requirement. Cilium&amp;rsquo;s &lt;code>CiliumNetworkPolicy&lt;/code> with FQDN selectors is the only CNI that supports this at the policy layer without a proxy. Hubble metrics integrate directly with Prometheus. eBPF-based enforcement has lower overhead than iptables at scale.&lt;/p>
&lt;p>&lt;strong>cert-manager with DNS-01 exclusively:&lt;/strong> HTTP-01 is broken by Traefik&amp;rsquo;s global HTTP→HTTPS redirect, which cannot be disabled without breaking HSTS compliance. DNS-01 with cloud IAM scoping works identically on bare metal and cloud, and does not require inbound HTTP access.&lt;/p>
&lt;p>&lt;strong>Cluster API over cloud-specific tooling:&lt;/strong> Provider-agnostic cluster lifecycle in Git. The same declarative model covers Hetzner bare metal, AWS, and Azure. Rolling control plane replacements, MachineHealthChecks, and autoscaling are provider-agnostic concerns handled by CAPI — not bespoke automation per cloud.&lt;/p>
&lt;p>&lt;strong>Helm for chart packaging:&lt;/strong> The KubeAid chart library wraps upstream charts and embeds the platform layer (network policies, monitoring rules, ArgoCD ignoreDifferences) alongside the workload. Customers use standard Helm values overrides. No custom CRDs or operators required for the integration layer.&lt;/p>
&lt;h2 id="what-works-particularly-well">What works particularly well&lt;/h2>
&lt;p>&lt;strong>The two-repo pattern scales linearly.&lt;/strong> A platform fix committed to KubeAid propagates to every cluster within hours. A team of under 10 engineers operates dozens of production clusters across four cloud providers with no per-cluster patching.&lt;/p>
&lt;p>&lt;strong>Production failures become permanent fixes.&lt;/strong> Every incident is an opportunity to close the gap for every cluster simultaneously. The fleet never re-experiences the same failure in the same way.&lt;/p>
&lt;p>&lt;strong>Jsonnet for monitoring composition.&lt;/strong> kube-prometheus Jsonnet templates allow custom alerting rules to compose with upstream libraries without merge conflicts. One engineer maintains alerting for the entire fleet.&lt;/p>
&lt;p>&lt;strong>Cilium FQDN policies as a compliance primitive.&lt;/strong> Embedding FQDN egress rules alongside every workload manifest means network policy is not a separate compliance exercise it ships with the workload definition and is applied everywhere.&lt;/p>
&lt;p>&lt;strong>Velero key export as a bootstrap invariant.&lt;/strong> Making Sealed Secrets private key export mandatory at cluster creation means DR is never an afterthought. The constraint was added after finding the same gap on every cluster simultaneously during a drill.&lt;/p>
&lt;p>&lt;strong>Zero vendor control plane.&lt;/strong> The same CNCF stack runs on Hetzner bare metal in Germany, on-premises in Danish datacentres, and in EU-region cloud VMs. Customers can move it, fork it, and audit every component. GDPR, NIS2, and ISO 27001 requirements are satisfied by architecture.&lt;/p>
&lt;h2 id="what-needs-improvement">What needs improvement&lt;/h2>
&lt;p>&lt;strong>ArgoCD ignoreDifferences maintenance.&lt;/strong> Runtime drift Azure webhook injections, controller-managed fields, CRD caBundle rotation requires ongoing ignoreDifferences tuning in every affected chart. Each cloud provider introduces its own drift patterns. This operational overhead ideally belongs upstream in the charts themselves.&lt;/p>
&lt;p>&lt;strong>kube-prometheus regeneration across clusters.&lt;/strong> When a fix lands in a shared Jsonnet library, manifests must be regenerated for every affected cluster. This is currently a per-cluster manual step. A CI pipeline that detects library changes, regenerates all affected clusters, and opens PRs automatically would eliminate the gap.&lt;/p>
&lt;p>&lt;strong>Cluster API bare metal host pool management.&lt;/strong> Rolling control plane replacements require a spare host in the pool. When all bare metal hosts are occupied, a new control plane node cannot be provisioned and the rollout stalls. Better capacity planning automation is needed.&lt;/p>
&lt;p>&lt;strong>Sealed Secrets rotation.&lt;/strong> Sealed Secrets use asymmetric encryption keyed to a specific cluster key. Key rotation requires re-sealing every secret in the config repo. Tooling to automate re-sealing across the fleet is not yet in place.&lt;/p>
&lt;h2 id="what-sort-of-glue-had-to-be-developed">What sort of &amp;ldquo;glue&amp;rdquo; had to be developed?&lt;/h2>
&lt;p>&lt;strong>KubeAid chart library.&lt;/strong> The 100+ Helm chart wrappers that embed Cilium policies, Prometheus rules, and ArgoCD ignoreDifferences alongside upstream charts. These are the integration layer pre-built wiring that no operator writes from scratch for each cluster.&lt;/p>
&lt;p>&lt;strong>kube-prometheus Jsonnet library extensions.&lt;/strong> Custom libsonnet files that extend the upstream kube-prometheus library with Obmondo-specific alerting rules. These compose cleanly with upstream rules via Jsonnet merging semantics.&lt;/p>
&lt;p>&lt;strong>ArgoCD ApplicationSet templates.&lt;/strong> Parameterized ApplicationSet definitions that deploy the full KubeAid chart suite to any cluster whose config repo follows the two-repo pattern. Adding a new cluster is a config-repo operation, not a platform operation.&lt;/p>
&lt;p>&lt;strong>Sealed Secrets key export automation.&lt;/strong> A bootstrap step that exports the Sealed Secrets private key to external object storage via Velero immediately after cluster creation. This step is mandatory it cannot be skipped.&lt;/p>
&lt;p>&lt;strong>Prometheus alert composition templates.&lt;/strong> A set of reusable Jsonnet patterns for constructing SLI-based alerts (backup age, certificate validity window, database replication lag) that are consistent across the fleet without per-cluster duplication.&lt;/p>
&lt;h2 id="how-did-the-architecture-evolve">How did the Architecture Evolve&lt;/h2>
&lt;p>The architecture began as manually-managed clusters with per-cluster Helm deployments. The first pain point was drift: a fix applied to cluster A was not applied to clusters B–Z. The second was silent failures that were only discovered at impact.&lt;/p>
&lt;p>Each failure drove a platform default:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Failure&lt;/th>
&lt;th>Root Cause&lt;/th>
&lt;th>KubeAid Default Added&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Silent TLS expiry (90 days)&lt;/td>
&lt;td>HTTP-01 blocked by Traefik redirect&lt;/td>
&lt;td>DNS-01 + CertificateNotReady alert + external probe&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Duplicate Prometheus timestamps&lt;/td>
&lt;td>Two kubelet endpoints emitting same metric&lt;/td>
&lt;td>Scrape-level relabeling rule in kube-prometheus&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Service discovery silent failure&lt;/td>
&lt;td>Missing RBAC on prometheus-k8s ServiceAccount&lt;/td>
&lt;td>ClusterRole fix in prometheus-k8s chart&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>DR gap across all clusters&lt;/td>
&lt;td>Sealed Secrets key not exported&lt;/td>
&lt;td>Mandatory Velero key export at bootstrap&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>snowflake clusters&lt;/td>
&lt;td>Per-cluster manual patching&lt;/td>
&lt;td>Two-repo GitOps with KubeAid defaults&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Each fix landed in KubeAid once. Every cluster received it. No future cluster will hit any of these failures in the same way.&lt;/p>
&lt;h2 id="whats-next-for-your-architecture">What&amp;rsquo;s next for your architecture?&lt;/h2>
&lt;p>&lt;strong>Automated kube-prometheus regeneration.&lt;/strong> A CI pipeline that detects when a shared Jsonnet library changes, regenerates manifests for all affected clusters, and opens PRs automatically eliminating the manual per-cluster regeneration step.&lt;/p>
&lt;p>&lt;strong>Deeper OpenTelemetry integration.&lt;/strong> Distributed tracing across customer workloads, integrated with the existing Prometheus metrics pipeline for a unified observability experience.&lt;/p>
&lt;p>&lt;strong>Automated compliance evidence generation.&lt;/strong> Generating GDPR, NIS2, and ISO 27001 evidence artifacts directly from Prometheus metrics and Kubernetes audit logs compliance as a cluster output, not a manual exercise.&lt;/p>
&lt;p>&lt;strong>Broader FQDN egress coverage.&lt;/strong> Extending Cilium FQDN policy defaults to every KubeAid chart in the library, closing the remaining gap between workloads that have pre-wired policies and those that do not.&lt;/p>
&lt;p>&lt;strong>Sealed Secrets rotation tooling.&lt;/strong> Automation to re-seal every secret in a config repo after a cluster key rotation making key rotation a safe, routine operation rather than a risky manual process.&lt;/p>
&lt;h2 id="key-takeaways--lessons">Key Takeaways / Lessons&lt;/h2>
&lt;p>&lt;strong>Every manual fix is a fix that has not been applied everywhere.&lt;/strong> The two-repo GitOps pattern is not primarily about automation it is about making the gap visible. If a fix requires touching a per-cluster config repo, it is a signal that the fix belongs in KubeAid instead.&lt;/p>
&lt;p>&lt;strong>Silent failures are the expensive ones.&lt;/strong> TLS expiry, backup failures, and RBAC gaps were all silent no component logged an error until impact. The alerting investment (CertificateNotReady, VeleroBackupMissed, PrometheusKubernetesListWatchFailures) pays back in avoided incidents, not reduced noise.&lt;/p>
&lt;p>&lt;strong>Compliance by architecture, not by policy.&lt;/strong> GDPR, NIS2, and ISO 27001 requirements are satisfied by the architecture itself: no vendor control plane, full auditability, data residency by infrastructure choice, DR proven at bootstrap. Policy documents that reference the architecture are a consequence, not the mechanism.&lt;/p>
&lt;p>&lt;strong>The CNCF ecosystem composability is the product.&lt;/strong> ArgoCD reconciles Helm charts. Helm packages Cilium, Prometheus, cert-manager, Velero. Prometheus scrapes Cilium Hubble metrics, cert-manager certificate status, and Velero backup completion metrics. Each CNCF project does one thing well. KubeAid is the integration layer and it is open source because the problems it solves are not unique to Obmondo.&lt;/p>
&lt;p>&lt;strong>DR gaps are always discovered on every cluster simultaneously.&lt;/strong> If a DR gap exists, it exists everywhere because every cluster was provisioned from the same template. The corollary is equally powerful: close the gap once, and it closes everywhere.&lt;/p>
&lt;h2 id="discussion">Discussion&lt;/h2>
&lt;p>End user members may participate in the &lt;a href="https://github.com/cncf/tab/issues/139">discussion thread&lt;/a> for this architecture.&lt;/p></description></item><item><title>Architectures: A Cloud Native Scientific Computing Platform for CERN NextGen AI</title><link>https://deploy-preview-35--cncfarchitecture.netlify.app/architectures/cern-scientific-computing/</link><pubDate>Mon, 09 Mar 2026 00:00:00 +0000</pubDate><guid>https://deploy-preview-35--cncfarchitecture.netlify.app/architectures/cern-scientific-computing/</guid><description>
&lt;h2 id="relevant-projects">Relevant Projects&lt;/h2>
&lt;div class="row row-cols-1 row-cols-md-3 mb-4">
&lt;div class="col mb-4">
&lt;div class="card h-100">
&lt;div class="card-header">
Argo
&lt;/div>
&lt;div class="card-body">
&lt;p class="card-text">
&lt;p>&lt;a href="https://www.cncf.io/projects/argo/">&lt;img src="https://raw.githubusercontent.com/cncf/artwork/main/projects/argo/icon/color/argo-icon-color.svg" alt="argo logo">&lt;/a>&lt;/p>
&lt;p>ArgoCD is used to manage deployments of all services across multiple clusters and environments. Argo Workflows is used to manage multiple day-2 cluster operations.&lt;/p>
&lt;/p>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="col mb-4">
&lt;div class="card h-100">
&lt;div class="card-header">
Bootc
&lt;/div>
&lt;div class="card-body">
&lt;p class="card-text">
&lt;p>&lt;a href="https://www.cncf.io/projects/bootc/">&lt;img src="https://raw.githubusercontent.com/cncf/artwork/main/projects/bootc/icon/color/bootc-icon-color.svg" alt="bootc logo">&lt;/a>&lt;/p>
&lt;p>Bootc provides transactional, in-place operating system images and updates using OCI/Docker container images. Bootc is used to build the minimal base images for our cluster nodes.&lt;/p>
&lt;/p>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="col mb-4">
&lt;div class="card h-100">
&lt;div class="card-header">
ContainerSSH
&lt;/div>
&lt;div class="card-body">
&lt;p class="card-text">
&lt;p>&lt;a href="https://www.cncf.io/projects/containerssh/">&lt;img src="https://raw.githubusercontent.com/cncf/artwork/main/projects/containerssh/icon/containerssh-icon-dark.svg" alt="containerssh logo">&lt;/a>&lt;/p>
&lt;p>ContainerSSH offers a SSH frontend to containers/pods running on Kubernetes clusters. Used to expose SSH as a way to access existing sessions in the cluster, with multiple authentication mechanisms offered (Kerberos, OIDC/OAuth2).&lt;/p>
&lt;/p>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="col mb-4">
&lt;div class="card h-100">
&lt;div class="card-header">
Longhorn
&lt;/div>
&lt;div class="card-body">
&lt;p class="card-text">
&lt;p>&lt;a href="https://www.cncf.io/projects/longhorn/">&lt;img src="https://raw.githubusercontent.com/cncf/artwork/main/projects/longhorn/icon/color/longhorn-icon-color.svg" alt="longhorn logo">&lt;/a>&lt;/p>
&lt;p>Longhorn offers cloud native distributed block storage for Kubernetes. Used to offer in-cluster shared storage to users, with individual and team getting dedicated volumes with read-write-multi access and automated backups.&lt;/p>
&lt;/p>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="col mb-4">
&lt;div class="card h-100">
&lt;div class="card-header">
Kubernetes
&lt;/div>
&lt;div class="card-body">
&lt;p class="card-text">
&lt;p>&lt;a href="https://www.cncf.io/projects/kubernetes/">&lt;img src="https://raw.githubusercontent.com/cncf/artwork/main/projects/kubernetes/icon/color/kubernetes-icon-color.svg" alt="kubernetes logo">&lt;/a>&lt;/p>
&lt;p>Kubernetes provides the required workload scheduling and orchestration for the diverse workloads running in our scientific platform.&lt;/p>
&lt;/p>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="col mb-4">
&lt;div class="card h-100">
&lt;div class="card-header">
Kubeflow
&lt;/div>
&lt;div class="card-body">
&lt;p class="card-text">
&lt;p>&lt;a href="https://www.cncf.io/projects/kubeflow/">&lt;img src="https://raw.githubusercontent.com/cncf/artwork/main/projects/kubeflow/icon/color/kubeflow-icon.svg" alt="kubeflow logo">&lt;/a>&lt;/p>
&lt;p>Kubeflow offers tools to manage the complete MLOps lifecycle. Used for profile management and quotas for users and teams, instantiation of notebook servers, pipelines for common and reusable tasks, hyper-parameter tuning with Katib and managing inference endpoints.&lt;/p>
&lt;/p>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="col mb-4">
&lt;div class="card h-100">
&lt;div class="card-header">
Kserve
&lt;/div>
&lt;div class="card-body">
&lt;p class="card-text">
&lt;p>&lt;a href="https://www.cncf.io/projects/kserve/">&lt;img src="https://raw.githubusercontent.com/cncf/artwork/main/projects/kserve/icon/color/k-serve-icon-color.svg" alt="kubeflow logo">&lt;/a>&lt;/p>
&lt;p>Kserve standardizes hosting of inference endpoints. Used to encapsulate multiple runtime flavors, such as ONNX, Triton and several others, and offering a declarative way to define inference servers.&lt;/p>
&lt;/p>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="col mb-4">
&lt;div class="card h-100">
&lt;div class="card-header">
Kyverno
&lt;/div>
&lt;div class="card-body">
&lt;p class="card-text">
&lt;p>&lt;a href="https://www.cncf.io/projects/kyverno/">&lt;img src="https://raw.githubusercontent.com/cncf/artwork/main/projects/kyverno/icon/color/kyverno-icon-color.svg" alt="kyverno logo">&lt;/a>&lt;/p>
&lt;p>Kyverno offers policy as code with support for YAML and CEL based policies. Used as a key component for policy enforcement and mutating workloads according to those policies, adding required settings to expose storage systems, set resources based on GPUs, etc.&lt;/p>
&lt;/p>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="col mb-4">
&lt;div class="card h-100">
&lt;div class="card-header">
Kueue
&lt;/div>
&lt;div class="card-body">
&lt;p class="card-text">
&lt;p>&lt;a href="https://kueue.sigs.k8s.io/">&lt;img src="https://raw.githubusercontent.com/kubernetes-sigs/kueue/main/site/static/images/logo.svg" alt="kueue logo">&lt;/a>&lt;/p>
&lt;p>Kueue is a kubernetes-native system offering advanced scheduling capabilities and quota management. Used to provide job queues and quotas, gang scheduling, fair sharing, among other capabilities.&lt;/p>
&lt;/p>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="col mb-4">
&lt;div class="card h-100">
&lt;div class="card-header">
Prometheus
&lt;/div>
&lt;div class="card-body">
&lt;p class="card-text">
&lt;p>&lt;a href="https://www.cncf.io/projects/prometheus/">&lt;img src="https://raw.githubusercontent.com/cncf/artwork/main/projects/prometheus/icon/color/prometheus-icon-color.svg" alt="prometheus logo">&lt;/a>&lt;/p>
&lt;p>Prometheus gathers the metrics and insights from all components in the cluster. Used for system and service metrics as well as providing individual workload performance insights on cpu, memory, power and other areas.&lt;/p>
&lt;/p>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="col mb-4">
&lt;div class="card h-100">
&lt;div class="card-header">
stargz-snapshotter
&lt;/div>
&lt;div class="card-body">
&lt;p class="card-text">
&lt;p>&lt;a href="https://github.com/containerd/stargz-snapshotter">&lt;img src="https://raw.githubusercontent.com/cncf/artwork/main/projects/containerd/icon/color/containerd-icon-color.svg" alt="containerd logo">&lt;/a>&lt;/p>
&lt;p>stargz-snapshotter provides lazy pulling of container images. Used to handle efficient job start and execution with image sizes of over 100GB in some cases.&lt;/p>
&lt;/p>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;p>Some additional projects outside the CNCF are essential to this deployment.&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://mlflow.org/">MLFlow&lt;/a>, a project under the Linux Foundation used for model management and versioning&lt;/li>
&lt;li>&lt;a href="https://github.com/NVIDIA/gpu-operator">Nvidia GPU operator&lt;/a> to setup and manage drivers and configurations for Nvidia GPUs&lt;/li>
&lt;li>&lt;a href="https://github.com/ROCm/gpu-operator">AMD GPU operator&lt;/a> to setup and manage drivers and configurations for AMD GPUs&lt;/li>
&lt;/ul>
&lt;h2 id="tldr-synopsis">TLDR; Synopsis&lt;/h2>
&lt;p>This reference architecture describes a deployment supporting multiple teams in CERN’s new flagship “&lt;a href="https://nextgentriggers.web.cern.ch/">Next Generation Triggers&lt;/a>” project, looking at innovative computing technologies for data acquisition and processing for the High-Luminosity Large Hadron Collider and beyond.&lt;/p>
&lt;p>The cluster and platform target:&lt;/p>
&lt;ul>
&lt;li>Multiple scientific use cases, covering &lt;strong>traditional numerical computing&lt;/strong> as well as &lt;strong>machine learning workloads&lt;/strong> across the different CERN experiments. Scientific computing and in particular high performance computing (HPC) have relied on cloud native tooling for parts of their workloads for several years, but relied on tools like SLURM for advanced scheduling capabilities. This is our first production deployment to offer the full stack based only on cloud native infrastructure&lt;/li>
&lt;li>Access to both accelerators (in particular &lt;strong>GPUs&lt;/strong>) as well as specialized nodes such as &lt;strong>high CPU core count&lt;/strong> and &lt;strong>high CPU clock frequency&lt;/strong>. In an earlier stage of experimentation also &lt;strong>FPGAs&lt;/strong> are being integrated targeting fast inference in the CERN experiment online filters&lt;/li>
&lt;li>In a shared pool of resources allow &lt;strong>interactive access (including SSH, VSCode, Notebooks and just kubectl), traditional batch, MPI and training workloads and inference&lt;/strong>&lt;/li>
&lt;li>Integration with the existing infrastructure at CERN for CI / CD systems (on-premises GitLab and GitHub), identity, and efficient access to multiple storage systems for both user and physics data&lt;/li>
&lt;/ul>
&lt;p>A pure cloud native based infrastructure can now successfully serve scientific computing workloads, with advanced scheduling features such as co-scheduling, fair sharing, among others.&lt;/p>
&lt;h2 id="use-cases--requirements">Use Cases &amp;amp; Requirements&lt;/h2>
&lt;p>A set of requirements and use cases was initially defined when designing the architecture. The figure below shows how a shared pool of resources, mostly on-premises but integrating public cloud and supercomputing centers, should be accessed from different services.&lt;/p>
&lt;p>&lt;img src="images/use-cases.png" alt="Use Cases and Resources">&lt;/p>
&lt;p>Below we highlight specific requirements in terms of hardware and user facing functionality.&lt;/p>
&lt;h3 id="hardware">Hardware&lt;/h3>
&lt;ul>
&lt;li>Support for an &lt;strong>heterogeneous set of resources&lt;/strong>: multiple CPU types, GPUs from multiple vendors, FPGAs and specialized accelerators, all in a shared pool of resources&lt;/li>
&lt;li>Integration with &lt;strong>multiple network interconnects&lt;/strong> targeting low latency, including at least Infiniband and RDMA over Converged Ethernet (RoCEv2)&lt;/li>
&lt;li>A &lt;strong>hybrid deployment&lt;/strong> integrating external resources, both from public cloud providers and supercomputing centers&lt;/li>
&lt;/ul>
&lt;h3 id="user-facing">User Facing&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>Curated environments&lt;/strong> based on container images and maintained by the platform team for the most common user setups, covering ML workloads but also traditional scientific computing. Particularly important has been ensuring these environments are compatible with the existing ways of working, with session environments setup with backwards compatibility for existing physicist tools and scripts&lt;/li>
&lt;li>Easily &lt;strong>customizable environments&lt;/strong>, either via dedicated environments maintained by user teams or the ability to install additional packages at runtime. This means users have sudo capabilities inside their sessions&lt;/li>
&lt;li>&lt;strong>Interactive access&lt;/strong> to sessions with the ability to choose the amount of GPUs at creation, and a corresponding CPU and memory allocation depending on the type of GPU selected. Once created, access available to the session via notebooks, local vscode instances and most importantly &lt;strong>SSH for compatibility&lt;/strong> with the existing ways of working&lt;/li>
&lt;li>&lt;strong>Batch access&lt;/strong> to resources, with support for advanced scheduling capabilities such as queues, quotas, co-scheduling, fair sharing. In addition to the high priority user submissions of training or MPI jobs, the system should be able to backfill unused resources with lower priority workloads to ensure high usage efficiency&lt;/li>
&lt;li>Support for the complete &lt;strong>machine learning lifecycle&lt;/strong>, including data preparation, training, hyper-parameter tuning and model inference. In particular, support, efficient integration and automation using common training and tuning frameworks&lt;/li>
&lt;li>&lt;strong>Model management and versioning&lt;/strong>, integrated with the rest of the platform with collection and storage of training metadata and logging&lt;/li>
&lt;/ul>
&lt;h2 id="architecture">Architecture&lt;/h2>
&lt;p>The diagram below shows how the different projects and tools match the requirements.&lt;/p>
&lt;p>&lt;img src="images/ngt-refarch.png" alt="">&lt;/p>
&lt;p>Areas of particular interest where effort was required include compute, scheduling, networking, storage and observability.&lt;/p>
&lt;h3 id="compute">Compute&lt;/h3>
&lt;p>&lt;strong>Proper isolation and reproducibility&lt;/strong> is essential for reliable performance and results, removing the effect of noisy neighbors and the latency between CPU and GPU. GPU nodes follow a NUMA-aware dual-socket layout, designed to preserve locality between CPU, memory, and accelerator resources. Each node has two CPU sockets, exposed as two NUMA nodes.&lt;/p>
&lt;p>&lt;img src="images/hwlayout.png" alt="">&lt;/p>
&lt;p>Depending on the node type, GPUs are distributed evenly across these NUMA domains: either 8 GPUs per node, with 4 GPUs attached to each NUMA node, or 4 GPUs per node, with 2 GPUs attached to each NUMA node.&lt;/p>
&lt;p>Some relevant configurations to ensure the desired reproducibility and isolation.&lt;/p>
&lt;p>&lt;em>CPU and memory resource allocations (requests and limits)&lt;/em> scale with the number of GPUs requested by a session: pods receive resources in proportion to the selected GPU count while remaining aligned with the corresponding NUMA locality. This minimizes cross-socket communication, reduces latency between CPU and GPU, and improves the consistency of performance-sensitive workloads&lt;/p>
&lt;p>&lt;em>Control CPU Management Policies on the Node&lt;/em>, as &lt;a href="https://kubernetes.io/docs/tasks/administer-cluster/cpu-management-policies/">documented here&lt;/a> with the following settings on the kubelet.&lt;/p>
&lt;ul>
&lt;li>&lt;code>cpu-manager-policy=static&lt;/code>&lt;/li>
&lt;li>&lt;code>cpu-manager-policy-options=full-pcpus-only=true&lt;/code>&lt;/li>
&lt;li>&lt;code>memory-manager-policy=Static&lt;/code>&lt;/li>
&lt;li>&lt;code>topology-manager-policy=restricted&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>&lt;em>Reserved systems resources&lt;/em> for kubelet and other add-ons.&lt;/p>
&lt;ul>
&lt;li>&lt;code>system-reserved=cpu=2,memory=1000Mi&lt;/code>&lt;/li>
&lt;li>&lt;code>reserved-memory=0:memory=1000Mi&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Efficient access and distribution of container images&lt;/strong>, to accelerate the start of sessions based on both curated and custom environments each being multiple 10s of GBs in size. We provide this with a custom daemonset pre-pulling all curated images in advance when published, as well as the ability to do image streaming with the stargz-snapshotter.&lt;/p>
&lt;p>&lt;strong>Capability to burst out to external resources,&lt;/strong> in particular public cloud providers and HPC resources.&lt;/p>
&lt;h3 id="scheduling">Scheduling&lt;/h3>
&lt;p>&lt;a href="https://kubernetes.io/docs/concepts/scheduling-eviction/resource-bin-packing/">&lt;strong>Bin packing&lt;/strong>&lt;/a> &lt;strong>in the scheduling profile&lt;/strong> instead of the default workload spread across nodes, with strategy &lt;code>MostAllocated&lt;/code> ensuring better availability for workloads requiring full nodes.&lt;/p>
&lt;p>&lt;strong>Advanced scheduling features&lt;/strong> for queues supporting different resource types and QoS, workload co-scheduling, quotas and fair sharing to optimize overall resource utilization.&lt;br>
Kueue is the main component being used to achieve the advanced scheduling functionality we need.&lt;/p>
&lt;h3 id="networking">Networking&lt;/h3>
&lt;p>&lt;strong>Low latency networking&lt;/strong> such as Infiniband and RDMA over Converged Ethernet (RoCEv2) supporting both traditional CPU and GPU MPI workloads. Currently done by enabling hostNetwork and exposing the corresponding PCI devices for these specific use cases. Driver and lifecycle management of IB/RoCEv2 networking resources is controlled using the Nvidia network operator.&lt;/p>
&lt;h3 id="storage">Storage&lt;/h3>
&lt;p>Users get different storage tiers which fit different usages.&lt;/p>
&lt;h4 id="node-local">Node local&lt;/h4>
&lt;p>Very high IOPS but limited space, typically on the low TBs available to all workloads on that node. Not useful for multi-node jobs requiring a shared filesystem. Used also for GPU Direct Storage (GDS) with local NVMEs.&lt;/p>
&lt;h4 id="cluster-local">Cluster local&lt;/h4>
&lt;p>Shared filesystem across all nodes in the cluster, deployed using Longhorn. Limiting the number of network hops as much as possible ensures reasonable IOPS and scales out well in space available with the number of nodes in the cluster (typically 10s of TBs per node). Connection through a single switch for higher performance, as much as possible. Volumes stored in this filesystem are backed up to S3 storage relying on the internal Longhorn backup functionality, with incremental points daily for a week and monthly.&lt;/p>
&lt;h4 id="central">Central&lt;/h4>
&lt;p>Shared filesystem outside the cluster with much higher storage space available. Managed using CEPH with different IOPS available, up to 2000 guaranteed with bursting to higher values.&lt;/p>
&lt;h3 id="observability">Observability&lt;/h3>
&lt;p>The stack provides visibility into hardware performance, resource efficiency, and environmental impact.&lt;/p>
&lt;h4 id="telemetry-collection">Telemetry Collection&lt;/h4>
&lt;p>Leveraging a multi-layered collection strategy integrated with the kube-prometheus-stack.&lt;/p>
&lt;p>&lt;strong>Accelerators&lt;/strong>: NVIDIA dcgm-exporter and AMD device-metrics-exporter provide deep-field GPU telemetry (utilization, memory, power, temperature, and frequency).&lt;/p>
&lt;p>&lt;strong>Power &amp;amp; Sustainability&lt;/strong>: IPMI and Kepler capture hardware-level power metrics. Kepler utilizes RAPL to attribute energy consumption to individual workloads.&lt;/p>
&lt;p>&lt;strong>System Metrics&lt;/strong>: Standardized node and container metrics are ingested via Prometheus for a unified view of the cluster.&lt;/p>
&lt;h4 id="visualization-and-analysis">Visualization and Analysis&lt;/h4>
&lt;p>Data is exposed via Grafana through three specialized dashboard tiers.&lt;/p>
&lt;p>&lt;strong>Cluster Overview&lt;/strong>: Tracks aggregate utilization (CPU, GPU, RAM, Network, Thermals) and node-level health. It highlights idle resources and historical trends to guide capacity planning.&lt;/p>
&lt;p>&lt;strong>User/Workload Analytics&lt;/strong>: Provides namespace-filtered views for individual developers to monitor their specific deployments. This view balances resource efficiency (allocated vs. actual usage) with performance profiling (GPU/CPU/RAM saturation) and power consumption, allowing users to independently debug bottlenecks and optimize job performance.&lt;/p>
&lt;p>&lt;strong>Sustainability Tracking&lt;/strong>: A dedicated dashboard for CO2-equivalent emissions, offering transparency into the carbon footprint at both the cluster and individual workload levels.&lt;/p>
&lt;h4 id="alerting-and-optimization">Alerting and Optimization&lt;/h4>
&lt;p>Alertmanager is configured to trigger notifications for idle resources. By monitoring the delta between allocated requests and actual utilization, the system identifies &amp;ldquo;zombie&amp;rdquo; workloads or over-provisioned namespaces, allowing for potential automated or manual resource reclamation to reduce costs and energy waste.&lt;/p>
&lt;h2 id="what-works-particularly-well">What works particularly well&lt;/h2>
&lt;p>&lt;strong>Workload isolation&lt;/strong> which is a key aspect when considering needs for reliable benchmarking results. Recent versions of Kubernetes have all the required capabilities to ensure NUMA affinity between CPUs and GPUs, resource pinning to individual workloads and reservation for system services and add-ons.&lt;/p>
&lt;p>&lt;strong>GPU setup, configuration and monitoring&lt;/strong> with well supported and up to date operators for both Nvidia and AMD GPUs and automation for metric collection on utilization, power, memory, etc. This includes the initial node configuration required with loading drivers and exposing them to the workloads, as well as day-2 operations such as driver upgrades with integration with the default methods for cordoning and draining nodes.&lt;/p>
&lt;p>&lt;strong>Kyverno for validation and mutation&lt;/strong> of cluster resources, allowing a policy based mutation of the resource capabilities based on labels available to users. This ranges from attaching volumes for access to external storage, setting environment variables such as home directories or authentication, automation of resources for cpu and memory and many others. Validation policies also include ensuring users do not attempt invalid NUMA allocations of CPUs and GPUs. Kyverno was chosen after the initial choice of the OPA Gatekeeper had limitations when modifying fields outside the matching location.&lt;/p>
&lt;h2 id="what-needs-improvement">What needs improvement&lt;/h2>
&lt;p>&lt;strong>GPU failure detection&lt;/strong> and integration with the scheduler, either by cordoning nodes or blocking access to faulty GPUs. Depending on the type of fault, the device plugins (for both Nvidia and AMD) may stop exposing faulty devices, but this is not reliable in all cases. Options such as &lt;a href="https://github.com/NVIDIA/NVSentinel">Nvidia Sentinel&lt;/a> are being evaluated.&lt;/p>
&lt;p>&lt;strong>GPU partitioning currently at node level&lt;/strong>, limiting the ability to have in the same node devices being exposed fully and others being partitioned using MIG. This is currently not supported by the GPU operators, but should be available in the future with the DRA drivers.&lt;/p>
&lt;p>&lt;strong>Scheduling workloads across multiple clusters&lt;/strong>, while possible, does not allow seamless access to logs or launching interactive sessions as done for single clusters - `kubectl log` and `kubectl exec` type of request. This is ongoing work in Kueue but currently limits the workloads submitted outside the main cluster to batch-like workloads.&lt;/p>
&lt;p>&lt;strong>Limited support for checkpoint and restore&lt;/strong> in several types of workloads, in particular the non machine-learning workloads. This limits the ability to push overall usage of the cluster further up by suspending / preempting idle sessions without losing any work. Efforts such as &lt;a href="https://criu.org/Kubernetes">criu&lt;/a> and the &lt;a href="https://kubernetes.io/blog/2026/01/21/introducing-checkpoint-restore-wg/">checkpoint-restore working group&lt;/a> promise to greatly advance the capabilities of the cloud native ecosystem in this area in an workload agnostic way.&lt;/p>
&lt;p>&lt;strong>Low latency networking&lt;/strong> with InfiniBand or RoCEv2 in our setup is currently not namespaced and exposed to the users through &lt;em>hostNetwork&lt;/em>. In case user workloads are not trusted, other options that provide better network-level isolation should be explored, including SR-IOV and via efforts such as &lt;a href="https://github.com/kubernetes-sigs/dranet">dranet&lt;/a>.&lt;/p>
&lt;h2 id="what-sort-of-glue-have-you-had-to-develop">What sort of &amp;ldquo;glue&amp;rdquo; have you had to develop?&lt;/h2>
&lt;p>A key goal of our architecture was ensure the complete functionality is available via cloud native APIs, easing the integration with all other tools in the ecosystem. The glue pieces below target ease of use.&lt;/p>
&lt;p>&lt;strong>Access via SSH&lt;/strong> was one of the main requests from our users, allowing backwards compatibility with years of custom scripts, continuous integration and several other &amp;ldquo;ways of working&amp;rdquo; that require this type of access. We invested internally in developing the required capabilities in the &lt;a href="https://containerssh.io/">containerssh&lt;/a> project, with management of multiple sessions, multiple authenticated methods (OAuth2, Kerberos, X509), among others.&lt;/p>
&lt;p>&lt;strong>Large number of mutating policies&lt;/strong>, allowing us to give a better experience to users that do not want to use &lt;code>kubectl&lt;/code> or write yaml. Relying on metadata labels in the different resources hides the complexity of setting up volume mounts, environment variables, etc. Our current policies include setting tolerations to assign workloads to specific node flavors, additional environment configurations for MPI workloads, injecting user metadata to access storage systems and interact with internal services, mounting multiple storage systems at CERN or enabling RDMA and GPU Direct Storage.&lt;/p>
&lt;h2 id="whats-next-for-your-architecture">What&amp;rsquo;s next for your architecture?&lt;/h2>
&lt;p>&lt;strong>Interactive session management&lt;/strong> via notebooks, relying on the Kubeflow Notebooks UI. As of today, users require a minimal yaml and usage of the &lt;code>kubectl&lt;/code> client to create, list and delete their interactive sessions, even if access is then available via ssh, notebooks, vscode, etc. An upcoming improvement is to offer a UI based interface to manage sessions, likely relying on the Kubeflow Notebook UI but applying to any type of workload.&lt;/p>
&lt;p>&lt;strong>DRA and automated partitioning&lt;/strong> in the cluster, as currently we still rely on the Nvidia and AMD operators to manage GPU resources for this particular setup and need to manually set the desired MIG configuration for each node/pool of nodes. This will allow us to have heterogeneous configurations in the same node (with both partitioned and non-partitioned devices) as well as, in the future when the DRA drivers get this functionality, automatic partitioning of devices based on the current workloads.&lt;/p>
&lt;p>&lt;strong>Bursting to HPC resources&lt;/strong>, as existing supercomputers and upcoming AI factories have a large number of available GPUs. The main requirement is to integrate with SLURM as an API to manage these remote resources, but in a way that is seamless to users of the service. Projects such as &lt;a href="https://github.com/interlink-hq">interLink&lt;/a> promise to hide the SLURM backends behind the Kubernetes APIs in our platform.&lt;/p>
&lt;h2 id="key-takeaways--lessons">Key Takeaways / Lessons&lt;/h2>
&lt;p>&lt;strong>Adapt to existing ways of working&lt;/strong>: the success of the platform depends on acceptance by users, who often will not have the time to change their ways of working. Anticipate where effort is needed to meet users where they&amp;rsquo;re at, building the required glue on top of your cloud native infrastructure.&lt;/p>
&lt;p>&lt;strong>Iterative and quick development&lt;/strong>: when exposing a new platform to users with so many stack changes from previous deployments, the ability to iterate very quickly taking into account user feedback is essential. This likely means planning for an intense period after first exposing the services, with the risk of loosing users from the start otherwise.&lt;/p>
&lt;p>&lt;strong>Upstream first&lt;/strong>: this is only way to ensure long term sustainability of a platform, exposing requirements and working together with the rest of the community. Local, temporary patches, when required, should be done in parallel with the upstream contributions.&lt;/p>
&lt;p>&lt;strong>Cloud native is ready for scientific computing and AI/ML&lt;/strong>: if there were doubts, this experience cleared them up. Cloud native enables the next generation of scientific computing and AI/ML platforms, with all the advanced requirements from high performance computing together with the integration with all modern tools that talk cloud native.&lt;/p>
&lt;h2 id="discussion">Discussion&lt;/h2>
&lt;p>End user members may participate in the &lt;a href="https://github.com/cncf/tab/discussions/137">discussion thread&lt;/a> for this architecture.&lt;/p></description></item></channel></rss>