6.7 Container & Node Logging Architecture, Journalctl & Fluentd
Key Takeaways
- Kubernetes container logging relies on applications writing directly to stdout and stderr streams; the Container Runtime Interface (CRI) captures these streams and stores them in /var/log/pods/<namespace>_<name>_<uid>/<container>/<retry>.log.
- Log files on nodes are managed via symlinks in /var/log/containers/; kubelet and containerd enforce log rotation policies (e.g., containerLogMaxSize and containerLogMaxFiles) to prevent host disk exhaustion.
- The 'kubectl logs' CLI provides versatile streaming options: '-f' (follow), '-p' (--previous for crashed instances), '--all-containers' (multi-container pods), '--timestamps', '--tail=N', and '-l' (label selector aggregation).
- Host-level and systemd daemon logging requires 'journalctl' commands on node instances ('journalctl -u kubelet -e --no-pager', 'journalctl -u containerd').
- Cluster-level logging architectures deploy node-level logging agents (DaemonSets like Fluent Bit, Fluentd, or Promtail) that scrape /var/log/pods and forward structured logs to centralized backends (Elasticsearch, Loki, Cloud Logging).
6.7 Container & Node Logging Architecture, Journalctl & Fluentd
In containerized environments, applications are ephemeral. When a container crashes, restarts, or is rescheduled to another node, its local in-memory state and ephemeral files are lost. To maintain observability and troubleshoot complex failures, Kubernetes establishes a standardized logging architecture.
Understanding how application output travels from standard streams to on-disk files, how kubectl logs streams data, how host daemons log to systemd-journald, and how cluster-wide log forwarders operate is vital for the CKA exam and production engineering.
1. Container Engine Logging Pipeline & Storage Layout
Kubernetes assumes that containerized applications write their operational logs directly to standard output (stdout) and standard error (stderr).
+-----------------------------------------------------------------------------------------+
| CONTAINER LOG PIPELINE ARCHITECTURE |
| |
| [APPLICATION IN CONTAINER] |
| | (stdout / stderr) |
| v |
| [CONTAINER RUNTIME (containerd / CRI-O)] |
| - Formats logs into CRI format (timestamp stream log-line) |
| - Writes to physical disk on host node: |
| /var/log/pods/<namespace>_<pod-name>_<pod-uid>/<container-name>/<retry-count>.log |
| | |
| +---> Symlinked to: /var/log/containers/<pod-name>_<namespace>_<container>.log |
| | |
| +====================================+====================================+ |
| | | | |
| v v v |
| [KUBECTL LOGS STREAM] [NODE-LEVEL AGENT] [HOST DAEMONS] |
| - Kubelet serves log stream - Fluentd / Fluent Bit / Promtail - kubelet |
| to kube-apiserver over - DaemonSet mounts /var/log/pods - containerd |
| HTTPS port 10250 - Forwards to Elastic / Loki - journalctl |
+-----------------------------------------------------------------------------------------+
Physical On-Disk Log Structure:
- Primary Log Path:
/var/log/pods/<namespace>_<pod-name>_<pod-uuid>/<container-name>/0.log - Convenience Symlink:
/var/log/containers/<pod-name>_<namespace>_<container-name>-<container-id>.log - CRI Log Line Format:
2026-08-23T08:15:30.123456789Z stdout F [INFO] Server listening on port 8080 2026-08-23T08:15:31.987654321Z stderr F [ERROR] Failed to connect to database2026-08-23T...: ISO 8601 UTC timestamp.stdout/stderr: Origin stream.F(Full) /P(Partial): Indicates whether the log line was complete or truncated across multiple chunks.
2. Kubelet & Containerd Log Rotation Mechanics
To prevent rogue applications from generating massive logs that exhaust host disk space (DiskPressure), both the kubelet and containerd implement automatic log rotation.
Kubelet Configuration Parameters (/var/lib/kubelet/config.yaml):
containerLogMaxSize: Maximum file size before rotation (default:10Mi).containerLogMaxFiles: Maximum number of rotated log archives retained per container (default:5).
Kubelet asks the runtime to rotate logs according to configured size and file-count limits. Exact rotated filenames and whether archives are compressed are runtime-specific, so inspect /var/log/pods and the node runtime rather than assuming a 0.log.1.gz convention.
3. Mastering kubectl logs Syntax
kubectl logs queries the kubelet API on the target node via kube-apiserver:
# 1. Basic log retrieval for a single-container pod
kubectl logs web-pod
# 2. Specify container in a multi-container pod
kubectl logs multi-pod -c app-container
# 3. Stream logs across ALL containers in a multi-container pod simultaneously
kubectl logs multi-pod --all-containers=true
# 4. Stream logs from a previously crashed container instance
kubectl logs web-pod --previous
# 5. Follow live log output in real time (-f)
kubectl logs -f web-pod
# 6. View the last N lines (--tail)
kubectl logs --tail=50 web-pod
# 7. View logs generated in the last 15 minutes (--since)
kubectl logs --since=15m web-pod
# 8. Include RFC3339 timestamps in log output
kubectl logs --timestamps web-pod
# 9. Aggregate logs from all pods matching a label selector
kubectl logs -l app=payment-service --tail=20
4. Host Systemd & OS Log Diagnostics (journalctl)
Host-level systemd services (such as kubelet and containerd) do not write to /var/log/pods. Their logs are managed by systemd-journald.
# View kubelet logs starting from the end of the journal (-e) with line limit (-n)
journalctl -u kubelet -e --no-pager -n 100
# Follow live kubelet logs
journalctl -u kubelet -f
# View containerd runtime logs
journalctl -u containerd -e --no-pager -n 100
# Filter logs by time window
journalctl -u kubelet --since "2026-08-23 07:00:00" --until "2026-08-23 08:00:00"
# Check kernel messages for hardware errors or OOM events
dmesg -T | tail -n 50
5. Cluster-Level Logging Architectures
Kubernetes does not provide a native centralized storage solution for logs. Three primary architectural patterns exist for cluster-level logging:
+-----------------------------------------------------------------------------------------+
| CLUSTER LOGGING PATTERNS COMPARISON |
| |
| [PATTERN 1: NODE LOGGING AGENT DAEMONSET (Standard / Recommended)] |
| - Fluent Bit / Fluentd runs as DaemonSet on every node. |
| - Mounts host `/var/log/pods` read-only. |
| - Parses CRI formatting, enriches with K8s metadata, forwards to Elastic / Loki. |
| - Pros: Minimal resource overhead; zero changes to application pods. |
| |
| [PATTERN 2: SIDECAR LOGGING CONTAINER] |
| - Sidecar container runs inside application pod. |
| - Streams application log files (e.g., `/var/log/nginx/access.log`) to sidecar stdout |
| or ships directly to central backend. |
| - Pros: Useful for legacy applications that cannot log to stdout. |
| - Cons: Doubled memory/CPU overhead per pod. |
| |
| [PATTERN 3: DIRECT APPLICATION LOGGING] |
| - Application directly connects to logging backend (e.g., Logstash / Datadog API). |
| - Cons: Tightly couples application code to logging infrastructure. |
+-----------------------------------------------------------------------------------------+
Troubleshooting Missing Logs in Centralized Pipelines:
- DaemonSet Pod Failed: Verify logging DaemonSet health:
kubectl get pods -n logging. - Host Volume Mount Broken: Ensure Fluent Bit manifest mounts
/var/log/podsand/var/log/containers. - Application Writing to Internal File: If
kubectl logsproduces nothing, the app may be logging to a private on-disk file instead ofstdout/stderr.
A pod named order-gateway contains two containers: gateway-proxy and token-validator. Running kubectl logs order-gateway fails with an error requiring a container name. What command syntax will stream logs from ALL containers within the pod simultaneously?
Where does the Container Runtime Interface (such as containerd) store physical container log files on the host filesystem of a Kubernetes worker node?
An administrator is troubleshooting a legacy enterprise Java application running in a pod. Executing kubectl logs <pod-name> returns completely empty output, but the application is actively serving requests. What is the most likely architectural explanation for this behavior?