Skip to content

Sample manifests

Samples are not deployable as written. Set an explicit verified compatible fork runtime digest, replace the bucket name with a dedicated bucket, create the referenced ServiceAccount with a runtime IAM identity, and use zone names in the storage region.

Bucket fleet using the Ordered StatefulSet layout with deterministic highest-ordinal retirement, across two zones.

config/samples/bucket-ordered.yaml
apiVersion: celld.eric.dev/v1alpha1
kind: CelldFleet
metadata:
name: ordered-bucket-example
namespace: default
spec:
profile: Bucket
bucketWorkload: Ordered
replicas: 3
serviceAccountName: celld-runtime
storage:
bucket: replace-with-dedicated-bucket
region: us-east-1
sizeGiB: 10
placement:
azCount: 2
zones: [us-east-1a, us-east-1b]

Three-replica Bucket fleet spread strictly across three zones. The minimal starting point.

config/samples/bucket.yaml
apiVersion: celld.eric.dev/v1alpha1
kind: CelldFleet
metadata:
name: bucket-example
namespace: default
spec:
profile: Bucket
replicas: 3
serviceAccountName: celld-runtime
storage:
bucket: replace-with-dedicated-bucket
region: us-east-1
sizeGiB: 10
placement:
azCount: 3
zones: [us-east-1a, us-east-1b, us-east-1c]

Ordered Bucket with an HPA targeting the CelldFleet /scale subresource; scale-in removes one member per step after survivor-capacity checks.

config/samples/capacity-external.yaml
# External capacity mode: one HorizontalPodAutoscaler owns spec.replicas through
# the CelldFleet /scale subresource. Never target the managed StatefulSet.
apiVersion: celld.eric.dev/v1alpha1
kind: CelldFleet
metadata:
name: agents
namespace: agents-prod
spec:
profile: Bucket
bucketWorkload: Ordered # Scale-in checks survivor capacity for the highest ordinal only.
replicas: 3
serviceAccountName: agents-celld
storage:
bucket: agents-prod-celld
region: us-east-1
placement:
azCount: 3
zones: [us-east-1a, us-east-1b, us-east-1c]
capacity:
mode: External
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: agents
namespace: agents-prod
spec:
scaleTargetRef:
apiVersion: celld.eric.dev/v1alpha1
kind: CelldFleet
name: agents
minReplicas: 3 # never below placement.azCount; the CRD rejects lower writes
maxReplicas: 30
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
behavior:
scaleDown:
stabilizationWindowSeconds: 600
policies:
- type: Pods
value: 1
periodSeconds: 120

A Bucket fleet with a capacity block in Shadow mode: recommendations are recorded and reported, nothing scales.

config/samples/capacity-shadow.yaml
apiVersion: celld.eric.dev/v1alpha1
kind: CelldFleet
metadata:
name: bucket-example
namespace: default
spec:
profile: Bucket
replicas: 3
serviceAccountName: celld-runtime
storage:
bucket: replace-with-dedicated-bucket
region: us-east-1
sizeGiB: 10
placement:
azCount: 3
zones: [us-east-1a, us-east-1b, us-east-1c]
# Add this block to either profile. Collect observations before enabling ScaleOut.
capacity:
mode: Shadow
minReplicas: 3
maxReplicas: 6
scaleOutStep: 1
sampleIntervalSeconds: 15
maxAgeSeconds: 45
scaleOutStabilizationSeconds: 30
scaleInStabilizationSeconds: 600
scaleOutCooldownSeconds: 300
scaleInCooldownSeconds: 900
provisioningTimeoutSeconds: 600
config/samples/export-bucket.yaml
apiVersion: celld.eric.dev/v1alpha1
kind: CelldFleet
metadata:
name: export-bucket-example
namespace: fleets
spec:
profile: Bucket
replicas: 3
# Replace with a fork release that ships change export; none does yet.
runtimeImage: ghcr.io/ewhauser/celld@sha256:1c0d854cd2af39fa439f163d5b88a19c7bccefd25fe35e2c0e1f43b3d886f424
serviceAccountName: runtime
storage:
bucket: replace-with-dedicated-bucket
region: us-east-1
sizeGiB: 10
placement:
azCount: 3
zones: [us-east-1a, us-east-1b, us-east-1c]
export:
sink: Bucket
classes: [Cart, Order]
excludeTables: [Cart.audit_log]
bucket:
# Optional; the runtime ServiceAccount must be able to write it.
name: replace-with-export-bucket
flushMilliseconds: 10000
retentionDays: 30
config/samples/export-kafka.yaml
apiVersion: celld.eric.dev/v1alpha1
kind: CelldFleet
metadata:
name: export-kafka-example
namespace: fleets
spec:
profile: Bucket
replicas: 3
# v0.6.1-ewhauser.3 Kafka variant, built with export-kafka.
runtimeImage: ghcr.io/ewhauser/celld@sha256:d880dae9f8e14d55740fbcf361d01e32cefca113b631a6e9cf99f5f1f1edbc4e
serviceAccountName: runtime
storage:
bucket: replace-with-dedicated-bucket
region: us-east-1
sizeGiB: 10
placement:
azCount: 3
zones: [us-east-1a, us-east-1b, us-east-1c]
execution:
# Room for the default 256 MiB export queue.
memoryLimit: 2Gi
export:
sink: Kafka
classes: [Cart, Order]
kafka:
brokers:
- kafka-0.kafka.kafka.svc:9092
- kafka-1.kafka.kafka.svc:9092
- kafka-2.kafka.kafka.svc:9092
# Create it first, with max.message.bytes >= 1114112.
topic: celld-changes
retryMilliseconds: 30000
# librdkafka settings, one name=value per line. Every key of the
# Secret is mounted under /etc/celld/export, so it can carry the CA:
# security.protocol=SASL_SSL
# sasl.mechanisms=SCRAM-SHA-512
# sasl.username=celld
# sasl.password=...
# ssl.ca.location=/etc/celld/export/ca.crt
propertiesSecretKeyRef:
name: kafka-client
key: kafka.properties
egress:
podLabels:
app.kubernetes.io/name: kafka
namespace: kafka

Platform-owned shared storage and routing configuration with small independent preview runtimes.

config/samples/fleet-previews.yaml
# Existing application fleet with optional preview configuration.
# The preview bucket and credentials are separate from this fleet's own storage.
apiVersion: celld.eric.dev/v1alpha1
kind: CelldFleet
metadata:
name: development
namespace: previews
spec:
runtimeImage: ghcr.io/ewhauser/celld@sha256:1c0d854cd2af39fa439f163d5b88a19c7bccefd25fe35e2c0e1f43b3d886f424
profile: Bucket
replicas: 1
serviceAccountName: celld-runtime
storage:
bucket: development-application
region: us-east-1
sizeGiB: 10
placement:
azCount: 1
zones: [us-east-1a]
mode: Relaxed
previews:
runtimeImage: ghcr.io/ewhauser/celld@sha256:1c0d854cd2af39fa439f163d5b88a19c7bccefd25fe35e2c0e1f43b3d886f424
serviceAccountName: preview-runtime
zone: us-east-1a
storage:
bucket: shared-previews
region: us-east-1
# Omit endpoint to use AWS S3 with the ServiceAccount's identity.
endpoint:
url: http://preview-store.previews.svc:9000
credentialsSecretName: preview-store
egress:
namespace: previews
podLabels:
app.kubernetes.io/name: preview-store
routing:
baseDomain: previews.example.com
scheme: https
ingress:
className: nginx
tlsSecretName: previews-wildcard-tls
source:
namespace: ingress-nginx
podLabels:
app.kubernetes.io/component: controller
# Defaults shown for capacity planning; these sections may be omitted.
execution:
cpuRequest: 25m
memoryRequest: 64Mi
memoryLimit: 256Mi
maxResidentCells: 8
idleEvictSeconds: 30
scratch:
request: 64Mi
limit: 512Mi

Bucket fleet in the Istio mesh under STRICT mTLS, with port 8080 left to your own AuthorizationPolicy, shown after the fleet.

config/samples/istio-mesh.yaml
apiVersion: celld.eric.dev/v1alpha1
kind: CelldFleet
metadata:
name: mesh-example
namespace: fleets
spec:
profile: Bucket
replicas: 3
# Replace with the verified compatible fork digest.
runtimeImage: ghcr.io/ewhauser/celld@sha256:1c0d854cd2af39fa439f163d5b88a19c7bccefd25fe35e2c0e1f43b3d886f424
serviceAccountName: runtime
storage:
bucket: replace-with-dedicated-bucket
region: us-east-1
sizeGiB: 10
placement:
azCount: 3
zones: [us-east-1a, us-east-1b, us-east-1c]
# Members join the Istio mesh with a native sidecar and stay reachable under
# STRICT mTLS. The operator must be in the mesh too (chart value
# podLabels."sidecar.istio.io/inject": "true").
mesh:
istio:
controlPlaneNamespace: istio-system
# Port 8080 callers are granted by your own AuthorizationPolicies.
applicationAccess: Policies
---
# Your policy for the application port. The operator's mesh-example-mesh policy
# already admits peers and the operator on 8081.
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: mesh-example-clients
namespace: fleets
spec:
selector:
matchLabels:
celld.eric.dev/fleet: mesh-example
action: ALLOW
rules:
- from:
- source:
principals: ["cluster.local/ns/apps/sa/web"]
to:
- operation:
ports: ["8080"]

PersistentFleet with maintenance paused and a commented restart token, showing the request fields.

config/samples/maintenance-paused.yaml
apiVersion: celld.eric.dev/v1alpha1
kind: CelldFleet
metadata:
name: maintenance-example
namespace: fleets
spec:
profile: PersistentFleet
replicas: 3
maintenance:
paused: true
# Change restartToken to request a same-version restart after unpausing.
# Strict placement must remain valid; small PersistentFleets need explicit downtime.
# restartToken: maintenance-2026-09
# Use the same verified sha256 digest through a registry mirror when needed.
# The mirrored image must be the qualified celld fork artifact.
runtimeImage: 123456789012.dkr.ecr.us-east-1.amazonaws.com/cache/celld@sha256:1c0d854cd2af39fa439f163d5b88a19c7bccefd25fe35e2c0e1f43b3d886f424
# There is no default compatible pin; omission blocks provisioning.
serviceAccountName: runtime
storage:
bucket: replace-with-dedicated-bucket
region: us-east-1
storageClassName: ebs-delete
placement:
azCount: 3
zones: [us-east-1a, us-east-1b, us-east-1c]

Three-replica PersistentFleet on a Delete-policy CSI StorageClass with strict placement.

config/samples/persistent.yaml
apiVersion: celld.eric.dev/v1alpha1
kind: CelldFleet
metadata:
name: persistent-example
namespace: default
spec:
profile: PersistentFleet
replicas: 3
serviceAccountName: celld-runtime
storage:
bucket: replace-with-another-dedicated-bucket
region: us-east-1
storageClassName: ebs-delete
sizeGiB: 10
placement:
azCount: 3
zones: [us-east-1a, us-east-1b, us-east-1c]
mode: Strict

A preview seeded from several Durable Objects; requires pool source authorization and a separately installed snapshot/import executor.

config/samples/preview-seeded.yaml
# Developer-owned selection for a pool with seeding configured.
# Requires a compatible external celld snapshot/import executor; none is bundled.
apiVersion: celld.eric.dev/v1alpha1
kind: CelldPreview
metadata:
name: reproduce-checkout
namespace: previews
spec:
fleetRef:
name: development
source: feature/checkout-fix
revision: replace-with-commit-sha
ttlSeconds: 86400
seed:
source: production
alarms: Clear
objects:
- class: Cart
id: cart-123
- class: Customer
id: customer-456
- class: Inventory
id: sku-789

Optional disposable shared MinIO store; replacing its Pod loses all preview data.

config/samples/preview-store.yaml
# Optional disposable shared store. Adapt capacity and placement to your cluster.
# A lost Pod loses ALL preview data; use an existing retained store when needed.
# Pre-create Secret preview-store with accessKeyId and secretAccessKey keys.
# Create the shared-previews bucket before creating previews (see docs/previews.md).
apiVersion: v1
kind: ServiceAccount
metadata:
name: preview-runtime
namespace: previews
---
apiVersion: v1
kind: Service
metadata:
name: preview-store
namespace: previews
spec:
selector:
app.kubernetes.io/name: preview-store
ports:
- name: s3
port: 9000
targetPort: 9000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: preview-store
namespace: previews
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app.kubernetes.io/name: preview-store
template:
metadata:
labels:
app.kubernetes.io/name: preview-store
spec:
automountServiceAccountToken: false
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: minio
image: quay.io/minio/minio@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e
args: [server, /data, --address, ':9000']
env:
- name: MINIO_ROOT_USER
valueFrom:
secretKeyRef:
name: preview-store
key: accessKeyId
- name: MINIO_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: preview-store
key: secretAccessKey
ports:
- name: s3
containerPort: 9000
readinessProbe:
httpGet:
path: /minio/health/ready
port: s3
resources:
requests:
cpu: 100m
memory: 256Mi
ephemeral-storage: 1Gi
limits:
memory: 1Gi
ephemeral-storage: 10Gi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: [ALL]
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
emptyDir:
sizeLimit: 10Gi
---
# Runtime and in-cluster CI clients need this namespace and label.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: preview-store
namespace: previews
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: preview-store
policyTypes: [Ingress]
ingress:
- from:
- podSelector:
matchExpressions:
- key: celld.eric.dev/fleet-uid
operator: Exists
- podSelector:
matchLabels:
celld.eric.dev/preview-uploader: 'true'
ports:
- protocol: TCP
port: 9000

A developer preview referencing a shared pool, with a unique URL and 24-hour lifetime.

config/samples/preview.yaml
# Developer-owned: all infrastructure settings come from the existing pool.
apiVersion: celld.eric.dev/v1alpha1
kind: CelldPreview
metadata:
name: pr-42
namespace: previews
spec:
fleetRef:
name: development
source: feature/login
revision: replace-with-commit-sha
ttlSeconds: 86400
config/samples/routing-gateway.yaml
# Requires an existing edge controller; adapt hosts, source labels and bucket.
apiVersion: celld.eric.dev/v1alpha1
kind: CelldFleet
metadata:
name: routed-example
namespace: default
spec:
runtimeImage: ghcr.io/ewhauser/celld@sha256:1c0d854cd2af39fa439f163d5b88a19c7bccefd25fe35e2c0e1f43b3d886f424
profile: Bucket
bucketWorkload: Ordered
replicas: 3
serviceAccountName: celld-runtime
storage:
bucket: replace-with-dedicated-bucket
region: us-east-1
sizeGiB: 10
placement:
azCount: 2
zones: [us-east-1a, us-east-1b]
routing:
hostnames: [app.example.com]
gateway:
name: public
namespace: edge
sectionName: https
source:
namespace: edge
podLabels:
app: public-gateway
config/samples/routing-ingress.yaml
# Requires an existing edge controller; adapt hosts, source labels and bucket.
apiVersion: celld.eric.dev/v1alpha1
kind: CelldFleet
metadata:
name: routed-example
namespace: default
spec:
runtimeImage: ghcr.io/ewhauser/celld@sha256:1c0d854cd2af39fa439f163d5b88a19c7bccefd25fe35e2c0e1f43b3d886f424
profile: Bucket
bucketWorkload: Ordered
replicas: 3
serviceAccountName: celld-runtime
storage:
bucket: replace-with-dedicated-bucket
region: us-east-1
sizeGiB: 10
placement:
azCount: 2
zones: [us-east-1a, us-east-1b]
routing:
hostnames: [app.example.com]
ingress:
className: nginx
tlsSecretName: app-tls
annotations:
cert-manager.io/cluster-issuer: letsencrypt
source:
namespace: ingress-nginx
podLabels:
app.kubernetes.io/component: controller
config/samples/telemetry.yaml
apiVersion: celld.eric.dev/v1alpha1
kind: CelldFleet
metadata:
name: telemetry-example
namespace: fleets
spec:
profile: Bucket
replicas: 3
# Replace with the verified compatible fork digest.
runtimeImage: ghcr.io/ewhauser/celld@sha256:1c0d854cd2af39fa439f163d5b88a19c7bccefd25fe35e2c0e1f43b3d886f424
serviceAccountName: runtime
storage:
bucket: replace-with-dedicated-bucket
region: us-east-1
sizeGiB: 10
placement:
azCount: 3
zones: [us-east-1a, us-east-1b, us-east-1c]
telemetry:
collectorURL: http://otel-collector.fleets.svc:4318
egress:
podLabels:
app: otel-collector
sampler: parentbased_traceidratio
samplerArg: "0.1"
flushMilliseconds: 5000
flushBytes: 1048576
headersSecretKeyRef:
name: otel-auth
key: headers

Immutable execution sizing and lifecycle budgets selected before creation.

config/samples/tuned.yaml
# Per-fleet tuning. Every field is optional and immutable after creation; the
# operator never rolls out a changed pod template. Values are starting points,
# not capacity guarantees, and the capacity policy's thresholds are independent.
apiVersion: celld.eric.dev/v1alpha1
kind: CelldFleet
metadata:
name: agents
namespace: agents-prod
spec:
# Optional additional celld settings are immutable after fleet creation.
# env:
# - name: CELLD_LOG
# value: debug
# - name: CELLD_API_TOKEN
# secretKeyRef:
# name: runtime-auth
# key: token
profile: Bucket
replicas: 3
serviceAccountName: agents-celld
storage:
bucket: agents-prod-celld
region: us-east-1
sizeGiB: 20
placement:
azCount: 3
zones: [us-east-1a, us-east-1b, us-east-1c]
execution:
cpuRequest: "2"
cpuLimit: "2"
memoryRequest: 4Gi
memoryLimit: 4Gi
maxResidentCells: 400 # replace with a measured safe cap for the application
idleEvictSeconds: 60
lifecycle:
shutdownSeconds: 120 # CELLD_SHUTDOWN_TOTAL_MS
terminationGraceSeconds: 180 # must exceed shutdownSeconds by at least 5

Experimental software for evaluation.Capabilities and limitations· Contribute