| name | k8s-timezone-config |
| description | Configure timezone for Kubernetes pods using TZ environment variable. Use when deploying workloads that need Brazil/São Paulo timezone or when logs show UTC (+0000) instead of local time. |
Kubernetes Pod Timezone Configuration
Standard timezone for your organization infrastructure: America/Sao_Paulo
Problem
Kubernetes pods run in UTC by default. Logs and application timestamps show +0000 offset instead of local Brazil time (-0300).
Solution
Add the TZ environment variable to container specifications.
Implementation Patterns
1. Helm Values (extraEnv pattern)
For Helm charts that support extraEnv:
extraEnv:
- name: TZ
value: America/Sao_Paulo
2. Multiple Containers
When a deployment has multiple containers (e.g., API server + frontend), add TZ to ALL containers:
apiServer:
extraEnv:
- name: TZ
value: America/Sao_Paulo
frontend:
extraEnv:
- name: TZ
value: America/Sao_Paulo
3. Raw Kubernetes Deployment
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
containers:
- name: app
env:
- name: TZ
value: America/Sao_Paulo
4. StatefulSet
apiVersion: apps/v1
kind: StatefulSet
spec:
template:
spec:
containers:
- name: app
env:
- name: TZ
value: America/Sao_Paulo
Verification
After deployment, verify timezone is set correctly:
kubectl exec -it <pod-name> -n <namespace> -- date
Common Applications Requiring Timezone
| Application | Config Location | Notes |
|---|
| Dependency-Track | apiServer.extraEnv + frontend.extraEnv | Both containers need TZ |
| Grafana | env or extraEnvVars | Single container |
| Loki | extraEnv | Affects log timestamps |
| Prometheus | server.env | Affects alert timestamps |
| DefectDojo | extraEnv | Django app |
| PostgreSQL | primary.extraEnvVars | Database timestamps |
Important Notes
- Restart required: Pods must restart for TZ changes to take effect
- All containers: Set TZ on ALL containers in a pod, including sidecars
- Init containers: Also set TZ on init containers if they log timestamps
- Cron jobs: Kubernetes CronJob schedules are always UTC - TZ only affects container-level time
your organization GitOps Workflow
- Edit values.yaml in
argo-cd-helm-values/kube-addons/<service>/<cluster>/values.yaml
- Add TZ environment variable to all containers
- Commit and push (ArgoCD auto-syncs)
- Verify pods restart with new timezone
Reference
- IANA Timezone Database:
America/Sao_Paulo = UTC-3 (no DST since 2019)
- Linux TZ variable: Uses
/usr/share/zoneinfo/America/Sao_Paulo
Gotchas
TZ env var only affects app-level timestamps, not kubectl logs timestamps (those come from the container runtime, which stays UTC). The kubelet timestamps stay +0000 even after the pod's internal clock is São Paulo.
- CronJob
schedule: is always UTC regardless of pod TZ. A 0 8 * * * schedule fires at 05:00 BRT, not 08:00 BRT. Use spec.timeZone: America/Sao_Paulo on the CronJob itself (K8s 1.27+) or compute the UTC offset manually.
- Distroless and scratch images have no
/usr/share/zoneinfo — TZ=America/Sao_Paulo silently falls back to UTC. Either use a base image that ships tzdata or mount it via configMap/volume.
- Init containers don't inherit
TZ from the main container in older charts — set it on the init container spec separately or their migration logs stay UTC.
- Java apps need
-Duser.timezone=America/Sao_Paulo in JAVA_OPTS in addition to TZ — the JVM reads its own property, not the env var, on some distributions.
- PostgreSQL
TZ env var sets the OS clock, not the database timezone setting. Server timestamps via now() still use the value in postgresql.conf — set both.