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)