<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Elastic Observability Labs - Google Cloud</title>
        <link>https://www.elastic.co/observability-labs</link>
        <description>Trusted security news &amp; research from the team at Elastic.</description>
        <lastBuildDate>Fri, 10 Jul 2026 05:08:02 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>Elastic Observability Labs - Google Cloud</title>
            <url>https://www.elastic.co/observability-labs/assets/observability-labs-thumbnail.png</url>
            <link>https://www.elastic.co/observability-labs</link>
        </image>
        <copyright>© 2026. Elasticsearch B.V. All Rights Reserved</copyright>
        <item>
            <title><![CDATA[Scale testing OpenTelemetry log ingestion on GCP with EDOT Cloud Forwarder]]></title>
            <link>https://www.elastic.co/observability-labs/blog/edot-cloud-forwarder-gcp-load-testing</link>
            <guid isPermaLink="false">edot-cloud-forwarder-gcp-load-testing</guid>
            <pubDate>Wed, 04 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Learn how we load tested the EDOT Cloud Forwarder for GCP on Google Cloud Run and identified practical capacity limits per instance. We show how runtime tuning improves stability and translate the results into concrete configuration and scaling guidance.]]></description>
            <content:encoded><![CDATA[<p>EDOT Cloud Forwarder (ECF) for GCP is an event-triggered, serverless OpenTelemetry Collector deployment for Google Cloud. It runs the OpenTelemetry Collector on Cloud Run, ingests events from Pub/Sub and Google Cloud Storage, parses Google Cloud service logs into OpenTelemetry semantic conventions, and forwards the resulting OTLP data to Elastic, relying on Cloud Run for scaling, execution, and infrastructure lifecycle management.</p>
<p>To run ECF for GCP confidently at scale, you need to understand its capacity characteristics and sizing behavior. For ECF for GCP which is part of the broader <a href="https://www.elastic.co/docs/reference/opentelemetry/edot-cloud-forwarder/gcp">ECF architecture</a>, we answered those questions through repeatable load testing and by grounding decisions in measured data.</p>
<p>We'll introduce the test setup, explain each runtime setting, and share the capacity numbers we observed for a single instance.</p>
<h2>How we load tested EDOT Cloud Forwarder for GCP</h2>
<h3>Architecture</h3>
<p><img src="https://www.elastic.co/observability-labs/assets/images/edot-cloud-forwarder-gcp-load-testing/load-testing.png" alt="Load testing overview" /></p>
<p>The load testing architecture simulates a realistic, high-volume pipeline:</p>
<ol>
<li>We developed a load tester service that uploads generated log files to a GCS bucket as fast as possible.</li>
<li>Each file creation in this Google Cloud Storage (GCS) bucket then triggers an event notification to Pub/Sub.</li>
<li>Pub/Sub delivers push messages to a Cloud Run service where EDOT Cloud Forwarder fetches and processes these log files.</li>
</ol>
<p>Our setup exposes two primary tunable settings that directly influence Cloud Run scaling behavior and memory pressure:</p>
<ul>
<li>Request pressure using a concurrency setting (how many concurrent requests each ECF instance can handle).</li>
<li>Work per request using a log count setting (number of logs per file in each uploaded object).</li>
</ul>
<p>In our tests, we used a testing system that:</p>
<ul>
<li>Deploys the whole testing infrastructure. This includes the complete ECF infrastructure, a mock backend, etc.</li>
<li>Generates log files according to the configured log counts, using a Cloud Audit log of ~1.4 KB.</li>
<li>Runs a matrix of tests across all combinations of concurrency and log volume.</li>
<li>Produces a report for each tested concurrency level in which several stats are reported, such as CPU usage and memory consumption.</li>
</ul>
<p>For reproducibility and isolation, the <code>otlphttp</code> exporter in EDOT Cloud Forwarder uses a <strong>mock backend</strong> that always returns HTTP 200. This ensures all observed behavior is attributable to ECF itself, not downstream systems or network variability.</p>
<h2>Step 1: Establish a stable runtime before measuring capacity</h2>
<p>Before asking how much load a single instance can handle, we first established a stable runtime baseline.</p>
<p>We quickly learned that a single flag, <code>cpu_idle</code>, can turn Cloud Run into a garbage-collector (GC) starvation trap. This is amplified by a known <a href="https://www.elastic.co/docs/reference/opentelemetry/edot-cloud-forwarder/gcp#limitations">limitation</a> of our ECF current architecture: the existing OpenTelemetry implementation reads whole log files into memory before processing them. Our goal was to eliminate configuration side effects so capacity tests reflected ECF actual limits.</p>
<p>We focused on three runtime parameters:</p>
<table>
<thead>
<tr>
<th>Setting</th>
<th>What it controls</th>
<th>Why it matters for ECF</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>cpu_idle</code></td>
<td>Whether CPU is always allocated or only during requests</td>
<td>Dictates how much background time the garbage collector gets to reclaim memory</td>
</tr>
<tr>
<td><code>GOMEMLIMIT</code></td>
<td>Upper bound on Go heap size inside the container</td>
<td>Keeps the process from quietly growing until Cloud Run kills it on OOM</td>
</tr>
<tr>
<td><code>GOGC</code></td>
<td>Heap growth and collection aggressiveness in Go</td>
<td>Trades lower memory usage for higher CPU consumption</td>
</tr>
</tbody>
</table>
<p>All parameter-isolation tests use a single Cloud Run instance (min 0, max 1), fix concurrency for the scenario under study, and keep input files and test matrix identical across runs. This design lets us attribute differences directly to the parameter in question.</p>
<h3>CPU allocation: Stop starving the garbage collector</h3>
<p>Cloud Run offers two CPU allocation modes:</p>
<ul>
<li>Request-based (throttled). Enabled with <code>cpu_idle: true</code>. CPU is available only while a request is actively being processed.</li>
<li>Instance-based (always on). Enabled with <code>cpu_idle: false</code>. CPU remains available when idle, allowing background work such as garbage collection to run.</li>
</ul>
<p>The tests compared these modes under identical conditions:</p>
<table>
<thead>
<tr>
<th>Parameter</th>
<th align="center">Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>vCPU</td>
<td align="center">1</td>
</tr>
<tr>
<td>Memory</td>
<td align="center">4 GiB (high enough to remove OOM as a factor)</td>
</tr>
<tr>
<td><code>GOMEMLIMIT</code></td>
<td align="center">90% of memory</td>
</tr>
<tr>
<td><code>GOGC</code></td>
<td align="center">Default (unset)</td>
</tr>
<tr>
<td>Concurrency</td>
<td align="center">10</td>
</tr>
</tbody>
</table>
<h4>What we observed</h4>
<p><img src="https://www.elastic.co/observability-labs/assets/images/edot-cloud-forwarder-gcp-load-testing/cpu_allocation.png" alt="CPU allocation" /></p>
<p>With CPU allocated only on requests (<code>cpu_idle: true</code>):</p>
<ul>
<li>Memory variance was extreme (±71% RSS, ±213% heap).</li>
<li>Peak heap reached ~304 MB in the worst run.</li>
<li>We saw request refusals in the sample (90% success rate).</li>
</ul>
<p>With CPU always allocated (<code>cpu_idle: false</code>):</p>
<ul>
<li>Memory variance became tightly bounded (±8% RSS, ±32% heap).</li>
<li>Peak heap dropped to ~89 MB in the worst run.</li>
<li>We saw no refusals in the sample (100% success).</li>
</ul>
<p>From these runs we saw:</p>
<ul>
<li>When CPU is throttled, the Go garbage collector is effectively starved, leading to heap accumulation and large run-to-run variance.</li>
<li>When CPU is always available, garbage collection keeps pace with allocation, resulting in lower and more predictable memory usage.</li>
</ul>
<p><em>Takeaway:</em> for this set of tests, <code>cpu_idle: false</code> was the most stable baseline configuration. Request-based CPU throttling introduced artificial instability that makes capacity planning much harder.</p>
<h3>Go memory limit: <code>GOMEMLIMIT</code> in constrained containers</h3>
<p>Cloud Run enforces a hard memory limit at the container level. If the process exceeds it, the instance is OOM-killed.</p>
<p>We tested Cloud Run with:</p>
<table>
<thead>
<tr>
<th>Parameter</th>
<th align="center">Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>Container memory</td>
<td align="center">512 MiB</td>
</tr>
<tr>
<td>vCPU</td>
<td align="center">1</td>
</tr>
<tr>
<td>Concurrency</td>
<td align="center">20</td>
</tr>
<tr>
<td><code>GOGC</code></td>
<td align="center">Default (unset)</td>
</tr>
<tr>
<td><code>cpu_idle</code></td>
<td align="center"><code>false</code></td>
</tr>
</tbody>
</table>
<p>The tests compared:</p>
<ul>
<li>No <code>GOMEMLIMIT</code> (Go relies on OS pressure).</li>
<li><code>GOMEMLIMIT=460MiB</code> (or 90% of container memory).</li>
</ul>
<p>The results were clear:</p>
<table>
<thead>
<tr>
<th><code>GOMEMLIMIT</code></th>
<th>Outcome</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td>Unset</td>
<td>Unstable; repeated OOM kills</td>
<td>Service never produced stable results</td>
</tr>
<tr>
<td><code>460MiB</code></td>
<td>Stable; runs completed</td>
<td>Worst-case peak RSS reached ~505 MB, but the process within container limits</td>
</tr>
</tbody>
</table>
<p><em>Takeaway:</em> in a memory-constrained environment like Cloud Run, setting <code>GOMEMLIMIT</code> close to (but below) the container limit is essential for predictable behavior under load.</p>
<h3>GOGC: memory savings vs. reliability</h3>
<p>The <code>GOGC</code> parameter controls how much the heap can grow (in %) between GC cycles:</p>
<ul>
<li>Lower values (e.g., <code>GOGC=50</code>): more frequent collections, lower memory, higher CPU.</li>
<li>Higher values (e.g., <code>GOGC=100</code>): fewer collections, higher memory, lower CPU.</li>
</ul>
<p>The tests covered: (1) <code>GOGC=50</code> (aggressive); (2) <code>GOGC=75</code> (moderate); (3) <code>GOGC=100</code> (default/unset).</p>
<p>Setup:</p>
<table>
<thead>
<tr>
<th>Parameter</th>
<th align="center">Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>Container memory</td>
<td align="center">4  GiB (high enough to remove OOM as a factor)</td>
</tr>
<tr>
<td>vCPU</td>
<td align="center">1</td>
</tr>
<tr>
<td>Concurrency</td>
<td align="center">10 (safe level)</td>
</tr>
<tr>
<td><code>GOMEMLIMIT</code></td>
<td align="center">90% of memory</td>
</tr>
<tr>
<td><code>cpu_idle</code></td>
<td align="center"><code>false</code></td>
</tr>
</tbody>
</table>
<h4>What we observed</h4>
<p><img src="https://www.elastic.co/observability-labs/assets/images/edot-cloud-forwarder-gcp-load-testing/gogc.png" alt="GOGC" /></p>
<p>From the runs:</p>
<table>
<thead>
<tr>
<th align="center"><code>GOGC</code></th>
<th align="center">Peak RSS (sample)</th>
<th>CPU behavior</th>
<th align="center">Failure rate</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td align="center">50</td>
<td align="center">~267 MB</td>
<td>Very high; often saturating</td>
<td align="center">30%</td>
<td>GC consumed cycles needed for ingestion</td>
</tr>
<tr>
<td align="center">75</td>
<td align="center">~454 MB</td>
<td>~83.5% avg</td>
<td align="center">10%</td>
<td>GC consumed cycles needed for ingestion</td>
</tr>
<tr>
<td align="center">100 (default)</td>
<td align="center">~472 MB</td>
<td>~83.5% avg; leaves headroom for bursts</td>
<td align="center">0%</td>
<td></td>
</tr>
</tbody>
</table>
<p>The conclusion from these runs is clear: pushing <code>GOGC</code> down trades memory for reliability, and the trade is not favorable for ECF.</p>
<p><em>Takeaway:</em> for this workload, the default <code>GOGC=100</code> provided the best balance. Attempts to optimize memory by lowering <code>GOGC</code> directly reduced reliability.</p>
<h2>Step 2: Find capacity and breaking points</h2>
<p>With the runtime stabilized, we evaluated how much traffic a single instance can sustain by increasing concurrency until failures emerged.</p>
<p><em>How to read the tables:</em> each concurrency level was tested across 20 runs covering both light (240 logs per file, around 362KB file size) and heavy inputs (over 6k logs per file, around 8MB file size). Tables report baseline RSS from light workloads and peak values from the worst-case run.</p>
<h3>Concurrency 5: Stable baseline</h3>
<p><img src="https://www.elastic.co/observability-labs/assets/images/edot-cloud-forwarder-gcp-load-testing/concurrency_5.png" alt="Concurrency 5" /></p>
<p>At concurrency 5, the service was solid.</p>
<table>
<thead>
<tr>
<th align="left">Case</th>
<th align="right">Memory (RSS)</th>
<th align="right">CPU utilization</th>
<th align="left">Requests refused</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">Baseline (lightest workload avg)</td>
<td align="right">99.89 MB</td>
<td align="right"></td>
<td align="left"></td>
</tr>
<tr>
<td align="left">Worst run</td>
<td align="right">211.02 MB</td>
<td align="right">86.43%</td>
<td align="left">No</td>
</tr>
</tbody>
</table>
<p>This proved that a single instance handles a moderate load comfortably, with memory usage staying well within safe limits.</p>
<h3>Concurrency 10: Safe but volatile</h3>
<p><img src="https://www.elastic.co/observability-labs/assets/images/edot-cloud-forwarder-gcp-load-testing/concurrency_10.png" alt="Concurrency 10" /></p>
<p>At concurrency 10, the system remained functional but with significant volatility.</p>
<table>
<thead>
<tr>
<th align="left">Case</th>
<th align="right">Memory (RSS)</th>
<th align="right">CPU utilization</th>
<th align="left">Requests refused</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">Baseline (lightest workload avg)</td>
<td align="right">100.33 MB</td>
<td align="right"></td>
<td align="left"></td>
</tr>
<tr>
<td align="left">Worst run</td>
<td align="right">424.80 MB</td>
<td align="right">94.10%</td>
<td align="left">No (in sample)</td>
</tr>
</tbody>
</table>
<p>We also noticed that memory usage shows extreme variance:</p>
<ul>
<li>Best run RSS: 178 MB.</li>
<li>Worst run RSS: 425 MB.</li>
</ul>
<p>This behavior comes mainly from two effects:</p>
<ul>
<li>Bursty Pub/Sub delivery: 10 heavy requests may land at nearly the same instant.</li>
<li>The use of <code>io.ReadAll</code> inside the collector: each request reads the entire log file into memory.</li>
</ul>
<p>When all 10 requests arrived concurrently, we were effectively stacking ~10× file size in RAM before the GC can clean up. When they are slightly staggered, GC has time to reclaim memory between requests, leading to much lower peaks.</p>
<p>This leads to a crucial sizing insight:</p>
<ul>
<li>Do not size the service using average memory (for example, ~260 MB).</li>
<li>Size it for the worst observed burst (~425 MB) to avoid OOM or GC stalls.</li>
</ul>
<p>In practice, you should set the memory limit to at least 512 MiB per instance at concurrency 10.</p>
<h3>Concurrency 20: Unstable, systemic load shedding</h3>
<p><img src="https://www.elastic.co/observability-labs/assets/images/edot-cloud-forwarder-gcp-load-testing/concurrency_20.png" alt="Concurrency 20" /></p>
<p>At concurrency 20, the system consistently began shedding load.</p>
<table>
<thead>
<tr>
<th align="left">Case</th>
<th align="right">Memory (RSS)</th>
<th align="right">CPU utilization</th>
<th align="left">Requests refused</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">Baseline (lightest workload avg)</td>
<td align="right">97.44 MB</td>
<td align="right"></td>
<td align="left"></td>
</tr>
<tr>
<td align="left">Worst run</td>
<td align="right">482.42 MB</td>
<td align="right">88.90%</td>
<td align="left">Yes (every run)</td>
</tr>
</tbody>
</table>
<p>Even though memory and CPU metrics don't look drastically worse than at concurrency 10, behavior changes qualitatively: the service begins to refuse requests consistently.</p>
<h3>Concurrency 40: Failure mode</h3>
<p><img src="https://www.elastic.co/observability-labs/assets/images/edot-cloud-forwarder-gcp-load-testing/concurrency_40.png" alt="Concurrency 40" /></p>
<p>At concurrency 40, the instance collapsed completely. Memory and CPU are overwhelmed, and ingest reliability collapses.</p>
<table>
<thead>
<tr>
<th align="left">Case</th>
<th align="right">Memory (RSS)</th>
<th align="right">CPU utilization</th>
<th align="left">Requests refused</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">Baseline (lightest workload avg)</td>
<td align="right">100.20 MB</td>
<td align="right"></td>
<td align="left"></td>
</tr>
<tr>
<td align="left">Worst run</td>
<td align="right">1234.28 MB</td>
<td align="right">96.57%</td>
<td align="left">Yes (all runs)</td>
</tr>
</tbody>
</table>
<h3>The breaking point: a 1 vCPU instance's realistic limits</h3>
<table>
<thead>
<tr>
<th align="center">Concurrency</th>
<th align="center">Peak RSS (MB)</th>
<th align="center">Stability</th>
<th align="center">Refusals?</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td align="center">5</td>
<td align="center">211.02</td>
<td align="center">Low variance</td>
<td align="center">No</td>
<td>Stable baseline</td>
</tr>
<tr>
<td align="center">10</td>
<td align="center">424.80</td>
<td align="center">High variance</td>
<td align="center">No</td>
<td>Safe but volatile</td>
</tr>
<tr>
<td align="center">20</td>
<td align="center">482.42</td>
<td align="center">High variance</td>
<td align="center">Yes (Frequent)</td>
<td>Unstable (sheds load)</td>
</tr>
<tr>
<td align="center">40</td>
<td align="center">1234.28</td>
<td align="center">Extreme variance</td>
<td align="center">Yes (Always)</td>
<td>Failure (memory explosion)</td>
</tr>
</tbody>
</table>
<p>Combined with the CPU data (94% peak at concurrency 10), this supports a practical rule: <strong>for this workload</strong> and architecture, 10 concurrent heavy requests per 1 vCPU instance is the realistic upper bound.</p>
<h2>Turning findings into concrete recommendations</h2>
<p>These experiments lead to clear, actionable recommendations for running the ECF OpenTelemetry collector on Cloud Run as part of the broader Elastic Cloud Forwarder deployment.</p>
<p>Scope: these recommendations apply to the workload and harness we tested (light vs. heavy log files up to 8MB, and Pub/Sub burst delivery), using the tuned runtime settings listed below. If your log sizes, request burstiness, or pipeline shape differ significantly, validate these limits against your own traffic.</p>
<h3>Runtime and container configuration</h3>
<table>
<thead>
<tr>
<th>Area</th>
<th>Recommendation</th>
<th>Rationale</th>
</tr>
</thead>
<tbody>
<tr>
<td>CPU allocation</td>
<td>Set <code>cpu_idle: false</code> (always-on CPU)</td>
<td>Avoids GC starvation, stabilizes memory variance, and eliminates request failures caused by long GC pauses</td>
</tr>
<tr>
<td>Go memory limit</td>
<td>Set <code>GOMEMLIMIT</code> to ~90% of container memory</td>
<td>Enforces a heap boundary aligned with the Cloud Run limit so that Go reacts before the OS, preventing OOM kills</td>
</tr>
<tr>
<td>Garbage collection</td>
<td>Keep <code>GOGC</code> at 100 (default)</td>
<td>Lower <code>GOGC</code> reduces memory at the cost of higher CPU usage and measurable failure rates</td>
</tr>
</tbody>
</table>
<h3>Capacity and per-instance limits</h3>
<p>For a 1 vCPU Cloud Run instance running the ECF OpenTelemetry collector with the tuned runtime:</p>
<table>
<thead>
<tr>
<th>Limit</th>
<th>Recommendation</th>
<th>Rationale</th>
</tr>
</thead>
<tbody>
<tr>
<td>Hard concurrency</td>
<td>Cap concurrency at 10 requests per instance</td>
<td>At concurrency 10, CPU already reaches ~94% in the worst run; higher concurrency drives instability (refusals, GC stalls)</td>
</tr>
<tr>
<td>Memory</td>
<td>Use at least 512 MiB per instance (for concurrency 10)</td>
<td>Worst-case observed RSS is ~425 MB; 512 MiB provides a narrow but workable safety margin against burst alignment</td>
</tr>
</tbody>
</table>
<h3>Scaling strategy: horizontal, not vertical</h3>
<ul>
<li>Vertical scaling (increasing concurrency per instance) quickly runs into CPU and memory limits for this workload.</li>
<li>Horizontal scaling is a better fit: treat each instance as a worker with a hard limit of 10 concurrent heavy jobs.</li>
</ul>
<p>Practically:</p>
<ul>
<li>Configure the service so that no instance exceeds 10 concurrent requests.</li>
<li>Let autoscaling handle an increased load by adding instances, not by increasing per-instance concurrency.</li>
</ul>
<h2>Takeaways</h2>
<ul>
<li>Tuned runtime settings matter as much as raw resources: a single flag like <code>cpu_idle</code> can be the difference between predictable behavior and GC-driven chaos.</li>
<li>Go needs explicit limits in containers: <code>GOMEMLIMIT</code> must be set in memory-constrained environments; otherwise, OOM kills are inevitable under heavy ingesting.</li>
<li>&quot;Lower memory&quot; is not always better: aggressive GC tuning (<code>GOGC</code> &lt; 100) did reduce memory usage but directly increased failure rates.</li>
<li>Concurrency 10 is the realistic ceiling for a 1 vCPU ECF instance; beyond that, refusals and instability become the norm.</li>
<li>Horizontal scaling is the right model: each instance should be treated as a 10-request worker, with higher total throughput coming from more workers rather than more concurrency per worker.</li>
</ul>
]]></content:encoded>
            <category>observability-labs</category>
            <enclosure url="https://www.elastic.co/observability-labs/assets/images/edot-cloud-forwarder-gcp-load-testing/cover-gcp.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[Elastic Observability monitors metrics for Google Cloud in just minutes]]></title>
            <link>https://www.elastic.co/observability-labs/blog/observability-monitors-metrics-google-cloud</link>
            <guid isPermaLink="false">observability-monitors-metrics-google-cloud</guid>
            <pubDate>Mon, 20 Nov 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Follow this step-by-step process to enable Elastic Observability for Google Cloud Platform metrics.]]></description>
            <content:encoded><![CDATA[<p>Developers and SREs choose to host their applications on Google Cloud Platform (GCP) for its reliability, speed, and ease of use. On Google Cloud, development teams are finding additional value in migrating to Kubernetes on GKE, leveraging the latest serverless options like Cloud Run, and improving traditional, tiered applications with managed services.</p>
<p>Elastic Observability offers 16 out-of-the-box integrations for Google Cloud services with more on the way. A full list of Google Cloud integrations can be found in <a href="https://docs.elastic.co/en/integrations/gcp">our online documentation</a>.</p>
<p>In addition to our native Google Cloud integrations, Elastic Observability aggregates not only logs but also metrics for Google Cloud services and the applications running on Google Cloud compute services (Compute Engine, Cloud Run, Cloud Functions, Kubernetes Engine). All this data can be analyzed visually and more intuitively using Elastic®’s advanced machine learning (ML) capabilities, which help detect performance issues and surface root causes before end users are affected.</p>
<p>For more details on how Elastic Observability provides application performance monitoring (APM) capabilities such as service maps, tracing, dependencies, and ML based metrics correlations, read: <a href="https://www.elastic.co/blog/apm-correlations-elastic-observability-root-cause-transactions">APM correlations in Elastic Observability: Automatically identifying probable causes of slow or failed transactions</a>.</p>
<p>That’s right, Elastic offers metrics ingest, aggregation, and analysis for Google Cloud services and applications on Google Cloud compute services. Elastic is more than logs — it offers a unified observability solution for Google Cloud environments.</p>
<p>In this blog, I’ll review how Elastic Observability can monitor metrics for a three-tier web application running on Google Cloud services, which include:</p>
<ul>
<li>Google Cloud Run</li>
<li>Google Cloud SQL for PostgreSQL</li>
<li>Google Cloud Memorystore for Redis</li>
<li>Google Cloud VPC Network</li>
</ul>
<p>As you will see, once the integration is installed, metrics will arrive instantly and you can immediately start reviewing metrics.</p>
<h2>Prerequisites and config</h2>
<p>Here are some of the components and details we used to set up this demonstration:</p>
<ul>
<li>Ensure you have an account on <a href="http://cloud.elastic.co">Elastic Cloud</a> and a deployed stack (<a href="https://www.elastic.co/guide/en/elastic-stack/current/installing-elastic-stack.html">see instructions here</a>).</li>
<li>Ensure you have a Google Cloud project and a Service Account with permissions to pull the necessary data from Google Cloud (<a href="https://docs.elastic.co/en/integrations/gcp#authentication">see details in our documentation</a>).</li>
<li>We used <a href="https://cloud.google.com/architecture/application-development/three-tier-web-app">Google Cloud’s three-tier app</a> and deployed it using the Google Cloud console.</li>
<li>We’ll walk through installing the general <a href="https://docs.elastic.co/en/integrations/gcp">Elastic Google Cloud Platform Integration</a>, which covers the services we want to collect metrics for.</li>
<li>We will <em>not</em> cover application monitoring; instead, we will focus on how Google Cloud services can be easily monitored.</li>
<li>In order to see metrics, you will need to load the application. We’ve also created a playwright script to drive traffic to the application.</li>
</ul>
<h2>Three-tier application overview</h2>
<p>Before we dive into the Elastic configuration, let's review what we are monitoring. If you follow the <a href="https://cloud.google.com/architecture/application-development/three-tier-web-app">Jump Start Solution: Three-tier web app</a> instructions for<a href="https://github.com/aws-samples/aws-three-tier-web-architecture-workshop"></a>deploying the task-tracking app, you will have the following deployed.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/1.png" alt="1" /></p>
<p>What’s deployed:</p>
<ul>
<li>Cloud Run frontend tier that renders an HTML client in the user's browser and enables user requests to be sent to the task-tracking app</li>
<li>Cloud Run middle tier API layer that communicates with the frontend and the database tier</li>
<li>Memorystore for Redis instance in the database tier, caching and serving data that is read frequently</li>
<li>Cloud SQL for PostgreSQL instance in the database tier, handling requests that can't be served from the in-memory Redis cache</li>
</ul>
<p>At the end of the blog, we will also provide a Playwright script that can be run to send requests to this app in order to load it with example data and exercise its functionality. This will help drive metrics to “light up” the dashboards.</p>
<h2>Setting it all up</h2>
<p>Let’s walk through the details of how to get the application, Google Cloud integration on Elastic, and what gets ingested.</p>
<h3>Step 0: Get an account on Elastic Cloud</h3>
<p>Follow the instructions to <a href="https://cloud.elastic.co/registration?fromURI=/home">get started on Elastic Cloud</a>.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/2.png" alt="2 - start free trial" /></p>
<h3>Step 1: Deploy the Google Cloud three-tier application</h3>
<p>Follow the instructions listed out in <a href="https://cloud.google.com/architecture/application-development/three-tier-web-app">Jump Start Solution: Three-tier web app</a> choosing the <strong>Deploy through the console</strong> option for deployment.</p>
<h3>Step 2: Create a Google Cloud Service Account and download credentials file</h3>
<p>Once you’ve installed the app, the next step is to create a <em>Service Account</em> with a <em>Role</em> and a <em>Service Account Key</em> that will be used by Elastic’s integration to access data in your Google Cloud project.</p>
<p>Go to Google Cloud <a href="https://console.cloud.google.com/iam-admin/roles">IAM Roles</a> to create a Role with the necessary permissions. Click the <strong>CREATE ROLE</strong> button.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/3.png" alt="3" /></p>
<p>Give the Role a <strong>Title</strong> and an <strong>ID</strong>. Then add the 10 assigned permissions listed here.</p>
<ul>
<li>cloudsql.instances.list</li>
<li>compute.instances.list</li>
<li>monitoring.metricDescriptors.list</li>
<li>monitoring.timeSeries.list</li>
<li>pubsub.subscriptions.consume</li>
<li>pubsub.subscriptions.create</li>
<li>pubsub.subscriptions.get</li>
<li>pubsub.topics.attachSubscription</li>
<li>redis.instances.list</li>
<li>run.services.list</li>
</ul>
<p>These permissions are a minimal set of what’s required for this blog post. You should add permissions for all the services for which you would like to collect metrics. If you need to add or remove permissions in the future, the Role’s permissions can be updated as many times as necessary.</p>
<p>Click the <strong>CREATE</strong> button.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/4.png" alt="4" /></p>
<p>Go to Google Cloud <a href="https://console.cloud.google.com/iam-admin/serviceaccounts">IAM Service Accounts</a> to create a Service Account that will be used by the Elastic integration for access to Google Cloud. Click the <strong>CREATE SERVICE ACCOUNT</strong> button.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/5.png" alt="5" /></p>
<p>Enter a <strong>Service account name</strong> and a <strong>Service account ID.</strong> Click the <strong>CREATE AND CONTINUE</strong> button.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/6.png" alt="6" /></p>
<p>Then select the <strong>Role</strong> that you created previously and click the <strong>CONTINUE</strong> button.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/7.png" alt="7" /></p>
<p>Click the <strong>DONE</strong> button to complete the Service Account creation process.</p>
<p>Next select the Service Account you just created to see its details page. Under the <strong>KEYS</strong> tab, click the <strong>ADD KEY</strong> dropdown and select <strong>Create new key</strong>.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/8.png" alt="8" /></p>
<p>In the Create private key dialog window, with the <strong>Key type</strong> set as JSON, click the <strong>CREATE</strong> button.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/9.png" alt="9" /></p>
<p>The JSON credentials file key will be automatically downloaded to your local computer’s <strong>Downloads</strong> folder. The credentials file will be named something like:</p>
<pre><code class="language-bash">your-project-id-12a1234b1234.json
</code></pre>
<p>You can rename the file to be something else. For the purpose of this blog, we’ll rename it to:</p>
<pre><code class="language-bash">credentials.json
</code></pre>
<h3>Step 3: Create a Google Cloud VM instance</h3>
<p>To create the Compute Engine VM instance in Google Cloud, go to <a href="https://console.cloud.google.com/compute/instances">Compute Engine</a>. Then select <strong>CREATE INSTANCE.</strong></p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/10.png" alt="10" /></p>
<p>Enter the following values for the VM instance details:</p>
<ul>
<li>Enter a <strong>Name</strong> of your choice for the VM instance.</li>
<li>Expand the <strong>Advanced Options</strong> section and the <strong>Networking</strong> sub-section.
<ul>
<li>Enter allow-ssh as the Networking tag.</li>
<li>Select the <strong>Network Interface</strong> to use the <strong>tiered-web-app-private-network</strong> , which is the network on which the Google Cloud three-tier web app is deployed.</li>
</ul>
</li>
</ul>
<p>Click the <strong>CREATE</strong> button to create the VM instance.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/11.png" alt="11" /></p>
<h3>Step 4: SSH in to the Google Cloud VM instance and upload the credentials file</h3>
<p>In order to SSH into the Google Cloud VM instance you just created in the previous step, you’ll need to create a Firewall rule in <strong>tiered-web-app-private-network</strong> , which is the network where the VM instance resides.</p>
<p>Go to the Google Cloud <a href="https://console.cloud.google.com/net-security/firewall-manager/firewall-policies/list"><strong>Firewall policies</strong></a> page. Click the <strong>CREATE FIREWALL RULE</strong> button.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/12.png" alt="12" /></p>
<p>Enter the following values for the Firewall Rule.</p>
<ul>
<li>Enter a firewall rule <strong>Name</strong>.</li>
<li>Select <strong>tiered-web-app-private-network</strong> for the <strong>Network</strong>.</li>
<li>Enter allow-ssh for <strong>Target Tags</strong>.</li>
<li>Enter 0.0.0.0/0 for the <strong>Source IPv4 ranges</strong>.Click <strong>TCP</strong> and set the <strong>Ports</strong> to <strong>22</strong>.</li>
</ul>
<p>Click <strong>CREATE</strong> to create the firewall rule.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/13.png" alt="13" /></p>
<p>After the new Firewall rule is created, you can now SSH into your VM instance. Go to the <a href="https://console.cloud.google.com/compute/instances">Google Cloud VM instances</a> and select the VM instance you created in the previous step to see its details page. Click the <strong>SSH</strong> button.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/14.png" alt="14" /></p>
<p>Once you are SSH’d inside the VM instance terminal window, click the <strong>UPLOAD FILE</strong> button.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/15.png" alt="15" /></p>
<p>Select the credentials.json file located on your local computer and click the <strong>Upload Files</strong> button to upload the file.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/16.png" alt="16" /></p>
<p>In the VM instance’s SSH terminal, run the following command to get the full path to your Google Cloud Service Account credentials file.</p>
<pre><code class="language-bash">realpath credentials.json
</code></pre>
<p>This should return the full path to your Google Cloud Service Account credentials file.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/17.png" alt="17" /></p>
<p>Copy the credentials file’s full path and save it in a handy location to be used in a later step.</p>
<h3>Step 5: Add the Elastic Google Cloud integration</h3>
<p>Navigate to the Google Cloud Platform integration in Elastic by selecting <strong>Integrations</strong> from the top-level menu. Search for google and click the <strong>Google Cloud Platform</strong> tile.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/18.png" alt="18" /></p>
<p>Click <strong>Add Google Cloud Platform</strong>.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/19.png" alt="19" /></p>
<p>Click <strong>Add integration only (skip agent installation)</strong>.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/20.png" alt="20" /></p>
<p>Update the <strong>Project Id</strong> input text box to be your Google Cloud Project ID. Next, paste in the credentials file’s full path into the <strong>Credentials File</strong> input text box.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/21.png" alt="21" /></p>
<p>As you can see, the general Elastic Google Cloud Platform Integration will collect a significant amount of data from 16 Google Cloud services. If you don’t want to install this general Elastic Google Cloud Platform Integration, you can select individual integrations to install. Click <strong>Save and continue</strong>.</p>
<p>You’ll be presented with a confirmation dialog window. Click <strong>Add Elastic Agent to your hosts</strong>.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/22.png" alt="22" /></p>
<p>This will display the instructions required to install the Elastic agent. Copy the command under the <strong>Linux Tar</strong> tab.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/23.png" alt="23" /></p>
<p>Next you will need to use SSH to log in to the Google Cloud VM instance and run the commands copied from <strong>Linux Tar</strong> tab. Go to <a href="https://console.cloud.google.com/compute/instances">Compute Engine</a>. Then click the name of the VM instance that you created in Step 2. Log in to the VM by clicking the <strong>SSH</strong> button.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/14.png" alt="24 - instance" /></p>
<p>Once you are SSH’d inside the VM instance terminal window, run the commands copied previously from <strong>Linux Tar tab</strong> in the <strong>Install Elastic Agent on your host</strong> instructions.</p>
<p>When the installation completes, you’ll see a confirmation message in the Install Elastic Agent on your host form. Click the <strong>Add the integration</strong> button.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/25.png" alt="25 - add agent" /></p>
<p>Excellent! The Elastic agent is sending data to Elastic Cloud. Now let’s observe some metrics.</p>
<h3>Step 6: Run traffic against the application</h3>
<p>While getting the application running is fairly easy, there is nothing to monitor or observe with Elastic unless you add a load on the application.</p>
<p>Here is a simple script you can also run using <a href="https://playwright.dev/">Playwright</a> to add traffic and exercise the functionality of the Google Cloud three-tier application:</p>
<pre><code class="language-javascript">import { test, expect } from &quot;@playwright/test&quot;;

test(&quot;homepage for Google Cloud Threetierapp&quot;, async ({ page }) =&gt; {
  await page.goto(&quot;https://tiered-web-app-fe-zg62dali3a-uc.a.run.app&quot;);
  // Insert 2 todo items
  await page.fill(&quot;id=todo-new&quot;, (Math.random() * 100).toString());
  await page.keyboard.press(&quot;Enter&quot;);
  await page.waitForTimeout(1000);
  await page.fill(&quot;id=todo-new&quot;, (Math.random() * 100).toString());
  await page.keyboard.press(&quot;Enter&quot;);
  await page.waitForTimeout(1000);
  // Click one todo item
  await page.getByRole(&quot;checkbox&quot;).nth(0).check();
  await page.waitForTimeout(1000);
  // Delete one todo item
  const deleteButton = page.getByText(&quot;delete&quot;).nth(0);
  await deleteButton.dispatchEvent(&quot;click&quot;);
  await page.waitForTimeout(4000);
});
</code></pre>
<h3>Step 7: Go to Google Cloud dashboards in Elastic</h3>
<p>With Elastic Agent running, you can go to Elastic Dashboards to view what’s being ingested. Simply search for “dashboard” in Elastic and choose <strong>Dashboards.</strong></p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/26.png" alt="26 - dashboard" /></p>
<p>This will open the Elastic Dashboards page.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/27.png" alt="27" /></p>
<p>In the Dashboards search box, search for GCP and click the <strong>[Metrics GCP] CloudSQL PostgreSQL Overview</strong> dashboard, one of the many out-of-the-box dashboards available. Let’s see what comes up.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/28.png" alt="28" /></p>
<p>On the Cloud SQL dashboard, we can see the following sampling of some of the many available metrics:</p>
<ul>
<li>Disk write ops</li>
<li>CPU utilization</li>
<li>Network sent and received bytes</li>
<li>Transaction count</li>
<li>Disk bytes used</li>
<li>Disk quota</li>
<li>Memory usage</li>
<li>Disk read ops</li>
</ul>
<p>Next let’s take a look at metrics for Cloud Run.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/29.png" alt="29 - line graphs" /></p>
<p>We’ve created a custom dashboard using the <strong>Create dashboard</strong> button on the Elastic Dashboards page. Here we see a few of the numerous available metrics:</p>
<ul>
<li>Container instance count</li>
<li>CPU utilization for the three-tier app frontend and API</li>
<li>Request count for the three-tier app frontend and API</li>
<li>Bytes in and out of the API</li>
</ul>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/30.png" alt="30" /></p>
<p>This is a custom dashboard created for MemoryStore where we can see the following sampling of the available metrics:</p>
<ul>
<li>Network traffic to the Memorystore Redis instance</li>
<li>Count of the keys stored in Memorystore Redis</li>
<li>CPU utilization of the Memorystore Redis instance</li>
<li>Memory usage of the Memorystore Redis instance</li>
</ul>
<p><strong>Congratulations, you have now started monitoring metrics from key Google Cloud services for your application!</strong></p>
<h2>What to monitor on Google Cloud next?</h2>
<h3>Add logs from Google Cloud Services</h3>
<p>Now that metrics are being monitored, you can also now add logging. There are several options for ingesting logs.</p>
<p>The Google Cloud Platform Integration in the Elastic Agent has four separate logs settings: audit logs, firewall logs, VPC Flow logs, and DNS logs. Just ensure you turn on what you wish to receive.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/31.png" alt="31" /></p>
<h3>Analyze your data with Elastic machine learning</h3>
<p>Once metrics and logs (or either one) are in Elastic, start analyzing your data through Elastic’s ML capabilities. A great review of these features can be found here:</p>
<ul>
<li><a href="https://www.elastic.co/blog/apm-correlations-elastic-observability-root-cause-transactions">Correlating APM Telemetry to determine root causes in transactions</a></li>
<li><a href="https://www.elastic.co/elasticon/archive/2020/global/machine-learning-and-the-elastic-stack-everywhere-you-need-it">Introduction to Elastic Machine Learning</a></li>
</ul>
<h2>Conclusion: Monitoring Google Cloud service metrics with Elastic Observability is easy!</h2>
<p>I hope you’ve gotten an appreciation for how Elastic Observability can help you monitor Google Cloud service metrics. Here’s a quick recap of lessons and what you learned:</p>
<ul>
<li>Elastic Observability supports ingest and analysis of Google Cloud service metrics.</li>
<li>It’s easy to set up ingest from Google Cloud services via the Elastic Agent.</li>
<li>Elastic Observability has multiple out-of-the-box Google Cloud service dashboards you can use to preliminarily review information and then modify for your needs.</li>
<li>For metrics not covered by out-of-the-box dashboards, custom dashboards can be easily created to visualize metrics that are important to you.</li>
<li>16 Google Cloud services are supported as part of Google Cloud Platform Integration on Elastic Observability, with more services being added regularly.</li>
<li>As noted in related blogs, you can analyze your Google Cloud service metrics with Elastic’s machine learning capabilities.</li>
</ul>
<p>Try it out for yourself by signing up via <a href="https://console.cloud.google.com/marketplace/product/elastic-prod/elastic-cloud">Google Cloud Marketplace</a> and quickly spin up a deployment in minutes on any of the <a href="https://www.elastic.co/guide/en/cloud/current/ec-reference-regions.html#ec_google_cloud_platform_gcp_regions">Elastic Cloud regions on Google Cloud</a> around the world. Your Google Cloud Marketplace purchase of Elastic will be included in your monthly consolidated billing statement and will draw against your committed spend with Google Cloud.</p>
<p><em>The release and timing of any features or functionality described in this post remain at Elastic's sole discretion. Any features or functionality not currently available may not be delivered on time or at all.</em></p>
]]></content:encoded>
            <category>observability-labs</category>
            <enclosure url="https://www.elastic.co/observability-labs/assets/images/observability-monitors-metrics-google-cloud/serverless-launch-blog-image.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Using Elastic to observe GKE Autopilot clusters]]></title>
            <link>https://www.elastic.co/observability-labs/blog/observe-gke-autopilot-clusters</link>
            <guid isPermaLink="false">observe-gke-autopilot-clusters</guid>
            <pubDate>Wed, 15 Mar 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[See how deploying the Elastic Agent onto a GKE Autopilot cluster makes observing the cluster’s behavior easy. Kibana integrations make visualizing the behavior a simple addition to your observability dashboards.]]></description>
            <content:encoded><![CDATA[<p>Elastic has formally supported Google Kubernetes Engine (GKE) since January 2020, when Elastic Cloud on Kubernetes was announced. Since then, Google has expanded GKE, with new service offerings and delivery mechanisms. One of those new offerings is GKE Autopilot. Where GKE is a managed Kubernetes environment, GKE Autopilot is a mode of Kubernetes operation where Google manages your cluster configuration, scaling, security, and more. It is production ready and removes many of the challenges associated with tasks like workload management, deployment automation, and scalability rules. Autopilot lets you focus on building and deploying your application while Google manages everything else.</p>
<p>Elastic is committed to supporting Google Kubernetes Engine (GKE) in all of its delivery modes. In October, during the Google Cloud Next ‘22 event, we announced our intention to integrate and certify Elastic Agent on Anthos, Autopilot, Google Distributed Cloud, and more.</p>
<p>Since that event, we have worked together with Google to get the Elastic Agent certified for use on Anthos, but we didn’t stop there.</p>
<p>Today we are happy to <a href="https://github.com/elastic/elastic-agent/blob/autopilotdocumentaton/docs/elastic-agent-gke-autopilot.md">announce</a> that we have been certified for operation on GKE Autopilot.</p>
<h2>Hands on with Elastic and GKE Autopilot</h2>
<h3><a href="https://www.elastic.co/observability/kubernetes-monitoring">Kubernetes observability</a> has never been easier</h3>
<p>To show how easy it is to get started with Autopilot and Elastic, let's walk through deploying the Elastic Agent on an Autopilot cluster. I’ll show how easy it is to set up and monitor an Autopilot cluster with the Elastic Agent and observe the cluster’s behavior with Kibana integrations.</p>
<p>One of the main differences between GKE and GKE Autopilot is that Autopilot protects the system namespace “kube-system.” To increase the stability and security of a cluster, Autopilot prevents user space workloads from adding or modifying system pods. The default configuration for Elastic Agent is to install itself into the system namespace. The majority of the changes we will make here are to convince the Elastic Agent to run in a different namespace.</p>
<h2>Let’s get started with Elastic Stack!</h2>
<p>While writing this article, I used the latest version of Elastic. The best way for you to get started with Elastic Observability is to:</p>
<ol>
<li>Get an account on <a href="https://cloud.elastic.co/registration?fromURI=/home">Elastic Cloud</a> and look at this <a href="https://www.elastic.co/videos/training-how-to-series-cloud">tutoria</a>l to help launch your first stack, or</li>
<li><a href="https://www.elastic.co/partners/google-cloud">Launch Elastic Cloud on your Google Account</a></li>
</ol>
<h2>Provisioning an Autopilot cluster and an Elastic stack</h2>
<p>To test the agent, I first deployed the recommended, default GKE Autopilot cluster. Elastic’s GKE integration supports kube-state-metrics (KSM), which will increase the number of reported metrics available for reporting and dashboards. Like the Elastic Agent, KSM defaults to running in the system namespace, so I modified its manifest to work with Autopilot. For my testing, I also deployed a basic Elastic stack on Elastic Cloud in the same Google region as my Autopilot cluster. I used a fresh cluster deployed on Elastic’s managed service (ESS), but the process is the same if you are using an Elastic Cloud subscription purchased through the Google marketplace.</p>
<h2>Adding Elastic Observability to GKE Autopilot</h2>
<p>Because this is a brand new deployment, Elastic suggests adding integrations to it. Let’s add the Kubernetes integration into the new deployment:</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observe-gke-autopilot-clusters/blog-welcome-to-elastic.png" alt="elastic agent GKE autopilot welcome" /></p>
<p>Elastic offers hundreds of integrations; filter the list by typing “kub” into the search bar (1) and then click the Kubernetes integration (2).</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observe-gke-autopilot-clusters/blog-elastic-kubernetes-integration.png" alt="elastic agent GKE autopilot kubernetes integration" /></p>
<p>The Kubernetes integration page gives you an overview of the integration and lets you manage the Kubernetes clusters you want to observe. We haven’t added a cluster yet, so I clicked “Add Kubernetes” to add the first integration.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observe-gke-autopilot-clusters/blog-elastic-add-kubernetes.png" alt="elastic agent GKE autopilot add kubernetes" /></p>
<p>I changed the integration name to reflect the Kubernetes offering type and then clicked “Save and continue” to accept the integration defaults.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observe-gke-autopilot-clusters/blog-elastic-add-kubernetes-integration.png" alt="elastic agent GKE autopilot add kubernetes integration" /></p>
<p>At this point, an Agent policy has been created. Now it’s time to install the agent. I clicked on the “Kubernetes” integration.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observe-gke-autopilot-clusters/blog-elastic-agent-policy-1.png" alt="elastic agent GKE autopilot agent policy" /></p>
<p>Then I selected the “integration policies” tab (1) and clicked “Add agent” (2).</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observe-gke-autopilot-clusters/blog-elastic-add-agent.png" alt="elastic agent GKE autopilot add agent" /></p>
<p>Finally, I downloaded the full manifest for a standard GKE environment.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observe-gke-autopilot-clusters/blog-elastic-download-manifest.png" alt="elastic agent GKE autopilot download manifest" /></p>
<p>We won’t be using this manifest directly, but it contains many of the values that we will need to deploy the agent on Autopilot in the next section.</p>
<p>The Elastic stack is ready and waiting for the Autopilot logs, metrics, and events. It’s time to connect Autopilot to this deployment using the Elastic Agent for GKE.</p>
<h2>Connect Autopilot to Elastic</h2>
<p>From the Google cloud terminal, I downloaded and edited the Elastic Agent manifest for GKE Autopilot.</p>
<pre><code class="language-bash">$ curl -o elastic-agent-managed-gke-autopilot.yaml \
https://github.com/elastic/elastic-agent/blob/autopilotdocumentaton/docs/manifests/elastic-agent-managed-gke-autopilot.yaml
</code></pre>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observe-gke-autopilot-clusters/blog-elastic-cloud-shell-editor.png" alt="elastic agent GKE autopilot cloud shell editor" /></p>
<p>I used the cloud shell editor to configure the manifest for my Autopilot and Elastic clusters. For example, I updated the following:</p>
<pre><code class="language-yaml">containers:
  - name: elastic-agent
    image: docker.elastic.co/beats/elastic-agent:8.19.13
</code></pre>
<p>I also changed the agent to the version of Elastic that I installed (8.6.0).</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observe-gke-autopilot-clusters/blog-elastic-google-cloud.png" alt="elastic agent GKE autopilot google cloud" /></p>
<p>From the Integration manifest I downloaded earlier, I copied the values for FLEET_URL and FLEET_ENROLLMENT_TOKEN into this YAML file.</p>
<p>Now it’s time to apply the updated manifest to the Autopilot instance.</p>
<p>Before I commit, I always like to see what’s going to be created (and check for syntax errors) with a dry run.</p>
<pre><code class="language-bash">$ clear
$ kubectl apply --dry-run=&quot;client&quot; -f elastic-agent-managed-gke-autopilot.yaml
</code></pre>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observe-gke-autopilot-clusters/blog-elastic-dry-run.png" alt="elastic agent GKE autopilot dry run" /></p>
<p>Everything looks good, so I’ll do it for real this time.</p>
<pre><code class="language-bash">$ clear
$ kubectl apply -f elastic-agent-managed-gke-autopilot.yaml
</code></pre>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observe-gke-autopilot-clusters/blog-elastic-autopilot-cluster.png" alt="elastic agent GKE autopilot cluster" /></p>
<p>After several minutes, metrics will start flowing from the Autopilot cluster directly into the Elastic deployment.</p>
<h2>Adding a workload to the Autopilot cluster</h2>
<p>Observing an Autopilot cluster without a workload is boring, so I deployed a modified version of Google’s <a href="https://github.com/bshetti/opentelemetry-microservices-demo">Hipster Shop</a> (which includes OpenTelemetry reporting):</p>
<pre><code class="language-yaml">$ git clone https://github.com/bshetti/opentelemetry-microservices-demo
$ cd opentelemetry-microservices-demo
$ nano ./deploy-with-collector-k8s/otelcollector.yaml
</code></pre>
<p>To get the application’s telemetry talking to our Elastic stack, I replaced all instances of the exporter type from HTTP (otlphttp/elastic) to gRPC (otlp/elastic). I then replaced OTEL_EXPORTER_OTLP_ENDPOINT with my APM endpoint and I replaced OTEL_EXPORTER_OTLP_HEADERS with my APM OTEL Bearer and Token.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observe-gke-autopilot-clusters/blog-elastic-terminal-telemetry.png" alt="elastic agent GKE autopilot terminal telemetry" /></p>
<p>Then I deployed the Hipster Shop.</p>
<pre><code class="language-bash">$ kubectl create -f ./deploy-with-collector-k8s/adservice.yaml
$ kubectl create -f ./deploy-with-collector-k8s/redis.yaml
$ kubectl create -f ./deploy-with-collector-k8s/cartservice.yaml
$ kubectl create -f ./deploy-with-collector-k8s/checkoutservice.yaml
$ kubectl create -f ./deploy-with-collector-k8s/currencyservice.yaml
$ kubectl create -f ./deploy-with-collector-k8s/emailservice.yaml
$ kubectl create -f ./deploy-with-collector-k8s/frontend.yaml
$ kubectl create -f ./deploy-with-collector-k8s/paymentservice.yaml
$ kubectl create -f ./deploy-with-collector-k8s/productcatalogservice.yaml
$ kubectl create -f ./deploy-with-collector-k8s/recommendationservice.yaml
$ kubectl create -f ./deploy-with-collector-k8s/shippingservice.yaml
$ kubectl create -f ./deploy-with-collector-k8s/loadgenerator.yaml
</code></pre>
<p>Once all of the shop’s pods were running, I deployed the OpenTelemetry collector.</p>
<pre><code class="language-bash">$ kubectl create -f ./deploy-with-collector-k8s/otelcollector.yaml
</code></pre>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observe-gke-autopilot-clusters/blog-elastic-deployed-opentelemetry-collector.png" alt="elastic agent GKE autopilot deployed opentelemetry collector" /></p>
<h2>Observe and visualize Autopilot’s metrics</h2>
<p>Now that we have added the Elastic Agent to our Autopilot cluster and added a workload, let's take a look at some of the Kubernetes visualizations the integration provides out of the box.</p>
<p>The “[Metrics Kubernetes] Overview” is a great place to start. It provides a high-level view of the resources used by the cluster and allows me to drill into more specific dashboards that I find interesting:</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observe-gke-autopilot-clusters/blog-elastic-create-visualization.png" alt="elastic agent GKE autopilot create visualization" /></p>
<p>For example, the “[Metrics Kubernetes] Pods” gives me a high-level view of the pods deployed in the cluster:</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observe-gke-autopilot-clusters/blog-elastic-pod.png" alt="elastic agent GKE autopilot pod" /></p>
<p>The “[Metrics Kubernetes] Volumes” gives me an in-depth view to how storage is allocated and used in the Autopilot cluster:</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observe-gke-autopilot-clusters/blog-elastic-filesystem-information.png" alt="elastic agent GKE autopilot filesystem information" /></p>
<h2>Creating an alert</h2>
<p>From here, I can easily discover patterns in my cluster’s behavior and even create Alerts. Here is an example of an alert to notify me if the the main storage volume (called “volume”) exceeds 80% of its allocated space:</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observe-gke-autopilot-clusters/blog-elastic-create-rule-elasticsearch-query.png" alt="elastic agent GKE autopilot create rule" /></p>
<p>With a little work, I created this view from the standard dashboard:</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/observe-gke-autopilot-clusters/blog-elastic-kubernetes-dashboard.png" alt="elastic agent GKE autopilot kubernetes dashboard" /></p>
<h2>Conclusion</h2>
<p>Today I have shown how easy it is to monitor, observe, and generate alerts on a GKE Autopilot cluster. To get more information on what is possible, see the official Elastic documentation for <a href="https://github.com/elastic/elastic-agent/blob/autopilotdocumentaton/docs/elastic-agent-gke-autopilot.md">Autopilot observability with Elastic Agent</a>.</p>
<h2>Next steps</h2>
<p>If you don’t have Elastic yet, you can get started for free with an <a href="https://www.elastic.co/cloud/elasticsearch-service/signup">Elastic Trial</a> today. Get more from Elastic and Google together with a <a href="https://console.cloud.google.com/marketplace/browse?q=Elastic&amp;utm_source=Elastic&amp;utm_medium=qwiklabs&amp;utm_campaign=Qwiklabs+to+Marketplace">Marketplace subscription</a>. Elastic does more than just integrate with GKE — check out the almost <a href="https://www.elastic.co/integrations">300 integrations</a> that Elastic provides.</p>
]]></content:encoded>
            <category>observability-labs</category>
            <enclosure url="https://www.elastic.co/observability-labs/assets/images/observe-gke-autopilot-clusters/blog-elastic-kubernetes-dashboard.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[LLM Observability for Google Cloud’s Vertex AI platform - understand performance, cost and reliability]]></title>
            <link>https://www.elastic.co/observability-labs/blog/elevate-llm-observability-with-gcp-vertex-ai-integration</link>
            <guid isPermaLink="false">elevate-llm-observability-with-gcp-vertex-ai-integration</guid>
            <pubDate>Wed, 09 Apr 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Enhance LLM observability with Elastic's GCP Vertex AI Integration — gain actionable insights into model performance, resource efficiency, and operational reliability.]]></description>
            <content:encoded><![CDATA[<p>As organizations increasingly adopt large language models (LLMs) for AI-powered applications such as content creation, Retrieval-Augmented Generation (RAG), and data analysis, SREs and developers face new challenges. Tasks like monitoring workflows, analyzing input and output, managing query latency, and controlling costs become critical. LLM observability helps address these issues by providing clear insights into how these models perform, allowing teams to quickly identify bottlenecks, optimize configurations, and improve reliability. With better observability, SREs can confidently scale LLM applications, especially on platforms like <a href="https://cloud.google.com/vertex-ai">Google Cloud’s Vertex AI</a>.</p>
<h3>New Elastic Observability LLM integration with Google Cloud’s Vertex AI platform</h3>
<p>We are thrilled to announce general availability of monitoring LLMs hosted in Google Cloud through the <a href="https://www.elastic.co/docs/current/integrations/gcp_vertexai">Elastic integration with Vertex AI</a>. This integration enables users to experience enhanced LLM Observability by providing deep insights into the usage, cost and operational performance of models on Vertex AI, including latency, errors, token usage, frequency of model invocations as well as resources utilized by models. By leveraging this data, organizations can optimize resource usage, identify and resolve performance bottlenecks, and enhance the model efficiency and accuracy.</p>
<h3>Observability needs for AI-powered applications using the Vertex AI platform</h3>
<p>Leveraging AI models creates unique needs around the observability and monitoring of AI-powered applications. Some of the challenges that come with using LLMs are related to the high cost to call the LLMs, the quality and safety of LLM responses, and the performance, reliability and availability of the LLMs.</p>
<p>Lack of visibility into LLM observability data can make it harder for SREs and DevOps teams to ensure their AI-powered applications meet their service level objectives for reliability, performance, cost and quality of the AI-generated content and have enough telemetry data to troubleshoot related issues. Thus, robust LLM observability and detection of anomalies in the performance of models hosted on Google Cloud’s Vertex AI platform in real time is critical for the success of AI-powered applications.</p>
<p>Depending on the needs of their LLM applications, customers can make use of a growing list of models hosted on the Vertex AI platform such as Gemini 2.0 Pro, Gemini 2.0 Flash, and Imagen for image generation. Each model excels in specific areas and generates content in some modalities including Language, Audio, Vision, Code, etc. No two models are the same; each model has specific performance characteristics. So, it is important that service operators are able to track the individual performance, behaviour and cost of each model.</p>
<h3>Unlocking Insights with Vertex AI Metrics</h3>
<p>The Elastic integration with Google Cloud’s Vertex AI platform collects a wide range of metrics from models hosted on Vertex AI, enabling users to monitor, analyze, and optimize their AI deployments effectively.</p>
<p>Once you use the integration, you can review all the metrics in the Vertex AI dashboard</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/elevate-llm-observability-with-gcp-vertex-ai-integration/Overview.png" alt="Overview Dashboard" /></p>
<p>These metrics can be categorized into the following groups:</p>
<h4>1. Prediction Metrics</h4>
<p>Prediction metrics provide critical insights into model usage, performance bottlenecks, and reliability. These metrics help ensure smooth operations, optimize response times, and maintain robust, accurate predictions.</p>
<ul>
<li>
<p><strong>Prediction Count by Endpoint</strong>: Measures the total number of predictions across different endpoints.</p>
</li>
<li>
<p><strong>Prediction Latency</strong>: Provides insights into the time taken to generate predictions, allowing users to identify bottlenecks in performance.</p>
</li>
<li>
<p><strong>Prediction Errors</strong>: Monitors the count of failed predictions across endpoints.</p>
</li>
</ul>
<p><img src="https://www.elastic.co/observability-labs/assets/images/elevate-llm-observability-with-gcp-vertex-ai-integration/Prediction.png" alt="Prediction Metrics" /></p>
<h4>2. Model Performance Metrics</h4>
<p>Model performance metrics provide crucial insights into deployment efficiency, and responsiveness. These metrics help optimize model performance and ensure reliable operations.</p>
<ul>
<li>
<p><strong>Model Usage</strong>: Tracks the usage distribution among different model deployments.</p>
</li>
<li>
<p><strong>Token Usage</strong>: Tracks the number of tokens consumed by each model deployment, which is critical for understanding model efficiency.</p>
</li>
</ul>
<p><img src="https://www.elastic.co/observability-labs/assets/images/elevate-llm-observability-with-gcp-vertex-ai-integration/token_model_usage.png" alt="Token model usage" /></p>
<ul>
<li>
<p><strong>Invocation Rates</strong>: Tracks the frequency of invocations made by each model deployment.</p>
</li>
<li>
<p><strong>Model Invocation Latency</strong>: Measures the time taken to invoke a model, helping in diagnosing performance issues.</p>
</li>
</ul>
<p><img src="https://www.elastic.co/observability-labs/assets/images/elevate-llm-observability-with-gcp-vertex-ai-integration/Invocation_Vertex.png" alt="Model Invocation Metrics" /></p>
<h4>3. Resource Utilization Metrics</h4>
<p>Resource utilization metrics are vital for monitoring resource efficiency and workload performance. They help optimize infrastructure, prevent bottlenecks, and ensure smooth operation of AI deployments.</p>
<ul>
<li>
<p><strong>CPU Utilization</strong>: Monitors CPU usage to ensure optimal resource allocation for AI workloads.</p>
</li>
<li>
<p><strong>Memory Usage</strong>: Tracks the memory consumed across all model deployments.</p>
</li>
<li>
<p><strong>Network Usage</strong>: Measures bytes sent and received, providing insights into data transfer during model interactions.</p>
</li>
</ul>
<p><img src="https://www.elastic.co/observability-labs/assets/images/elevate-llm-observability-with-gcp-vertex-ai-integration/Resource_Utilization.png" alt="Resource Utilization Metrics" /></p>
<h4>4. Overview Metrics</h4>
<p>These metrics give an overview of the models deployed in Google Cloud’s Vertex AI platform. They are essential for tracking overall performance, optimizing efficiency, and identifying potential issues across deployments.</p>
<ul>
<li>
<p><strong>Total Invocations</strong>: The overall count of prediction invocations across all models and endpoints, providing a comprehensive view of activity.</p>
</li>
<li>
<p><strong>Total Tokens</strong>: The total number of tokens processed across all model interactions, offering insights into resource utilization and efficiency.</p>
</li>
<li>
<p><strong>Total Errors</strong>: The total count of errors encountered across all models and endpoints, helping identify reliability issues.</p>
</li>
</ul>
<p>All metrics can be filtered by <strong>region</strong>, offering localized insights for better analysis.</p>
<p>Note: The Elastic I integration with Vertex AI provides comprehensive visibility into both deployment models: provisioned throughput, where capacity is pre-allocated, and pay-as-you-go, where resources are consumed on demand.</p>
<h3>Conclusion</h3>
<p>This <a href="https://www.elastic.co/docs/current/integrations/gcp_vertexai">integration with Vertex AI</a> represents a significant step forward in enhancing the LLM Observability for users of Google Cloud’s Vertex AI platform. By unlocking a wealth of actionable data, organizations can assess the health, performance and cost of LLMs and troubleshoot operational issues, ensuring scalability, and accuracy in AI-driven applications.</p>
<p>Now that you know how the Vertex AI integration enhances LLM Observability, it’s your turn to try it out n. Spin up an Elastic Cloud, and start monitoring your LLM applications hosted on Google Cloud’s Vertex AI platform.</p>
]]></content:encoded>
            <category>observability-labs</category>
            <enclosure url="https://www.elastic.co/observability-labs/assets/images/elevate-llm-observability-with-gcp-vertex-ai-integration/vertexai-title.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[How to deploy Hello World Elastic Observability on Google Cloud Run]]></title>
            <link>https://www.elastic.co/observability-labs/blog/deploy-observability-google-cloud-run</link>
            <guid isPermaLink="false">deploy-observability-google-cloud-run</guid>
            <pubDate>Mon, 28 Aug 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Follow the step-by-step process of instrumenting Elastic Observability for a Hello World web app running on Google Cloud Run.]]></description>
            <content:encoded><![CDATA[<p>Elastic Cloud Observability is the premiere tool to provide visibility into your running web apps. Google Cloud Run is the serverless platform of choice to run your web apps that need to scale up massively and scale down to zero. Elastic Observability combined with Google Cloud Run is the perfect solution for developers to deploy <a href="https://www.elastic.co/blog/observability-powerful-flexible-efficient">web apps that are auto-scaled with fully observable operations</a>, in a way that’s straightforward to implement and manage.</p>
<p>This blog post will show you how to deploy a simple Hello World web app to Cloud Run and then walk you through the steps to instrument the Hello World web app to enable observation of the application’s operations with Elastic Cloud.</p>
<h2>Elastic Observability setup</h2>
<p>We’ll start with setting up an Elastic Cloud deployment, which is where observability will take place for the web app we’ll be deploying.</p>
<p>From the <a href="https://cloud.elastic.co">Elastic Cloud console</a>, select <strong>Create deployment</strong>.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/deploy-observability-google-cloud-run/elastic-blog-1-create-deployment.png" alt="create deployment" /></p>
<p>Enter a deployment name and click <strong>Create deployment</strong>. It takes a few minutes for your deployment to be created. While waiting, you are prompted to save the admin credentials for your deployment, which provides you with superuser access to your Elastic&lt;sup&gt;®&lt;/sup&gt; deployment. Keep these credentials safe as they are shown only once.</p>
<p>Elastic Observability requires an APM Server URL and an APM Secret token for an app to send observability data to Elastic Cloud. Once the deployment is created, we’ll copy the Elastic Observability server URL and secret token and store them somewhere safely for adding to our web app code in a later step.</p>
<p>To copy the APM Server URL and the APM Secret Token, go to <a href="https://cloud.elastic.co/home">Elastic Cloud</a>. Then go to the <a href="https://cloud.elastic.co/deployments">Deployments</a> page which lists all of the deployments you have created. Select the deployment you want to use, which will open the deployment details page. In the <strong>Kibana</strong> row of links, click on <strong>Open</strong> to open <strong>Kibana</strong> for your deployment.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/deploy-observability-google-cloud-run/elastic-blog-2-my-deployment.png" alt="my deployment" /></p>
<p>Select <strong>Integrations</strong> from the top-level menu. Then click the <strong>APM</strong> tile.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/deploy-observability-google-cloud-run/elastic-blog-3-apm.png" alt="apm" /></p>
<p>On the APM Agents page, copy the secretToken and the serverUrl values and save them for use in a later step.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/deploy-observability-google-cloud-run/elastic-blog-4-apm-agents.png" alt="apm agents" /></p>
<p>Now that we’ve completed the Elastic Cloud setup, the next step is to set up our Google Cloud project for deploying apps to Cloud Run.</p>
<h2>Google Cloud Run setup</h2>
<p>First we’ll need a Google Cloud project, so let’s create one by going to the <a href="https://console.cloud.google.com">Google Cloud console</a> and creating a new project. Select the project menu and then click the <strong>New Project</strong> button.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/deploy-observability-google-cloud-run/elastic-blog-5-google-cloud-gray-dropdown.png" alt="google cloud with gray dropdown" /></p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/deploy-observability-google-cloud-run/elastic-blog-5-select-a-project.png" alt="select a project" /></p>
<p>Once the new project is created, we’ll need to enable the necessary APIs that our Hello World app will be using. This can be done by clicking this <a href="https://console.cloud.google.com/flows/enableapi?apiid=compute.googleapis.com,,run.googleapis.com,containerregistry.googleapis.com,cloudbuild.googleapis.com">enable APIs</a> link, which opens a page in the Google Cloud console that lists the APIs that will be enabled and allows us to confirm their activation.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/deploy-observability-google-cloud-run/elastic-blog-6-enable-apis.png" alt="enable apis" /></p>
<p>After we’ve enabled the necessary APIs, we’ll need to set up the required permissions for our Hello World app, which can be done in the <a href="https://console.cloud.google.com/iam-admin">IAM section</a> of the Google Cloud Console. Within the IAM section, select the <strong>Compute Engine</strong> default service account and add the following roles:</p>
<ul>
<li>Logs Viewer</li>
<li>Monitoring Viewer</li>
<li>Pub/Sub Subscriber</li>
</ul>
<p><img src="https://www.elastic.co/observability-labs/assets/images/deploy-observability-google-cloud-run/elastic-blog-7-principals.png" alt="principals" /></p>
<h2>Deploy a Hello World web app to Cloud Run</h2>
<p>We’ll perform the process of deploying a Node.js Hello World web app to Cloud Run using the handy Google Cloud tool called <a href="https://console.cloud.google.com/cloudshelleditor">Cloud Shell Editor</a>. To deploy the Hello World app, we’ll perform the following five steps:</p>
<ol>
<li>In Cloud Shell Editor, in the terminal window that appears at the bottom of the screen, clone a <a href="https://github.com/elastic/observability-examples/tree/main/gcp/run/helloworld">Node.js Hello World sample app</a> repo from GitHub by entering the following command.</li>
</ol>
<pre><code class="language-bash">git clone https://github.com/elastic/observability-examples
</code></pre>
<ol start="2">
<li>Change directory to the location of the Hello World web app code.</li>
</ol>
<pre><code class="language-bash">cd gcp/run/helloworld
</code></pre>
<ol start="3">
<li>Build the Hello World app image and push the image to Google Container Registry by running the command below in the terminal. Be sure to replace your-project-id in the command below with your actual Google Cloud project ID.</li>
</ol>
<pre><code class="language-bash">gcloud builds submit --tag gcr.io/your-project-id/elastic-helloworld
</code></pre>
<ol start="4">
<li>Deploy the Hello World app to Google Cloud Run by running the command below. Be sure to replace your-project-id in the command below with your actual Google Cloud project ID.</li>
</ol>
<pre><code class="language-bash">gcloud run deploy elastic-helloworld --image gcr.io/your-project-id/elastic-helloworld
</code></pre>
<ol start="5">
<li>When the deployment process is complete, a Service URL will be displayed within the terminal. Copy and paste the Service URL in a browser to view the Hello World app running in Cloud Run.</li>
</ol>
<p><img src="https://www.elastic.co/observability-labs/assets/images/deploy-observability-google-cloud-run/elastic-blog-8-hello-world.png" alt="hello world" /></p>
<h2>Instrument the Hello World web app with Elastic Observability</h2>
<p>With a web app successfully running in Cloud Run, we’re now ready to add the minimal code necessary to start monitoring the app. To enable observability for the Hello World app in Elastic Cloud, we’ll perform the following six steps:</p>
<ol>
<li>In the Google Cloud Shell Editor, edit the Dockerfile file to add the following Elastic Open Telemetry environment variables along with the commands to install and run the Elastic APM agent. Replace the ELASTIC_APM_SERVER_URL text and the ELASTIC_APM_SECRET_TOKEN text with the APM Server URL and the APM Secret Token values that you copied and saved in an earlier step.</li>
</ol>
<pre><code class="language-dockerfile">ENV OTEL_EXPORTER_OTLP_ENDPOINT='ELASTIC_APM_SERVER_URL'
ENV OTEL_EXPORTER_OTLP_HEADERS='Authorization=Bearer ELASTIC_APM_SECRET_TOKEN'
ENV OTEL_LOG_LEVEL=info
ENV OTEL_METRICS_EXPORTER=otlp
ENV OTEL_RESOURCE_ATTRIBUTES=service.version=1.0,deployment.environment=production
ENV OTEL_SERVICE_NAME=helloworld
ENV OTEL_TRACES_EXPORTER=otlp
RUN npm install --save @opentelemetry/api
RUN npm install --save @opentelemetry/auto-instrumentations-node
CMD [&quot;node&quot;, &quot;--require&quot;, &quot;@opentelemetry/auto-instrumentations-node/register&quot;, &quot;index.js&quot;]
</code></pre>
<p>The updated Dockerfile should look something like this:</p>
<pre><code class="language-dockerfile">FROM node:18-slim
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install --only=production
COPY . ./
OTEL_EXPORTER_OTLP_ENDPOINT='https://******.apm.us-central1.gcp.cloud.es.io:443'
ENV OTEL_EXPORTER_OTLP_HEADERS='Authorization=Bearer ******************'
ENV OTEL_LOG_LEVEL=info
ENV OTEL_METRICS_EXPORTER=otlp
ENV OTEL_RESOURCE_ATTRIBUTES=service.version=1.0,deployment.environment=production
ENV OTEL_SERVICE_NAME=helloworld
ENV OTEL_TRACES_EXPORTER=otlp
RUN npm install --save @opentelemetry/api
RUN npm install --save @opentelemetry/auto-instrumentations-node
CMD [&quot;node&quot;, &quot;--require&quot;, &quot;@opentelemetry/auto-instrumentations-node/register&quot;, &quot;index.js&quot;]
</code></pre>
<ol start="2">
<li>In the Google Cloud Shell Editor, edit the package.json file to add the Elastic APM dependency. The dependencies section in package.json should look something like this:</li>
</ol>
<pre><code class="language-json">&quot;dependencies&quot;: {
  	&quot;express&quot;: &quot;^4.18.2&quot;,
  	&quot;elastic-apm-node&quot;: &quot;^3.49.1&quot;
  },
</code></pre>
<ol start="3">
<li>In the Google Cloud Shell Editor, edit the index.js file:</li>
</ol>
<ul>
<li>Add the code required to initialize the Elastic Open Telemetry APM agent:</li>
</ul>
<pre><code class="language-javascript">const otel = require(&quot;@opentelemetry/api&quot;);
const tracer = otel.trace.getTracer(&quot;hello-world&quot;);
</code></pre>
<ul>
<li>Replace the “Hello World!” output code . . .</li>
</ul>
<pre><code class="language-javascript">res.send(`&lt;h1&gt;Hello World!&lt;/h1&gt;`);
</code></pre>
<p>...with the “Hello Elastic Observability” code block.</p>
<pre><code class="language-javascript">res.send(
  `&lt;div style=&quot;text-align: center;&quot;&gt;
   &lt;h1 style=&quot;color: #005A9E; font-family:'Verdana'&quot;&gt;
   Hello Elastic Observability - Google Cloud Run - Node.js
   &lt;/h1&gt;
   &lt;img src=&quot;https://storage.googleapis.com/elastic-helloworld/elastic-logo.png&quot;&gt;
   &lt;/div&gt;`
);
</code></pre>
<ul>
<li>Add a trace “hi” before the “Hello Elastic Observability” code block and add a trace “bye” after the “Hello Elastic Observability” code block.</li>
</ul>
<pre><code class="language-javascript">tracer.startActiveSpan(&quot;hi&quot;, (span) =&gt; {
  console.log(&quot;hello&quot;);
  span.end();
});
res.send(
  `&lt;div style=&quot;text-align: center;&quot;&gt;
   &lt;h1 style=&quot;color: #005A9E; font-family:'Verdana'&quot;&gt;
   Hello Elastic Observability - Google Cloud Run - Node.js
   &lt;/h1&gt;
   &lt;img src=&quot;https://storage.googleapis.com/elastic-helloworld/elastic-logo.png&quot;&gt;
   &lt;/div&gt;`
);
tracer.startActiveSpan(&quot;bye&quot;, (span) =&gt; {
  console.log(&quot;goodbye&quot;);
  span.end();
});
</code></pre>
<ul>
<li>The completed index.js file should look something like this:</li>
</ul>
<pre><code class="language-javascript">const otel = require(&quot;@opentelemetry/api&quot;);
const tracer = otel.trace.getTracer(&quot;hello-world&quot;);

const express = require(&quot;express&quot;);
const app = express();

app.get(&quot;/&quot;, (req, res) =&gt; {
  tracer.startActiveSpan(&quot;hi&quot;, (span) =&gt; {
    console.log(&quot;hello&quot;);
    span.end();
  });
  res.send(
    `&lt;div style=&quot;text-align: center;&quot;&gt;
    &lt;h1 style=&quot;color: #005A9E; font-family:'Verdana'&quot;&gt;
    Hello Elastic Observability - Google Cloud Run - Node.js
    &lt;/h1&gt;
   &lt;img src=&quot;https://storage.googleapis.com/elastic-helloworld/elastic-logo.png&quot;&gt;
    &lt;/div&gt;`
  );
  tracer.startActiveSpan(&quot;bye&quot;, (span) =&gt; {
    console.log(&quot;goodbye&quot;);
    span.end();
  });
});

const port = parseInt(process.env.PORT) || 8080;
app.listen(port, () =&gt; {
  console.log(`helloworld: listening on port ${port}`);
});
</code></pre>
<ol start="4">
<li>Rebuild the Hello World app image and push the image to the Google Container Registry by running the command below in the terminal. Be sure to replace your-project-id in the command below with your actual Google Cloud project ID.</li>
</ol>
<pre><code class="language-bash">gcloud builds submit --tag gcr.io/your-project-id/elastic-helloworld
</code></pre>
<ol start="5">
<li>Redeploy the Hello World app to Google Cloud Run by running the command below. Be sure to replace your-project-id in the command below with your actual Google Cloud project ID.</li>
</ol>
<pre><code class="language-bash">gcloud run deploy elastic-helloworld --image gcr.io/your-project-id/elastic-helloworld
</code></pre>
<ol start="6">
<li>When the deployment process is complete, a Service URL will be displayed within the terminal. Copy and paste the Service URL in a browser to view the updated Hello World app running in Cloud Run.</li>
</ol>
<p><img src="https://www.elastic.co/observability-labs/assets/images/deploy-observability-google-cloud-run/elastic-blog-9-elastic-logo.png" alt="elastic logo" /></p>
<h2>Observe the Hello World web app</h2>
<p>Now that we’ve instrumented the web app to send observability data to Elastic Observability, we can now use Elastic Cloud to monitor the web app’s operations.</p>
<ol>
<li>
<p>In Elastic Cloud, select the Observability <strong>Services</strong> menu item.</p>
</li>
<li>
<p>Click the <strong>helloworld</strong> service.</p>
</li>
<li>
<p>Click the <strong>Transactions</strong> tab.</p>
</li>
<li>
<p>Scroll down and click the <strong>GET /</strong> transaction.</p>
</li>
<li>
<p>Scroll down to the <strong>Trace Sample</strong> section to see the <strong>GET /</strong> , <strong>hi</strong> and <strong>bye</strong> trace samples.</p>
</li>
</ol>
<p><img src="https://www.elastic.co/observability-labs/assets/images/deploy-observability-google-cloud-run/elastic-blog-10-trace-sample.png" alt="trace sample" /></p>
<h2>Observability made to scale</h2>
<p>You’ve seen the entire process of deploying a web app to Google Cloud Run that is instrumented with Elastic Observability. The end result is a web app that will scale up and down with demand combined with the observability tools to monitor the web app as it serves a single user or millions of users.</p>
<p>Now that you’ve seen how to deploy a serverless web app instrumented with observability, visit <a href="https://www.elastic.co/observability">Elastic Observability</a> to learn more about how to implement a complete observability solution for your apps. Or visit <a href="https://www.elastic.co/getting-started/google-cloud">Getting started with Elastic on Google Cloud</a> for more examples of how you can drive the data insights you need by combining <a href="https://www.elastic.co/observability/google-cloud-monitoring">Google Cloud monitoring</a> and cloud computing services with Elastic’s search-powered platform.</p>
<p><em>The release and timing of any features or functionality described in this post remain at Elastic's sole discretion. Any features or functionality not currently available may not be delivered on time or at all.</em></p>
]]></content:encoded>
            <category>observability-labs</category>
            <enclosure url="https://www.elastic.co/observability-labs/assets/images/deploy-observability-google-cloud-run/illustration-dev-sec-ops-cloud-automations-1680x980.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[Managing your Kubernetes cluster with Elastic Observability]]></title>
            <link>https://www.elastic.co/observability-labs/blog/kubernetes-cluster-metrics-logs-monitoring</link>
            <guid isPermaLink="false">kubernetes-cluster-metrics-logs-monitoring</guid>
            <pubDate>Mon, 24 Oct 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[Unify all of your Kubernetes metrics, log, and trace data on a single platform and dashboard, Elastic. From the infrastructure to the application layer Elastic Observability makes it easier for you to understand how your cluster is performing.]]></description>
            <content:encoded><![CDATA[<p>As an operations engineer (SRE, IT manager, DevOps), you’re always struggling with how to manage technology and data sprawl. Kubernetes is becoming increasingly pervasive and a majority of these deployments will be in Amazon Elastic Kubernetes Service (EKS), Google Kubernetes Engine (GKE), or Azure Kubernetes Service (AKS). Some of you may be on a single cloud while others will have the added burden of managing clusters on multiple Kubernetes cloud services. In addition to cloud provider complexity, you also have to manage hundreds of deployed services generating more and more observability and telemetry data.</p>
<p>The day-to-day operations of understanding the status and health of your Kubernetes clusters and applications running on them, through the logs, metrics, and traces they generate, will likely be your biggest challenge. But as an operations engineer you will need all of that important data to help prevent, predict, and remediate issues. And you certainly don’t need that volume of metrics, logs and traces spread across multiple tools when you need to visualize and analyze Kubernetes telemetry data for troubleshooting and support.</p>
<p>Elastic Observability helps manage the sprawl of Kubernetes metrics and logs by providing extensive and centralized observability capabilities beyond just the logging that we are known for. Elastic Observability provides you with granular insights and context into the behavior of your Kubernetes clusters along with the applications running on them by unifying all of your metrics, log, and trace data through OpenTelemetry and APM agents.</p>
<p>Regardless of the cluster location (EKS, GKE, AKS, self-managed) or application, <a href="https://www.elastic.co/what-is/kubernetes-monitoring">Kubernetes monitoring</a> is made simple with Elastic Observability. All of the node, pod, container, application, and infrastructure (AWS, GCP, Azure) metrics, infrastructure and application logs, along with application traces are available in Elastic Observability.</p>
<p>In this blog we will show:</p>
<ul>
<li>How <a href="http://cloud.elastic.co">Elastic Cloud</a> can aggregate and ingest metrics and log data through the Elastic Agent (easily deployed on your cluster as a DaemonSet) to retrieve logs and metrics from the host (system metrics, container stats) along with logs from all services running on top of Kubernetes.</li>
<li>How Elastic Observability can bring a unified telemetry experience (logs, metrics,traces) across all your Kubernetes cluster components (pods, nodes, services, namespaces, and more).</li>
</ul>
<p><img src="https://www.elastic.co/observability-labs/assets/images/kubernetes-cluster-metrics-logs-monitoring/ManagingKubernetes-ElasticAgentIntegration-1.png" alt="Elastic Agent with Kubernetes Integration" /></p>
<h2>Prerequisites and config</h2>
<p>If you plan on following this blog, here are some of the components and details we used to set up this demonstration:</p>
<ul>
<li>Ensure you have an account on <a href="http://cloud.elastic.co">Elastic Cloud</a> and a deployed stack (<a href="https://www.elastic.co/guide/en/elastic-stack/current/installing-elastic-stack.html">see instructions here</a>).</li>
<li>While we used GKE, you can use any location for your Kubernetes cluster.</li>
<li>We used a variant of the ever so popular <a href="https://github.com/GoogleCloudPlatform/microservices-demo">HipsterShop</a> demo application. It was originally written by Google to showcase Kubernetes across a multitude of variants available such as the <a href="https://github.com/open-telemetry/opentelemetry-demo">OpenTelemetry Demo App</a>. To use the app, please go <a href="https://github.com/bshetti/opentelemetry-microservices-demo/tree/main/deploy-with-collector-k8s">here</a> and follow the instructions to deploy. You don’t need to deploy otelcollector for Kubernetes metrics to flow — we will cover this below.</li>
<li>Elastic supports native ingest from Prometheus and FluentD, but in this blog, we are showing a direct ingest from Kubernetes cluster via Elastic Agent. There will be a follow-up blog showing how Elastic can also pull in telemetry from Prometheus or FluentD/bit.</li>
</ul>
<h2>What can you observe and analyze with Elastic?</h2>
<p>Before we walk through the steps on getting Elastic set up to ingest and visualize Kubernetes cluster metrics and logs, let’s take a sneak peek at Elastic’s helpful dashboards.</p>
<p>As we noted, we ran a variant of HipsterShop on GKE and deployed Elastic Agents with Kubernetes integration as a DaemonSet on the GKE cluster. Upon deployment of the agents, Elastic starts ingesting metrics from the Kubernetes cluster (specifically from kube-state-metrics) and additionally Elastic will pull all log information from the cluster.</p>
<h3>Visualizing Kubernetes metrics on Elastic Observability</h3>
<p>Here are a few Kubernetes dashboards that will be available out of the box (OOTB) on Elastic Observability.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/kubernetes-cluster-metrics-logs-monitoring/ManagingKubernetes-HipsterShopMetrics-2.png" alt="HipsterShop cluster metrics on Elastic Kubernetes overview dashboard " /></p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/kubernetes-cluster-metrics-logs-monitoring/ManagingKubernetes-HipsterShopDashboard-3.png" alt="HipsterShop default namespace pod dashboard on Elastic Observability" /></p>
<p>In addition to the cluster overview dashboard and pod dashboard, Elastic has several useful OOTB dashboards:</p>
<ul>
<li>Kubernetes overview dashboard (see above)</li>
<li>Kubernetes pod dashboard (see above)</li>
<li>Kubernetes nodes dashboard</li>
<li>Kubernetes deployments dashboard</li>
<li>Kubernetes DaemonSets dashboard</li>
<li>Kubernetes StatefulSets dashboards</li>
<li>Kubernetes CronJob &amp; Jobs dashboards</li>
<li>Kubernetes services dashboards</li>
<li>More being added regularly</li>
</ul>
<p>Additionally, you can either customize these dashboards or build out your own.</p>
<h3>Working with logs on Elastic Observability</h3>
<p><img src="https://www.elastic.co/observability-labs/assets/images/kubernetes-cluster-metrics-logs-monitoring/ManagingKubernetes-Logging-4.png" alt="Kubernetes container logs and Elastic Agent logs" /></p>
<p>As you can see from the screens above, not only can I get Kubernetes cluster metrics, but also all the Kubernetes logs simply by using the Elastic Agent in my Kubernetes cluster.</p>
<h3>Prevent, predict, and remediate issues</h3>
<p>In addition to helping manage metrics and logs, Elastic can help you detect and predict anomalies across your cluster telemetry. Simply turn on Machine Learning in Elastic against your data and watch it help you enhance your analysis work. As you can see below, Elastic is not only a unified observability location for your Kubernetes cluster logs and metrics, but it also provides extensive true machine learning capabilities to enhance your analysis and management.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/kubernetes-cluster-metrics-logs-monitoring/ManagingKubernetes-AnomalyDetection-5.png" alt="Anomaly detection across logs on Elastic Observability" /></p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/kubernetes-cluster-metrics-logs-monitoring/ManagingKubernetes-PodIssues-6.png" alt="Analyzing issues on a Kubernetes pod with Elastic Observability " /></p>
<p>In the top graph, you see anomaly detection across logs and it shows something potentially wrong in the September 21 to 23 time period. Dig into the details on the bottom chart by analyzing a single kubernetes.pod.cpu.usage.node metric showing cpu issues early in September and again, later on in the month. You can do more complicated analyses on your cluster telemetry with Machine Learning using multi-metric analysis (versus the single metric issue I am showing above) along with population analysis.</p>
<p>Elastic gives you better machine learning capabilities to enhance your analysis of Kubernetes cluster telemetry. In the next section, let’s walk through how easy it is to get your telemetry data into Elastic.</p>
<h2>Setting it all up</h2>
<p>Let’s walk through the details of how to get metrics, logs, and traces into Elastic from a HipsterShop application deployed on GKE.</p>
<p>First, pick your favorite version of Hipstershop — as we noted above, we used a variant of the <a href="https://github.com/open-telemetry/opentelemetry-demo">OpenTelemetry-Demo</a> because it already has OTel. We slimmed it down for this blog, however (fewer services with some varied languages).</p>
<h3>Step 0: Get an account on Elastic Cloud</h3>
<p>Follow the instructions to <a href="https://cloud.elastic.co/registration?fromURI=/home">get started on Elastic Cloud</a>.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/kubernetes-cluster-metrics-logs-monitoring/ManagingKubernetes-FreeElasticCloud-7.png" alt="" /></p>
<h3>Step 1: Get a Kubernetes cluster and load your Kubernetes app into your cluster</h3>
<p>Get your app on a Kubernetes cluster in your Cloud service of choice or local Kubernetes platform. Once your app is up on Kubernetes, you should have the following pods (or some variant) running on the default namespace.</p>
<pre><code class="language-yaml">NAME                                    READY   STATUS    RESTARTS   AGE
adservice-8694798b7b-jbfxt              1/1     Running   0          4d3h
cartservice-67b598697c-hfsxv            1/1     Running   0          4d3h
checkoutservice-994ddc4c4-p9p2s         1/1     Running   0          4d3h
currencyservice-574f65d7f8-zc4bn        1/1     Running   0          4d3h
emailservice-6db78645b5-ppmdk           1/1     Running   0          4d3h
frontend-5778bfc56d-jjfxg               1/1     Running   0          4d3h
jaeger-686c775fbd-7d45d                 1/1     Running   0          4d3h
loadgenerator-c8f76d8db-gvrp7           1/1     Running   0          4d3h
otelcollector-5b87f4f484-4wbwn          1/1     Running   0          4d3h
paymentservice-6888bb469c-nblqj         1/1     Running   0          4d3h
productcatalogservice-66478c4b4-ff5qm   1/1     Running   0          4d3h
recommendationservice-648978746-8bzxc   1/1     Running   0          4d3h
redis-cart-96d48485f-gpgxd              1/1     Running   0          4d3h
shippingservice-67fddb767f-cq97d        1/1     Running   0          4d3h
</code></pre>
<h3>Step 2: Turn on &lt;a href=&quot;https://github.com/kubernetes/kube-state-metrics&quot; target=&quot;_self&quot;&gt;kube-state-metrics&lt;/a&gt;</h3>
<p>Next you will need to turn on <a href="https://github.com/kubernetes/kube-state-metrics">kube-state-metrics</a>.</p>
<p>First:</p>
<pre><code class="language-bash">git clone https://github.com/kubernetes/kube-state-metrics.git
</code></pre>
<p>Next, in the kube-state-metrics directory under the examples directory, just apply the standard config.</p>
<pre><code class="language-bash">kubectl apply -f ./standard
</code></pre>
<p>This will turn on kube-state-metrics, and you should see a pod similar to this running in kube-system namespace.</p>
<pre><code class="language-yaml">kube-state-metrics-5f9dc77c66-qjprz                    1/1     Running   0          4d4h
</code></pre>
<h3>Step 3: Install the Elastic Agent with Kubernetes integration</h3>
<p><strong>Add Kubernetes Integration:</strong></p>
<ol>
<li><img src="https://images.contentstack.io/v3/assets/bltefdd0b53724fa2ce/blt5a3ae745e98b9e37/635691670a58db35cbdbc0f6/ManagingKubernetes-Addk8sButton-8.png" alt="" /></li>
<li>In Elastic, go to integrations and select the Kubernetes Integration, and select to Add Kubernetes.</li>
<li>Select a name for the Kubernetes integration.</li>
<li>Turn on kube-state-metrics in the configuration screen.</li>
<li>Give the configuration a name in the new-agent-policy-name text box.</li>
<li>Save the configuration. The integration with a policy is now created.</li>
</ol>
<p>You can read up on the agent policies and how they are used on the Elastic Agent <a href="https://www.elastic.co/guide/en/fleet/current/agent-policy.html">here</a>.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/kubernetes-cluster-metrics-logs-monitoring/ManagingKubernetes-K8sIntegration-9.png" alt="" /></p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/kubernetes-cluster-metrics-logs-monitoring/ManagingKubernetes-FleetManagement-10.png" alt="" /></p>
<ol>
<li>Add Kubernetes integration.</li>
<li>Select the policy you just created in the second.</li>
<li>In the third step of Add Agent instructions, copy and paste or download the manifest.</li>
<li>Add manifest to the shell where you have kubectl running, save it as elastic-agent-managed-kubernetes.yaml, and run the following command.</li>
</ol>
<pre><code class="language-yaml">kubectl apply -f elastic-agent-managed-kubernetes.yaml
</code></pre>
<p>You should see a number of agents come up as part of a DaemonSet in kube-system namespace.</p>
<pre><code class="language-yaml">NAME                                                   READY   STATUS    RESTARTS   AGE
elastic-agent-qr6hj                                    1/1     Running   0          4d7h
elastic-agent-sctmz                                    1/1     Running   0          4d7h
elastic-agent-x6zkw                                    1/1     Running   0          4d7h
elastic-agent-zc64h                                    1/1     Running   0          4d7h
</code></pre>
<p>In my cluster, I have four nodes and four elastic-agents started as part of the DaemonSet.</p>
<h3>Step 4: Look at Elastic out of the box dashboards (OOTB) for Kubernetes metrics and start discovering Kubernetes logs</h3>
<p>That is it. You should see metrics flowing into all the dashboards. To view logs for specific pods, simply go into Discover in Kibana and search for a specific pod name.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/kubernetes-cluster-metrics-logs-monitoring/ManagingKubernetes-HipsterShopMetrics-2.png" alt="HipsterShop cluster metrics on Elastic Kubernetes overview dashboard" /></p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/kubernetes-cluster-metrics-logs-monitoring/ManagingKubernetes-HipsterShopDashboard-3.png" alt="Hipstershop default namespace pod dashboard on Elastic Observability" /></p>
<p>Additionally, you can browse all the pod logs directly in Elastic.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/kubernetes-cluster-metrics-logs-monitoring/ManagingKurbenetes-PodLogs-11.png" alt="frontendService and cartService logs" /></p>
<p>In the above example, I searched for frontendService and cartService logs.</p>
<h3>Step 5: Bonus!</h3>
<p>Because we were using an OTel based application, Elastic can even pull in the application traces. But that is a discussion for another blog.</p>
<p>Here is a quick peek at what Hipster Shop’s traces for a front end transaction look like in Elastic Observability.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/kubernetes-cluster-metrics-logs-monitoring/ManagingKubernetes-CheckOutTransaction-12.png" alt="Trace for Checkout transaction for HipsterShop" /></p>
<h2>Conclusion: Elastic Observability rocks for Kubernetes monitoring</h2>
<p>I hope you’ve gotten an appreciation for how Elastic Observability can help you manage Kubernetes clusters along with the complexity of the metrics, log, and trace data it generates for even a simple deployment.</p>
<p>A quick recap of lessons and more specifically learned:</p>
<ul>
<li>How <a href="http://cloud.elastic.co">Elastic Cloud</a> can aggregate and ingest telemetry data through the Elastic Agent, which is easily deployed on your cluster as a DaemonSet and retrieves metrics from the host, such as system metrics, container stats, and metrics from all services running on top of Kubernetes</li>
<li>Show what Elastic brings from a unified telemetry experience (Kubernenetes logs, metrics, traces) across all your Kubernetes cluster components (pods, nodes, services, any namespace, and more).</li>
<li>Interest in exploring Elastic’s ML capabilities which will reduce your <strong>MTTHH</strong> (mean time to happy hour)</li>
</ul>
<p>Ready to get started? <a href="https://cloud.elastic.co/registration">Register</a> and try out the features and capabilities I’ve outlined above.</p>
]]></content:encoded>
            <category>observability-labs</category>
            <enclosure url="https://www.elastic.co/observability-labs/assets/images/kubernetes-cluster-metrics-logs-monitoring/ManagingKubernetes-ElasticAgentIntegration-1.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[Automatic cloud resource attributes with OpenTelemetry Java]]></title>
            <link>https://www.elastic.co/observability-labs/blog/opentelemetry-java-automatic-cloud-resource-attributes</link>
            <guid isPermaLink="false">opentelemetry-java-automatic-cloud-resource-attributes</guid>
            <pubDate>Thu, 27 Jun 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Capturing cloud resource attributes allow to describe application cloud deployment details. In this article we describe three distinct ways to enable them for Java applications using OpenTelemetry]]></description>
            <content:encoded><![CDATA[<p>With OpenTelemetry, the observed entities (application, services, processes, …) are described through resource attributes. The definitions and the values of those attributes are defined in the <a href="https://opentelemetry.io/docs/concepts/semantic-conventions/">semantic conventions</a>.<br />
In practice, for a typical java application running in a cloud environment like Google Cloud Platform (GCP), Amazon Web Services (AWS) or Azure, it means capturing the name of the cloud provider, the cloud service name or availability zone in addition to per-provider attributes. Those attributes are then used to describe and qualify the observability signals (logs, traces, metrics), defined by semantic conventions in the <a href="https://opentelemetry.io/docs/specs/semconv/resource/cloud/">cloud resource attributes</a> section.</p>
<p>When using the <a href="https://github.com/open-telemetry/opentelemetry-java">OpenTelemetry Java SDK</a> or the <a href="https://github.com/open-telemetry/opentelemetry-java-instrumentation">OpenTelemetry instrumentation agent</a>, those attributes are not automatically captured by default. In this article we will show you first how to enable them with the SDK, then using the instrumentation agent and then we will show you how using the <a href="https://github.com/elastic/elastic-otel-java/">Elastic OpenTelemetry Distribution</a> makes it even easier.</p>
<h2>OpenTelemetry Java SDK</h2>
<p>The OpenTelemetry Java SDK does not capture any cloud resource attributes, however it provides a pluggable service provider interface to register resource attributes providers and application developers have to provide the implementations.</p>
<p>Implementations for <a href="https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/gcp-resources">GCP</a> and <a href="https://github.com/open-telemetry/opentelemetry-java-contrib/tree/main/aws-resources">AWS</a> are already included in the <a href="https://github.com/open-telemetry/opentelemetry-java-contrib/">OpenTelemetry Java Contrib</a> repo, so if you are using one of those cloud providers then it's mostly a matter of adding those providers to your application dependencies. Thanks to autoconfiguration those should be automatically included and enabled once they are added to the application classpath. The <a href="https://github.com/open-telemetry/opentelemetry-java/tree/main/sdk-extensions/autoconfigure#resource-provider-spi">SDK documentation</a> provides all the details to add and configure those in your application.</p>
<p>If you are using a cloud provider for which no such implementation is available, then you still have the option to provide your own which is a straightforward implementation of the <a href="https://github.com/open-telemetry/opentelemetry-java/blob/main/sdk-extensions/autoconfigure/README.md#resource-provider-spi">ResourceProvider</a> SPI (Service Provider Interface). In order to keep things consistent, you will have to rely on the existing <a href="https://opentelemetry.io/docs/specs/semconv/resource/cloud/">cloud semantic conventions</a>.</p>
<p>For example here is an example of a simple cloud resource attributes provider for a fictitious cloud provider named &quot;potatoes&quot;.</p>
<pre><code>package potatoes;

import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import io.opentelemetry.sdk.autoconfigure.spi.ResourceProvider;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.semconv.incubating.CloudIncubatingAttributes;

public class PotatoesResourceProvider implements ResourceProvider {

@Override
public Resource createResource(ConfigProperties configProperties) {
   return Resource.create(Attributes.of(
           CloudIncubatingAttributes.CLOUD_PROVIDER, &quot;potatoes&quot;,
           CloudIncubatingAttributes.CLOUD_PLATFORM, &quot;french-fries&quot;,
           CloudIncubatingAttributes.CLOUD_REGION, &quot;garden&quot;
           ));
  }
}
</code></pre>
<h2>OpenTelemetry Java instrumentation</h2>
<p>The <a href="https://github.com/open-telemetry/opentelemetry-java-instrumentation">OpenTelemetry Java Instrumentation</a> provides a java agent that instruments the application at runtime automatically for an extensive set of frameworks and libraries (see <a href="https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/docs/supported-libraries.md">supported technologies</a>).</p>
<p>Using instrumentation means that the application bytecode and the embedded libraries are modified automatically to make them behave as if explicit modifications were made in their source code to call the OpenTelemetry SDK in order to create traces, spans and metrics.</p>
<p>When an application is deployed with the OpenTelemetry instrumentation agent, the cloud resource attributes for GCP and AWS are included but not enabled by default since version 2.2.0. You can enable them <a href="https://opentelemetry.io/docs/languages/java/automatic/configuration/#enable-resource-providers-that-are-disabled-by-default">through configuration</a> by setting the following properties:</p>
<ul>
<li>
<p>For AWS: <code>otel.resource.providers.aws.enabled=true</code></p>
</li>
<li>
<p>For GCP: <code>otel.resource.providers.gcp.enabled=true</code></p>
</li>
</ul>
<h2>Elastic OpenTelemetry Java Distribution</h2>
<p>The Elastic OpenTelemetry Java distribution relies on the OpenTelemetry Java instrumentation which we often refer to as the Vanilla OpenTelemetry, and it thus inherits all of its features.</p>
<p>One major difference though is that the resource attributes providers for GCP and AWS are included and enabled by default to provide a better onboarding experience without extra configuration.</p>
<p>The minor cost to this is that it might make the application startup slightly slower due to having to call an HTTP(S) endpoint. This overhead is usually negligible compared to application startup but can become significant for some setups.</p>
<p>In order to reduce the startup overhead, or when the cloud provider is known in advance, you can selectively disable unused provider implementations through configuration:</p>
<ul>
<li>
<p>For AWS: <code>otel.resource.providers.aws.enabled=false</code></p>
</li>
<li>
<p>For GCP: <code>otel.resource.providers.gcp.enabled=false</code></p>
</li>
</ul>
<h2>Conclusion</h2>
<p>With this blogpost we have introduced what OpenTelemetry cloud resource attributes are and how they can be used and configured into application deployments using either OpenTelemetry SDK/API and Instrumentation agents.</p>
<p>When using the Elastic OpenTelemetry Java distribution, those resource providers are automatically provided and enabled for an easy and simple onboarding experience.</p>
<p>Another very interesting aspect of the cloud resource attribute providers available in the <a href="https://github.com/open-telemetry/opentelemetry-java-contrib">opentelemetry-java-contrib</a> repository is that they are maintained by their respective vendors (Google and Amazon). For the end-user it means those implementations should be quite well tested and be robust to changes in the underlying infrastructure. For solution vendors like Elastic, it means we don't have to re-implement and reverse-engineer the infrastructure details of every cloud provider, hence proving that investing in those common components is a net win for the broader OpenTelemetry community.</p>
]]></content:encoded>
            <category>observability-labs</category>
            <enclosure url="https://www.elastic.co/observability-labs/assets/images/opentelemetry-java-automatic-cloud-resource-attributes/flexible-implementation-1680X980.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[Independence with OpenTelemetry on Elastic]]></title>
            <link>https://www.elastic.co/observability-labs/blog/opentelemetry-observability</link>
            <guid isPermaLink="false">opentelemetry-observability</guid>
            <pubDate>Tue, 15 Nov 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[OpenTelemetry has become a key component for observability given its open standards and developer-friendly tools. See how easily Elastic Observability integrates with OTel to provide a platform that minimizes vendor lock-in and maximizes flexibility.]]></description>
            <content:encoded><![CDATA[<p>The drive for faster, more scalable services is on the rise. Our day-to-day lives depend on apps, from a food delivery app to have your favorite meal delivered, to your banking app to manage your accounts, to even apps to schedule doctor’s appointments. These apps need to be able to grow from not only a features standpoint but also in terms of user capacity. The scale and need for global reach drives increasing complexity for these high-demand cloud applications.</p>
<p>In order to keep pace with demand, most of these online apps and services (for example, mobile applications, web pages, SaaS) are moving to a distributed microservice-based architecture and Kubernetes. Once you’ve migrated your app to the cloud, how do you manage and monitor production, scale, and availability of the service? <a href="https://opentelemetry.io/">OpenTelemetry</a> is quickly becoming the de facto standard for instrumentation and collecting application telemetry data for Kubernetes applications.</p>
<p><a href="https://www.elastic.co/what-is/opentelemetry">OpenTelemetry (OTel)</a> is an open source project providing a collection of tools, APIs, and SDKs that can be used to generate, collect, and export telemetry data (metrics, logs, and traces) to understand software performance and behavior. OpenTelemetry recently became a CNCF incubating project and has a significant amount of growing community and vendor support.</p>
<p>While OTel provides a standard way to instrument applications with a standard telemetry format, it doesn’t provide any backend or analytics components. Hence using OTel libraries in applications, infrastructure, and user experience monitoring provides flexibility in choosing the appropriate <a href="https://www.elastic.co/observability">observability tool</a> of choice. There is no longer any vendor lock-in for application performance monitoring (APM).</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/opentelemetry-observability/blog-elastic-otel-1.png" alt="" /></p>
<p>Elastic Observability natively supports OpenTelemetry and its OpenTelemetry protocol (OTLP) to ingest traces, metrics, and logs. All of Elastic Observability’s APM capabilities are available with OTel data. Hence the following capabilities (and more) are available for OTel data:</p>
<ul>
<li>Service maps</li>
<li>Service details (latency, throughput, failed transactions)</li>
<li>Dependencies between services</li>
<li>Transactions (traces)</li>
<li>ML correlations (specifically for latency)</li>
<li>Service logs</li>
</ul>
<p>In addition to Elastic’s APM and unified view of the telemetry data, you will now be able to use Elastic’s powerful machine learning capabilities to reduce the analysis, and alerting to help reduce MTTR.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/opentelemetry-observability/blog-elastic-otel-2.png" alt="" /></p>
<p>Given its open source heritage, Elastic also supports other CNCF based projects, such as Prometheus, Fluentd, Fluent Bit, Istio, Kubernetes (K8S), and many more.</p>
<p>This blog will show:</p>
<ul>
<li>How to get a popular OTel instrumented demo app (Hipster Shop) configured to ingest into <a href="http://cloud.elastic.co">Elastic Cloud</a> through a few easy steps</li>
<li>Highlight some of the Elastic APM capabilities and features around OTel data and what you can do with this data once it’s in Elastic</li>
</ul>
<p>In follow-up blogs, we will detail how to use Elastic’s machine learning with OTel telemetry data, how to instrument OTel application metrics for specific languages, how we can support Prometheus ingest through the OTel collector, and more. Stay tuned!</p>
<h2>Prerequisites and config</h2>
<p>If you plan on following this blog, here are some of the components and details we used to set up the configuration:</p>
<ul>
<li>Ensure you have an account on <a href="http://cloud.elastic.co">Elastic Cloud</a> and a deployed stack (<a href="https://www.elastic.co/guide/en/elastic-stack/current/installing-elastic-stack.html">see instructions here</a>).</li>
<li>We used the OpenTelemetry Demo. Directions for using Elastic with OpenTelemetry Demo are <a href="https://github.com/elastic/opentelemetry-demo">here</a>.</li>
<li>Make sure you have <a href="https://kubernetes.io/docs/reference/kubectl/">kubectl</a> and <a href="https://helm.sh/">helm</a> also installed locally.</li>
<li>Additionally, we are using an OTel manually instrumented version of the application. No OTel automatic instrumentation was used in this blog configuration.</li>
<li>Location of our clusters. While we used Google Kubernetes Engine (GKE), you can use any Kubernetes platform of your choice.</li>
<li>While Elastic can ingest telemetry directly from OTel instrumented services, we will focus on the more traditional deployment, which uses the OpenTelemetry Collector.</li>
<li>Prometheus and FluentD/Fluent Bit — traditionally used to pull all Kubernetes data — is not being used here versus Kubernetes Agents. Follow-up blogs will showcase this.</li>
</ul>
<p>Here is the configuration we will get set up in this blog:</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/opentelemetry-observability/blog-elastic-otel-3.png" alt="Configuration to ingest OpenTelemetry data used in this blog" /></p>
<h2>Setting it all up</h2>
<p>Over the next few steps, I’ll walk through an <a href="https://www.elastic.co/observability/opentelemetry">Opentelemetry visualization</a>:</p>
<ul>
<li>Getting an account on Elastic Cloud</li>
<li>Bringing up a GKE cluster</li>
<li>Bringing up the application</li>
<li>Configuring Kubernetes OTel Collector configmap to point to Elastic Cloud</li>
<li>Using Elastic Observability APM with OTel data for improved visibility</li>
</ul>
<h3>Step 0: Create an account on Elastic Cloud</h3>
<p>Follow the instructions to <a href="https://cloud.elastic.co/registration?fromURI=/home">get started on Elastic Cloud</a>.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/opentelemetry-observability/blog-elastic-otel-4.png" alt="" /></p>
<h3>Step 1: Bring up a K8S cluster</h3>
<p>We used Google Kubernetes Engine (GKE), but you can use any Kubernetes platform of your choice.</p>
<p>There are no special requirements for Elastic to collect OpenTelemetry data from a Kubernetes cluster. Any normal Kubernetes cluster on GKE, EKS, AKS, or Kubernetes compliant cluster (self-deployed and managed) works.</p>
<h3>Step 2: Load the OpenTelemetry demo application on the cluster</h3>
<p>Get your application on a Kubernetes cluster in your cloud service of choice or local Kubernetes platform. The application I am using is available <a href="https://github.com/bshetti/opentelemetry-microservices-demo/tree/main/deploy-with-collector-k8s">here</a>.</p>
<p>First clone the directory locally:</p>
<pre><code class="language-bash">git clone https://github.com/elastic/opentelemetry-demo.git
</code></pre>
<p>(Make sure you have <a href="https://kubernetes.io/docs/reference/kubectl/">kubectl</a> and <a href="https://helm.sh/">helm</a> also installed locally.)</p>
<p>The instructions utilize a specific opentelemetry-collector configuration for Elastic. Essentially, the Elastic <a href="https://github.com/elastic/opentelemetry-demo/blob/main/kubernetes/elastic-helm/values.yaml">values.yaml</a> file specified in the elastic/opentelemetry-demo configure the opentelemetry-collector to point to the Elastic APM Server using two main values:</p>
<p>OTEL_EXPORTER_OTLP_ENDPOINT is Elastic’s APM Server<br />
OTEL_EXPORTER_OTLP_HEADERS Elastic Authorization</p>
<p>These two values can be found in the OpenTelemetry setup instructions under the APM integration instructions (Integrations-&gt;APM) in your Elastic cloud.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/opentelemetry-observability/blog-elastic-apm-agents.png" alt="elastic apm agents" /></p>
<p>Once you obtain this, the first step is to create a secret key on the cluster with your Elastic APM server endpoint, and your APM Secret Token with the following instruction:</p>
<pre><code class="language-bash">kubectl create secret generic elastic-secret \
  --from-literal=elastic_apm_endpoint='YOUR_APM_ENDPOINT_WITHOUT_HTTPS_PREFIX' \
  --from-literal=elastic_apm_secret_token='YOUR_APM_SECRET_TOKEN'
</code></pre>
<p>Don't forget to replace:</p>
<ul>
<li>YOUR_APM_ENDPOINT_WITHOUT_HTTPS_PREFIX: your Elastic APM endpoint ( <strong>without https:// prefix</strong> ) with OTEL_EXPORTER_OTLP_ENDPOINT</li>
<li>YOUR_APM_SECRET_TOKEN: your Elastic APM secret token OTEL_EXPORTER_OTLP_HEADERS</li>
</ul>
<p>Now execute the following commands:</p>
<pre><code class="language-bash"># switch to the kubernetes/elastic-helm directory
cd kubernetes/elastic-helm

# add the open-telemetry Helm repostiroy
helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts

# deploy the demo through helm install
helm install -f values.yaml my-otel-demo open-telemetry/opentelemetry-demo
</code></pre>
<p>Once your application is up on Kubernetes, you will have the following pods (or some variant) running on the <strong>default</strong> namespace.</p>
<pre><code class="language-bash">kubectl get pods -n default
</code></pre>
<p>Output should be similar to the following:</p>
<pre><code class="language-bash">NAME                                                  READY   STATUS    RESTARTS      AGE
my-otel-demo-accountingservice-5c77754b4f-vwph6       1/1     Running   0             5d4h
my-otel-demo-adservice-6b8b7c7dc5-mb7j5               1/1     Running   0             5d4h
my-otel-demo-cartservice-76d94b7dcd-2g4lf             1/1     Running   0             5d4h
my-otel-demo-checkoutservice-988bbdb88-hmkrp          1/1     Running   0             5d4h
my-otel-demo-currencyservice-6cf4b5f9f6-vz9t2         1/1     Running   0             5d4h
my-otel-demo-emailservice-868c98fd4b-lpr7n            1/1     Running   6 (18h ago)   5d4h
my-otel-demo-featureflagservice-8446ff9c94-lzd4w      1/1     Running   0             5d4h
my-otel-demo-ffspostgres-867945d9cf-zzwd7             1/1     Running   0             5d4h
my-otel-demo-frauddetectionservice-5c97c589b9-z8fhz   1/1     Running   0             5d4h
my-otel-demo-frontend-d85ccf677-zg9fp                 1/1     Running   0             5d4h
my-otel-demo-frontendproxy-6c5c4fccf6-qmldp           1/1     Running   0             5d4h
my-otel-demo-kafka-68bcc66794-dsbr6                   1/1     Running   0             5d4h
my-otel-demo-loadgenerator-64c545b974-xfccq           1/1     Running   1 (36h ago)   5d4h
my-otel-demo-otelcol-fdfd9c7cf-6lr2w                  1/1     Running   0             5d4h
my-otel-demo-paymentservice-7955c68859-ff7zg          1/1     Running   0             5d4h
my-otel-demo-productcatalogservice-67c879657b-wn2wj   1/1     Running   0             5d4h
my-otel-demo-quoteservice-748d754ffc-qcwm4            1/1     Running   0             5d4h
my-otel-demo-recommendationservice-df78894c7-lwm5v    1/1     Running   0             5d4h
my-otel-demo-redis-7d48567546-h4p4t                   1/1     Running   0             5d4h
my-otel-demo-shippingservice-f6fc76ddd-2v7qv          1/1     Running   0             5d4h
</code></pre>
<h3>Step 3: Open Kibana and use the APM Service Map to view your OTel instrumented Services</h3>
<p>In the Elastic Observability UI under APM, select servicemap to see your services.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/opentelemetry-observability/blog-elastic-observability-APM.png" alt="elastic observability APM" /></p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/opentelemetry-observability/blog-elastic-observability-OTEL-service-map.png" alt="elastic observability OTEL service map" /></p>
<p>If you are seeing this, then the OpenTelemetry Collector is sending data into Elastic:</p>
<p><em>Congratulations,</em> <em>you've instrumented the OpenTelemetry demo application using and successfully ingested the telemetry data into the Elastic!</em></p>
<h3>Step 4: What can Elastic show me?</h3>
<p>Now that the OpenTelemetry data is ingested into Elastic, what can you do?</p>
<p>First, you can view the APM service map (as shown in the previous step) — this will give you a full view of all the services and the transaction flows between services.</p>
<p>Next, you can now check out individual services and the transactions being collected.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/opentelemetry-observability/blog-elastic-observability-frontend-overview.png" alt="elastic observability frontend overview" /></p>
<p>As you can see, the frontend details are listed. Everything from:</p>
<ul>
<li>Average service latency</li>
<li>Throughput</li>
<li>Main transactions</li>
<li>Failed traction rate</li>
<li>Errors</li>
<li>Dependencies</li>
</ul>
<p>Let’s get to the trace. In the Transactions tab, you can review all the types of transactions related to the frontend service:</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/opentelemetry-observability/blog-elastic-observability-frontend-transactions.png" alt="elastic observability frontend transactions" /></p>
<p>Selecting the HTTP POST transaction, we can see the full trace with all the spans:</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/opentelemetry-observability/blog-elastic-observability-frontend-HTTP-POST.png" alt="Average latency for this transaction, throughput, any failures, and of course the trace!" /></p>
<p>Not only can you review the trace but you can also analyze what is related to higher than normal latency for HTTP POST .</p>
<p>Elastic uses machine learning to help identify any potential latency issues across the services from the trace. It’s as simple as selecting the Latency Correlations tab and running the correlation.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/opentelemetry-observability/blog-elastic-latency-correlations.png" alt="elastic observability latency correlations" /></p>
<p>This shows that the high latency transactions are occurring in checkout service with a medium correlation.</p>
<p>You can then drill down into logs directly from the trace view and review the logs associated with the trace to help identify and pinpoint potential issues.</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/opentelemetry-observability/blog-elastic-latency-distribution.png" alt="elastic observability latency distribution" /></p>
<h3>Analyze your data with Elastic machine learning (ML)</h3>
<p>Once OpenTelemetry metrics are in Elastic, start analyzing your data through Elastic’s ML capabilities.</p>
<p>A great review of these features can be found here: <a href="https://www.elastic.co/blog/apm-correlations-elastic-observability-root-cause-transactions">Correlating APM telemetry to determine root causes in transactions</a>. And there are many more videos and blogs on <a href="https://www.elastic.co/blog/">Elastic’s Blog</a>. We’ll follow up with additional blogs on leveraging Elastic’s machine learning capabilities for OpenTelemetry data.</p>
<h2>Conclusion</h2>
<p>I hope you’ve gotten an appreciation for how Elastic Observability can help you ingest and analyze OpenTelemetry data with Elastic’s APM capabilities.</p>
<p>A quick recap of lessons and more specifically learned:</p>
<ul>
<li>How to get a popular OTel instrumented demo app (Hipster Shop) configured to ingest into <a href="http://cloud.elastic.co">Elastic Cloud</a>, through a few easy steps</li>
<li>Highlight some of the Elastic APM capabilities and features around OTel data and what you can do with this once it’s in Elastic</li>
</ul>
<p>Ready to get started? Sign up <a href="https://cloud.elastic.co/registration">for Elastic Cloud</a> and try out the features and capabilities I’ve outlined above to get the most value and visibility out of your OpenTelemetry data.</p>
]]></content:encoded>
            <category>observability-labs</category>
            <enclosure url="https://www.elastic.co/observability-labs/assets/images/opentelemetry-observability/illustration-scalability-gear-1680x980_(1).jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Optimizing cloud resources and cost with APM metadata in Elastic Observability]]></title>
            <link>https://www.elastic.co/observability-labs/blog/optimize-cloud-resources-apm-observability</link>
            <guid isPermaLink="false">optimize-cloud-resources-apm-observability</guid>
            <pubDate>Wed, 16 Aug 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Optimize cloud costs with Elastic APM. Learn how to leverage cloud metadata, calculate pricing, and make smarter decisions for better performance.]]></description>
            <content:encoded><![CDATA[<p>Application performance monitoring (APM) is much more than capturing and tracking errors and stack traces. Today’s cloud-based businesses deploy applications across various regions and even cloud providers. So, harnessing the power of metadata provided by the Elastic APM agents becomes more critical. Leveraging the metadata, including crucial information like cloud region, provider, and machine type, allows us to track costs across the application stack. In this blog post, we look at how we can use cloud metadata to empower businesses to make smarter and cost-effective decisions, all while improving resource utilization and the user experience.</p>
<p>First, we need an example application that allows us to monitor infrastructure changes effectively. We use a Python Flask application with the Elastic Python APM agent. The application is a simple calculator taking the numbers as a REST request. We utilize Locust — a simple load-testing tool to evaluate performance under varying workloads.</p>
<p>The next step includes obtaining the pricing information associated with the cloud services. Every cloud provider is different. Most of them offer an option to retrieve pricing through an API. But today, we will focus on Google Cloud and will leverage their pricing calculator to retrieve relevant cost information.</p>
<h2>The calculator and Google Cloud pricing</h2>
<p>To perform a cost analysis, we need to know the cost of the machines in use. Google provides a billing <a href="https://cloud.google.com/billing/v1/how-tos/catalog-api">API</a> and <a href="https://cloud.google.com/billing/docs/reference/libraries#client-libraries-install-python">Client Library</a> to fetch the necessary data programmatically. In this blog, we are not covering the API approach. Instead, the <a href="https://cloud.google.com/products/calculator">Google Cloud Pricing Calculator</a> is enough. Select the machine type and region in the calculator and set the count 1 instance. It will then report the total estimated cost for this machine. Doing this for an e2-standard-4 machine type results in 107.7071784 US$ for a runtime of 730 hours.</p>
<p>Now, let’s go to our Kibana® where we will create a new index inside Dev Tools. Since we don’t want to analyze text, we will tell Elasticsearch® to treat every text as a keyword. The index name is cloud-billing. I might want to do the same for Azure and AWS, then I can append it to the same index.</p>
<pre><code class="language-bash">PUT cloud-billing
{
  &quot;mappings&quot;: {
    &quot;dynamic_templates&quot;: [
      {
        &quot;stringsaskeywords&quot;: {
          &quot;match&quot;: &quot;*&quot;,
          &quot;match_mapping_type&quot;: &quot;string&quot;,
          &quot;mapping&quot;: {
            &quot;type&quot;: &quot;keyword&quot;
          }
        }
      }
    ]
  }
}
</code></pre>
<p>Next up is crafting our billing document:</p>
<pre><code class="language-bash">POST cloud-billing/_doc/e2-standard-4_europe-west4
{
  &quot;machine&quot;: {
    &quot;enrichment&quot;: &quot;e2-standard-4_europe-west4&quot;
  },
  &quot;cloud&quot;: {
    &quot;machine&quot;: {
       &quot;type&quot;: &quot;e2-standard-4&quot;
    },
    &quot;region&quot;: &quot;europe-west4&quot;,
    &quot;provider&quot;: &quot;google&quot;
  },
  &quot;stats&quot;: {
    &quot;cpu&quot;: 4,
    &quot;memory&quot;: 8
  },
  &quot;price&quot;: {
    &quot;minute&quot;: 0.002459068,
    &quot;hour&quot;: 0.14754408,
    &quot;month&quot;: 107.7071784
  }
}
</code></pre>
<p>We create a document and set a custom ID. This ID matches the instance name and the region since the machines' costs may differ in each region. Automatic IDs could be problematic because I might want to update what a machine costs regularly. I could use a timestamped index for that and only ever use the latest document matching. But this way, I can update and don’t have to worry about it. I calculated the price down to minute and hour prices as well. The most important thing is the machine.enrichment field, which is the same as the ID. The same instance type can exist in multiple regions, but our enrichment processor is limited to match or range. We create a matching name that can explicitly match as in e2-standard-4_europe-west4. It’s up to you to decide whether you want the cloud provider in there and make it google_e2-standard-4_europ-west-4.</p>
<h2>Calculating the cost</h2>
<p>There are multiple ways of achieving this in the Elastic Stack. In this case, we will use an enrich policy, ingest pipeline, and transform.</p>
<p>The enrich policy is rather easy to setup:</p>
<pre><code class="language-bash">PUT _enrich/policy/cloud-billing
{
  &quot;match&quot;: {
    &quot;indices&quot;: &quot;cloud-billing&quot;,
    &quot;match_field&quot;: &quot;machine.enrichment&quot;,
    &quot;enrich_fields&quot;: [&quot;price.minute&quot;, &quot;price.hour&quot;, &quot;price.month&quot;]
  }
}

POST _enrich/policy/cloud-billing/_execute
</code></pre>
<p>Don’t forget to run the _execute at the end of it. This is necessary to make the internal indices used by the enrichment in the ingest pipeline. The ingest pipeline is rather minimalistic — it calls the enrichment and renames a field. This is where our machine.enrichment field comes in. One caveat around enrichment is that when you add new documents to the cloud-billing index, you need to rerun the _execute statement. The last bit calculates the total cost with the count of unique machines seen.</p>
<pre><code class="language-bash">PUT _ingest/pipeline/cloud-billing
{
  &quot;processors&quot;: [
    {
      &quot;set&quot;: {
        &quot;field&quot;: &quot;_temp.machine_type&quot;,
        &quot;value&quot;: &quot;{{cloud.machine.type}}_{{cloud.region}}&quot;
      }
    },
    {
      &quot;enrich&quot;: {
        &quot;policy_name&quot;: &quot;cloud-billing&quot;,
        &quot;field&quot;: &quot;_temp.machine_type&quot;,
        &quot;target_field&quot;: &quot;enrichment&quot;
      }
    },
    {
      &quot;rename&quot;: {
        &quot;field&quot;: &quot;enrichment.price&quot;,
        &quot;target_field&quot;: &quot;price&quot;
      }
    },
    {
      &quot;remove&quot;: {
        &quot;field&quot;: [
          &quot;_temp&quot;,
          &quot;enrichment&quot;
        ]
      }
    },
    {
      &quot;script&quot;: {
        &quot;source&quot;: &quot;ctx.total_price=ctx.count_machines*ctx.price.hour&quot;
      }
    }
  ]
}
</code></pre>
<p>Since this is all configured now, we are ready for our Transform. For this, we need a data view that matches the APM data_streams. This is traces-apm*, metrics-apm.*, logs-apm.*. For the Transform, go to the Transform UI in Kibana and configure it in the following way:</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/optimize-cloud-resources-apm-observability/elastic-blog-1-transform-configuration.png" alt="transform configuration" /></p>
<p>We are doing an hourly breakdown, therefore, I get a document per service, per hour, per machine type. The interesting bit is the aggregations. I want to see the average CPU usage and the 75,95,99 percentile, to view the CPU usage on an hourly basis. Allowing me to identify the CPU usage across an hour. At the bottom, give the transform a name and select an index cloud-costs and select the cloud-billing ingest pipeline.</p>
<p>Here is the entire transform as a JSON document:</p>
<pre><code class="language-bash">PUT _transform/cloud-billing
{
  &quot;source&quot;: {
    &quot;index&quot;: [
      &quot;traces-apm*&quot;,
      &quot;metrics-apm.*&quot;,
      &quot;logs-apm.*&quot;
    ],
    &quot;query&quot;: {
      &quot;bool&quot;: {
        &quot;filter&quot;: [
          {
            &quot;bool&quot;: {
              &quot;should&quot;: [
                {
                  &quot;exists&quot;: {
                    &quot;field&quot;: &quot;cloud.provider&quot;
                  }
                }
              ],
              &quot;minimum_should_match&quot;: 1
            }
          }
        ]
      }
    }
  },
  &quot;pivot&quot;: {
    &quot;group_by&quot;: {
      &quot;@timestamp&quot;: {
        &quot;date_histogram&quot;: {
          &quot;field&quot;: &quot;@timestamp&quot;,
          &quot;calendar_interval&quot;: &quot;1h&quot;
        }
      },
      &quot;cloud.provider&quot;: {
        &quot;terms&quot;: {
          &quot;field&quot;: &quot;cloud.provider&quot;
        }
      },
      &quot;cloud.region&quot;: {
        &quot;terms&quot;: {
          &quot;field&quot;: &quot;cloud.region&quot;
        }
      },
      &quot;cloud.machine.type&quot;: {
        &quot;terms&quot;: {
          &quot;field&quot;: &quot;cloud.machine.type&quot;
        }
      },
      &quot;service.name&quot;: {
        &quot;terms&quot;: {
          &quot;field&quot;: &quot;service.name&quot;
        }
      }
    },
    &quot;aggregations&quot;: {
      &quot;avg_cpu&quot;: {
        &quot;avg&quot;: {
          &quot;field&quot;: &quot;system.cpu.total.norm.pct&quot;
        }
      },
      &quot;percentiles_cpu&quot;: {
        &quot;percentiles&quot;: {
          &quot;field&quot;: &quot;system.cpu.total.norm.pct&quot;,
          &quot;percents&quot;: [
            75,
            95,
            99
          ]
        }
      },
      &quot;avg_transaction_duration&quot;: {
        &quot;avg&quot;: {
          &quot;field&quot;: &quot;transaction.duration.us&quot;
        }
      },
      &quot;percentiles_transaction_duration&quot;: {
        &quot;percentiles&quot;: {
          &quot;field&quot;: &quot;transaction.duration.us&quot;,
          &quot;percents&quot;: [
            75,
            95,
            99
          ]
        }
      },
      &quot;count_machines&quot;: {
        &quot;cardinality&quot;: {
          &quot;field&quot;: &quot;cloud.instance.id&quot;
        }
      }
    }
  },
  &quot;dest&quot;: {
    &quot;index&quot;: &quot;cloud-costs&quot;,
    &quot;pipeline&quot;: &quot;cloud-costs&quot;
  },
  &quot;sync&quot;: {
    &quot;time&quot;: {
      &quot;delay&quot;: &quot;120s&quot;,
      &quot;field&quot;: &quot;@timestamp&quot;
    }
  },
  &quot;settings&quot;: {
    &quot;max_page_search_size&quot;: 1000
  }
}
</code></pre>
<p>Once the transform is created and running, we need a Kibana Data View for the index: cloud-costs. For the transaction, use the custom formatter inside Kibana and set its format to “Duration” in “microseconds.”</p>
<p><img src="https://www.elastic.co/observability-labs/assets/images/optimize-cloud-resources-apm-observability/elastic-blog-2-cloud-costs.png" alt="cloud costs" /></p>
<p>With that, everything is arranged and ready to go.</p>
<h2>Observing infrastructure changes</h2>
<p>Below I created a dashboard that allows us to identify:</p>
<ul>
<li>How much costs a certain service creates</li>
<li>CPU usage</li>
<li>Memory usage</li>
<li>Transaction duration</li>
<li>Identify cost-saving potential</li>
</ul>
<p><img src="https://www.elastic.co/observability-labs/assets/images/optimize-cloud-resources-apm-observability/elastic-blog-3-graphs.png" alt="graphs" /></p>
<p>From left to right, we want to focus on the very first chart. We have the bars representing the CPU as average in green and 95th percentile in blue on top. It goes from 0 to 100% and is normalized, meaning that even with 8 CPU cores, it will still read 100% usage and not 800%. The line graph represents the transaction duration, the average being in red, and the 95th percentile in purple. Last, we have the orange area at the bottom, which is the average memory usage on that host.</p>
<p>We immediately realize that our calculator does not need a lot of memory. Hovering over the graph reveals 2.89% memory usage. The e2-standard-8 machine that we are using has 32 GB of memory. We occasionally spike to 100% CPU in the 95th percentile. When this happens, we see that the average transaction duration spikes to 2.5 milliseconds. However, every hour this machine costs us a rounded 30 cents. Using this information, we can now downsize to a better fit. The average CPU usage is around 11-13%, and the 95th percentile is not that far away.</p>
<p>Because we are using 8 CPUs, one could now say that 12.5% represents a full core, but that is just an assumption on a piece of paper. Nonetheless, we know there is a lot of headroom, and we can downscale quite a bit. In this case, I decided to go to 2 CPUs and 2 GB of RAM, known as e2-highcpu2. This should fit my calculator application better. We barely touched the RAM, 2.89% out of 32GB are roughly 1GB of use. After the change and reboot of the calculator machine, I started the same Locust test to identify my CPU usage and, more importantly, if my transactions get slower, and if so, by how much. Ultimately, I want to decide whether 1 millisecond more latency is worth 10 more cents per hour. I added the change as an annotation in Lens.</p>
<p>After letting it run for a bit, we can now identify the smaller hosts' impact. In this case, we can see that the average did not change. However, the 95th percentile — as in 95% of all transactions are below this value — did spike up. Again, it looks bad at first, but checking in, it went from ~1.5 milliseconds to ~2.10 milliseconds, a ~0.6 millisecond increase. Now, you can decide whether that 0.6 millisecond increase is worth paying ~180$ more per month or if the current latency is good enough.</p>
<h2>Conclusion</h2>
<p>Observability is more than just collecting logs, metrics, and traces. Linking user experience to cloud costs allows your business to identify areas where you can save money. Having the right tools at your disposal will help you generate those insights quickly. Making informed decisions about how to optimize your cloud cost and ultimately improve the user experience is the bottom-line goal.</p>
<p>The dashboard and data view can be found in my <a href="https://github.com/philippkahr/blogs/tree/main/apm-cost-optimisation">GitHub repository</a>. You can download the .ndjson file and import it using the Saved Objects inside Stack Management in Kibana.</p>
<h2>Caveats</h2>
<p>Pricing is only for base machines without any disk information, static public IP addresses, and any other additional cost, such as licenses for operating systems. Furthermore, it excludes spot pricing, discounts, or free credits. Additionally, data transfer costs between services are also not included. We only calculate it based on the minute rate of the service running — we are not checking billing intervals from Google Cloud. In our case, we would bill per minute, regardless of what Google Cloud has. Using the count for unique instance.ids work as intended. However, if a machine is only running for one minute, we calculate it based on the hourly rate. So, a machine running for one minute, will cost the same as running for 50 minutes — at least how we calculate it. The transform uses calendar hour intervals; therefore, it's 8 am-9 am, 9 am-10 am, and so on.</p>
<p><em>The release and timing of any features or functionality described in this post remain at Elastic's sole discretion. Any features or functionality not currently available may not be delivered on time or at all.</em></p>
]]></content:encoded>
            <category>observability-labs</category>
            <enclosure url="https://www.elastic.co/observability-labs/assets/images/optimize-cloud-resources-apm-observability/illustration-out-of-box-data-vis-1680x980.png" length="0" type="image/png"/>
        </item>
    </channel>
</rss>