Timeouts
Linkerd provides fine‑grained timeout settings to control the lifecycle of HTTP requests and TCP connections between services in your mesh. You can configure three primary timeout policies via Kubernetes service annotations:
- timeout.linkerd.io/request: Maximum time from when a request is sent until the first byte of the request body arrives at the server.
- timeout.linkerd.io/response: Maximum time from when the first byte of the response header is received until the entire response body is delivered.
- timeout.linkerd.io/idle: Maximum time of inactivity between data frames (both request and response) before the connection is closed.
Prerequisites
- macOS/Linux/Windows with a Unix‑style shell
- k3d (v5+) for local Kubernetes clusters
- kubectl (v1.25+)
- Helm (v3+)
- Smallstep (step) CLI for certificate generation
Tutorial
1. Create the configuration files
cat << 'EOF' > cluster.yaml
apiVersion: k3d.io/v1alpha5
kind: Simple
metadata:
name: "cluster"
servers: 1
agents: 0
image: rancher/k3s:v1.33.0-k3s1
network: playground
options:
k3s:
extraArgs:
- arg: --disable=traefik
nodeFilters: ["server:*"]
- arg: --cluster-cidr=10.23.0.0/16
nodeFilters: ["server:*"]
- arg: --service-cidr=10.247.0.0/16
nodeFilters: ["server:*"]
- arg: --debug
nodeFilters: ["server:*"]
ports:
- port: 8081:80
nodeFilters: ["loadbalancer"]
EOF
cat << 'EOF' > application.yaml
apiVersion: v1
kind: Pod
metadata:
name: client
namespace: simple-app
annotations:
linkerd.io/inject: enabled
spec:
containers:
- name: curl
image: curlimages/curl:latest
command: ["sleep", "infinity"]
---
apiVersion: v1
kind: Namespace
metadata:
name: simple-app
annotations:
linkerd.io/inject: enabled
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: server
namespace: simple-app
spec:
replicas: 1
selector:
matchLabels:
app: server
version: v1
template:
metadata:
labels:
app: server
version: v1
spec:
containers:
- name: http-app
image: kong/httpbin:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: server
namespace: simple-app
spec:
selector:
app: server
version: v1
ports:
- port: 80
targetPort: 80
EOF
2. Create a Local Kubernetes Cluster
Use k3d and your cluster.yaml to spin up a lightweight Kubernetes cluster:
k3d cluster create --kubeconfig-update-default \
-c ./cluster.yaml
3. Generate Identity Certificates
Linkerd requires a trust anchor (root CA) and an issuer (intermediate CA) for mTLS identity.
step certificate create root.linkerd.cluster.local ./certificates/ca.crt ./certificates/ca.key \
--profile root-ca \
--no-password \
--insecure
step certificate create identity.linkerd.cluster.local ./certificates/issuer.crt ./certificates/issuer.key \
--profile intermediate-ca \
--not-after 8760h \
--no-password \
--insecure \
--ca ./certificates/ca.crt \
--ca-key ./certificates/ca.key
4. Install Linkerd via Helm
helm repo add linkerd-edge https://helm.linkerd.io/edge
helm repo update
helm install linkerd-crds linkerd-edge/linkerd-crds \
-n linkerd --create-namespace --set installGatewayAPI=true
helm install linkerd-control-plane \
-n linkerd \
--set-file identityTrustAnchorsPEM=./certificates/ca.crt \
--set-file identity.issuer.tls.crtPEM=./certificates/issuer.crt \
--set-file identity.issuer.tls.keyPEM=./certificates/issuer.key \
linkerd-edge/linkerd-control-plane
5. Deploy the Sample Application
kubectl apply -f ./application.yaml
You can then validate that the traffic is going from the client’s pod to server’s deployment
kubectl exec -n simple-app client -c curl -- sh -c '\
curl -sS --no-progress-meter \
-X POST \
-H "Content-Type: application/json" \
-o /dev/null \
-w "HTTPSTATUS:%{http_code}\n" \
http://server.simple-app.svc.cluster.local/post \
'
Timeout Scenarios
Below are examples of how to annotate your server service and test each timeout policy.
1. Request Timeout (timeout.linkerd.io/request)
Limit the time to upload the entire request body by setting the following annotation to the server’s service.
kubectl annotate svc server \
-n simple-app \
timeout.linkerd.io/request=1s \
timeout.linkerd.io/response=1h \
timeout.linkerd.io/idle=1h \
--overwrite
Throttle the upload to take longer than 1s (100 KB at 20 KB/s):
kubectl exec -n simple-app client -c curl -- sh -c '\
yes a | head -c 100000 > /tmp/payload.json && \
curl -sS --no-progress-meter \
--limit-rate 20K \
-X POST \
-H "Content-Type: application/json" \
--data-binary @/tmp/payload.json \
-o /dev/null \
-w "HTTPSTATUS:%{http_code}\n" \
http://server.simple-app.svc.cluster.local/post \
'
2. Response Timeout (timeout.linkerd.io/response)
Limit the time to receive the full response by setting the following annotation to the server’s service.
kubectl annotate svc server \
-n simple-app \
timeout.linkerd.io/request=1h \
timeout.linkerd.io/response=1s \
timeout.linkerd.io/idle=1h \
--overwrite
Use HTTPBin’s /delay/5 endpoint to delay the response >5s:
kubectl exec -n simple-app client -c curl -- sh -c '\
curl -sS --no-progress-meter \
-X POST \
-H "Content-Type: application/json" \
-o /dev/null \
-w "HTTPSTATUS:%{http_code}\n" \
http://server.simple-app.svc.cluster.local/delay/5 \
'