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
| Field | Values | Default |
|---|---|---|
scope.mode | all | application | all |
scope.excludeNamespaces | []string | — |
refresh.mode | interval | interval |
refresh.interval | duration | 5m |
source.type | file | s3 | blob | pvc | file (report <name>.mirops) |
A spec change rebuilds the mirror at once; so does bumping the mirops.io/refresh annotation.
status (read-only)
| Field | Meaning |
|---|---|
components, edges | Size of the dependency graph |
atRisk | Components with risk 50 or higher |
byNamespace[] | namespace, maxRisk (0–100), atRisk |
lastSync | When the mirror was last rebuilt |
syncError | Why the last rebuild or its report failed; empty on success |
reportState, reportError, reportLocation | Report write outcome |
observedGeneration | The 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
| Field | Values | Default |
|---|---|---|
targetVersion | string, e.g. "1.35" | required |
scoringProfile | production | non-production | production |
scope.mode | all | application | all |
scope.excludeNamespaces | []string | — |
ai.enabled | bool | false |
ai.provider | anthropic | openai | anthropic |
ai.model | string | provider default |
ai.maxTokens | int 1–32768 | 2048 |
ai.credentialsSecret | string | — |
ai.remediation.enabled | bool | false |
ai.remediation.maxRiskLevel | low | medium | high | low |
ai.remediation.autoApprove | bool | false |
resync.interval | duration | — (once) |
source.type | file | s3 | blob | pvc | file (report <name>.mirops) |
status (read-only)
| Field | Meaning |
|---|---|
decision | SAFE / WARNING / CRITICAL / ERROR |
totalScore | readiness gauge (0–100) |
reason | primary reason for the verdict |
aiScore, aiReasoning, aiModel, aiError | AI results (when enabled) |
addonsChecked, incompatibleAddons | compatibility counts |
reportState, reportError, reportLocation | report write outcome |
lastAnalysisTime | timestamp 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.