Skip to content
Last9
Book demo

CAST AI Audit Logs

Ship CAST AI Kubernetes cost-optimization audit logs to Last9 via OpenTelemetry

Stream CAST AI audit events — cluster connections, autoscaling decisions, configuration changes, user actions — into Last9 using CAST AI’s custom OpenTelemetry Collector.

Prerequisites

  • Kubernetes cluster with kubectl and Helm v3.14+
  • CAST AI API key with Audit Log read scope (CAST AI docs)
  • CAST AI cluster ID (optional; restricts events to a single cluster)
  • Last9 OTLP endpoint and Basic auth header (region-specific) from Integrations → OpenTelemetry

Installation

Add the CAST AI Helm repository:

helm repo add castai-helm https://castai.github.io/helm-charts
helm repo update castai-helm

Save the following as values.yaml:

castai:
apiKey: ""
clusterID: ""
apiURL: "https://api.cast.ai"
config:
receivers:
castai_audit_logs:
api:
url: ${env:CASTAI_API_URL}
key: ${env:CASTAI_API_KEY}
poll_interval_sec: 30
page_limit: 100
storage:
type: "persistent"
filename: "/var/lib/otelcol/file_storage/audit_logs_poll_data.json"
filters:
cluster_id: ${env:CASTAI_CLUSTER_ID}
processors:
transform:
error_mode: ignore
log_statements:
- context: log
statements:
- set(body, String(attributes["event"])) where IsMap(attributes["event"])
- delete_key(attributes, "event") where IsMap(attributes)
- set(time, observed_time)
resource:
attributes:
- key: service.name
value: castai-audit-logs
action: upsert
batch:
timeout: 5s
send_batch_size: 100
exporters:
otlphttp/last9:
endpoint: "<your-last9-otlp-endpoint>"
encoding: json
headers:
Authorization: "<your-last9-otlp-basic-auth>"
extensions:
health_check:
endpoint: "0.0.0.0:13133"
service:
extensions: [health_check]
telemetry:
logs:
level: info
pipelines:
logs:
receivers: [castai_audit_logs]
processors: [transform, resource, batch]
exporters: [otlphttp/last9]

Install the chart:

helm install audit-logs castai-helm/castai-audit-logs-receiver \
--namespace castai-logs --create-namespace \
--set castai.apiKey="$CASTAI_API_KEY" \
--set castai.clusterID="$CASTAI_CLUSTER_ID" \
--set-string "config.exporters.otlphttp/last9.endpoint=$LAST9_OTLP_ENDPOINT" \
--set-string "config.exporters.otlphttp/last9.headers.Authorization=$LAST9_OTLP_AUTH" \
--values values.yaml

Why the transform processor is required

The CAST AI receiver emits each audit event as an OTel LogRecord where the full event payload sits under Attributes["event"]. The Body, service.name, and Timestamp fields are not populated by default. Without the transform and resource processors above, records reach Last9 but are not indexed in a way that surfaces them via standard queries.

StatementPurpose
set(body, String(attributes["event"]))Serialize the event payload into LogRecord.Body so Last9 indexes the content.
delete_key(attributes, "event")Avoid duplicating the full event payload in both Body and Attributes.
set(time, observed_time)The receiver emits LogRecord.Timestamp as 0 (Unix epoch) for audit events, so records land outside every recent-time query window in Last9 and stay invisible. Override to the observed (ingestion) timestamp.
resource processor upsert of service.nameThe receiver does not set service.name. Without it, records cannot be filtered by service.

The encoding: json exporter option ensures the OTLP/HTTP payload uses the JSON variant.

Verification

kubectl get pods -n castai-logs
kubectl logs -n castai-logs audit-logs-castai-audit-logs-receiver-0 --tail=50

Look for processing new audit log entries. Then query the Logs Explorer with:

service.name = "castai-audit-logs"

Trigger a new audit event by performing any action in the CAST AI console — creating a node template, changing an autoscaler policy, or reconnecting a cluster — and confirm it appears in Last9 within one poll cycle.

Troubleshooting

invalid api access key, response code: 403 The CAST AI API key is missing the Audit Log read scope. Create a new key in the CAST AI console with that scope and run helm upgrade --reuse-values --set castai.apiKey=<new-key>.

No audit events visible in Last9 Verify all four fixes are present in the config: body set, time overridden, service.name upserted, exporter encoding: json. Without any one of these, events are accepted by Last9 (HTTP 200 {"partialSuccess":{}}) but not retrievable via the Logs Explorer.

Pod restarts with config unmarshal errors The CAST AI audit-logs-receiver image ships a restricted set of OpenTelemetry Collector components. Supported exporters are otlp_http (alias otlphttp), coralogix, datadog, splunk_hec, debug, and file. The gRPC otlp exporter is not available; use otlphttp for Last9.

Uninstall

helm uninstall audit-logs -n castai-logs
kubectl delete namespace castai-logs

References