Prepare and test your skills
Prepare and test your skills
Tracing latency and resource bottlenecks is the practice of combining aggregate metrics, per-request traces, and code profiles to separate slow code from saturated infrastructure and slow dependencies. In Google Cloud, Cloud Monitoring (opens in a new tab) shows how widespread latency is, Cloud Trace with Cloud Logging shows where time goes inside one distributed request, and Cloud Profiler (opens in a new tab) shows which functions consume CPU and memory in production. Traffic flows from users to Cloud Run (opens in a new tab) revisions or App Engine services, telemetry flows from those services to Monitoring, Trace, Logging, and Profiler, and decisions flow back to scaling settings or code fixes.
Cloud Monitoring quantifies whether latency affects all traffic or only a small fraction before deeper diagnosis begins. Cloud Run is automatically integrated with Cloud Monitoring with no setup, exposing a Request latencies dashboard and the metric Cloud Run Revision > Request_latencies > Request latency. App Engine exposes a latency dashboard with 50th, 95th, and 99th percentile latency, so high values on all three mean at least 50% of requests are slow, while high values only at the 99th percentile mean about 1% are slow. A spike must be read in the context of its time window, because a large spike in a small window can be negligible in a larger window and vice versa.
Cloud Trace and Cloud Logging isolate the slow request and reveal whether the delay comes from application code, a downstream call, or instance behavior. Correlated container logs tied to the request log let an operator identify the request, find its trace, and analyze root cause, while the traceSampled=true filter in Logs Explorer correlates sampled logs with traces in Cloud Trace. Each Cloud Run request log contains an instanceId that identifies the instance that handled it, which matters because one instance can handle multiple concurrent requests and share global-scope state such as a single connection-pool object. Dependencies require explicit logging of outbound calls, because without that logging, time spent waiting on another service can appear as latency originating in Cloud Run itself.
A consistent triage order prevents misattribution of latency to the wrong layer:
traceSampled=true, correlate the container logs with the request log, then filter by instanceId under resource Cloud Run Revision or Cloud Run Job to see sequential requests on the same instance.Exam tip: Without explicit logs for calls to other services, downstream wait time looks like Cloud Run latency, so add targeted dependency logging before concluding the bottleneck is local.
Cloud Profiler is a statistical, low-overhead profiler that continuously gathers CPU usage and memory-allocation data from production applications and attributes it to source code. Because collection is continuous and sampled, Cloud Profiler illuminates which functions are hot under real load without stopping the application, and flame-graph workflows for focusing the graph, comparing profiles across deployments, and viewing historical trends show whether a hotspot is new, growing, or persistent. Profiler answers the code question of which function is expensive, while layered metrics answer the capacity question of which tier is saturated.
Gathering metrics at every tier gives a holistic picture that one signal cannot:
When application-blocking latencies stay high while server latency is low, the bottleneck is likely client-side queuing, high client VM CPU, an undersized channel pool, or an intermediate network path rather than the backend service.
Remediation matches the diagnosed cause rather than scaling blindly, because adding capacity can overload a backing service. Increasing minimum instances keeps warm instances ready and avoids cold starts for incoming requests, while App Engine equivalents are larger instance classes, configured warmup requests, and adjusted dynamic scaling settings. Limiting maximum instances or otherwise adjusting scaling settings reduces the number of concurrent connections to a backing database or API when that dependency is the constraint. Code fixes address the remaining causes, including global variables reused across concurrent requests, oversized connection pools, missing indexes or inefficient queries, and hot functions identified by Cloud Profiler.
The three observability signals compose in a fixed order, with each signal answering a different question:
| Signal | Primary unit | Choose when |
|---|---|---|
| Cloud Monitoring | Aggregate latency and resource metrics | The question is how many requests are slow and whether CPU, memory, throughput, or node count changed |
| Cloud Trace with Cloud Logging | Sampled request trace correlated to logs | The question is which request is slow and whether time sits in local code, a dependency, or instance startup |
| Cloud Profiler | Function-level CPU and allocation profile | The question is which lines of code consume resources and whether the hotspot changed across releases |
Monitoring scopes the incident, Trace with Logging isolates the slow path and dependency, and Profiler proves the code hotspot, so a scaling change is made only after the trace and profile show whether capacity or code is the constraint.
Troubleshooting containerized application runtime and lifecycle failures in Google Kubernetes Engine (GKE) (opens in a new tab) means correlating live health signals from Cloud Monitoring (opens in a new tab) with historical evidence from Cloud Logging (opens in a new tab) to explain startup failures, crash loops, and probe mismatches. Cloud Monitoring metrics show whether a container is restarting, throttled, or approaching its memory limit, while Cloud Logging preserves the sequence of kubelet, runtime, and application events that led to the failure. Together they reveal whether the root cause is application code, probe configuration, or resource limit allocation.
Container health signals are Cloud Monitoring metrics that quantify how a container uses its configured requests and limits on its node. A rising kubernetes.io/container/restart_count highlights crashing apps, misconfigurations, or resource exhaustion, and it should be read alongside memory and CPU utilization to separate code crashes from kills by the platform. Because memory limit_utilization cannot exceed 1 while CPU limit_utilization can exceed 1, sustained memory pressure near 1.0 points toward an OutOfMemory (OOM) kill while high CPU values point toward throttling and performance degradation. Node pressure can mimic application failure, so container signals must be checked against node allocatable utilization when the sum of Pod usage strains available CPU or memory.
The core container signals for crash loops and pressure are:
kubernetes.io/container/restart_count tracks number of restarts to detect crash loops from app errors, bad configuration, or resource exhaustion.kubernetes.io/container/memory/limit_utilization tracks fraction of memory limit in use, capped at 1.0, to monitor risk of OOM errors.kubernetes.io/container/memory/used_bytes tracks actual memory consumed in bytes to identify leaks or growth toward the limit.kubernetes.io/container/memory/page_fault_count tracks major and minor page faults, where major faults mean memory is read from disk and indicate pressure even before limits are reached.kubernetes.io/container/cpu/limit_utilization tracks fraction of CPU limit in use, which can exceed 1.0, to identify throttling that degrades performance.kubernetes.io/container/ephemeral_storage/used_bytes tracks local temporary disk usage in bytes to prevent Pod evictions from full ephemeral storage.kubernetes.io/container/cpu/request_utilization tracks fraction of requested CPU in use, which can exceed 1.0, to identify over or under-provisioned CPU requests.kubernetes.io/container/memory/request_utilization tracks fraction of requested memory in use, which can exceed 1.0, to improve scheduling and prevent OOM errors.Runtime and application log sources in Cloud Logging are distinct streams from the node services, the container runtime, the application process, and the control plane that together cover the full container lifecycle. The kubelet manages the lifecycle of all Pods on a node, so its logs record container startups, OOM events, probe failures, and volume mount errors. The containerd runtime manages container lifecycle steps including pulling images, so its logs document activities and errors that happen before the kubelet can start the container.
The log sources differ in origin and in the failures they reveal:
| Log source | Collected from | Lifecycle failures it reveals |
|---|---|---|
| kubelet logs | Node service managing Pods on the node | Container startup sequence, probe failures, OOM events, volume mount errors, and NotReady node causes |
| containerd logs | Container runtime on the node | Image pull errors and runtime activities before container start |
| App logs | Container stdout and stderr streams | Application crashes, runtime errors, and unexpected behavior inside the process |
| Audit logs | Kubernetes API server calls | Who created, changed, or deleted objects such as Deployments, for failures caused by configuration changes |
App logs flow from the containerized process to Cloud Logging, while kubelet and containerd logs flow from node services to Cloud Logging, and audit logs flow from the API server to Cloud Logging. A failure with rich app logs points to code or probe handling inside the container, while empty app logs with kubelet or containerd errors points to image, resource, scheduling, or node-level causes.
Diagnosing startup failures, crash loops, and probe mismatches is an ordered correlation of metrics, app output, and node history that isolates the layer that first failed. First the restart and utilization signals establish whether the container is looping and whether memory or CPU limits are implicated, then the logs establish the exact startup, probe, or kill event. Only after the container layer is ruled out does the investigation move to scheduling and audit history.
restart_count for loop frequency, then read memory/limit_utilization and memory/used_bytes for OOM risk and cpu/limit_utilization for throttling.stdout and stderr to Cloud Logging to reveal crashes and errors from application code.Exam tip: Empty app logs with a Pod that never starts points to containerd image or kubelet scheduling pressure, not application code; memory/limit_utilization cannot exceed 1.0, while CPU utilization can exceed 1.0.
Isolating runtime exceptions and dependency integration issues means deciding whether a failure comes from application code or from an external service the code depends on. Cloud Error Reporting (opens in a new tab) isolates code errors by grouping crashes and exceptions, structured log parsing traces a single request across services and dependencies, and service-to-service identity and access management (IAM) audits prove whether the calling service identity still has permission to reach the dependency. Together the three signals separate a bug in code from a timeout, permission denial, or network block at a trust boundary.
Cloud Error Reporting is the centralized service that aggregates errors produced by running cloud services and displays top and new errors so root causes can be fixed faster. The service groups repeated stack traces into a single error issue, which makes a new deployment regression stand out from long-standing background errors. This grouping depends on errors arriving with stack-trace data that Error Reporting can parse.
Data flows from the application to Cloud Error Reporting through one of two paths: the application sends a properly formatted entry to Cloud Logging, which Error Reporting reads automatically, or the application calls an Error Reporting API endpoint that sends the error directly. Setup varies by platform and language, with guides for App Engine (opens in a new tab) standard and flexible environments, Cloud Run (opens in a new tab) , Cloud Functions, Compute Engine, Google Kubernetes Engine (GKE), and languages including Go, Java, Node.js, Python, PHP, Ruby, and .NET. Errors from Android and iOS clients flow through Firebase Crashlytics, formerly a separate mobile crash service, instead of direct Error Reporting ingestion.
Reporting depends on the workload identity holding the Error Reporting Writer role (roles/errorreporting.writer) and having the cloud-platform access scope. For GKE, the cluster must be created with the cloud-platform scope and a service account that holds the Writer role, and the service account cannot be changed after cluster creation. For Compute Engine, the virtual machine (VM) instance must be stopped, edited to attach a service account with the Writer role and to allow full access to all Cloud APIs, and then started again. If either dependency is missing, application exceptions will not appear in Error Reporting even though the code is still crashing.
Structured log parsing is the practice of writing correlated logs so container or application logs link to the same request log and trace. Cloud Logging holds the request log and application log entries, while Cloud Trace holds the timing trace for the same request. With correlation, an operator can identify the failing request, find its trace, and analyze whether time was spent in application code or waiting on a downstream dependency. Explicit logging around calls to other services is critical because without it, dependency latency appears as latency originating in the calling service itself.
Each Cloud Run request log contains an instanceId field that identifies the instance that handled the request, and filtering by that field isolates the sequential requests that led to a crash or slowdown. Filtering matters when one instance handles multiple concurrent requests and when a global-scope object, such as a single connection-pool object, is reused across those requests. To filter to one instance in Logs Explorer, the operator follows an ordered workflow where log data flows from the Cloud Run Revision or Cloud Run Job resource to the filtered view:
instanceId field.The filtered sequence reveals whether failures follow a cold start, follow increased concurrency, or follow reuse of shared global state. Cold-start and global-variable problems stay with one instance while other instances stay healthy, which proves the issue is instance-local rather than a dependency-wide outage. High-latency requests are further isolated by applying the traceSampled=true filter in Cloud Logging to correlate logs with traces in Cloud Trace, while App Engine percentile context and time-window context decide whether 50% or about 1% of requests are affected.
Service-to-service integration failures occur when application code is correct but the workload identity can no longer call a Google Cloud API. A common case is a GKE application that becomes unable to write to Cloud Storage after IAM permissions change, where GKE namespaces and role and cluster-role bindings control what the application identity can access. The audit must first decide whether traffic is blocked by the network or denied by policy, because a firewall denial and a permission denial require different fixes.
Cloud Audit Logs records who performed which action on which resource and when, with the audit data stored in the protoPayload field as an AuditLog object. The three log streams differ in what they capture and whether they are on by default, and retention plus export decisions determine how far back the audit can reach.
| Log stream | What it records | Enablement |
|---|---|---|
| Admin Activity logs | API calls or administrative actions that modify configuration or metadata | Always enabled |
| Data Access logs | API calls that create, modify, or read user-provided data | Disabled by default, except for BigQuery, and can grow large with cost and quota impact |
| System Event logs | System events performed by Compute Engine, such as each live migration | Generated by the system |
Viewing Admin Activity logs requires the Logs Viewer role (roles/logging.viewer) or basic Viewer role (roles/viewer), with least privilege preferred. Individual entries are kept for a specified retention period, and longer history requires export to Cloud Storage, BigQuery, or Pub/Sub, including aggregated exports that centralize logs across projects, folders, and billing accounts. For proactive detection, a Cloud Logging sink can filter organization-level SetIamPolicy calls and send matching entries to a Pub/Sub topic that triggers a Cloud Run function, so permission changes generate near-real-time notifications.
Connectivity Tests in Network Intelligence Center is a static configuration analyzer that checks connectivity between a source endpoint and a destination endpoint. Traffic paths tested include the Virtual Private Cloud (VPC) (opens in a new tab) network, VPC Network Peering, virtual private network (VPN) tunnels to on-premises, and paths from Cloud Run revisions and Cloud Run functions to a VM instance, IP address, or Google-managed service. A test result can identify a firewall rule blocking connectivity, which proves the failure sits at the network boundary rather than in IAM policy. Firewall Rules Logging complements the test by auditing actual rule effects, but logging must be enabled individually for each firewall rule whose connections need analysis.
Policy Troubleshooter debugs why one identity can access a resource while another cannot by comparing effective permissions. The three inputs are principal, which is the individual user, service account, or group requesting access, permission, which is the specific underlying permission required for the task, and resource, which is the project, bucket, image, or other object being accessed. IAM Recommender adds time context by running a daily job that analyzes IAM access-log data against permissions granted over the previous 60 days. If a recommendation to remove unused permissions was recently approved and applied, a previously working service-to-service call can start failing with a permission denial.
Exam tip: Policy Troubleshooter requires the underlying permission, not the IAM role name, plus the principal and resource — for example, creating an instance from a Compute Engine image requires the compute.imageUser role with its nine permissions, so the principal must hold all nine through combined roles.
traceSampled=true and instanceId, and Cloud Profiler proves which functions consume CPU and memory.kubernetes.io/container/restart_count detects crash loops, memory limit_utilization cannot exceed 1.0 and signals OutOfMemory risk near 1.0, while CPU limit_utilization can exceed 1.0 and signals throttling.cloud-platform scope, and missing Writer permissions prevent exceptions from appearing.protoPayload field for IAM permission audits.Cloud Monitoring answers how many requests are slow and whether CPU, memory, throughput, or node count changed by showing aggregate latency and resource metrics. Cloud Trace with Cloud Logging answers which request is slow and whether time sits in local code, a dependency, or instance startup by correlating a sampled request trace to logs. Cloud Profiler answers which lines of code consume resources and whether the hotspot changed across releases by providing function-level CPU and allocation profiles.
Filter by traceSampled=true in Logs Explorer to correlate sampled logs with traces in Cloud Trace and correlate container logs tied to the request log to identify the request. Then filter by instanceId under the Cloud Run Revision or Cloud Run Job resource to see sequential requests on the same instance and check for explicit dependency logs, cold-start patterns, and global-state reuse before changing scaling or code. Without explicit logs for calls to other services, downstream wait time looks like Cloud Run latency.
Start with kubernetes.io/container/restart_count to detect crash loops and read it alongside memory and CPU utilization to separate code crashes from kills by the platform. Sustained memory limit_utilization near 1.0 points toward an OutOfMemory kill because memory limit_utilization cannot exceed 1.0, while high CPU limit_utilization points toward throttling and performance degradation because CPU limit_utilization can exceed 1.0. Check node allocatable utilization as well because node pressure can mimic application failure when the sum of Pod usage strains available CPU or memory.
Exceptions only appear when the workload identity holds the Error Reporting Writer role and has the cloud-platform access scope, so missing Writer permissions prevent exceptions from appearing even though the code is still crashing. For Google Kubernetes Engine (GKE) the cluster must be created with the cloud-platform scope and a service account that holds the Writer role and the service account cannot be changed after cluster creation. For Compute Engine the virtual machine instance must be stopped, edited to attach a service account with the Writer role and to allow full access to all Cloud APIs, and then started again.
A production microservice running on Cloud Run begins throwing intermittent HTTP 403 Forbidden runtime exceptions when attempting to integrate with downstream Google Cloud storage services. A recent security update introduced both VPC Service Controls perimeters and revised identity policies across service accounts. You need to isolate whether the integration failures originate from service account IAM permission gaps or VPC Service Controls perimeter restrictions, while identifying the exact caller identity and requested method.
Which troubleshooting strategy should you use to isolate the root cause?
Last updated