Skip to content

Sidecar

The sidecar resource creates a supplementary container that runs alongside a target container. Sidecars are commonly used for logging, monitoring, proxying, or other supporting services that complement the main application container.

As a lab author, you can use sidecars to enhance your lab environment without modifying main application containers:

  • Add Observability: Attach log collectors (e.g. Fluent Bit), metrics exporters (e.g. Prometheus node-exporter), or APM agents to demonstrate monitoring without changing your app
  • Provide Development Tools: Add debugging containers, code hot-reload watchers, or development proxies to create better learning experiences
  • Simulate Production Patterns: Include service mesh proxies (e.g. Envoy), load balancers, or security scanners to show real-world architectures
  • Database Utilities: Add connection poolers, query analyzers, or backup tools alongside database containers for comprehensive database labs
  • Network Debugging: Include network diagnostic tools (e.g. tcpdump, curl, nmap) as sidecars for troubleshooting exercises
  • File Processing: Add containers that process logs, transform data, or sync files to demonstrate data pipeline concepts

Sidecars let you create rich, multi-container lab environments that mirror production complexity while keeping your main application containers simple and focused.

resource "sidecar" "proxy" {
target = resource.container.app
image {
name = "envoy:latest"
}
}
resource "sidecar" "monitoring" {
target = resource.container.app
image {
name = "prometheus/node-exporter:latest"
username = "registry_user"
password = "registry_pass"
}
# Container configuration
entrypoint = ["/bin/node_exporter"]
command = ["--path.rootfs=/host"]
privileged = false
max_restart_count = 3
# Environment variables
environment = {
NODE_ID = "worker-1"
METRICS_PORT = "9100"
}
# Labels
labels = {
service = "monitoring"
component = "exporter"
}
# Volume mounts
volume {
source = "/proc"
destination = "/host/proc"
type = "bind"
read_only = true
}
volume {
source = "/sys"
destination = "/host/sys"
type = "bind"
read_only = true
}
# Resource constraints
resources {
cpu = 100 # 0.1 CPU
memory = 128 # 128MB
gpu {
driver = "nvidia"
device_ids = ["0"]
}
}
# Health check
health_check {
timeout = "30s"
http {
address = "http://localhost:9100/metrics"
success_codes = [200]
}
tcp {
address = "localhost:9100"
}
exec {
script = <<-EOF
#!/bin/bash
curl -f http://localhost:9100/metrics || exit 1
EOF
}
}
}
FieldRequiredTypeDescription
targetreference to containerReference to the target container this sidecar runs alongside
imageblockContainer image configuration
entrypointlist(string)Override the container’s entrypoint
commandlist(string)Command arguments to pass to the container
environmentmap(string)Environment variables to set in the container
labelsmap(string)Labels to apply to the container
privilegedboolWhether to run the container in privileged mode
max_restart_countnumberMaximum number of times to restart the container on failure
volumeblockVolume mounts (repeatable)
resourcesblockResource constraints
health_checkblockHealth check configuration

sidecar → image

Configures the Docker image to use for the sidecar container.

FieldRequiredTypeDescription
namestringImage name and tag (e.g., “nginx:latest”, “docker.io/library/redis:6”)
usernamestringUsername for private registry authentication
passwordstringPassword for private registry authentication

sidecar → volume

Configures volume mounts for the sidecar container. This block can be repeated to mount multiple volumes.

FieldRequiredTypeDescription
sourcestringSource path on the host (relative paths are relative to the HCL file)
destinationstringDestination path inside the container (must be absolute)
typestringVolume type: “bind”, “volume”, or “tmpfs”. Defaults to “bind”.
read_onlyboolWhether the volume should be read-only
bind_propagationstringBind propagation mode: “shared”, “private”, “slave”, “rslave”, “rprivate”
bind_propagation_non_recursiveboolWhether to use non-recursive bind mounting
selinux_relabelstringSELinux relabeling mode: “shared” or “private”

sidecar → resources

Configures CPU, memory, and GPU resource limits for the sidecar container.

FieldRequiredTypeDescription
cpunumberCPU limit in MHz (1000 = 1 CPU core)
cpu_pinlist(number)Pin container to specific CPU cores
memorynumberMemory limit in megabytes
gpublockGPU resource allocation

sidecarresources → gpu

Configures GPU resource allocation for the sidecar container.

FieldRequiredTypeDescription
driverstringGPU driver to use (e.g., “nvidia”)
device_idslist(string)GPU device IDs to allocate

sidecar → health_check

Configures health checks to monitor sidecar status and availability.

FieldRequiredTypeDescription
timeoutstringMaximum time to wait for health check (e.g., ”30s”, “2m”)
httpblockHTTP health check (repeatable)
tcpblockTCP health check (repeatable)
execblockExecute command health check (repeatable)

sidecarhealth_check → http

Defines an HTTP-based health check that sends requests to specified endpoints.

FieldRequiredTypeDescription
addressstringURL to check
methodstringHTTP method to use. Defaults to “GET”.
bodystringRequest body to send
headersmap(list(string))HTTP headers to send
success_codeslist(number)HTTP status codes that indicate success. Defaults to [200].

sidecarhealth_check → tcp

Defines a TCP-based health check that verifies network connectivity.

FieldRequiredTypeDescription
addressstringAddress to check (e.g., “localhost:8080”)

sidecarhealth_check → exec

Defines a command-based health check that executes a script or command to determine sidecar health.

FieldRequiredTypeDescription
commandlist(string)Command to execute
scriptstringScript to execute
exit_codenumberExpected exit code for success. Defaults to 0.

The following attributes are set by the system after the sidecar is created:

Field Type Description
meta.id string Full resource ID (e.g., resource.sidecar.proxy)
meta.type string Resource type (sidecar)
meta.name string Resource name
container_name string Fully qualified domain name for accessing the sidecar
  • Target requirement: Must reference a valid container resource
  • Volume source paths: Made absolute relative to the config file location
  • Health check timeout: Must be a valid Go duration string (e.g., ”30s”, “2m”)
  • CPU limits: Specified in MHz where 1000 = 1 CPU core
  • Memory limits: Specified in megabytes
resource "container" "app" {
image {
name = "myapp:latest"
}
}
resource "sidecar" "logs" {
target = resource.container.app
image {
name = "fluent/fluent-bit:latest"
}
volume {
source = "./fluent-bit.conf"
destination = "/fluent-bit/etc/fluent-bit.conf"
type = "bind"
read_only = true
}
}
resource "container" "backend" {
image {
name = "backend-service:latest"
}
}
resource "sidecar" "proxy" {
target = resource.container.backend
image {
name = "envoyproxy/envoy:v1.28.0"
}
command = [
"envoy",
"-c", "/etc/envoy/envoy.yaml",
"--service-cluster", "backend",
"--service-node", "backend-proxy"
]
volume {
source = "./envoy.yaml"
destination = "/etc/envoy/envoy.yaml"
type = "bind"
read_only = true
}
health_check {
timeout = "10s"
http {
address = "http://localhost:9901/ready"
success_codes = [200]
}
}
}

Monitoring Sidecar with Resource Constraints

Section titled “Monitoring Sidecar with Resource Constraints”
resource "container" "web" {
image {
name = "nginx:alpine"
}
}
resource "sidecar" "metrics" {
target = resource.container.web
image {
name = "nginx/nginx-prometheus-exporter:latest"
}
command = [
"-nginx.scrape-uri=http://localhost:8080/metrics"
]
resources {
cpu = 50 # 0.05 CPU
memory = 64 # 64MB
}
health_check {
timeout = "5s"
tcp {
address = "localhost:9113"
}
}
}
  1. Resource Limits: Set appropriate CPU and memory limits to prevent sidecars from consuming excessive resources
  2. Health Checks: Configure health checks for critical sidecars to ensure they’re functioning properly
  3. Volume Mounts: Use read-only mounts when the sidecar only needs to read configuration files
  4. Image Tags: Always specify explicit image tags rather than using latest
  5. Target Dependencies: Ensure the target container is properly configured before adding sidecars
  6. Single Responsibility: Keep each sidecar focused on a single function (logging, monitoring, proxying)
  7. Shared Volumes: Use shared volumes to facilitate communication between the main container and sidecar