Skip to content

Metrics

The controller exposes Prometheus metrics from the controller-runtime metrics server. With the manifest install the endpoint is enabled on :8443 (HTTPS) behind a Service argocd-terraform-controller-controller-manager-metrics-service in argocd-terraform-controller-system; scraping requires a token with get on the /metrics non-resource URL (the install ships a metrics-reader ClusterRole for that).

Scraping

With the Prometheus Operator, apply the ServiceMonitor from the repository's config/prometheus (it targets the https port and uses the Prometheus ServiceAccount token):

kubectl apply -k "https://github.com/redhat-developer/argocd-terraform-controller/config/prometheus?ref=${VERSION}"
kubectl create clusterrolebinding argocd-terraform-metrics-reader \
  --clusterrole=argocd-terraform-controller-metrics-reader \
  --serviceaccount=monitoring:prometheus-k8s

The shipped ServiceMonitor uses insecureSkipVerify: true for the self-signed serving certificate. For production, mount a certificate from cert-manager into the manager (--metrics-cert-path) and set serverName/ca in the tlsConfig instead — the commented monitor_tls_patch.yaml in the same directory shows the fields.

The install also contains a NetworkPolicy that admits traffic to the metrics port only from namespaces labelled metrics: enabled:

kubectl label namespace monitoring metrics=enabled

To scrape over plain HTTP in a test cluster, pass --metrics-bind-address=:8080 --metrics-secure=false to the manager.

What is exported

Everything controller-runtime provides, labelled with controller="terraform" where applicable:

Metric Use it for
controller_runtime_reconcile_total{result=…} Reconcile rate; result="error" for failing runs
controller_runtime_reconcile_errors_total Errors over time
controller_runtime_reconcile_time_seconds (histogram) How long runs take — Terraform plan/apply duration dominates
controller_runtime_max_concurrent_reconciles Confirms --concurrent
controller_runtime_active_workers How many objects are being reconciled right now (each holds a runner Pod)
workqueue_depth{name="terraform"} Backlog: objects waiting for a worker
workqueue_queue_duration_seconds How long objects wait before a worker picks them up
rest_client_requests_total API server traffic
leader_election_master_status 1 on the active replica
go_*, process_* Runtime health

A useful starting alert set:

- alert: TerraformReconcileErrors
  expr: rate(controller_runtime_reconcile_errors_total{controller="terraform"}[15m]) > 0
  for: 30m
- alert: TerraformBacklog
  expr: workqueue_depth{name="terraform"} > 10
  for: 15m
- alert: TerraformControllerDown
  expr: absent(up{job=~".*argocd-terraform-controller.*"} == 1)
  for: 5m

Per-object status instead of metrics

There are no per-Terraform-object metrics yet (drift count, pending approvals, last apply age). That information is in the object's status and in Argo CD:

  • pending approvals: kubectl get tf -A -o json | jq '.items[] | select(.status.plan.pending != "") | .metadata.name', or the counters at the top of the Terraform dashboard in Argo CD;
  • drift: Ready condition reason DriftDetected, Argo CD health Degraded, and a Warning event with the drift plan;
  • staleness: status.lastSuccessfulReconcileAt, status.lastDriftDetectedAt.

Argo CD's own argocd_app_info{health_status=…} metric therefore reflects Terraform objects too: an Application that contains a Terraform object waiting for approval reports health_status="Suspended", a failing one Degraded. Alerting on Argo CD health is often the simplest way to cover Terraform runs.

Per-object metrics are a reasonable future addition; please open an issue with the labels you would need.