Skip to content

This tool is not affiliated with, endorsed by or sponsored by The Linux Foundation, the Cloud Native Computing Foundation (CNCF) or the Kubernetes project. Kubernetes and K8s are registered trademarks of The Linux Foundation. EKS, GKE, AKS and other names are trademarks of their respective owners.

EKS, GKE and AKS Audit Logs: Enable and Export Them

How to enable and export Kubernetes audit logs on Amazon EKS, Google GKE and Azure AKS: where they live, what the managed policy drops, and the export commands.

Published on 6 min read

TL;DR. On managed Kubernetes you cannot edit the audit policy, but you decide whether the audit log is kept at all. EKS: enable the audit control-plane log type; events land in CloudWatch Logs, group /aws/eks/<cluster>/cluster, streams kube-apiserver-audit-*. GKE: Admin Activity (writes) is always on; reads, including secret reads, go to Data Access logs, which you must enable for the Kubernetes Engine API. AKS: create a diagnostic setting with the kube-audit category (or kube-audit-admin, which drops get and list). Export as JSON, then drop the files into the audit log analyzer.

None of these three is on by default in a way that covers an investigation. The worst time to discover that is the morning after an alert. This guide covers what to switch on now and how to get the data out when you need it.

Amazon EKS

Enable

By default, EKS sends no control-plane logs to CloudWatch; each log type is enabled individually, as the EKS control plane logging documentation states. In the console: cluster, Observability, Control plane logging, Manage logging, turn on Audit (and Authenticator, which maps IAM principals to Kubernetes users). With the CLI:

aws eks update-cluster-config --region eu-west-1 --name my-cluster \
  --logging '{"clusterLogging":[{"types":["audit","authenticator"],"enabled":true}]}'

Standard CloudWatch Logs ingestion and storage charges apply. Delivery is best effort and usually takes a few minutes. Set a retention on the log group that matches your investigation needs.

What the EKS policy logs

AWS publishes the EKS audit policy in the EKS best practices guide. Points that matter for forensics:

  • Secrets, configmaps and token reviews: Metadata only.
  • serviceaccounts/token: Request.
  • Reads (get, list, watch) on core and well-known API groups: Request; writes: RequestResponse. Workload specs and RBAC bodies are therefore available.
  • events are not logged at all. A deletion of Events will not appear.
  • CloudWatch Logs entries are capped at 1 MB while an API request can reach 1.5 MiB, so very large objects may be truncated or reduced to metadata.

Export

For a short range, filter-log-events is enough:

aws logs filter-log-events --log-group-name /aws/eks/my-cluster/cluster \
  --log-stream-name-prefix kube-apiserver-audit \
  --start-time 1789344000000 --end-time 1789430400000 > eks-audit.json

Times are in epoch milliseconds. For days or weeks of logs, use an export task to S3 (aws logs create-export-task) and download the .gz objects: each line is a timestamp followed by the JSON event. CloudWatch Logs Insights results exported as JSON work too. The analyzer reads all three shapes, including gzip files and whole folders.

IAM identities show up in the audit log under the username mapped by access entries or the aws-auth ConfigMap. To follow the same principal on the AWS side (CloudTrail, the EKS API, AssumeRole calls), see AWS Forensics.

Google GKE

Two logs, one of them off by default

GKE writes Kubernetes audit entries to Cloud Audit Logs under the k8s_cluster resource type. The GKE audit policy routes them:

  • create, update and delete requests go to the Admin Activity log, which is always on and cannot be disabled.
  • get, list and updateStatus go to the Data Access log, which, as the GKE audit logging page notes, is disabled by default and billed when enabled.

The consequence is blunt: on a default GKE project, an attacker who reads every secret with get leaves no audit entry for those reads. Enable Data Access logs for the Kubernetes Engine API in IAM & Admin, Audit Logs before you need them, and weigh the volume against the cost.

What the GKE policy logs

The same page states that requests on secrets, configmaps and token reviews are logged at Metadata, reads are generally Metadata, and writes are generally RequestResponse. Workload specs and RBAC bindings are therefore visible for writes.

In Cloud Logging the event is rewritten: protoPayload.methodName (for example io.k8s.core.v1.pods.exec.create), protoPayload.resourceName, protoPayload.authenticationInfo.principalEmail, protoPayload.requestMetadata.callerIp and callerSuppliedUserAgent, a gRPC status code instead of HTTP. The analyzer maps these back to verb, resource, subresource, user, IP and HTTP code.

Export

gcloud logging read \
  'resource.type="k8s_cluster" AND logName:"cloudaudit.googleapis.com"' \
  --project=my-project --freshness=30d --format=json > gke-audit.json

You can also download results from Logs Explorer as JSON, or, for long periods, route the logs with a sink to Cloud Storage or BigQuery. BigQuery stores the payload in protopayload_auditlog with request and response bodies as JSON text; the analyzer reads those rows when you export the table or query results as JSON or newline-delimited JSON (not CSV, Avro or Parquet). Retention depends on the log bucket: Admin Activity logs go to the _Required bucket, Data Access logs to _Default, unless you changed the routing. For the Google Cloud side of an incident (IAM, service account keys, Compute), GCP Forensics covers those logs.

One current limitation of the analyzer: GKE impersonation details carried in serviceAccountDelegationInfo are not yet mapped.

Azure AKS

Enable

AKS sends control-plane logs through a diagnostic setting on the cluster resource. The AKS monitoring documentation describes the audit categories:

CategoryContains
kube-auditEvery audit event, including get and list
kube-audit-adminThe same without get and list events

kube-audit is the one you want for credential theft, since secret reads are get and list. Microsoft warns that it can be expensive; kube-audit-admin is the cheaper compromise, at the price of losing reads. Destinations:

  • Log Analytics, in resource-specific mode (tables AKSAudit and AKSAuditAdmin) or legacy Azure diagnostics mode (table AzureDiagnostics, event JSON in log_s).
  • Storage account: hourly PT1H.json blobs under the insights-logs-kube-audit container.
  • Event Hubs: {"records": [...]} batches, typically consumed by a SIEM.

Example with the Azure CLI, sending to Log Analytics in resource-specific mode:

az monitor diagnostic-settings create --name aks-audit \
  --resource <aks-resource-id> --workspace <workspace-resource-id> \
  --export-to-resource-specific true \
  --logs '[{"category":"kube-audit","enabled":true}]'

Export

From a storage account, download the PT1H.json blobs for the period (the folder structure encodes the date and hour) and drop the whole folder. From Log Analytics, query the table and save the result as JSON rather than CSV:

az monitor log-analytics query --workspace <workspace-guid> \
  --analytics-query "AKSAudit | where TimeGenerated between (datetime(2026-09-13) .. datetime(2026-09-15))" \
  -o json > aks-audit.json

Query results are capped in size, so split long ranges into several queries. The analyzer reads AKSAudit rows (PascalCase columns), AzureDiagnostics rows, storage-account blobs and Event Hubs batches. For Entra ID sign-ins and Azure activity around the cluster, see Azure Forensics.

Self-managed clusters

On kubeadm, k3s, RKE2 or on-premises distributions, you own the policy and the files. Copy audit.log and its rotated siblings from every control-plane node (each API server logs only the requests it served), or export from wherever your webhook or log shipper sends them. The audit policy article has a forensics-oriented policy to start from.

Before you analyze

  • Cover the whole period, starting days before the first suspicious event.
  • Keep the originals untouched and work on copies; record hashes if the case may go to court.
  • Note the time zone. Audit timestamps are UTC; console exports may not be.
  • Check for gaps. A day with no events at all usually means a logging change, not a quiet cluster.

Then open the Kubernetes audit log analyzer, drop the files or folders, and follow the step-by-step analysis guide.

Related articles

The blind spots of Kubernetes audit logs: in-container activity, kubelet and etcd access, policy gaps, spoofable fields, and the evidence that fills them.
A fictional Kubernetes incident, step by step in the audit log: exposed dashboard token, can-i recon, secret theft, privileged DaemonSet, cluster-admin, XMRig.
Step-by-step Kubernetes audit log analysis with a free in-browser tool: load EKS, GKE, AKS or raw exports, read the verdict, findings, timeline and entities.

This tool is not affiliated with, endorsed by or sponsored by The Linux Foundation, the Cloud Native Computing Foundation (CNCF) or the Kubernetes project. Kubernetes and K8s are registered trademarks of The Linux Foundation. EKS, GKE, AKS and other names are trademarks of their respective owners.