Skip to content

feat: add R8sCluster recipe — opinionated cluster foundation - #59

Merged
irony merged 3 commits into
mainfrom
feat/stack-recipe
Aug 7, 2026
Merged

feat: add R8sCluster recipe — opinionated cluster foundation#59
irony merged 3 commits into
mainfrom
feat/stack-recipe

Conversation

@irony

@irony irony commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

What

A new R8sCluster component that sets up a complete cluster foundation in one call. Renamed from Stack to avoid collision with CNPG's Cluster CRD.

What R8sCluster does

Concern Solution Operator
TLS certificates cert-manager cert-manager
DNS updates external-dns with TSIG (RFC 2136) external-dns
Routing Envoy Gateway API envoy-gateway
Secrets OpenBao VSO vault-secrets-operator
Metrics Prometheus (kube-prometheus-stack) prometheus
Log aggregation Loki + FluentBit (Banzai Logging Operator) loki + logging-operator

All 7 operators are declared automatically. Children inherit routing (gateway), secrets (OpenBao), and DNS (external-dns with TSIG) contexts.

Cluster-scoped — does not take a namespace prop. Operators install to their own namespaces. Logging infrastructure lives in a dedicated namespace (default logging). App namespaces are managed by Platform or the apps themselves.

Usage

import { R8sCluster, Platform, App, Database } from "@r8s/recipes"

export default (
  <R8sCluster
    secrets={{ mount: "secret", path: "production" }}
    dns={{ server: "ns1.example.com", zone: "example.com", tsigPath: "dns/tsig" }}
  >
    <Platform namespace="production">
      <Database name="api-db" storage="20Gi" />
      <App name="api" image="api:v1" host="api.example.com" />
    </Platform>
  </R8sCluster>
)

What it creates

  • LokiStack in logging namespace (log backend)
  • Logging (FluentBit daemonset collecting all pod logs) in logging
  • Flow (matches all pods) + Output (ships to Loki) in logging
  • OpenBaoStaticSecret for TSIG key in external-dns namespace
  • All 7 operator declarations (cert-manager, external-dns, envoy-gateway, VSO, prometheus, loki, logging-operator)

Props

Prop Type Required Default Description
secrets { mount, path, authRef? } yes OpenBao secrets backend config
dns { server, zone, tsigPath, tsigKey? } yes ExternalDNS with TSIG
gatewayClassName string no "eg" Envoy Gateway class name
labels Record<string, string> no Default labels
operators Operator[] no Pre-installed operators (skip auto-declare)
logsNamespace string no "logging" Namespace for LokiStack and logging resources
logsStorageClass string no "standard" Storage class for Loki logs
children unknown yes App/Database/Auth components

Tests

19 tests covering: operator declaration (7 operators), operator dedup, LokiStack/Logging/Flow/Output creation in logging namespace, custom logs namespace, custom storage class, TSIG secret in external-dns namespace, DNS context propagation to children, secrets context propagation to children, gateway routing context propagation, custom gatewayClassName, cluster-scoped behavior (no namespace prop, no Namespace resource), Platform integration, and complete cluster rendering with apps.

CLI

r8s info R8sCluster and r8s explain R8sCluster work — R8sCluster is in the catalog.

Stack sets up a complete cluster foundation in one component:
- cert-manager for TLS certificate automation
- external-dns with TSIG for secure RFC 2136 DNS updates
- Envoy Gateway for Gateway API routing
- OpenBao VSO for secrets management
- Prometheus for metrics and alerting
- Loki + FluentBit for log aggregation of all user pods

All 7 operators are declared automatically. Children inherit
namespace, routing (gateway), secrets (OpenBao), and DNS (external-dns
with TSIG) contexts — just add apps.

Includes 12 tests covering operator declaration, Namespace
materialization, LokiStack/Logging/Flow/Output creation, context
propagation to children, and operator dedup.
@irony
irony requested a review from a team as a code owner August 7, 2026 10:12
Copilot AI lite review requested due to automatic review settings August 7, 2026 10:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Stack recipe component intended to provision an opinionated “cluster foundation” (operators + baseline resources) and propagate shared contexts (namespace/routing/secrets/DNS) to child recipes, plus integrates it into the recipes export surface and CLI catalog with accompanying tests.

Changes:

  • Introduces Stack recipe that declares a fixed set of cluster operators and creates baseline logging resources (LokiStack + Logging Operator Flow/Output).
  • Exports Stack from @r8s/recipes and adds it to the CLI component catalog (r8s info/explain).
  • Adds a new Vitest suite covering operator declaration, resource materialization, and context propagation.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.

File Description
packages/recipes/src/stack.tsx New Stack recipe: operator declaration, provider wiring, and baseline Loki/logging resources.
packages/recipes/src/index.ts Exports Stack from the recipes package entrypoint.
packages/recipes/tests/stack.test.ts Adds test coverage for Stack behavior and context propagation.
packages/cli/src/catalog.ts Adds Stack to CLI catalog metadata for info/explain.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/recipes/src/r8s-cluster.tsx Outdated
@@ -0,0 +1,295 @@
import { jsx, Fragment, useContext, declareOperator } from '@r8s/core'
Comment on lines +70 to +74
/**
* Application components (App, Database, Auth, etc.).
*/
children: unknown
}
Comment thread packages/recipes/src/stack.tsx Outdated
Comment on lines +168 to +170
// Cluster-level logging: FluentBit collects logs from ALL pods in
// the namespace and ships to Loki. A ClusterFlow matches everything.
const loggingName = `${namespace}-logging`
Comment on lines +181 to +188
spec: {
size: '1x.small',
storageClassName: logsStorageClass,
storage: {
schemas: [{ version: 'v13', effectiveDate: '2024-01-01' }],
secret: { name: lokiStorageSecret, type: 's3' },
},
tenants: {
Comment thread packages/recipes/src/r8s-cluster.tsx Outdated
Comment on lines +275 to +279
// Apply operators context (all declared + preinstalled)
const allOperators = [...preinstalled, ...declared]
if (allOperators.length > 0) {
result = jsx(OperatorContext.Provider, { value: allOperators, children: result })
}
Comment on lines +256 to +261
{
name: 'children',
type: 'unknown',
required: true,
description: 'App/Database/Auth components',
},
Avoids collision with CNPG's Cluster CRD. Cluster-scoped, no namespace
prop. Logging infra in dedicated namespace (default 'logging').

- Rename stack.tsx → r8s-cluster.tsx, Stack → R8sCluster
- Update catalog: remove namespace/domain/logsRetention props,
  add logsNamespace prop
- 19 tests covering operators, logging, DNS, secrets, routing,
  cluster-scoped behavior, and complete cluster rendering
@irony irony changed the title feat: add Stack recipe — opinionated cluster foundation feat: add R8sCluster recipe — opinionated cluster foundation Aug 7, 2026
- Remove unused declareOperator import
- Make children optional (R8sCluster can set up infra standalone)
- Merge parent OperatorContext instead of overwriting it
- Mark children as not required in CLI catalog
@irony
irony merged commit 14f5936 into main Aug 7, 2026
3 checks passed
@irony
irony deleted the feat/stack-recipe branch August 7, 2026 13:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants