API Group and CRDs
The operator uses the API groupplatform.chatcli.io/v1alpha1 with 17 Custom Resource Definitions:
For detailed documentation on each v2 CRD (NotificationPolicy, EscalationPolicy, SLO, SLA, ApprovalPolicy, ApprovalRequest, ClusterRegistration, AuditEvent, ChaosExperiment), see the AIOps Platform sub-pages.
Operator Installation
A single command installs everything: 17 CRDs + RBAC + Deployment + Service + Dashboard.- Via OCI Registry (recommended)
- Via local path (if you cloned the repo)
Install directly from GHCR β no need to clone the repository:To pin a specific version:
Configurable values
Configurable values
Manual installation via kubectl (alternative)
Manual installation via kubectl (alternative)
Build via Docker (optional)
Build via Docker (optional)
AIOps Platform Architecture
Autonomous Pipeline
Issue State Machine
Create Secret with API Keys
Before creating an Instance, you need a Secret with the LLM provider API keys. The Instance references this Secret viaapiKeys.name β without it, the server cannot call the AI.
- OpenAI
- Anthropic (Claude)
- Google AI
- OpenRouter
- Multiple providers
- Via YAML
CRD: Instance
TheInstance manages ChatCLI server instances in the cluster.
Complete Specification
Spec Fields
Root
AIOpsSpec
Configures the automatic remediation pipeline. All fields are optional with sensible defaults. AI auto-generated runbooks inheritmaxRemediationAttempts from this configuration.
In agentic mode, the postmortem includes the full AI reasoning for each step β which action was chosen, why, and the observed result. This ensures complete audit trail of autonomous AI decisions.
FallbackSpec
Configures automatic failover between LLM providers. When the primary provider fails (rate limit, timeout, server error), the system automatically tries the next provider in the chain.FallbackProviderEntry
WatcherSpec
WatchTargetSpec
Resources Created by Instance
gRPC Load Balancing
gRPC uses persistent HTTP/2 connections that pin to a single pod via kube-proxy, leaving extra replicas idle.- 1 replica (default): Standard ClusterIP Service
- Multiple replicas: Headless Service (
ClusterIP: None) is created automatically, enabling client-side round-robin via gRPCdns:///resolver - Keepalive: WatcherBridge pings every 30s (5s timeout) to detect inactive pods quickly. The server accepts pings with a minimum interval of 20s (
EnforcementPolicy.MinTime) - Transition: When scaling from 1 to 2+ replicas (or back), the operator deletes and recreates the Service automatically (ClusterIP is immutable in Kubernetes)
Automatic RBAC
- Same namespace (all targets in the same namespace as the Instance): Creates per-Instance
Role+RoleBinding - Cross-namespace (targets in a different namespace than the Instance, or in multiple namespaces): Creates only a per-Instance
ClusterRoleBindingpointing at the sharedchatcli-watcherClusterRole (pre-provisioned by the Helm chart / kustomize overlay) - On CR deletion, the finalizer removes the
ClusterRoleBinding; the shared ClusterRole stays (owned by the release)
As of v1.172.0, the operator no longer creates
ClusterRole resources at runtime (H5 hardening). Shared ClusterRoles β chatcli-watcher for the watcher and chatcli-role-{viewer,operator,admin,superadmin} for platform roles β are installed by the operator Helm chart. The operatorβs ServiceAccount carries the bind verb restricted to those exact names via resourceNames, preventing privilege escalation even if the operator is compromised.Upgrading from v1.105.0: clusters with pre-existing multi-namespace Instances had a
ClusterRoleBinding pointing to a per-Instance ClusterRole (legacy shape). Because roleRef is immutable in Kubernetes, a direct helm upgrade used to freeze the reconcile with cannot change roleRef. As of v1.172.0, the operator detects the divergent roleRef at the top of reconcileClusterRBAC, deletes the stale binding, and recreates it pointing at chatcli-watcher β transparent migration, no manual intervention.Server Image and Auto-Resolution
The server image tag (spec.image.tag) follows a three-step priority:
- Explicit pin in
spec.image.tagβ honored verbatim (GitOps-friendly). - Omitted β the operator resolves it from the
CHATCLI_OPERATOR_APP_VERSIONenv var, which the Helm chart injects automatically from.Chart.AppVersion. Effect:helm upgrade chatcli-operatorrolls the server of every Instance that opted into auto-resolution, with no per-Instance patch. - Fallback β
latestwhen neither is present (e.g.,make deploywithout Helm).
Auto-Rollout on Configuration Changes
The operator monitors changes in ConfigMaps and Secrets referenced by the Instance and triggers rolling updates automatically via hash annotations on the PodTemplate:Secret and ConfigMap Observation
The operator watches (Watches) Secrets in the Instance namespace. When a Secret referenced in apiKeys.name or server.tls.secretName is created or updated, the reconciler is triggered automatically β even if the Secret did not exist when the Instance was created.
- ConfigMap and Secret
envFrom: Marked asoptional: true, allowing the Instance to be created before the Secret/ConfigMap - Flexible deploy order: Namespace -> Instance -> Secret/ConfigMap (any order after the namespace)
AIOps Platform CRDs
Anomaly
Represents a raw signal detected by the WatcherBridge.Anomaly Spec Fields
Signals Detected (21 types)
Watcher signals:
Additional signals (via Prometheus, webhooks, or internal detection):
Node Monitoring
The watcher automatically monitors the health of nodes where target pods are running. On each collection cycle, it:- Identifies nodes via label selector from the targetβs pods
- Collects all 5 official Kubernetes conditions:
Ready,DiskPressure,MemoryPressure,PIDPressure,NetworkUnavailable - Collects node CPU/memory metrics (via metrics server)
- Counts active pods vs node pod capacity
- Checks if the node is cordoned (unschedulable)
Node information is included in the AI analysis context, enabling root cause correlation with infrastructure problems (e.g., βOOMKill caused by MemoryPressure on node Xβ).
Issue
Correlated incident that groups anomalies and manages the remediation lifecycle.Issue States
AIInsight
AI-generated root cause analysis with suggested actions for automatic remediation.AIInsight Status Fields
SuggestedAction
RemediationPlan
Concrete remediation plan automatically generated from a Runbook or AI actions.Automatic Rollback and State Protection
The operator implements an automatic rollback system that ensures unsuccessful remediations do not leave the cluster in a worse state than before. Before executing any action, the complete resource state is captured in a structured restorable snapshot.1
Pre-Remediation Snapshot
Before the first action, the
RollbackEngine captures a structured ResourceSnapshot with: replicas, container images, CPU/memory requests and limits, HPA state (min/max replicas), and node state (schedulable/unschedulable). Works for Deployments, StatefulSets, DaemonSets, Nodes, and HPAs.2
Per-Action Checkpoint
In plans with multiple actions, an
ActionCheckpoint is captured before each individual action. This makes it possible to know exactly which action modified what and at which point the plan failed.3
Automatic Rollback on Action Failure
If any action fails during execution, the operator automatically restores the resource to the
PreflightSnapshot state. Replicas, images, resource requests/limits, and HPA state are reverted. The plan transitions to RolledBack state (not Failed).4
Rollback on Verification Timeout
If all actions execute successfully but the resource does not become healthy within 90 seconds (verification timeout), the operator also performs automatic rollback to the pre-remediation state.
5
Post-Failure Health Check
After the rollback, the operator verifies whether the resource returned to a healthy state (
PostFailureHealthy). This information is recorded in the plan status for auditing and retry decisions.
Example of a RemediationPlan with rollback executed:
Action Types (54 types)
Workload:
GitOps:
Autoscaling:
Infrastructure:
Storage:
Security:
Networking:
Advanced:
ExecDiagnostic Allowlist
ExecDiagnostic does an exact-string match against a read-only command allowlist. Any variation (different flags, alternate host, etc.) is rejected with command "..." not in approved diagnostic commands whitelist.
Default approved commands (~90):
Extend via the
CHATCLI_ALLOWED_DIAGNOSTIC_COMMANDS env var (comma-separated, read once at startup):
DaemonSet:
Job:
CronJob:
RemediationPlan Examples with New Actions
- GitOps: HelmRollback
- GitOps: ArgoSyncApp
- StatefulSet + HPA
- Infra: Node Drain
- Storage + Security
- Networking
- Advanced: Manifest + Diagnostic
Runbook (Manual or Auto-generated)
Operational procedures. Manual Runbooks have priority over everything. When there is no manual Runbook, the AI automatically generates a reusable Runbook CR from the suggested actions.- Manual Runbook
- AI Auto-generated Runbook
- Runbook: Helm + ArgoCD
- Runbook: StatefulSet + Storage
RemediationPlan (Agentic Mode)
When there is no manual Runbook or AI-suggested actions, the operator creates an agentic plan. The AI acts as an agent with Kubernetes skills in an observe-decide-act loop:Safety Guards: Maximum of 10 steps (configurable via
agenticMaxSteps), timeout of 10 minutes. If an action fails, the observation reports βFAILED: errorβ and the loop continues β the AI receives the feedback and adapts.- PostMortem CR with timeline, root cause, impact, lessons learned
- Reusable Runbook CR with successful steps (label
source=agentic)
PostMortem (Auto-generated)
Incident report automatically generated after any remediation resolution (standard or agentic). Contains the complete incident history: detection, analysis, executed actions, resolution, plus metrics, git correlation, cascade chain, recurring incident trending, and developer feedback field.PostMortem Status Fields
Runbook Matching (Tiered)
Remediation Priority
SourceRepository (Code-Aware Diagnostics)
Links a Kubernetes workload to its source code repository. When configured, the AI receives code context during incident analysis: recent commits correlated with the timestamp, code snippets referenced in stack traces, and configuration files (Dockerfile, values.yaml).Input validation (hardening):
spec.url only accepts the https://, ssh:// or git@host:path forms, and spec.branch is restricted to [A-Za-z0-9._/-] with no leading - β closing the git argument-injection vector (e.g. --upload-pack). Reads of code referenced by stack traces are confined to the repository clone via os.Root (no traversal, no symlink escape). Out-of-pattern URLs or branches fail the sync with an explicit status error.- Token Auth (GitHub PAT)
- SSH Key
- Basic Auth
- Public Repo (no auth)
- StatefulSet (Database)
- Shallow clone of the repository (depth 50) and periodic sync
- Indexes detected languages, entrypoints (main.go, app.py, etc.), config files
- Temporal correlation: finds commits within 30 min before the incident
- Suspect commit: identifies the most likely commit to have caused the problem
- Code extraction: when stack traces reference files, extracts the relevant snippets
- Feed to AI: all context is included in the analysis prompt
The repository is cloned locally on the operator pod. For private repos, create a Secret with the key corresponding to the chosen
authType and reference it in secretRef. The operator supports HTTPS repos (token/basic) and SSH (ssh-key).Correlation Engine
The correlation engine groups anomalies into issues using:Risk Scoring
Each signal type has a weight:
The risk score is the sum of correlated anomaly weights (maximum 100).
Severity Classification
Grouping
- Anomalies on the same resource (deployment + namespace) within the same time window are grouped into the same Issue
- Incident ID is deterministic: hash of resource + signal type (prevents duplicates)
WatcherBridge
TheWatcherBridge is the component that connects the ChatCLI server to the operator:
- Polling: Queries
GetAlertsfrom the server every 30 seconds - Discovery: Locates the server via Instance CRs (first Instance with a ready gRPC endpoint)
- Dedup: SHA256 hash of type+deployment+namespace (no temporal component β a continuous problem generates only one Anomaly). 2-hour TTL
- Dedup invalidation: When an Issue reaches a terminal state (Resolved/Escalated), dedup entries for the resource are removed, allowing immediate recurrence detection
- Pruning: Removes expired hashes automatically (> 2h)
- Creation: Converts alerts to Anomaly CRs with valid K8s names
Usage Examples
- Minimal (no AIOps)
- Full AIOps
- With Fallback Multi-Provider
- Manual Runbook (optional)
- API Keys Secret
Status and Monitoring
Check Instances
Check Instances
Check Active Issues
Check Active Issues
Check AI Insights
Check AI Insights
Check Remediation Plans
Check Remediation Plans
Check PostMortems
Check PostMortems
Check Anomalies
Check Anomalies
Development
Security
The Operator implements multiple security layers by default, following the fail-closed principle (deny by default):REST API Authentication
The REST API operates in fail-closed mode by default β there is no dev mode without authentication. Every request must include a validX-API-Key header with a mapped role (viewer/operator/admin).
API keys are loaded with the following priority order and hot-reloaded every 30 seconds:
- Secret
chatcli-operator-secrets(priority) βapi-keysfield containing a YAML list of{key, role, description}entries - ConfigMap
chatcli-operator-config(fallback) β sameapi-keysfield - Reject the request (or accept in dev-mode if
CHATCLI_OPERATOR_DEV_MODE=true)
Two distinct Secrets in this project β do not confuse it with the LLM provider keys consumed by the chatcli server (
chatcli-api-keys, referenced via Instance.spec.apiKeys.name). See the comparison table in Security β Operator Authentication.The chatcli-operator-secrets Secret must live in the same namespace as the operator pod (the controller resolves it via the POD_NAMESPACE env var / ServiceAccount namespace file, falling back to chatcli-system). If you ran helm install --namespace <X>, create the Secret in <X>.Resource Type Allowlist
The Operator classifies Kubernetes resource types into two categories:- 17 Safe Types (allowed)
- 18 Dangerous Types (blocked)
Pods, Deployments, StatefulSets, DaemonSets, Services, ConfigMaps, Ingresses, Jobs, CronJobs, ReplicaSets, Endpoints, PersistentVolumeClaims, HorizontalPodAutoscalers, NetworkPolicies, ServiceAccounts, Namespaces, Events.
Log Scrubbing
Before sending application logs to the LLM for analysis, the Operator removes 18 sensitive patterns, including:- JWT/Bearer tokens, API keys, passwords
- Email addresses, internal IPs, URLs with credentials
- Credit card numbers, SSNs, PEM certificates
TLS and RBAC
- TLS 1.3 required on all ChatCLI server connections
- ClusterRoles with least privilege (read-only by default)
- NetworkPolicy configurable to restrict network traffic to the Operator namespace
- H5 hardening β no runtime RBAC escalation: the operator never creates or mutates
ClusterRole/ClusterRoleBindingat runtime. Shared ClusterRoles (chatcli-watcher,chatcli-role-*) are pre-provisioned by the Helm chart, and the operatorβs SA holds thebindverb restricted to those exact names viaresourceNames. A compromised operator cannot reference a more-privileged ClusterRole from a newClusterRoleBinding.
Audit
- AuditEvent CRD for immutable audit trail (append-only)
- Structured logs with Request ID for correlation
- Integration with
CHATCLI_AUDIT_LOG_PATHviaextraEnv
Next Steps
AIOps Platform
Deep-dive into the AIOps architecture
K8s Watcher
Collection and budget details
Server Mode
GetAlerts and AnalyzeIssue RPCs
K8s Monitoring
Recipe: K8s Monitoring with AI