A sidecar container is commonly used in real-world applications to augment the functionality of the primary container. And here we will see some simplified examples of typical sidecar container use cases, along with their scripts or configurations.
1. Logging and Monitoring
Scenario: A sidecar container collects logs from the primary application and sends them to a logging service.
apiVersion: v1
kind: Pod
metadata:
name: logging-sidecar
spec:
containers:
- name: app-container
image: nginx
volumeMounts:
- name: shared-logs
mountPath: /var/log/nginx
- name: log-collector
image: busybox
command: ["sh", "-c", "tail -f /var/log/nginx/access.log"]
volumeMounts:
- name: shared-logs
mountPath: /var/log/nginx
volumes:
- name: shared-logs
emptyDir: {}
- The
nginx
app writes logs to/var/log/nginx
.- default logs:
access.log
record the access messages;error.log
record error messages.
- default logs:
- The
log-collector
sidecar tails the log file and can send it to an external logging service.
# when we access the ngnix
controlplane $ curl 192.168.1.4
# it will record the access msg
controlplane $ k exec -it pods/logging-sidecar -c log-collector -- cat /var/log/nginx/access.log
192.168.1.4 - - [07/Dec/2024:21:34:51 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.88.1" "-"
192.168.0.0 - - [07/Dec/2024:21:35:13 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/7.68.0" "-"
2. Security Proxy
Scenario: A sidecar acts as a proxy to add authentication or encryption to requests before they reach the primary container.
-
main-app
container serves traffic. - Sidecar container intercepts and routes traffic.
apiVersion: v1
kind: Pod
metadata:
name: proxy-sidecar
spec:
containers:
- name: main-app
image: httpd
ports:
- containerPort: 80
- name: envoy-proxy
image: envoyproxy/envoy:v1.27.0
args: ["-c", "/etc/envoy/envoy.yaml"]
ports:
- containerPort: 10000
Then configure envoy.yaml to route traffic. Access the service through the proxy and verify logs in Envoy. The configure file envoy.yaml
can be found here.
And the
envoy-proxy
container not installvim
ornano
editor, so you can use
kubectl cp <local-file-path> <pod-name>:<pod-destination-path> -c <container-name>
kubectl cp <pod-name>:<source-path> <destination-path> -c <container-name>
# eg.
kubectl cp proxy-sidecar:/etc/envoy/envoy.yaml ./envoy.yaml -c envoy-proxy
to copy it outside pod to edit it.
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
proxy-sidecar 2/2 Running 0 13m 192.168.1.4 node01 <none> <none>
controlplane $ curl http://192.168.1.4:10000
The auth-proxy
sidecar intercepts requests to the main-app
, applies authentication, and forwards them.
3. File Synchronization
Scenario: A sidecar container keeps files synchronized between the application and an external storage system:
-
main-app
container save file under/data
-
syncer
sidecar container synchronize it at/backup
apiVersion: v1
kind: Pod
metadata:
name: data-sync-sidecar
spec:
containers:
- name: main-app
image: busybox
command: ["/bin/sh", "-c"]
args: ["echo 'hallo syncer!' > /data/file.txt; sleep 3600"]
volumeMounts:
- name: data-volume
mountPath: /data
- name: syncer
image: alpine
command: ["/bin/sh", "-c"]
args: ["apk add --no-cache rsync; while true; do rsync -av /data/ /backup/; sleep 10; done"]
volumeMounts:
- name: data-volume
mountPath: /data
- name: backup-volume
mountPath: /backup
volumes:
- name: data-volume
emptyDir: {}
- name: backup-volume
emptyDir: {}
The sync-agent
periodically synchronizes files between /data
and /backup
.
4. Initialization with InitContainer
Scenario: A initContainers
init-db
container, which used to init the db provided for main application to use. (The whole yaml file can be checked at this GitHub Repo).
Here we use a busybox
as the main app container, but it just a placeholder. We can run the actual application that relies on the initialization performed by the initContainer. For example, the main container is some web application.
You can check this Repo which is the full yaml file for a flask
app to use the initContainers
container.
apiVersion: v1
kind: Pod
metadata:
name: db-init-pod
spec:
initContainers:
- name: init-db
image: postgres:latest
command: ["sh", "-c"]
args:
- |
until pg_isready -h postgres -U user; do
echo "Waiting for PostgreSQL to be ready...";
sleep 2;
done;
psql -h postgres -U user -d mydb -c "CREATE TABLE IF NOT EXISTS test (id SERIAL PRIMARY KEY, name TEXT);"
env:
- name: PGPASSWORD
value: "password" # Match the PostgreSQL password
containers:
- name: app
image: busybox
command: ["/bin/sh", "-c"]
args: ["echo 'App starting'; sleep 3600"]
And then we can verify Database Initialization by logging into the PostgreSQL container and check for the test
table. or inspect the init-db
logs for progress or errors.
NAME READY STATUS RESTARTS AGE
db-init-pod 1/1 Running 0 33s
postgres-7c8f74d97b-cxdmp 1/1 Running 0 32s
# check the log
controlplane $ k logs db-init-pod -c init-db
# logging into postgres container verify the db
controlplane $ k exec -it postgres-7c8f74d97b-cxdmp -- psql -U user -d mydb -c "\dt"
List of relations
Schema | Name | Type | Owner
--------+------+-------+-------
public | test | table | user
(1 row)
or if you change the busybox
image to what your app used eg. flask
controlplane $ kubectl logs db-init-pod -c init-db
postgres:5432 - no response
Waiting for PostgreSQL to be ready...
postgres:5432 - accepting connections
CREATE TABLE
controlplane $ kubectl logs db-init-pod -c app
And then we can add a svc
to access the Flask application.
Benefits of Sidecars:
The sidecars container has many other usages, such as debugging, caching. And it's better to use a sidecar container, as:
- Modularity: Sidecars add functionality without altering the primary app.
- Scalability: The same sidecar logic can be reused across different apps.
- Separation of Concerns: Keeps application code clean and focused.
Therefore it is a powerful tool for extending functionality while maintaining a clean architecture.
Reference
In official document, we can see more details about the sidecar container.
Also we can check here for the init containers.
Top comments (0)