Kubernetes
kubectl
timeout
command execution
container management

Timeout for Kubectl exec

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

kubectl exec does not have a built-in --timeout flag. To add a timeout, wrap the command executed inside the container with the timeout utility (if available in the container), use the --request-timeout flag for the kubectl client connection, or run kubectl exec itself inside a shell timeout command. The distinction matters: --request-timeout controls how long kubectl waits for the API server to respond, while wrapping the command in timeout controls how long the process runs inside the container.

Using timeout Inside the Container

bash
1# Run a command with a 30-second timeout inside the container
2kubectl exec my-pod -- timeout 30 /bin/sh -c "long-running-command"
3
4# With a specific signal (SIGKILL after grace period)
5kubectl exec my-pod -- timeout --signal=SIGTERM --kill-after=5 30 my-script.sh
6
7# Example: timeout a curl request inside the pod
8kubectl exec my-pod -- timeout 10 curl -s http://internal-service:8080/health

The timeout command is part of GNU coreutils and is available in most Linux-based container images. It sends SIGTERM after the specified duration, then SIGKILL after the --kill-after grace period.

Using Shell timeout on the Client Side

bash
1# Timeout the entire kubectl exec command (Linux/macOS)
2timeout 60 kubectl exec my-pod -- /bin/sh -c "sleep 100"
3
4# macOS (using gtimeout from coreutils)
5gtimeout 60 kubectl exec my-pod -- /bin/sh -c "sleep 100"
6
7# Install gtimeout on macOS
8# brew install coreutils

This kills the kubectl exec process on the client side after 60 seconds. The process inside the container may continue running unless the container handles the disconnection.

Using --request-timeout

bash
1# Timeout the API server connection (not the command execution)
2kubectl exec --request-timeout=30s my-pod -- /bin/sh -c "echo hello"
3
4# This controls:
5# - How long kubectl waits for the initial connection to the API server
6# - How long it waits for the exec session to be established
7# It does NOT control how long the command runs inside the container

--request-timeout is useful for detecting unreachable clusters or hung API servers, but it does not limit command execution time.

Combining Both Approaches

bash
1# Best practice: timeout on both sides
2# - Client side: kill kubectl if it hangs (network issues)
3# - Container side: kill the actual command if it takes too long
4timeout 120 kubectl exec my-pod -- timeout 60 /bin/sh -c "
5    echo 'Starting backup...'
6    pg_dump mydb > /tmp/backup.sql
7    echo 'Done'
8"

Interactive Sessions with Timeout

bash
1# Timeout an interactive session
2timeout 300 kubectl exec -it my-pod -- /bin/bash
3
4# The session auto-terminates after 5 minutes
5# User gets SIGTERM, then the bash session closes

Scripting Patterns

bash
1#!/bin/bash
2# Run a command in a pod with timeout and error handling
3run_in_pod() {
4    local pod=$1
5    local timeout_secs=$2
6    shift 2
7
8    if timeout "$timeout_secs" kubectl exec "$pod" -- "$@"; then
9        echo "Command completed successfully"
10        return 0
11    else
12        local exit_code=$?
13        if [ $exit_code -eq 124 ]; then
14            echo "ERROR: Command timed out after ${timeout_secs}s"
15        else
16            echo "ERROR: Command failed with exit code $exit_code"
17        fi
18        return $exit_code
19    fi
20}
21
22# Usage
23run_in_pod my-pod 30 /bin/sh -c "curl -s http://localhost:8080/health"
24run_in_pod my-pod 60 /bin/sh -c "python migrate.py"

Using Kubernetes Jobs Instead

For long-running tasks that need reliable timeouts, use a Kubernetes Job instead of kubectl exec:

yaml
1apiVersion: batch/v1
2kind: Job
3metadata:
4  name: db-migration
5spec:
6  activeDeadlineSeconds: 300  # Built-in timeout — kills the pod after 5 minutes
7  backoffLimit: 2
8  template:
9    spec:
10      containers:
11        - name: migrate
12          image: my-app:latest
13          command: ["python", "migrate.py"]
14      restartPolicy: Never
bash
# Run and wait for completion
kubectl apply -f migration-job.yaml
kubectl wait --for=condition=complete job/db-migration --timeout=360s

activeDeadlineSeconds is the native Kubernetes way to timeout workloads. It kills the pod after the specified duration regardless of what the process is doing.

Common Pitfalls

  • Assuming --request-timeout limits command execution: --request-timeout only controls the kubectl client's connection to the API server. A command running for hours inside the container is unaffected. Use the timeout utility inside the container to limit actual command execution time.
  • Container image missing the timeout command: Minimal images (alpine, distroless, scratch) may not include timeout. Alpine has it in coreutils (apk add coreutils). For distroless containers, you cannot exec into them at all. Consider using a debug container: kubectl debug my-pod --image=busybox --target=my-container.
  • Client-side timeout leaving orphan processes in the container: When timeout kills the kubectl exec process on the client, the container process may keep running. The exec session closes the stdin/stdout pipes, but the process continues unless it checks for a closed pipe or handles SIGHUP. Always use container-side timeout as the primary control.
  • Exit code 124 vs other failures: The timeout command returns exit code 124 when the time limit is reached. Other exit codes come from the command itself. Scripts must distinguish between "timed out" (124) and "failed for another reason" to take appropriate action.
  • Using kubectl exec for tasks that should be Jobs: kubectl exec is designed for debugging and quick commands. For repeatable, timed operations (migrations, backups, data processing), use Kubernetes Jobs with activeDeadlineSeconds. Jobs provide retries, completion tracking, and proper resource cleanup.

Summary

  • Use timeout N command inside the container to limit how long a command runs
  • Use timeout N kubectl exec ... on the client side to handle hung connections
  • --request-timeout controls API server connection time, not command execution time
  • Combine both client-side and container-side timeouts for robust scripts
  • Use Kubernetes Jobs with activeDeadlineSeconds for production-grade timeout control

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.