In modern micro service architectures, applications are decomposed into small, independently deployable services. While this brings tremendous benefits in agility and scalability, it also introduces cross-cutting concerns—logging, monitoring, security proxying, configuration reloading, and more—that must be uniformly applied across services. Embedding these capabilities directly into each service leads to duplicated code, increased complexity, and tighter coupling.
The Sidecar Pattern offers a solution by offloading these auxiliary tasks to a companion container within the same Kubernetes Pod. This pattern, stable in Kubernetes v1.33 as of recent documentation, allows sidecars to share the Pod’s network namespace, filesystem volumes, and lifecycle, ensuring tight operational proximity while isolating supporting capabilities. Think of it as a motorcycle sidecar: the rider (main app) focuses on the journey, while the sidecar (logger, proxy, or agent) carries the tools.
shareProcessNamespace: true
and shared volumes, as demonstrated by lightweight tools like config-reloader-sidecar
.Let’s walk through a simple, yet powerful implementation:
app.py
The Flask application writes every incoming request to /var/log/app.log
, which is backed by a shared volume:
# app.py
from flask import Flask, request
import os
app = Flask(__name__)
LOG_PATH = "/var/log/app.log"
@app.route("/")
def hello():
log_msg = f"Request: {request.method} {request.path}\n"
with open(LOG_PATH, "a") as log_file:
log_file.write(log_msg)
return "Hello from Flask with Sidecar Logging!: v1"
if __name__ == "__main__":
os.makedirs("/var/log", exist_ok=True)
app.run(host="0.0.0.0", port=5000)
apiVersion: apps/v1
kind: Deployment
metadata:
name: flask-sidecar-logger
spec:
replicas: 1
selector:
matchLabels:
app: flask-logger-demo
template:
metadata:
labels:
app: flask-logger-demo
spec:
volumes:
- name: shared-logs
emptyDir: {}
containers:
- name: app
image: safeeraccuknox/demo:flask-sidecar
imagePullPolicy: Always
ports:
- containerPort: 5000
volumeMounts:
- name: shared-logs
mountPath: /var/log
- name: log-tailer-sidecar
image: busybox
volumeMounts:
- name: shared-logs
mountPath: /var/log
command: ["/bin/sh", "-c", "while true; do echo '--- Sidecar Log Dump ---'; cat /var/log/app.log; sleep 60; done"]
---
apiVersion: v1
kind: Service
metadata:
name: flask-logger-service
labels:
app: flask-logger-demo
spec:
selector:
app: flask-logger-demo
ports:
- protocol: TCP
port: 80
targetPort: 5000
type: ClusterIP
kubectl apply -f deployment.yaml
kubectl port-forward service/flask-logger-service 8080:80
Then visit:
http://localhost:8080/
kubectl logs -l app=flask-logger-demo -c log-tailer-sidecar
We’ve now successfully decoupled logging logic from the application.