Sidecar Container: What is it and How to use it (Examples)

Have you ever wanted to add extra functionality to your main container without modifying its code or image? Or wanted to monitor, log, or secure your containerized application without affecting its performance? If so, you need to learn about Kubernetes’ sidecar containers.

In this article, we’ll explore what a sidecar container is and look at some examples of how to use it. We assume that you have a basic understanding of Kubernetes concepts and commands. If not, you can check out our Kubernetes for Absolute Beginners course.

Key Takeaways

  • A sidecar container allows you to run an additional container alongside your main container in the same pod, to perform tasks that enhance the main container.
  • One common use case for sidecar containers is to sync data from a remote source to a local volume that is shared by the main container, such as configuration files, secrets, or certificates.
  • To use sidecar containers in Kubernetes, you need to define a pod with two containers that share the same lifecycle, resources, and network namespace, but have their own file system and process space.

What is a Sidecar Container?

A sidecar container is a design pattern that allows you to run an additional container alongside your main container in the same pod. The sidecar container can perform tasks that complement the main container, such as syncing data from a remote source, collecting and shipping logs, providing health checks and metrics, proxying network traffic, encrypting or decrypting data, or injecting faults for testing.

The sidecar container shares the same lifecycle, resources, and network namespace as the main container but has its own file system and process space. This means that the sidecar container can access the same ports, volumes, and environment variables as the main container but cannot interfere with its execution.

Let us explore two different sidecar use cases using examples.

Prerequisites

To follow along with this article, you will need the following:

  • A Kubernetes cluster with at least one worker node. You can use minikube to create this.
  • A kubectl command-line tool installed and configured to access your cluster.
  • A code editor. We used VS-Code for this example.
  • A basic understanding of Kubernetes concepts and commands.

Try the Kubernetes Deployments Lab for free

Kubernetes Deployments Lab
Kubernetes Deployments Lab

Example 1: Access logs from logfile in main container using sidecar

One basic use case for sidecar containers is to access logs from a logfile in the main container using a sidecar container. For example, you might want to tail the logs from the main container and print them to the standard output.

To demonstrate this, we will create a simple application that writes logs to a file every second. The main container will run a busybox image that runs a shell script that generates logs. The sidecar container will run another busybox image that runs tail to read the logs from the file.

First, we need to create a Kubernetes deployment that defines the pod with two containers:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: log-app # Name of the deployment
spec:
  replicas: 1 # Number of replicas
  selector:
    matchLabels:
      app: log-app # Label selector for the pod
  template:
    metadata:
      labels:
        app: log-app # Label for the pod
    spec:
      volumes:
        - name: log-volume # Define a volume to store the logs
          emptyDir: {} # Use an emptyDir volume type
      containers:
        - name: log-generator # Main container
          image: busybox # Use the busybox image
          command: ["/bin/sh"] # Override the default command
          args: ["-c", "while true; do date >> /var/log/app.log; sleep 1; done"] # Run a shell script that generates logs every second
          volumeMounts:
            - name: log-volume # Mount the volume to the container
              mountPath: /var/log # Mount it to the log directory
        - name: log-reader # Sidecar container
          image: busybox # Use another busybox image
          command: ["/bin/sh"] # Override the default command
          args: ["-c", "tail -f /var/log/app.log"] # Run a shell script that tails the log file
          volumeMounts:
            - name: log-volume # Mount the same volume as the main container
              mountPath: /var/log # Mount it to the same directory in the sidecar container

Next, we can apply this YAML file using kubectl:

kubectl apply -f deployment.yaml

After a few minutes, we can check the status of the deployment and pod using kubectl:

kubectl get deployment log-app
kubectl get pod -l app=log-app

We should see something like this:

Verify that the pod has two containers using this command:

kubectl get pods log-app-7f9f8c4b9-6xq8w -o jsonpath='{.spec.containers[*].name}'

This gives the following output:

log-generator log-reader

We can see the pod has two containers, a log-generator, and a log-reader. The log-generator stores its logs in the volume named log-volume. We want to use the log-reader to read the logs stored in log-volume.

To do this, run this command to see the file where log-generator is storing the logs:

kubectl exec -it log-app-7f9f8c4b9-6xq8w -c log-generator -- ls /var/log

This shows the output as follows:

app.log

We can now read the log file above from the log-reader using this command:

kubectl exec -it log-app-7f9f8c4b9-6xq8w -- cat /var/log/app.log

This shows an output similar to this:

The sidecar container prints the logs from the main container's log file to the standard output.

This way, we are using a sidecar container to access logs from a log file in the main container using tail.

Example 2: Access logs from the main container using HTTP in the sidecar

Another basic use case for sidecar containers is to access logs from the main container using HTTP in a sidecar container. For example, you might want to expose an HTTP endpoint that returns the logs from the main container.

To demonstrate this, we will create a simple web server that writes logs to the standard output every second. The main container will run an nginx image that exposes port 80. The sidecar container will run an alpine image that runs socat to listen on port 8080 and return the logs from the main container.

First, we need to create a Kubernetes deployment that defines the pod with two containers:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-server # Name of the deployment
spec:
  replicas: 1 # Number of replicas
  selector:
    matchLabels:
      app: web-server # Label selector for the pod
  template:
    metadata:
      labels:
        app: web-server # Label for the pod
    spec:
      containers:
        - name: nginx # Main container
          image: nginx # Use the nginx image
          ports:
            - containerPort: 80 # Expose port 80
          command: ["/bin/sh"] # Override the default command
          args: ["-c", "while true; do echo \"$(date) Hello from nginx\"; sleep 1; done | tee /var/log/nginx/access.log"] # Run a shell script that generates logs every second and writes them to a file and standard output 
        - name: socat # Sidecar container
          image: alpine/socat # Use the alpine/socat image
          ports:
            - containerPort: 8080 # Expose port 8080
          command: ["socat"] # Override the default command
          args: ["-v", "TCP-LISTEN:8080,fork,reuseaddr", "EXEC:\"kubectl logs web-server-7f9f8c4b9-6xq8w -c nginx\""] # Run socat to listen on port 8080 and execute kubectl logs to return the logs from the main container


Next, we need to create a Kubernetes service that exposes the sidecar container's port to the outside world:

apiVersion: v1
kind: Service
metadata:
  name: web-server-service # Name of the service
spec:
  type: LoadBalancer # Use a load balancer service type
  selector:
    app: web-server # Select pods with this label
  ports:
    - protocol: TCP # Use TCP protocol
      port: 80 # Expose port 80 on the service
      targetPort: 8080 # Map it to port 8080 on the pod

We can apply these YAML files using kubectl:

kubectl apply -f deployment.yaml -f service.yaml

After a few minutes, we can check the status of the deployment, pod, and service using kubectl:

kubectl get deployment web-server
kubectl get pod -l app=web-server
kubectl get service web-server-service

We should see something like this:

We can see that the deployment has one pod with two containers running, and the service has an external IP address assigned by the cloud provider. We can use this IP address to access the logs from the sidecar container from a browser:

To access the logs from the sidecar container from a browser, we can use the external IP address of the service that we obtained. In this case, the external IP address is 35.238.123.123.

We can open a web browser and enter the following URL:

http://35.238.123.123:8080

This will send an HTTP request to the sidecar container, which will proxy the request to the main container and return the logs from the main container’s standard output.

We can also see that the sidecar container is returning the logs from the main container's standard output. The request is proxied by the sidecar container to the main container.

To verify that the request is proxied by the sidecar container to the main container, we can use the command:

kubectl logs web-server-7f9f8c4b9-6xq8w -c socat

We should see something like this:

We can see that socat is listening on port 8080 and accepting a connection from the browser. It then forks a child process and executes kubectl logs to get the logs from the main container named nginx in the pod named web-server-7f9f8c4b9-6xq8w. This way, the sidecar container exposes an HTTP endpoint that returns the logs from the main container.

Why use Kubernetes sidecar container

The sidecar container provides helper functionality to the main container, such as file synchronization, logging, and watcher capabilities.

Sidecars are not part of the main traffic or API of the primary application. They usually operate asynchronously and are not involved in the public API. This way, they can enhance the main container without modifying its code or image.

A common example is a central logging agent. Your main container can just log to stdout, but the sidecar container will send all logs to a central logging service, where they will be aggregated with the logs from the entire system.

Below are some of the benefits of using sidecar containers in Kubernetes:

  • Modularity: You can separate the concerns of different functionalities and avoid modifying the code or image of the main container. This makes your application more modular and easier to maintain and update.
  • Reusability: You can reuse the same sidecar container for different main containers that need the same functionality. This reduces duplication and improves consistency and efficiency.
  • Scalability: You can scale the sidecar container independently of the main container if they have different resource requirements or performance characteristics. This allows you to optimize the resource utilization and performance of your application.
  • Security: You can isolate the sidecar container from the main container using different security policies or network rules. This can help prevent unauthorized access or malicious attacks on your application.

To LEARN Kubernetes concepts with hands-on labs, ENROLL in our Kubernetes Course.

Conclusion

In this article, we learned what sidecar containers are and how to use them in Kubernetes. We saw two examples of how sidecar containers can access logs from the main container and add extra functionality to the main container without modifying its code or image. We also learned how to use YAML files and kubectl commands to create pods with sidecar containers.

We hope you enjoyed this article and learned something new. If you have any questions, please leave your comments below.