DEV Community

Cheedge Lee
Cheedge Lee

Posted on • Originally published at notes-renovation.hashnode.dev

Sidecar container simplified examples

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: {}
Enter fullscreen mode Exit fullscreen mode
  • The nginx app writes logs to /var/log/nginx.
    • default logs: access.log record the access messages; error.log record error messages.
  • 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" "-"
Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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 install vim or nano 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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: {}
Enter fullscreen mode Exit fullscreen mode

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"]

Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)