Skip to main content
Version: 0.2 · v0.2.1

CRD reference

Three cluster-scoped custom resources, group mirops.mirops.io/v1. You author ClusterMirror and UpgradeAnalysis; the operator creates RemediationPlan. The operator installs the CRDs itself and creates none of the inputs. Everything works with plain kubectl.

ClusterMirror​

The always-on mirror of the cluster. See Create a ClusterMirror.

Minimal​

apiVersion: mirops.mirops.io/v1
kind: ClusterMirror
metadata:
name: default
spec: {} # every field has a default

Full spec​

spec:
scope:
mode: all # all (default) | application
excludeNamespaces: [monitoring]

refresh:
mode: interval # the only mode today
interval: 5m # default 5m

source:
type: file # file (default) | s3 | blob | pvc
# file/pvc: path
# s3: bucket, region, key, credentialsSecret
# blob: accountName, containerName, blobName, credentialsSecret

spec fields​

FieldValuesDefault
scope.modeall | applicationall
scope.excludeNamespaces[]string—
refresh.modeintervalinterval
refresh.intervalduration5m
source.typefile | s3 | blob | pvcfile (report <name>.mirops)

A spec change rebuilds the mirror at once; so does bumping the mirops.io/refresh annotation.

status (read-only)​

FieldMeaning
components, edgesSize of the dependency graph
atRiskComponents with risk 50 or higher
byNamespace[]namespace, maxRisk (0–100), atRisk
lastSyncWhen the mirror was last rebuilt
syncErrorWhy the last rebuild or its report failed; empty on success
reportState, reportError, reportLocationReport write outcome
observedGenerationThe spec generation the last rebuild ran against

kubectl get clustermirror prints COMPONENTS, EDGES, AT RISK and LAST SYNC.

UpgradeAnalysis​

Processed only when the chart sets upgrade.enabled=true; otherwise it stays unprocessed.

Minimal​

apiVersion: mirops.mirops.io/v1
kind: UpgradeAnalysis
metadata:
name: to-1-35
spec:
targetVersion: "1.35" # the only required field, higher than the cluster's version

Full spec​

spec:
targetVersion: "1.35" # REQUIRED
scoringProfile: production # production (default) | non-production

scope:
mode: all # all (default) | application
excludeNamespaces: [monitoring]

ai:
enabled: true # default false
provider: anthropic # anthropic | openai
model: claude-sonnet-4-6 # optional
maxTokens: 2048 # 1–32768, default 2048
credentialsSecret: mirops-ai # Secret in the operator namespace
remediation:
enabled: true # default false
maxRiskLevel: low # low (default) | medium | high
autoApprove: false # default false

resync:
interval: "30m" # empty = run once

source:
type: file # file (default) | s3 | blob | pvc
# file/pvc: path
# s3: bucket, region, key, credentialsSecret
# blob: accountName, containerName, blobName, credentialsSecret

spec fields​

FieldValuesDefault
targetVersionstring, e.g. "1.35"required
scoringProfileproduction | non-productionproduction
scope.modeall | applicationall
scope.excludeNamespaces[]string—
ai.enabledboolfalse
ai.provideranthropic | openaianthropic
ai.modelstringprovider default
ai.maxTokensint 1–327682048
ai.credentialsSecretstring—
ai.remediation.enabledboolfalse
ai.remediation.maxRiskLevellow | medium | highlow
ai.remediation.autoApproveboolfalse
resync.intervalduration— (once)
source.typefile | s3 | blob | pvcfile (report <name>.mirops)

status (read-only)​

FieldMeaning
decisionSAFE / WARNING / CRITICAL / ERROR
totalScorereadiness gauge (0–100)
reasonprimary reason for the verdict
aiScore, aiReasoning, aiModel, aiErrorAI results (when enabled)
addonsChecked, incompatibleAddonscompatibility counts
reportState, reportError, reportLocationreport write outcome
lastAnalysisTimetimestamp of the last run

RemediationPlan​

Created by the operator when ai.remediation.enabled is true. You set spec.approved: true to execute.

apiVersion: mirops.mirops.io/v1
kind: RemediationPlan
metadata:
name: to-1-35-remediation
spec:
upgradeAnalysisRef: to-1-35
approved: false # ← set true to execute
actions:
- id: action-1
type: restart-pod # restart-pod | delete-pod | scale-deployment | cordon-node
namespace: default
name: crash-test-...
reason: "..."
risk: low # low | medium | high
skip: false
params: {} # type-specific, e.g. { replicas: "2" }

status.phase moves pending-approval → running → completed | failed; status.results[] records each action's outcome. See the remediation guide.