Sidecars are containers that run alongside the Steps in your Task, providing supporting services like databases, Docker daemons, or SSH servers. This guide shows you how to use sidecars effectively.
Overview
Sidecars enable you to:
Run services that Steps need to communicate with
Provide test dependencies like databases or message queues
Run Docker-in-Docker for building container images
Set up SSH servers or other network services
Share resources with Steps through volumes
Sidecars start before Steps execute and run throughout the Task execution.
Basic Sidecar Configuration
Define sidecars in the Task specification:
apiVersion : tekton.dev/v1
kind : TaskRun
metadata :
generateName : sidecar-example-
spec :
taskSpec :
steps :
- name : main
image : alpine
script : |
echo "Main step running"
# Steps can communicate with sidecar
sidecars :
- name : helper
image : nginx
Docker-in-Docker Sidecar
A common use case is running Docker commands from Steps:
apiVersion : tekton.dev/v1
kind : TaskRun
metadata :
generateName : dind-sidecar-
spec :
taskSpec :
steps :
- name : client
image : docker
env :
# Connect to the sidecar over TCP, with TLS
- name : DOCKER_HOST
value : tcp://localhost:2376
# Verify TLS
- name : DOCKER_TLS_VERIFY
value : '1'
# Use the certs generated by the sidecar daemon
- name : DOCKER_CERT_PATH
value : /certs/client
workingDir : /workspace
script : |
#!/usr/bin/env sh
set -e
# Run a Docker container
docker run busybox echo hello
# Write a Dockerfile and build it
cat > Dockerfile << EOF
FROM ubuntu
RUN apt-get update
ENTRYPOINT ["echo", "hello"]
EOF
docker build -t hello .
docker images
# Run the built image
docker run hello
volumeMounts :
- mountPath : /certs/client
name : dind-certs
sidecars :
- name : server
image : docker:dind
args :
- --storage-driver=vfs
- --userland-proxy=false
- --debug
computeResources :
requests :
memory : "512Mi"
securityContext :
privileged : true
env :
# Write generated certs to the path shared with the client
- name : DOCKER_TLS_CERTDIR
value : /certs
volumeMounts :
- mountPath : /certs/client
name : dind-certs
# Wait for the dind daemon to generate the certs
startupProbe :
periodSeconds : 1
failureThreshold : 30
exec :
command : [ 'ls' , '/certs/client/ca.pem' ]
# Verify Docker daemon is ready to accept commands
readinessProbe :
periodSeconds : 2
exec :
command : [ 'docker' , 'info' ]
volumes :
- name : dind-certs
emptyDir : {}
Docker-in-Docker requires privileged mode. Ensure your cluster security policies allow privileged containers.
Sharing Data with Volumes
Sidecars and Steps can share data through volumes:
apiVersion : tekton.dev/v1
kind : TaskRun
metadata :
generateName : shared-volume-
spec :
taskSpec :
volumes :
- name : messages
emptyDir : {}
steps :
- name : write
image : alpine
volumeMounts :
- name : messages
mountPath : /messages
script : |
echo "Hello from step" > /messages/greeting.txt
- name : read
image : alpine
volumeMounts :
- name : messages
mountPath : /messages
script : |
cat /messages/greeting.txt
sidecars :
- name : processor
image : alpine
volumeMounts :
- name : messages
mountPath : /messages
command : [ 'sh' , '-c' ]
args :
- |
while true; do
if [ -f /messages/greeting.txt ]; then
echo "Sidecar saw: $(cat /messages/greeting.txt)"
fi
sleep 2
done
Sidecar Readiness
Use readiness probes to ensure sidecars are ready before Steps start:
sidecars :
- name : database
image : postgres:13
env :
- name : POSTGRES_PASSWORD
value : example
readinessProbe :
exec :
command :
- pg_isready
- -U
- postgres
periodSeconds : 2
initialDelaySeconds : 5
Steps wait for sidecars with readiness probes to become ready before executing.
Startup Probes
Use startup probes for sidecars that need extra time to initialize:
sidecars :
- name : slow-service
image : my-slow-service
startupProbe :
periodSeconds : 1
failureThreshold : 30 # Allow up to 30 seconds for startup
exec :
command : [ 'cat' , '/tmp/ready' ]
readinessProbe :
periodSeconds : 2
exec :
command : [ 'curl' , 'localhost:8080/health' ]
SSH Server Sidecar
Run an SSH server for Git operations:
apiVersion : tekton.dev/v1
kind : TaskRun
metadata :
name : authenticating-git-commands
spec :
serviceAccountName : ssh-key-service-account
taskSpec :
volumes :
- name : messages
emptyDir : {}
sidecars :
- name : server
image : alpine/git:v2.26.2
securityContext :
runAsUser : 0
volumeMounts :
- name : messages
mountPath : /messages
script : |
#!/usr/bin/env ash
# Generate a private host key
ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
chmod 0600 /etc/ssh/ssh_host_rsa_key*
HOST_PUBLIC_KEY=$(cat /etc/ssh/ssh_host_rsa_key.pub | awk '{ print $2 }')
echo "localhost ssh-rsa $HOST_PUBLIC_KEY" > /messages/known_hosts
# Wait for Steps to supply the server a public key
while [ ! -f /messages/authorized_keys ] ; do
sleep 1
done
# Configure SSH to allow login
mkdir /root/.ssh
cp /messages/authorized_keys /root/.ssh/
sed -i s/root:!/'root:*'/g /etc/shadow
# Create a git repo
cd /root/
mkdir repo
cd repo
git init . --bare
# Start the sshd server
/usr/sbin/sshd -E /var/log/sshd
touch /messages/sshd-ready
tail -f /var/log/sshd
steps :
- name : setup
image : alpine/git:v2.26.2
volumeMounts :
- name : messages
mountPath : /messages
script : |
# Generate authorized_keys from credentials
ssh-keygen -y -f $(credentials.path)/.ssh/id_* > /messages/authorized_keys
# Wait for sshd to start
while [ ! -f /messages/sshd-ready ] ; do
sleep 1
done
- name : git-clone-and-push
image : alpine/git:v2.26.2
volumeMounts :
- name : messages
mountPath : /messages
script : |
ln -s $(credentials.path)/.ssh /root/.ssh
cp /messages/known_hosts /root/.ssh/
git clone root@localhost:/root/repo ./repo
cd repo
echo "Hello, world!" > README
git add README
git commit -m "Test commit"
git push origin master
Workspaces in Sidecars
Sidecars can access Task workspaces:
apiVersion : tekton.dev/v1
kind : Task
metadata :
name : sidecar-workspace-example
spec :
workspaces :
- name : source
sidecars :
- name : file-server
image : python:3-alpine
workingDir : $(workspaces.source.path)
command : [ 'python' , '-m' , 'http.server' , '8000' ]
steps :
- name : download
image : alpine
script : |
echo "File server available at localhost:8000"
# Step can access files via HTTP from sidecar
Variable Substitution in Sidecars
Sidecars support variable substitution:
sidecars :
- name : database
image : $(params.database-image)
env :
- name : DB_NAME
value : $(params.database-name)
- name : WORKSPACE_PATH
value : $(workspaces.data.path)
Supported fields:
spec.sidecars[].name
spec.sidecars[].image
spec.sidecars[].imagePullPolicy
spec.sidecars[].env.value
spec.sidecars[].command
spec.sidecars[].args
spec.sidecars[].script
spec.sidecars[].volumeMounts
Sidecar Lifecycle
Startup Order
Sidecars start first
Sidecars with readiness probes must become ready
Steps execute in order
Sidecars continue running during Step execution
Shutdown
Sidecars automatically stop when:
All Steps complete successfully
A Step fails and the Task stops
The TaskRun times out
Tekton sends a SIGTERM to sidecars to request graceful shutdown. If sidecars don’t exit within the grace period, they receive SIGKILL.
Resource Management
Specify resource requests and limits for sidecars:
sidecars :
- name : memory-intensive
image : my-service
computeResources :
requests :
memory : "512Mi"
cpu : "500m"
limits :
memory : "1Gi"
cpu : "1000m"
Best Practices
Use Readiness Probes
Always configure readiness probes for sidecars that Steps depend on. This prevents race conditions where Steps try to connect before the sidecar is ready.
sidecars :
- name : api-server
image : my-api
readinessProbe :
httpGet :
path : /health
port : 8080
periodSeconds : 2
Minimize Sidecar Size
# Good: Lightweight sidecar
sidecars :
- name : cache
image : redis:alpine
# Avoid: Unnecessarily large images
sidecars :
- name : cache
image : ubuntu-with-redis
Share Data via Volumes
Use volumes instead of network communication when possible:
volumes :
- name : shared-data
emptyDir : {}
steps :
- name : producer
volumeMounts :
- name : shared-data
mountPath : /data
sidecars :
- name : consumer
volumeMounts :
- name : shared-data
mountPath : /data
Set Security Contexts
sidecars :
- name : secure-service
image : my-service
securityContext :
runAsNonRoot : true
runAsUser : 1000
allowPrivilegeEscalation : false
capabilities :
drop :
- ALL
Common Patterns
Database for Testing
sidecars :
- name : postgres
image : postgres:13
env :
- name : POSTGRES_PASSWORD
value : test
- name : POSTGRES_DB
value : testdb
readinessProbe :
exec :
command : [ 'pg_isready' , '-U' , 'postgres' ]
periodSeconds : 2
Service Mesh Proxy
sidecars :
- name : envoy
image : envoyproxy/envoy:v1.20.0
args :
- -c
- /config/envoy.yaml
volumeMounts :
- name : envoy-config
mountPath : /config
Message Queue
sidecars :
- name : rabbitmq
image : rabbitmq:3-alpine
env :
- name : RABBITMQ_DEFAULT_USER
value : guest
- name : RABBITMQ_DEFAULT_PASS
value : guest
readinessProbe :
exec :
command : [ 'rabbitmq-diagnostics' , 'ping' ]
periodSeconds : 5
Why isn't my sidecar starting?
Check these common issues:
Image pull errors : Verify the image exists and is accessible
Resource constraints : Ensure the cluster has sufficient resources
Security policies : Check if security contexts or policies block the sidecar
Volume mount conflicts : Verify volume mounts don’t conflict with Step mounts
View sidecar logs: kubectl logs < pod-nam e > -c < sidecar-nam e >
How do Steps communicate with sidecars?
Steps communicate with sidecars via:
Localhost networking : Sidecars listen on localhost or 127.0.0.1
Shared volumes : Exchange files through mounted volumes
Environment variables : Pass configuration via env vars
Example: steps :
- name : client
script : |
# Connect to sidecar on localhost
curl http://localhost:8080/api