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.
Use Cases
Section titled “Use Cases”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.
HCL Syntax
Section titled “HCL Syntax”Basic Syntax
Section titled “Basic Syntax”resource "sidecar" "proxy" { target = resource.container.app
image { name = "envoy:latest" }}
Full Syntax
Section titled “Full Syntax”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 } }}
Fields
Section titled “Fields”Field | Required | Type | Description |
---|---|---|---|
target | ✓ | reference to container | Reference to the target container this sidecar runs alongside |
image | ✓ | block | Container image configuration |
entrypoint | list(string) | Override the container’s entrypoint | |
command | list(string) | Command arguments to pass to the container | |
environment | map(string) | Environment variables to set in the container | |
labels | map(string) | Labels to apply to the container | |
privileged | bool | Whether to run the container in privileged mode | |
max_restart_count | number | Maximum number of times to restart the container on failure | |
volume | block | Volume mounts (repeatable) | |
resources | block | Resource constraints | |
health_check | block | Health check configuration |
Image Configuration
Section titled “Image Configuration”sidecar → image
Configures the Docker image to use for the sidecar container.
Field | Required | Type | Description |
---|---|---|---|
name | ✓ | string | Image name and tag (e.g., “nginx:latest”, “docker.io/library/redis:6”) |
username | string | Username for private registry authentication | |
password | string | Password for private registry authentication |
Volume Configuration
Section titled “Volume Configuration”sidecar → volume
Configures volume mounts for the sidecar container. This block can be repeated to mount multiple volumes.
Field | Required | Type | Description |
---|---|---|---|
source | ✓ | string | Source path on the host (relative paths are relative to the HCL file) |
destination | ✓ | string | Destination path inside the container (must be absolute) |
type | string | Volume type: “bind”, “volume”, or “tmpfs”. Defaults to “bind”. | |
read_only | bool | Whether the volume should be read-only | |
bind_propagation | string | Bind propagation mode: “shared”, “private”, “slave”, “rslave”, “rprivate” | |
bind_propagation_non_recursive | bool | Whether to use non-recursive bind mounting | |
selinux_relabel | string | SELinux relabeling mode: “shared” or “private” |
Resource Constraints
Section titled “Resource Constraints”sidecar → resources
Configures CPU, memory, and GPU resource limits for the sidecar container.
Field | Required | Type | Description |
---|---|---|---|
cpu | number | CPU limit in MHz (1000 = 1 CPU core) | |
cpu_pin | list(number) | Pin container to specific CPU cores | |
memory | number | Memory limit in megabytes | |
gpu | block | GPU resource allocation |
GPU Configuration
Section titled “GPU Configuration”Configures GPU resource allocation for the sidecar container.
Field | Required | Type | Description |
---|---|---|---|
driver | ✓ | string | GPU driver to use (e.g., “nvidia”) |
device_ids | ✓ | list(string) | GPU device IDs to allocate |
Health Monitoring
Section titled “Health Monitoring”sidecar → health_check
Configures health checks to monitor sidecar status and availability.
Field | Required | Type | Description |
---|---|---|---|
timeout | ✓ | string | Maximum time to wait for health check (e.g., ”30s”, “2m”) |
http | block | HTTP health check (repeatable) | |
tcp | block | TCP health check (repeatable) | |
exec | block | Execute command health check (repeatable) |
HTTP Health Check
Section titled “HTTP Health Check”sidecar → health_check → http
Defines an HTTP-based health check that sends requests to specified endpoints.
Field | Required | Type | Description |
---|---|---|---|
address | ✓ | string | URL to check |
method | string | HTTP method to use. Defaults to “GET”. | |
body | string | Request body to send | |
headers | map(list(string)) | HTTP headers to send | |
success_codes | list(number) | HTTP status codes that indicate success. Defaults to [200]. |
TCP Health Check
Section titled “TCP Health Check”sidecar → health_check → tcp
Defines a TCP-based health check that verifies network connectivity.
Field | Required | Type | Description |
---|---|---|---|
address | ✓ | string | Address to check (e.g., “localhost:8080”) |
Exec Health Check
Section titled “Exec Health Check”sidecar → health_check → exec
Defines a command-based health check that executes a script or command to determine sidecar health.
Field | Required | Type | Description |
---|---|---|---|
command | list(string) | Command to execute | |
script | string | Script to execute | |
exit_code | number | Expected exit code for success. Defaults to 0. |
Computed Attributes
Section titled “Computed Attributes”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 |
Validation Rules
Section titled “Validation Rules”- 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
Examples
Section titled “Examples”Logging Sidecar Example
Section titled “Logging Sidecar Example”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 }}
Proxy Sidecar Example
Section titled “Proxy Sidecar Example”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" } }}
Best Practices
Section titled “Best Practices”- Resource Limits: Set appropriate CPU and memory limits to prevent sidecars from consuming excessive resources
- Health Checks: Configure health checks for critical sidecars to ensure they’re functioning properly
- Volume Mounts: Use read-only mounts when the sidecar only needs to read configuration files
- Image Tags: Always specify explicit image tags rather than using
latest
- Target Dependencies: Ensure the target container is properly configured before adding sidecars
- Single Responsibility: Keep each sidecar focused on a single function (logging, monitoring, proxying)
- Shared Volumes: Use shared volumes to facilitate communication between the main container and sidecar