Kubernetes
CronJob
Sidecar Container
DevOps
Container Orchestration

Kubernetes CronJob with a sidecar container

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

Running a sidecar next to a scheduled task is possible in Kubernetes, but Jobs and CronJobs behave differently from long-running Deployments. The key detail is that the Pod does not complete until every required container exits, so a sidecar that runs forever can leave the CronJob stuck.

Understand the Completion Model

A CronJob creates Jobs, and each Job creates a Pod template. In that Pod, all regular containers start together. The Job is considered complete only after the workload finishes successfully and the other required containers have also terminated.

That is why a logging or proxy sidecar that loops forever is a problem for batch work. In a Deployment, a never-ending sidecar is normal. In a Job, it prevents completion.

Use Coordinated Shutdown Between the Main Container and the Sidecar

A practical pattern is to share an emptyDir volume and let the main task write a "done" signal when its work is complete. The sidecar watches for that signal and exits cleanly.

yaml
1apiVersion: batch/v1
2kind: CronJob
3metadata:
4  name: hourly-report
5spec:
6  schedule: "0 * * * *"
7  jobTemplate:
8    spec:
9      template:
10        spec:
11          restartPolicy: Never
12          volumes:
13            - name: shared
14              emptyDir: {}
15          containers:
16            - name: main
17              image: busybox:1.36
18              command: ["/bin/sh", "-c"]
19              args:
20                - |
21                  date > /shared/report.txt
22                  echo "report generated"
23                  touch /shared/done
24              volumeMounts:
25                - name: shared
26                  mountPath: /shared
27            - name: sidecar
28              image: busybox:1.36
29              command: ["/bin/sh", "-c"]
30              args:
31                - |
32                  while [ ! -f /shared/done ]; do
33                    if [ -f /shared/report.txt ]; then
34                      cat /shared/report.txt
35                    fi
36                    sleep 2
37                  done
38                  echo "sidecar exiting"
39              volumeMounts:
40                - name: shared
41                  mountPath: /shared

The main container performs the batch work and touches /shared/done when it is finished. The sidecar polls for that marker, exits, and lets the Pod finish successfully.

Choose a Sidecar Only When It Adds Real Value

Some helper behavior is better handled outside the Pod. For example, if you only need logs, standard container stdout plus cluster log aggregation is often simpler than adding a sidecar. A sidecar is more appropriate when the helper process must share the Pod lifecycle or filesystem, such as:

  • A lightweight proxy used only during the job
  • A local helper that transforms output files before upload
  • A companion process that streams artifacts while the job runs

The closer the helper is to "always on forever," the more suspicious it is in a CronJob design.

Keep the Pod Easy to Debug

Batch Pods are already transient, so operational simplicity matters. Use clear commands, shared files with obvious names, and straightforward exit behavior. If the main container can fail, ensure the sidecar also stops or times out appropriately so the Job does not remain in a confusing state.

You can test the same template as a plain Job before putting it behind a schedule. That shortens the debugging loop and makes completion behavior easier to inspect.

Common Pitfalls

The biggest mistake is copying a sidecar pattern from a Deployment into a CronJob without changing shutdown behavior. A sidecar that tails logs indefinitely or waits forever on a socket can keep the Pod alive even though the actual batch task already finished.

Another problem is forgetting shared state. If the containers need to coordinate completion, they need some communication path such as a shared volume, a file marker, or another explicit signal. Without that, each container has no idea when the other one is done.

It is also easy to overcomplicate the design. If the sidecar only exists to watch stdout, remove it and rely on your cluster's logging stack instead. Simpler CronJobs are easier to operate and less likely to hang.

Finally, test failure paths, not only the happy path. If the main container crashes before writing the done marker, your sidecar should not wait forever.

Summary

  • CronJobs can use sidecars, but the Pod completes only after all required containers exit.
  • A never-ending sidecar is the main reason CronJob Pods get stuck in a running state.
  • Use explicit coordination, such as a shared volume and a done file, so the sidecar knows when to stop.
  • Prefer simpler designs when platform logging or external services can replace the sidecar.
  • Test both success and failure paths before scheduling the job in production.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.