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 string
  • to_int(): Chuyển đổi response code sang integer
  • parse_regex(): Extract log level và container ID
  • contains(): Kiểm tra log level trong message
  • downcase(): Chuyển log level sang lowercase

Log Type Detection Logic

ConditionLog TypeEvent Category
kubernetes.pod_name existsPod Container Logprocess
event.type existsK8s Eventconfiguration
audit.verb existsAudit Logiam

Log Level Mapping

Message Containslog.levelevent.outcome
ERRORerrorfailure
FATALfatalfailure
WARNwarningunknown
INFOinfosuccess
DEBUGdebugsuccess

K8s Event Reason Mapping

Event Reasonevent.action
Pulledimage_pulled
Createdcontainer_created
Startedcontainer_started
Killingcontainer_killing
BackOffcontainer_backoff
Scheduledpod_scheduled
FailedSchedulingpod_scheduling_failed

Audit Verb Mapping

Audit Verbevent.action
createresource_created
updateresource_updated
deleteresource_deleted
getresource_read
listresource_listed
watchresource_watched
patchresource_patched

ECS Field Mapping

K8s FieldECS Field
kubernetes.pod_nameservice.name
kubernetes.namespace_namelabels.namespace
kubernetes.container_namecontainer.name
kubernetes.container_idcontainer.id
kubernetes.hosthost.hostname
kubernetes.labels.applabels.app
audit.useruser.name

Security Use Cases

  1. Error Monitoring: Track container errors với log.level: error
  2. Audit Compliance: Monitor API calls với event.category: iam
  3. Deployment Tracking: Theo dõi resource changes qua audit logs
  4. Pod Health: Monitor pod events (BackOff, FailedScheduling)
  5. Container Lifecycle: Track container create/start/kill events

logo
CMC Telecom
Aspire to Inspire the Digital World