Skip to main content
Version: Next 🚧

Resource Governance

This document describes the compute resource governance model of TFRS Operator, including ResourceQuota management, component resource defaults, and auto-fill mechanisms.

Governance Model Overview​

ResourceQuota (Namespace-level)
├── TFRTenant Internal Components (12) ── User config > Operator defaults
└── TFRServer Containers (3) ── User config > Operator defaults

Core logic: When a namespace has a ResourceQuota with CPU/Memory constraints, Kubernetes requires all containers to declare resources. The Operator uses a three-layer mechanism to prevent Pod rejection by the apiserver:

  1. Component resource auto-fill: Components without explicit config use Operator defaults
  2. LimitRange defaults: Provides fallback resources for third-party operator injected containers (e.g., MinIO sidecar)
  3. Istio sidecar annotations: Declares resources for the istio-proxy container

ResourceQuota Management​

Enabling​

Controlled via the spec.resourceQuota field of the TFRTenant CR:

apiVersion: infra.tfrobot.io/v1
kind: TFRTenant
spec:
resourceQuota:
enabled: true
spec:
hard:
requests.cpu: "8"
requests.memory: "16Gi"
limits.cpu: "16"
limits.memory: "32Gi"
pods: "50"
  • CRD type definition: api/infra/v1/tfrtenant_types.go:316-329
  • Deployable implementation: internal/controller/infra/tenant/resource_quota.go

Lifecycle​

OperationBehavior
enabled: trueCreates or updates the tfrs-quota-{tenantName} object
enabled: true + compute resourcesAlso creates tfrs-limit-{tenantName} LimitRange
enabled: falseAuto-deletes both ResourceQuota and LimitRange
TFRTenant deletionCascade-deleted via OwnerReference
Spec changeSpec drift detection auto-corrects (resource_quota.go:155-191)

LimitRange Auto-Creation​

When ResourceQuota contains compute resources (CPU/Memory), the Operator automatically creates a LimitRange to provide default values for containers without resource declarations:

TypeDefault (limits)DefaultRequest (requests)
Container50m / 64Mi10m / 32Mi

Positioned as a "minimum safety net": only prevents containers without resource declarations from being rejected by Quota, not intended as reasonable defaults. Solves the problem of third-party operator injected containers (e.g., MinIO's sidecar and validate-arguments) lacking resource declarations and being rejected by ResourceQuota.

Implementation: internal/controller/infra/tenant/resource_quota.go

Istio Sidecar Resource Annotations​

When a component has Resources set, the Operator automatically adds Istio sidecar resource annotations to the Pod:

AnnotationValue
sidecar.istio.io/proxyCPU10m
sidecar.istio.io/proxyMemory64Mi
sidecar.istio.io/proxyCPULimit100m
sidecar.istio.io/proxyMemoryLimit128Mi

Implementation: MergeIstioSidecarAnnotations() in internal/controller/infra/tenant/resources.go

Quota Detection​

The Operator detects whether a namespace has compute resource quotas through two methods:

  1. APIServer query: Checks all ResourceQuota objects in the namespace (resources.go:192-213)
  2. TFRTenant Spec check: Handles first reconcile when the ResourceQuota object doesn't exist yet (resources.go:172-188)

Monitored fields: requests.cpu, requests.memory, limits.cpu, limits.memory — matching any one triggers auto-fill.

Entry point: tfrtenant_controller.go:276-277

TFRTenant Component Resources​

Default Values​

All defaults are defined in internal/controller/infra/tenant/resources.go:

ComponentRequests (CPU/Mem)Limits (CPU/Mem)
PostgreSQL200m / 256Mi1000m / 1Gi
MinIO200m / 256Mi1000m / 1Gi
RabbitMQ200m / 256Mi1000m / 1Gi
TimescaleDB250m / 1Gi500m / 2Gi
TFRSUtils Worker250m / 256Mi1000m / 2Gi
Prometheus100m / 128Mi500m / 512Mi
Redis Server100m / 128Mi500m / 512Mi
OtelCollector100m / 128Mi500m / 512Mi
Vector100m / 128Mi500m / 512Mi
Grafana100m / 128Mi500m / 512Mi
TFRSUtils Beat100m / 128Mi500m / 512Mi
Jaeger50m / 128Mi500m / 1Gi
TFRobotFront50m / 64Mi200m / 256Mi
Redis Insight50m / 64Mi200m / 256Mi

Total Requests for all components: ~1.85 CPU / 3Gi Memory

Total Limits for all components: ~8.4 CPU / 11.5Gi Memory

Resource Priority​

User-specified in TFRTenant spec > Operator defaults

Implemented via EnsureResources() (resources.go:289-294): uses user config when non-nil, otherwise falls back to defaults.

User Configuration Example​

apiVersion: infra.tfrobot.io/v1
kind: TFRTenant
spec:
postgresql:
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "2000m"
memory: "2Gi"
redis:
resources:
requests:
cpu: "200m"
memory: "256Mi"

See component Options definitions for supported resource fields: internal/controller/infra/tenant/options.go:131-207

TFRServer Container Resources​

Default Values​

Defined in internal/controller/tfrobot/deployables/resources.go:22-46:

ContainerRequests (CPU/Mem)Limits (CPU/Mem)
API250m / 256Mi1000m / 1Gi
Worker (memory-worker)500m / 512Mi2000m / 2Gi
RobotWorker500m / 512Mi2000m / 2Gi

Total Requests per TFRServer: 1.25 CPU / 1.25Gi Memory

Total Limits per TFRServer: 5 CPU / 5Gi Memory

Auto-Fill Trigger Conditions​

Triggered when both conditions are met (deployables/resources.go:48-60):

  1. At least one container has nil resources
  2. The namespace has a ResourceQuota with CPU/Memory constraints

Entry point: tfrserver_controller.go:286-295

User Configuration Example​

apiVersion: tfrobot.tfrobot.io/v1
kind: TFRServer
spec:
apiResources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "2000m"
memory: "2Gi"
workerResources:
requests:
cpu: "1000m"
memory: "1Gi"

CRD field definitions: api/tfrobot/v1/tfrserver_types.go:401-418

Quota Capacity Planning​

Minimum quota for a single tenant (1 TFRTenant + 1 TFRServer) using default values:

Resource TypeRequestsLimits
CPU3.1 (1.85 + 1.25)13.4 (8.4 + 5)
Memory4.3Gi (3 + 1.25)16.5Gi (11.5 + 5)
Note
  • The above covers only Operator-managed Pods, excluding Kubernetes system components and third-party Operator Pods
  • For multiple TFRServers, scale proportionally: each additional TFRServer adds 1.25 CPU / 1.25Gi to Requests
  • Recommend reserving 20-30% headroom for rolling updates and temporary Pods

Code Reference Index​

ModulePath
TFRTenant component defaultsinternal/controller/infra/tenant/resources.go
ResourceQuota Deployableinternal/controller/infra/tenant/resource_quota.go
TFRTenant auto-fill logicinternal/controller/infra/tfrtenant_controller.go:255-295
TFRServer container defaultsinternal/controller/tfrobot/deployables/resources.go
TFRServer auto-fill logicinternal/controller/tfrobot/tfrserver_controller.go:286-295
ResourceQuota CRD typesapi/infra/v1/tfrtenant_types.go:316-329
Container resource CRD typesapi/tfrobot/v1/tfrserver_types.go:401-418
Options definitionsinternal/controller/infra/tenant/options.go