Basic K3s Log Collection
Stream logs from all pods and namespaces to S3 with batching.
Pipeline
input:
subprocess:
name: kubectl
args:
- logs
- --all-containers=true
- --prefix=true
- --follow
- --tail=-1
- --all-namespaces
codec: lines
restart_on_exit: true
pipeline:
processors:
- mapping: |
root.raw_log = this
root.timestamp = now()
root.node_id = env("NODE_ID")
root.cluster = env("CLUSTER_NAME").or("k3s-edge")
output:
aws_s3:
bucket: edge-k3s-logs
path: 'logs/${! env("NODE_ID") }/${! timestamp_unix() }.jsonl'
batching:
count: 1000
period: 1m
processors:
- archive:
format: concatenate
What This Does
- Follows logs from all containers in all namespaces using
kubectl logs --follow - Adds metadata: node identifier, cluster name, and timestamp to each log entry
- Batches logs: Collects 1000 logs or waits 1 minute before writing
- Writes to S3: Organizes logs by node and timestamp for easy retrieval
- Auto-restarts: If kubectl process exits, it automatically restarts
Key Configuration
--all-containers=true: Includes logs from all containers in each pod
--prefix=true: Adds [namespace/pod/container] prefix to each log line
--follow: Continuously streams new logs (like tail -f)
restart_on_exit: true: Ensures log collection continues even if kubectl crashes
Batching: Reduces S3 API calls by writing 1000 logs at once instead of individual files
Environment Variables
Set these environment variables where Expanso runs:
NODE_ID: Unique identifier for this edge node (e.g.,edge-site-42)CLUSTER_NAME: Name of the K3s cluster (optional, defaults tok3s-edge)
Next Steps
- Parse Metadata: Extract namespace, pod, and container from log prefix
- Multiple Destinations: Send logs to both S3 and Elasticsearch
- Filter by Log Level: Reduce volume by only collecting errors