Skip to main content

Monitoring & Observability

This guide covers the monitoring and observability features of DR-Syncer, including Prometheus metrics, Kubernetes events, alerting recommendations, and troubleshooting patterns.

Overview​

DR-Syncer provides comprehensive observability through three channels:

ChannelPurposeAccess Method
Prometheus MetricsQuantitative performance data/metrics endpoint on port 8080
Kubernetes EventsWorkflow progress and issueskubectl get events
Controller LogsDetailed debugging informationkubectl logs

Prometheus Metrics​

DR-Syncer exposes custom Prometheus metrics for monitoring PVC synchronization operations. The metrics endpoint is available at :8080/metrics on the controller pod.

Metrics Reference​

Transfer Metrics​

MetricTypeLabelsDescription
dr_syncer_pvc_sync_bytes_transferred_totalCounternamespace, pvc_name, destination_namespaceTotal bytes transferred during PVC sync operations
dr_syncer_pvc_sync_files_transferred_totalCounternamespace, pvc_name, destination_namespaceTotal files transferred during PVC sync operations
dr_syncer_pvc_sync_speed_bytes_per_secondGaugenamespace, pvc_name, destination_namespaceCurrent transfer speed in bytes per second

Progress Metrics​

MetricTypeLabelsDescription
dr_syncer_pvc_sync_progress_percentGaugenamespace, pvc_name, destination_namespaceCurrent sync progress percentage (0-100)
dr_syncer_pvc_sync_duration_secondsHistogramnamespace, pvc_name, destination_namespace, statusDuration of PVC sync operations
dr_syncer_pvc_sync_operations_totalCounternamespace, pvc_name, destination_namespace, statusTotal number of sync operations by status

Queue Metrics​

MetricTypeLabelsDescription
dr_syncer_pvc_sync_queue_depthGauge-Number of PVC syncs waiting in queue
dr_syncer_pvc_sync_concurrent_countGauge-Number of PVC syncs currently running
dr_syncer_pvc_sync_queue_wait_secondsHistogram-Time spent waiting in queue before sync starts

Histogram Buckets​

The dr_syncer_pvc_sync_duration_seconds histogram uses exponential buckets optimized for sync operations:

Buckets: 1s, 2s, 4s, 8s, 16s, 32s, 64s, 128s, 256s, 512s, 1024s, 2048s, 4096s, 8192s, 16384s
Range: 1 second to ~4.5 hours

Metrics Endpoint Configuration​

The metrics endpoint is configured in the Helm values:

# values.yaml
controller:
metricsAddr: ":8080"

Example Prometheus Queries​

Sync Throughput​

# Average sync speed across all PVCs (MB/s)
avg(dr_syncer_pvc_sync_speed_bytes_per_second) / 1024 / 1024

# Total data transferred in last hour (GB)
increase(dr_syncer_pvc_sync_bytes_transferred_total[1h]) / 1024 / 1024 / 1024

# Files synced per minute
rate(dr_syncer_pvc_sync_files_transferred_total[5m]) * 60

Sync Performance​

# 95th percentile sync duration
histogram_quantile(0.95, rate(dr_syncer_pvc_sync_duration_seconds_bucket[1h]))

# Average sync duration by PVC
avg by (pvc_name) (rate(dr_syncer_pvc_sync_duration_seconds_sum[1h]) / rate(dr_syncer_pvc_sync_duration_seconds_count[1h]))

# Sync success rate
sum(rate(dr_syncer_pvc_sync_operations_total{status="success"}[1h])) / sum(rate(dr_syncer_pvc_sync_operations_total[1h])) * 100

Queue Health​

# Current queue depth
dr_syncer_pvc_sync_queue_depth

# Queue wait time 95th percentile
histogram_quantile(0.95, rate(dr_syncer_pvc_sync_queue_wait_seconds_bucket[1h]))

# Concurrent syncs vs limit
dr_syncer_pvc_sync_concurrent_count

Kubernetes Events​

DR-Syncer emits Kubernetes events on source PVCs during synchronization workflows. Events provide real-time visibility into sync progress and are the fastest way to monitor operations.

Event Reference​

Event ReasonTypeDescription
SyncStartedNormalSync workflow has begun for this PVC
LockAcquiredNormalDistributed lock acquired for this PVC
RsyncPodDeployedNormalRsync pod deployed in destination cluster
SSHConnectedNormalSSH connectivity established to source agent
SyncCompletedNormalSync completed successfully
SyncSkippedNormalSync skipped (PVC locked, not mounted, etc.)
LockReleasedNormalDistributed lock released
SyncFailedWarningSync operation failed

Viewing Events​

# View all DR-Syncer events in a namespace
kubectl get events -n <namespace> --field-selector reason=SyncStarted,reason=SyncCompleted,reason=SyncFailed

# Watch events in real-time
kubectl get events -n <namespace> -w | grep -E 'Sync|Lock|SSH|Rsync'

# View events for a specific PVC
kubectl describe pvc <pvc-name> -n <namespace> | grep -A 20 Events

# View recent events across all namespaces
kubectl get events -A --sort-by='.lastTimestamp' | grep dr-syncer

Event Sequence Examples​

Successful Sync Workflow​

LAST SEEN   TYPE     REASON            OBJECT                          MESSAGE
2m Normal SyncStarted persistentvolumeclaim/data-pvc Starting PVC sync to dr-cluster/data-pvc
2m Normal LockAcquired persistentvolumeclaim/data-pvc Acquired sync lock (lease dr-syncer-pvc-data-pvc)
90s Normal RsyncPodDeployed persistentvolumeclaim/data-pvc Rsync pod deployed in destination cluster
60s Normal SSHConnected persistentvolumeclaim/data-pvc SSH connection established to agent on node-1
10s Normal LockReleased persistentvolumeclaim/data-pvc Released sync lock
10s Normal SyncCompleted persistentvolumeclaim/data-pvc Sync completed: 1.5GB transferred in 1m50s

Failed Sync​

LAST SEEN   TYPE      REASON      OBJECT                          MESSAGE
30s Warning SyncFailed persistentvolumeclaim/data-pvc Sync failed: rsync error: connection refused

Skipped Sync​

LAST SEEN   TYPE     REASON       OBJECT                          MESSAGE
15s Normal SyncSkipped persistentvolumeclaim/data-pvc PVC locked by another sync operation

Critical Alerts​

groups:
- name: dr-syncer-critical
rules:
# Sync failure rate exceeds threshold
- alert: DRSyncerHighFailureRate
expr: |
sum(rate(dr_syncer_pvc_sync_operations_total{status="failed"}[15m]))
/ sum(rate(dr_syncer_pvc_sync_operations_total[15m])) > 0.1
for: 5m
labels:
severity: critical
annotations:
summary: "DR-Syncer sync failure rate exceeds 10%"
description: "{{ $value | humanizePercentage }} of PVC syncs are failing"

# No syncs completing for extended period
- alert: DRSyncerNoSyncsCompleting
expr: |
sum(increase(dr_syncer_pvc_sync_operations_total{status="success"}[30m])) == 0
and sum(dr_syncer_pvc_sync_queue_depth) > 0
for: 15m
labels:
severity: critical
annotations:
summary: "DR-Syncer syncs are stalled"
description: "No syncs have completed in 30 minutes while queue has pending items"

# Controller pod not running
- alert: DRSyncerControllerDown
expr: |
absent(up{job="dr-syncer-controller"}) == 1
for: 5m
labels:
severity: critical
annotations:
summary: "DR-Syncer controller is down"
description: "The DR-Syncer controller pod is not responding"

Warning Alerts​

groups:
- name: dr-syncer-warning
rules:
# High queue depth
- alert: DRSyncerQueueBacklog
expr: dr_syncer_pvc_sync_queue_depth > 50
for: 15m
labels:
severity: warning
annotations:
summary: "DR-Syncer sync queue backlog"
description: "{{ $value }} PVCs waiting in sync queue"

# Long queue wait times
- alert: DRSyncerLongQueueWait
expr: |
histogram_quantile(0.95, rate(dr_syncer_pvc_sync_queue_wait_seconds_bucket[15m])) > 600
for: 10m
labels:
severity: warning
annotations:
summary: "DR-Syncer queue wait time is high"
description: "95th percentile queue wait is {{ $value | humanizeDuration }}"

# Slow sync operations
- alert: DRSyncerSlowSyncs
expr: |
histogram_quantile(0.95, rate(dr_syncer_pvc_sync_duration_seconds_bucket[1h])) > 3600
for: 30m
labels:
severity: warning
annotations:
summary: "DR-Syncer sync operations are slow"
description: "95th percentile sync duration is {{ $value | humanizeDuration }}"

# Approaching concurrency limit
- alert: DRSyncerConcurrencyNearLimit
expr: dr_syncer_pvc_sync_concurrent_count > 0.9 * dr_syncer_global_concurrency_limit
for: 30m
labels:
severity: warning
annotations:
summary: "DR-Syncer near concurrency limit"
description: "{{ $value }} of {{ $labels.limit }} concurrent syncs running"

Informational Alerts​

groups:
- name: dr-syncer-info
rules:
# Large data transfer
- alert: DRSyncerLargeTransfer
expr: |
increase(dr_syncer_pvc_sync_bytes_transferred_total[1h]) > 100 * 1024 * 1024 * 1024
labels:
severity: info
annotations:
summary: "DR-Syncer transferred over 100GB in last hour"
description: "{{ $value | humanize1024 }}B transferred"

# Sync completed after long duration
- alert: DRSyncerLongSyncCompleted
expr: |
dr_syncer_pvc_sync_duration_seconds_bucket{le="7200", status="success"} == 0
and dr_syncer_pvc_sync_duration_seconds_bucket{le="+Inf", status="success"} > 0
labels:
severity: info
annotations:
summary: "DR-Syncer completed sync after 2+ hours"
description: "Long-running sync completed for {{ $labels.pvc_name }}"

Grafana Dashboard​

Dashboard JSON Overview​

Create a Grafana dashboard with the following panels:

Row 1: Overview​

PanelTypeQuery
Sync Success RateStatsum(rate(dr_syncer_pvc_sync_operations_total{status="success"}[1h])) / sum(rate(dr_syncer_pvc_sync_operations_total[1h])) * 100
Active SyncsStatdr_syncer_pvc_sync_concurrent_count
Queue DepthStatdr_syncer_pvc_sync_queue_depth
Data Transferred (24h)Statsum(increase(dr_syncer_pvc_sync_bytes_transferred_total[24h]))

Row 2: Transfer Performance​

PanelTypeQuery
Transfer SpeedTime Seriesavg(dr_syncer_pvc_sync_speed_bytes_per_second) / 1024 / 1024
Bytes TransferredTime Seriesrate(dr_syncer_pvc_sync_bytes_transferred_total[5m])
Files TransferredTime Seriesrate(dr_syncer_pvc_sync_files_transferred_total[5m])

Row 3: Sync Duration​

PanelTypeQuery
Sync Duration HeatmapHeatmaprate(dr_syncer_pvc_sync_duration_seconds_bucket[5m])
Duration PercentilesTime Serieshistogram_quantile(0.50/0.90/0.95/0.99, rate(...))

Row 4: Queue Health​

PanelTypeQuery
Queue Wait TimeTime Serieshistogram_quantile(0.95, rate(dr_syncer_pvc_sync_queue_wait_seconds_bucket[5m]))
Concurrent vs LimitGaugedr_syncer_pvc_sync_concurrent_count with threshold

Row 5: Operations by Status​

PanelTypeQuery
Operations by StatusPie Chartsum by (status) (increase(dr_syncer_pvc_sync_operations_total[24h]))
Failed SyncsTabletopk(10, increase(dr_syncer_pvc_sync_operations_total{status="failed"}[24h]))

Importing the Dashboard​

  1. Navigate to Grafana → Dashboards → Import
  2. Upload JSON file or paste JSON content
  3. Select Prometheus data source
  4. Save dashboard

Log Analysis Patterns​

Controller Log Structure​

DR-Syncer uses structured JSON logging. Key fields:

FieldDescription
levelLog level (info, error, debug)
msgLog message
controllerController name (remotecluster, replication)
namespaceKubernetes namespace
nameResource name
errorError message (if present)

Common Log Queries​

Find Sync Errors​

# Using kubectl
kubectl logs -n dr-syncer -l app=dr-syncer -c controller | grep '"level":"error"'

# With jq for structured output
kubectl logs -n dr-syncer -l app=dr-syncer -c controller | jq 'select(.level == "error")'

# Find specific PVC errors
kubectl logs -n dr-syncer -l app=dr-syncer -c controller | jq 'select(.msg | contains("pvc-name"))'

Track Sync Progress​

# Follow sync operations
kubectl logs -n dr-syncer -l app=dr-syncer -c controller -f | grep -E 'sync|rsync|transfer'

# Filter by namespace
kubectl logs -n dr-syncer -l app=dr-syncer -c controller | jq 'select(.namespace == "production")'

Debug Connection Issues​

# SSH connection problems
kubectl logs -n dr-syncer -l app=dr-syncer -c controller | grep -i ssh

# Agent connectivity
kubectl logs -n dr-syncer -l app=dr-syncer -c controller | grep -i 'agent\|connection'

# Cluster connectivity
kubectl logs -n dr-syncer -l app=dr-syncer -c controller | grep -i 'remote\|cluster'

Log Level Configuration​

Enable debug logging for troubleshooting:

# Update controller deployment
kubectl set env deployment/dr-syncer-controller -n dr-syncer LOG_LEVEL=debug

# Or via Helm
helm upgrade dr-syncer dr-syncer/dr-syncer \
--namespace dr-syncer \
--set controller.logLevel=debug

Log Aggregation Integration​

For centralized logging, DR-Syncer logs are compatible with:

SystemConfiguration
Elasticsearch/KibanaJSON logs parsed automatically
Loki/GrafanaUse json parser in LogQL
SplunkJSON sourcetype with automatic field extraction
CloudWatchJSON format with Insights queries

Example Loki LogQL:

{namespace="dr-syncer", app="dr-syncer"} | json | level="error"

ServiceMonitor Configuration​

If using Prometheus Operator, create a ServiceMonitor:

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: dr-syncer
namespace: dr-syncer
labels:
app: dr-syncer
spec:
selector:
matchLabels:
app: dr-syncer
endpoints:
- port: metrics
interval: 30s
path: /metrics
namespaceSelector:
matchNames:
- dr-syncer

Service Configuration​

Ensure the controller Service exposes the metrics port:

apiVersion: v1
kind: Service
metadata:
name: dr-syncer-controller-metrics
namespace: dr-syncer
labels:
app: dr-syncer
spec:
ports:
- name: metrics
port: 8080
targetPort: 8080
protocol: TCP
selector:
app: dr-syncer

Health Endpoints​

The controller exposes health endpoints:

EndpointPortPurpose
/healthz8081Liveness probe
/readyz8081Readiness probe
/metrics8080Prometheus metrics

Kubernetes Probe Configuration​

livenessProbe:
httpGet:
path: /healthz
port: 8081
initialDelaySeconds: 15
periodSeconds: 20

readinessProbe:
httpGet:
path: /readyz
port: 8081
initialDelaySeconds: 5
periodSeconds: 10

Troubleshooting with Metrics​

Diagnosing Slow Syncs​

  1. Check queue metrics: High queue_depth with low concurrent_count suggests bottleneck
  2. Check transfer speed: Low speed_bytes_per_second indicates network or storage issues
  3. Check duration histogram: Identify which percentile is problematic

Diagnosing Failed Syncs​

  1. Check events: kubectl get events --field-selector reason=SyncFailed
  2. Check failure count: Rising operations_total{status="failed"} counter
  3. Check controller logs: Filter for error level messages

Diagnosing Queue Buildup​

  1. Check concurrent limit: Compare concurrent_count vs configured limit
  2. Check wait time: High queue_wait_seconds indicates limit too low
  3. Check sync duration: Long syncs may be blocking queue