Parser Example
Kubernetes
Kubernetes
Overview
Parser xử lý các loại log từ Kubernetes cluster:
- Pod Container Logs: Application logs từ containers trong pods
- K8s Events: Cluster events (Normal/Warning) từ kubelet
- Audit Logs: API server audit logs cho security monitoring
Sample Logs
1. Pod Container Log (INFO)
{"@timestamp":"2026-03-17T10:30:15.123Z","message":"2026-03-17T10:30:15.123456Z INFO Starting web server on port 8080","timestamp":"2026-03-17T10:30:15.123Z","kubernetes":{"pod_name":"nginx-deployment-7fb96c846b-xk9mn","namespace_name":"production","container_name":"nginx","container_id":"docker://a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef12345678","pod_id":"12345678-1234-1234-1234-123456789abc","host":"worker-node-01","labels":{"app":"nginx","version":"1.21"}}}
2. Pod Container Log (ERROR)
{"@timestamp":"2026-03-17T10:31:22.456Z","message":"2026-03-17T10:31:22.456789Z ERROR Connection refused to database at 10.96.0.15:5432","timestamp":"2026-03-17T10:31:22.456Z","kubernetes":{"pod_name":"backend-api-5d8f9c7b6a-m2p4n","namespace_name":"staging","container_name":"api","container_id":"docker://b2c3d4e5f6a789012345678901234567890abcdef1234567890abcdef12345679","pod_id":"23456789-2345-2345-2345-234567890bcd","host":"worker-node-02","labels":{"app":"backend-api","tier":"backend"}}}
3. K8s Event (Image Pulled)
{"@timestamp":"2026-03-17T10:32:45.789Z","message":"Successfully pulled image \"nginx:1.21\" in 3.245s","timestamp":"2026-03-17T10:32:45.789Z","kubernetes":{"pod_name":"nginx-deployment-7fb96c846b-abc12","namespace_name":"default","container_name":"nginx","host":"worker-node-01"},"event":{"type":"Normal","reason":"Pulled","source":"kubelet"}}
4. API Server Audit Log
{"@timestamp":"2026-03-17T10:33:59.123Z","message":"audit: id=\"a1b2c3d4\" stage=\"ResponseComplete\" verb=\"create\" user=\"admin\" resource=\"deployments\" namespace=\"production\" responseCode=201","timestamp":"2026-03-17T10:33:59.123Z","kubernetes":{"host":"master-node-01"},"audit":{"id":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","level":"RequestResponse","stage":"ResponseComplete","verb":"create","user":"admin","groups":"system:masters","resource":"deployments","namespace":"production","apiVersion":"apps/v1","responseCode":"201"}}
Parser Configuration
#regex
#conditional
event_timestamp = .timestamp
event_module = "kubernetes"
container_id = ""
container_name = ""
pod_name = ""
pod_id = ""
namespace_name = ""
host_name = ""
app_label = ""
log_level = ""
event_message = ""
event_action = ""
event_category = ""
event_outcome = ""
audit_id = ""
audit_verb = ""
audit_resource = ""
audit_user = ""
audit_response_code = ""
k8s_event_type = ""
k8s_event_reason = ""
k8s_event_source = ""
k8s_str = ""
if (k, err = to_string(.kubernetes); err == null) { k8s_str = k }
if (pod, err = to_string(.kubernetes.pod_name); err == null) { pod_name = pod }
if (ns, err = to_string(.kubernetes.namespace_name); err == null) { namespace_name = ns }
if (cname, err = to_string(.kubernetes.container_name); err == null) { container_name = cname }
if (cid, err = to_string(.kubernetes.container_id); err == null) { container_id = cid }
if (pid, err = to_string(.kubernetes.pod_id); err == null) { pod_id = pid }
if (h, err = to_string(.kubernetes.host); err == null) { host_name = h }
if (app, err = to_string(.kubernetes.labels.app); err == null) { app_label = app }
msg_str = ""
if (m, err = to_string(.message); err == null) { msg_str = m }
event_message = msg_str
if pod_name != "" {
event_category = "process"
event_action = "container_log"
if contains(msg_str, "ERROR") {
log_level = "error"
event_outcome = "failure"
}
if contains(msg_str, "WARN") {
log_level = "warning"
event_outcome = "unknown"
}
if contains(msg_str, "INFO") {
log_level = "info"
event_outcome = "success"
}
if contains(msg_str, "DEBUG") {
log_level = "debug"
event_outcome = "success"
}
if log_level == "" {
log_level = "info"
}
if (level_m, err = parse_regex(msg_str, r'(?P<level>INFO|ERROR|WARN|DEBUG|FATAL)\s'); err == null) {
level_str = to_string(level_m.level)
log_level = downcase(level_str)
if level_str == "ERROR" { event_outcome = "failure" }
if level_str == "FATAL" { event_outcome = "failure" }
if level_str == "WARN" { event_outcome = "unknown" }
if level_str == "INFO" { event_outcome = "success" }
if level_str == "DEBUG" { event_outcome = "success" }
}
}
if (et, err = to_string(.event.type); err == null) { k8s_event_type = et }
if (er, err = to_string(.event.reason); err == null) { k8s_event_reason = er }
if (es, err = to_string(.event.source); err == null) { k8s_event_source = es }
if k8s_event_type != "" {
event_category = "configuration"
event_action = "k8s_event"
if k8s_event_type == "Normal" {
log_level = "info"
event_outcome = "success"
}
if k8s_event_type == "Warning" {
log_level = "warning"
event_outcome = "unknown"
}
if k8s_event_reason == "Pulled" { event_action = "image_pulled" }
if k8s_event_reason == "Created" { event_action = "container_created" }
if k8s_event_reason == "Started" { event_action = "container_started" }
if k8s_event_reason == "Killing" { event_action = "container_killing" }
if k8s_event_reason == "BackOff" { event_action = "container_backoff" }
if k8s_event_reason == "Scheduled" { event_action = "pod_scheduled" }
if k8s_event_reason == "FailedScheduling" {
event_action = "pod_scheduling_failed"
event_outcome = "failure"
}
}
if (av, err = to_string(.audit.verb); err == null) { audit_verb = av }
if (ar, err = to_string(.audit.resource); err == null) { audit_resource = ar }
if (au, err = to_string(.audit.user); err == null) { audit_user = au }
if (aid, err = to_string(.audit.id); err == null) { audit_id = aid }
if (arc, err = to_string(.audit.responseCode); err == null) { audit_response_code = arc }
if audit_verb != "" {
event_category = "iam"
log_level = "info"
if audit_verb == "create" { event_action = "resource_created" }
if audit_verb == "update" { event_action = "resource_updated" }
if audit_verb == "delete" { event_action = "resource_deleted" }
if audit_verb == "get" { event_action = "resource_read" }
if audit_verb == "list" { event_action = "resource_listed" }
if audit_verb == "watch" { event_action = "resource_watched" }
if audit_verb == "patch" { event_action = "resource_patched" }
if audit_response_code != "" {
if (rc, err = to_int(audit_response_code); err == null) {
if rc >= 200 {
if rc < 300 { event_outcome = "success" }
}
if rc >= 400 { event_outcome = "failure" }
}
}
}
clean_container_id = container_id
if contains(container_id, "docker://") {
if (cid_m, err = parse_regex(container_id, r'docker://(?P<id>[a-f0-9]+)'); err == null) {
clean_container_id = cid_m.id
}
}
if contains(container_id, "containerd://") {
if (cid_m, err = parse_regex(container_id, r'containerd://(?P<id>[a-f0-9]+)'); err == null) {
clean_container_id = cid_m.id
}
}
if event_category == "" { event_category = "host" }
if event_action == "" { event_action = "log" }
if log_level == "" { log_level = "info" }
#normalize
timestamp: format_timestamp!(parse_timestamp!(event_timestamp, "%Y-%m-%dT%H:%M:%S.%3fZ"), "%Y-%m-%d %H:%M:%S")
event.module: event_module
event.category: event_category
event.action: event_action
event.outcome: event_outcome
log.level: log_level
message: event_message
container.id: clean_container_id
container.name: container_name
host.hostname: host_name
service.name: pod_name
labels: {"namespace": namespace_name, "app": app_label, "pod_id": pod_id, "k8s_event_type": k8s_event_type, "k8s_event_reason": k8s_event_reason, "k8s_event_source": k8s_event_source, "audit_id": audit_id, "audit_verb": audit_verb, "audit_resource": audit_resource, "response_code": audit_response_code}
user.name: audit_user
Output (ECS Format)
1. Pod Container Log (INFO) Output
{
"timestamp": "2026-03-17T10:30:15.123Z",
"event.module": "kubernetes",
"event.category": "process",
"event.action": "container_log",
"event.outcome": "success",
"log.level": "info",
"message": "2026-03-17T10:30:15.123456Z INFO Starting web server on port 8080",
"container.id": "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef12345678",
"container.name": "nginx",
"host.hostname": "worker-node-01",
"service.name": "nginx-deployment-7fb96c846b-xk9mn",
"labels": {
"namespace": "production",
"app": "nginx",
"pod_id": "12345678-1234-1234-1234-123456789abc"
}
}
2. Pod Container Log (ERROR) Output
{
"timestamp": "2026-03-17T10:31:22.456Z",
"event.module": "kubernetes",
"event.category": "process",
"event.action": "container_log",
"event.outcome": "failure",
"log.level": "error",
"message": "2026-03-17T10:31:22.456789Z ERROR Connection refused to database at 10.96.0.15:5432",
"container.id": "b2c3d4e5f6a789012345678901234567890abcdef1234567890abcdef12345679",
"container.name": "api",
"host.hostname": "worker-node-02",
"service.name": "backend-api-5d8f9c7b6a-m2p4n",
"labels": {
"namespace": "staging",
"app": "backend-api",
"pod_id": "23456789-2345-2345-2345-234567890bcd"
}
}
3. K8s Event (Image Pulled) Output
{
"timestamp": "2026-03-17T10:32:45.789Z",
"event.module": "kubernetes",
"event.category": "configuration",
"event.action": "image_pulled",
"event.outcome": "success",
"log.level": "info",
"message": "Successfully pulled image \"nginx:1.21\" in 3.245s",
"container.name": "nginx",
"host.hostname": "worker-node-01",
"service.name": "nginx-deployment-7fb96c846b-abc12",
"labels": {
"namespace": "default",
"k8s_event_type": "Normal",
"k8s_event_reason": "Pulled",
"k8s_event_source": "kubelet"
}
}
4. API Server Audit Log Output
{
"timestamp": "2026-03-17T10:33:59.123Z",
"event.module": "kubernetes",
"event.category": "iam",
"event.action": "resource_created",
"event.outcome": "success",
"log.level": "info",
"message": "audit: id=\"a1b2c3d4\" stage=\"ResponseComplete\" verb=\"create\" user=\"admin\" resource=\"deployments\" namespace=\"production\" responseCode=201",
"host.hostname": "master-node-01",
"user.name": "admin",
"labels": {
"audit_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"audit_verb": "create",
"audit_resource": "deployments",
"response_code": "201"
}
}
Notes
VRL Functions Used
Parser sử dụng các functions được phép trong VRL Functions.md:
to_string(): Chuyển đổi giá trị sang stringto_int(): Chuyển đổi response code sang integerparse_regex(): Extract log level và container IDcontains(): Kiểm tra log level trong messagedowncase(): Chuyển log level sang lowercase
Log Type Detection Logic
| Condition | Log Type | Event Category |
|---|---|---|
kubernetes.pod_name exists | Pod Container Log | process |
event.type exists | K8s Event | configuration |
audit.verb exists | Audit Log | iam |
Log Level Mapping
| Message Contains | log.level | event.outcome |
|---|---|---|
| ERROR | error | failure |
| FATAL | fatal | failure |
| WARN | warning | unknown |
| INFO | info | success |
| DEBUG | debug | success |
K8s Event Reason Mapping
| Event Reason | event.action |
|---|---|
| Pulled | image_pulled |
| Created | container_created |
| Started | container_started |
| Killing | container_killing |
| BackOff | container_backoff |
| Scheduled | pod_scheduled |
| FailedScheduling | pod_scheduling_failed |
Audit Verb Mapping
| Audit Verb | event.action |
|---|---|
| create | resource_created |
| update | resource_updated |
| delete | resource_deleted |
| get | resource_read |
| list | resource_listed |
| watch | resource_watched |
| patch | resource_patched |
ECS Field Mapping
| K8s Field | ECS Field |
|---|---|
| kubernetes.pod_name | service.name |
| kubernetes.namespace_name | labels.namespace |
| kubernetes.container_name | container.name |
| kubernetes.container_id | container.id |
| kubernetes.host | host.hostname |
| kubernetes.labels.app | labels.app |
| audit.user | user.name |
Security Use Cases
- Error Monitoring: Track container errors với
log.level: error - Audit Compliance: Monitor API calls với
event.category: iam - Deployment Tracking: Theo dõi resource changes qua audit logs
- Pod Health: Monitor pod events (BackOff, FailedScheduling)
- Container Lifecycle: Track container create/start/kill events