<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: hridyesh bisht</title>
    <description>The latest articles on DEV Community by hridyesh bisht (@hridyeshbisht).</description>
    <link>https://dev.to/hridyeshbisht</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F468199%2Fe4a23a5f-a1f2-4844-b2c5-e2bc9b847acb.jpg</url>
      <title>DEV Community: hridyesh bisht</title>
      <link>https://dev.to/hridyeshbisht</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hridyeshbisht"/>
    <language>en</language>
    <item>
      <title>Your Telemetry Has Data. Does It Have Context?</title>
      <dc:creator>hridyesh bisht</dc:creator>
      <pubDate>Fri, 13 Nov 2026 18:01:09 +0000</pubDate>
      <link>https://dev.to/aws-builders/your-telemetry-has-data-does-it-have-context-3a92</link>
      <guid>https://dev.to/aws-builders/your-telemetry-has-data-does-it-have-context-3a92</guid>
      <description>&lt;p&gt;Imagine you're investigating a slow checkout experience. Your application generates metrics, logs, and traces, but connecting the information across these signals isn't always straightforward.&lt;/p&gt;

&lt;p&gt;For example, one component identifies a service as &lt;code&gt;checkout-api&lt;/code&gt;, while another reports it as &lt;code&gt;checkout&lt;/code&gt;. Although both refer to the same logical service, inconsistent naming makes it harder to connect related telemetry and understand what's happening.&lt;/p&gt;

&lt;p&gt;This highlights an important challenge in distributed systems: collecting telemetry is only the first step. You also need consistent naming, shared context, and reliable ways to navigate between signals.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://programmerprodigy.code.blog/2026/11/01/beyond-the-collector-how-the-open-source-observability-stack-fits-together/" rel="noopener noreferrer"&gt;previous article&lt;/a&gt;, we explored how Prometheus, Jaeger, OpenSearch, and Perses fit into an open-source observability stack. Now, let's look at how to make telemetry from different services and signals work together.&lt;/p&gt;

&lt;p&gt;We'll explore three concepts that make this possible: semantic conventions, resource attributes, and context propagation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Semantic conventions
&lt;/h2&gt;

&lt;p&gt;OpenTelemetry semantic conventions define standard names and meanings for telemetry attributes, events, and operations. They help instrumentation libraries and applications describe common concepts consistently, making telemetry easier for observability tools to interpret.&lt;/p&gt;

&lt;p&gt;For example, OpenTelemetry defines standard HTTP attributes:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Attribute&lt;/th&gt;
&lt;th&gt;Example value&lt;/th&gt;
&lt;th&gt;What it describes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;http.request.method&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;POST&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The HTTP request method&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;http.route&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/payments/{payment_id}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The matched route template&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;http.response.status_code&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;201&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The HTTP response status code&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;However, semantic conventions don't enforce consistency automatically. Your instrumentation and telemetry pipeline must use and preserve the defined conventions. Custom attributes might still be necessary for application-specific details.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Pay attention to attribute cardinality, especially when using attributes as metric dimensions. Use route templates such as &lt;code&gt;/payments/{payment_id}&lt;/code&gt; rather than individual URLs such as &lt;code&gt;/payments/12345&lt;/code&gt;. Recording unique values for every request can create high-cardinality metric data, increasing storage and query costs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resource attributes vs. span attributes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Resource attributes
&lt;/h3&gt;

&lt;p&gt;A resource represents an entity that produces telemetry, such as a service, process, or container. Its attributes provide identifying information that can accompany the entity's metrics, logs, and traces.&lt;/p&gt;

&lt;p&gt;For example, a &lt;code&gt;payment-service&lt;/code&gt; instance might report the following resource:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;"service.name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"payment-service"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"service.namespace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"checkout"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"service.version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2.4.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"deployment.environment.name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"production"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"service.instance.id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"payment-service-instance-01"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each attribute provides a different piece of information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;service.name&lt;/code&gt; identifies the logical service.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;service.namespace&lt;/code&gt; groups related services.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;service.version&lt;/code&gt; identifies the deployed version.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;deployment.environment.name&lt;/code&gt; identifies the deployment environment.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;service.instance.id&lt;/code&gt; distinguishes this instance from other instances of the same service.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, multiple instances of &lt;code&gt;payment-service&lt;/code&gt; can share the same &lt;code&gt;service.name&lt;/code&gt;, &lt;code&gt;service.version&lt;/code&gt;, and environment while reporting different &lt;code&gt;service.instance.id&lt;/code&gt; values.&lt;/p&gt;

&lt;h3&gt;
  
  
  Span attributes
&lt;/h3&gt;

&lt;p&gt;A span represents an individual operation within a trace. Its attributes describe what happened during that operation.&lt;/p&gt;

&lt;p&gt;For example, a span created when &lt;code&gt;payment-service&lt;/code&gt; handles an HTTP request might contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;"http.request.method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"POST"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"http.route"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"/payments/{payment_id}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"http.response.status_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These attributes describe the request handled by the service, rather than the service itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This distinction helps you investigate telemetry at different levels. Resource attributes identify the source of telemetry, while span attributes provide details about individual operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Context propagation
&lt;/h2&gt;

&lt;p&gt;A distributed request often passes through several services. To understand the complete request, you need to connect the spans generated by each service into one distributed trace.&lt;/p&gt;

&lt;p&gt;OpenTelemetry context propagation carries information between services and execution units. For distributed tracing, this context includes identifiers such as the trace ID and span ID. The receiving service extracts the incoming context and uses it when creating its own span.&lt;/p&gt;

&lt;p&gt;OpenTelemetry commonly uses the &lt;a href="https://www.w3.org/TR/trace-context/" rel="noopener noreferrer"&gt;W3C Trace Context&lt;/a&gt; specification to propagate trace context across HTTP requests.&lt;/p&gt;

&lt;p&gt;For HTTP requests, services commonly transmit this context through the &lt;code&gt;traceparent&lt;/code&gt; header. Its format is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;version&amp;gt;-&amp;lt;trace-id&amp;gt;-&amp;lt;parent-id&amp;gt;-&amp;lt;trace-flags&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each field serves a specific purpose:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;version&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The Trace Context format version&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;trace-id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The identifier shared by all spans in the distributed trace&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;parent-id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The span ID of the calling operation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;trace-flags&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Trace-related flags, including the sampling decision&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;When a service receives a request, it extracts the incoming context and uses it as the parent context for its new span. Before calling another service, it propagates the updated context. This process connects spans across the request path.&lt;/p&gt;

&lt;p&gt;The following sequence shows how the API gateway, order service, and payment service propagate context.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftpswmujs3731urp28sjo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftpswmujs3731urp28sjo.png" alt="A diagram displaying sequence shows how the API gateway, order service, and payment service propagate context." width="799" height="552"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The resulting trace represents the request across all three services. You can inspect it in a tracing backend such as Jaeger to follow the request and identify where an operation takes longer than expected.&lt;/p&gt;

&lt;h3&gt;
  
  
  What context propagation does not do
&lt;/h3&gt;

&lt;p&gt;Context propagation carries context information, not telemetry data. It does not transfer log records or metric measurements between services. Each service must still generate and export its own telemetry.&lt;/p&gt;

&lt;p&gt;It also does not guarantee that every signal will automatically appear together in an observability tool. Correlation requires the relevant trace context, resource information, instrumentation, and backend support.&lt;/p&gt;

&lt;p&gt;Propagation also requires attention at service boundaries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Asynchronous communication:&lt;/strong&gt; Message queues and event-driven systems need to carry context through message headers or other supported metadata. Depending on the instrumentation, you might need additional configuration or manual propagation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;External services:&lt;/strong&gt; Avoid propagating sensitive information to untrusted services. In particular, review what you include in baggage and define clear propagation boundaries.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Correlating logs, metrics, and traces
&lt;/h2&gt;

&lt;p&gt;Two mechanisms are particularly useful for connecting logs and metrics to traces: trace identifiers in log records and exemplars in metrics.&lt;/p&gt;

&lt;h3&gt;
  
  
  Linking logs to traces
&lt;/h3&gt;

&lt;p&gt;A log record can include the trace and span IDs active when the application emits it. These identifiers help an observability backend associate the log with the operation that generated it.&lt;/p&gt;

&lt;p&gt;For example, the &lt;code&gt;payment-service&lt;/code&gt; might emit the following log record:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2026-11-10T10:30:00Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"severity_text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"ERROR"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Payment provider request timed out"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"trace_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"4bf92f3577b34da6a3ce929d0e0e4736"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"span_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"00f067aa0ba902b7"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is an illustrative JSON representation. OpenTelemetry's log data model defines the corresponding fields as &lt;code&gt;TraceId&lt;/code&gt; and &lt;code&gt;SpanId&lt;/code&gt;. Exporters and logging integrations can map them to different field names and formats.&lt;/p&gt;

&lt;p&gt;With these identifiers, you can open a trace, locate the relevant span, and inspect the associated log records. For example, a timeout message linked to a payment span can help you investigate why a checkout request failed.&lt;/p&gt;

&lt;p&gt;This correlation requires a logging integration or another mechanism that captures the active trace context and adds the identifiers to log records. Not every logging framework does this automatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  Linking metrics to traces with exemplars
&lt;/h3&gt;

&lt;p&gt;Metrics help you identify patterns and changes in system behavior, such as increased request latency or error rates. However, an aggregated metric usually doesn't show which individual request contributed to a measurement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exemplars&lt;/strong&gt; provide a way to investigate individual measurements. An exemplar associates a metric measurement with additional context, which can include a trace ID and span ID.&lt;/p&gt;

&lt;p&gt;Consider an HTTP request duration histogram. The following is a simplified representation of the histogram and one of its exemplars:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Metric: http.server.request.duration

Aggregated measurements:
  Request count: 1,250
  Duration distribution: ...

Exemplar:
  Observed value: 2.4 seconds
  Trace ID: 4bf92f3577b34da6a3ce929d0e0e4736
  Span ID: 00f067aa0ba902b7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The histogram helps you identify a latency problem across many requests. The exemplar provides a reference to a particular measurement and its trace context, so you can investigate the corresponding request.&lt;/p&gt;

&lt;p&gt;Exemplars are optional. Their availability depends on instrumentation, SDK and exporter configuration, and backend support. The referenced trace must also be available in your tracing backend.&lt;/p&gt;

&lt;p&gt;Avoid adding trace IDs or span IDs as metric labels. Because these identifiers can vary for every request, using them as labels creates high-cardinality time series and increases storage and query costs. Exemplars provide a more suitable way to link metric measurements to traces.&lt;/p&gt;

&lt;h3&gt;
  
  
  How the signals fit together
&lt;/h3&gt;

&lt;p&gt;The following diagram distinguishes shared resource information from direct links between signals.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq3aeaech9hbdt1fe8tnm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq3aeaech9hbdt1fe8tnm.png" alt="The following diagram distinguishes shared resource information from direct links between signals. &lt;br&gt;
" width="594" height="622"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Resource attributes help identify and group telemetry from the same entity. Logs can link directly to traces through trace and span identifiers, while metric exemplars provide references to trace context.&lt;/p&gt;

&lt;p&gt;Together, these mechanisms help you move from an aggregated view of system health to the details of an individual request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common correlation gaps
&lt;/h2&gt;

&lt;p&gt;Even with consistent instrumentation, implementation and configuration issues can make cross-signal correlation unreliable.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Context propagation stops at service boundaries:&lt;/strong&gt; HTTP instrumentation might handle propagation automatically, but asynchronous messaging, custom protocols, and unsupported libraries can require additional configuration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logs don't contain trace context:&lt;/strong&gt; A logging framework might not automatically include trace and span IDs. Verify that your logging integration captures the active context and exports the identifiers with log records.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exemplars aren't available or preserved:&lt;/strong&gt; Exemplar support depends on the SDK, exporter, and observability backend. Verify that your pipeline preserves exemplars and that your backend can use them to navigate to traces.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A missing trace is mistaken for an instrumentation failure:&lt;/strong&gt; Sampling decisions, export failures, and retention policies can affect trace availability. Check these settings before concluding that instrumentation failed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separate backends don't support cross-signal navigation:&lt;/strong&gt; Exporting metrics, logs, and traces to different destinations doesn't guarantee that you can navigate between them. Check whether your observability tools support the required correlation features and whether you have configured them correctly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Validate telemetry correlation
&lt;/h3&gt;

&lt;p&gt;Use this checklist when testing a new service or reviewing an existing telemetry pipeline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Send a test request that crosses at least two services.&lt;/li&gt;
&lt;li&gt;[ ] Verify that the resulting spans share a trace ID and have the expected parent-child relationships.&lt;/li&gt;
&lt;li&gt;[ ] Confirm that the corresponding log records contain the expected trace and span identifiers.&lt;/li&gt;
&lt;li&gt;[ ] Check whether metric exemplars link to traces that are available for inspection.&lt;/li&gt;
&lt;li&gt;[ ] Test cross-signal navigation in your observability backend.&lt;/li&gt;
&lt;li&gt;[ ] Repeat these checks across asynchronous and external service boundaries where applicable.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Dash0
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.dash0.com/" rel="noopener noreferrer"&gt;Dash0&lt;/a&gt; is an OpenTelemetry-native observability platform that brings metrics, logs, traces, and resource information into a unified interface. It also provides service monitoring, dashboards, alerting, and query capabilities.&lt;/p&gt;

&lt;p&gt;Dash0 extends OpenTelemetry semantic conventions with its own &lt;code&gt;dash0.*&lt;/code&gt; attributes, metrics, and events. It maintains a public registry that documents the meaning and usage of these fields.&lt;/p&gt;

&lt;p&gt;Dash0 also supports &lt;strong&gt;semantic convention migrations&lt;/strong&gt; during ingestion. These migrations help align incoming telemetry with a selected conventions version. For example, Dash0 can rename &lt;code&gt;http.status_code&lt;/code&gt; to &lt;code&gt;http.response.status_code&lt;/code&gt; or move &lt;code&gt;service.name&lt;/code&gt; from span attributes to resource attributes.&lt;/p&gt;

&lt;p&gt;Consider the checkout application from our earlier example. Users report slow checkout requests, and the operations team needs to identify the affected service.&lt;/p&gt;

&lt;p&gt;Dash0 provides several tools to investigate the issue:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Identify the problem:&lt;/strong&gt; The Service Catalog helps identify checkout services with increased latency or error rates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Find the dependency:&lt;/strong&gt; The Service Map shows service relationships and request flows, helping identify which downstream services need investigation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inspect the request:&lt;/strong&gt; The Trace Explorer lets you examine a representative trace and locate slow operations across the service path.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Find supporting evidence:&lt;/strong&gt; Inspect related logs for errors, such as payment provider timeouts, associated with the affected request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify the fix:&lt;/strong&gt; After resolving the issue, compare latency and error metrics to confirm that the service has recovered.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The following diagram summarizes the workflow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4bb9lo5q1jnekuu62jaq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4bb9lo5q1jnekuu62jaq.png" alt="The following diagram displaying how to investigate data in Dash0." width="799" height="110"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A unified observability platform doesn't remove the need for correct instrumentation. Dash0 cannot reconstruct missing trace context or generate application-specific telemetry that your instrumentation doesn't capture. You still need to configure your OpenTelemetry SDKs and Collectors correctly.&lt;/p&gt;

&lt;p&gt;You should also evaluate data residency, deployment requirements, telemetry volume, and compatibility with existing tools and workflows before adopting the platform.&lt;/p&gt;

&lt;p&gt;Dash0 is worth considering when you want a managed, OpenTelemetry-native experience without operating multiple observability backends yourself. However, teams with specific infrastructure, compliance, or backend requirements should validate those needs before migrating.&lt;/p&gt;

&lt;p&gt;For more information, see the &lt;a href="https://www.dash0.com/docs/dash0" rel="noopener noreferrer"&gt;Dash0 documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Collecting metrics, logs, and traces gives you visibility into your applications. Connecting those signals gives you a more complete picture of system behavior.&lt;/p&gt;

&lt;p&gt;OpenTelemetry provides several building blocks for doing this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Semantic conventions&lt;/strong&gt; establish common names and meanings for telemetry.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource attributes&lt;/strong&gt; identify the entities producing telemetry.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context propagation&lt;/strong&gt; connects operations across service boundaries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Log trace context and metric exemplars&lt;/strong&gt; provide ways to navigate between signals.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These mechanisms don't remove the need for correct instrumentation or backend configuration. They provide the shared structure and context that make correlation possible.&lt;/p&gt;

&lt;p&gt;When telemetry follows consistent conventions and carries the right context, you spend less time figuring out what each data point represents and more time understanding what happened.&lt;/p&gt;

</description>
      <category>opentelemetry</category>
      <category>data</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>Beyond the Collector: How the Open-Source Observability Stack Fits Together</title>
      <dc:creator>hridyesh bisht</dc:creator>
      <pubDate>Fri, 06 Nov 2026 07:13:59 +0000</pubDate>
      <link>https://dev.to/aws-builders/beyond-the-collector-how-the-open-source-observability-stack-fits-together-l0j</link>
      <guid>https://dev.to/aws-builders/beyond-the-collector-how-the-open-source-observability-stack-fits-together-l0j</guid>
      <description>&lt;p&gt;In &lt;a href="https://programmerprodigy.code.blog/2025/06/04/understanding-observability-with-opentelemetry-and-coffee/" rel="noopener noreferrer"&gt;Understanding Observability with OpenTelemetry and Coffee&lt;/a&gt;, I introduced the fundamentals of observability. In &lt;a href="https://programmerprodigy.code.blog/2026/02/08/native-opetelemetry/" rel="noopener noreferrer"&gt;Native OpenTelemetry&lt;/a&gt;, I explored how OpenTelemetry generates and processes telemetry, how the OpenTelemetry Collector manages telemetry pipelines, and why understanding those pipelines matters when troubleshooting production issues.&lt;/p&gt;

&lt;p&gt;But what happens after telemetry leaves the Collector? Which tools store and analyze it? How do you connect these tools, and what should you consider before operating them in production?&lt;/p&gt;

&lt;p&gt;This article explores the open-source observability ecosystem, from the responsibilities of individual tools to the engineering decisions involved in running them together.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;OpenTelemetry isn't your observability backend&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;OpenTelemetry is an open-source, vendor-neutral observability framework. It provides APIs, SDKs, instrumentation libraries, and tools for generating, collecting, and exporting telemetry such as metrics, logs, and traces.&lt;/p&gt;

&lt;p&gt;It also defines common data formats and semantic conventions that help applications describe telemetry consistently. However, OpenTelemetry isn't an observability backend. It doesn't replace the storage, query interfaces, and dashboards that teams use to investigate production issues. Those capabilities come from other tools.&lt;/p&gt;

&lt;p&gt;Think of OpenTelemetry as the system that standardizes how information leaves each part of the coffee shop. The observability tools help you examine that information and understand what happened.&lt;/p&gt;

&lt;p&gt;Let's look at what each tool contributes to an observability stack.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Prometheus&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Prometheus commonly scrapes metrics endpoints exposed by applications and infrastructure. This pull-based model lets Prometheus collect measurements at configured intervals and discover targets through supported service-discovery mechanisms.&lt;/p&gt;

&lt;p&gt;Prometheus is useful when you need to answer questions such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is request latency increasing?
&lt;/li&gt;
&lt;li&gt;Are error rates rising after a deployment?
&lt;/li&gt;
&lt;li&gt;Is an application approaching its CPU or memory limits?
&lt;/li&gt;
&lt;li&gt;Does the system meet its latency or availability targets?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; You can also use alerting rules to detect conditions that require investigation.&lt;/p&gt;

&lt;p&gt;When integrating Prometheus with OpenTelemetry, decide how Prometheus will receive metrics. A common approach is to scrape an endpoint exposed by an application or the OpenTelemetry Collector's Prometheus exporter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Documentation:&lt;/strong&gt; &lt;a href="https://prometheus.io/docs/" rel="noopener noreferrer"&gt;Prometheus documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community:&lt;/strong&gt; &lt;a href="https://prometheus.io/community/" rel="noopener noreferrer"&gt;Prometheus community channels&lt;/a&gt;, including the #prometheus channel on CNCF Slack.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Discussions:&lt;/strong&gt; &lt;a href="https://discuss.prometheus.io/" rel="noopener noreferrer"&gt;Prometheus user forum&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Jaeger&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Jaeger provides a platform for exploring distributed traces and understanding how requests move through services.&lt;/p&gt;

&lt;p&gt;Jaeger is useful when metrics tell you that a service is slow but don't explain which operation causes the delay. You can inspect individual traces to investigate service dependencies, slow operations, and errors.&lt;/p&gt;

&lt;p&gt;When integrating Jaeger with OpenTelemetry, configure a compatible trace ingestion path, such as an appropriate OTLP endpoint. Also plan for trace storage and retention based on your deployment requirements. Jaeger uses a configured storage backend, so you must account for that backend in your architecture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Documentation:&lt;/strong&gt; &lt;a href="https://www.jaegertracing.io/docs/" rel="noopener noreferrer"&gt;Jaeger documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community:&lt;/strong&gt; &lt;a href="https://www.jaegertracing.io/get-in-touch/" rel="noopener noreferrer"&gt;Jaeger community channels&lt;/a&gt;, including the #jaeger channel on CNCF Slack.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Discussions:&lt;/strong&gt; &lt;a href="https://github.com/jaegertracing/jaeger/discussions" rel="noopener noreferrer"&gt;Jaeger GitHub Discussions&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;OpenSearch&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;OpenSearch provides search and analytics capabilities for observability data, including application logs. Structured fields make it easier to filter records by service, environment, timestamp, or trace ID. For example, a log record might contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"service.name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"payment-service"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nl"&gt;"severity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ERROR"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Payment provider timed out"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nl"&gt;"trace_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"example-trace-id"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fields such as &lt;code&gt;service.name&lt;/code&gt; and &lt;code&gt;trace_id&lt;/code&gt; can help you narrow a search and connect a log entry to a related request. That connection depends on your instrumentation, log format, ingestion configuration, and the way you query the data.&lt;/p&gt;

&lt;p&gt;OpenSearch provides flexible search and analytics, but you need to configure ingestion, indexing, storage, and retention. For example, OpenSearch Data Prepper can process telemetry before sending it to OpenSearch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Documentation:&lt;/strong&gt; &lt;a href="https://docs.opensearch.org/latest/observing-your-data/" rel="noopener noreferrer"&gt;OpenSearch observability documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community:&lt;/strong&gt; &lt;a href="https://opensearch.org/connect/" rel="noopener noreferrer"&gt;Connect with the OpenSearch community&lt;/a&gt;, including its public Slack workspace.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Discussions:&lt;/strong&gt; &lt;a href="https://forum.opensearch.org/" rel="noopener noreferrer"&gt;OpenSearch community forum&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Perses&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Perses is an open-source dashboarding tool with an open dashboard specification and support for managing dashboards as code.&lt;/p&gt;

&lt;p&gt;Perses doesn't replace the systems that store telemetry. It queries configured data sources and displays their results. Its plugins determine which backends it can query. This separation lets teams manage dashboards independently of telemetry storage. However, dashboard definitions still depend on compatible data sources, queries, and configuration.&lt;/p&gt;

&lt;p&gt;For example, a team might configure Prometheus as a Perses data source to display request rates, error rates, and latency measurements. Other data sources depend on the available plugins and configuration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Documentation:&lt;/strong&gt; &lt;a href="https://perses.dev/docs/" rel="noopener noreferrer"&gt;Perses documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community:&lt;/strong&gt; &lt;a href="https://perses.dev/docs/perses/latest/contact/" rel="noopener noreferrer"&gt;Perses contact and community channels&lt;/a&gt;, including the #perses-dev channel on CNCF Slack.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Discussions:&lt;/strong&gt; &lt;a href="https://github.com/perses/perses/discussions" rel="noopener noreferrer"&gt;Perses GitHub Discussions&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;How do these tools fit together?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;An observability stack isn't one application. Installing these components doesn't automatically create a working observability stack. You must decide how data reaches each backend, which components process it, and how engineers access the results.&lt;/p&gt;

&lt;p&gt;The following diagram illustrates one possible architecture. It distinguishes the Prometheus scrape process from the trace and log ingestion paths.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm4puv364zve8sw7nyu11.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm4puv364zve8sw7nyu11.png" alt="A diagram displaying how Open-Source Observability Stack Fits Together" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This architecture has three important parts.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ingestion:&lt;/strong&gt; Choose how each backend receives data. The Collector supports multiple receivers and exporters, but not every backend uses the same ingestion method.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storage and analysis:&lt;/strong&gt; Decide which systems handle each data set. You might store metrics in Prometheus, configure a storage backend for Jaeger, and store logs in OpenSearch.

&lt;ul&gt;
&lt;li&gt;Routing data to multiple destinations is also possible when your requirements justify the additional processing and storage.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visualization:&lt;/strong&gt; Decide where engineers will explore the data. Jaeger and OpenSearch provide their own interfaces. Perses supports reusable dashboards, but you must configure compatible data sources.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OpenTelemetry provides a foundation for telemetry transport. It doesn't automatically configure every backend, unify their interfaces, or correlate all the data they contain. Correlation also depends on consistent attributes, trace context, and compatible ingestion and query capabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What happens when an incident occurs?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Consider a production service whose response latency suddenly increases. An engineer might follow this workflow:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe72wli0fadl0od0qtug9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe72wli0fadl0od0qtug9.png" alt="A diagram displaying what happens when an incident works with open telemetry" width="800" height="62"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Metrics help you detect and scope the problem. Traces help you locate the delay, and logs provide events that may explain it. After applying a fix, check the relevant telemetry to verify that the system has recovered.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Start with one use case&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You don't need to deploy every tool at once. Start with one observability question and build the smallest setup that can help you answer it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Define the question.&lt;/strong&gt; For example, determine whether a service's request latency is increasing.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Choose a backend.&lt;/strong&gt; Select a tool that supports the type of data you need to investigate.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Send test telemetry.&lt;/strong&gt; Configure the required ingestion path and generate a small amount of test data.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify the results.&lt;/strong&gt; Query the data and confirm that the expected measurements and attributes appear.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Document what you learned.&lt;/strong&gt; Record the configuration, useful queries, and any limitations you encountered.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For example, you could start with Prometheus and query request latency for one service. Once you need to investigate individual requests, add tracing. If you also need to search detailed application events, introduce a log backend.&lt;/p&gt;

&lt;p&gt;This approach helps you validate each component before expanding the stack. It also makes integration problems easier to identify while the system is still small.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What should you consider before choosing your stack?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A successful experiment doesn't guarantee that a stack is ready for production. Before deploying it across services and environments, evaluate the integration work and operational responsibilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Integration and query models&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Prometheus uses PromQL. OpenSearch supports its own query and analytics capabilities. Jaeger provides an interface for exploring traces, while Perses uses configured data sources and their respective query languages.&lt;/p&gt;

&lt;p&gt;Engineers may need to switch between tools to investigate the same incident. You also need to configure data sources, align resource attributes, and preserve trace context in logs when you want to connect related events.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Reliability, storage, and security&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Each deployed component introduces operational requirements. Plan for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Storage and retention:&lt;/strong&gt; Estimate how data volume will grow and define retention policies for each signal.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Availability:&lt;/strong&gt; Decide how ingestion and investigation should behave when a backend becomes unavailable.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scaling:&lt;/strong&gt; Determine how to handle increasing telemetry volume and query load.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security:&lt;/strong&gt; Control access to telemetry and protect sensitive information.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintenance:&lt;/strong&gt; Manage upgrades, configuration changes, backups, and recovery.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These concerns become more important as the number of services, environments, and engineering teams grows.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Licensing and long-term flexibility&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Open-source projects provide different levels of freedom depending on their licenses. Some products follow an open-core model, offering an open-source base while reserving some capabilities for commercial editions.&lt;/p&gt;

&lt;p&gt;Before adopting a tool, review its license, governance, community activity, commercial feature boundaries, and data export options. Consider how difficult it would be to replace the component if your requirements change.&lt;/p&gt;

&lt;p&gt;The goal isn't to choose open-source software at any cost. It's to make an informed decision about flexibility, operational effort, and long-term sustainability.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Self-managed stack or unified observability platform?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You can assemble an observability stack from individual open-source tools or use a platform that brings telemetry together in one place. The right choice depends on your team's requirements, desired control, and capacity to operate the infrastructure.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Consideration&lt;/th&gt;
&lt;th&gt;Self-managed stack&lt;/th&gt;
&lt;th&gt;Unified observability platform&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Control&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Choose and configure individual components.&lt;/td&gt;
&lt;td&gt;Use the capabilities and configuration options provided by the platform.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Integration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Your team connects and maintains the components.&lt;/td&gt;
&lt;td&gt;The platform provides an integrated experience for supported signals.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Operations&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Your team manages the infrastructure, storage, upgrades, and maintenance.&lt;/td&gt;
&lt;td&gt;The platform can reduce the work required to operate separate backends.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Flexibility&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Customize components to meet specific requirements.&lt;/td&gt;
&lt;td&gt;Evaluate supported integrations, export options, and platform limitations.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best fit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Teams that need direct control and have the capacity to maintain the stack.&lt;/td&gt;
&lt;td&gt;Teams that prioritize a unified investigation experience and reduced operational work.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Neither approach is inherently better. A self-managed stack gives you control over individual components, while a unified platform can reduce integration and maintenance work, which allows you to focus on your business logic.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffr54k8g6pwccqjwdqqcw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffr54k8g6pwccqjwdqqcw.png" alt="A diagram displaying Dash0 integration with Open-Source Observability Stack" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Dash0: Explore telemetry in one platform&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Dash0 is an OpenTelemetry-native observability platform that brings metrics, logs, traces, and resource information together for analysis and investigation.&lt;/p&gt;

&lt;p&gt;For example, when a service's latency increases, you can examine metrics to understand the impact, inspect traces to identify slow operations, and investigate related logs to find potential causes within the same platform.&lt;/p&gt;

&lt;p&gt;Dash0 supports PromQL and uses the &lt;a href="https://www.dash0.com/docs/dash0/dashboards/about-dashboards" rel="noopener noreferrer"&gt;Perses dashboard specification&lt;/a&gt;. These open standards help teams reuse familiar query capabilities and dashboard workflows. Dash0 isn't a connector that automatically combines an existing Prometheus, Jaeger, OpenSearch, and Perses deployment. It's an alternative approach that can reduce the need to operate these components separately, depending on your requirements.&lt;/p&gt;

&lt;p&gt;Choose a self-managed stack when you need control over individual components and can maintain the infrastructure. Consider Dash0 when you want a unified place to investigate telemetry with less operational overhead.&lt;/p&gt;

&lt;p&gt;Learn more in the &lt;a href="https://www.dash0.com/docs/dash0" rel="noopener noreferrer"&gt;Dash0 documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;An open-source observability stack is an architecture you design, not a set of tools that automatically work together.&lt;/p&gt;

&lt;p&gt;Prometheus, Jaeger, OpenSearch, and Perses address different needs. OpenTelemetry provides a foundation for instrumentation and telemetry transport, but you must configure the data paths, storage, integrations, and investigation workflows.&lt;/p&gt;

&lt;p&gt;You can assemble and maintain those components yourself, or evaluate a platform such as Dash0 to bring telemetry into a common observability experience. The best choice is the one that meets your requirements without introducing more operational complexity than your team can manage.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>observability</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Your telemetry doesn't go straight to the backend: Understanding the OpenTelemetry Collector</title>
      <dc:creator>hridyesh bisht</dc:creator>
      <pubDate>Sun, 01 Nov 2026 06:11:34 +0000</pubDate>
      <link>https://dev.to/aws-builders/your-telemetry-doesnt-go-straight-to-the-backend-understanding-the-opentelemetry-collector-1dgd</link>
      <guid>https://dev.to/aws-builders/your-telemetry-doesnt-go-straight-to-the-backend-understanding-the-opentelemetry-collector-1dgd</guid>
      <description>&lt;p&gt;Imagine you run a coffee shop with an online ordering system. A customer orders a cappuccino, completes the payment, and waits for a pickup notification. But the notification never arrives.&lt;/p&gt;

&lt;p&gt;Your application generates telemetry as it processes the order. Traces capture the request's journey, logs record events, and metrics show how the system behaves. But generating telemetry is only part of the problem. You also need to decide where it goes, what information it contains, and how to deliver it reliably so you can investigate issues.&lt;/p&gt;

&lt;p&gt;The OpenTelemetry Collector helps you manage these tasks outside your application code. It receives, processes, and exports telemetry, giving you a dedicated layer for controlling your telemetry pipeline.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://programmerprodigy.code.blog/2025/06/04/understanding-observability-with-opentelemetry-and-coffee/" rel="noopener noreferrer"&gt;Understanding Observability with OpenTelemetry and Coffee&lt;/a&gt;, I introduced OpenTelemetry's fundamentals through a coffee-shop example. In &lt;a href="https://programmerprodigy.code.blog/2026/02/08/native-opetelemetry/" rel="noopener noreferrer"&gt;Native OpenTelemetry&lt;/a&gt;, I explored why visibility into telemetry processing matters. I also discussed the risks of sharing telemetry with AI tools in &lt;a href="https://www.linkedin.com/pulse/before-you-paste-telemetry-data-ai-agent-hridyesh-bisht-hcnqe/" rel="noopener noreferrer"&gt;Before you paste telemetry data into an AI agent&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This article builds on those ideas to explain how the Collector manages telemetry, why you might need one, and what to consider when operating it in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Do you need a Collector?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In our coffee shop. When a customer places an order, the application checks ingredient availability, records the order, and contacts the payment service. OpenTelemetry instrumentation can generate telemetry for these operations.&lt;/p&gt;

&lt;p&gt;You can export that telemetry directly to an observability backend or route it through a Collector.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdvldlqpunsw69z9xic79.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdvldlqpunsw69z9xic79.png" alt="Coffee shop with OTel Collector example" width="800" height="154"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, imagine that your coffee shop expands to multiple locations. You now have several services running in different environments, and you want consistent metadata, filtering rules, and export configurations across all of them. Managing these responsibilities independently in every application can become difficult.&lt;/p&gt;

&lt;p&gt;A Collector is particularly useful when you need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Apply consistent processing rules across multiple services.
&lt;/li&gt;
&lt;li&gt;Enrich telemetry with additional context.
&lt;/li&gt;
&lt;li&gt;Filter data, batch exports, or control telemetry volume.
&lt;/li&gt;
&lt;li&gt;Route telemetry to multiple destinations.
&lt;/li&gt;
&lt;li&gt;Manage telemetry delivery independently of application code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;How does the Collector process telemetry?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The Collector organizes telemetry processing into pipelines. A typical pipeline uses three primary component types: receivers, processors, and exporters.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkan1n7p0c3vq0mwtitxq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkan1n7p0c3vq0mwtitxq.png" alt="How does OTel Collector collect telemetry for coffee shop example" width="800" height="132"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each component has a specific responsibility.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Receivers: Accept telemetry&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Receivers accept telemetry from applications and other sources.&lt;/p&gt;

&lt;p&gt;For example, the coffee shop's ordering system can use the OpenTelemetry SDK to export traces, metrics, and logs through the OpenTelemetry Protocol (OTLP). The Collector's OTLP receiver accepts this data and passes it to the appropriate pipeline.&lt;/p&gt;

&lt;p&gt;The Collector also supports other protocols and data sources, depending on the components available in your deployment.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Processors: Process telemetry&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Processors transform, enrich, filter, or otherwise process telemetry before export.&lt;/p&gt;

&lt;p&gt;Suppose the coffee shop has separate staging and production environments. You want to identify the environment that generated each measurement so engineers can distinguish test activity from production activity.&lt;/p&gt;

&lt;p&gt;A resource processor can add an environment attribute. A batch processor groups telemetry before export, while a memory limiter helps protect the Collector from excessive memory use.&lt;/p&gt;

&lt;p&gt;Other processors can filter telemetry or modify attributes. Processor order matters.&lt;/p&gt;

&lt;p&gt;Each processor receives the output of the preceding processor. To activate a processor, you must include it in the relevant pipeline. Adjust the order to suit your pipeline. For example, if a filter depends on an attribute added by a resource processor, make that attribute available before the filter runs.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Exporters: Send telemetry to a destination&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Exporters send processed telemetry to backends or other destinations.&lt;/p&gt;

&lt;p&gt;For example, you can export traces to Jaeger over OTLP, expose metrics through an endpoint that Prometheus scrapes, or use a supported Prometheus Remote Write exporter with a compatible destination. You can also send logs to a compatible logging backend, such as OpenSearch, when the required integration is available.&lt;/p&gt;

&lt;p&gt;Alternatively, you can send telemetry to an integrated observability platform such as Dash0.&lt;/p&gt;

&lt;p&gt;The exact configuration depends on the Collector distribution and destination. This approach lets you manage downstream export configuration separately from your application's instrumentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Where should you deploy the Collector?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;You can deploy the Collector near your applications, run it as a shared gateway, or combine both approaches.&lt;/p&gt;

&lt;p&gt;Two common deployment patterns are the agent and gateway patterns.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Agent pattern&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In the agent pattern, a Collector runs close to the application or host that generates telemetry. On Kubernetes, you can deploy it as a DaemonSet or sidecar, depending on your requirements.&lt;/p&gt;

&lt;p&gt;For the coffee shop, an agent could collect telemetry from the ordering service or its underlying infrastructure. This provides a local collection point for application and infrastructure telemetry.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Gateway pattern&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In the gateway pattern, applications or local Collectors send telemetry to a shared Collector endpoint. The gateway processes the telemetry and exports it to the backend.&lt;/p&gt;

&lt;p&gt;Imagine that the coffee shop operates several branches, each with its own services and infrastructure. A shared gateway provides a central place to manage processing rules, credentials, and export traffic.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fncf1zz28dilxcb6910u7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fncf1zz28dilxcb6910u7.png" alt="Gateway pattern for coffee shop OTel Collector" width="767" height="853"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can combine the two patterns. Agents collect telemetry near workloads, while gateway Collectors handle shared processing and export policies. Neither pattern is always better. The decision depends on your deployment architecture, scale, security boundaries, processing requirements, and operational capacity.&lt;/p&gt;

&lt;p&gt;A gateway centralizes control but also concentrates traffic. You need to provide sufficient capacity and configure appropriate availability controls.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What happens to telemetry inside the pipeline?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The Collector can enrich and filter telemetry before exporting it. However, these decisions can affect the information available during an investigation.&lt;/p&gt;

&lt;p&gt;The following YAML examples are configuration fragments, not complete Collector configurations. Define each processor and include it in the relevant pipeline under service.pipelines to apply it. Validate the configuration against the Collector distribution and version you use.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Add context to telemetry&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Suppose the coffee shop has separate staging and production environments. You want to identify the environment associated with each service's telemetry.&lt;/p&gt;

&lt;p&gt;This approach helps standardize metadata at the collection layer. However, application-specific details, such as why the system applied a particular discount, might still require instrumentation in the application.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Filter sensitive information&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Suppose the ordering system includes a customer's email address in a span attribute. The coffee shop doesn't want to send this information to its observability backend.&lt;/p&gt;

&lt;p&gt;This removes the specified attribute from the telemetry the processor handles. It doesn't automatically remove the same information if it appears in a log body, an event, or another attribute.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://www.linkedin.com/pulse/before-you-paste-telemetry-data-ai-agent-hridyesh-bisht-hcnqe/" rel="noopener noreferrer"&gt;Before you paste telemetry data into an AI agent&lt;/a&gt;, I explored the risks of exposing sensitive information and untrusted content when using AI tools to investigate production issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Manage telemetry volume&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A busy coffee shop might process hundreds of orders during peak hours. Its ordering system can generate substantial telemetry, especially when requests pass through multiple services.&lt;/p&gt;

&lt;p&gt;Batching, filtering, and sampling can help manage the volume of data sent to downstream systems, but they serve different purposes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Batching&lt;/strong&gt; groups telemetry before export.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Filtering&lt;/strong&gt; removes selected telemetry records or attributes.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trace sampling&lt;/strong&gt; determines which traces or spans to retain, depending on the sampling strategy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sampling can occur in the SDK or Collector, depending on your configuration and requirements.&lt;/p&gt;

&lt;p&gt;Reducing telemetry volume involves trade-offs. Filtering might remove useful attributes, while sampling might exclude a trace that an engineer needs to investigate. The goal is to retain useful diagnostic information while managing resource usage and cost.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://programmerprodigy.code.blog/2026/02/08/native-opetelemetry/" rel="noopener noreferrer"&gt;Native OpenTelemetry&lt;/a&gt; we focus on understanding how telemetry is transformed or discarded helps engineers make informed decisions about data quality.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What happens when the backend becomes unavailable?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Suppose a customer places an order, but the observability backend becomes unavailable. The ordering service continues generating telemetry, and the Collector continues receiving it. Depending on its configuration, the Collector can queue outgoing telemetry and retry failed exports. This can help the pipeline recover when the destination becomes available again.&lt;/p&gt;

&lt;p&gt;However, retries don't guarantee delivery. If the backend remains unavailable and the queue reaches capacity, the Collector can drop telemetry. In-memory queues can also lose pending data if the Collector restarts.&lt;/p&gt;

&lt;p&gt;When supported and configured, persistent storage can preserve queued telemetry across restarts. However, it doesn't prevent every type of data loss.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvm79j7ym62ef42x9jcpz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvm79j7ym62ef42x9jcpz.png" alt="What happens when the backend becomes unavailable in Coffee shop OTel example" width="800" height="844"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before deploying a Collector in production, consider how much telemetry you need to buffer, how long to retry failed exports, and whether persistent storage is necessary. Monitor queue capacity and export failures so you can detect problems before they affect telemetry delivery.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Monitor the Collector itself&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Imagine that the coffee shop's ordering service continues sending telemetry, but the Collector can't export it because the backend is unavailable. How would you know that the pipeline is falling behind?&lt;/p&gt;

&lt;p&gt;The Collector exposes internal telemetry, including metrics for accepted and refused data, exporter failures, queue sizes, and resource usage. For example, a growing exporter queue might indicate that the backend can't process incoming data quickly enough. An increase in export failures might indicate connectivity or configuration problems.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxmtxdhwgfmepvy9au4ra.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxmtxdhwgfmepvy9au4ra.png" alt="Monitor the Collector itself in coffee shop OTel Collector example" width="800" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Monitor these metrics to identify issues with the Collector and investigate problems in the telemetry pipeline. Monitor both the applications that generate telemetry and the infrastructure that collects and exports it.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Where does Dash0 fit?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Dash0 is an observability platform that accepts OpenTelemetry data. You can configure the Collector to process telemetry before exporting it to Dash0. This keeps your application's instrumentation separate from your backend configuration.&lt;/p&gt;

&lt;p&gt;In our coffee shop example, the ordering system continues to generate telemetry through OpenTelemetry, while the Collector manages how that data is processed and delivered.&lt;/p&gt;

&lt;p&gt;Alternatively, you can build a self-managed, open-source observability stack using tools such as Prometheus, Jaeger, and OpenSearch. This approach offers flexibility and control, but your team must maintain the individual components and their integrations.&lt;/p&gt;

&lt;p&gt;An integrated observability platform can reduce the effort required to bring telemetry together and investigate issues. Choose the approach that best fits your organization's requirements, resources, and operational needs.&lt;/p&gt;

&lt;p&gt;For setup instructions, refer to the &lt;a href="https://www.dash0.com/docs/integrations/int_opentelemetry-collector/overview" rel="noopener noreferrer"&gt;Dash0 OpenTelemetry Collector integration guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion: Treat telemetry as a pipeline, not an afterthought&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;OpenTelemetry standardizes how applications generate and export telemetry. The Collector provides a separate layer for managing how that telemetry is processed and delivered.&lt;/p&gt;

&lt;p&gt;You can use the Collector to enrich data, batch exports, filter records, manage data volume, and route telemetry to one or more destinations. These capabilities become increasingly valuable as your architecture grows and observability becomes a shared responsibility across engineering teams.&lt;/p&gt;

&lt;p&gt;However, introducing a Collector also means operating another component. You must configure its pipelines, secure its endpoints, allocate sufficient resources, handle failures, and monitor its health.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyosdqs8w60fymbzq4byb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyosdqs8w60fymbzq4byb.png" alt="Treat telemetry as a pipeline example" width="800" height="128"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You don't always need a Collector. Introduce one when you need greater control over your telemetry pipeline. The goal is to make telemetry collection and delivery consistent, manageable, and adaptable as your systems grow.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Further reading&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://opentelemetry.io/docs/collector/architecture/" rel="noopener noreferrer"&gt;OpenTelemetry Collector architecture&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://opentelemetry.io/docs/collector/components/" rel="noopener noreferrer"&gt;OpenTelemetry Collector components&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://opentelemetry.io/docs/collector/configuration/" rel="noopener noreferrer"&gt;OpenTelemetry Collector configuration&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://opentelemetry.io/docs/collector/deploy/" rel="noopener noreferrer"&gt;OpenTelemetry Collector deployment patterns&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>opentelemetry</category>
      <category>kubernetes</category>
      <category>cloudnative</category>
    </item>
    <item>
      <title>Serverless Computing in Kubernetes: A Developer’s Guide</title>
      <dc:creator>hridyesh bisht</dc:creator>
      <pubDate>Sun, 10 Aug 2025 10:40:46 +0000</pubDate>
      <link>https://dev.to/aws-builders/serverless-computing-in-kubernetes-a-developers-guide-2c2n</link>
      <guid>https://dev.to/aws-builders/serverless-computing-in-kubernetes-a-developers-guide-2c2n</guid>
      <description>&lt;p&gt;Serverless computing allows you to focus on writing business logic without managing infrastructure. While often confused with Functions as a Service (FaaS), serverless is broader. It includes event-driven execution, auto-scaling, stateless workloads, and billing based on usage rather than uptime.&lt;/p&gt;

&lt;p&gt;This guide explores serverless from a developer's point of view using a coffee shop application deployed on Kubernetes. You also learn about cover setup, advanced use cases, observability, deployment strategies, and production readiness.&lt;/p&gt;

&lt;p&gt;For this blog, consider a coffee shop app with the following services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;order-service&lt;/code&gt; (handles orders)
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;payment-service&lt;/code&gt; (processes payments)
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;inventory-service&lt;/code&gt; (manages beans and stock)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Combine Serverless and Kubernetes?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Kubernetes is designed to run containers continuously. This works well for workloads that must always be available. However, many workloads are event-driven and only need to run when triggered.&lt;/p&gt;

&lt;p&gt;OpenFaaS extends Kubernetes to run workloads only when needed, scaling them down to zero when idle. This approach saves costs, improves resource efficiency, and accelerates development.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftqi745noqv3lvepmaqar.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftqi745noqv3lvepmaqar.png" alt="An image flow displaying OpenFaas integration with Kubernetes." width="742" height="561"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;OpenFaaS does not replace Kubernetes, it enhances it with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scale to zero&lt;/strong&gt;: No pods running = zero resource cost during inactivity.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Function templates&lt;/strong&gt;: Developers write the logic; OpenFaaS handles packaging, networking, scaling, and observability.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standard Kubernetes integration&lt;/strong&gt;: Works with any Kubernetes distribution; no special infrastructure required.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Event-driven triggers&lt;/strong&gt;: Supports HTTP, Kafka, MQTT, cron, and more.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in monitoring&lt;/strong&gt;: Integrates with Prometheus and Grafana out of the box.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, in the coffee shop app, the &lt;strong&gt;payment-service&lt;/strong&gt; is only used during checkout. Running it all day wastes resources. With OpenFaaS:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;payment-service&lt;/code&gt; function spins up only when a customer checks out.
&lt;/li&gt;
&lt;li&gt;During busy hours (e.g., morning rush), it automatically scales to handle high demand.
&lt;/li&gt;
&lt;li&gt;After hours, it scales down to zero, using no resources.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Serverless in Kubernetes&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Kubernetes is not inherently serverless, but open-source projects like OpenFaaS bring serverless capabilities to it. These platforms provide abstraction layers over Kubernetes primitives like Pods, Services, and Deployments.&lt;/p&gt;

&lt;p&gt;To run a serverless function on Kubernetes, the following components are typically required:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A container image containing your function or application
&lt;/li&gt;
&lt;li&gt;A container registry to store the image
&lt;/li&gt;
&lt;li&gt;A Pod to run the container
&lt;/li&gt;
&lt;li&gt;A Service or Ingress to expose it
&lt;/li&gt;
&lt;li&gt;An autoscaler (e.g., HPA, KEDA) to handle scale
&lt;/li&gt;
&lt;li&gt;ConfigMaps and Secrets to store configuration and credentials&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmp595wfuvh0txfd1zj3i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmp595wfuvh0txfd1zj3i.png" alt="Flow of development in Kubernetes." width="800" height="689"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: OpenFaas supports Serverless 2.0 out of the box.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;OpenFaaS&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;OpenFaaS enables developers to run functions and microservices on Kubernetes using Rancher or containerd. It supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build templates for languages like Python, Go, Node.js
&lt;/li&gt;
&lt;li&gt;Scale to zero using Prometheus or Kubernetes HPA v2
&lt;/li&gt;
&lt;li&gt;Event triggers: HTTP, cron, Kafka, SQS, MQTT
&lt;/li&gt;
&lt;li&gt;CLI and web UI for deployment and monitoring
&lt;/li&gt;
&lt;li&gt;Secrets management
&lt;/li&gt;
&lt;li&gt;OpenFaaS Cloud for CI/CD and team-based management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: OpenFaaS also offers faasd, a minimal single-node alternative to Kubernetes using containerd and CNI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftf6qlz70sajygzc00y6v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftf6qlz70sajygzc00y6v.png" alt="A service using OpenFaas in coffee shop container app." width="800" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the coffee-shop app, in a real coffee shop:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An order is placed by the user
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;order-service&lt;/code&gt; validates and sends the request to &lt;code&gt;inventory-service&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;inventory-service&lt;/code&gt; checks stock and updates it
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;payment-service&lt;/code&gt; processes the transaction&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;You could write a function to check inventory:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="n"&gt;order&lt;/span&gt; \&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;\&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;quantity&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;\&lt;span class="p"&gt;]&lt;/span&gt; \&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;inventory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;\&lt;span class="nf"&gt;_stock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;\&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;item&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;\&lt;span class="p"&gt;]):&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Out of stock&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="n"&gt;inventory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decrement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;\&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;item&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;\&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;\&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;quantity&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;\&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Order accepted&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And trigger it through HTTP or MQTT when new orders arrive.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Architecture of OpenFaaS&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;OpenFaaS is composed of the following layers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gateway&lt;/strong&gt;: Handles all incoming requests
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Watchdog&lt;/strong&gt;: Converts HTTP to stdin/stdout and back
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Function containers&lt;/strong&gt;: Stateless business logic
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Autoscaler&lt;/strong&gt;: Monitors metrics and adjusts replicas
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connector SDK&lt;/strong&gt;: Connects external events (e.g., MQTT, Kafka)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prometheus&lt;/strong&gt;: Collects metrics for observability
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;faas-cli&lt;/strong&gt;: CLI tool for development and CI/CD&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnggc3461jweof9h7hvdn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnggc3461jweof9h7hvdn.png" alt="An architecture image integrating Rancher, OpenFaas and Kubernetes." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The function deployment flow with OpenFaas is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Write your function using a template (e.g., Python, Go, &lt;a href="http://node.js" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt;).

&lt;ol&gt;
&lt;li&gt;Write handler logic for your function.
&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;Package it as a container image.
&lt;/li&gt;

&lt;li&gt;Deploy to Kubernetes using faas-cli.
&lt;/li&gt;

&lt;li&gt;Invoke it through HTTP, MQTT, cron, or a message queue.
&lt;/li&gt;

&lt;li&gt;Prometheus gathers metrics; logs go to stdout.
&lt;/li&gt;

&lt;li&gt;Scale automatically based on usage or metrics.&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr88nzply44urh92yjxx4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr88nzply44urh92yjxx4.png" alt="Function deployment flow with OpenFaas." width="800" height="198"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Interacting with OpenFaaS&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;You can manage OpenFaaS functions in three ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;faas-cli (recommended for scripting and CI)
&lt;/li&gt;
&lt;li&gt;Web UI (good for demos or quick insights)
&lt;/li&gt;
&lt;li&gt;REST API (custom app integration)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F40nsctfxoazfgidf56js.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F40nsctfxoazfgidf56js.png" alt="Interacting with OpenFaas" width="781" height="496"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;OpenFaaS supports various trigger mechanisms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTTP (default)
&lt;/li&gt;
&lt;li&gt;MQTT (great for IoT devices)
&lt;/li&gt;
&lt;li&gt;Apache Kafka
&lt;/li&gt;
&lt;li&gt;cron (time-based)
&lt;/li&gt;
&lt;li&gt;AWS SQS
&lt;/li&gt;
&lt;li&gt;MinIO
&lt;/li&gt;
&lt;li&gt;RabbitMQ&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most of these use the connector-sdk, allowing custom event bridges.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Accessing the OpenFaaS Gateway&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;After installing OpenFaaS (using Helm or arkade), you can access the Gateway. An HTTP API and UI that manages all deployed functions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Forward the OpenFaaS Gateway to your local machine&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl rollout status &lt;span class="se"&gt;\-&lt;/span&gt;n openfaas deploy/gateway

kubectl port-forward &lt;span class="se"&gt;\-&lt;/span&gt;n openfaas svc/gateway 8080:8080 &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This exposes the Gateway at &lt;a href="http://127.0.0.1:8080" rel="noopener noreferrer"&gt;http://127.0.0.1:8080&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5jmthdkdtjnfcan0br88.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5jmthdkdtjnfcan0br88.png" alt="A screenshot of OpenFaas dashboard" width="800" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: If the port becomes unavailable later, rerun the port-forward command.&lt;/p&gt;

&lt;p&gt;Some of the key features are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deploy New Function&lt;/strong&gt;: From the store or using custom Rancher images
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Invoke Functions&lt;/strong&gt;: Test your functions manually with input data
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitor Logs and Metrics&lt;/strong&gt;: Includes basic Prometheus metrics and live logs
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manage Deployments&lt;/strong&gt;: Delete or update existing functions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;OpenFaaS CLI&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The faas-cli is the primary developer interface for building, deploying, and managing OpenFaaS functions. It communicates directly with the Gateway.&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;faas-cli --help&lt;/code&gt; to learn about available options for each command. You can also find help for some of the commands in the &lt;a href="https://docs.openfaas.com/" rel="noopener noreferrer"&gt;OpenFaaS documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fww6i5vnl3v2kkkigfose.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fww6i5vnl3v2kkkigfose.png" alt="A flow of data from Faas CLI to Container registery" width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, each store tracks daily espresso counts. An OpenFaaS function reads an MQTT message, then pushes usage stats to a central dashboard.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="n"&gt;count&lt;/span&gt; \&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;count&lt;/span&gt; \&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Daily threshold reached\!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Usage normal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Function and Template Stores&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;OpenFaaS simplifies function development with two built-in stores:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Function Store&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The Function Store is a curated catalog of ready-to-deploy serverless functions. These functions follow reusable patterns such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Image conversion
&lt;/li&gt;
&lt;li&gt;Sentiment analysis
&lt;/li&gt;
&lt;li&gt;Slack notifications
&lt;/li&gt;
&lt;li&gt;PDF generation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, in a coffee ordering app. You can search for functions that relate to coffee logic, like coffee-order, inspect their behavior, and deploy instantly. A deployed function could receive order data (e.g., drink type, size, customer name) and respond with a formatted confirmation receipt.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdb323vr3c1c267dhhgn3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdb323vr3c1c267dhhgn3.png" alt="An image displaying flow of data from customer to coffee order function." width="800" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Template Store&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The Template Store provides scaffolding to build your own functions using supported languages and frameworks (e.g., Python, Flask, Node.js, Go).&lt;/p&gt;

&lt;p&gt;Templates handle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTTP input and response setup
&lt;/li&gt;
&lt;li&gt;Boilerplate build and deploy logic
&lt;/li&gt;
&lt;li&gt;Language-specific structure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, you could scaffold a &lt;code&gt;payment-service&lt;/code&gt; function using a Python template and extend it to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Parse JSON order data
&lt;/li&gt;
&lt;li&gt;Validate payment information
&lt;/li&gt;
&lt;li&gt;Return a payment confirmation status&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Templates are extensible, you can add packages like jinja2 for HTML rendering or numpy for calculations by modifying the template's dependency file.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Observability: Prometheus + Grafana&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;OpenFaaS integrates with Prometheus by default to enable real-time observability.&lt;/p&gt;

&lt;p&gt;For example, you can track:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Number of coffee orders processed
&lt;/li&gt;
&lt;li&gt;Payment success vs. failure rate
&lt;/li&gt;
&lt;li&gt;Low-stock alerts for ingredients&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To access Prometheus (hidden by default for security), use port-forwarding:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="se"&gt;\-&lt;/span&gt;n openfaas port-forward deployment/prometheus 9090:9090 &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each function automatically exposes a /metrics endpoint. Prometheus scrapes this and Grafana can visualize metrics on dashboards.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc2xfta4zh9mh6h4anaq4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc2xfta4zh9mh6h4anaq4.png" alt="Integrating order-service with Grafana dashboard." width="800" height="48"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Create Your First Function&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;OpenFaaS offers templates that scaffold functions, handling HTTP entry, code wiring, and build scripts automatically.&lt;/p&gt;

&lt;p&gt;You can source templates from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OpenFaaS official repo
&lt;/li&gt;
&lt;li&gt;OpenFaaS incubator or community stores
&lt;/li&gt;
&lt;li&gt;Custom template repos&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To build a function from scratch, you’ll:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Choose a template (e.g., python3-flask-debian)
&lt;/li&gt;
&lt;li&gt;Generate your function using the CLI
&lt;/li&gt;
&lt;li&gt;Edit logic and dependencies
&lt;/li&gt;
&lt;li&gt;Build, push, and deploy to OpenFaaS&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fup2ib86pqxbwt5rpnk5g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fup2ib86pqxbwt5rpnk5g.png" alt="Creating a function template using Faas CLI ." width="800" height="274"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Templates are pulled from the Template Store. You can use community-curated templates or your own custom versions. Each function includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;lang: the template type
&lt;/li&gt;
&lt;li&gt;handler: the path to your business logic
&lt;/li&gt;
&lt;li&gt;image: the container image to publish&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once set up, the CLI can build, push, and deploy your function in a single command. This creates a Kubernetes deployment behind the scenes, ready to accept HTTP requests.&lt;/p&gt;

&lt;p&gt;You can run each step individually or use faas-cli up:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;faas-cli up -f order-service.yml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This does the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;builds the container locally via Rancher.
&lt;/li&gt;
&lt;li&gt;pushes the image to your registry.
&lt;/li&gt;
&lt;li&gt;deploys via OpenFaaS API → Kubernetes → Pod.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Templating with Jinja2&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;For functions that return HTML, Jinja2 can render dynamic content using variables. In the coffee app, a receipt template could include placeholders for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Customer name
&lt;/li&gt;
&lt;li&gt;Coffee type
&lt;/li&gt;
&lt;li&gt;Timestamp&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This improves user-facing responses without hardcoding the output.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; To include large or compiled packages (e.g., NumPy or Flask), use a Debian-based template like python3-debian. These templates support native compilation and pip installs that Alpine-based templates might not.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Controlling HTTP Responses in OpenFaaS&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;When you need precise control over status codes, headers, and response types (like JSON or binary), OpenFaaS offers flexible templates, especially python3-flask and python3-http. These allow you to build rich APIs with familiar HTTP semantics.&lt;/p&gt;

&lt;p&gt;For example, consider the &lt;code&gt;payment-service&lt;/code&gt; in a coffee shop. It needs to return:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A 201 Created status for successful payments
&lt;/li&gt;
&lt;li&gt;A 400 Bad Request for invalid inputs
&lt;/li&gt;
&lt;li&gt;Custom headers with order IDs and trace IDs
&lt;/li&gt;
&lt;li&gt;Structured JSON for frontend integration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These templates allow you to define all of the above without additional tools.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2vuqbwi7azcwoefhzzmm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2vuqbwi7azcwoefhzzmm.png" alt="Controlling HTTP responses in OpenFaas." width="800" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Serving Static Sites and Microservices&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;With HTTP-based templates, you can also serve static content or build lightweight services.&lt;/p&gt;

&lt;p&gt;For example, a function in Coffee Shop menu could serve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;menu.html&lt;/strong&gt; for your store’s website.
&lt;/li&gt;
&lt;li&gt;Promotional flyers as PDFs.
&lt;/li&gt;
&lt;li&gt;Static assets such as HTML, CSS, or JSON.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Functions with Secrets&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To protect sensitive operations like payment validation or admin APIs, OpenFaaS supports secret management.&lt;/p&gt;

&lt;p&gt;You can integrate common HTTP API authentication methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;API Token in Header&lt;/strong&gt;: A shared API key is sent in the request header.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HMAC (Hash-based Message Authentication Code)&lt;/strong&gt;: Used by providers like GitHub, PayPal, and Stripe to sign payloads with a shared key.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OAuth2&lt;/strong&gt;: Delegates authentication to a third-party identity provider.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, your &lt;code&gt;payment-service&lt;/code&gt; might require an API key passed as a header. The function reads the key from a mounted secret and compares it with the request input. This ensures only trusted clients can access sensitive endpoints such as payment processing or refunds.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo561sfyacp49kzet4n18.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo561sfyacp49kzet4n18.png" alt="Calling Secrets with OpenFaas Function." width="800" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Asynchronous Invocations&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;High-traffic periods, such as the morning coffee rush, can cause latency spikes. OpenFaaS supports asynchronous function calls to mitigate this.&lt;/p&gt;

&lt;p&gt;For example, when rendering large receipt PDFs or syncing inventory with external systems, your function can be invoked asynchronously. &lt;/p&gt;

&lt;p&gt;Async calls return an immediate acknowledgment while processing jobs in the background. You can optionally send results to a callback endpoint.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Autoscaling Functions&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;OpenFaaS supports both horizontal scaling and scale-to-zero based on real-time demand.&lt;/p&gt;

&lt;p&gt;The minimum (initial) and maximum replica count can be set at deployment time by adding a label to the function.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;com.openfaas.scale.min&lt;/strong&gt;: by default, this is set to 1, which is also the lowest value and unrelated to scale-to-zero.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;com.openfaas.scale.max&lt;/strong&gt;: the current default value is 20 for 20 replicas.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;com.openfaas.scale.factor&lt;/strong&gt;: by default, this is set to 20% and has to be a value between 0-100 (including borders).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, if you want a function to have at least 5 replicas at all times, but to scale up to 15 when under load, set it as follows in your &lt;strong&gt;stack.yml&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;com.openfaas.scale.min&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;

  &lt;span class="na"&gt;com.openfaas.scale.max&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;15&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Horizontal Scaling&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You can configure functions with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Minimum replicas (for readiness)
&lt;/li&gt;
&lt;li&gt;Maximum replicas (to conserve resources)
&lt;/li&gt;
&lt;li&gt;Scale factor to control how fast functions scale out&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, during peak morning hours, the coffee shop scales &lt;code&gt;order-service&lt;/code&gt; from 2 to 10 replicas to meet demand. In off-peak hours, the function scales back down.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Scale-to-Zero and Cold Starts&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You can enable cold starts by setting minimum replicas to zero. This reduces idle costs for functions like inventory-audit that run infrequently.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp3xomjep1lrt27bo9r16.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp3xomjep1lrt27bo9r16.png" alt="An image displaying scale to zero and cold starts with OpenFaas in Kubernetes." width="800" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kubernetes is also called “eventually consistent” and requires some tuning to get the cold-start.  Cold starts in Kubernetes can take 1–2 seconds without tuning. Keep 1–5 replicas to avoid delays or use asynchronous calls to hide scaling latency.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;TLS and Production Readiness&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;TLS is optional for local testing because &lt;code&gt;kubectl port-forward&lt;/code&gt; already provides an encrypted tunnel. For production:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install Ingress with TLS.
&lt;/li&gt;
&lt;li&gt;Use cert-manager for certificate management.
&lt;/li&gt;
&lt;li&gt;Route traffic over HTTPS.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once set up, you can log in with the CLI using a secure gateway.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Advanced Use Cases&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Custom HTTP Responses&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Using templates like python3-http or python3-flask, you can control:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTTP status codes (e.g., 201 Created, 500 Internal Server Error)
&lt;/li&gt;
&lt;li&gt;Custom headers (e.g., Content-Type)
&lt;/li&gt;
&lt;li&gt;JSON-formatted responses for frontend apps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, your function could return {"error": "Insufficient balance"} with a 402 Payment Required code.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Binary Data Handling&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To support raw byte input/output (e.g., uploading a receipt image), enable RAW_BODY: True in the function’s environment.&lt;/p&gt;

&lt;p&gt;For example, in a coffee shop's self-ordering kiosk, a function could:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Receive a JPEG from a camera
&lt;/li&gt;
&lt;li&gt;Convert it to grayscale
&lt;/li&gt;
&lt;li&gt;Return the processed image as a binary payload&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0w8o4lmebr9yv1h0fjrb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0w8o4lmebr9yv1h0fjrb.png" alt="Converting binary data using OpenFaas" width="800" height="43"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Serving Static Pages&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You can serve a micro-site using the python3-http template.&lt;/p&gt;

&lt;p&gt;For example, a function named homepage could return static HTML pages like &lt;code&gt;/about.html&lt;/code&gt; or &lt;code&gt;/menu.html&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwqos9c4cft6ik6t4x3qo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwqos9c4cft6ik6t4x3qo.png" alt="Serving static pages with OpenFaas." width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Combining OpenFaaS and MQTT for Edge Use Cases&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;MQTT (Message Queuing Telemetry Transport) is a lightweight, pub-sub messaging protocol designed for unreliable or constrained networks. It’s ideal for edge use cases like IoT and retail.&lt;/p&gt;

&lt;p&gt;Some benefits of integrating OpenFaas and MQTT are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Low bandwidth and power usage
&lt;/li&gt;
&lt;li&gt;Decouples producers and consumers
&lt;/li&gt;
&lt;li&gt;Buffers messages locally when offline
&lt;/li&gt;
&lt;li&gt;Reliable delivery once reconnected&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8j7xu8qnm5k0wfk6bdyx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8j7xu8qnm5k0wfk6bdyx.png" alt="Integrating OpenFaas and MQTT for edge use case." width="800" height="154"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In edge computing scenarios, OpenFaaS and MQTT work together:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MQTT brokers handle sensor data (e.g., temperature, order count).
&lt;/li&gt;
&lt;li&gt;OpenFaaS functions are triggered by these MQTT events.
&lt;/li&gt;
&lt;li&gt;Responses are logged, alerts are triggered, or orders are adjusted.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: For more information, refer to &lt;a href="https://programmerprodigy.code.blog/2025/07/09/microservices-at-edge-with-k3s-and-fleet/" rel="noopener noreferrer"&gt;https://programmerprodigy.code.blog/2025/07/09/microservices-at-edge-with-k3s-and-fleet/&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Balancing Containers and OpenFaaS
&lt;/h2&gt;

&lt;p&gt;Choosing between a traditional cloud native app and a serverless approach with OpenFaaS is not not an "either-or" choice. The most effective cloud-native solutions often combine both to balance their strengths.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpqxjsjt6lfrsanulw5nv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpqxjsjt6lfrsanulw5nv.png" alt="How to choose balance between Containers and OpenFaaS" width="800" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In a coffee shop app, Kubernetes container workloads are ideal for services that must always be available.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The core order-service runs continuously to ensure customers can place orders anytime.&lt;/li&gt;
&lt;li&gt;For event-driven or infrequently used workloads, such as payment-service and inventory-service, OpenFaaS offers a more efficient, cost-effective option. It can scale these services to zero when idle, reducing unnecessary resource use.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A hybrid approach delivers the best of both worlds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Optimize costs by running resource-intensive services only when needed.&lt;/li&gt;
&lt;li&gt;Improve resource efficiency by reducing idle workloads.&lt;/li&gt;
&lt;li&gt;Accelerate development by breaking down logic into small, manageable functions.&lt;/li&gt;
&lt;li&gt;Scale intelligently to handle unpredictable traffic spikes without over-provisioning.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key is to use the right tool for each job. Kubernetes provides persistence and control for always-on workloads, while OpenFaaS adds event-driven, scalable, and cost-efficient capabilities. Together, they enable a resilient, adaptable, and optimized cloud-native architecture.&lt;/p&gt;

</description>
      <category>serverless</category>
      <category>kubernetes</category>
      <category>observability</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Microservices at Edge with K3s and Fleet</title>
      <dc:creator>hridyesh bisht</dc:creator>
      <pubDate>Thu, 10 Jul 2025 14:29:07 +0000</pubDate>
      <link>https://dev.to/hridyeshbisht/microservices-at-edge-with-k3s-and-fleet-5cjd</link>
      <guid>https://dev.to/hridyeshbisht/microservices-at-edge-with-k3s-and-fleet-5cjd</guid>
      <description>&lt;p&gt;Imagine you're building a coffee shop application with three core microservices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;order-service&lt;/strong&gt;: Handles customer orders.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;payment-service&lt;/strong&gt;: Processes transactions.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;inventory-service&lt;/strong&gt;: Tracks beans, milk, cups, and other inventory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now scale this across hundreds or thousands of physical store locations—each with its own on-site device like a Raspberry Pi or Intel NUC. How do you maintain consistency, ensure reliability, and keep deployments secure across all sites?&lt;/p&gt;

&lt;p&gt;That’s where K3s (a lightweight Kubernetes distribution for edge) and Rancher Fleet(GitOps engine) are designed to manage thousands of clusters to help you.&lt;/p&gt;

&lt;p&gt;In this guide, you learn how to build a resilient, scalable edge infrastructure using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;K3s to run Kubernetes clusters on resource-constrained devices,
&lt;/li&gt;
&lt;li&gt;Fleet to manage deployments across hundreds or thousands of clusters,
&lt;/li&gt;
&lt;li&gt;OpenFaaS and MQTT for lightweight event-driven automation and telemetry,
&lt;/li&gt;
&lt;li&gt;And strategies for handling air-gapped stores, remote access, logging, and storage.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What Is a Container Image?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Before diving into Kubernetes or K3s, it’s essential to understand container image&lt;/p&gt;

&lt;p&gt;A container image is a lightweight, portable unit that includes everything needed to run a service that includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application code&lt;/li&gt;
&lt;li&gt;Runtime (like Python, Java, or Node.js)&lt;/li&gt;
&lt;li&gt;System libraries and binaries&lt;/li&gt;
&lt;li&gt;Configuration and dependencies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, in the coffee shop app each service: order-service, payment-service, and inventory-service is built as a container image:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;order-service: Python + Flask + order logic&lt;/li&gt;
&lt;li&gt;payment-service: Node.js + Stripe SDK&lt;/li&gt;
&lt;li&gt;inventory-service: Go + SQLite + inventory tracker&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flzdqpoett0yuwjyvzonc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flzdqpoett0yuwjyvzonc.png" alt="A visual example of coffee shop app container with CI pipeline." width="800" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kubernetes (K8s) is an open-source system that automates the deployment, scaling, and management of containerized applications. It provides a robust, extensible platform for orchestrating containers across clusters of machines, simplifying the management of distributed, cloud-native systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; For more information, refer to &lt;a href="https://programmerprodigy.code.blog/2025/05/06/introduction-to-container-images-and-orchestration/" rel="noopener noreferrer"&gt;Introduction to Container Images and Orchestration&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Understanding Edge Computing&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Edge computing&lt;/strong&gt; refers to placing compute resources as close as possible to the data source or end-user. In our case, this means deploying services directly into each coffee shop rather than relying on centralized cloud data centers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefits of Edge Computing:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Real-time inventory decisions:&lt;/strong&gt; Milk running low, auto order more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Low-latency UX:&lt;/strong&gt; Instant response at self-service kiosks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data sovereignty:&lt;/strong&gt; Payment data stays local to comply with regulations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Challenges at the Edge:&lt;/strong&gt; While beneficial, edge environments present unique challenges:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Resource constraints&lt;/strong&gt;: Devices at the edge, such as those in your coffee shops, often have lower compute and memory capacity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Intermittent connectivity&lt;/strong&gt;: Edge devices may not maintain a constant 24/7 internet connection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remote management difficulty&lt;/strong&gt;: You cannot manually SSH into hundreds of individual store servers to update software.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;K3s: Kubernetes Optimized for the Edge&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;K3s is a lightweight, CNCF-certified Kubernetes distribution built specifically for edge and IoT environments. Developed by Rancher, K3s simplifies cluster setup while remaining fully compatible with Kubernetes tooling and APIs. It’s ideal for resource-constrained devices—such as Raspberry Pis or Intel NUCs deployed in coffee shops or retail branches.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key K3s Features for Edge Deployments:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Single binary distribution (~100MB)&lt;/strong&gt; for fast installs and minimal overhead.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embedded components&lt;/strong&gt;: containerd (container runtime), runc, and kubectl.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Supports multiple storage backends&lt;/strong&gt;: SQLite (via Kine), embedded etcd, and external SQL (MySQL/PostgreSQL).
&lt;/li&gt;
&lt;li&gt;Works on ARM and x86_64 platforms.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pre-configured defaults&lt;/strong&gt;: Includes Flannel for networking, Traefik for ingress, and metrics-server for observability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzt5vmz04kl66foayrsp9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzt5vmz04kl66foayrsp9.png" alt="A visual example of K3s for coffee shop app." width="666" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How K3s Optimizes for the Edge&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unified Binary&lt;/strong&gt;: Embeds everything needed—container runtime, CRI tools, control plane in one downloadable file. Makes updates easy via binary replacement.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kine (SQLite integration)&lt;/strong&gt;: Reduces overhead by emulating etcd with SQLite, ideal for single-node clusters without consensus requirements.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimal System Requirements&lt;/strong&gt;: Can run in 512MB RAM, uses minimal CPU.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Comparing K3s and Kubernetes&lt;/strong&gt;
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Capability&lt;/th&gt;
&lt;th&gt;K3s&lt;/th&gt;
&lt;th&gt;Upstream Kubernetes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Installation&lt;/td&gt;
&lt;td&gt;Single binary, HTTP tunnel&lt;/td&gt;
&lt;td&gt;kubeadm, multiple binaries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Control plane&lt;/td&gt;
&lt;td&gt;Embedded etcd or SQLite&lt;/td&gt;
&lt;td&gt;etcd only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runtime&lt;/td&gt;
&lt;td&gt;Embedded containerd + runc&lt;/td&gt;
&lt;td&gt;External container runtime&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;System requirements&lt;/td&gt;
&lt;td&gt;~500MB RAM, low CPU&lt;/td&gt;
&lt;td&gt;1GB+ RAM, higher CPU&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HA options&lt;/td&gt;
&lt;td&gt;SQLite, etcd, SQL&lt;/td&gt;
&lt;td&gt;etcd only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Targets&lt;/td&gt;
&lt;td&gt;Edge, IoT, hobbyists&lt;/td&gt;
&lt;td&gt;Data centers, cloud&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;There are several personas or users of Kubernetes. Refer how K3s may affect each of them:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Developers&lt;/strong&gt;: Write standard manifests. No changes needed.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Platform Engineers&lt;/strong&gt;: Use pre-bundled defaults to reduce setup time.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SREs/SecOps&lt;/strong&gt;: Need to understand K3s-specific HA, upgrades, and bootstrap.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;K3s renames Kubernetes control plane nodes to "servers" and worker nodes to "agents". It uses an HTTP tunnel for simplified server-agent communication, Flannel for networking by default, and Traefik for ingress.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Server&lt;/strong&gt;: Control plane node
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent&lt;/strong&gt;: Worker node&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;K3s Architecture&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;K3s is purpose-built for edge and resource-constrained environments. Unlike upstream Kubernetes, which requires multiple binaries and external dependencies, K3s is distributed as a single binary. Internally, K3s embeds several core components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;containerd and runc&lt;/strong&gt;: Used as the default container runtime.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embedded SQLite or etcd&lt;/strong&gt;: For storing Kubernetes cluster state. SQLite is ideal for single-node clusters; etcd enables high availability.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in defaults&lt;/strong&gt;: Includes Flannel (CNI), Traefik (Ingress), metrics-server, and Helm controller.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;K3s uses a simplified bootstrapping process where agents (workers) connect to the control plane (server) via an encrypted tunnel (k3s-agent uses reverse tunnels).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1iys4wfmt6ytrz5z4y94.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1iys4wfmt6ytrz5z4y94.png" alt="A visual example of K3s server components." width="653" height="301"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; In smaller stores, a single-node K3s cluster can run all three services—order, payment, and inventory—on one device.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;High Availability (HA) with K3s&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you want your cluster to tolerate failures (e.g., a power outage at one device), K3s supports HA using embedded etcd. This mode is recommended for clusters that run critical systems and must remain available even during node failures.&lt;/p&gt;

&lt;p&gt;For resilience, K3s supports two HA modes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Embedded etcd (Raft consensus)&lt;/strong&gt;: Suitable for production. Requires 3 or 5 server nodes.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;External SQL DB (PostgreSQL/MySQL)&lt;/strong&gt;: Lightweight but harder to scale.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What's up with k3sup?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;k3sup (pronounced "ketchup") is a community tool that simplifies K3s installation and joining agents to a cluster over SSH, making remote setup trivial. k3sup can also update your kubectl configuration file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Use k3sup?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Remote installation via SSH&lt;/strong&gt;: great for air-gapped or low-access environments.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One-line cluster provisioning&lt;/strong&gt;:ideal for bootstrapping multiple stores quickly.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;kubectl auto-merge&lt;/strong&gt;: automatically adds new K3s clusters to your KUBECONFIG file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6bj9904l90laq62oyjuf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6bj9904l90laq62oyjuf.png" alt="A visual example for flow of data in K3sup." width="800" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Fleet: Centralized Multi-Cluster Management&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Fleet is Rancher’s GitOps controller purpose-built to manage thousands of Kubernetes clusters—ideal for widespread edge deployments like your coffee shop application. While K3s runs a lightweight cluster at each store, Fleet offers centralized visibility, version control, and deployment across all of them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Use Fleet with K3s?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Central control, local autonomy&lt;/strong&gt;: You manage manifests, Helm charts, and configurations from a single Git repository. Each K3s store fetches its configuration independently.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Designed for scale&lt;/strong&gt;: Fleet supports &lt;strong&gt;up to 1 million clusters&lt;/strong&gt; and uses lightweight agents with minimal overhead.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pull-based sync&lt;/strong&gt;: Suitable for remote stores with dynamic IPs or unreliable connectivity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;How Fleet Works?&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Git Repository as Source of Truth&lt;/strong&gt;
You store application definitions (YAML, Helm, Kustomize, or OCI bundles) in a Git repo. These include:

&lt;ul&gt;
&lt;li&gt;fleet.yaml for configuration
&lt;/li&gt;
&lt;li&gt;Manifests for each microservice (order.yaml, payment.yaml, inventory.yaml)
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fleet Manager (Controller)&lt;/strong&gt;
The Fleet controller runs in a central management cluster (on-prem or in the cloud). It watches Git repositories and generates bundles for deployment.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fleet Agents in Edge Clusters&lt;/strong&gt;
Each K3s cluster runs a Fleet agent. This agent:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Connects back to the Fleet manager securely.
&lt;/li&gt;
&lt;li&gt;Pulls the correct workload bundle.
&lt;/li&gt;
&lt;li&gt;Applies the manifests locally.
&lt;/li&gt;
&lt;li&gt;Reports status.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb1fl6p8fp8pyiup47hfk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb1fl6p8fp8pyiup47hfk.png" alt="A visual example of K3s integration with Fleet." width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Coffee Shop Deployment: &lt;code&gt;fleet.yaml&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;defaultNamespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;coffee-shop&lt;/span&gt;  
  &lt;span class="s"&gt;targets&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;\- name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;edge-shops&lt;/span&gt;  
    &lt;span class="s"&gt;clusterSelector&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
        &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;edge&lt;/span&gt;  
    &lt;span class="na"&gt;yaml&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;\- path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;manifests/order.yaml&lt;/span&gt;  
      &lt;span class="na"&gt;\- path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;manifests/payment.yaml&lt;/span&gt;  
      &lt;span class="na"&gt;\- path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;manifests/inventory.yaml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Benefits of Using Fleet in Edge Deployments&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Resilient by Design:&lt;/strong&gt; If a cluster goes offline, Fleet retries syncing when it's back online. No manual recovery needed.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Declarative GitOps Workflow:&lt;/strong&gt; All changes are Git-driven and reproducible. Every store gets the same, tested configuration.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security &amp;amp; Separation:&lt;/strong&gt; Since clusters &lt;strong&gt;pull&lt;/strong&gt; workloads from Fleet, they don't need inbound access or public IPs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Remote Access&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Because edge locations (coffee shops) often lack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Static IPs&lt;/li&gt;
&lt;li&gt;VPNs&lt;/li&gt;
&lt;li&gt;SSH access&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fleet enables secure pull-based management, where the cluster reaches out to Fleet rather than requiring a central controller to initiate communication.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Alternatives and Tradeoffs&lt;/strong&gt;
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Pros&lt;/th&gt;
&lt;th&gt;Cons&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Fleet (GitOps)&lt;/td&gt;
&lt;td&gt;Secure, scalable, automatic retries&lt;/td&gt;
&lt;td&gt;Requires pre-registration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VPN&lt;/td&gt;
&lt;td&gt;Secure tunneling&lt;/td&gt;
&lt;td&gt;Complex to set up at scale&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSH&lt;/td&gt;
&lt;td&gt;Quick setup, compatible with k3sup&lt;/td&gt;
&lt;td&gt;Hard to scale, brittle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Inlets&lt;/td&gt;
&lt;td&gt;Easy tunneling of HTTP/TCP&lt;/td&gt;
&lt;td&gt;Requires cloud relay or tunnel server&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;When managing 1,000+ coffee shops, you can't SSH into each branch to make changes. Most shops lack static IPs or stable internet. Instead of managing clusters by pushing changes from a central control plane, Fleet agents run inside each K3s cluster and initiate outbound connections to the central Fleet controller. This helps you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoid the need for public or routable IP addresses.
&lt;/li&gt;
&lt;li&gt;Work over common outbound ports (e.g., HTTPS).
&lt;/li&gt;
&lt;li&gt;Enable auto-recovery when clusters reboot or reconnect&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0wvy3kwo6cx3n7oqoslk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0wvy3kwo6cx3n7oqoslk.png" alt="A visual example of remote access for Fleet and Edge of coffee shop." width="609" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, in coffee shop app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A barista at "Store 042" restarts their Raspberry Pi.
&lt;/li&gt;
&lt;li&gt;It boots K3s, pulls the latest manifests from Fleet via Git.
&lt;/li&gt;
&lt;li&gt;Fleet ensures order-service, payment-service, and inventory-service run correctly without manual intervention.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Air-Gapped Environment&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Many remote stores may lack internet access. K3s and Fleet support full air-gapped deployments.&lt;/p&gt;

&lt;p&gt;In these setups, you prepare everything ahead of time using USB drives or local staging networks.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Resource&lt;/th&gt;
&lt;th&gt;Where to Load&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;K3s binary&lt;/td&gt;
&lt;td&gt;Flash drive or staging laptop&lt;/td&gt;
&lt;td&gt;Install manually&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Container images&lt;/td&gt;
&lt;td&gt;/var/lib/rancher/k3s/agent/images/&lt;/td&gt;
&lt;td&gt;Use ctr images export and import&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fleet.yaml and app manifests&lt;/td&gt;
&lt;td&gt;Local Git repo clone or OCI registry mirror&lt;/td&gt;
&lt;td&gt;Load from USB or portable device&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fleet agent&lt;/td&gt;
&lt;td&gt;Bundled with app or installed offline&lt;/td&gt;
&lt;td&gt;Uses local bundle and syncs when connected&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; For air-gapped shops, you can use a portable Git repo or OCI registry mirror hosted temporarily on a laptop or USB stick.&lt;/p&gt;

&lt;p&gt;Fleet still works offline by syncing from this local source. Later, when connectivity returns, these nodes can reconnect and pull updates as usual.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What Is MQTT and Why Use It at the Edge?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;MQTT (Message Queuing Telemetry Transport) is a lightweight, publish-subscribe messaging protocol designed for constrained devices and unreliable networks—making it ideal for edge computing.&lt;/p&gt;

&lt;p&gt;For example, in the Coffee Shop app, each store has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A temperature sensor inside a fridge.
&lt;/li&gt;
&lt;li&gt;An espresso machine that counts daily cycles.
&lt;/li&gt;
&lt;li&gt;A grinder that logs wear or usage hours.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;MQTT enables these devices to publish events (like temp=97°F) to a local broker running in the store (e.g., Mosquitto). Meanwhile, your backend services (e.g., an OpenFaaS function or logging collector) subscribe to relevant topics (/store104/fridge/temp).&lt;/p&gt;

&lt;p&gt;Why MQTT at the Edge?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Offline Resilience&lt;/strong&gt;: Devices buffer messages even when the internet is unavailable.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Loose Coupling&lt;/strong&gt;: Producers don’t need to know who the consumers are.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Asynchronous&lt;/strong&gt;: Ideal for non-blocking sensor data or logs.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bandwidth Efficient&lt;/strong&gt;: Optimized for unreliable or metered networks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When connectivity returns, MQTT relays buffered messages to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;central cloud MQTT broker&lt;/strong&gt; (e.g., EMQX, HiveMQ, or AWS IoT)
&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;data lake&lt;/strong&gt;, &lt;strong&gt;time-series database&lt;/strong&gt;, or &lt;strong&gt;dashboard&lt;/strong&gt; via Kafka or Prometheus exporters&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Using OpenFaaS for Functions at the Edge&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;OpenFaaS (Function-as-a-Service) is a serverless framework designed to run lightweight, containerized functions on Kubernetes—including K3s at the edge.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Use It at the Edge?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduces the overhead of running full-blown apps
&lt;/li&gt;
&lt;li&gt;Fast deployment via Kubernetes CRDs
&lt;/li&gt;
&lt;li&gt;Supports HTTP, MQTT, and CRON as event sources
&lt;/li&gt;
&lt;li&gt;Integrates with container registries and GitOps workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1f4hss36af6zj3bcgxk2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1f4hss36af6zj3bcgxk2.png" alt="A visual example in coffee shop app using MQTT." width="800" height="48"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, in a coffee Shop app consider store 14 has a Raspberry Pi that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Receives real-time fridge temperature via MQTT.
&lt;/li&gt;
&lt;li&gt;Triggers a Python-based function when data is published.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
    &lt;span class="n"&gt;temp&lt;/span&gt; \&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt; \&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;95&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Warning: Too hot\!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Temperature OK&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Other Edge Functions You Can Run:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detect low inventory thresholds and alert inventory-service.
&lt;/li&gt;
&lt;li&gt;Sanitize incoming sensor data and write to local disk.
&lt;/li&gt;
&lt;li&gt;Detect anomalies and forward to a machine-learning model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OpenaaS wraps this as a function, builds a container image, and deploys it via Kubernetes CRDs. Supports MQTT, HTTP, and CRON-based triggers.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Integrating MQTT and OpenFaaS&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Integrating MQTT and OpenFaaS provides a powerful, event-driven model for edge computing. MQTT acts as the event transport layer, while OpenFaaS serves as the event processor. Together, they create a reactive system that processes local data in real time and only syncs to the cloud when necessary.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ibuf581ugogwmpbgtak.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ibuf581ugogwmpbgtak.png" alt="A visual example integrating MQTT and OpenFaas for coffee shop app." width="800" height="750"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Consider Store 14's Fridge Monitoring in a coffee shop app:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sensor detects fridge temperature and publishes a message:

&lt;ul&gt;
&lt;li&gt;Topic: /store104/fridge/temp
&lt;/li&gt;
&lt;li&gt;Payload: {"temp": 97.4, "unit": "F"}
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Mosquitto (local MQTT broker) receives the message.
&lt;/li&gt;
&lt;li&gt;OpenFaaS MQTT Connector subscribes to the topic, reads the payload, and invokes a &lt;strong&gt;temperature-check function&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;The function evaluates the temperature:

&lt;ul&gt;
&lt;li&gt;Logs a warning if it's too high.
&lt;/li&gt;
&lt;li&gt;Optionally triggers an alert (e.g., send webhook, write to disk, store in SQLite).
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;If the internet is offline, logs and events are buffered locally.

&lt;ul&gt;
&lt;li&gt;MQTT persists the message.
&lt;/li&gt;
&lt;li&gt;OpenFaaS writes logs to a mounted persistent volume.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;When connectivity is restored:

&lt;ul&gt;
&lt;li&gt;Logs or alerts can be forwarded to a centralized logging system or metrics database.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Logging and Storage in Edge Scenarios&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In edge environments—like individual coffee shop branches—connectivity isn't guaranteed. Devices must operate independently for logging, metrics collection, and temporary data storage. Here's how to plan for these constraints.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Local Storage Considerations&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Each store’s K3s device should have storage for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;System:&lt;/strong&gt; K3s binary, operating system, configuration files.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runtime:&lt;/strong&gt; Container logs, telemetry, ephemeral workloads.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persistent Data:&lt;/strong&gt; Customer orders, payment events, inventory state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This ensures store operations can continue even if cloud connectivity is lost.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Logging Options&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;K3s includes metrics-server for lightweight resource monitoring. For advanced use cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prometheus/Grafana can run on each edge cluster for real-time observability.
&lt;/li&gt;
&lt;li&gt;Use Loki or Elasticsearch to forward logs when reconnected.
&lt;/li&gt;
&lt;li&gt;Local logs can be written using Kubernetes emptyDir or persistent volumes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; For more information, refer to &lt;a href="https://programmerprodigy.code.blog/2025/06/04/understanding-observability-with-opentelemetry-and-coffee/" rel="noopener noreferrer"&gt;Understanding Observability with OpenTelemetry and Coffee&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Syncing Logs and Events&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Logs and events generated at the edge can be buffered and forwarded later:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use MQTT to publish sensor data or application events to a central broker.
&lt;/li&gt;
&lt;li&gt;Store logs on local disk or persistent volume.
&lt;/li&gt;
&lt;li&gt;Sync to the cloud (object storage, log aggregation system) when a connection becomes available.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Best Practices&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cache locally:&lt;/strong&gt; Ensure services like inventory-service and payment-service write to disk.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use queues:&lt;/strong&gt; MQTT or Redis queues help avoid data loss when offline.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CSI Plugins:&lt;/strong&gt; Use Kubernetes-compatible storage interfaces suited for edge devices.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backups:&lt;/strong&gt; Use the 3-2-1 rule: 3 copies, 2 local (disk + USB/flash), 1 remote (cloud or data center).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Addressing Common Edge Challenges with K3s and Fleet&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The combined power of K3s and Fleet helps you overcome typical edge computing hurdles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Connectivity&lt;/strong&gt;: K3s nodes might go offline, but Fleet handles retries and synchronizes changes when network connectivity is restored.

&lt;ul&gt;
&lt;li&gt; For scenarios where continuous connectivity is a concern, MQTT can be used to buffer and forward messages from edge devices to a central network.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Upgrades&lt;/strong&gt;: K3s offers a simplified one-binary upgrade process, and Fleet centrally manages the redeployment of your applications across clusters.
&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Storage&lt;/strong&gt;: At the edge, you need to consider storage for the operating system, K3s itself, logged data, and container images.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Local Data&lt;/strong&gt;: For local logs or transactions, you can use persistent volumes (if available) or write data to local disk and sync to the cloud when connected.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concerns&lt;/strong&gt;: Be mindful of latency, capacity, and reliability when designing your storage solution.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backups&lt;/strong&gt;: Employ the 3-2-1 backup method: three copies of data, on two different media, with one copy off-site.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

</description>
      <category>microservices</category>
      <category>rancher</category>
    </item>
    <item>
      <title>Simplifying Microservices with Istio and Service Mesh Architecture</title>
      <dc:creator>hridyesh bisht</dc:creator>
      <pubDate>Thu, 03 Jul 2025 07:04:23 +0000</pubDate>
      <link>https://dev.to/aws-builders/simplifying-microservices-with-istio-and-service-mesh-architecture-41bp</link>
      <guid>https://dev.to/aws-builders/simplifying-microservices-with-istio-and-service-mesh-architecture-41bp</guid>
      <description>&lt;p&gt;As apps shift from monoliths to microservices, managing service-to-service communication becomes complex. Developers must handle traffic routing, retries, timeouts, load balancing, TLS encryption, metrics, and logs for each service. This leads to duplicated code and operational complexity.&lt;/p&gt;

&lt;p&gt;Service mesh is an infrastructure layer that manages service-to-service communication transparently. Istio, a popular open-source service mesh, addresses these challenges by deploying Envoy proxies as sidecars to your pods. The proxies intercept traffic and apply consistent policies without requiring code changes.&lt;/p&gt;

&lt;p&gt;I use a coffee shop microservices app as a running example, since I love coffee. The app includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;order-service (handles customer orders)
&lt;/li&gt;
&lt;li&gt;payment-service (processes payments)
&lt;/li&gt;
&lt;li&gt;inventory-service (manages coffee inventory)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Core Capabilities of Istio&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Istio provides powerful capabilities for traffic management, security, and observability within a microservices environment.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Capability&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Traffic Management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Define routing, fault injection, and load balancing using CRDs like &lt;code&gt;VirtualService&lt;/code&gt;, &lt;code&gt;DestinationRule&lt;/code&gt;, and &lt;code&gt;ServiceEntry&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Traffic Routing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Flexible traffic routing configurations using &lt;code&gt;VirtualService&lt;/code&gt; and &lt;code&gt;DestinationRule&lt;/code&gt; resources.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Resiliency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Enforce timeouts, retries, circuit breaking, and failover without changing app logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mesh Extension&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Integrate external services, Virtual Machines (VMs), and custom Envoy configurations Apply strong authentication (AuthN) and authorization (AuthZ) using mTLS and identity-based policies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Security&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Apply strong authentication (AuthN) and authorization (AuthZ) using mTLS and identity-based policies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Observability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Export telemetry (metrics, traces, logs) using integrations like SigNoz, Prometheus, Jaeger, and Kiali&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Installing Istio&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Istio provides flexible installation options to support different environments and use cases. You can install Istio using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;istioctl CLI&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Helm charts
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Istio Operator&lt;/code&gt; (for GitOps and declarative installs)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Istio includes predefined installation profiles optimized for different scenarios. Each profile configures control and data plane components through the &lt;code&gt;IstioOperator&lt;/code&gt; resource.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;istioctl profile list&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Istio provides different profiles:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Profile&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;default&lt;/td&gt;
&lt;td&gt;Production-ready; installs control plane and ingress gateway.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;demo&lt;/td&gt;
&lt;td&gt;Best for demos and learning; enables tracing, logging, ingress, and egress.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;minimal&lt;/td&gt;
&lt;td&gt;Control plane only; no gateways.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;external&lt;/td&gt;
&lt;td&gt;Used in remote clusters for multi-cluster mesh; installs nothing.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;empty&lt;/td&gt;
&lt;td&gt;Baseline config for custom setups.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;preview&lt;/td&gt;
&lt;td&gt;Includes experimental features.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ambient&lt;/td&gt;
&lt;td&gt;Sets up sidecar-less ambient mesh (Alpha; not for production).&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;To install Istio using the Istio CLI, you can use the &lt;code&gt;--set flag&lt;/code&gt; and specify the profile like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;istioctl install \--set profile=demo&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Use the demo profile during development to enable full telemetry. For production, switch to default to improve performance and security.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Get full configuration of a profile:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;istioctl profile dump demo&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compare two profiles:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;istioctl profile diff demo default&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Combining Helm and Operator&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You can use the IstioOperator resource alongside Helm:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use Helm to install base components.
&lt;/li&gt;
&lt;li&gt;Use IstioOperator to apply profile-level and mesh-level configurations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This modular setup is useful in environments where GitOps or CI/CD pipelines manage different aspects of configuration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo3phznx6jtui5xnf5p6h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo3phznx6jtui5xnf5p6h.png" alt="An image displaying Combining Helm and Operator" width="800" height="182"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Istio Architecture&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Istio consists of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data Plane: Lightweight Envoy proxies injected as sidecars to each pod. These proxies handle all ingress and egress traffic for the pod.
&lt;/li&gt;
&lt;li&gt;Control Plane: The Istiod component configures and manages the behavior of Envoy proxies by pushing policies and configuration dynamically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The overall architecture of an Istio-based application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxdq4hwvpvrmltt7g0ink.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxdq4hwvpvrmltt7g0ink.png" alt="The overall architecture of an Istio-based application." width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
Image credits: &lt;a href="https://istio.io/latest/docs/ops/deployment/architecture/" rel="noopener noreferrer"&gt;Istio documentation.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, each pod in the Coffee Shop app has a sidecar Envoy proxy that intercepts all traffic. This enables Istio to provide seamless:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Traffic routing
&lt;/li&gt;
&lt;li&gt;mTLS encryption
&lt;/li&gt;
&lt;li&gt;Metrics and tracing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F51b8xyy55cgcfexoqcd1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F51b8xyy55cgcfexoqcd1.png" alt="An architecture image of coffee shop app " width="800" height="129"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Sidecar&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Manually modifying manifests to add sidecars is error-prone and not scalable. Istio supports two approaches:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Manual Sidecar&lt;/strong&gt;: This method involves using the istioctl CLI to manually inject sidecars into YAML manifests. You can use the CLI to inject sidecars into your YAML manifests. Run the following command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;istioctl kube-inject \-f deployment.yaml | kubectl apply \-f \-&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automatic Sidecar&lt;/strong&gt;: This is the recommended approach for most use cases. Istio uses a &lt;a href="https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#mutatingadmissionwebhook" rel="noopener noreferrer"&gt;Mutating Admission Webhook&lt;/a&gt; to inject sidecars into all pods created in a namespace labeled with &lt;code&gt;istio-injection=enabled&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; All new pods in that namespace get sidecars injected automatically.&lt;/p&gt;

&lt;p&gt;To enable for a namespace, run:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl label namespace coffee-shop istio-injection=enabled&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Routing Traffic Through Sidecars&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Istio uses &lt;strong&gt;iptables rules&lt;/strong&gt; or &lt;strong&gt;CNI plugins&lt;/strong&gt; to transparently route traffic through the Envoy sidecar.&lt;/p&gt;

&lt;p&gt;An init container sets up the iptables rules before the application starts. This ensures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Outbound traffic from the app is redirected to the Envoy sidecar
&lt;/li&gt;
&lt;li&gt;Inbound traffic hits the sidecar before reaching the app&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, a request from &lt;code&gt;order-service&lt;/code&gt; to &lt;code&gt;payment-service&lt;/code&gt; is transparently routed via sidecars.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F56ptab74sszazfgo3rej.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F56ptab74sszazfgo3rej.png" alt="An image of request from order-service to payment-service routed via sidecars." width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Configuring Envoy Proxies&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When an app makes a call to another service, that call is now intercepted by its sidecar. The job of configuring the proxies with all the information they need to handle both incoming and outgoing traffic falls to the Istio control plane.&lt;/p&gt;

&lt;p&gt;The Istio control plane configures all Envoy proxies dynamically using &lt;strong&gt;xDS APIs&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Delivered via Istio Control Plane&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Route discovery&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;VirtualService&lt;/code&gt; and &lt;code&gt;DestinationRule&lt;/code&gt; updates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Load balancing&lt;/td&gt;
&lt;td&gt;Weighted or subset-based routing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Retry and timeout&lt;/td&gt;
&lt;td&gt;Policy enforcement without app changes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;mTLS and security&lt;/td&gt;
&lt;td&gt;Dynamic certificate provisioning&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Istio automates all sidecar configurations according to the current mesh topology. Each time services are added, removed, or updated, Istio ensures that the latest configurations—network, routing, or security policies—are distributed to the appropriate sidecars.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4x6kqbr9yuuimtnhogib.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4x6kqbr9yuuimtnhogib.png" alt="A flow of data image when order-service wants to call payment-service in coffee shop example" width="800" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, order-service wants to call payment-service:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Istio discovers endpoints of payment-service
&lt;/li&gt;
&lt;li&gt;Pushes routing config to order-service’s proxy
&lt;/li&gt;
&lt;li&gt;Applies retries, timeouts, load balancing, and TLS&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Traffic Management&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Istio's traffic management relies on Custom Resources (CRDs) like &lt;code&gt;VirtualService&lt;/code&gt;, &lt;code&gt;DestinationRule&lt;/code&gt;, and &lt;code&gt;ServiceEntry&lt;/code&gt; to define fine-grained routing, resiliency, and fault injection policies&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Ingress and Egress Gateways&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Istio uses the &lt;code&gt;Gateway&lt;/code&gt; resource to manage how Envoy proxies handle inbound and outbound traffic. Unlike Kubernetes Ingress, Istio Gateways provide richer Layer 7 routing.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Gateway Type&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;th&gt;Example Scenario&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ingress Gateway&lt;/td&gt;
&lt;td&gt;Accepts external traffic into the mesh&lt;/td&gt;
&lt;td&gt;Client → Ingress Gateway → order-service&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Egress Gateway&lt;/td&gt;
&lt;td&gt;Manages outbound traffic to external APIs&lt;/td&gt;
&lt;td&gt;payment-service → Egress Gateway → Payment API&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: &lt;code&gt;Gateway&lt;/code&gt; and &lt;code&gt;VirtualService&lt;/code&gt; Configuration&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.istio.io/v1beta1&lt;/span&gt;

&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Gateway&lt;/span&gt;

&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;coffee-ingress&lt;/span&gt;

&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;istio&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ingressgateway&lt;/span&gt;

  &lt;span class="na"&gt;servers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;\- port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

        &lt;span class="na"&gt;number&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;

        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;

        &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HTTP&lt;/span&gt;

      &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

        &lt;span class="s"&gt;\- "order.coffee.com"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;VirtualService with Gateway&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To route external traffic to internal services, a &lt;code&gt;Gateway&lt;/code&gt; must be used in conjunction with a &lt;code&gt;VirtualService&lt;/code&gt;. If a &lt;code&gt;VirtualService&lt;/code&gt; is not bound to a Gateway, Envoy returns an HTTP 404, indicating no route has been defined.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhf8iv4591ztv4chr8dkx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhf8iv4591ztv4chr8dkx.png" alt="A flow of data with virtualService and Gateway in coffee shop app" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create a corresponding &lt;code&gt;VirtualService&lt;/code&gt; that binds to the Gateway:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.istio.io/v1beta1&lt;/span&gt;

&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;VirtualService&lt;/span&gt;

&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;order-route&lt;/span&gt;

&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="s"&gt;\- "\*"&lt;/span&gt;

  &lt;span class="na"&gt;gateways&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="s"&gt;\- coffee-gateway&lt;/span&gt;

  &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;\- route&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;\- destination&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

        &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;order-service.default.svc.cluster.local&lt;/span&gt;

        &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

          &lt;span class="na"&gt;number&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Apply the configuration:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl apply \-f order-route.yaml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test the route:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;curl \-v http://$GATEWAY_IP/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Usually, istio-ingressgateway service is exposed using the Kubernetes LoadBalancer type, which assigns an external IP to receive HTTP(S) traffic.&lt;/p&gt;

&lt;p&gt;How the LoadBalancer Kubernetes service type works depends on how and where you run the Kubernetes cluster. &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;LoadBalancer Behavior&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AWS, GCP, Azure&lt;/td&gt;
&lt;td&gt;Provisions a cloud load balancer and assigns external IP.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Minikube&lt;/td&gt;
&lt;td&gt;Requires minikube tunnel to simulate external access.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For example, In coffee shop app, gateways are essential to expose services like &lt;code&gt;order-service&lt;/code&gt;, &lt;code&gt;payment-service&lt;/code&gt;, and &lt;code&gt;inventory-service&lt;/code&gt; to the outside world or external systems.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9aqhngpdv80ro3093mtc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9aqhngpdv80ro3093mtc.png" alt="An image displaying gateways for services in coffee shop app." width="800" height="96"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Traffic Routing and Resiliency&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Istio allows flexible traffic routing configurations using &lt;code&gt;VirtualService&lt;/code&gt; and &lt;code&gt;DestinationRule&lt;/code&gt; resources.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Resource&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;VirtualService&lt;/td&gt;
&lt;td&gt;Defines traffic routing rules to one or more destinations.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DestinationRule&lt;/td&gt;
&lt;td&gt;Configures policies for routed traffic, such as load balancing and TLS.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ServiceEntry&lt;/td&gt;
&lt;td&gt;Adds external services to the mesh registry.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For example, consider a coffee-shop app with these services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Web-frontend: the UI for customers.
&lt;/li&gt;
&lt;li&gt;Customer-service: handles customer profiles.

&lt;ul&gt;
&lt;li&gt;Two versions of customer-service: v1 and v2.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ezidu2z7d4bn9dpre6j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ezidu2z7d4bn9dpre6j.png" alt="An image of coffee shop Kubernetes pod." width="619" height="208"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can define different subsets of a service, typically based on labels in the pod spec (e.g., version: v1 or version: v2 for a customer-service). Pods are labeled with version: v1 or version: v2. You set subsets in a &lt;code&gt;DestinationRule&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.istio.io/v1beta1&lt;/span&gt;

&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;DestinationRule&lt;/span&gt;

&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;customer-service&lt;/span&gt;

&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;customer-service.default.svc.cluster.local&lt;/span&gt;

  &lt;span class="na"&gt;subsets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;\- name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;

    &lt;span class="s"&gt;labels&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;

      &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;

  &lt;span class="na"&gt;\- name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v2&lt;/span&gt;

    &lt;span class="s"&gt;labels&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;

      &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Routing Traffic with VirtualService&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In the &lt;code&gt;VirtualService&lt;/code&gt;, you can specify the traffic matching and routing rules that decide which destinations traffic is routed to.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; To generate some traffic, open a separate terminal window and start making requests to the &lt;strong&gt;GATEWAY_IP&lt;/strong&gt; in an endless loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;GATEWAY_IP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;kubectl get svc &lt;span class="se"&gt;\-&lt;/span&gt;n istio-system istio-ingressgateway &lt;span class="se"&gt;\-&lt;/span&gt;&lt;span class="nv"&gt;ojsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.status.loadBalancer.ingress\[0\].ip}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do &lt;/span&gt;curl http://&lt;span class="nv"&gt;$GATEWAY_IP&lt;/span&gt;/&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Weight-Based Routing&lt;/strong&gt;: Distributes traffic across different subsets of the same service based on assigned weights (e.g., 70% to v1 and 30% to v2).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.istio.io/v1beta1&lt;/span&gt;

&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;VirtualService&lt;/span&gt;

&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;customer-service&lt;/span&gt;

&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="s"&gt;\- customer-service.default.svc.cluster.local&lt;/span&gt;

  &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;\- route&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;\- destination&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

        &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;customer-service.default.svc.cluster.local&lt;/span&gt;

        &lt;span class="na"&gt;subset&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;

      &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;70&lt;/span&gt;

    &lt;span class="na"&gt;\- destination&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

        &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;customer-service.default.svc.cluster.local&lt;/span&gt;

        &lt;span class="na"&gt;subset&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v2&lt;/span&gt;

      &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Match-Based Routing&lt;/strong&gt;: Routes traffic based on specific conditions, such as HTTP headers (e.g., User-Agent) or URI paths.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;\- match&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;\- headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

      &lt;span class="na"&gt;user-agent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

        &lt;span class="na"&gt;regex&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;*Firefox.&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt;

  &lt;span class="na"&gt;route&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;\- destination&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

      &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;customer-service.default.svc.cluster.local&lt;/span&gt;

      &lt;span class="na"&gt;subset&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;

&lt;span class="na"&gt;\- route&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;\- destination&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

      &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;customer-service.default.svc.cluster.local&lt;/span&gt;

      &lt;span class="na"&gt;subset&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Redirect and Rewrite&lt;/strong&gt;: Redirects traffic (HTTP 301) to a different URI or hostname, or rewrites path prefixes before forwarding. Note that redirect and destination fields are mutually exclusive.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;\- match&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;\- uri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

      &lt;span class="na"&gt;exact&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/v1/hello&lt;/span&gt;

  &lt;span class="na"&gt;redirect&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/v2/hello&lt;/span&gt;

    &lt;span class="na"&gt;authority&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hello.default.svc.cluster.local&lt;/span&gt;

&lt;span class="na"&gt;Rewrite path prefix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;\- match&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;\- uri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

      &lt;span class="na"&gt;prefix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/v1/api&lt;/span&gt;

  &lt;span class="na"&gt;rewrite&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/v2/api&lt;/span&gt;

  &lt;span class="na"&gt;route&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;\- destination&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

      &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;customer-service.default.svc.cluster.local&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;redirect&lt;/code&gt; and &lt;code&gt;destination&lt;/code&gt; fields are mutually exclusive. If we use the &lt;code&gt;redirect&lt;/code&gt;, there is no need to set the destination.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mirroring Traffic&lt;/strong&gt;: Sends a copy of live traffic to another service version (e.g., mirroring 100% of traffic sent to v1 to v2). This "fire and forget" mechanism is useful for testing and debugging with production traffic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;\- route&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;\- destination&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

      &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;customer-service.default.svc.cluster.local&lt;/span&gt;

      &lt;span class="na"&gt;subset&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;

    &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;

  &lt;span class="na"&gt;mirror&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;customer-service.default.svc.cluster.local&lt;/span&gt;

    &lt;span class="na"&gt;subset&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v2&lt;/span&gt;

  &lt;span class="na"&gt;mirrorPercentage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Header Manipulation&lt;/strong&gt;: Allows you to add, set, or remove request and response headers, either for individual destinations or all destinations within a &lt;code&gt;VirtualService&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;\- headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

      &lt;span class="na"&gt;set&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

        &lt;span class="na"&gt;debug&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;

&lt;span class="err"&gt;  &lt;/span&gt;&lt;span class="na"&gt;route&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;\- destination&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

      &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;customer-service.default.svc.cluster.local&lt;/span&gt;

      &lt;span class="na"&gt;subset&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v2&lt;/span&gt;

    &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;

  &lt;span class="na"&gt;\- destination&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

      &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;customer-service.default.svc.cluster.local&lt;/span&gt;

      &lt;span class="na"&gt;subset&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;

    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

      &lt;span class="na"&gt;response&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

        &lt;span class="na"&gt;remove&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

        &lt;span class="s"&gt;\- x-api-key&lt;/span&gt;

    &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;70&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, you set a request header &lt;strong&gt;debug: true&lt;/strong&gt; for all traffic sent to the host. You are removing a response header called &lt;strong&gt;x-api-key&lt;/strong&gt;. So, whenever the traffic reaches the subset v1, the response from the service will not include the &lt;strong&gt;x-api-key&lt;/strong&gt; header.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AND Matching&lt;/strong&gt;: Rules can combine multiple conditions using AND logic (e.g., matching a URI prefix &lt;em&gt;and&lt;/em&gt; a specific header).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;\- uri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;prefix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/v1&lt;/span&gt;

  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

      &lt;span class="na"&gt;exact&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;debug&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;OR Matching&lt;/strong&gt;: Rules can combine multiple conditions using OR logic (matching either a URI prefix &lt;em&gt;or&lt;/em&gt; a header).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;\- uri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;prefix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/v1&lt;/span&gt;

&lt;span class="na"&gt;\- headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

      &lt;span class="na"&gt;exact&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;debug&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the first match does not evaluate to true, the algorithm moves to the second &lt;strong&gt;match&lt;/strong&gt; field and tries to match the header. If you omit the &lt;code&gt;match&lt;/code&gt; field on the route, it will continually evaluate to true.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: When using either of the two options, make sure you provide a fallback route if applicable. That way, if traffic doesn’t match any of the conditions, it could still be routed to a “default” route.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Resiliency Patterns&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Istio enables the application of resiliency policies at the network layer, reducing the need for application code changes&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Both retries and timeouts happen on the client side.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Timeouts&lt;/strong&gt; : If a request exceeds the timeout, Envoy responds with HTTP 408.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;\- route&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;\- destination&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

      &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;customer-service.default.svc.cluster.local&lt;/span&gt;

      &lt;span class="na"&gt;subset&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;

  &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Retries&lt;/strong&gt;: If the first pod fails, Envoy retries with a different healthy endpoint.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;retries&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;attempts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;

  &lt;span class="na"&gt;perTryTimeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2s&lt;/span&gt;

  &lt;span class="na"&gt;retryOn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gateway-error,connect-failure,reset&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Circuit Breaking with Outlier Detection&lt;/strong&gt;: This prevents cascading failures by automatically rejecting requests to overloaded or unhealthy services.&lt;/p&gt;

&lt;p&gt;Istio implements circuit breaking using &lt;strong&gt;outlier detection&lt;/strong&gt;, a passive health-checking mechanism. Envoy doesn't actively probe services but observes runtime metrics such as failure rate, latency, and connection health.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.istio.io/v1beta1&lt;/span&gt;

&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;DestinationRule&lt;/span&gt;

&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;customer-service&lt;/span&gt;

&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;customer-service&lt;/span&gt;

  &lt;span class="na"&gt;trafficPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;outlierDetection&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

      &lt;span class="na"&gt;consecutive5xxErrors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;

      &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1s&lt;/span&gt;

      &lt;span class="na"&gt;baseEjectionTime&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;3m&lt;/span&gt;

      &lt;span class="na"&gt;maxEjectionPercent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;consecutive5xxErrors&lt;/strong&gt;: Number of consecutive 5xx responses before ejection.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;interval&lt;/strong&gt;: How often Envoy checks pod health.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;baseEjectionTime&lt;/strong&gt;: Initial duration a pod remains ejected. This increases with repeated failures.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;maxEjectionPercent&lt;/strong&gt;: Caps the percentage of pods that can be ejected.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When thresholds are met, Envoy temporarily removes the unhealthy pod from the load-balancing pool. Over time, the pod is gradually reintroduced if it recovers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Failure Injection&lt;/strong&gt;: This allows you to simulate network failures or delays. This helps validate your service's resilience and fallback mechanisms.&lt;/p&gt;

&lt;p&gt;Istio supports two types of fault injection in the VirtualService:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Abort&lt;/strong&gt;: Simulate HTTP errors by terminating requests with a specified status code.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delay&lt;/strong&gt;: Introduce artificial latency before forwarding requests.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Abort 30% of requests:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;fault&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;abort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;percentage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;

    &lt;span class="na"&gt;httpStatus&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;404&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;:  If you omit the percentage field, all matching requests will be aborted.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inject delay to 5% of requests:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;fault&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;delay&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;percentage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;

    &lt;span class="na"&gt;fixedDelay&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;3s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fault injection only affects services matched by the &lt;code&gt;VirtualService&lt;/code&gt;. It does &lt;strong&gt;not&lt;/strong&gt; impact other consumers.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Extending the Istio Mesh&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Istio provides mechanisms to bring external services and Virtual Machines (VMs) into the mesh, and to customize Envoy proxies.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Bringing External Services into the Mesh&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Istio tracks internal services automatically. To include external or non-Kubernetes services, use the &lt;code&gt;ServiceEntry&lt;/code&gt; custom resource. This allows you to manage traffic and apply policies like retries, timeouts, mirroring, and fault injection to external endpoints.&lt;/p&gt;

&lt;p&gt;For example, the Coffee Shop microservices application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;payment-service needs to call an external payment API (mesh-external)
&lt;/li&gt;
&lt;li&gt;rewards-service communicates with an internal legacy database (mesh-internal)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;MESH_EXTERNAL&lt;/strong&gt;: Used for services outside the mesh (e.g., &lt;a href="http://www.googleapis.com" rel="noopener noreferrer"&gt;www.googleapis.com&lt;/a&gt;), typically with resolution: DNS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.istio.io/v1beta1&lt;/span&gt;  
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ServiceEntry&lt;/span&gt;  
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;googleapis-svc-entry&lt;/span&gt;  
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="s"&gt;\- www.googleapis.com&lt;/span&gt;  
  &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MESH_EXTERNAL&lt;/span&gt;  
  &lt;span class="na"&gt;resolution&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;DNS&lt;/span&gt;  
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;\- number&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;443&lt;/span&gt;  
    &lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https&lt;/span&gt;  
    &lt;span class="s"&gt;protocol&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TLS&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;location: MESH_EXTERNAL: Specifies the service is outside the mesh.
&lt;/li&gt;
&lt;li&gt;resolution: DNS: Istio uses DNS to resolve the host.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;MESH_INTERNAL&lt;/strong&gt;: Used for services within the mesh that do not have DNS, requiring resolution: &lt;code&gt;STATIC&lt;/code&gt; and explicit IP addresses. The hosts field is optional with &lt;code&gt;STATIC&lt;/code&gt; resolution. You can also use &lt;code&gt;workloadSelector&lt;/code&gt; for endpoint selection.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.istio.io/v1beta1&lt;/span&gt;  
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ServiceEntry&lt;/span&gt;  
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;legacy-loyalty-db&lt;/span&gt;  
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;addresses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="s"&gt;\- 192.192.192.192/24&lt;/span&gt;  
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;\- number&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;27018&lt;/span&gt;  
    &lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mongodb&lt;/span&gt;  
    &lt;span class="s"&gt;protocol&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MONGO&lt;/span&gt;  
  &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MESH_INTERNAL&lt;/span&gt;  
  &lt;span class="na"&gt;resolution&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;STATIC&lt;/span&gt;  
  &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;\- address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10.0.0.2&lt;/span&gt;  
  &lt;span class="na"&gt;\- address&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10.0.0.3&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The hosts field is optional when using STATIC resolution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Outbound Traffic Policy&lt;/strong&gt;: The &lt;code&gt;REGISTRY_ONLY&lt;/code&gt; outbound traffic policy can be configured to ensure traffic is only allowed to known services registered in the mesh.&lt;/p&gt;

&lt;p&gt;Configure Mesh to Registry-Only:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;istioctl install \--set profile=demo \--set meshConfig.outboundTrafficPolicy.mode=REGISTRY_ONLY&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Confirm Configuration:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl get cm \-n istio-system istio \-o yaml | grep outboundTrafficPolicy&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Centralized Egress via Gateway&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Use an Egress Gateway to manage and monitor all outbound traffic. This setup enables centralized TLS termination, access control, and observability.&lt;/p&gt;

&lt;p&gt;Required resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;AuthorizationPolicy&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Gateway&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;VirtualService&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DestinationRule&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Onboarding VMs into the Mesh&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;VMs can join the mesh using the &lt;code&gt;WorkloadEntry&lt;/code&gt; and &lt;code&gt;WorkloadGroup&lt;/code&gt; resources. Istio treats VMs similarly to Kubernetes pods, assigning identities based on namespace and service account.&lt;/p&gt;

&lt;p&gt;The general procedure for onboarding a VM can be summarized by the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install the Istio sidecar using &lt;code&gt;.deb&lt;/code&gt; or &lt;code&gt;.rpm&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Define a &lt;code&gt;WorkloadGroup&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.istio.io/v1beta1&lt;/span&gt;  
  &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;WorkloadGroup&lt;/span&gt;  
  &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;barista-vm&lt;/span&gt;  
    &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;coffee-shop&lt;/span&gt;  
  &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;barista-service&lt;/span&gt;  
    &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;serviceAccount&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;barista-account&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Configure the east-west gateway:
&lt;code&gt;./samples/multicluster/gen-eastwest-gateway.sh \--single-cluster | istioctl install \-y \-f \-&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Expose &lt;code&gt;istiod&lt;/code&gt;:
&lt;code&gt;kubectl apply \-n istio-system \-f ./samples/multicluster/expose-istiod.yaml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Generate and copy configs:
&lt;code&gt;istioctl x workload entry configure \-f barista.yaml \-o ./output-dir&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Place files in the correct locations and start the sidecar on the VM.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Communication in extending to VM:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Services in the cluster can reach VMs using DNS.
&lt;/li&gt;
&lt;li&gt;VMs can access services inside Kubernetes using mesh DNS.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An east-west gateway is necessary to enable communication between the sidecar that will be running on the VM and istiod, the Istio control plane (see the &lt;a href="https://istio.io/latest/docs/ops/deployment/vm-architecture/" rel="noopener noreferrer"&gt;Istio documentation&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To Install the East-West Gateway and Expose Istiod&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install the east-west gateway: &lt;strong&gt;&lt;code&gt;A./samples/multicluster/gen-eastwest-gateway.sh --single-cluster | istioctl install -y -f -&lt;/code&gt;&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;If you list the pods in the &lt;strong&gt;istio-system&lt;/strong&gt; namespace you’ll notice the &lt;strong&gt;istio-eastwestgateway&lt;/strong&gt; instance was created.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Expose istiod though the east-west gateway: &lt;strong&gt;&lt;code&gt;kubectl apply -n istio-system -f ./samples/multicluster/expose-istiod.yaml&lt;/code&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For example, consider&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.istio.io/v1beta1&lt;/span&gt;  
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;WorkloadGroup&lt;/span&gt;  
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;barista-vm&lt;/span&gt;  
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;coffee-shop&lt;/span&gt;  
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;barista-service&lt;/span&gt;  
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;serviceAccount&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;barista-account&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgvp95nh6odaumnh1cnut.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgvp95nh6odaumnh1cnut.png" alt="An image displaying flow of data from Coffee Shop pods to VM + Sidecar." width="800" height="58"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Customizing and Extending Envoy Proxies&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Istio automatically generates the Envoy configuration for each proxy. However, for advanced use cases, you can customize this configuration and extend Envoy's functionality.&lt;/p&gt;

&lt;p&gt;Envoy's configuration is structured into several key components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Listeners:&lt;/strong&gt; Network locations (IP and port) where Envoy listens for incoming connections and requests. Istio generates multiple listeners for each sidecar.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Filters&lt;/strong&gt;: Ordered lists of processing logic that a request flows through (Listener, Network, and HTTP filters). The router filter is typically the last HTTP filter and is responsible for routing traffic.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Routes&lt;/strong&gt;: URI/path-based traffic routing rules defined within the route configuration. These rules match incoming requests and specify where traffic should be sent.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clusters&lt;/strong&gt;: Groups of similar upstream hosts (destinations or servers), analogous to Kubernetes Services, that accept traffic.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Endpoints&lt;/strong&gt;: Concrete &lt;code&gt;IP:port&lt;/code&gt; pairs within a cluster, representing the specific addresses where traffic can be sent.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpy63roukzs6livzn2t1t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpy63roukzs6livzn2t1t.png" alt="A flow displaying extending envoy proxies for coffee shop app" width="800" height="37"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, when a request reaches coffee-frontend:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Envoy listens on port 15001.
&lt;/li&gt;
&lt;li&gt;Filters inspect and process the request.
&lt;/li&gt;
&lt;li&gt;Routing sends it to the barista-service cluster.
&lt;/li&gt;
&lt;li&gt;One of the barista pods (endpoint) handles the request.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can inspect the Envoy configuration using the istioctl proxy-config command. For example:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;istioctl proxy-config clusters coffee-frontend-xyz \--namespace coffee-shop&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The EnvoyFilter resource allows you to customize portions of the auto-generated Envoy proxy configuration by patching existing settings. This enables updating values, adding or removing filters, or creating new listeners and clusters.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application Scope: EnvoyFilter resources can be applied at three levels: globally (affecting all proxies in the mesh), per namespace, or to specific workloads.
&lt;/li&gt;
&lt;li&gt;Patch Location (applyTo): You can target specific configuration sections, such as LISTENER, HTTP_FILTER, NETWORK_FILTER, or CLUSTER.
&lt;/li&gt;
&lt;li&gt;Patch Target (match): The scope can be narrowed using context (e.g., SIDECAR_INBOUND, SIDECAR_OUTBOUND, GATEWAY), listener properties, route configuration, or cluster properties.
&lt;/li&gt;
&lt;li&gt;Patch Action (patch): Defines how the patch is applied, with operations like MERGE, ADD, REMOVE, INSERT_BEFORE, or INSERT_AFTER.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example to patch with EnvoyFilter&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;\- applyTo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;EXTENSION_CONFIG&lt;/span&gt;  
  &lt;span class="s"&gt;patch&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;operation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ADD&lt;/span&gt;  
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;custom-metrics&lt;/span&gt;  
      &lt;span class="na"&gt;typed_config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
        &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@type"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm&lt;/span&gt;  
        &lt;span class="s"&gt;config&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;  
          &lt;span class="na"&gt;root_id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;metrics-root&lt;/span&gt;  
          &lt;span class="na"&gt;vm_config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
            &lt;span class="na"&gt;vm_id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;metrics-vm&lt;/span&gt;  
            &lt;span class="na"&gt;runtime&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;envoy.wasm.runtime.v8&lt;/span&gt;  
            &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
              &lt;span class="na"&gt;remote&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
                &lt;span class="na"&gt;http_uri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
                  &lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://wasm-module-uri&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Extending Envoy with WebAssembly&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Envoy's functionality can be extended using custom filters written in different languages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;C++: Offers native, high-performance extensions but requires rebuilding Envoy.
&lt;/li&gt;
&lt;li&gt;Lua: Script-based, suitable for simpler use cases.
&lt;/li&gt;
&lt;li&gt;WebAssembly (Wasm): Enables run-time loaded plugins compiled from languages like Rust, Go, or AssemblyScript. Wasm plugins run in a sandboxed virtual machine (VM), providing isolation and memory safety.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wasm allows dynamic extensibility of the Envoy data plane without needing to rebuild Envoy or manually modify its configurations. Istio's istio-agent handles the distribution of Wasm plugins, fetching them from registries and mounting them into Envoy's file system.&lt;/p&gt;

&lt;p&gt;For example, in the Coffee Shop app: Use a WASM filter to collect metrics on espresso orders handled by barista-service. This plugin runs inside the Envoy proxy and logs telemetry data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuz2t3yxl0b7ejwtjmddr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuz2t3yxl0b7ejwtjmddr.png" alt="An image displaying flow in coffee shop app using WebAssembly" width="800" height="55"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In Istio, Wasm enables customization of the Envoy data plane without rebuilding or manually modifying Envoy configurations. It introduces dynamic extensibility to the mesh.&lt;/p&gt;

&lt;p&gt;Wasm Plugin Deployment Workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Compile Plugin&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Use your SDK to generate &lt;code&gt;.wasm&lt;/code&gt; file
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Publish to Registry&lt;/strong&gt;&lt;code&gt;docker build -t registry.io/barista-metrics:v1 . docker push registry.io/barista-metrics:v1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploy with WasmPlugin&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;extensions.istio.io/v1alpha1&lt;/span&gt;  
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;WasmPlugin&lt;/span&gt;  
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;barista-metrics&lt;/span&gt;  
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;coffee-shop&lt;/span&gt;  
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;barista-service&lt;/span&gt;  
  &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;oci://registry.io/barista-metrics:v1&lt;/span&gt;  
  &lt;span class="na"&gt;pluginConfig&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;trackEspresso&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;  
    &lt;span class="na"&gt;debug&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Plugin Source Options&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;oci://&lt;/code&gt;: OCI registry
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;http://&lt;/code&gt;: Direct HTTP URL
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/path/to/local&lt;/code&gt;: Local file path&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using &lt;code&gt;WasmPlugin&lt;/code&gt; is preferred over &lt;code&gt;EnvoyFilter&lt;/code&gt; as it simplifies deployment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5imsec4ljrrb79k3hno1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5imsec4ljrrb79k3hno1.png" alt="An image displaying OCI registry to Wasm Runtime." width="800" height="52"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Security&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Istio enhances security by enforcing strong authentication (AuthN) and authorization (AuthZ) policies.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Authentication&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Istio issues X.509 SPIFFE-compliant certificates to each pod, based on Kubernetes ServiceAccounts.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;mTLS&lt;/strong&gt;: Ensures both client and server verify each other’s identities.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Certificates&lt;/strong&gt;: Automatically rotated and managed by Istio agent using SDS.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1muvxvgvsd3nzv64hi61.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1muvxvgvsd3nzv64hi61.png" alt="An image displaying Authentication flow using coffee shop services." width="770" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automated Identity Provisioning&lt;/strong&gt;: Istio automates workload identity through these components:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Istio Agent&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Runs in the sidecar, manages certificates and bootstraps Envoy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SDS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Envoy’s Secret Discovery Service; fetches certs dynamically&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Istiod&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Acts as the Certificate Authority (CA); issues and rotates certs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;When a sidecar starts, the Istio agent sends a &lt;strong&gt;Certificate Signing Request (CSR)&lt;/strong&gt; to &lt;code&gt;istiod&lt;/code&gt;. Once verified, &lt;code&gt;istiod&lt;/code&gt; returns a signed certificate. This identity is used for secure communication between services. Certificates are rotated automatically.&lt;/p&gt;

&lt;p&gt;For example, in the coffee shop microservices app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;barista-service&lt;/code&gt; runs with a sidecar.
&lt;/li&gt;
&lt;li&gt;Istio agent requests a certificate for the &lt;code&gt;barista-service&lt;/code&gt; account.
&lt;/li&gt;
&lt;li&gt;CA authenticates the request and returns a signed certificate.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;barista-service&lt;/code&gt; uses this identity for secure communication.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Mutual TLS (mTLS)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Mutual TLS ensures encrypted and authenticated communication. Both client and server validate each other using their certificates. Envoy sidecars handle this process transparently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PeerAuthentication (Inbound)&lt;/strong&gt;: Configures the mTLS mode for incoming traffic to a service or workload.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;security.istio.io/v1beta1&lt;/span&gt;

&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PeerAuthentication&lt;/span&gt;

&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;

&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;mtls&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;STRICT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;DestinationRule (Outbound)&lt;/strong&gt;: Configures the mTLS mode for outgoing traffic from a service or workload. This also applies to outgoing traffic through an egress gateway.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;trafficPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
 &lt;span class="na"&gt;tls&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
   &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ISTIO_MUTUAL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;mTLS Modes Overview&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mode&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PERMISSIVE&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Accepts both plain text and mTLS connections (default for onboarding)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;STRICT&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Only mTLS connections are allowed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ISTIO_MUTUAL&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Uses Istio-managed certificates for mTLS (recommended default)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SIMPLE&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;One-way TLS (client verifies server)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;MUTUAL&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;mTLS using custom certificates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PASSTHROUGH&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Routes encrypted TLS traffic without termination&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AUTO_PASSTHROUGH&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Automatically forwards TLS based on SNI (no VirtualService required)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;:  You can apply mTLS at mesh, namespace, workload, or port level and these modes apply to both Ingress and Egress gateways.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; Set STRICT mTLS for payment-service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;security.istio.io/v1beta1&lt;/span&gt;

&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PeerAuthentication&lt;/span&gt;

&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;payment-service-mtls&lt;/span&gt;

  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;coffee-shop&lt;/span&gt;

&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;payment-service&lt;/span&gt;

  &lt;span class="na"&gt;mtls&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;STRICT&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcomyvgi7vuaiwwq3ablr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcomyvgi7vuaiwwq3ablr.png" alt="An image displaying flow from coffee-order to external payment-service." width="800" height="25"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request Authentication (User Authentication)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;RequestAuthentication&lt;/code&gt; to verify &lt;strong&gt;JWT tokens&lt;/strong&gt; from end users. If a token is invalid or missing, the request is rejected. Valid tokens yield an authenticated principal for policy enforcement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; Require JWT for customer-service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;security.istio.io/v1&lt;/span&gt;  
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;RequestAuthentication&lt;/span&gt;  
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;customer-jwt&lt;/span&gt;  
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;coffee-shop&lt;/span&gt;  
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;customer-service&lt;/span&gt;  
  &lt;span class="na"&gt;jwtRules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;\- issuer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://auth.coffeeshop.com"&lt;/span&gt;  
    &lt;span class="na"&gt;jwksUri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://auth.coffeeshop.com/.well-known/jwks.json"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Authorization (Access Control)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Use the &lt;code&gt;AuthorizationPolicy&lt;/code&gt; resource to enforce fine-grained control over what services or users can access. Policies use service identities (via mTLS) and user identities (via JWT).&lt;/p&gt;

&lt;p&gt;For example, only allow authenticated users to call customer-service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;security.istio.io/v1&lt;/span&gt;

&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AuthorizationPolicy&lt;/span&gt;

&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;require-jwt&lt;/span&gt;

  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;coffee-shop&lt;/span&gt;

&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;customer-service&lt;/span&gt;

  &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ALLOW&lt;/span&gt;

  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;\- from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;\- source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

        &lt;span class="na"&gt;requestPrincipals&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;\["\*"\]&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flu92y471g0lcgc3fv8uz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flu92y471g0lcgc3fv8uz.png" alt="An image displaying Authorization in Istio." width="800" height="30"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Match Conditions: Rules can match requests based on:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;from&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Source identity: service accounts, IPs, JWT principals&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;to&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Operation match: HTTP methods, ports, paths&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;when&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Additional conditions: headers, claims, IPs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: Allow DELETE only from admin-service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
&lt;span class="na"&gt;\- from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;\- source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;principals&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;\["spiffe://cluster.local/ns/coffee-shop/sa/admin-service"\]&lt;/span&gt;  
  &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;\- operation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;methods&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;\["DELETE"\]&lt;/span&gt;  
      &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;\["/customers/\*"\]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Action Types in &lt;code&gt;AuthorizationPolicy&lt;/code&gt;:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ALLOW&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Permit matching requests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DENY&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Block matching requests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CUSTOM&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Delegate evaluation to a custom extension&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;AUDIT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Log matching requests without enforcing access decisions&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Istio evaluates policies in this order: &lt;code&gt;CUSTOM&lt;/code&gt; → &lt;code&gt;DENY&lt;/code&gt; → &lt;code&gt;ALLOW&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Best Practices&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Start with a &lt;strong&gt;DENY-all&lt;/strong&gt; policy and incrementally allow access using &lt;code&gt;ALLOW&lt;/code&gt; rules.
&lt;/li&gt;
&lt;li&gt;Assign &lt;strong&gt;dedicated ServiceAccounts&lt;/strong&gt; per workload to ensure identity isolation.
&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;STRICT&lt;/code&gt; mTLS once workloads are mesh-ready.
&lt;/li&gt;
&lt;li&gt;Combine &lt;code&gt;PeerAuthentication&lt;/code&gt;, &lt;code&gt;RequestAuthentication&lt;/code&gt;, and &lt;code&gt;AuthorizationPolicy&lt;/code&gt; for zero-trust enforcement.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Observability&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Observability is essential for understanding and operating microservices in production. Istio provides out-of-the-box observability by capturing telemetry at the network layer through sidecar proxies.&lt;/p&gt;

&lt;p&gt;Istio enables deep insights across services by capturing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Metrics&lt;/strong&gt;: Quantitative measurements such as request latency or error rates.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Traces&lt;/strong&gt;: End-to-end request flow across services.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logs&lt;/strong&gt;: Context-rich records for debugging.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These signals work together. For example, a spike in latency (metrics) leads you to a specific service call (trace), and the logs explain the failure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: For more information, refer to &lt;a href="https://programmerprodigy.code.blog/2025/06/04/understanding-observability-with-opentelemetry-and-coffee/" rel="noopener noreferrer"&gt;Understanding Observability with OpenTelemetry and Coffee&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For the coffee shop example,the coffee shop app has three microservices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;order-service
&lt;/li&gt;
&lt;li&gt;payment-service
&lt;/li&gt;
&lt;li&gt;inventory-service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each service includes an injected Envoy sidecar that automatically collects and exposes telemetry.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Setup for Observability&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Install Istio using the &lt;code&gt;demo&lt;/code&gt; profile to enable full telemetry:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;istioctl install \--set profile=demo \-y&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This profile enables 100% trace sampling—ideal for development. In production, reduce sampling to 1% to balance overhead.&lt;/p&gt;

&lt;p&gt;Envoy sidecars expose Prometheus scrape endpoints. Metrics can also be accessed via each pod’s Envoy admin dashboard.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmcopkzd1e1cit3teucl7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmcopkzd1e1cit3teucl7.png" alt="An image displaying Observability in coffee pod using Istio, SigNoz, Prometheus, and Grafana" width="800" height="204"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Tracing and Logs with SigNoz&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;SigNoz is an OpenTelemetry-compatible observability tool that integrates seamlessly with Istio:&lt;/p&gt;

&lt;p&gt;helm install signoz signoz/signoz -n platform&lt;/p&gt;

&lt;p&gt;You can use the SigNoz UI to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Search for traces by service (e.g., &lt;code&gt;order-service&lt;/code&gt;)
&lt;/li&gt;
&lt;li&gt;Visualize trace duration and latency
&lt;/li&gt;
&lt;li&gt;Correlate logs and spans&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Refer to &lt;a href="https://signoz.io/docs" rel="noopener noreferrer"&gt;SigNoz Installation Guide&lt;/a&gt; for setup instructions.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Optimization and Advanced Deployments&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In large meshes, every sidecar receives service discovery updates for all mesh services. This can lead to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Excessive configuration updates
&lt;/li&gt;
&lt;li&gt;Increased startup time for proxies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To limit this, use the &lt;code&gt;Sidecar&lt;/code&gt; resource to restrict which services a workload can see.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8qz9v3k9pv1612nrj1ir.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8qz9v3k9pv1612nrj1ir.png" alt="An image displaying optimization of coffee app mesh" width="694" height="251"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, a Sidecar resource can restrict outbound traffic (egress) from a coffee-frontend workload to only communicate with order-service and payment-service within its namespace.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.istio.io/v1beta1&lt;/span&gt;  
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Sidecar&lt;/span&gt;  
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;coffee-frontend&lt;/span&gt;  
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;coffee-shop&lt;/span&gt;  
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;workloadSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;coffee-frontend&lt;/span&gt;  
  &lt;span class="na"&gt;egress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;\- hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="s"&gt;\- "order-service.coffee-shop.svc.cluster.local"&lt;/span&gt;  
    &lt;span class="s"&gt;\- "payment-service.coffee-shop.svc.cluster.local"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This configuration allows &lt;code&gt;coffee-frontend&lt;/code&gt; to communicate only with &lt;code&gt;order-service&lt;/code&gt; and &lt;code&gt;payment-service&lt;/code&gt;, reducing its load.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Multi-Cluster Deployments&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Deploying Istio across multiple Kubernetes clusters offers benefits such as high availability, failover capabilities, and organizational separation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Network Models:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Single Network: Pods across different clusters can communicate directly.
&lt;/li&gt;
&lt;li&gt;Multiple Networks: East-west gateways are used to facilitate communication between clusters.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyqfrhs95x86szvgtcx79.png" alt="An image displaying multiple networks connected by East-west gateway." width="679" height="63"&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Control Plane Models:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Single Control Plane: A single Istiod instance manages all clusters. While simpler, it represents a single point of failure.
&lt;/li&gt;
&lt;li&gt;Per-Cluster Control Plane: Each cluster has its own Istiod instance, providing better high availability and isolation.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Mesh Models:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Single Mesh: A unified trust domain and configuration across all clusters.
&lt;/li&gt;
&lt;li&gt;Multi-Mesh Federation: Separate meshes can share trust bundles (root certificates), define shared ServiceEntry resources, and apply AuthorizationPolicy for secure cross-mesh communication.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Tenancy Models:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Soft Tenancy: Achieves isolation at the namespace level.
&lt;/li&gt;
&lt;li&gt;Hard Tenancy: Provides isolation at the cluster level with separate meshes.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Locality-Aware Load Balancing:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;localityLbSetting&lt;/code&gt; to steer traffic based on geographic proximity (region, zone, sub-zone).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Failover Example&lt;/strong&gt;: If all endpoints in &lt;code&gt;us-west&lt;/code&gt; are unavailable, traffic fails over to &lt;code&gt;us-east&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;trafficPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;localityLbSetting&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

    &lt;span class="na"&gt;failover&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

      &lt;span class="na"&gt;\- from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;us-west&lt;/span&gt;

        &lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;us-east&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Weighted Distribution&lt;/strong&gt;: This routes 50% of the traffic to local zone &lt;code&gt;us-west1-a&lt;/code&gt;, 30% to the neighboring zone, and 20% to a remote zone.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;trafficPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;localityLbSetting&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

    &lt;span class="na"&gt;distribute&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

      &lt;span class="na"&gt;\- from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;us-west1/us-west1-a/&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt;

        &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

          &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;us-west1/us-west1-a/&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;

          &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;us-west1/us-west1-b/&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;

          &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;us-east1/us-east1-a/&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Wrapping Up: Istio as Your Mesh Barista&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Istio helps transform your distributed microservices from a tangle of complexity into a well-orchestrated system. Whether it's fine-grained traffic routing, observability across services, enforcing security through mTLS, or extending the mesh with WebAssembly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fis795yzgzpsydodj4oq4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fis795yzgzpsydodj4oq4.png" alt="Summary image of the coffee shop with WebAssembly." width="800" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Like a well-run coffee shop, every component of your system needs to collaborate in real time. Istio acts as the operations manager behind the scenes, ensuring communication flows smoothly, issues are detected early, and only trusted interactions are allowed.&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>architecture</category>
      <category>servicemesh</category>
      <category>observability</category>
    </item>
    <item>
      <title>Understanding Observability with OpenTelemetry and Coffee</title>
      <dc:creator>hridyesh bisht</dc:creator>
      <pubDate>Wed, 04 Jun 2025 16:39:38 +0000</pubDate>
      <link>https://dev.to/hridyeshbisht/understanding-observability-with-opentelemetry-and-coffee-19l1</link>
      <guid>https://dev.to/hridyeshbisht/understanding-observability-with-opentelemetry-and-coffee-19l1</guid>
      <description>&lt;p&gt;Solutions are increasingly built using microservices architecture, leading to complex distributed systems. Monitoring these systems becomes challenging due to the diversity of tools, protocols, and data formats. &lt;/p&gt;

&lt;p&gt;This blog focuses on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Explaining the basics of OpenTelemetry, its role in observability, and the current state of observability in the industry.
&lt;/li&gt;
&lt;li&gt;Explaining how to instrument code and identify when to use manual and automatic instrumentation.
&lt;/li&gt;
&lt;li&gt;Discussing the OpenTelemetry Collector and Connector, which are responsible for processing and forwarding telemetry data.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What is OpenTelemetry?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;OpenTelemetry addresses these challenges by providing a unified framework for collecting, processing, and exporting telemetry data, enabling you to gain deep insights into their apps’ behavior.&lt;/p&gt;

&lt;p&gt;For this guide, consider a modern coffee shop app with the following microservices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Order Service&lt;/strong&gt;: Handles customer orders.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Payment Service&lt;/strong&gt;: Processes payments.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inventory Service&lt;/strong&gt;: Manages stock levels.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notification Service&lt;/strong&gt;: Sends order confirmations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2tfjtu5xm0mxzbcjn1i7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2tfjtu5xm0mxzbcjn1i7.png" alt="An visual asset displaying flow of data from Service -&gt; OTel Collector -&gt; Observability Backend" width="800" height="297"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each service operates independently, possibly written in different languages and deployed across various environments. When a customer places an order, the request traverses multiple services, making it essential to have a comprehensive observability solution to monitor and troubleshoot the system effectively. &lt;/p&gt;

&lt;p&gt;Key Benefits of OpenTelemetry:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unified Instrumentation&lt;/strong&gt;: Instrument your code once and send telemetry data to multiple backends without re-instrumentation.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vendor-Neutral&lt;/strong&gt;: Avoid vendor lock-in by using standard APIs and protocols. Since you can switch platforms without having to re-instrument your entire solution.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unified telemetry:&lt;/strong&gt; Combines tracing, logging, and metrics into a single framework enabling correlation of all data and establishing an open standard for telemetry data.

&lt;ul&gt;
&lt;li&gt;Linking these parameters helps you make better decisions.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Community-Driven&lt;/strong&gt;: Benefit from a vibrant open-source community contributing to continuous improvements.
&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Improved Correlation&lt;/strong&gt;: Easily correlate data across different telemetry signals for better insights.&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Three pillars of Observability&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Telemetry is collected via instrumentation and flows through a pipeline that enriches, batches, and stores it for later analysis. Most observability tooling revolves around three categories of telemetry: &lt;strong&gt;logs, metrics, and traces&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;While they share architectural similarities, such as instrumentation, ingestion, storage, and visualization. Each type presents unique challenges and is best suited to answer different types of questions.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Logs&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Logs are immutable, timestamped records of discrete events. Each log entry typically contains a message and optional structured metadata. However, coming up with a standardized log format is no easy task, since different pieces of information are critical for different types of software. &lt;/p&gt;

&lt;p&gt;You can also build logging agents and protocols to forward logs  to a central location for efficient storage. For example, consider  a user placing an order in a microservices-based coffee shop app. The order-service logs a line like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;{&lt;/span&gt;  
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;timestamp"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2025-06-01T08:43:12Z"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;  
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;level"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;INFO"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;  
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;service"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;order-service"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;  
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;New&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;order&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;placed:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;latte"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;  
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;order&lt;/span&gt;&lt;span class="se"&gt;\_&lt;/span&gt;&lt;span class="s"&gt;id"&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ORD-20250601-001"&lt;/span&gt;  
&lt;span class="pi"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Metrics&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Metrics help you understand a high-level view of the current state of your system. A metric is a single numerical value derived by applying a statistical measure to a group of events. &lt;/p&gt;

&lt;p&gt;In other words, metrics represent an aggregate. This is useful because their compact representation allows us to graph how a system changes over time. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Different Metric Types:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Counters:&lt;/strong&gt; Total number of orders placed
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gauges:&lt;/strong&gt; Current number of in-progress orders
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Histograms:&lt;/strong&gt; Distribution of order preparation times
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Summaries:&lt;/strong&gt; Quantiles of response times&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Coffee Shop Example*&lt;em&gt;:&lt;/em&gt;*  The order-service emits a metric would be displayed.&lt;/p&gt;

&lt;p&gt;orders_placed_total{beverage=”latte”} 1560&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmm2i32q88y1zuiliob17.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmm2i32q88y1zuiliob17.png" alt="A visual asset displaying Metrics agent sending data to Prometheus DB and then Grafana Dashboard." width="800" height="57"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A Prometheus dashboard may show a sharp spike in latte orders, suggesting a promotional campaign is working or an anomaly is occurring.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Traces&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To understand the larger context in distributed solution, you must identify other related events, such as the specific requests or transactions that initiated the log entry and the sequence of services or microservices involved in processing that request across the system. &lt;/p&gt;

&lt;p&gt;Traces visualize the full journey of a single request across services. A trace consists of multiple &lt;strong&gt;spans&lt;/strong&gt;, each representing a step in the request’s lifecycle. This makes it possible to reconstruct the journey of requests in the system.&lt;/p&gt;

&lt;p&gt;Coffee Shop Example*&lt;em&gt;:&lt;/em&gt;*  A user places an order. The request flows through UI -&amp;gt; order-service -&amp;gt; payment-service -&amp;gt; inventory-service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe5coseuoqikbeextnoxp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe5coseuoqikbeextnoxp.png" alt="A visual asset displaying flow of request through UI-&gt; order-service -&gt; payment-service -&gt; inventory-service." width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each service adds a span with trace and span IDs, allowing you to view:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Total request duration
&lt;/li&gt;
&lt;li&gt;Which service caused a delay
&lt;/li&gt;
&lt;li&gt;Any failed steps in the chain&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Problems with the Current Observability Approach&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Logs, metrics, and traces typically live in separate systems, with different formats and tooling. This fragmentation forces you to jump between dashboards and correlate data manually. Even with shared metadata like timestamps or service names, stitching information together remains time-consuming and error-prone.&lt;/p&gt;

&lt;p&gt;Coffee Shop Example: Imagine a spike in failed order-service requests. You check metrics and see a high error rate. You then switch to logs, scan for failures, and try to match logs with trace IDs. Without consistent context, root cause analysis becomes guesswork.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Lack of Built-in Instrumentation in Open Source Software&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Many open source libraries expose hooks but do not include native telemetry support. You must build and maintain custom adapters.&lt;/p&gt;

&lt;p&gt;Problems this causes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Version Compatibility:&lt;/strong&gt; Library updates may break adapters.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Telemetry Loss:&lt;/strong&gt; Converting data between formats can degrade signal quality.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Engineering Overhead:&lt;/strong&gt; Teams spend time wiring telemetry instead of building features.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Coffee Shop Example*&lt;em&gt;:&lt;/em&gt;* If the inventory-service uses a third-party stock manager with no OpenTelemetry support, you must manually instrument it or depend on its observability hooks.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What OpenTelemetry is NOT&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;OpenTelemetry simplifies telemetry collection and export, but it doesn’t offer end-to-end observability out of the box. It’s a toolkit, not a monitoring platform.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Not OpenTelemetry’s Job&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;OpenTelemetry exports data; it doesn’t store it. You’ll need systems like SigNoz, Prometheus, or Elasticsearch.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Visualization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No dashboards or charts are included. Use tools like Grafana, Jaeger, or Datadog.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Alerting&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;OpenTelemetry doesn’t generate alerts. Integrate it with systems that support alert rules.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Monitoring out-of-the-box&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;It doesn’t auto-instrument everything or provide prebuilt dashboards. You must configure and integrate.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Performance optimization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;It helps identify bottlenecks, but doesn’t tune your app.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;OpenTelemetry standardizes how you collect logs, metrics, and traces. It enables observability, but doesn’t deliver it on its own. You still need storage, visualization, alerting, and analysis platforms to complete the picture.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Signals in OpenTelemetry&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;OpenTelemetry organizes observability data into three core signals:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Traces&lt;/td&gt;
&lt;td&gt;Capture the lifecycle and flow of a request across services.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Metrics&lt;/td&gt;
&lt;td&gt;Measure system and app performance over time.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Logs&lt;/td&gt;
&lt;td&gt;Record discrete events and state changes in the app.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each signal is independent but can be correlated to provide richer observability. OpenTelemetry’s architecture ensures signal consistency and interoperability across programming languages through its official OpenTelemetry Specification.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ek8wkxixvh6qyxhu3hf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ek8wkxixvh6qyxhu3hf.png" alt="A visual asset displaying flow of data in OpenTelemetry Specifications" width="800" height="24"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;OpenTelemetry Specification Components&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Common Terminology&lt;/strong&gt;: Ensures a consistent vocabulary across implementations.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API Specification&lt;/strong&gt;: Provides language-agnostic interfaces to generate telemetry (traces, metrics, logs). APIs are backend-agnostic and enable portable instrumentation.

&lt;ul&gt;
&lt;li&gt;For more information, refer to &lt;a href="https://opentelemetry.io/docs/specs/otel/trace/api/" rel="noopener noreferrer"&gt;&lt;strong&gt;Tracing API&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://opentelemetry.io/docs/specs/otel/metrics/api/" rel="noopener noreferrer"&gt;&lt;strong&gt;Metrics API&lt;/strong&gt;&lt;/a&gt;, and &lt;a href="https://opentelemetry.io/docs/specs/otel/logs/" rel="noopener noreferrer"&gt;&lt;strong&gt;OpenTelemetry Logging&lt;/strong&gt;&lt;/a&gt;.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;SDK Specification&lt;/strong&gt;: Defines how SDKs process, sample, and export telemetry. Ensures consistent behavior across languages.

&lt;ul&gt;
&lt;li&gt;For more information, refer to &lt;a href="https://opentelemetry.io/docs/specs/otel/trace/sdk/" rel="noopener noreferrer"&gt;&lt;strong&gt;Tracing SDK&lt;/strong&gt;&lt;/a&gt;, &lt;a href="https://opentelemetry.io/docs/specs/otel/metrics/sdk/" rel="noopener noreferrer"&gt;&lt;strong&gt;Metrics SDK&lt;/strong&gt;&lt;/a&gt;, and &lt;a href="https://opentelemetry.io/docs/specs/otel/logs/sdk/" rel="noopener noreferrer"&gt;&lt;strong&gt;Logs SDK&lt;/strong&gt;&lt;/a&gt;.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Semantic Conventions&lt;/strong&gt;: Standardizes names and attributes for telemetry data (e.g., HTTP status codes, DB queries).
&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;OpenTelemetry Protocol (OTLP)&lt;/strong&gt;: Describes a vendor-neutral transport protocol to send telemetry &lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why separate API from SDK?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;API–SDK split&lt;/strong&gt; improves &lt;strong&gt;modularity, portability, and vendor neutrality&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Library safety&lt;/strong&gt;: A shared library (e.g., database driver) can safely include only the API, avoiding heavy SDK dependencies and avoiding conflicts in user apps.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Portability&lt;/strong&gt;: You can ship apps with OpenTelemetry APIs baked in, and let platform teams decide which SDK/exporter to use later.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility&lt;/strong&gt;: You can write your own SDK or replace components (e.g., use a custom sampler or exporter).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;OpenTelemetry API vs SDK&lt;/strong&gt;
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;OpenTelemetry API&lt;/th&gt;
&lt;th&gt;OpenTelemetry SDK&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Purpose&lt;/td&gt;
&lt;td&gt;Defines interfaces to generate telemetry&lt;/td&gt;
&lt;td&gt;Implements logic to process and export telemetry&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Responsibility&lt;/td&gt;
&lt;td&gt;Exposes functions to create spans, metrics, logs&lt;/td&gt;
&lt;td&gt;Manages batching, sampling, context, and export&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Language-specific?&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Included by default?&lt;/td&gt;
&lt;td&gt;Yes, lightweight&lt;/td&gt;
&lt;td&gt;No, must be explicitly added and configured&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Default behavior&lt;/td&gt;
&lt;td&gt;No-op&lt;/td&gt;
&lt;td&gt;Active when configured&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Used by&lt;/td&gt;
&lt;td&gt;App and library developers&lt;/td&gt;
&lt;td&gt;DevOps, SREs, platform engineers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stability&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;May evolve with backends and exporter needs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Customizable&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (exporters, processors, samplers)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For example,  consider the following scenarios:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Best choice&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Open-source library with tracing support&lt;/td&gt;
&lt;td&gt;API only (lightweight, no deps)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Production microservice exporting to Grafana&lt;/td&gt;
&lt;td&gt;API + SDK + OTLP Exporter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CLI tool needing optional debug tracing&lt;/td&gt;
&lt;td&gt;API (enabled conditionally with SDK)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;How to Instrument Code with OpenTelemetry&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;OpenTelemetry supports multiple instrumentation approaches to capture telemetry from apps. Understanding these methods helps choose the right approach based on your app’s complexity, development stage, and observability goals.&lt;/p&gt;

&lt;p&gt;OpenTelemetry classifies instrumentation into three categories, often overlapping in practice:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Effort&lt;/th&gt;
&lt;th&gt;Control&lt;/th&gt;
&lt;th&gt;Customization&lt;/th&gt;
&lt;th&gt;Code Changes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Automatic Instrumentation (Zero-Code)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Minimal&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Instrumentation Libraries&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;td&gt;Minimal to moderate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Manual Instrumentation (Fully Code-Based)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Full&lt;/td&gt;
&lt;td&gt;Full&lt;/td&gt;
&lt;td&gt;Extensive&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;OpenTelemetry provides three ways to capture telemetry from your app:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Automatic Instrumentation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Auto-instrumentation in .NET 8 is available via the &lt;strong&gt;OpenTelemetry .NET Auto-Instrumentation Agent&lt;/strong&gt;, which instruments common libraries like ASP.NET Core, HttpClient, and SQL clients at runtime.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ideal use case:&lt;/strong&gt; Use this to quickly add observability to .NET services without modifying source code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: orders-service (.NET 8, ASP.NET Core)&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download and install the auto-instrumentation binaries  &lt;a href="https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation" rel="noopener noreferrer"&gt;&lt;strong&gt;.NET Auto-Instrumentation GitHub&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Run the app with the auto-instrumentation profiler
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;set &lt;/span&gt;&lt;span class="nv"&gt;OTEL_SERVICE_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;orders-service
&lt;span class="nb"&gt;set &lt;/span&gt;&lt;span class="nv"&gt;OTEL_EXPORTER_OTLP_ENDPOINT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://otel-collector:4317
&lt;span class="nb"&gt;set &lt;/span&gt;&lt;span class="nv"&gt;CORECLR_ENABLE_PROFILING&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;span class="nb"&gt;set &lt;/span&gt;&lt;span class="nv"&gt;CORECLR_PROFILER_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;C:&lt;span class="se"&gt;\o&lt;/span&gt;tel-dotnet auto&lt;span class="se"&gt;\O&lt;/span&gt;penTelemetry.AutoInstrumentation.Native.dll
dotnet run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What it captures:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTTP requests and responses
&lt;/li&gt;
&lt;li&gt;Outgoing HTTP/gRPC calls
&lt;/li&gt;
&lt;li&gt;SQL queries via ADO.NET&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No code changes required
&lt;/li&gt;
&lt;li&gt;Fast onboarding
&lt;/li&gt;
&lt;li&gt;Works well for ASP.NET Core, Entity Framework, and HttpClient&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Limited to supported libraries
&lt;/li&gt;
&lt;li&gt;Less control over span names and metadata&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Library-Based Instrumentation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Library-based instrumentation uses the OpenTelemetry SDK and prebuilt instrumentations like AddAspNetCoreInstrumentation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ideal use case:&lt;/strong&gt; You want to customize configuration and capture high-value signals without full manual control.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: menu-service (.NET 8, ASP.NET Core)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Install NuGet packages:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet add package OpenTelemetry.Extensions.Hosting
dotnet add package OpenTelemetry.Instrumentation.AspNetCore
dotnet add package OpenTelemetry.Instrumentation.Http
dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Configure in Program.cs:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;OpenTelemetry.Metrics&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;OpenTelemetry.Resources&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;OpenTelemetry.Trace&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddOpenTelemetry&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithTracing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tracerProviderBuilder&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;tracerProviderBuilder&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetResourceBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;ResourceBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateDefault&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"menu-service"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddAspNetCoreInstrumentation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddHttpClientInstrumentation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddOtlpExporter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;otlp&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;otlp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Endpoint&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http://otel-collector:4317"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;MapGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Hello from Menu Service"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What it captures:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inbound ASP.NET Core request spans
&lt;/li&gt;
&lt;li&gt;Outbound calls (HttpClient, gRPC)
&lt;/li&gt;
&lt;li&gt;Custom span and resource metadata&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy to configure
&lt;/li&gt;
&lt;li&gt;Integrates well with DI and hosting model
&lt;/li&gt;
&lt;li&gt;Supports enrichment and filtering&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requires adding code/configuration
&lt;/li&gt;
&lt;li&gt;Less flexible than full manual instrumentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. Manual Instrumentation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Manual instrumentation lets you define custom spans for critical business logic (e.g., awarding loyalty points or calculating discounts).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ideal use case:&lt;/strong&gt; You need to trace domain-specific logic not covered by auto or library-based methods.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: loyalty-service (.NET 8 Worker Service)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Install packages:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet add package OpenTelemetry
dotnet add package OpenTelemetry.Trace
dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Configure tracing in Program.cs:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;OpenTelemetry.Trace&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;OpenTelemetry.Resources&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Diagnostics&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateApplicationBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddOpenTelemetry&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithTracing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tracerProviderBuilder&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;tracerProviderBuilder&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetResourceBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ResourceBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateDefault&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;AddService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"loyalty-service"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"LoyaltyService"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddOtlpExporter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Endpoint&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http://otel-collector:4317"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Start a custom span manually&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ActivitySource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"LoyaltyService"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;activity&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StartActivity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"AwardLoyaltyPoints"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ActivityKind&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Internal&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;activity&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;SetTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"customer.id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"cust-123"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;activity&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;SetTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"points.awarded"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Simulate business logic&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Loyalty points awarded."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What it captures:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Custom spans for logic like point calculations
&lt;/li&gt;
&lt;li&gt;Rich metadata (tags)
&lt;/li&gt;
&lt;li&gt;Correlation with other telemetry (metrics/logs)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full control over telemetry
&lt;/li&gt;
&lt;li&gt;Capture domain-specific operations
&lt;/li&gt;
&lt;li&gt;High value for debugging or performance tuning&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requires development effort
&lt;/li&gt;
&lt;li&gt;Must manage span lifecycle correctly
&lt;/li&gt;
&lt;li&gt;Potential for inconsistent usage without guidelines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff7z79zmtpkmzfa5ijao0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff7z79zmtpkmzfa5ijao0.png" alt="A visual asset displaying three ways to capture telemetry from your app and send it to OLTP" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Overlaps and Clarifications&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Instrumentation libraries sometimes provide automatic instrumentation after import, blurring the line between zero-code and code-based.
&lt;/li&gt;
&lt;li&gt;Under the hood, all approaches use some form of libraries.
&lt;/li&gt;
&lt;li&gt;Zero-code is broad and quick; libraries add customization; manual is full control.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Recommended Approach and Strategy&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Start with automatic instrumentation&lt;/strong&gt; to gain immediate insight with minimal effort.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add instrumentation libraries&lt;/strong&gt; where you need more coverage or framework-specific tracing.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use manual instrumentation&lt;/strong&gt; for critical business logic or custom metrics requiring fine-grained control.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Why use OpenTelemetry Collector?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The OpenTelemetry Collector is a vendor-agnostic, standalone service that simplifies telemetry management in production. It decouples telemetry generation from ingestion and export, offering the following benefits:&lt;/p&gt;

&lt;p&gt;The Collector provides three core capabilities:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Function&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Receive&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Accepts telemetry from apps, agents, or other Collectors via OTLP or other supported protocols.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Process&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Filters, enriches, transforms, batches, or samples telemetry data.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Export&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Sends processed data to one or more observability backends.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzb8j66uwczcz8sefuzau.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzb8j66uwczcz8sefuzau.png" alt="A visual asset displaying information sent from OTel Collector to Prometheus, Jaeger and S3" width="800" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Key benefits&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Without Collector&lt;/th&gt;
&lt;th&gt;With Collector&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Apps must export data directly to each backend&lt;/td&gt;
&lt;td&gt;Central point of control for all telemetry&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Risk of tight coupling to backend protocols&lt;/td&gt;
&lt;td&gt;Decouples app logic from backend details&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Difficult to enforce consistent processing&lt;/td&gt;
&lt;td&gt;Apply transformations consistently&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No central routing or batching&lt;/td&gt;
&lt;td&gt;Route and batch data efficiently&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Understanding OpenTelemetry Protocol (OTLP)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;OTLP&lt;/strong&gt; is the &lt;strong&gt;native telemetry transport&lt;/strong&gt; used across OpenTelemetry. It standardizes how telemetry is serialized, transmitted, and received.&lt;/p&gt;

&lt;p&gt;Key benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unified&lt;/strong&gt;: Handles traces, metrics, and logs in one format.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vendor-neutral&lt;/strong&gt;: Reduces backend lock-in and removes custom exporters.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Efficient&lt;/strong&gt;: Uses &lt;strong&gt;gRPC&lt;/strong&gt; and &lt;strong&gt;Protobuf&lt;/strong&gt; for high-performance streaming.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extensible&lt;/strong&gt;: Schema evolves without breaking compatibility.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integrated&lt;/strong&gt;: Collector and most observability tools support OTLP out of the box.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OTLP transport options&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Transport&lt;/th&gt;
&lt;th&gt;Encoding&lt;/th&gt;
&lt;th&gt;Use case&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;gRPC&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Protobuf&lt;/td&gt;
&lt;td&gt;Default for performance and bi-directional streaming&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;HTTP/1.1&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;JSON&lt;/td&gt;
&lt;td&gt;Debugging, human-readable payloads&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;HTTP/2&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Protobuf&lt;/td&gt;
&lt;td&gt;Efficient, firewall-friendly alternative to gRPC&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Example: Pre-OTLP &lt;em&gt;vs&lt;/em&gt; OTLP&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Before OTLP&lt;/th&gt;
&lt;th&gt;With OTLP&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Prometheus exporter, Zipkin exporter, Fluentd plugin&lt;/td&gt;
&lt;td&gt;One OTLP exporter and one Collector instance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multiple exporters in each service&lt;/td&gt;
&lt;td&gt;Centralized, simplified telemetry pipeline&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In OpenTelemetry, logs are a critical signal for observability. Any data that isn’t a trace or metric is categorized as a log. Events, for instance, are specialized log entries.&lt;/p&gt;

&lt;p&gt;Unlike traces and metrics, which OpenTelemetry implements via dedicated APIs and SDKs, logging is designed to integrate with existing logging frameworks in various programming languages. Instead of requiring a brand-new logging API, OpenTelemetry provides a &lt;strong&gt;Logs Bridge API&lt;/strong&gt; that links traditional logging systems with telemetry signals such as traces and metrics.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;How Logging Works in OpenTelemetry&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You instrument logging using the &lt;strong&gt;Logs Bridge API&lt;/strong&gt;, which connects popular logging frameworks (like Serilog, ILogger, or log4net in .NET) to OpenTelemetry’s pipeline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Components&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;LoggerProvider&lt;/strong&gt;: Factory for creating loggers.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logger&lt;/strong&gt;: Used to create log entries (LogRecord).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LogRecord&lt;/strong&gt;: Represents a single log entry with metadata.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LogRecordExporter&lt;/strong&gt;: Sends logs to destinations like the OpenTelemetry Collector.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LogRecordProcessor&lt;/strong&gt;: Processes logs before they’re exported.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;LogRecord Structure&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A LogRecord typically includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;timestamp: When the log occurred.
&lt;/li&gt;
&lt;li&gt;trace_id, span_id: Links to a trace/span for correlation.
&lt;/li&gt;
&lt;li&gt;severity_text: e.g., INFO, WARNING, ERROR.
&lt;/li&gt;
&lt;li&gt;body: The log message or structured content.
&lt;/li&gt;
&lt;li&gt;attributes: Custom metadata (e.g., user.id, http.method).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftn5az021i18hbvug2sbr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftn5az021i18hbvug2sbr.png" alt="A visual asset displaying flow of logs from OpenTelemetry Logging module" width="800" height="25"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example Use Case&lt;/strong&gt;: Coffee app has a /get_coffee endpoint. When a coffee request fails due to a missing ID, the app logs this event.&lt;/p&gt;

&lt;p&gt;logger.error(“Missing coffee ID”, extra={“http.status_code”: 400, “coffee_id”: None})&lt;/p&gt;

&lt;p&gt;This log entry can be linked to the trace of the request, helping correlate the failure with upstream service calls and backend metrics.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Collector Configuration&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The OpenTelemetry Collector decouples telemetry generation from backend concerns. It processes logs, traces, and metrics independently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Collector Pipeline Example&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;receivers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;otlp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;protocols&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;grpc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;


&lt;span class="na"&gt;processors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;batch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;


&lt;span class="na"&gt;exporters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;logging&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;loglevel&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;debug&lt;/span&gt;


&lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pipelines&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;logs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;receivers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;otlp&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;processors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;batch&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;exporters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;logging&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Collector Deployment Topologies&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The OpenTelemetry Collector supports multiple deployment models, allowing you to tailor observability pipelines based on your architecture and scalability needs. Each topology serves different use cases—from tightly coupled microservices to centralized processing in large-scale environments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sidecar Deployment :&lt;/strong&gt; OpenTelemetry Collector runs &lt;strong&gt;as a sidecar&lt;/strong&gt; alongside each application instance. This setup is common in containerized environments like Kubernetes, where the Collector is injected into each Pod.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqe6ofltku5dt4ee2rtv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqe6ofltku5dt4ee2rtv.png" alt="A visual asset displaying Sidecar Deployment in OpenTelemetry Collector" width="635" height="158"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Low latency:&lt;/strong&gt; The Collector runs on the same host or Pod, reducing network overhead for exporting telemetry data.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Isolation:&lt;/strong&gt; Each service has a dedicated Collector instance, ensuring telemetry data stays service-specific and avoids cross-contamination.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplified trace correlation:&lt;/strong&gt; Local logs, traces, and metrics can be more easily linked.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ideal for &lt;strong&gt;microservices architectures&lt;/strong&gt; where services operate independently and require individual telemetry pipelines.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Node Agent Deployment:&lt;/strong&gt; a single Collector instance runs per host or node. This is typically implemented as a &lt;strong&gt;Kubernetes DaemonSet&lt;/strong&gt; or similar system service in virtual machine environments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff39agp28mqlkm92w0rwr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff39agp28mqlkm92w0rwr.png" alt="A visual asset displaying Node Agent Deployment in OpenTelemetry Collector" width="630" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Centralized control per node:&lt;/strong&gt; One Collector handles telemetry for all services on the same node.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource-efficient:&lt;/strong&gt; Fewer Collector instances are required compared to the sidecar model.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;System metrics access:&lt;/strong&gt; Can collect host-level metrics (CPU, memory, disk, etc.) in addition to application telemetry.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Ideal Use Case:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Suitable for &lt;strong&gt;clusters with many lightweight services&lt;/strong&gt; that share node resources.
&lt;/li&gt;
&lt;li&gt;Often used to monitor &lt;strong&gt;node-level infrastructure and runtime metrics&lt;/strong&gt; alongside service-level data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Standalone or Gateway Deployment&lt;/strong&gt;: The Collector runs as a &lt;strong&gt;dedicated service&lt;/strong&gt;, often behind a load balancer. Applications send telemetry data remotely to this central Collector (typically over OTLP).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2sz3cq53gld3hrdkeopu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2sz3cq53gld3hrdkeopu.png" alt="A visual asset displaying Standalone Deployment in OpenTelemetry Collector" width="800" height="319"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scalability:&lt;/strong&gt; A centralized Collector cluster can scale independently from application workloads.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplified configuration management:&lt;/strong&gt; Telemetry pipelines and transformations are managed in one place.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decoupling from application logic:&lt;/strong&gt; Developers don’t need to worry about backend changes or exporter configurations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Ideal Use Case:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Best suited for &lt;strong&gt;large-scale systems&lt;/strong&gt; with high telemetry volume.
&lt;/li&gt;
&lt;li&gt;Useful for teams that want to &lt;strong&gt;offload all processing from applications&lt;/strong&gt; and maintain a consistent observability architecture.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Benefits of OpenTelemetry Collectors&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Separation of concerns&lt;/strong&gt;: Developers emit logs; operators manage pipelines.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Centralized management&lt;/strong&gt;: All configuration is in one place.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource efficiency&lt;/strong&gt;: Offloads processing from app.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No redeployments needed&lt;/strong&gt;: Change pipelines without touching app code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;SigNoz with OpenTelemetry&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;SigNoz is a powerful observability platform built specifically for OpenTelemetry. It provides a seamless experience for collecting, storing, visualizing, and querying telemetry data, without vendor lock-in.&lt;/p&gt;

&lt;p&gt;With OpenTelemetry, you collect signals (logs, metrics, and traces) from the coffee shop services. These signals are sent to the OpenTelemetry Collector, which processes and forwards them to SigNoz.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa6lpz5bk1pthpo7xakxf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa6lpz5bk1pthpo7xakxf.png" alt="A visual asset displaying flow of metrics from OTel Collector to SigNoz" width="800" height="35"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In our coffee shop microservices example, SigNoz plays the role of the observability backend, giving your team full visibility into traces, metrics, and logs generated by the app. Here’s how SigNoz helps the coffee shop:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Traces&lt;/strong&gt;: Visualize how an order moves through the system, from frontend-service to payment-service and inventory-service. Identify latency bottlenecks or failed calls.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Metrics&lt;/strong&gt;: Monitor key service-level indicators like espresso_orders_per_minute, latency, and error_rate without writing custom dashboards.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logs&lt;/strong&gt;: Correlate logs with trace IDs and span IDs to troubleshoot order failures (e.g., inventory out-of-stock or payment declined).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhd1pmx1r5d4oxbwmut77.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhd1pmx1r5d4oxbwmut77.png" alt="A screenshot displaying logs linked with traces in SigNoz" width="800" height="714"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more information, refer to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://signoz.io/docs/cloud/" rel="noopener noreferrer"&gt;&lt;strong&gt;https://signoz.io/docs/cloud/&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://signoz.io/docs/instrumentation/overview/" rel="noopener noreferrer"&gt;&lt;strong&gt;https://signoz.io/docs/instrumentation/overview/&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>observability</category>
      <category>opentelemetry</category>
      <category>logs</category>
      <category>traces</category>
    </item>
    <item>
      <title>Introduction to Container Images and Orchestration</title>
      <dc:creator>hridyesh bisht</dc:creator>
      <pubDate>Wed, 07 May 2025 08:09:02 +0000</pubDate>
      <link>https://dev.to/hridyeshbisht/introduction-to-container-images-and-orchestration-32pb</link>
      <guid>https://dev.to/hridyeshbisht/introduction-to-container-images-and-orchestration-32pb</guid>
      <description>&lt;p&gt;As modern apps shift toward microservices and cloud-native architectures, containers have become the standard for packaging and deploying software. However, running containers in production requires more than just building images—it demands scalable orchestration and intelligent management.&lt;/p&gt;

&lt;p&gt;This blog introduces container images. It explains why orchestration is essential in production environments. The blog also explores Kubernetes, the industry-standard platform for container orchestration.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What Are Container Images?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;container image&lt;/strong&gt; packages app code, its runtime, libraries, and all dependencies in a predefined, portable format. This enables consistent deployment across various environments.&lt;/p&gt;

&lt;p&gt;Container runtimes—such as &lt;strong&gt;containerd&lt;/strong&gt;, &lt;strong&gt;runC&lt;/strong&gt;, and &lt;strong&gt;CRI-O&lt;/strong&gt;—use these prebuilt images to create and run one or more containers. While these runtimes are effective on a single host, they lack scalability and fault tolerance required for production environments.&lt;/p&gt;

&lt;p&gt;In production scenarios, apps must meet several critical requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fault tolerance&lt;/strong&gt;: Automatically recover from failures.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: Adjust resources based on demand.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Efficient resource utilization&lt;/strong&gt;: Optimize hardware usage.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service discovery&lt;/strong&gt;: Enable components to find each other dynamically.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;External accessibility&lt;/strong&gt;: Expose services to external clients.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seamless updates and rollbacks&lt;/strong&gt;: Deploy new versions without downtime.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Managing containers manually or through scripts becomes impractical as the number of containers grows. This is where container orchestrators come into play.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;What Is a Container Orchestrator?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A container orchestrator automates the deployment, scaling, networking, and management of containers across multiple hosts. It treats a group of systems as a single cluster, providing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;High availability&lt;/strong&gt;: Ensures services are always accessible.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Distributed workloads&lt;/strong&gt;: Balances tasks across nodes.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimized resource allocation&lt;/strong&gt;: Efficiently utilizes system resources.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated health checks and restarts&lt;/strong&gt;: Maintains application health.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Common features of orchestrators include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cluster management&lt;/strong&gt;: Combine multiple hosts into a unified cluster.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Container scheduling&lt;/strong&gt;: Deploy containers based on resource availability.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service discovery&lt;/strong&gt;: Enable communication across containers, regardless of the host.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storage binding&lt;/strong&gt;: Attach persistent storage volumes to containers.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load balancing&lt;/strong&gt;: Distribute traffic across containers.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security policies&lt;/strong&gt;: Control access to containerized applications.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource optimization&lt;/strong&gt;: Automatically manage and scale resources based on demand.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Popular container orchestrators and services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Kubernetes&lt;/strong&gt;: Open-source and cloud-agnostic; the industry standard for container orchestration.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amazon ECS&lt;/strong&gt;: A fully managed service by AWS for running Docker containers at scale.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amazon EKS&lt;/strong&gt;: A managed Kubernetes service by AWS.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Azure Kubernetes Service (AKS)&lt;/strong&gt;: Microsoft's managed Kubernetes offering.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Kubernetes Engine (GKE)&lt;/strong&gt;: Google's managed Kubernetes service.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HashiCorp Nomad&lt;/strong&gt;: A flexible orchestrator for containers and other workloads.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Container orchestrators are platform-agnostic and can be deployed on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bare metal servers
&lt;/li&gt;
&lt;li&gt;Virtual machines (VMs)
&lt;/li&gt;
&lt;li&gt;On-premises infrastructure
&lt;/li&gt;
&lt;li&gt;Public clouds (AWS, Azure, Google Cloud, etc.)
&lt;/li&gt;
&lt;li&gt;Hybrid cloud environments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For instance, Kubernetes can be deployed on a local machine, in a private data center, or across public cloud services like AWS EC2, Google Compute Engine, or OpenStack.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Understanding Kubernetes&lt;/strong&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What Is Kubernetes?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Kubernetes (K8s) is an open-source system that automates the deployment, scaling, and management of containerized applications. It provides a robust, extensible platform for orchestrating containers across clusters of machines, simplifying the management of distributed, cloud-native systems.&lt;/p&gt;

&lt;p&gt;Key features of Kubernetes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automated scheduling&lt;/strong&gt;: Assigns containers to nodes based on resource requirements and constraints.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extensibility&lt;/strong&gt;: Supports custom resources and controllers without modifying the core codebase.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-healing&lt;/strong&gt;: Monitors container health and replaces failed or unresponsive containers automatically.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service discovery and load balancing&lt;/strong&gt;: Assigns stable DNS names and IP addresses to services, distributing network traffic evenly across pods.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated rollouts and rollbacks&lt;/strong&gt;: Manages application updates and configuration changes incrementally, with automatic rollbacks on failure.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secret and configuration management&lt;/strong&gt;: Separates sensitive data and configuration from application code, injecting secrets securely into the runtime environment.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storage orchestration&lt;/strong&gt;: Mounts persistent storage from various sources dynamically, based on declarative configuration.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batch and job processing&lt;/strong&gt;: Supports batch jobs, cron jobs, and long-running tasks with automatic retries and failure handling.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Managed Kubernetes-as-a-Service (KaaS)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Managed Kubernetes offerings simplify setup and operations, allowing you to provision production-grade clusters with minimal effort. Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Amazon EKS
&lt;/li&gt;
&lt;li&gt;Azure Kubernetes Service (AKS)
&lt;/li&gt;
&lt;li&gt;Google Kubernetes Engine (GKE)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These platforms handle cluster provisioning, scaling, patching, and security, enabling teams to focus on application development.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Kubernetes Architecture Overview&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A Kubernetes cluster consists of two main node types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Control plane nodes&lt;/strong&gt;: Manage the cluster and maintain its desired state.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Worker nodes&lt;/strong&gt;: Run the containerized applications.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhlk20cwacakeh7lt573o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhlk20cwacakeh7lt573o.png" alt="Kubernetes architecture" width="800" height="372"&gt;&lt;/a&gt;&lt;br&gt;
Image credits : &lt;a href="https://trainingportal.linuxfoundation.or" rel="noopener noreferrer"&gt;https://trainingportal.linuxfoundation.org&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Control Plane Node&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The control plane is the brain of the Kubernetes cluster, managing cluster state, responding to user requests, scheduling workloads, and ensuring the desired state matches the actual state. Users interact with the control plane using the Kubernetes API—through the CLI (&lt;code&gt;kubectl&lt;/code&gt;), a web UI (Dashboard), or external tools.&lt;/p&gt;

&lt;p&gt;Core components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;API Server (&lt;code&gt;kube-apiserver&lt;/code&gt;)&lt;/strong&gt;: Exposes the Kubernetes API, validating and processing requests, and communicating with &lt;code&gt;etcd&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scheduler (&lt;code&gt;kube-scheduler&lt;/code&gt;)&lt;/strong&gt;: Assigns pods to nodes based on resource availability and constraints.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Controller Manager (&lt;code&gt;kube-controller-manager&lt;/code&gt;)&lt;/strong&gt;: Runs background reconciliation loops to maintain the desired cluster state.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloud Controller Manager&lt;/strong&gt;: Integrates the cluster with cloud provider APIs for storage, load balancing, and node management.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;etcd&lt;/strong&gt;: Stores all configuration and state data for the cluster, using the Raft consensus algorithm for leader election and fault tolerance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz7aqwbk3zvyh1wvxlbog.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz7aqwbk3zvyh1wvxlbog.png" alt="Kubeadm HA topology" width="800" height="559"&gt;&lt;/a&gt;&lt;br&gt;
Image credits : &lt;a href="https://trainingportal.linuxfoundation.or" rel="noopener noreferrer"&gt;https://trainingportal.linuxfoundation.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For high availability(HA), replicate control plane nodes and configure them in HA mode. In HA setups, one node acts as the leader, while others remain synchronized and ready to take over if needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Worker Node&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Pods are the smallest deployable units in Kubernetes. A pod can contain one or more containers sharing the same network and storage context.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl8waayij5tdw8wqfe829.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl8waayij5tdw8wqfe829.png" alt="Container Runtime Interface" width="800" height="238"&gt;&lt;/a&gt;&lt;br&gt;
Image credits : &lt;a href="https://trainingportal.linuxfoundation.or" rel="noopener noreferrer"&gt;https://trainingportal.linuxfoundation.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Worker nodes host the containerized applications in pods. Each worker node contains the necessary services to run and manage these pods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Container Runtime&lt;/strong&gt;: Executes containers. Supported runtimes include &lt;code&gt;containerd&lt;/code&gt;, &lt;code&gt;CRI-O&lt;/code&gt;, and Docker (via &lt;code&gt;cri-dockerd&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kubelet&lt;/strong&gt;: Agent that communicates with the control plane and manages pods on the node.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CRI Shim&lt;/strong&gt;: Interfaces between the Kubelet and container runtime using the Container Runtime Interface (CRI).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;kube-proxy&lt;/strong&gt;: Manages network rules and forwards traffic to the correct pods based on Kubernetes services.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add-ons&lt;/strong&gt;: Optional services like DNS, logging, monitoring, and dashboards.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Networking in Kubernetes&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Kubernetes networking supports four main types of communication:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Container-to-container&lt;/strong&gt;: Containers in the same pod communicate over &lt;code&gt;localhost&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pod-to-pod&lt;/strong&gt;: Uses the "IP-per-pod" model, with each pod receiving a unique IP.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service-to-pod&lt;/strong&gt;: Enables load-balanced access to pods using stable service endpoints.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;External-to-service&lt;/strong&gt;: Routes external traffic into the cluster via NodePorts, Ingress, or LoadBalancers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Container Network Interface (CNI)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Kubernetes relies on the CNI specification to configure networking. Common CNI plugins include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Flannel
&lt;/li&gt;
&lt;li&gt;Calico
&lt;/li&gt;
&lt;li&gt;Cilium
&lt;/li&gt;
&lt;li&gt;Weave&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These plugins handle IP allocation, routing, and network policies.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Kubernetes Extensibility and Ecosystem&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Kubernetes has a modular, pluggable architecture, supporting the development of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Custom resources and operators
&lt;/li&gt;
&lt;li&gt;Custom APIs and admission controllers
&lt;/li&gt;
&lt;li&gt;Custom scheduling rules and plugins&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This flexibility enables you to tailor Kubernetes to your specific needs, especially in complex microservices environments.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Installing Kubernetes&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You can install Kubernetes using several cluster configurations, each serving different use cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;All-in-One Single-Node Installation&lt;/strong&gt;: Installs both control plane and worker components on a single node. Ideal for learning, development, and testing. Not recommended for production due to lack of high availability and scalability.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single-Control Plane and Multi-Worker Installation&lt;/strong&gt;: Includes a single control plane node running a stacked &lt;code&gt;etcd&lt;/code&gt; instance, managing multiple worker nodes. Suitable for small-scale environments but introduces a single point of failure.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single-Control Plane with External &lt;code&gt;etcd&lt;/code&gt; and Multi-Worker Installation&lt;/strong&gt;: The control plane runs independently from an external &lt;code&gt;etcd&lt;/code&gt; instance, improving data durability. The single control plane manages multiple worker nodes.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-Control Plane and Multi-Worker Installation&lt;/strong&gt;: High-availability setup with multiple control plane nodes, each running a stacked &lt;code&gt;etcd&lt;/code&gt; instance forming an HA &lt;code&gt;etcd&lt;/code&gt; cluster. Offers better fault tolerance.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-Control Plane with External &lt;code&gt;etcd&lt;/code&gt; and Multi-Worker Installation&lt;/strong&gt;: The most robust and production-ready configuration. Each control plane node connects to a dedicated external &lt;code&gt;etcd&lt;/code&gt; instance, all configured in a highly available cluster. Ensures maximum resilience and scalability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6k77nsi07wa1xl4kf7u8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6k77nsi07wa1xl4kf7u8.png" alt="Installing Kubernetes selection diagram" width="800" height="61"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As cluster complexity increases, so do the hardware and infrastructure requirements. For production environments, use a multi-node setup with high availability and redundant control planes.&lt;/p&gt;

&lt;p&gt;When planning infrastructure, consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Environment&lt;/strong&gt;: Bare metal, public cloud, private cloud, or hybrid cloud?
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operating System&lt;/strong&gt;: Red Hat-based, Debian-based, or Windows OS?
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Networking&lt;/strong&gt;: Which CNI plugin best fits your needs?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;For more information, refer to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/hridyeshbisht/getting-started-with-minikube-for-kubernetes-40a6"&gt;Getting started with minikube.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/hridyeshbisht/a-developers-guide-to-kubernetes-components-222g"&gt;A Developer’s Guide to Kubernetes&amp;nbsp;Components.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>A Developer's Guide to Kubernetes Components</title>
      <dc:creator>hridyesh bisht</dc:creator>
      <pubDate>Wed, 07 May 2025 07:56:08 +0000</pubDate>
      <link>https://dev.to/hridyeshbisht/a-developers-guide-to-kubernetes-components-222g</link>
      <guid>https://dev.to/hridyeshbisht/a-developers-guide-to-kubernetes-components-222g</guid>
      <description>&lt;p&gt;Kubernetes is the backbone of modern cloud-native applications. It simplifies deploying, scaling, and managing containerized workloads. But for developers, understanding its core concepts—like Pods, Deployments, and Services—is essential to building scalable and resilient apps.&lt;/p&gt;

&lt;p&gt;In this guide, you learn about Kubernetes components from a developer’s point of view, complete with real-life use cases and visual diagrams.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Understanding Kubernetes Objects&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Kubernetes uses a declarative object model. Each object’s &lt;code&gt;spec&lt;/code&gt; defines the desired state. The &lt;code&gt;status&lt;/code&gt; reflects the current state. Common fields are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;apiVersion&lt;/code&gt;&lt;/strong&gt;: API version (e.g., &lt;code&gt;v1&lt;/code&gt;)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;kind&lt;/code&gt;&lt;/strong&gt;: Object type (e.g., Pod, Service)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;metadata&lt;/code&gt;&lt;/strong&gt;: Name, namespace, labels
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;spec&lt;/code&gt;&lt;/strong&gt;: Desired configuration
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;status&lt;/code&gt;&lt;/strong&gt;: System-managed status&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For certain objects like Secrets and ConfigMaps, data and stringData fields are used to store key-value pairs.​Kubernetes API Server accepts object definitions in a JSON format, most often such definition manifests in a YAML format which is converted by &lt;strong&gt;kubectl&lt;/strong&gt; in a JSON payload and sent to the API Server.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Enable Autocompletion (Optional)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Autocompletion enhances your CLI experience. For example, in Bash:&lt;/p&gt;

&lt;p&gt;source &amp;lt;(minikube completion bash)&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Nodes&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A node is a physical or virtual machine in a Kubernetes cluster. Each node runs the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;kubelet&lt;/strong&gt;: Ensures containers in a Pod are running.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;kube-proxy&lt;/strong&gt;: Manages network rules for communication.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Container runtime&lt;/strong&gt;: Runs containers (e.g., Docker, containerd).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In a cloud-native e-commerce app, each node could run pods handling different services—payments, inventory, or recommendations.&lt;/p&gt;

&lt;p&gt;There are two types of nodes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Control plane nodes&lt;/strong&gt;: Manage the cluster. They run the API server, scheduler, controller manager, and etcd.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Worker nodes&lt;/strong&gt;: Run application workloads.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fznwvq46c5cbiassivkd1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fznwvq46c5cbiassivkd1.png" alt="image of Kubernetes architecture" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Image credits : &lt;a href="https://trainingportal.linuxfoundation.or" rel="noopener noreferrer"&gt;https://trainingportal.linuxfoundation.org&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Namespaces&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Namespaces partition cluster resources and isolate workloads. They allow teams to share a cluster without interfering with each other.&lt;/p&gt;

&lt;p&gt;Default namespaces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;default&lt;/code&gt;: For user-defined resources.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kube-system&lt;/code&gt;: For system-level components.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kube-public&lt;/code&gt;: Readable by all users.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kube-node-lease&lt;/code&gt;: Used for node heartbeats.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If multiple users and teams use the same Kubernetes cluster you can partition the cluster into virtual sub-clusters using Namespaces. The names of the resources/objects created inside a Namespace are unique, but not across Namespaces in the cluster.&lt;/p&gt;

&lt;p&gt;To list all namespaces:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl get namespaces&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To create a namespace:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl create namespace \&amp;lt;namespace-name\&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Namespaces support:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unique resource names within each namespace
&lt;/li&gt;
&lt;li&gt;Resource isolation by team, project, or environment
&lt;/li&gt;
&lt;li&gt;Resource quotas and limits&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A good practice, however, is to create additional Namespaces, as desired, to virtualize the cluster and isolate users, developer teams, apps, or tiers.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Pods&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A Pod is the smallest deployable unit in Kubernetes. It can contain one or more containers that share:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The same network namespace
&lt;/li&gt;
&lt;li&gt;Storage volumes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pods are ephemeral and typically managed by higher-level objects like Deployments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr2rn764wcnnopqr5q2at.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr2rn764wcnnopqr5q2at.png" alt="Single- and Multi-Container Pods" width="800" height="241"&gt;&lt;/a&gt;&lt;br&gt;
Image credits : &lt;a href="https://trainingportal.linuxfoundation.or" rel="noopener noreferrer"&gt;https://trainingportal.linuxfoundation.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Example, &lt;code&gt;nginx-pod.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;  
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;  
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx-pod&lt;/span&gt;  
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;\- name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;  
    &lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:1.22.1&lt;/span&gt;  
    &lt;span class="s"&gt;ports&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;\- containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply the manifest:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl apply \-f nginx-pod.yaml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Generate the manifest without creating the Pod:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl run nginx-pod \--image=nginx:1.22.1&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Labels and Selectors&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Labels are key-value pairs used to organize, select, and manage Kubernetes objects. They are used by controllers and services to organize and manage resources, hence many objects can have the same Label(s).&lt;/p&gt;

&lt;p&gt;Label Selectors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Equality-based&lt;/strong&gt;: Select resources matching specific key-value pairs.​ 

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;kubectl get pods -l env=dev&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Set-based&lt;/strong&gt;: Select resources matching a set of values.​

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;kubectl get pods -l 'env in (dev, qa)'&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxp7wgsp796nk22hi1qrs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxp7wgsp796nk22hi1qrs.png" alt="Labels and Selector diagram" width="800" height="668"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Image credits : &lt;a href="https://trainingportal.linuxfoundation.or" rel="noopener noreferrer"&gt;https://trainingportal.linuxfoundation.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use labels to group resources logically (e.g., by environment, app version).&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;ReplicaSets&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A ReplicaSet ensures a specific number of identical Pods are always running.&lt;/p&gt;

&lt;p&gt;Key features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Self-healing: Replaces failed Pods
&lt;/li&gt;
&lt;li&gt;Scalable: Supports manual and automated scaling
&lt;/li&gt;
&lt;li&gt;Uses label selectors to identify Pods&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, consider a ReplicaSet with a replica count set to 3 for a specific Pod template. Pod-1, Pod-2, and Pod-3 are identical, running the same app container image, being cloned from the same Pod template.&lt;/p&gt;

&lt;p&gt;Although the three Pod replicas are said to be identical, they have unique Pod name and IP address. The Pod object ensures that the application can be individually placed on any worker node of the cluster as a result of the scheduling process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;YAML Example&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;  
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ReplicaSet&lt;/span&gt;  
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend&lt;/span&gt;  
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;guestbook&lt;/span&gt;  
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;3&lt;/span&gt;  
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;guestbook&lt;/span&gt;  
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;guestbook&lt;/span&gt;  
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;\- name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;php-redis&lt;/span&gt;  
        &lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gcr.io/google\_samples/gb-frontend:v3&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To create the ReplicaSet:​&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl create \-f redis-rs.yaml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Assume that one of the Pods is forced to unexpectedly terminate (due to insufficient resources, timeout, its hosting node has crashed, etc.), causing the current state to no longer match the desired state.&lt;/p&gt;

&lt;p&gt;The ReplicaSet detects that the current state is no longer matching the desired state and triggers a request for an additional Pod to be created, thus ensuring that the current state matches the desired state.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnqok3xj1fnpjdh9miogo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnqok3xj1fnpjdh9miogo.png" alt="ReplicaSet (Creating a Pod to Match Current State with Desired State)" width="800" height="469"&gt;&lt;/a&gt;&lt;br&gt;
Image credits : &lt;a href="https://trainingportal.linuxfoundation.or" rel="noopener noreferrer"&gt;https://trainingportal.linuxfoundation.org&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Deployments&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Deployments manage the creation, deletion, and updates of Pods. A Deployment automatically creates a ReplicaSet, which then creates a Pod.&lt;/p&gt;

&lt;p&gt;There is no need to manage ReplicaSets and Pods separately, the Deployment will manage them on our behalf.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;YAML Example&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;  
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;  
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx-deployment&lt;/span&gt;  
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx-deployment&lt;/span&gt;  
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;3&lt;/span&gt;  
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx-deployment&lt;/span&gt;  
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx-deployment&lt;/span&gt;  
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;\- name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;  
        &lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:1.20.2&lt;/span&gt;  
        &lt;span class="s"&gt;ports&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;  
        &lt;span class="na"&gt;\- containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;** Apply the manifest:**&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl apply \-f def-deploy.yaml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;When you update the Pod template (for example, a container image), Kubernetes performs a rolling update. Each update creates a new ReplicaSet and marks it as a new revision.&lt;/p&gt;

&lt;p&gt;Once the rolling update has completed, the &lt;strong&gt;Deployment&lt;/strong&gt; will show both &lt;strong&gt;ReplicaSets A&lt;/strong&gt; and &lt;strong&gt;B&lt;/strong&gt;, where &lt;strong&gt;A&lt;/strong&gt; is scaled to 0 (zero) Pods, and &lt;strong&gt;B&lt;/strong&gt; is scaled to 3 Pods. This is how the Deployment records its prior state configuration settings, as &lt;strong&gt;Revisions&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsztaes92j7y8hytmidkb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsztaes92j7y8hytmidkb.png" alt="Deployment (ReplicaSet B Created)" width="800" height="491"&gt;&lt;/a&gt;&lt;br&gt;
Image credits : &lt;a href="https://trainingportal.linuxfoundation.or" rel="noopener noreferrer"&gt;https://trainingportal.linuxfoundation.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you update the Pod template (for example, a container image), Kubernetes performs a rolling update. Each update creates a new ReplicaSet and marks it as a new revision.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;DaemonSets&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A DaemonSet ensures a Pod runs on all (or some) Nodes in the cluster. It's ideal for running background agents (e.g., log collectors, monitoring tools).&lt;/p&gt;

&lt;p&gt;In contrast, the ReplicaSet and Deployment operators by default have no control over the scheduling and placement of multiple Pod replicas on the same Node.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;YAML Example&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;  
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;DaemonSet&lt;/span&gt;  
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fluentd-agent&lt;/span&gt;  
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;k8s-app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fluentd-agent&lt;/span&gt;  
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;k8s-app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fluentd-agent&lt;/span&gt;  
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
        &lt;span class="na"&gt;k8s-app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fluentd-agent&lt;/span&gt;  
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;\- name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fluentd&lt;/span&gt;  
        &lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;quay.io/fluentd\_elasticsearch/fluentd:v4.5.2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Create the DaemonSet:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl create \-f fluentd-ds.yaml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Whenever a Node is added to the cluster, a Pod from a given DaemonSet is automatically placed on it. When any one Node crashes or it is removed from the cluster, the respective DaemonSet operated Pods are garbage collected. If a DaemonSet is deleted, all Pod replicas it created are deleted as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Authentication, Authorization, and Admission Control&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To manage Kubernetes resources, all API requests go through three control stages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Authentication:&lt;/strong&gt; Authenticate a user based on credentials provided as part of API requests.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authorization:&lt;/strong&gt; Authorizes the API requests submitted by the authenticated user.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Admission Control:&lt;/strong&gt; Software modules that validate and/or modify user requests. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn5vrl8dnyezy6ghtxwqb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn5vrl8dnyezy6ghtxwqb.png" alt="Controlling Access to the API" width="800" height="418"&gt;&lt;/a&gt;&lt;br&gt;
Image credits : &lt;a href="https://trainingportal.linuxfoundation.or" rel="noopener noreferrer"&gt;https://trainingportal.linuxfoundation.org&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Authentication&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Authentication verifies the identity of a user or service making a request to the API server. Kubernetes doesn’t store user objects but supports various authentication methods:&lt;/p&gt;

&lt;p&gt;Different user types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Normal users&lt;/strong&gt;: Managed externally (e.g., client certificates, static token files, OIDC).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service accounts&lt;/strong&gt;: Used by in-cluster processes. Automatically created per namespace and mount credentials into pods. The Service Accounts are tied to a particular Namespace and mount the respective credentials to communicate with the API server as Secrets.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If properly configured, Kubernetes can also support anonymous requests, along with requests from Normal Users and Service Accounts.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Authorization&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Authorization determines whether an authenticated user is allowed to perform an action.&lt;/p&gt;

&lt;p&gt;More than one module can be configured for one Kubernetes cluster, and each module is checked in sequence. If any authorizer approves or denies a request, then that decision is returned immediately.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Supported Modes&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Node Authorization&lt;/strong&gt;: Grants kubelet access to node- and pod-related APIs.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Attribute-Based Access Control (ABAC)&lt;/strong&gt;: Policy-based access using user attributes.

&lt;ul&gt;
&lt;li&gt;To enable ABAC mode, you must start the API server with the --authorization-mode=ABAC option, while specifying the authorization policy with --authorization-policy-file=PolicyFile.json.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Webhook&lt;/strong&gt;: Sends authorization requests to an external service.

&lt;ul&gt;
&lt;li&gt;To enable the Webhook authorizer, we need to start the API server with the --authorization-webhook-config-file=SOME_FILENAME option, where SOME_FILENAME is the configuration of the remote authorization service.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Role-Based Access Control (RBAC)&lt;/strong&gt; &lt;em&gt;(Recommended)&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example: Role granting pod read access in lfs158 namespace&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io/v1&lt;/span&gt;  
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Role&lt;/span&gt;  
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;lfs158&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pod-reader&lt;/span&gt;  
&lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
&lt;span class="na"&gt;\- apiGroups&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;\[""\]&lt;/span&gt;  
  &lt;span class="s"&gt;resources&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;\["pods"\]&lt;/span&gt;  
  &lt;span class="s"&gt;verbs&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;\["get", "watch", "list"\]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Kubernetes, multiple Roles can be attached to subjects like users, service accounts, etc. In RBAC, you can create two kinds of Roles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Role&lt;/strong&gt;: Grants namespace-scoped permissions.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ClusterRole&lt;/strong&gt;: Grants cluster-wide permissions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once the role is created, youcan bind it to users with a RoleBinding object. There are two kinds of RoleBindings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;RoleBinding&lt;/strong&gt;: Binds a Role or ClusterRole to users/groups/service accounts in a namespace.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ClusterRoleBinding&lt;/strong&gt;: Binds a ClusterRole at the cluster scope.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example: RoleBinding for user bob&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io/v1&lt;/span&gt;  
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;RoleBinding&lt;/span&gt;  
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pod-read-access&lt;/span&gt;  
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;lfs158&lt;/span&gt;  
&lt;span class="na"&gt;subjects&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
&lt;span class="na"&gt;\- kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;User&lt;/span&gt;  
  &lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bob&lt;/span&gt;  
  &lt;span class="s"&gt;apiGroup&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io&lt;/span&gt;  
&lt;span class="na"&gt;roleRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Role&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pod-reader&lt;/span&gt;  
  &lt;span class="na"&gt;apiGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Admission Control&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Admission controllers validate or modify API requests after authentication and authorization but before persistence.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Controller Types&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Validating&lt;/strong&gt;: Check request validity.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mutating&lt;/strong&gt;: Modify request objects.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Examples&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;LimitRanger: Enforces resource limits.
&lt;/li&gt;
&lt;li&gt;ResourceQuota: Enforces resource quotas.
&lt;/li&gt;
&lt;li&gt;DefaultStorageClass: Sets default storage class.
&lt;/li&gt;
&lt;li&gt;AlwaysPullImages: Forces images to always be pulled.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Enable admission controllers with:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;\--enable-admission-plugins=NamespaceLifecycle,ResourceQuota,PodSecurity,DefaultStorageClass&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Custom controllers can be created as &lt;strong&gt;admission webhooks&lt;/strong&gt; to support dynamic, external validation or mutation.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Accessing Application Pods&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Each Pod is assigned a dynamic IP address. If a Pod is restarted, Kubernetes assigns a new IP. If you're connecting directly to a Pod IP, you'll lose access when the Pod is replaced.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff6p697aclampfuajraaw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff6p697aclampfuajraaw.png" alt="A New Pod Is Created After an Old One Terminated Unexpectedly" width="800" height="506"&gt;&lt;/a&gt;&lt;br&gt;
Image credits : &lt;a href="https://trainingportal.linuxfoundation.or" rel="noopener noreferrer"&gt;https://trainingportal.linuxfoundation.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: Accessing Pods by IP&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For example, a client accesses Pods using their individual IPs. If one Pod fails, a new Pod is created with a different IP. The client must then detect and update its target IPs, which adds complexity and increases overhead.&lt;/p&gt;

&lt;p&gt;To overcome this situation, Kubernetes provides a higher-level abstraction called &lt;strong&gt;Service&lt;/strong&gt;, which logically groups Pods and defines a policy to access them. This grouping is achieved via &lt;em&gt;Labels&lt;/em&gt; and &lt;em&gt;Selectors&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;**apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1**&lt;/span&gt;  
&lt;span class="na"&gt;**kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment**&lt;/span&gt;  
&lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="nv"&gt;*metadata&lt;/span&gt;&lt;span class="s"&gt;:**&lt;/span&gt;  
  &lt;span class="s"&gt;**labels:**&lt;/span&gt;  
    &lt;span class="s"&gt;**app&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend**&lt;/span&gt;  
  &lt;span class="s"&gt;**name&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend**&lt;/span&gt;  
&lt;span class="err"&gt;*&lt;/span&gt;&lt;span class="nv"&gt;*spec&lt;/span&gt;&lt;span class="s"&gt;:**&lt;/span&gt;  
  &lt;span class="s"&gt;**replicas&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;3**&lt;/span&gt;  
  &lt;span class="s"&gt;**selector:**&lt;/span&gt;  
    &lt;span class="s"&gt;**matchLabels:**&lt;/span&gt;  
      &lt;span class="s"&gt;**app&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend**&lt;/span&gt;  
    &lt;span class="s"&gt;**template:**&lt;/span&gt;  
      &lt;span class="s"&gt;**metadata:**&lt;/span&gt;  
        &lt;span class="s"&gt;**labels:**&lt;/span&gt;  
          &lt;span class="s"&gt;**app&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend**&lt;/span&gt;  
      &lt;span class="s"&gt;**spec:**&lt;/span&gt;  
        &lt;span class="s"&gt;**containers:**&lt;/span&gt;  
        &lt;span class="s"&gt;**\- image&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend-application**&lt;/span&gt;  
        &lt;span class="s"&gt;**name&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend-application**&lt;/span&gt;  
        &lt;span class="s"&gt;**ports:**&lt;/span&gt;  
        &lt;span class="s"&gt;**\- containerPort&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5000**&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Services&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A Kubernetes Service provides a stable network endpoint for a group of Pods. It automatically routes traffic to healthy Pods and load balances requests.&lt;/p&gt;

&lt;p&gt;Services use label selectors to identify target Pods.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Create a Service to Expose Pods&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;First, define a Deployment that runs your application and labels the Pods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;  
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;  
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend&lt;/span&gt;  
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;3&lt;/span&gt;  
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend&lt;/span&gt;  
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend&lt;/span&gt;  
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
        &lt;span class="na"&gt;\- name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend-application&lt;/span&gt;  
          &lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend-application&lt;/span&gt;  
          &lt;span class="s"&gt;ports&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;  
            &lt;span class="na"&gt;\- containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, expose these Pods using a Service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;  
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;  
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend-svc&lt;/span&gt;  
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend&lt;/span&gt;  
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;\- port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;80&lt;/span&gt;  
      &lt;span class="s"&gt;targetPort&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5000&lt;/span&gt;  
      &lt;span class="s"&gt;protocol&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, the Service type is &lt;code&gt;ClusterIP&lt;/code&gt;, which exposes the Service only within the cluster.&lt;/p&gt;

&lt;p&gt;To apply the Service:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl apply \-f frontend-svc.yaml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Or use &lt;code&gt;kubectl expose&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl expose deployment frontend &lt;span class="se"&gt;\-&lt;/span&gt;&lt;span class="nt"&gt;-name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;frontend-svc &lt;span class="se"&gt;\\&lt;/span&gt;  
  &lt;span class="se"&gt;\-&lt;/span&gt;&lt;span class="nt"&gt;-port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;80 &lt;span class="se"&gt;\-&lt;/span&gt;&lt;span class="nt"&gt;-target-port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5000&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;How Services Group Pods&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Services use label selectors to identify groups of Pods. You can define separate Services for each group:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;frontend-svc&lt;/code&gt; — targets Pods with &lt;code&gt;app=frontend&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;db-svc&lt;/code&gt; — targets Pods with &lt;code&gt;app=db&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7hbzsrt82youbqxgu928.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7hbzsrt82youbqxgu928.png" alt="Accessing the Pods Using Service Object" width="717" height="559"&gt;&lt;/a&gt;&lt;br&gt;
Image credits : &lt;a href="https://trainingportal.linuxfoundation.or" rel="noopener noreferrer"&gt;https://trainingportal.linuxfoundation.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you create a Service, Kubernetes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Assigns it a ClusterIP (accessible only inside the cluster)
&lt;/li&gt;
&lt;li&gt;Maps that ClusterIP to a list of Pod IPs and ports (called Endpoints)
&lt;/li&gt;
&lt;li&gt;Uses kube-proxy to route traffic based on IP rules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To view the Service and its endpoints:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl get service,endpoints frontend-svc&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The client connects to the Service via its &lt;code&gt;ClusterIP&lt;/code&gt;. The Service forwards traffic to one of the selected Pods and performs load balancing.&lt;/p&gt;

&lt;p&gt;The user/client now connects to a Service via its ClusterIP, which forwards traffic to one of the Pods attached to it. A Service provides load balancing by default while selecting the Pods for traffic forwarding.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Load Balancing and Failover&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A Service balances traffic across all healthy Pods. When a Pod is replaced, the Service updates its endpoints list and redirects traffic to the new Pod—no changes needed in client configuration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Each endpoint includes the Pod's IP and its target port.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Kube-proxy&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In Kubernetes, each node runs kube-proxy, a network proxy that maintains network rules on nodes. It enables communication to your Pods from network sessions inside or outside of your cluster.&lt;/p&gt;

&lt;p&gt;Each node runs &lt;code&gt;kube-proxy&lt;/code&gt;, which:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Service Management&lt;/strong&gt;: kube-proxy watches the Kubernetes API for changes in Service and Endpoint objects, updating the node's network rules accordingly.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Traffic Routing&lt;/strong&gt;: It uses either iptables or IPVS to handle traffic routing. By default, iptables is used, which is simple and well-supported but less efficient than IPVS.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For each new Service, kube-proxy configures iptables rules on each node to capture traffic for the Service's ClusterIP and forward it to one of the Service's endpoints. This enables any node to receive external traffic and route it internally based on the iptables rules. When a Service is removed, kube-proxy deletes the corresponding iptables rules from all nodes.&lt;/p&gt;

&lt;p&gt;The kube-proxy agent runs on every node, and iptables rules are redundantly populated across nodes. Each iptables instance stores routing rules for the entire cluster, ensuring that Service objects implement distributed load balancing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgaqj2k8cn0xqus0403z4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgaqj2k8cn0xqus0403z4.png" alt="Kube-proxy description diagram" width="800" height="464"&gt;&lt;/a&gt; &lt;br&gt;
Image credits : &lt;a href="https://trainingportal.linuxfoundation.or" rel="noopener noreferrer"&gt;https://trainingportal.linuxfoundation.org&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Traffic Policies&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Kubernetes Services support traffic policies that influence routing decisions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cluster (Default)&lt;/strong&gt;: Routes traffic to all ready endpoints, regardless of their node.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local&lt;/strong&gt;: Routes traffic only to endpoints on the same node as the client. If no local endpoints are available, the traffic is dropped. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can configure these policies in your Service manifest:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;  
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;  
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend-svc&lt;/span&gt;  
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend&lt;/span&gt;  
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;\- protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;  
      &lt;span class="s"&gt;port&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;80&lt;/span&gt;  
      &lt;span class="s"&gt;targetPort&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5000&lt;/span&gt;  
  &lt;span class="na"&gt;internalTrafficPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Local&lt;/span&gt;  
  &lt;span class="na"&gt;externalTrafficPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Local&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Service Discovery&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Kubernetes supports two service discovery mechanisms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Environment Variables: For each active Service, Kubernetes injects environment variables into new Pods. For example: &lt;code&gt;REDIS_MASTER_SERVICE_PORT&lt;/code&gt;.

&lt;ul&gt;
&lt;li&gt;Note: These variables are set only when the Pod starts.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;DNS-Based Discovery: Kubernetes DNS creates names like: &lt;code&gt;my-svc.my-namespace.svc.cluster.local&lt;/code&gt;
&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;This allows Services to be discoverable within the cluster.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;ServiceType&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Kubernetes Services can be exposed in different ways, defined by the type field:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is only accessible within the cluster.
&lt;/li&gt;
&lt;li&gt;Is accessible from within the cluster and the external world.
&lt;/li&gt;
&lt;li&gt;Maps to an entity which resides either inside or outside the cluster.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Access scope is decided by &lt;strong&gt;ServiceType&lt;/strong&gt; property, defined when creating the Service.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;ClusterIP (default)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Exposes the Service on an internal IP, making it accessible only within the cluster.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe56q6ai1b1wi2nr7wbh9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe56q6ai1b1wi2nr7wbh9.png" alt="ClusterIP exposing the service on NodePort" width="800" height="464"&gt;&lt;/a&gt;&lt;br&gt;
Image credits : &lt;a href="https://trainingportal.linuxfoundation.or" rel="noopener noreferrer"&gt;https://trainingportal.linuxfoundation.org&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;NodePort&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Exposes the Service on a static port on each node’s IP. A ClusterIP Service, to which the NodePort Service routes, is automatically created.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;LoadBalancer&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Exposes the Service externally using a cloud provider's load balancer. NodePort and ClusterIP Services, to which the external load balancer routes, are automatically created.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsm53h7ynnj18b3zxidr2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsm53h7ynnj18b3zxidr2.png" alt="LoadBalancer exposing the service" width="800" height="530"&gt;&lt;/a&gt;&lt;br&gt;
Image credits : &lt;a href="https://trainingportal.linuxfoundation.or" rel="noopener noreferrer"&gt;https://trainingportal.linuxfoundation.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note: Requires cloud provider support.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;ExternalIP&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Maps a Service to an external IP address. Traffic that is ingressed into the cluster with the ExternalIP (as destination IP) on the Service port, gets routed to one of the Service endpoints&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ozl5cc2qrt5mjl8uj11.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ozl5cc2qrt5mjl8uj11.png" alt="External Ip to access the Service" width="800" height="507"&gt;&lt;/a&gt;&lt;br&gt;
Image credits : &lt;a href="https://trainingportal.linuxfoundation.or" rel="noopener noreferrer"&gt;https://trainingportal.linuxfoundation.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The administrator must configure external routing.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;ExternalName&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Maps the Service to an external DNS name using a CNAME record. No proxying occurs.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Multi-Port Services&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Expose multiple ports in a single Service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;  
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;  
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-service&lt;/span&gt;  
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;myapp&lt;/span&gt;  
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NodePort&lt;/span&gt;  
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;\- name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;  
      &lt;span class="s"&gt;protocol&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;  
      &lt;span class="s"&gt;port&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;8080&lt;/span&gt;  
      &lt;span class="s"&gt;targetPort&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;80&lt;/span&gt;  
      &lt;span class="s"&gt;nodePort&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;31080&lt;/span&gt;  
    &lt;span class="na"&gt;\- name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https&lt;/span&gt;  
      &lt;span class="s"&gt;protocol&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;  
      &lt;span class="s"&gt;port&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;8443&lt;/span&gt;  
      &lt;span class="s"&gt;targetPort&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;443&lt;/span&gt;  
      &lt;span class="s"&gt;nodePort&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="m"&gt;31443&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a helpful feature when exposing Pods with one container listening on more than one port, or when exposing Pods with multiple containers listening on one or more ports.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Port Forwarding for Local Testing&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;kubectl&lt;/code&gt; to forward a local port to a Service for testing:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl port-forward svc/frontend-svc 8080:80&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is useful for debugging applications without exposing the Service externally.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Kubernetes Ingress&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Kubernetes Services support internal routing, but defining routing logic per Service leads to duplication and limited flexibility. Ingress decouples routing rules from individual Services and acts as a centralized entry point for external traffic.&lt;/p&gt;

&lt;p&gt;Ingress defines HTTP and HTTPS routing rules and acts as a single entry point for external traffic into your cluster. It configures a Layer 7 (application layer) load balancer and supports the following capabilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;TLS termination&lt;/strong&gt;: Offload SSL at the edge.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Name-based virtual hosting&lt;/strong&gt;: Route traffic by hostname.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fanout routing&lt;/strong&gt;: Route traffic by URL path.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom routing rules&lt;/strong&gt;: Use annotations to enable advanced behaviors.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load balancing&lt;/strong&gt;: Distribute traffic across Service backends.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faxgktmyegae4e9mekyah.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faxgktmyegae4e9mekyah.png" alt="Kubernetes Ingrees" width="800" height="286"&gt;&lt;/a&gt;&lt;br&gt;
Image credits : &lt;a href="https://trainingportal.linuxfoundation.or" rel="noopener noreferrer"&gt;https://trainingportal.linuxfoundation.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instead of accessing a Service directly, clients connect to the Ingress endpoint. The Ingress resource defines routing rules that forward requests to the appropriate Service based on hostnames and URL paths.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The Ingress resource itself does not handle traffic. An Ingress Controller—such as NGINX—interprets the rules and manages request forwarding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: Name-Based Virtual Hosting&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use this pattern to route traffic based on the request hostname.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Ingress&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;virtual-host-ingress&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;nginx.ingress.kubernetes.io/service-upstream&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ingressClassName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;blue.example.com&lt;/span&gt;
    &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;
        &lt;span class="na"&gt;pathType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ImplementationSpecific&lt;/span&gt;
        &lt;span class="na"&gt;backend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;webserver-blue-svc&lt;/span&gt;
            &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;number&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;green.example.com&lt;/span&gt;
    &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;
        &lt;span class="na"&gt;pathType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ImplementationSpecific&lt;/span&gt;
        &lt;span class="na"&gt;backend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;webserver-green-svc&lt;/span&gt;
            &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;number&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, requests to &lt;code&gt;blue.example.com&lt;/code&gt; and &lt;code&gt;green.example.com&lt;/code&gt; are routed to their respective backend Services.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5zkas1u7vzga2yq9o1lj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5zkas1u7vzga2yq9o1lj.png" alt="Name-Based Virtual Hosting Ingress" width="800" height="286"&gt;&lt;/a&gt;&lt;br&gt;
Image credits : &lt;a href="https://trainingportal.linuxfoundation.or" rel="noopener noreferrer"&gt;https://trainingportal.linuxfoundation.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: Path-Based Fanout Routing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use this pattern to route traffic based on the URL path.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.k8s.io/v1&lt;/span&gt;  
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Ingress&lt;/span&gt;  
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fan-out-ingress&lt;/span&gt;  
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;  
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;nginx.ingress.kubernetes.io/service-upstream&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;  
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;ingressClassName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;  
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;\- host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;example.com&lt;/span&gt;  
    &lt;span class="s"&gt;http&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;\- path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/blue&lt;/span&gt;  
        &lt;span class="s"&gt;pathType&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ImplementationSpecific&lt;/span&gt;  
        &lt;span class="s"&gt;backend&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;  
          &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;webserver-blue-svc&lt;/span&gt;  
            &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
              &lt;span class="na"&gt;number&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;80&lt;/span&gt;  
      &lt;span class="na"&gt;\- path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/green&lt;/span&gt;  
        &lt;span class="s"&gt;pathType&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ImplementationSpecific&lt;/span&gt;  
        &lt;span class="s"&gt;backend&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;  
          &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;webserver-green-svc&lt;/span&gt;  
            &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
              &lt;span class="na"&gt;number&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Requests to &lt;code&gt;example.com/blue&lt;/code&gt; and &lt;code&gt;example.com/green&lt;/code&gt; are routed to the corresponding Services.&lt;/p&gt;

&lt;p&gt;The ingress is fulfilled by an Ingress Controller, which is a reverse proxy responsible for traffic routing based on rules defined in the Ingress resource.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Ingress Controller&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The Ingress resource only defines routing rules. It does not route traffic on its own. An &lt;strong&gt;Ingress Controller&lt;/strong&gt; is responsible for fulfilling these rules.&lt;/p&gt;

&lt;p&gt;An Ingress Controller:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Monitors the Kubernetes API for changes to Ingress resources
&lt;/li&gt;
&lt;li&gt;Configures the Layer 7 load balancer
&lt;/li&gt;
&lt;li&gt;Acts as a reverse proxy for external traffic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Popular Ingress Controllers&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NGINX Ingress Controller
&lt;/li&gt;
&lt;li&gt;AWS Load Balancer Controller
&lt;/li&gt;
&lt;li&gt;GCE L7 Load Balancer
&lt;/li&gt;
&lt;li&gt;Istio Ingress&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Each controller may require specific annotations. Always specify the correct &lt;code&gt;ingressClassName&lt;/code&gt; and annotations for compatibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Deploy an Ingress Resource&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;After enabling the Ingress Controller, deploy your Ingress resource using:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl create \-f virtual-host-ingress.yaml&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Annotations&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Annotations allow you to store non-identifying metadata on Kubernetes objects in key-value pairs. They're not used for selection but provide auxiliary information to tools.&lt;/p&gt;

&lt;p&gt;Common use cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Store build/release IDs, Git branch names.
&lt;/li&gt;
&lt;li&gt;Reference logging or monitoring tools.
&lt;/li&gt;
&lt;li&gt;Annotate ingress controller data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example: Add annotations during Deployment creation&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;  
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;  
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;webserver&lt;/span&gt;  
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Deployment&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;PoC&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Mar&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;2022"&lt;/span&gt;  
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="s"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Resource Quotas and Limit Ranges&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In multi-tenant Kubernetes clusters, it's essential to prevent any single user or team from consuming excessive resources. Kubernetes provides ResourceQuota and LimitRange objects to enforce such constraints.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Resource Quotas&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;ResourceQuota objects limit the aggregate resource consumption per namespace. They can restrict:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Object counts (Pods, Services, ConfigMaps, etc.)
&lt;/li&gt;
&lt;li&gt;Compute resources (CPU, memory).
&lt;/li&gt;
&lt;li&gt;Storage resources (PersistentVolumeClaims).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;  
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ResourceQuota&lt;/span&gt;  
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;compute-resources&lt;/span&gt;  
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;devspace&lt;/span&gt;  
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;hard&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;requests.cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1"&lt;/span&gt;  
    &lt;span class="na"&gt;limits.cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2"&lt;/span&gt;  
    &lt;span class="na"&gt;requests.memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1Gi&lt;/span&gt;  
    &lt;span class="na"&gt;limits.memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2Gi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Limit Ranges&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;LimitRange objects set default request and limit values for Pods or Containers within a namespace. They ensure that containers don't consume excessive resources and help maintain cluster stability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;LimitRange&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cpu-limits&lt;/span&gt;
 &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;devspace&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
     &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;500m&lt;/span&gt;
   &lt;span class="na"&gt;defaultRequest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
     &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;500m&lt;/span&gt;
   &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
     &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1"&lt;/span&gt;
   &lt;span class="na"&gt;min&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
     &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;100m&lt;/span&gt;
   &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Container&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Autoscaling&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Autoscaling in Kubernetes adjusts the number of running objects based on resource utilization, availability, and requirements. There are several types of autoscalers:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Horizontal Pod Autoscaler (HPA)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;HPA automatically scales the number of pod replicas based on CPU utilization or other select metrics.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl autoscale deploy myapp \--min=2 \--max=10 \--cpu-percent=80&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Vertical Pod Autoscaler (VPA)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;VPA adjusts the CPU and memory requests and limits for containers based on usage. It helps optimize resource allocation for individual pods.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Cluster Autoscaler&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The Cluster Autoscaler adjusts the number of nodes in your cluster when pods fail to launch due to insufficient resources or when nodes in the cluster are underutilized. In Azure Kubernetes Service (AKS), it's recommended to let the Kubernetes Cluster Autoscaler manage the required scale settings.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsdrd64vxavk6eg4d9hym.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsdrd64vxavk6eg4d9hym.png" alt="Autoscaling in Kubernetes" width="728" height="251"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Job Scheduling&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Jobs&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A Job creates one or more Pods to perform a specific task and ensures that the specified number of Pods successfully terminate. Jobs are useful for batch processing tasks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configuration Options:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;parallelism&lt;/strong&gt;: Number of Pods to run in parallel.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;completions&lt;/strong&gt;: Number of successful completions needed.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;activeDeadlineSeconds&lt;/strong&gt;: Duration in seconds the Job may be active.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;backoffLimit&lt;/strong&gt;: Number of retries before marking the Job as failed.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ttlSecondsAfterFinished&lt;/strong&gt;: Time to retain the Job after completion.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;batch/v1&lt;/span&gt;  
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Job&lt;/span&gt;  
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;data-cleanup&lt;/span&gt;  
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;\- name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cleaner&lt;/span&gt;  
        &lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;busybox&lt;/span&gt;  
        &lt;span class="s"&gt;command&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;\["sh", "-c", "cleanup.sh"\]&lt;/span&gt;  
      &lt;span class="na"&gt;restartPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Never&lt;/span&gt;  
  &lt;span class="na"&gt;backoffLimit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;CronJobs&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;CronJobs schedule Jobs to run periodically at fixed times, dates, or intervals. They are useful for recurring tasks like backups or report generation .&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configuration Options:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;schedule&lt;/strong&gt;: Cron format schedule string.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;startingDeadlineSeconds&lt;/strong&gt;: Deadline in seconds for starting the Job if it misses its scheduled time.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;concurrencyPolicy&lt;/strong&gt;: Specifies how to treat concurrent executions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;batch/v1&lt;/span&gt;  
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CronJob&lt;/span&gt;  
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;db-backup&lt;/span&gt;  
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt;  
  &lt;span class="na"&gt;jobTemplate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
        &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
          &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
          &lt;span class="na"&gt;\- name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;backup&lt;/span&gt;  
            &lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;backup-tool&lt;/span&gt;  
          &lt;span class="na"&gt;restartPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;OnFailure&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;StatefulSets&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;StatefulSets&lt;/strong&gt; manage the deployment and scaling of Pods with unique, persistent identities. Unlike Deployments, StatefulSets guarantee the ordering and uniqueness of Pods, making them ideal for stateful workloads.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Key Features&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Persistent storage&lt;/strong&gt;: Each Pod in a StatefulSet gets its own PersistentVolume. This volume is retained across Pod restarts or rescheduling.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stable network identity&lt;/strong&gt;: Each Pod receives a unique and consistent DNS name, allowing predictable network communication (for example, &lt;code&gt;pod-0.service-name&lt;/code&gt;).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ordered operations&lt;/strong&gt;: Pods are created, updated, and deleted in a defined order, one at a time. This ensures safe startup, updates, and shutdowns.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Real-World Example&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Use StatefulSets to deploy clustered databases or distributed systems where each node must retain its identity and storage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use Case: Cassandra or Redis Clusters&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In a Cassandra cluster:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each node (Pod) requires a stable hostname for cluster gossip protocol.
&lt;/li&gt;
&lt;li&gt;Each node needs its own storage volume to persist data across rescheduling.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;  
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;StatefulSet&lt;/span&gt;  
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;redis&lt;/span&gt;  
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;serviceName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;redis"&lt;/span&gt;  
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;3&lt;/span&gt;  
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;redis&lt;/span&gt;  
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;redis&lt;/span&gt;  
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
        &lt;span class="na"&gt;\- name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;redis&lt;/span&gt;  
          &lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;redis:7.0&lt;/span&gt;  
          &lt;span class="s"&gt;volumeMounts&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;  
            &lt;span class="na"&gt;\- name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;redis-data&lt;/span&gt;  
              &lt;span class="s"&gt;mountPath&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/data&lt;/span&gt;  
  &lt;span class="na"&gt;volumeClaimTemplates&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;\- metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;redis-data&lt;/span&gt;  
      &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
        &lt;span class="na"&gt;accessModes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;\[ "ReadWriteOnce" \]&lt;/span&gt;  
        &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
          &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
            &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1Gi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Custom Resources&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Custom Resources are user-defined API objects that allow you to store and retrieve structured data in Kubernetes. Combined with controllers, they help automate custom workflows or represent external systems inside your cluster.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Custom Resource Definitions (CRDs)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;CRDs are the most common way to add custom resources. They allow you to define custom objects without modifying the Kubernetes source code .&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apiextensions.k8s.io/v1&lt;/span&gt;  
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CustomResourceDefinition&lt;/span&gt;  
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;databases.example.com&lt;/span&gt;  
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
&lt;span class="na"&gt;group&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;example.com&lt;/span&gt;  
&lt;span class="na"&gt;versions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
&lt;span class="na"&gt;\- name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;  
&lt;span class="na"&gt;served&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;  
&lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;  
&lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
&lt;span class="na"&gt;openAPIV3Schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;object&lt;/span&gt;  
&lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;object&lt;/span&gt;  
&lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
&lt;span class="na"&gt;engine&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
&lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;  
&lt;span class="na"&gt;scope&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Namespaced&lt;/span&gt;  
&lt;span class="na"&gt;names&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
&lt;span class="na"&gt;plural&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;databases&lt;/span&gt;  
&lt;span class="na"&gt;singular&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;database&lt;/span&gt;  
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Database&lt;/span&gt;  
&lt;span class="na"&gt;shortNames&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
&lt;span class="s"&gt;\- db&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once registered, you can create resources like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;example.com/v1&lt;/span&gt;  
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Database&lt;/span&gt;  
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-postgres-db&lt;/span&gt;  
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
&lt;span class="na"&gt;engine&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use a CRD to manage custom services like Database, Cache, or Queue, with a controller automating provisioning tasks across your infrastructure.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;API Aggregation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;API Aggregation&lt;/strong&gt; is an advanced extension mechanism. It lets you run a separate API server behind the Kubernetes API, delegating requests to custom endpoints.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your API server must implement Kubernetes-style authentication, authorization, and admission control.
&lt;/li&gt;
&lt;li&gt;You write and deploy your own API server.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This method is more complex but offers greater flexibility.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Security Contexts&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Security Contexts define privilege and access controls for Pods and containers. You can use them to enforce non-root execution, set file system permissions, and limit privilege escalation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: Secure Pod Configuration&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;  
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;  
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;secure-pod&lt;/span&gt;  
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;securityContext&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;runAsUser&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1000       \# Runs Pod as non-root user&lt;/span&gt;  
    &lt;span class="na"&gt;fsGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2000         \# Shared file system group&lt;/span&gt;  
  &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;\- name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;app&lt;/span&gt;  
    &lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;busybox&lt;/span&gt;  
    &lt;span class="s"&gt;securityContext&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;allowPrivilegeEscalation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="s"&gt;  \# Prevents gaining extra privileges&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Always run containers as a non-root user unless absolutely necessary.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Pod Security Admission&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Pod Security Admission (PSA)&lt;/strong&gt; is a built-in admission controller in Kubernetes. It enforces security standards at the namespace level by applying predefined policies.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Restricted&lt;/strong&gt;: Strictest, enforces non-root and drops capabilities.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Baseline&lt;/strong&gt;: Reasonably secure defaults.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Privileged&lt;/strong&gt;: Allows full capabilities—use with caution.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example: Enable Restricted Policy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl label namespace my-namespace \\  pod-security.kubernetes.io/enforce=restricted&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Network Policies&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Network Policies&lt;/strong&gt; control traffic flow to and from Pods. By default, all traffic is allowed unless restricted by a policy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example: Allow Only Frontend to Access Database&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.k8s.io/v1&lt;/span&gt;  
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NetworkPolicy&lt;/span&gt;  
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;allow-frontend&lt;/span&gt;  
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;podSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;db&lt;/span&gt;  
  &lt;span class="na"&gt;ingress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;\- from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;\- podSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
        &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
          &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend&lt;/span&gt;  
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;\- port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5432&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Combine multiple policies to fine-tune network security for microservices.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpm0y2zx5jbhbjmv2oy24.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpm0y2zx5jbhbjmv2oy24.png" alt="A diagram explaining network policies" width="644" height="157"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Metrics Server&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Metrics Server&lt;/strong&gt; is a lightweight resource monitoring component. It provides CPU and memory usage data for Pods and nodes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example Commands:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl top pods  
kubectl top nodes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs8xnmpya0yykln46pcyr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs8xnmpya0yykln46pcyr.png" alt="Metrics Server in Kubernetes" width="800" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Prometheus&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Prometheus&lt;/strong&gt; is a robust monitoring tool that collects and queries time-series metrics.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scrapes metrics from applications and Kubernetes components.
&lt;/li&gt;
&lt;li&gt;Supports alerting and visualizations via Grafana.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example Use Case:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Monitor HTTP request rates and latency in a web application. Integrate alerts when request rates spike or response times degrade.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Helm: Kubernetes Package Manager&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Helm is the de facto package manager for Kubernetes. It enables developers to deploy and manage complex applications using templated YAML files—called &lt;em&gt;charts&lt;/em&gt;—that follow DRY (Don't Repeat Yourself) principles.&lt;/p&gt;

&lt;p&gt;Package and deploy complex applications like WordPress, NGINX Ingress, or custom APIs using reusable charts. A chart includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Template files for resource definitions
&lt;/li&gt;
&lt;li&gt;Configuration values
&lt;/li&gt;
&lt;li&gt;Metadata (e.g., chart name, version)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Charts can be stored in repositories—similar to how .deb or .rpm packages are stored for Linux distributions—or in container registries.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Key Benefits&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reusable templates&lt;/strong&gt;: Use Helm charts to define, install, and upgrade Kubernetes applications.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version control&lt;/strong&gt;: Roll back to previous releases with a single command.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitOps friendly&lt;/strong&gt;: Integrates well with tools like Argo CD and Flux for continuous delivery.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;How Helm Works&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Helm is a command-line tool that runs alongside kubectl and uses your existing kubeconfig file to connect securely to your cluster. It performs the following actions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Searches chart repositories based on your criteria.
&lt;/li&gt;
&lt;li&gt;Downloads the selected chart to your local system.
&lt;/li&gt;
&lt;li&gt;Uses the Kubernetes API to deploy the resources defined in the chart.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can also use Helm to upgrade or delete deployments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DRY deployment configs
&lt;/li&gt;
&lt;li&gt;Easy upgrades/rollbacks
&lt;/li&gt;
&lt;li&gt;Integrates with GitOps workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Service Mesh: Advanced Service Communication&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A service mesh abstracts communication between microservices into a dedicated infrastructure layer. It helps manage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Secure communication&lt;/strong&gt;: Enforces mutual TLS (mTLS) between Pods.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Advanced traffic routing&lt;/strong&gt;: Supports strategies like canary releases and A/B testing.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observability&lt;/strong&gt;: Collects traffic metrics, latency data, and failure insights without modifying app code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Architecture Overview&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Each Pod includes a &lt;strong&gt;sidecar proxy&lt;/strong&gt; that handles communication and policy enforcement. These proxies form the &lt;em&gt;data plane&lt;/em&gt;, while a central &lt;em&gt;control plane&lt;/em&gt; manages configuration and telemetry.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data Plane&lt;/strong&gt;: Handles service traffic. This usually includes sidecar proxies injected into each Pod, or node-level proxies in some implementations.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Control Plane&lt;/strong&gt;: Manages configuration, service discovery, policy enforcement, and telemetry.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The sidecar proxy intercepts all inbound and outbound traffic to the Pod, enabling consistent policy enforcement and observability without modifying the application code.&lt;/p&gt;

&lt;p&gt;Decoupling of networking logic from application code&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Popular Service Meshes&lt;/strong&gt;
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Notable Feature&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Istio&lt;/td&gt;
&lt;td&gt;Full-featured, widely adopted&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linkerd&lt;/td&gt;
&lt;td&gt;Lightweight and CNCF-supported&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Next steps&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;For more information, refer to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dev.to/hridyeshbisht/getting-started-with-minikube-for-kubernetes-40a6"&gt;Getting started with minikube.&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://programmerprodigy.code.blog/2025/05/06/introduction-to-container-images-and-orchestration/" rel="noopener noreferrer"&gt;Introduction to Container Images and Orchestration.&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://programmerprodigy.code.blog/2025/05/06/managing-configuration-with-configmaps-and-secrets/" rel="noopener noreferrer"&gt;Managing Configuration with ConfigMaps and Secrets.&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kubernetes</category>
      <category>containers</category>
    </item>
    <item>
      <title>Getting Started with minikube for Kubernetes</title>
      <dc:creator>hridyesh bisht</dc:creator>
      <pubDate>Tue, 06 May 2025 15:57:10 +0000</pubDate>
      <link>https://dev.to/hridyeshbisht/getting-started-with-minikube-for-kubernetes-40a6</link>
      <guid>https://dev.to/hridyeshbisht/getting-started-with-minikube-for-kubernetes-40a6</guid>
      <description>&lt;p&gt;Minikube is a lightweight tool that runs a full Kubernetes cluster on your local machine. It's ideal for developers who want to test applications, simulate production behavior, or learn Kubernetes without using cloud resources. Whether you’re developing microservices, testing Ingress routing, or deploying with Helm, Minikube provides a fast, isolated environment with full Kubernetes features.&lt;/p&gt;

&lt;p&gt;Key Features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Installs and manages Kubernetes components
&lt;/li&gt;
&lt;li&gt;Supports single-node and multi-node clusters
&lt;/li&gt;
&lt;li&gt;Offers both CLI and web-based access
&lt;/li&gt;
&lt;li&gt;Enables custom profiles and driver selection&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Hardware Requirements&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Minikube provisions local resources for cluster nodes. Minimum recommended per node:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CPU&lt;/strong&gt;: 2 cores
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory&lt;/strong&gt;: 2 GB (4–8 GB recommended)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storage&lt;/strong&gt;: 20 GB
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Internet&lt;/strong&gt;: Required for initial setup and image downloads&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ensure your system has enough resources for both Minikube and any workloads.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Software Requirements&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Minikube requires a supported Type-2 hypervisor or container runtime. It uses these to isolate Kubernetes from your host OS.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;OS&lt;/th&gt;
&lt;th&gt;Hypervisors&lt;/th&gt;
&lt;th&gt;Container Runtimes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Linux&lt;/td&gt;
&lt;td&gt;VirtualBox, KVM2, QEMU&lt;/td&gt;
&lt;td&gt;Docker, Podman&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;macOS&lt;/td&gt;
&lt;td&gt;VirtualBox, HyperKit, VMware Fusion, Parallels&lt;/td&gt;
&lt;td&gt;Docker, Podman&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows&lt;/td&gt;
&lt;td&gt;VirtualBox, Hyper-V, VMware Workstation, QEMU&lt;/td&gt;
&lt;td&gt;Docker, Podman&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: On Linux, you can use &lt;code&gt;--driver=none&lt;/code&gt; to run Minikube directly on the host. This bypasses isolation and requires root access.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Create and Manage Clusters&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Run the following to create your first cluster:&lt;/p&gt;

&lt;p&gt;minikube start&lt;/p&gt;

&lt;p&gt;This command:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detects or uses the specified driver
&lt;/li&gt;
&lt;li&gt;Creates a VM or container with:

&lt;ul&gt;
&lt;li&gt;2 CPUs
&lt;/li&gt;
&lt;li&gt;6 GB memory
&lt;/li&gt;
&lt;li&gt;20 GB storage
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Bootstraps Kubernetes using &lt;code&gt;kubeadm&lt;/code&gt;
&lt;/li&gt;

&lt;li&gt;Installs Docker as the default container runtime
&lt;/li&gt;

&lt;li&gt;Creates a default profile to track cluster state&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;To create a multi-node cluster:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;minikube start \--profile custom-cluster \--nodes 3 \--kubernetes-version=v1.28.1 \--driver=docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use the &lt;code&gt;--profile&lt;/code&gt; flag to create and manage multiple clusters.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Cluster Profiles&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Minikube uses profiles to store cluster configuration. By default, all commands apply to the default profile. To work with a custom profile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;minikube stop \--profile custom-cluster  
minikube start  \# Uses the default profile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use &lt;code&gt;--profile&lt;/code&gt; in commands to manage multiple environments.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Enable Autocompletion (Optional)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Autocompletion enhances your CLI experience. For example, in Bash:&lt;/p&gt;

&lt;p&gt;source &amp;lt;(minikube completion bash)&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Accessing Minikube&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;kubectl (CLI)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Minikube includes a bundled version of &lt;code&gt;kubectl&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;minikube kubectl \-- get pods

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, for convenience, install &lt;code&gt;kubectl&lt;/code&gt; separately. It automatically detects your Minikube cluster.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Kubernetes Dashboard (Web UI)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To use the web-based UI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;addons enable metrics-server  
minikube addons enable dashboard  
minikube dashboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This opens a browser UI for inspecting deployments, pods, and logs.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Kubernetes API Access&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The API server is the entry point to the cluster. You can access it via:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;kubectl and CLI tools
&lt;/li&gt;
&lt;li&gt;Web Dashboard
&lt;/li&gt;
&lt;li&gt;Custom automation using HTTP API calls&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use &lt;code&gt;kubectl proxy&lt;/code&gt; to expose the API server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl proxy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This opens access at &lt;code&gt;http://localhost:8001/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To explore the API: &lt;code&gt;curl http://localhost:8001/api/v1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To run the proxy in the background:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl proxy &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Access Without a Proxy&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;To access the Kubernetes API directly, use an authentication token or certificate credentials.&lt;/p&gt;

&lt;p&gt;For example, you must generate a token and grant access:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export TOKEN=$(kubectl create token default)  
export APISERVER=$(kubectl config view \--minify \-o jsonpath='{.clusters\[0\].cluster.server}')
curl $APISERVER \--header "Authorization: Bearer $TOKEN" \--insecure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Deploy and Access an NGINX Application Using the Minikube Dashboard&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;You’ll use the nginx container image from Docker Hub.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start Minikube: To launch your local Kubernetes cluster, run:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;minikube start&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Verify the status:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;minikube status&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Launch the Dashboard :Start the web-based Kubernetes Dashboard:

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;minikube dashboard&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9x2occ5vqpcq15lbfh3c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9x2occ5vqpcq15lbfh3c.png" alt="Dashboard displaying Deployments, Pods, and ReplicaSets" width="800" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This command opens the dashboard in your default browser. By default, it connects to the default namespace, where all operations occur unless you change the context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you reboot your machine or log out and log back in, rerun the minikube dashboard command to reopen the dashboard.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Deploying an Application - Accessing the Dashboard&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To deploy the NGINX application:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the Dashboard, select &lt;strong&gt;Deploy&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Choose &lt;strong&gt;Show Advanced Options&lt;/strong&gt; to set:

&lt;ul&gt;
&lt;li&gt;Labels
&lt;/li&gt;
&lt;li&gt;Namespace
&lt;/li&gt;
&lt;li&gt;Resource Requests
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use nginx as the container image.
&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Deploy&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The deployment creates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Deployment resource (for example, web-dash)
&lt;/li&gt;
&lt;li&gt;A ReplicaSet (e.g., web-dash-74d8bd488f)
&lt;/li&gt;
&lt;li&gt;A Pod (e.g., web-dash-74d8bd488f-dwbzz)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Resource names are unique and may vary in your cluster. The naming pattern follows Kubernetes conventions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh3lzmd2lvxrtdef0486q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh3lzmd2lvxrtdef0486q.png" alt="Accessing the Application In the Browser over the NodePort" width="800" height="978"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use the left navigation panel to explore the Deployment, ReplicaSet, and Pod resources.&lt;/p&gt;

&lt;p&gt;You can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;View properties by selecting resource names.
&lt;/li&gt;
&lt;li&gt;Scale the deployment from the vertical three-dots menu.
&lt;/li&gt;
&lt;li&gt;Delete individual Pods and observe them automatically recreated.
&lt;/li&gt;
&lt;li&gt;Delete the deployment to remove all Pods.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once we create the &lt;strong&gt;web-dash&lt;/strong&gt; Deployment, we can use the resource navigation panel from the left side of the Dashboard to display details of Deployments, ReplicaSets, and Pods in the &lt;strong&gt;default&lt;/strong&gt; Namespace. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frz0f7vnsrxo4fvfy5sw1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frz0f7vnsrxo4fvfy5sw1.png" alt="Deploy a Containerized Application - Interface" width="800" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Access the Application&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To access the application: get the Minikube IP  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;minikube ip&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In your browser, go to &lt;a href="http://192.168.99.100:%5C" rel="noopener noreferrer"&gt;http://192.168.99.100:\&lt;/a&gt;. Replace &amp;lt;NodePort&amp;gt; with the actual port assigned to your service (e.g., 31074).&lt;/p&gt;

&lt;p&gt;Minikube opens the application in your browser. You should see the default NGINX welcome page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy42w4d86k1zwscjjuf2c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy42w4d86k1zwscjjuf2c.png" alt="Deploying an Application - Accessing the Dashboard" width="800" height="253"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see the &lt;em&gt;Nginx&lt;/em&gt; welcome page, displayed by the &lt;strong&gt;webserver&lt;/strong&gt; application running inside the Pods created. Our requests could be served by either one of the three endpoints logically grouped by the Service since the Service acts as a Load Balancer in front of its endpoints.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Enable Ingress for Routing&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Minikube includes the NGINX Ingress Controller as a built-in add-on. To enable it, run:&lt;/p&gt;

&lt;p&gt;minikube addons enable ingress&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7j9tfixn64gons33ixel.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7j9tfixn64gons33ixel.png" alt="Enable Ingress for Routing" width="657" height="251"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Apply an Ingress manifest:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;kubectl apply \-f virtual-host-ingress.yaml&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Add entries to &lt;code&gt;/etc/hosts&lt;/code&gt;:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;192.168.99.100   blue.example.com green.example.com&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Deploy an Ingress Resource&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;After enabling the Ingress Controller, deploy your Ingress resource using:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl create \-f virtual-host-ingress.yaml&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Configure Liveness, Readiness, and Startup Probes&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Probes monitor and manage container health. If a container becomes unresponsive, the kubelet uses probes to take action (e.g., restart the container).&lt;/p&gt;

&lt;p&gt;Rather than restarting it manually, we can use a Liveness Probe. Liveness Probe checks on an application's health, and if the health check fails, &lt;strong&gt;kubelet&lt;/strong&gt; restarts the affected container automatically.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Liveness Probes&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Use Liveness Probes to detect and recover from unresponsive applications. &lt;/p&gt;

&lt;p&gt;Supported types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exec command
&lt;/li&gt;
&lt;li&gt;HTTP GET
&lt;/li&gt;
&lt;li&gt;TCP Socket
&lt;/li&gt;
&lt;li&gt;gRPC&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Liveness Probe (Exec)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;livenessProbe:  
  exec:  
    command: \["cat", "/tmp/healthy"\]  
  initialDelaySeconds: 15  
  periodSeconds: 5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simulate file removal after startup to trigger restarts. Until the container reports "ready," the Pod will not receive traffic from a Service.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Startup Probe (HTTP)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use Startup Probes for applications that take a long time to initialize. They prevent premature liveness and readiness checks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;startupProbe:  
  httpGet:  
    path: /startup  
    port: 8080  
  failureThreshold: 30  
  periodSeconds: 10 ` 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>minikube</category>
      <category>kubernetes</category>
      <category>containers</category>
    </item>
    <item>
      <title>Integrating Low-Code &amp; High-Code Solutions Effectively</title>
      <dc:creator>hridyesh bisht</dc:creator>
      <pubDate>Mon, 11 Nov 2024 10:39:38 +0000</pubDate>
      <link>https://dev.to/aws-builders/integrating-low-code-high-code-solutions-effectively-p6d</link>
      <guid>https://dev.to/aws-builders/integrating-low-code-high-code-solutions-effectively-p6d</guid>
      <description>&lt;p&gt;Low and high-code solutions address different needs in today's development landscape. Low-code platforms enable fast development with minimal coding, making them ideal for non-developers or projects with tight timelines. High code requires more technical expertise, offering greater customization and control over complex features. Combining low and high-code approaches can provide flexibility and speed, but successful integration and monitoring require a clear strategy.&lt;/p&gt;

&lt;p&gt;With over three years of experience in low-code solutions, I often get questions at meetups and hackathons like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why should I use low-code solutions?&lt;/li&gt;
&lt;li&gt;Can I integrate low-code and high-code solutions?&lt;/li&gt;
&lt;li&gt;How do I architect infrastructure that supports low- and high-code?&lt;/li&gt;
&lt;li&gt;How can I unify logs and traces to monitor my entire infrastructure?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This blog addresses these questions and helps you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Decide when to choose low code or high code.&lt;/li&gt;
&lt;li&gt;Integrate both solutions seamlessly.&lt;/li&gt;
&lt;li&gt;Architect an infrastructure that supports both approaches.&lt;/li&gt;
&lt;li&gt;Enable unified logging and tracing with tools like SigNoz.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When to Use Low-Code vs. High-Code
&lt;/h2&gt;

&lt;p&gt;Low-code platforms allow you to build applications with minimal coding, letting you focus on business logic. They offer visual tools, drag-and-drop interfaces, and pre-built components that simplify development. Low-code solution enables you to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build and deploy applications quickly using reusable components.&lt;/li&gt;
&lt;li&gt;Adapt to changing business needs with flexible, scalable applications.&lt;/li&gt;
&lt;li&gt;Automate workflows, reducing the overhead of traditional software development.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Low-code is often the best choice for fast development or projects with limited technical resources. High-code, however, is ideal when customization, scalability, and control are critical. Sometimes, combining both approaches provides an effective balance for different project components. In some cases, combining both approaches can leverage their strengths, effectively balancing different project components.&lt;/p&gt;

&lt;p&gt;For example, consider an employee onboarding app that collects employee details, generates tasks, assigns managers, and integrates with HR systems. You have two options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Low-Code Approach: Use drag-and-drop components for the UI, integrate APIs, automate task generation, and set up notifications.&lt;/li&gt;
&lt;li&gt;High-Code Approach: Manually code the UI, APIs, and business logic in Java or Python for full customization.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7x4ckkeiojdv4vyzzol9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7x4ckkeiojdv4vyzzol9.png" alt="When to choose Low or High code" width="800" height="645"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Benefits of Low-Code for Front-End Components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pre-built components: Forms, task management, and notifications are ready-made.&lt;/li&gt;
&lt;li&gt;Centralized dashboard: Easily monitor updates, reducing time on code changes and bug fixes.&lt;/li&gt;
&lt;li&gt;Built-in connectors: Common HR integrations like SAP reduce custom code requirements.&lt;/li&gt;
&lt;li&gt;Rapid prototyping: Build and adapt prototypes based on feedback.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Integrating Low Code and High Code Solutions
&lt;/h2&gt;

&lt;p&gt;Combining low-code and high-code solutions lets you leverage both rapid development and customization. This approach creates a flexible, scalable architecture supporting speed and control. Key benefits include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Flexibility: Design each component with the best approach for its needs. Use low-code for user interfaces and workflows and high-code for backend logic.&lt;/li&gt;
&lt;li&gt;Scalability: Quickly iterate on low-code components for front-end changes while handling complex business logic with high-code.&lt;/li&gt;
&lt;li&gt;Efficient collaboration: Non-developers can build front-end features in low-code while developers focus on high-code elements, maintaining functionality.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Despite the benefits, integrating low and high-code solutions comes with challenges that require careful planning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compatibility: Low-code platforms may have limited interoperability with custom high-code solutions.&lt;/li&gt;
&lt;li&gt;Data synchronization: Ensure seamless data flow between components, maintaining consistent formats and structures.&lt;/li&gt;
&lt;li&gt;API limitations: Restricted APIs in low-code platforms can complicate consistent bidirectional integration with high-code systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the earlier example about employee onboarding, the low code for the UI and the high code for backend functions were combined. In an employee onboarding system,&amp;nbsp;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Low-code: Manages front-end tasks, onboarding workflows, and notifications.&lt;/li&gt;
&lt;li&gt;High-code: Handles backend processing, complex integrations, analyzing data to track metrics and generating documents.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr6g43z8kssp4seekmknj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr6g43z8kssp4seekmknj.png" alt="An example of Employee Onboarding app" width="800" height="648"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This approach lets non-technical users manage the onboarding workflow while developers focus on implementing secure and efficient backend operations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Architecting an Infrastructure with Low-Code and High-Code Solutions
&lt;/h3&gt;

&lt;p&gt;When architecting an infrastructure with both low-code and high-code, address compatibility, data flow, and scalability:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Separation of concerns: Use microservices or modular components to separate low-code and high-code tasks, allowing flexibility in updates and maintenance.&lt;/li&gt;
&lt;li&gt;Data flow and APIs: Establish clear data pathways using APIs, creating a bridge between low-code and high-code.&lt;/li&gt;
&lt;li&gt;Scalability: Design the infrastructure to scale specific components independently, supporting growth without overhauling the system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To integrate both, you can use Middleware to manage communication between low- and high-code components using an API gateway. An API gateway centralizes communication, manages authentication, and routes requests to the appropriate services.&lt;/p&gt;

&lt;p&gt;The benefits of architecting an Infrastructure with Low-Code and High-Code Solutions are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scalability: By separating low-code and high-code tasks, each component can be scaled based on specific usage requirements, optimizing resource allocation.&lt;/li&gt;
&lt;li&gt;Efficient Collaboration: Developers and non-developers can collaborate efficiently, with each team focusing on the parts that best align with their expertise.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0bfwwr94qhg02npeluns.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0bfwwr94qhg02npeluns.png" alt="Adding Middleware in the employee onboarding app" width="800" height="648"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, in the employee onboarding app. You add an extra component:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Middleware: An API gateway centralizes communication, manages authentication, and routes requests to the appropriate services.
Unified Logging and Tracing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Combining low-code and high-code solutions adds flexibility but can complicate monitoring. Unified logging and tracing with observability tools like SigNoz provide a centralized view of application performance across both environments. SigNoz’s APM (Application Performance Monitoring) features enable monitoring and troubleshooting through a single dashboard.&lt;/p&gt;

&lt;p&gt;Unified logging and tracing across both approaches lets you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Monitor application performance: View metrics and logs across all components.&lt;/li&gt;
&lt;li&gt;Detect issues: Identify bottlenecks in both low-code and high-code elements.&lt;/li&gt;
&lt;li&gt;Simplify troubleshooting: Trace issues end-to-end for faster incident resolution.&lt;/li&gt;
&lt;li&gt;Optimize infrastructure: Use insights to allocate resources more effectively.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Implementing SigNoz for Unified Observability
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Instrument High Code Applications:

&lt;ol&gt;
&lt;li&gt;Integrate OpenTelemetry libraries in your high code applications to capture traces, metrics, and logs. This includes configuring custom traces for critical processes such as API calls, external integrations, and custom logic.&lt;/li&gt;
&lt;li&gt;High code applications can leverage SigNoz’s SDKs in languages like Python, Java, and Node.js to capture detailed telemetry data.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;Connect Low Code Platforms: 
1.If your low-code platform supports custom logging or webhooks, configure it to send logs to SigNoz. Alternatively, integrate through REST APIs to stream logs, events, and metrics from the low-code environment into SigNoz.&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;Use SigNoz’s UI to view real-time logs and traces across low- and high-code components. A unified dashboard allows you to correlate data from different sources, providing comprehensive insights and aiding in root-cause analysis.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5gogrex8tjgmveqi8193.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5gogrex8tjgmveqi8193.png" alt="Adding Data monitoring in the employee onboarding app" width="800" height="648"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Consider an employee onboarding app, and you need to add another layer to your infrastructure. An observability layer to:&amp;nbsp;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Aggregates all telemetry data from low and high code layers, allowing centralized monitoring and troubleshooting.&lt;/p&gt;

&lt;p&gt;Present real-time performance insights, helping teams monitor low and high code components.&lt;/p&gt;

&lt;p&gt;Best Practices for Unified Observability&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Standardize log formats: Ensure consistent log formats across components for seamless parsing.&lt;/li&gt;
&lt;li&gt;Use trace IDs: Connect transactions across low-code and high-code environments for end-to-end traceability.&lt;/li&gt;
&lt;li&gt;Monitor and adjust metrics regularly: Track key metrics and adjust infrastructure as needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Combining low-code and high-code solutions can empower your development strategy, providing the agility to build while retaining control over complex features. You can optimize performance and streamline collaboration across teams by architecting a unified infrastructure and leveraging robust observability tools like SigNoz. Whether you're building rapid prototypes or integrating with advanced systems, a thoughtful blend of low-code and high-code approaches offers the best of both worlds, making your applications adaptable, scalable, and resilient.&lt;/p&gt;

</description>
      <category>lowcode</category>
      <category>monitoring</category>
      <category>architecture</category>
      <category>data</category>
    </item>
    <item>
      <title>How to effectively store and ANALYSE logs in AWS CLOUD</title>
      <dc:creator>hridyesh bisht</dc:creator>
      <pubDate>Wed, 22 Mar 2023 15:12:53 +0000</pubDate>
      <link>https://dev.to/aws-builders/how-to-effectively-store-and-analyse-logs-in-aws-cloud-1k0d</link>
      <guid>https://dev.to/aws-builders/how-to-effectively-store-and-analyse-logs-in-aws-cloud-1k0d</guid>
      <description>&lt;p&gt;Services and applications typically create logs that contain significant amounts of information. This information is logged and stored on persistent storage, allowing it to be reviewed and analyzed at any time.&lt;/p&gt;

&lt;p&gt;By monitoring the data within your logs, you can quickly identify potential issues you want to be made aware of as soon as they occur. Resolving an incident as quickly as possible is paramount for developing real-life solutions.&lt;/p&gt;

&lt;p&gt;Having more data about how your environment is running far outweighs the disadvantage of needing more information, especially when it matters to your business in the case of incidents and security breaches.&lt;/p&gt;

&lt;p&gt;Some logs can be monitored in real-time, allowing automatic responses to be carried out depending on the data contents of the log. Logs often contain vast amounts of metadata, including date stamps and source information such as IP addresses or usernames.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This blog aims to help you understand how to store and analyze logs in AWS and some recommended practices.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Storing and analyzing logs in AWS can be done using various services and tools, depending on your requirements and use case. Here are some services you can consider:&lt;/p&gt;

&lt;h4&gt;A. AWS CloudWatch&lt;/h4&gt;

&lt;p&gt;AWS CloudWatch provides valuable insights into the health and performance of your applications and resources, which can help you optimize their performance, increase availability, and improve the overall customer experience.&amp;nbsp;Various components of Amazon CloudWatch include:&lt;/p&gt;

&lt;p&gt;1. &lt;strong&gt;Dashboards:&amp;nbsp;&lt;/strong&gt;You can quickly and easily design different dashboards to represent the data by building your views. For example, you can view all performance metrics and alarms from resources relating to a specific customer.&lt;/p&gt;

&lt;p&gt;Once you have built your Dashboards, you can easily share them with other users, even those who may not have access to your AWS account.&amp;nbsp;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&amp;nbsp;The resources within your customised dashboard can be from multiple different regions.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;2. &lt;strong&gt;Metrics: &lt;/strong&gt;You can monitor a specific element of an application or resource over time, for example, the number of DiskReadson in an EC2 instance.&amp;nbsp;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Anomaly detection allows CloudWatch to implement machine learning algorithms against your metric data to help detect any activity generally expected outside the normal baseline parameters.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Different services will offer different metrics.&lt;/p&gt;

&lt;p&gt;3. &lt;strong&gt;Amazon CloudWatch Alarms&lt;/strong&gt;:&amp;nbsp;You can implement automatic actions based on specific thresholds that you can configure relating to each metric.&lt;/p&gt;

&lt;p&gt;For example, you could set an alarm to activate an auto-scaling operation if your CPU utilization of an EC2 instance peaked at 75% for more than 2 minutes.&lt;/p&gt;

&lt;p&gt;There are three different states for any alarm associated with a metric,&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;OK – The metric is within the defined configured threshold.&lt;/li&gt;



&lt;li&gt;ALARM – The metric has exceeded the thresholds set.&lt;/li&gt;



&lt;li&gt;INSUFFICIENT_DATA – There is insufficient data for the metric to determine the alarm state.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;/p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdocs.aws.amazon.com%2Fimages%2FAmazonCloudWatch%2Flatest%2Fmonitoring%2Fimages%2FCW-Overview.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdocs.aws.amazon.com%2Fimages%2FAmazonCloudWatch%2Flatest%2Fmonitoring%2Fimages%2FCW-Overview.png" alt="" width="604" height="385"&gt;&lt;/a&gt;Image credits: &lt;a href="https://docs.aws.amazon.com/images/AmazonCloudWatch/latest/monitoring/images/CW-Overview.png" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/images/AmazonCloudWatch/latest/monitoring/images/CW-Overview.png&lt;/a&gt;&lt;p&gt;&lt;/p&gt;

&lt;p&gt;4. &lt;strong&gt;CloudWatch EventBridge:&lt;/strong&gt; You connect applications to various targets, allowing you to implement real-time monitoring and respond to events in your application.&amp;nbsp;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;The&lt;strong&gt; significant benefit of using CloudWatch EventBridge is that it allows you to implement the event-driven architecture &lt;/strong&gt;in a real-time decoupled environment.&amp;nbsp;&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Various elements of this feature include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Rules: A rule acts as a filter for incoming streams of event traffic and then routes these events to the appropriate target defined within the rule. The target must be in the same region.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Targets: Targets are where the Rules direct events, such as AWS Lambda, SQS, Kinesis, or SNS. All events received are in JSON format.&lt;/li&gt;



&lt;li&gt;&amp;nbsp;Event Buses: It receives the event from your applications, and your rules are associated with a specific event bus.&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;5. &lt;strong&gt;CloudWatch Logs:&lt;/strong&gt; You have a centralized location to store your logs from different AWS services that provide logs as an output, such as CloudTrail, EC2, VPC Flow logs, etc., in addition to your own applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;An added advantage of CloudWatch logs comes with the installation of the Unified CloudWatch Agent, &lt;/strong&gt;which can collect logs and additional metric data from EC2 instances as well as from on-premise services running either a Linux or Windows operating system. This metric data is in addition to the default EC2 metrics that CloudWatch automatically configures for you.&amp;nbsp;&lt;/p&gt;

&lt;p&gt;Various types of insights within CloudWatch include Log Insights, Container Insights, and Lambda Insights.&lt;/p&gt;

&lt;h4&gt;B. AWS Cloud Trail &lt;/h4&gt;

&lt;p&gt;AWS CloudTrail records and tracks all AWS API requests. It captures an API request made by a user as an event and logs it to a file it stores on S3.&lt;/p&gt;

&lt;p&gt;CloudTrail captures additional identifying information for every event, including the requester's identity, the initiation timestamp, and the source IP address.&lt;/p&gt;

&lt;p&gt;You can use the data captured by CloudTrail to help you enhance your AWS environment in several ways.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Security analysis tool.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Help resolve and manage day-to-day operational issues and problems.&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;C. AWS COnfig &lt;/h4&gt;

&lt;p&gt;AWS Config records and captures resource changes within your environment, allowing you to perform several actions against the data that help optimize resource management in the cloud.&lt;/p&gt;

&lt;p&gt;AWS Config can track changes made to a resource and store the information, including metadata, in a Configuration Item (CI) file. This file can also serve as a resource inventory.&lt;/p&gt;

&lt;p&gt;It can provide information on who made the change and when through AWS CloudTrail integration. &lt;strong&gt;AWS CloudTrail is used with AWS Config to help you identify who made the change and when and with which API.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: AWS Config is region specific.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstatic.us-east-1.prod.workshops.aws%2Fpublic%2F5659531a-ebcf-42ca-bd3f-f5b15e64cda5%2Fstatic%2Fimages%2Flogsinsights%2FCloud-Watch-Insights-Query-Results.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstatic.us-east-1.prod.workshops.aws%2Fpublic%2F5659531a-ebcf-42ca-bd3f-f5b15e64cda5%2Fstatic%2Fimages%2Flogsinsights%2FCloud-Watch-Insights-Query-Results.PNG" alt="" width="800" height="400"&gt;&lt;/a&gt;Image credits: &lt;a href="https://static.us-east-1.prod.workshops.aws/public/5659531a-ebcf-42ca-bd3f-f5b15e64cda5/static/images/logsinsights/Cloud-Watch-Insights-Query-Results.PNG" rel="noopener noreferrer"&gt;https://static.us-east-1.prod.workshops.aws/public/5659531a-ebcf-42ca-bd3f-f5b15e64cda5/static/images/logsinsights/Cloud-Watch-Insights-Query-Results.PNG&lt;/a&gt;&lt;p&gt;&lt;/p&gt;

&lt;h4&gt;D. AWS Cloud front logs &lt;/h4&gt;

&lt;p&gt;Enabling CloudFront access logs allows you to track each user's request for accessing your website and distribution. These logs contain information about the requests made to your CloudFront distributions, such as the request's date and time, the requester's IP address, the URL path, and the response's status code.&lt;/p&gt;

&lt;p&gt;Amazon S3 stores these logs, similar to S3 access logs, providing a durable and persistent storage solution. &lt;strong&gt;Although enabling logging is free, S3 will charge you for the storage used.&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;E. AWS VPC Flow logs&lt;/h4&gt;

&lt;p&gt;VPC Flow Logs allow you to capture IP traffic information between the network interfaces of resources within your VPC. This data aids in resolving network communication incidents and monitoring security by detecting prohibited traffic destinations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: VPC Flow Logs do not store data in S3 but transmit data to CloudWatch logs.&lt;/p&gt;

&lt;p&gt;Before creating VPC Flow Logs, you should know some limitations that may affect their implementation or configuration.&amp;nbsp;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If you have a VPC peered connection, you can only view flow logs of peered VPCs within the same account.&amp;nbsp;&amp;nbsp;&lt;/li&gt;



&lt;li&gt;You cannot modify its configuration once you create a VPC Flow Log. Instead, you need to delete it and create a new one to make changes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;You need an IAM role with the appropriate permissions to send your flow log data to a CloudWatch log group. &lt;/strong&gt;You select this role during the setup configuration of VPC Flow Logs. &lt;/p&gt;

&lt;h3&gt;Recommended practices for storing and analyzing logs in AWS:&lt;/h3&gt;

&lt;p&gt;By following these best practices, you can effectively store and analyze logs in AWS and improve the reliability and performance of your applications.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Define a consistent logging format such as JSON or Apache Log Format.&lt;/li&gt;



&lt;li&gt;Use log rotation to prevent from taking up too much storage space. You can use AWS Elastic Beanstalk helps to automate log rotation.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Set up alerts to notify you of any critical issues in your logs to quickly resolve any issues. Amazon CloudWatch helps to set up alerts based on predefined thresholds or custom metrics.&lt;/li&gt;



&lt;li&gt;Use encryption to protect your log data in transit and at rest. Amazon S3 server-side encryption or Amazon CloudFront field-level encryption helps protect your data,&lt;/li&gt;



&lt;li&gt;You should regularly review and analyze your logs to help identify potential issues. AWS services like Amazon Athena, Amazon Elasticsearch Service, and AWS Glue help you gain insights.&lt;/li&gt;



&lt;li&gt;Use a log aggregation service to centralize your logs across many AWS services. AWS CloudTrail or Amazon CloudWatch Logs helps to centralize your logs.&amp;nbsp;&lt;/li&gt;



&lt;li&gt;Implement a data retention policy that specifies how long you need to keep your log data. To help avoid unnecessary storage costs and ensure compliance with regulatory requirements.&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By monitoring the data within your logs, you can quickly identify potential issues you want to be made aware of as soon as they occur. In addition, by combining this monitoring of logs with thresholds and alerts, you can receive automatic notifications of potential issues, threats, and incidents, before they become production issues.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;By logging what's happening within your applications, network, and other cloud infrastructure, you can build a performance baseline and establish what's routine and what isn't.&lt;/strong&gt;&lt;/p&gt;



</description>
      <category>aws</category>
      <category>database</category>
      <category>performance</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
