Agent Observability Platform: Configuration Reference (AWS)
Optional configuration on AWS β TLS, retention, ClickHouse users, S3 ingest, and sizing
All settings on this page are optional β the defaults produce a working deployment. Set them as inputs to the Terraform module.
Data retention (TTL)
ClickHouse retains trace data for a fixed window, after which old data is dropped automatically.
| Input | Default | Description |
|---|---|---|
clickhouse_ttl_days | 30 | Days of trace data to retain. Governs the trace tables and their conversation-derived annotation tables. Applied cluster-wide by the schema job, so retention can't drift between replicas. |
ClickHouse users
The platform provisions a least-privilege ClickHouse user model β one SQL user per access path, each scoped to exactly the operations it performs:
| User | Access | Used by |
|---|---|---|
schema_owner | Read/write on the telemetry database, plus DDL (including cluster-wide ON CLUSTER statements) and system-table maintenance | The schema-migration job (creates tables, applies TTLs) and the owner (DEFINER) of the materialized views |
otel | Append into the telemetry tables | The OpenTelemetry Collector. Can be tightened to INSERT-only with restrict_grants (see below) |
llm_worker | Read/append on the LLM job-queue tables | The LLM worker |
monte_carlo | Read-only on telemetry, plus append to the job-queue, evaluation-score, and conversation-annotation tables | The Monte Carlo Agent (Trace Exploration, agent monitors, queuing evaluations) β this is the user you connect Monte Carlo as |
probe | system.replicas replication health and SHOW TABLES on the telemetry database (passwordless; no row-level data reads) | The ClickHouse readiness probe β needs no secret or configuration |
readonly_user | SELECT-only (optional) | External SQL clients (e.g. DataGrip), MCP, and the deployment verification script |
admin | Full superuser, including access management (optional, gated) | Break-glass DBA access β reachable only over loopback (pod-exec) by default |
schema_owner, otel, llm_worker, monte_carlo, and probe are always provisioned. readonly_user and admin are opt-in.
Each user's password is generated by the module and stored in AWS Secrets Manager (KMS-encrypted), then synced into the cluster by the External Secrets Operator. Each user has its own secret, exposed as a clickhouse_<user>_credentials_secret_arn output. The exception is probe, which is deliberately passwordless β its consumer is the kubelet's readiness check, which can't read a Kubernetes secret β and so has no Secrets Manager entry. Like the other non-admin users, probe is network-facing rather than loopback-restricted; what it can read is limited to replication-health metadata and table names, with no row data exposed. clickhouse_nlb_allowed_source_ranges (see Network access) governs who can reach it.
The stock ClickHouse
defaultsuperuser is removed during deployment as a hardening measure β every client authenticates as one of the users above.
Read-only user
To provision the optional readonly_user (SELECT-only, profile readonly_settings with readonly = 2 β SELECT plus per-session SET, so JDBC clients such as DataGrip connect cleanly):
helm = {
chart_registry = "oci://registry-1.docker.io/montecarlodata"
chart_version = "4.0.0"
clickhouse = {
readonly_user = {
enabled = true
# password = "..." # optional; omit to auto-generate
}
}
}Its password ARN is exposed as the clickhouse_readonly_user_credentials_secret_arn output.
The module requires
ao-data-platformchart version >= 2.0.0, which provisions the full least-privilege user model (includingreadonly_user).
Ingest user lock-down
otel defaults to read/write so the migration to the monte_carlo user is non-breaking. After Monte Carlo connects as monte_carlo (see Connect to Monte Carlo), set clickhouse.otel.restrict_grants = true to tighten otel to INSERT-only on the raw trace table (otel_traces.otel_traces). Normalization keeps working because the materialized views run as schema_owner, not otel.
Transitional.
restrict_grantsis a migration aid and will be removed onceotelisINSERT-only by default.
Break-glass admin user
The admin superuser is opt-in and, by default, reachable only over loopback (pod-exec) β it is never on a network path. Enable it for break-glass DBA access:
helm = {
chart_registry = "oci://registry-1.docker.io/montecarlodata"
chart_version = "4.0.0"
clickhouse = {
admin = {
enabled = true
# password = "..." # optional; omit to auto-generate
}
}
}Its password ARN is exposed as the clickhouse_admin_credentials_secret_arn output (null when disabled). Requires chart version >= 2.0.0.
Resource sizing
Each managed workload exposes optional Kubernetes resource requests/limits via helm.<workload>.resources. Omit a workload (or a requests/limits map) to use the chart defaults β start modest in development and tune up for production.
helm = {
chart_registry = "oci://registry-1.docker.io/montecarlodata"
chart_version = "4.0.0"
clickhouse = {
resources = {
requests = { cpu = "2", memory = "8Gi" }
limits = { cpu = "4", memory = "16Gi" }
}
}
opentelemetry_collector = {
resources = {
requests = { memory = "2Gi" }
limits = { memory = "6Gi" }
}
}
llm_worker = {
resources = {
requests = { cpu = "500m", memory = "1Gi" }
limits = { cpu = "2", memory = "4Gi" }
}
}
}requests and limits are maps keyed by Kubernetes resource name (cpu, memory, ephemeral-storage, etc.); either can be omitted independently.
Node groups (new-cluster path)
On the new-cluster path, you can size the node groups the workloads run on:
| Input | Default | Description |
|---|---|---|
clickhouse_ha_node_group.instance_type | r6i.xlarge | Instance type for the per-AZ ClickHouse node groups. |
keeper_node_group.instance_type | m6i.large | Instance type for the per-AZ Keeper node groups (deliberately non-burstable β a throttled quorum voter risks spurious leader elections). |
keeper_node_group.storage_size / .storage_class | 10Gi / gp3 | The Keeper persistent volume (Raft log and snapshots only). |
clickhouse_node_group.instance_type | r5.xlarge | Instance type for the legacy single-instance ClickHouse node group. |
cluster.node_instance_type | t3.large | Instance type for the main node group (Collector, LLM worker, controllers). |
cluster.main_node_group_size | 2 | Desired/minimum size of the main node group (set 1 for a cost-optimized single node; max 10). |
The ClickHouse and Keeper node groups pin their AMI version by default; update it deliberately via each node group's ami_release_version β see High availability β node AMI updates.
Workload replicas
| Input | Default | Description |
|---|---|---|
helm.opentelemetry_collector.replica_count | null (chart default) | OpenTelemetry Collector replicas. 0 is not honored β the chart treats it as unset; to stop ingest, pause the senders upstream instead. |
helm.llm_worker.replica_count | null (chart default) | LLM-worker replicas β 0 or 1 only. 0 pauses the worker declaratively (survives applies); set back to resume. |
ClickHouse replicas are controlled by clickhouse_replica_count β see High availability below.
High availability
The topology inputs below deploy the standard HA shape β how it works, the dev/testing single-replica variant, and day-2 operations are covered on the High availability page.
| Input | Default | Description |
|---|---|---|
clickhouse_availability_zones | [] | AZ names for the per-AZ ClickHouse node groups; the list length caps the replica count. |
keeper_availability_zones | [] | AZ names for the Keeper voter node groups β must be an odd count (3 standard, 1 for dev). Also sets the chart's Keeper replica count. |
clickhouse_replica_count | 1 | ClickHouse replicas (2 for the standard HA shape). Terraform-owned: a chart version bump alone never changes it. |
enforce_clickhouse_volume_az_match | true | Migration aid β requires clickhouse_availability_zones[0] to match the AZ of any existing single-instance ClickHouse volume. Most users leave the default. |
manage_legacy_clickhouse_node_group | true | Migration aid β keeps the legacy single-instance ClickHouse node group under module management. Most users leave the default. |
Storage
ClickHouse data is stored on an EBS-backed persistent volume.
| Input | Default | Description |
|---|---|---|
helm.clickhouse.storage_size | 500Gi | Size of the ClickHouse persistent volume. |
clickhouse_storage_class | clickhouse-gp3 | StorageClass for the ClickHouse volume. The module creates a dedicated clickhouse-gp3 class by default; set to an existing class name to use your own. |
storage_class_clickhouse_gp3.iops | 3000 | Provisioned IOPS for the clickhouse-gp3 class (min 3000, max 16000). |
storage_class_clickhouse_gp3.throughput | 125 | Throughput in MB/s for the clickhouse-gp3 class (min 125, max 1000; must be β€ iops Γ 0.25). |
Network access
By default the ClickHouse and OpenTelemetry Collector Network Load Balancers are internal, but accept traffic from any source that can route to them. Restrict the source ranges to harden access:
| Input | Default | Description |
|---|---|---|
clickhouse_nlb_allowed_source_ranges | null (unrestricted) | CIDR ranges permitted to reach the ClickHouse NLB. [] restricts to the VPC. |
otel_collector_nlb_allowed_source_ranges | null (unrestricted) | CIDR ranges permitted to reach the OpenTelemetry Collector NLB. [] restricts to the VPC. |
networking.control_plane_subnet_ids | [] | Existing-cluster only: pins the EKS control-plane subnets when widening existing_private_subnet_ids into a new AZ (a cluster's control-plane AZ set is immutable). See High availability β existing-cluster deployments. |
Both NLBs run with cross-zone routing enabled and their subnet placement pinned to the module's private subnets (one subnet per AZ) β see Harden network access.
These NLB source ranges are the primary network control for reaching ClickHouse β the network-facing ClickHouse users accept connections from any source at the ClickHouse layer. This includes the passwordless
probeuser (metadata-only access to replication health and table names) β one more reason to restrictclickhouse_nlb_allowed_source_ranges. (Theadminsuperuser is the exception: it is loopback-only and never reachable over the NLB.) Leaving the default unrestricted means anyone who can route to the internal NLB can attempt to connect. Setclickhouse_nlb_allowed_source_rangesto your VPC or a specific CIDR list, especially before enablingreadonly_userfor external SQL clients.
TLS
TLS is enabled by default. The OpenTelemetry Collector and ClickHouse NLB endpoints are TLS-terminated using ACM certificates that the module provisions for your otel_collector_domain and clickhouse_domain. Traffic between the Collector and ClickHouse inside the cluster is secured with certificates issued by cert-manager.
Encryption at rest
All persistent data is encrypted at rest by default:
- ClickHouse trace data β the module's
gp3andclickhouse-gp3StorageClasses setencrypted = "true", so the EBS volumes backing ClickHouse and Keeper are encrypted. - Credentials β every ClickHouse-user secret in AWS Secrets Manager is encrypted with a customer-managed KMS key the module creates (
aws_kms_key.pipeline_secrets). - Kubernetes secrets β EKS envelope encryption of etcd secrets is enabled by default on the new-cluster path.
Bring-your-own-key is not exposed for the Secrets Manager or EKS keys (both are module-created). The optional S3 trace-ingest buckets are customer-owned resources, so their encryption at rest is governed by your own bucket configuration.
S3 ingest (OTel Collector awss3 receivers)
awss3 receivers)In addition to its OTLP endpoints, the OpenTelemetry Collector can ingest OTLP traces from objects in one or more S3 buckets, each notified via its own SQS queue. Set helm.opentelemetry_collector.awss3_receivers with one map entry per queue/bucket pair (requires module >= 2.2.0). For every enabled entry, the module:
- Renders an
awss3receiver with component IDawss3/<key>, configured with the supplied SQS URL/region and S3 bucket/region/prefix, and appends it to the trace pipeline so the receiver is actually wired up. - Attaches an inline policy to the
otel-collectorIRSA role grantingsqs:ReceiveMessage/DeleteMessage/GetQueueAttributes/GetQueueUrlon every receiver's queue ands3:GetObject/GetBucketLocationon every receiver's bucket.
helm = {
chart_registry = "oci://registry-1.docker.io/montecarlodata"
chart_version = "4.0.0"
opentelemetry_collector = {
awss3_receivers = {
traces = {
sqs_queue_arn = "arn:aws:sqs:us-east-1:123456789012:otel-traces"
sqs_queue_url = "https://sqs.us-east-1.amazonaws.com/123456789012/otel-traces"
s3_bucket = "acme-otel-traces"
# enabled defaults to true
# sqs_region / s3_region default to var.region
# s3_prefix defaults to ""
}
}
}
}Give each receiver its own dedicated SQS queue β never share a queue. In SQS mode a receiver fetches whatever object each notification names but filters the records against its own configured bucket/prefix, and it deletes messages whose records were all filtered out β so two receivers sharing one queue destroy each other's notifications. Duplicate
sqs_queue_arnvalues across enabled receivers are rejected at plan time. To feed several consumers from one bucket's events, fan the bucket notification out via SNS with a queue per consumer.
Per entry: enabled defaults to true (set false to keep the entry without rendering it); sqs_region and s3_region default to var.region; s3_prefix defaults to "" (any object in the bucket) and is normalized internally to include a single trailing / when non-empty (so "traces" and "traces/" behave identically).
Adding, changing, or removing a receiver changes the collector's rendered config, which rolling-restarts the collector Deployment on apply. (helm.opentelemetry_collector.awss3_receiver β singular β is the deprecated single-receiver form; it keeps working throughout module v2.x but use awss3_receivers for new configuration.)
Evaluation (Amazon Bedrock)
On AWS deployments the LLM worker invokes models through Amazon Bedrock. By default it targets your deployment region.
| Input | Default | Description |
|---|---|---|
helm.llm_worker.bedrock_region | var.region | AWS region for Bedrock API calls. |
helm.llm_worker.image_repository | derived from chart_registry (e.g. registry-1.docker.io/montecarlodata/ao-llm-worker) | Override the LLM-worker image repository. |
helm.llm_worker.image_tag | latest-aws | LLM-worker image tag. The worker image is published with per-cloud tags; latest-aws is a floating tag. Pin a released tag for production β the current release is 1.1.0-aws. |
Updated 1 day ago
