<?xml version="1.0" encoding="UTF-8"?>
<rss  xmlns:atom="http://www.w3.org/2005/Atom" 
      xmlns:media="http://search.yahoo.com/mrss/" 
      xmlns:content="http://purl.org/rss/1.0/modules/content/" 
      xmlns:dc="http://purl.org/dc/elements/1.1/" 
      version="2.0">
<channel>
<title>Lahiru De Silva</title>
<link>https://lahirudesilva.com/blog.html</link>
<atom:link href="https://lahirudesilva.com/blog.xml" rel="self" type="application/rss+xml"/>
<description>Kubernetes, Envoy Proxy, Distributed Systems, and lessons from software that scales.</description>
<generator>quarto-1.10.18</generator>
<lastBuildDate>Tue, 14 Apr 2026 00:00:00 GMT</lastBuildDate>
<item>
  <title>Zero Trust Networking for OpenChoreo with Istio Ambient Mesh</title>
  <dc:creator>Lahiru De Silva</dc:creator>
  <link>https://lahirudesilva.com/posts/zero-trust-networking-for-openchoreo-with-istio-ambient-mesh/</link>
  <description><![CDATA[ 






<p>How OpenChoreo Cell architecture and Istio ambient mesh create defense-in-depth for Kubernetes workloads, demonstrated with a simulated NASA Artemis II lunar mission.</p>
<section id="introduction" class="level2">
<h2 class="anchored" data-anchor-id="introduction">Introduction</h2>
<p><a href="https://openchoreo.dev">OpenChoreo</a> is an open-source Internal Developer Platform (IDP) for Kubernetes that recently joined the <a href="https://openchoreo.dev/blog/openchoreo-joins-cncf-and-ships-1-0/">CNCF as a sandbox project</a>. It provides high-level abstractions such as Projects, Components, Endpoints that compile down to Kubernetes resources, letting developers focus on their applications while platform engineers govern the infrastructure.</p>
<p>One of the most powerful architectural concepts in OpenChoreo is the <strong>Cell</strong>, which is a secure isolated runtime boundary inspired by Domain-Driven Design and <a href="https://github.com/wso2/reference-architecture/blob/master/reference-architecture-cell-based.md">Cell-Based Architecture</a>. Each OpenChoreo Project becomes a Cell at runtime: a dedicated Kubernetes namespace with NetworkPolicies that govern ingress/egress traffic of the Cell.</p>
<p>OpenChoreo currently uses standard Kubernetes NetworkPolicies for Cell isolation, which operate at L3/L4. They control <em>which pods can talk to which pods (and on which ports)</em>, but not <em>what HTTP requests are allowed</em>. What if a container inside the Cell is compromised? What if a rogue pod can reach your services but shouldn’t be able to call specific endpoints? NetworkPolicies can’t distinguish a legitimate <code>POST /api/orders</code> from a malicious <code>DELETE /api/users</code>.</p>
<p>This is where <strong>Istio Ambient Mesh</strong> comes in. Istio ambient mesh can handle the full networking layer beneath OpenChoreo, managing both north/south traffic (external ingress/egress via the Istio Gateway API implementation) and east/west traffic (service-to-service communication via ztunnel mTLS and waypoint proxies). It provides transparent encryption and L7 authorization without sidecars, layering perfectly on top of OpenChoreo Cells.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/zero-trust-networking-for-openchoreo-with-istio-ambient-mesh/openchoreo-istio-ambient-mesh.svg" class="img-fluid figure-img"></p>
<figcaption>OpenChoreo + Istio Ambient Mesh Architecture</figcaption>
</figure>
</div>
<p>Together, they create a zero trust networking stack where:</p>
<ul>
<li><strong>OpenChoreo Cells</strong> define <em>what is isolated</em> (namespace boundaries with NetworkPolicies at L3/L4)</li>
<li><strong>Istio Gateway</strong> handles <em>north/south traffic</em> (external ingress via the standard Gateway API)</li>
<li><strong>Istio ztunnel</strong> secures <em>east/west traffic</em> (mTLS encryption with SPIFFE identities for all pod-to-pod communication)</li>
<li><strong>Istio waypoint proxies</strong> enforce <em>what requests are allowed</em> (L7 authorization with identity, method, and path)</li>
</ul>
</section>
<section id="why-istio-ambient-mesh-is-a-natural-fit-for-openchoreo" class="level2">
<h2 class="anchored" data-anchor-id="why-istio-ambient-mesh-is-a-natural-fit-for-openchoreo">Why Istio ambient mesh is a natural fit for OpenChoreo</h2>
<section id="the-cell-waypoint-alignment" class="level3">
<h3 class="anchored" data-anchor-id="the-cell-waypoint-alignment">The Cell-waypoint alignment</h3>
<p>OpenChoreo Cell architecture maps remarkably well to Istio ambient architecture:</p>
<table class="caption-top table">
<colgroup>
<col style="width: 16%">
<col style="width: 41%">
<col style="width: 42%">
</colgroup>
<thead>
<tr class="header">
<th>OpenChoreo Concept</th>
<th>Istio Ambient Equivalent</th>
<th>What It Does</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>Project (Cell)</strong></td>
<td>Namespace with <code>istio.io/dataplane-mode=ambient</code></td>
<td>Defines the isolation boundary</td>
</tr>
<tr class="even">
<td><strong>Cell networking</strong></td>
<td>ztunnel mTLS</td>
<td>Encrypts all traffic both within and across Cells</td>
</tr>
<tr class="odd">
<td><strong>Cell gateway</strong></td>
<td>Waypoint proxy</td>
<td>Enforces L7 policies at the Cell entrance</td>
</tr>
<tr class="even">
<td><strong>Component</strong></td>
<td>Pod with SPIFFE identity</td>
<td>Has a cryptographic identity for authorization</td>
</tr>
</tbody>
</table>
<p>The key insight is that OpenChoreo already creates one namespace per <em>Project-Environment</em> combination. When you label that namespace for ambient mesh enrollment, ztunnel automatically encrypts all <em>pod-to-pod</em> traffic with mTLS. Deploy a waypoint proxy in the namespace, and it becomes the Cell gateway evaluating AuthorizationPolicies before any request reaches your services.</p>
</section>
<section id="why-ambient-not-sidecars" class="level3">
<h3 class="anchored" data-anchor-id="why-ambient-not-sidecars">Why ambient, not sidecars?</h3>
<p>Istio ambient mode (ztunnel + waypoint) is a better fit for OpenChoreo than traditional sidecar injection:</p>
<ol type="1">
<li><strong>No pod mutation</strong> — OpenChoreo manages pod specs through its rendering pipeline. Sidecar injection would require adding an OpenChoreo Trait, losing the transparent encryption and mTLS becomes a developer concern instead of a platform default. Ambient needs only a namespace label.</li>
<li><strong>Namespace-level enrollment</strong> — OpenChoreo already manages namespace lifecycle per Cell. Labeling the namespace enrolls all pods automatically.</li>
<li><strong>Separation of concerns</strong> — ztunnel handles L4 mTLS for all pods, waypoints add L7 only where needed. This cleanly separates responsibilities: platform engineers get encryption everywhere by default, while developers define fine-grained L7 authorization policies based on their business requirements.</li>
<li><strong>Lower resource overhead</strong> — One ztunnel DaemonSet instead of a sidecar per pod.</li>
</ol>
</section>
<section id="using-the-standard-kubernetes-gateway-api" class="level3">
<h3 class="anchored" data-anchor-id="using-the-standard-kubernetes-gateway-api">Using the standard Kubernetes Gateway API</h3>
<p>OpenChoreo generates <code>Gateway</code> and <code>HTTPRoute</code> resources using the standard Kubernetes Gateway API. Istio implements the Kubernetes Gateway API via its <code>istio</code> GatewayClass. This means you can swap the default gateway implementation (<a href="https://kgateway.dev/">kgateway</a>) for Istio by changing a single value:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb1-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Data plane Helm values</span></span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gateway</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb1-3"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gatewayClassName</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> istio</span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"> # instead of "kgateway"</span></span></code></pre></div></div>
<p>The developer experience doesn’t change at all. They still declare endpoints with visibility levels, and the platform handles routing. Istio Envoy-based gateway processes the same HTTPRoutes that kgateway would.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/zero-trust-networking-for-openchoreo-with-istio-ambient-mesh/gateway-api-swap.svg" class="img-fluid figure-img"></p>
<figcaption>Gateway API Swap</figcaption>
</figure>
</div>
</section>
</section>
<section id="from-network-isolation-to-zero-trust-cells" class="level2">
<h2 class="anchored" data-anchor-id="from-network-isolation-to-zero-trust-cells">From network isolation to zero trust Cells</h2>
<p>OpenChoreo Cells already provide strong isolation. Each Project gets its own namespace with NetworkPolicies that restrict which pods can talk to which pods on which ports. But NetworkPolicies operate at L3/L4. They answer <em>“can this IP reach that port?”</em>, not <em>“should this identity be allowed to call that endpoint?”</em>. And all traffic inside the Cell travels as <strong>plaintext</strong>. Any process that can sniff the network can read every request.</p>
<p>Adding Istio ambient mesh transforms Cells from network-isolated boundaries into <strong>zero trust boundaries</strong>:</p>
<section id="what-changes" class="level3">
<h3 class="anchored" data-anchor-id="what-changes">What changes</h3>
<table class="caption-top table">
<colgroup>
<col style="width: 18%">
<col style="width: 31%">
<col style="width: 50%">
</colgroup>
<thead>
<tr class="header">
<th></th>
<th><strong>OpenChoreo Cell (default)</strong></th>
<th><strong>OpenChoreo Cell + Istio Ambient</strong></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>Traffic encryption</strong></td>
<td>Plaintext (unencrypted)</td>
<td>mTLS via ztunnel (HBONE)</td>
</tr>
<tr class="even">
<td><strong>Identity model</strong></td>
<td>IP-based (source pod IP)</td>
<td>Cryptographic SPIFFE identity per ServiceAccount</td>
</tr>
<tr class="odd">
<td><strong>Network policy</strong></td>
<td>L3/L4 NetworkPolicies (port + IP)</td>
<td>L3/L4 NetworkPolicies + L7 AuthorizationPolicies (identity + method + path)</td>
</tr>
<tr class="even">
<td><strong>Intra-cell visibility</strong></td>
<td>Any pod in the namespace can reach any port</td>
<td>Any pod can connect, but waypoint enforces identity-based access</td>
</tr>
<tr class="odd">
<td><strong>Cross-cell authorization</strong></td>
<td>Allowed/denied by namespace-level NetworkPolicy</td>
<td>Allowed/denied by SPIFFE identity + HTTP method + path</td>
</tr>
<tr class="even">
<td><strong>Compromised container</strong></td>
<td>Full access to all services in the Cell</td>
<td>Blocked — unknown identity is implicitly denied</td>
</tr>
</tbody>
</table>
</section>
<section id="the-three-layer-defense" class="level3">
<h3 class="anchored" data-anchor-id="the-three-layer-defense">The three layer defense</h3>
<p>These layers are <em>additive, not replacements</em>. A request must pass all three to reach a service:</p>
<ol type="1">
<li><p><strong>OpenChoreo NetworkPolicies (L3/L4)</strong> — The perimeter. Controls which namespaces and pods can establish connections. Blocks external traffic that shouldn’t reach the Cell at all.</p></li>
<li><p><strong>Istio ztunnel (L4 mTLS)</strong> — The encryption layer. Every pod-to-pod connection is wrapped in mTLS via the <a href="https://istio.io/latest/docs/ambient/architecture/hbone/">HBONE protocol</a>. Each pod gets a <strong>SPIFFE identity</strong> (<code>cluster.local/ns/&lt;namespace&gt;/sa/&lt;service-account&gt;</code>) which is a cryptographic certificate that proves <em>who</em> is making the request, not just <em>where</em> the request comes from.</p></li>
<li><p><strong>Istio waypoint proxy (L7 authorization)</strong> — The policy enforcement point. Deployed per-namespace, the waypoint acts as the Cell gateway. It evaluates <code>AuthorizationPolicy</code> rules that match on SPIFFE identity, HTTP method, and path before forwarding traffic to the destination service.</p></li>
</ol>
<table class="caption-top table">
<colgroup>
<col style="width: 23%">
<col style="width: 27%">
<col style="width: 49%">
</colgroup>
<thead>
<tr class="header">
<th>Layer</th>
<th>Blocks</th>
<th>Passes</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>OpenChoreo NetworkPolicy</strong></td>
<td>External namespaces, unknown pods</td>
<td>Same-namespace traffic, declared dependencies</td>
</tr>
<tr class="even">
<td><strong>Istio ztunnel (mTLS)</strong></td>
<td>Unencrypted traffic</td>
<td>All traffic (encrypted), assigns SPIFFE identity</td>
</tr>
<tr class="odd">
<td><strong>Istio Waypoint (AuthzPolicy)</strong></td>
<td>Unknown identities, wrong method/path</td>
<td>Only requests from authorized identities to permitted methods/paths</td>
</tr>
</tbody>
</table>
<p>A rogue pod deployed within the Cell passes Layer 1 (same namespace) and Layer 2 (gets encrypted with its own identity), but is <strong>implicitly denied at Layer 3</strong> as its SPIFFE identity doesn’t match any ALLOW rule. Even if an existing pod is compromised, the attacker is constrained to only the methods and paths that pod’s identity is authorized for.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/zero-trust-networking-for-openchoreo-with-istio-ambient-mesh/defense-layers.svg" class="img-fluid figure-img"></p>
<figcaption>Defense Layers</figcaption>
</figure>
</div>
</section>
</section>
<section id="nasa-artemis-ii-lunar-mission-demo" class="level2">
<h2 class="anchored" data-anchor-id="nasa-artemis-ii-lunar-mission-demo">NASA Artemis II lunar mission demo</h2>
<p>To demonstrate the power of OpenChoreo + Istio Ambient Mesh, a simulated NASA Artemis II mission was built with 5 OpenChoreo Projects (Cells) containing 18 microservices:</p>
<section id="mission-entities-as-cells" class="level3">
<h3 class="anchored" data-anchor-id="mission-entities-as-cells">Mission entities as Cells</h3>
<table class="caption-top table">
<colgroup>
<col style="width: 15%">
<col style="width: 44%">
<col style="width: 39%">
</colgroup>
<thead>
<tr class="header">
<th>Cell (Project)</th>
<th>Components</th>
<th>Role</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>Houston</strong></td>
<td>flight-director, capcom, telemetry-monitor, flight-dynamics</td>
<td>Mission control — commands, decisions, telemetry</td>
</tr>
<tr class="even">
<td><strong>Kennedy</strong></td>
<td>launch-control, ground-systems, weather-station, pad-operations</td>
<td>Launch operations at LC-39B</td>
</tr>
<tr class="odd">
<td><strong>Orion</strong></td>
<td>guidance-nav, life-support, crew-interface, comms-system</td>
<td>The spacecraft — navigation, crew health, communications</td>
</tr>
<tr class="even">
<td><strong>Deep Space Network</strong></td>
<td>signal-router, goldstone, madrid, canberra</td>
<td>Global antenna array — signal relay</td>
</tr>
<tr class="odd">
<td><strong>ESA Ops</strong></td>
<td>service-module-monitor, mission-relay</td>
<td>European Service Module monitoring</td>
</tr>
</tbody>
</table>
<p>Each Project becomes a Cell at runtime which is an isolated namespace with its own NetworkPolicies:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb2-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apiVersion</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> openchoreo.dev/v1alpha1</span></span>
<span id="cb2-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">kind</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Project</span></span>
<span id="cb2-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">metadata</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb2-4"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">name</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> orion</span></span>
<span id="cb2-5"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">namespace</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> default</span></span>
<span id="cb2-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">spec</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb2-7"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">deploymentPipelineRef</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb2-8"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">name</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> default</span></span></code></pre></div></div>
<p>Components are deployed as services inside each Cell:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb3-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apiVersion</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> openchoreo.dev/v1alpha1</span></span>
<span id="cb3-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">kind</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Component</span></span>
<span id="cb3-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">metadata</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb3-4"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">name</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> guidance-nav</span></span>
<span id="cb3-5"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">namespace</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> default</span></span>
<span id="cb3-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">spec</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb3-7"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">owner</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb3-8"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">projectName</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> orion</span></span>
<span id="cb3-9"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">autoDeploy</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">true</span></span>
<span id="cb3-10"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">componentType</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb3-11"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">kind</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> ClusterComponentType</span></span>
<span id="cb3-12"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">name</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> deployment/service</span></span></code></pre></div></div>
</section>
<section id="artemis-ii-cell-architecture" class="level3">
<h3 class="anchored" data-anchor-id="artemis-ii-cell-architecture">Artemis II Cell architecture</h3>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/zero-trust-networking-for-openchoreo-with-istio-ambient-mesh/artemis-cell-architecture.svg" class="img-fluid figure-img"></p>
<figcaption>Artemis II Communication Map</figcaption>
</figure>
</div>
<p>Each Cell communicates only with the Cells its mission role demands. No more, no less:</p>
<ul>
<li><strong>Houston → Orion</strong>: CAPCOM uplinks commands to the spacecraft comms-system</li>
<li><strong>Orion → DSN → Houston</strong>: Telemetry flows through the Deep Space Network back to mission control</li>
<li><strong>Kennedy → Houston</strong>: Launch control hands off to the flight director after liftoff</li>
<li><strong>ESA → Houston</strong>: The European Service Module monitor relays health data to mission control</li>
</ul>
<p>The demo includes a mission control dashboard where you can simulate adversaries, observe how each defense layer responds, and neutralize threats in real time to see zero trust networking in action.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/zero-trust-networking-for-openchoreo-with-istio-ambient-mesh/artemis-ii-launch.png" class="img-fluid figure-img"></p>
<figcaption>Artemis II launch</figcaption>
</figure>
</div>
</section>
</section>
<section id="a-rogue-pod-inside-the-cell" class="level2">
<h2 class="anchored" data-anchor-id="a-rogue-pod-inside-the-cell">A rogue pod inside the Cell</h2>
<p>A rogue pod gets deployed inside the Orion Cell namespace. Maybe an attacker gained access to the cluster through a misconfigured RBAC role, a leaked kubeconfig, or a CI/CD pipeline vulnerability. The pod runs with its own ServiceAccount and has full network access within the namespace.</p>
<p>As OpenChoreo NetworkPolicies operate at L3/L4, they can’t distinguish a legitimate <code>POST /uplink</code> from CAPCOM versus a malicious one from a rogue pod.</p>
<p>Without additional security, it can:</p>
<ol type="1">
<li><strong>Abort the mission</strong> — <code>POST /decision/abort</code> to Houston flight-director</li>
<li><strong>Hijack navigation</strong> — <code>POST /maneuver</code> to Orion guidance-nav, sending the spacecraft off course</li>
<li><strong>Steal classified crew data</strong> — <code>GET /crew/vitals</code> from Orion life-support</li>
<li><strong>Send fake commands</strong> — <code>POST /uplink</code> to Orion comms-system, impersonating CAPCOM</li>
</ol>
<pre><code>$ curl -X POST http://guidance-nav:8080/maneuver
{"status":"acknowledged","type":"course-correction","deltaV":"2.3 m/s"}
# 200 OK. No questions asked.</code></pre>
</section>
<section id="securing-the-mission-with-istio-ambient" class="level2">
<h2 class="anchored" data-anchor-id="securing-the-mission-with-istio-ambient">Securing the mission with Istio ambient</h2>
<section id="layer-1-encrypt-with-ztunnel-mtls-spiffe-identities" class="level3">
<h3 class="anchored" data-anchor-id="layer-1-encrypt-with-ztunnel-mtls-spiffe-identities">Layer 1: Encrypt with ztunnel (mTLS + SPIFFE identities)</h3>
<p>Label each Cell namespace to enroll in the ambient mesh:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb5-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kubectl</span> label namespace <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>cell-namespace<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> istio.io/dataplane-mode=ambient</span></code></pre></div></div>
<p>This does two things:</p>
<ol type="1">
<li><strong>Encrypts all traffic</strong> between pods using mTLS via the <a href="https://istio.io/latest/docs/ambient/architecture/hbone/">HBONE protocol</a></li>
<li><strong>Assigns SPIFFE identities</strong> to every pod based on its ServiceAccount</li>
</ol>
<p>After enrollment, every pod gets a cryptographic identity: <code>cluster.local/ns/&lt;namespace&gt;/sa/&lt;service-account&gt;</code></p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/zero-trust-networking-for-openchoreo-with-istio-ambient-mesh/ztunnel-mtls.svg" class="img-fluid figure-img"></p>
<figcaption>ztunnel mTLS</figcaption>
</figure>
</div>
<p>Verify all pods are enrolled in HBONE:</p>
<pre><code>$ istioctl ztunnel-config workloads | grep dp-default-orion
dp-default-orion-...  comms-system-...    10.42.0.131  HBONE
dp-default-orion-...  guidance-nav-...    10.42.0.132  HBONE
dp-default-orion-...  life-support-...    10.42.0.134  HBONE
dp-default-orion-...  crew-interface-...  10.42.0.133  HBONE</code></pre>
<p>All traffic is now mTLS encrypted. But encryption alone doesn’t stop the adversary, it just ensures they can’t eavesdrop on <em>other</em> traffic. They can still make requests.</p>
</section>
<section id="layer-2-enforce-with-waypoint-proxies" class="level3">
<h3 class="anchored" data-anchor-id="layer-2-enforce-with-waypoint-proxies">Layer 2: Enforce with waypoint proxies</h3>
<p>Waypoint proxies add L7 policy enforcement to the Cell. Think of them as the Cell security checkpoint where every request entering the namespace flows through the waypoint, where AuthorizationPolicies are evaluated.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb7-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">istioctl</span> waypoint apply <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-n</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span>cell-namespace<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> --enroll-namespace</span></code></pre></div></div>
<p>This creates an Envoy-based waypoint proxy (using the <code>istio-waypoint</code> GatewayClass) and labels the namespace so ztunnel routes all inbound traffic through it.</p>
<p>The waypoint naturally acts as a <strong>Cell gateway</strong> which is the L7 entrance point where identity based access control is enforced. This aligns perfectly with OpenChoreo Cell Architecture, where all cross-cell communication should flow through well defined gateways.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/zero-trust-networking-for-openchoreo-with-istio-ambient-mesh/waypoint-proxy.svg" class="img-fluid figure-img"></p>
<figcaption>Waypoint Proxy</figcaption>
</figure>
</div>
<p>Now the critical part is defining <em>who</em> can access <em>what</em>. Our approach is pure zero trust: <strong>allow only known identities, implicitly deny everything else</strong>.</p>
<p>For example, refer the <code>AuthorizationPolicy</code> for Orion comms-system. It combines <strong>principal-based identity</strong> (SPIFFE identities matching specific ServiceAccounts) with <strong>HTTP route enforcement</strong> (method and path):</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb8-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apiVersion</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> security.istio.io/v1</span></span>
<span id="cb8-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">kind</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> AuthorizationPolicy</span></span>
<span id="cb8-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">metadata</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb8-4"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">name</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> comms-system-policy</span></span>
<span id="cb8-5"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">namespace</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> dp-default-orion-development-&lt;hash&gt;</span></span>
<span id="cb8-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">spec</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb8-7"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">targetRefs</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb8-8"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">kind</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Service</span></span>
<span id="cb8-9"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">group</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span></span>
<span id="cb8-10"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">name</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> comms-system</span></span>
<span id="cb8-11"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">action</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> ALLOW</span></span>
<span id="cb8-12"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rules</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb8-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    # Houston can uplink commands</span></span>
<span id="cb8-14"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">from</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb8-15"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">source</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb8-16"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">            </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">principals</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb8-17"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">              </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cluster.local/ns/dp-default-houston-development-&lt;hash&gt;/sa/default"</span></span>
<span id="cb8-18"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">to</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb8-19"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">operation</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb8-20"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">            </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">methods</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"POST"</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">]</span></span>
<span id="cb8-21"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">            </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paths</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"/uplink"</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">,</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"/uplink/*"</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">]</span></span>
<span id="cb8-22"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    # DSN can request downlink</span></span>
<span id="cb8-23"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">from</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb8-24"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">source</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb8-25"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">            </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">principals</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb8-26"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">              </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cluster.local/ns/dp-default-deep-space-ne-development-&lt;hash&gt;/sa/default"</span></span>
<span id="cb8-27"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">to</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb8-28"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">operation</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb8-29"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">            </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">methods</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"POST"</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">]</span></span>
<span id="cb8-30"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">            </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paths</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"/downlink"</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">]</span></span>
<span id="cb8-31"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    # Intra-cell: only default SA</span></span>
<span id="cb8-32"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">from</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb8-33"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">source</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb8-34"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">            </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">principals</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb8-35"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">              </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"cluster.local/ns/dp-default-orion-development-&lt;hash&gt;/sa/default"</span></span></code></pre></div></div>
<p>Each rule defines <em>who</em> (the SPIFFE principal) and <em>what</em> (the HTTP method and path). Houston CAPCOM can <code>POST /uplink</code> but can’t <code>GET /downlink</code>. The Deep Space Network can <code>POST /downlink</code> but can’t touch <code>/uplink</code>. Intra-cell traffic from the Orion namespace is allowed on all paths but only from the <code>default</code> ServiceAccount.</p>
<p>There are no DENY policies. If your identity isn’t in the allowlist, the waypoint implicitly denies the request. Every service in every Cell gets a policy like this, each one tailored to the exact communication paths that service needs.</p>
</section>
</section>
<section id="abstracting-istio-complexity-with-openchoreo" class="level2">
<h2 class="anchored" data-anchor-id="abstracting-istio-complexity-with-openchoreo">Abstracting Istio complexity with OpenChoreo</h2>
<p>The AuthorizationPolicies, waypoint proxy configurations, and SPIFFE identity mappings shown above are powerful but too low level for developers to work with directly. Platform engineers shouldn’t expect developers to author these Istio specific resources directly. This is where OpenChoreo programmable abstraction layer <a href="https://openchoreo.dev/docs/developer-guide/projects-and-components/overview/#componenttypes-and-traits">ComponentTypes and Traits</a> comes in.</p>
<p>Platform engineers can encode all of this Istio complexity into <strong>ComponentTypes</strong> (deployment blueprints that define what Kubernetes resources get created) and <strong>Traits</strong> (reusable cross cutting concerns that attach to Components). For example, a platform engineer could create a <code>zero-trust-service</code> ComponentType that automatically generates the waypoint proxy enrollment and a baseline AuthorizationPolicy alongside the Deployment and Service. An <code>istio-authz</code> Trait could let developers declare allowed callers with a simple interface:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb9-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">traits</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb9-2"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">kind</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> ClusterTrait</span></span>
<span id="cb9-3"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">name</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> istio-authz</span></span>
<span id="cb9-4"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">instanceName</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> comms-policy</span></span>
<span id="cb9-5"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">parameters</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb9-6"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">allowFrom</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb9-7"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">project</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> houston</span></span>
<span id="cb9-8"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">          </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">methods</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"POST"</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">]</span></span>
<span id="cb9-9"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">          </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paths</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"/uplink"</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">,</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"/uplink/*"</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">]</span></span>
<span id="cb9-10"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">project</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> deep-space-network</span></span>
<span id="cb9-11"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">          </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">methods</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"POST"</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">]</span></span>
<span id="cb9-12"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">          </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paths</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">[</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"/downlink"</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">]</span></span></code></pre></div></div>
<p>Behind the scenes, the Trait template renders the full <code>AuthorizationPolicy</code> with SPIFFE principals, namespace mappings, and method/path rules. The developer never sees <code>security.istio.io/v1</code> or <code>cluster.local/ns/...</code>. Instead they work with project names, HTTP methods, and paths. The platform engineer owns the template, controls the security posture, and can update the underlying Istio configuration across all Components without requiring developer changes.</p>
</section>
<section id="key-takeaways" class="level2">
<h2 class="anchored" data-anchor-id="key-takeaways">Key takeaways</h2>
<section id="openchoreo-cells-istio-ambient-defense-in-depth" class="level3">
<h3 class="anchored" data-anchor-id="openchoreo-cells-istio-ambient-defense-in-depth">1. OpenChoreo Cells + Istio ambient = defense in depth</h3>
<p>OpenChoreo Cell Architecture provides the L3/L4 perimeter. Istio ambient mesh adds L4 encryption and L7 authorization inside the perimeter. Neither alone is sufficient and together they cover the full stack.</p>
</section>
<section id="zero-trust-is-allow-known-deny-unknown" class="level3">
<h3 class="anchored" data-anchor-id="zero-trust-is-allow-known-deny-unknown">2. Zero trust is “allow known, deny unknown”</h3>
<p>The most effective security model doesn’t try to enumerate attackers. It enumerates <em>legitimate callers</em> and denies everything else. Istio AuthorizationPolicies with SPIFFE identities make this practical. You define who should have access, and the cryptographic identity system ensures no one can fake it.</p>
</section>
<section id="waypoint-proxies-as-cell-gateways" class="level3">
<h3 class="anchored" data-anchor-id="waypoint-proxies-as-cell-gateways">3. Waypoint proxies as Cell gateways</h3>
<p>Istio waypoint proxies are a natural fit for OpenChoreo Cell architecture. Each Cell gets its own waypoint that acts as the L7 entrance point, evaluating identity, method, and path before any request reaches the application. This is the missing piece between OpenChoreo network isolation and full zero trust.</p>
</section>
<section id="developer-abstractions-hide-infrastructure-complexity" class="level3">
<h3 class="anchored" data-anchor-id="developer-abstractions-hide-infrastructure-complexity">4. Developer abstractions hide infrastructure complexity</h3>
<p>OpenChoreo ComponentTypes and Traits can encapsulate Istio specific resources like AuthorizationPolicies, waypoint configurations, and SPIFFE identity mappings into developer friendly interfaces. Platform engineers define the templates once, developers consume them with simple parameters like project names and allowed paths, never touching raw Istio manifests. This separation lets the platform team evolve the underlying security infrastructure without breaking the developer experience.</p>
</section>
<section id="gateway-api-as-the-universal-contract" class="level3">
<h3 class="anchored" data-anchor-id="gateway-api-as-the-universal-contract">5. Gateway API as the universal contract</h3>
<p>OpenChoreo uses the Kubernetes Gateway API for routing. Istio implements the same API. Swapping the gateway implementation is a single <code>gatewayClassName</code> change. The developer experience is identical, the platform engineer chooses the infrastructure.</p>
</section>
</section>
<section id="try-it-yourself" class="level2">
<h2 class="anchored" data-anchor-id="try-it-yourself">Try it yourself</h2>
<p>The complete Artemis II demo including installation instructions, deployment steps, and all manifests is available at <a href="https://github.com/NomadXD/samples/tree/main/artemis-ii-istio-openchoreo">github.com/NomadXD/samples/artemis-ii-istio-openchoreo</a>. The demo use the OpenChoreo single cluster k3d setup and includes:</p>
<ul>
<li>A configurable Go microservice (one binary, 18 deployments)</li>
<li>5 OpenChoreo Project manifests with 18 Components</li>
<li>Istio ambient mesh configuration, waypoint proxies, and AuthorizationPolicies</li>
<li>An adversary simulation with real API calls through the Istio gateway</li>
</ul>
<hr>
<p><em>OpenChoreo is a CNCF Sandbox project. Learn more at <a href="https://openchoreo.dev">openchoreo.dev</a>.</em></p>
<p><em>Istio ambient mesh is GA as of Istio 1.24. Learn more at <a href="https://istio.io/latest/docs/ambient/">istio.io/latest/docs/ambient/</a>.</em></p>


</section>

 ]]></description>
  <category>Kubernetes</category>
  <category>Networking</category>
  <category>Istio</category>
  <category>Security</category>
  <guid>https://lahirudesilva.com/posts/zero-trust-networking-for-openchoreo-with-istio-ambient-mesh/</guid>
  <pubDate>Tue, 14 Apr 2026 00:00:00 GMT</pubDate>
  <media:content url="https://lahirudesilva.com/posts/zero-trust-networking-for-openchoreo-with-istio-ambient-mesh/artemis-ii-cover.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>From Broken Network Drivers to a Working Kubernetes Cluster on Decade-Old Hardware</title>
  <dc:creator>Lahiru De Silva</dc:creator>
  <link>https://lahirudesilva.com/posts/from-broken-network-drivers-to-a-working-k8s-cluster/</link>
  <description><![CDATA[ 






<p>What began as a simple idea - <em>“let me reuse my old gaming laptop as a Kubernetes homelab”</em>, turned into a series of interesting challenges. On paper, the plan was straightforward: install Proxmox, spin up a couple of virtual machines, bootstrap a Kubernetes cluster using Kubeadm, and call it a day. In reality, the process became a deep dive through Linux kernel headers, broken network drivers, offline package installs, and typical networking subnet issues.</p>
<section id="setup-objectives-motivation" class="level2">
<h2 class="anchored" data-anchor-id="setup-objectives-motivation">Setup, objectives &amp; motivation</h2>
<p><strong>The Setup:</strong> A decade-old gaming laptop with an Intel Core i7 processor with 4 cores and 16 GB RAM (ASUS ROG GL 753VD with Intel Core i7-7700HQ @ 3.80 GHz).</p>
<p><strong>The Objective:</strong></p>
<ul>
<li>Run Proxmox VE as the base hypervisor</li>
<li>Deploy 2-3 virtual machines</li>
<li>Build a multi-node Kubernetes cluster using kubeadm</li>
</ul>
<p><strong>The Motivation:</strong></p>
<ul>
<li>A local environment for testing CNIs, K8s configs, linux networking etc.</li>
<li>To prepare for the upcoming CKS exam by doing the course labs in the local cluster</li>
<li>Turn a retired gaming laptop covered with dust into something useful</li>
</ul>
</section>
<section id="proxmox-installation---secure-boot-was-not-the-real-problem" class="level2">
<h2 class="anchored" data-anchor-id="proxmox-installation---secure-boot-was-not-the-real-problem">Proxmox installation - Secure Boot was not the real problem</h2>
<p>I started with a clean Proxmox VE installation using a USB flash drive as described in the <a href="https://pve.proxmox.com/wiki/Prepare_Installation_Media#installation_prepare_media">official docs</a>. The installation went smoothly, but after rebooting, Proxmox failed to boot properly with the following error.</p>
<pre><code>Could not create MokListTrustedRT: Volume full
Something has gone seriously wrong: import_mok_state() failed: Volume Full</code></pre>
<p>For context, MOK (Machine Owner Key) entries are cryptographic keys used by bootloaders to verify signed kernel modules when Secure Boot is enabled. They’re typically stored in EFI NVRAM and allow users to trust custom or third-party drivers that aren’t signed by the hardware vendor.</p>
<p>At first glance, this made no sense. Secure Boot was already disabled in BIOS.</p>
<p>I investigated the issue further and discovered the root cause: even with Secure Boot disabled, stale MOK (Machine Owner Key) entries were still present in EFI NVRAM from previous OS installations. These leftover entries were confusing the boot chain and filling up the NVRAM storage, preventing Proxmox from storing its own boot variables.</p>
<p>The solution was performing a hard reset for NVRAM. I powered off the machine, held the power button for approximately 30 seconds to perform a NVRAM reset, then booted again. This forces the BIOS to re-initialize the NVRAM variables. On many ASUS motherboards, this clears out temporary “garbage” entries in the UEFI storage, freeing up just enough space for the MokList to be created so you could boot again.</p>
<p>After this reset, all the stale entries were cleared, and Proxmox booted cleanly without any issues.</p>
</section>
<section id="network-interfaces-are-down" class="level2">
<h2 class="anchored" data-anchor-id="network-interfaces-are-down">Network interfaces are DOWN</h2>
<p>After installation, Proxmox came up BUT networking didn’t.</p>
<p>This turned out to be the major issue that consumed most of my troubleshooting time. I initially tried bringing the interfaces up manually, but nothing worked. After digging through ChatGPT responses, Google searches, and various Proxmox forums, I finally uncovered the root cause.</p>
<p>Proxmox 9 uses Debian 13 under the hood, which defaults to the <code>r8169</code> kernel module (maintained by the Linux kernel team) for Realtek Ethernet controllers. Unfortunately, this module has compatibility issues with certain Realtek hardware. The solution was to use the <code>r8168</code> module instead, which is maintained directly by Realtek and provides better hardware support.</p>
<p>The challenge? Without a working network connection, I needed to perform an offline installation of the <code>r8168</code> module and blacklist the <code>r8169</code> kernel module to prevent it from loading.</p>
</section>
<section id="offline-dependency-hell" class="level2">
<h2 class="anchored" data-anchor-id="offline-dependency-hell">Offline dependency hell</h2>
<p>From another machine with internet access, I downloaded the following <code>.deb</code> packages:</p>
<section id="proxmox-headers-6.17.2-1-pve_amd64.deb" class="level3">
<h3 class="anchored" data-anchor-id="proxmox-headers-6.17.2-1-pve_amd64.deb">1. proxmox-headers-6.17.2-1-pve_amd64.deb</h3>
<p>This provides the kernel headers for the exact Proxmox kernel I was running. These headers describe the internal APIs of the kernel and are mandatory for compiling any out-of-tree kernel module. Without them, the driver simply cannot be built.</p>
</section>
<section id="dkms_3.2.2-1deb13u1_all.deb" class="level3">
<h3 class="anchored" data-anchor-id="dkms_3.2.2-1deb13u1_all.deb">2. dkms_3.2.2-1~deb13u1_all.deb</h3>
<p>This installs the Dynamic Kernel Module Support (DKMS) framework.</p>
<p>DKMS is responsible for: - Building kernel modules from source - Integrating them with the running kernel - Rebuilding them automatically when the kernel changes</p>
<p>In short, DKMS is the glue between driver source code and the kernel.</p>
</section>
<section id="r8168-dkms_8.055.00-1_all.deb" class="level3">
<h3 class="anchored" data-anchor-id="r8168-dkms_8.055.00-1_all.deb">3. r8168-dkms_8.055.00-1_all.deb</h3>
<p>This contains the Realtek r8168 driver source code, along with DKMS metadata.</p>
<p>This package does not ship a precompiled driver. Instead, it provides: - The driver source - Build instructions (<code>dkms.conf</code>) - Hooks that tell DKMS how to compile it into a <code>.ko</code> module</p>
<p>When installed, DKMS uses this package to compile the actual kernel driver.</p>
<pre><code>r8168-dkms.deb
   │
   ├── driver source code
   ├── dkms.conf
   │
   ▼
DKMS
   │
   ├── uses kernel headers
   ├── runs make
   │
   ▼
r8168.ko
   │
   ▼
Kernel module loaded</code></pre>
<p>I copied the three required <code>.deb</code> packages onto a USB flash drive, mounted it on the Proxmox host, and attempted to install them using dpkg. As I suspected, the installation quickly failed due to unresolved dependencies, which couldn’t be fetched because the system was completely offline.</p>
<p>This is where I paused and reassessed the situation and eventually looked for a temporary way to get internet access, just long enough to fix the driver properly.</p>
</section>
</section>
<section id="a-temporary-network-lifeline" class="level2">
<h2 class="anchored" data-anchor-id="a-temporary-network-lifeline">A temporary network lifeline</h2>
<p>At this point, I asked ChatGPT for alternatives to get temporary internet access on the Proxmox host, just long enough to fix the broken NIC driver properly.</p>
<p>Two options came up: - USB tethering using a mobile phone - A USB to Ethernet adapter</p>
<p>I decided to try them in that order.</p>
<section id="usb-tethering" class="level3">
<h3 class="anchored" data-anchor-id="usb-tethering">USB tethering</h3>
<p>I started with USB tethering, hoping it would be the quickest path forward. The interface did show up on the system, but it was in a <code>DOWN</code> state. I tried to bring it up manually, and it transitioned from <code>DOWN</code> to <code>UNKNOWN</code>, but there was still no sign of connectivity - ping attempts failed completely.</p>
<p>After hours of debugging already behind me, this felt like yet another rabbit hole. At that point, I made a call to stop digging.</p>
</section>
<section id="the-usb-adapter-that-saved-the-day" class="level3">
<h3 class="anchored" data-anchor-id="the-usb-adapter-that-saved-the-day">The USB adapter that saved the day</h3>
<p>I was feeling hopeless at this point and almost ready to call it off for the day. But then I suddenly remembered something I’d completely forgotten about; the Baseus 6-in-1 USB-C adapter sitting in my bag.</p>
<p>It has an Ethernet port. Ironically, this was something my coworkers and I had joked about at the office before. None of us could quite justify why a USB adapter would even need an Ethernet port, especially in a world dominated by Wi-Fi. Turns out, this was exactly why.</p>
<p>I plugged the adapter into the laptop, connected an Ethernet cable, and within seconds the interface came up cleanly, obtained an IP address, and for the first time, the Proxmox host had stable internet access. No weird logs. No half-working interfaces. It just worked.</p>
<div class="quarto-figure quarto-figure-center" style="max-width: 600px; width: 100%;">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/from-broken-network-drivers-to-a-working-k8s-cluster/proxmox-setup-usb-adapter.jpg" class="img-fluid figure-img"></p>
<figcaption>The Baseus 6-in-1 USB-C adapter — its Ethernet port provided the temporary network lifeline that saved the day.</figcaption>
</figure>
</div>
<p>Unlike the onboard Realtek NIC, the USB Ethernet adapter uses a completely different chipset and driver, one that’s well-supported by the Linux kernel out of the box (most adapters use ASIX or AX88179 chip, which are supported in kernels ≥5.x).</p>
<p>That clean, temporary network connection was all I needed to: - Perform a system update - Install dkms, pve kernel headers and realtek r8168 driver</p>
<p>After installing the <code>r8168</code> driver, I blacklisted the built-in <code>r8169</code> driver to prevent it from loading and performed a reboot. After the reboot, finally, the <code>nic0</code> and <code>vmbr0</code> (Proxmox bridge) interfaces came up successfully.</p>
</section>
</section>
<section id="bridge-network-subnet-mismatch" class="level2">
<h2 class="anchored" data-anchor-id="bridge-network-subnet-mismatch">Bridge network subnet mismatch</h2>
<p>After fixing the Realtek driver and finally getting <code>nic0</code> into an UP state, I expected networking to just work. It didn’t. - The interface was up. - The bridge was up. - The link carrier was detected.</p>
<p>And yet nothing could reach the outside world. At first glance, everything looked healthy: - <code>nic0</code> showed UP - <code>vmbr0</code> showed UP</p>
<p>But basic connectivity checks failed. A closer look at the routing configuration revealed the real issue.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/from-broken-network-drivers-to-a-working-k8s-cluster/proxmox-setup-ping-failure.jpg" class="img-fluid figure-img"></p>
<figcaption>Ping failure</figcaption>
</figure>
</div>
<p>The Proxmox host was configured for the <code>192.168.100.0/24</code> subnet. However, my actual home network - the router, DHCP server, and other devices lived on <code>192.168.1.0/24</code>.</p>
<p>In other words: - The bridge was working perfectly just on the wrong network. - The system was trying to reach a gateway that didn’t exist.</p>
<section id="why-this-happened" class="level3">
<h3 class="anchored" data-anchor-id="why-this-happened">Why this happened</h3>
<p>During the initial Proxmox installation, I accepted the default network configuration. At the time, the <code>nic0</code> wasn’t working, so there was no immediate feedback that anything was wrong.</p>
<p>Once the driver issue was fixed, the misconfiguration surfaced: - <code>vmbr0</code> had a static IP in a non-existent subnet - The gateway pointed to an unreachable address - ARP requests never received replies</p>
<p>This is a particularly nasty class of issue because: - Interfaces appear healthy - No errors are logged - Everything looks correct unless you verify the subnet end-to-end.</p>
<p>The solution was straightforward once the problem was clear. I updated the bridge configuration to match my actual LAN in <code>/etc/network/interfaces</code>.</p>
<pre><code>auto lo
iface lo inet loopback

iface nic0 inet manual

auto vmbr0
iface vmbr0 inet static
    address 192.168.1.50/24
    gateway 192.168.1.1
    bridge-ports nic0
    bridge-stp off
    bridge-fd 0</code></pre>
<p>After restarting the network service with <code>systemctl restart networking</code>: - The gateway responded - Internet access worked - The Proxmox web UI became reachable from other machines in the LAN</p>
</section>
</section>
<section id="spinning-up-the-kubernetes-cluster" class="level2">
<h2 class="anchored" data-anchor-id="spinning-up-the-kubernetes-cluster">Spinning up the Kubernetes cluster</h2>
<p>With the Proxmox host finally stable and reachable over the LAN, the rest of the setup felt refreshingly straightforward.</p>
<p>From another machine on the same network, I accessed the Proxmox Web UI and created two virtual machines, both running Ubuntu 22.04:</p>
<p>Control Plane - 2 vCPUs - 4 GB RAM</p>
<p>Worker Node - 1 vCPU - 2 GB RAM</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/from-broken-network-drivers-to-a-working-k8s-cluster/proxmox-setup-vms.png" class="img-fluid figure-img"></p>
<figcaption>ProxMox VMs</figcaption>
</figure>
</div>
<p>Both VMs were attached to the same bridge interface <code>vmbr0</code>, allowing them to behave like first-class citizens on the local network.</p>
<section id="bootstrapping-kubernetes" class="level3">
<h3 class="anchored" data-anchor-id="bootstrapping-kubernetes">Bootstrapping Kubernetes</h3>
<p>Once the VMs were up, I used <code>kubeadm</code> to initialize the Kubernetes control plane and join the worker node to the cluster. With the networking issues behind me, the cluster came up cleanly and behaved exactly as expected.</p>
<p>Pods could communicate, services resolved correctly, and the environment finally felt “boringly stable”.</p>
</section>
<section id="headroom-for-growth" class="level3">
<h3 class="anchored" data-anchor-id="headroom-for-growth">Headroom for growth</h3>
<p>Even after provisioning the 2 VMs, Proxmox itself was only using about half of the available memory. That leaves plenty of headroom to: - Add another worker node - Experiment with multi-node or multi-cluster setups - Run additional infrastructure components alongside Kubernetes</p>
<p>Not bad for a decade old laptop after all !!!</p>
</section>
</section>
<section id="references" class="level2">
<h2 class="anchored" data-anchor-id="references">References</h2>
<ul>
<li><a href="https://forum.proxmox.com/threads/unable-to-install-r8168-dkms-for-realtek-nic.137727/?utm_source=chatgpt.com">unable to install r8168-dkms for Realtek NIC</a></li>
<li><a href="https://forum.proxmox.com/threads/new-installation-proxmox-8-0-network-interfaces-down-and-cannot-be-brought-up.130519/">[New Installation] Proxmox 8.0 - Network interfaces down and cannot be brought up</a></li>
<li><a href="https://forum.proxmox.com/threads/driver-problem-with-r8169-network-card-after-kernel-update.135302/">Driver Problem with r8169 Network Card after Kernel Update</a></li>
<li><a href="https://forum.proxmox.com/threads/networking-issues-pve8.129742/">Networking issues PVE8</a></li>
<li><a href="https://forum.proxmox.com/threads/usb-tethering-for-proxmox-host.166388/">USB Tethering for proxmox host</a></li>
</ul>


</section>

 ]]></description>
  <category>Kubernetes</category>
  <category>Homelab</category>
  <category>Proxmox</category>
  <guid>https://lahirudesilva.com/posts/from-broken-network-drivers-to-a-working-k8s-cluster/</guid>
  <pubDate>Tue, 30 Dec 2025 00:00:00 GMT</pubDate>
  <media:content url="https://lahirudesilva.com/posts/from-broken-network-drivers-to-a-working-k8s-cluster/proxmox-setup-cover.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Distributed Tracing Infrastructure for Cloud-Native Applications</title>
  <dc:creator>Lahiru De Silva</dc:creator>
  <link>https://lahirudesilva.com/posts/distributed-tracing-infrastructure-for-cloud-native-applications/</link>
  <description><![CDATA[ 






<p>As modern applications are increasingly built on a foundation of cloud-native infrastructure and microservices, the simplicity of monolithic debugging has given way to a new era of distributed complexity. When a single user request can trigger a cascade of calls across dozens of services, how do you find the root cause of a slowdown or an error? Traditional monitoring tools often fall short, leaving developers in the dark. This is precisely the problem that distributed tracing was designed to solve. By stitching together the entire lifecycle of a request as it hops across services, it provides the end-to-end visibility crucial for maintaining performance and reliability. This article will guide you through the architectural patterns and core components needed to build a robust distributed tracing infrastructure for your own cloud-native ecosystem.</p>
<section id="core-components-of-a-distributed-tracing-system" class="level2">
<h2 class="anchored" data-anchor-id="core-components-of-a-distributed-tracing-system">Core components of a distributed tracing system</h2>
<p>The foundation of a distributed tracing system consists of four essential components.</p>
<section id="instrumentation" class="level3">
<h3 class="anchored" data-anchor-id="instrumentation">1. Instrumentation</h3>
<p>This is the process of integrating code into applications to generate and emit trace data. This data usually takes the form of “spans” which represent individual units of work (e.g., an HTTP request or a database call). Each span includes a unique Span ID, the Trace ID of the overall request it belongs to, start and end timestamps, and other contextual metadata (tags or attributes).</p>
<p><a href="https://opentelemetry.io/docs/concepts/context-propagation/">Context propagation</a> ensures that the Trace ID and parent Span ID are passed along as requests flow between services, allowing the reconstruction of the entire trace. <a href="https://opentelemetry.io/docs/languages/">OpenTelemetry SDKs</a> are the current industry standard for application instrumentation.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/distributed-tracing-infrastructure-for-cloud-native-applications/instrumentation-overview.svg" class="img-fluid figure-img" alt="Instrumentation Overview"></p>
<figcaption>Figure 1: Application instrumentation using OpenTelemetry SDKs</figcaption>
</figure>
</div>
<section id="opentelemetry-otel" class="level4">
<h4 class="anchored" data-anchor-id="opentelemetry-otel">OpenTelemetry (OTel)</h4>
<p><a href="https://opentelemetry.io/">OpenTelemetry (OTel)</a> has emerged as the leading open standard for observability, regulated by the Cloud Native Computing Foundation (CNCF). It is a vendor neural approach for application instrumentation. It provides a unified set of APIs, SDKs, data formats (like OTLP), and tools for generating, collecting, and exporting telemetry data—specifically traces, metrics, and logs.</p>
</section>
<section id="zero-code-automatic-instrumentation" class="level4">
<h4 class="anchored" data-anchor-id="zero-code-automatic-instrumentation">Zero-code / automatic instrumentation</h4>
<p><a href="https://opentelemetry.io/docs/concepts/instrumentation/zero-code/">Zero-code instrumentation</a> adds the OpenTelemetry API and SDK capabilities to your application typically as an agent or agent-like installation. The specific mechanisms involved may differ by language, ranging from bytecode manipulation, monkey patching, or eBPF to inject calls to the OpenTelemetry API and SDK into your application. Zero-code instrumentation adds instrumentation for the libraries used by an application. This means that requests and responses, database calls, message queue calls, and so forth are what are instrumented. Application code is not typically instrumented. To instrument application code, code-based instrumentation should be used.</p>
</section>
<section id="code-based-manual-instrumentation" class="level4">
<h4 class="anchored" data-anchor-id="code-based-manual-instrumentation">Code-based / manual instrumentation</h4>
<p><a href="https://opentelemetry.io/docs/concepts/instrumentation/code-based/">Code-based instrumentation</a> provides deeper insights and visibility into applications itself in contrast to the zero-code instrumentation. Code-based instrumentation requires developers to add OpenTelemetry SDKs to application code and configure to export telemetry data. Also when the application code is instrumented, the libraries will also automatically export trace data depending on the language specific SDKs and the OpenTelemetry support in the used libraries.</p>
</section>
<section id="head-sampling" class="level4">
<h4 class="anchored" data-anchor-id="head-sampling">Head sampling</h4>
<p><a href="https://opentelemetry.io/docs/concepts/sampling/#head-sampling">Head sampling</a> is a sampling technique used to make a sampling decision as early as possible. A decision to sample or drop a span or trace is not made by inspecting the trace as a whole. Head sampling is usually performed at the client side and is a stateless operation.</p>
<p>The main purpose of head sampling is to reduce the volume of trace data in high-throughput systems that generate large amounts of telemetry. By making early sampling decisions, head sampling safeguards the collector tier from overload and helps prevent excessive data from reaching the OpenSearch storage layer, ensuring both scalability and cost efficiency.</p>
<p><a href="https://opentelemetry.io/docs/specs/otel/trace/sdk/#built-in-samplers">OpenTelemetry SDK built-in samplers</a> can be used to enforce head sampling at the client side by injecting the following environment variables into the applications.</p>
<ul>
<li>OTEL_TRACES_SAMPLER - <code>always_on</code>, <code>always_off</code>, <code>traceidratio</code>, <code>parentbased_always_on</code>, <code>parentbased_always_off</code>, <code>parentbased_traceidratio</code></li>
<li>OTEL_TRACES_SAMPLER_ARG - percentage value [0..1]</li>
</ul>
</section>
</section>
<section id="collection" class="level3">
<h3 class="anchored" data-anchor-id="collection">2. Collection</h3>
<p>Collectors, often deployed as agents running alongside applications or as standalone gateway services, are responsible for receiving telemetry data from instrumented applications. They can perform processing tasks such as batching, filtering, sampling, and attribute enrichment before exporting the data to a backend system.</p>
<p>In the context of distributed tracing, tail sampling and rate limiting are the most prominent use cases of collectors. Tail sampling at the collector level is crucial to filter out the events that are meaningful and have more value for troubleshooting application issues like events with errors, higher latencies etc.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/distributed-tracing-infrastructure-for-cloud-native-applications/traces-venn-diagram.svg" class="img-fluid figure-img" alt="Tail sampling"></p>
<figcaption>Figure 2: Sampling traces with important data for troubleshooting</figcaption>
</figure>
</div>
<section id="tail-sampling" class="level4">
<h4 class="anchored" data-anchor-id="tail-sampling">Tail sampling</h4>
<p><a href="https://opentelemetry.io/docs/concepts/sampling/#tail-sampling">Tail sampling</a> is where the decision to sample a trace takes place by considering all or most of the spans within the trace. Tail sampling gives you the option to sample your traces based on specific criteria derived from different parts of a trace, which isn’t an option with Head sampling.</p>
<p>Tail sampling is done by considering all or most of the spans within the trace and hence this is a stateful operation. <strong>This causes a well known limitation with scaling these stateful collectors as applications publishing spans of a trace to multiple collectors will cause fragmented traces.</strong> The solution to solve this problem involves a 2 tier collector architecture where the <em>Tier 1</em> load balances all the spans of a trace to a single collector instance in the <em>Tier 2</em> based on the Trace ID.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/distributed-tracing-infrastructure-for-cloud-native-applications/collector-architecture.svg" class="img-fluid figure-img" alt="Collector Architecture"></p>
<figcaption>Figure 3: 2-Tier Trace Collector Architecture</figcaption>
</figure>
</div>
</section>
<section id="rate-limiting" class="level4">
<h4 class="anchored" data-anchor-id="rate-limiting">Rate limiting</h4>
<p>Rate limiting at the collector level acts as a critical safety measure for distributed tracing infrastructure. By enforcing limits on the rate of incoming traces, collectors can prevent overload and protect downstream systems including storage backends and visualization tools from excessive traffic during unexpected incidents, such as application bugs or traffic spikes. This not only helps maintain system stability but also reduces operational costs by avoiding unnecessary ingestion and storage of trace data that may result from accidental or malicious events. Implementing rate limiting policies ensures that your tracing pipeline remains resilient and cost-effective, even under adverse conditions.</p>
</section>
</section>
<section id="backend-sink" class="level3">
<h3 class="anchored" data-anchor-id="backend-sink">3. Backend (sink)</h3>
<p>The backend represents the persistence layer of the distributed tracing system. It serves as the terminal sink for all processed telemetry from the collection tier and is engineered to perform the essential functions of data storage, retrieval, and indexing that underpin long-term analysis.</p>
<p>A robust tracing backend must perform three primary functions:</p>
<ol type="1">
<li><strong>Long-term storage:</strong> It must persistently store vast quantities of trace data, making it available for historical analysis, performance trend identification, Service Level Objective (SLO) tracking, and regulatory compliance.</li>
<li><strong>Indexing:</strong> To facilitate rapid data retrieval, the backend must create and maintain efficient indexes on key trace and span attributes. This includes indexing by service name, operation name, duration, timestamps, and any custom attributes (tags) that are critical for analysis. The quality of this indexing directly determines the power and performance of the query system.</li>
<li><strong>Query API:</strong> It must expose a powerful and flexible API that allows visualization tools and human operators to query the stored trace data, enabling the exploration, filtering, and aggregation required for effective troubleshooting and analysis.</li>
</ol>
<p>Today’s open-source ecosystem offers a spectrum of powerful tracing backends beyond just one or two solutions. Leading projects like Jaeger, Grafana Tempo, Signoz, and Zipkin each represent a distinct set of design choices and priorities. For instance, the architectural philosophies of Jaeger and Tempo are fundamentally different, tailored for vastly different use cases regarding data querying, scalability, and cost.</p>
<p>For organizations that prefer to buy a solution rather than build and manage one, commercial observability platforms offer tracing as a core feature of a broader, managed service. These platforms abstract away the immense complexity of operating a scalable backend. Key players include Datadog, New Relic, Dynatrace and Splunk.</p>
</section>
<section id="visualization" class="level3">
<h3 class="anchored" data-anchor-id="visualization">4. Visualization</h3>
<p>The final and most human-centric component of a distributed tracing system is the visualization layer. Raw trace data, which can consist of millions of individual spans, is essentially a stream of structured text that is impossible for a human operator to interpret directly. The visualization layer’s critical function is to transform this overwhelming volume of data into intuitive, interactive graphical representations. This transformation is what enables engineers to rapidly comprehend complex system behavior, identify performance bottlenecks, and accelerate the debugging of failures.</p>
<p>Several distinct visualization paradigms have become standard for presenting trace data, each offering a different perspective on system performance.</p>
<ul>
<li><strong>Gantt / Waterfall Charts:</strong> This is the most fundamental and widely used visualization for analyzing a single trace. It presents the trace as a cascading timeline of horizontal bars, where each bar represents a single span. The left-to-right position of a bar indicates its start time and its relationship to other spans, while its length is proportional to its duration. This view is exceptionally effective for latency analysis; the longest bars in the chart immediately draw the eye to the operations that are consuming the most time, providing an instant visual cue to the source of a slowdown.</li>
<li><strong>Service Dependency Graphs:</strong> This provides a high-level, aggregated view of the entire distributed system’s architecture. By analyzing a large number of traces, the visualization tool constructs a topological map where nodes represent individual services and directed edges represent the calls between them. These graphs are typically annotated with key health metrics, such as request throughput (requests per second), error rate, and p99 latency for each inter-service connection. This macro-level view is invaluable for understanding service dependencies, visualizing the potential “blast radius” of a failing component, and getting a quick, at-a-glance overview of the system’s overall health.</li>
<li><strong>Flame Graphs:</strong> While visually similar to a Gantt chart, a flame graph serves a different purpose: profiling. It aggregates many traces or spans with the same operation name and stacks them vertically to show which code paths are most frequently executed or are consuming the most time across a large sample of requests. The width of each block in the graph is proportional to its contribution to the total time, making it a powerful tool for identifying inefficient code paths within a single service.</li>
</ul>
</section>
</section>
<section id="reference-implementation" class="level2">
<h2 class="anchored" data-anchor-id="reference-implementation">Reference implementation</h2>
<div class="callout callout-style-default callout-note callout-titled" title="Prerequisites">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Prerequisites
</div>
</div>
<div class="callout-body-container callout-body">
<ul>
<li><p>Access to a Kubernetes cluster</p></li>
<li><p>Helm CLI</p></li>
<li><p>OpenSearch Helm charts repository:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">helm</span> repo add opensearch https://opensearch-project.github.io/helm-charts</span>
<span id="cb1-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">helm</span> repo update</span></code></pre></div></div>
<p>See: <a href="https://opensearch-project.github.io/helm-charts" class="uri">https://opensearch-project.github.io/helm-charts</a></p></li>
</ul>
</div>
</div>
<p>This section provides a practical guide for building an end to end distributed tracing system using Opensearch stack. This include Opensearch DataPrepper as the trace collector, Opensearch as the trace sink and Opensearch Trace Analytics plugin with Opensearch Dashboards for trace visualization.</p>
<section id="deploy-opensearch-single-node" class="level3">
<h3 class="anchored" data-anchor-id="deploy-opensearch-single-node">Deploy Opensearch single node</h3>
<p>For ease of use, demonstration purposes, and because there is no tracing-specific dependency with the OpenSearch deployment, we are using a single node deployment. This is not recommended for production use cases.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">helm</span> install opensearch opensearch/opensearch <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-f</span> https://raw.githubusercontent.com/NomadXD/samples/refs/heads/main/opensearch-distributed-tracing/values-opensearch.yaml <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--namespace</span> opensearch-stack <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--create-namespace</span></span>
<span id="cb2-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">NAME:</span> opensearch</span>
<span id="cb2-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">LAST</span> DEPLOYED: Tue Jul 29 20:48:58 2025</span>
<span id="cb2-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">NAMESPACE:</span> opensearch-stack</span>
<span id="cb2-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">STATUS:</span> deployed</span>
<span id="cb2-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">REVISION:</span> 1</span>
<span id="cb2-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">TEST</span> SUITE: None</span>
<span id="cb2-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">NOTES:</span></span>
<span id="cb2-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Watch</span> all cluster members come up.</span>
<span id="cb2-10">  <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">$</span> kubectl get pods <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--namespace</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>opensearch-stack <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-l</span> app.kubernetes.io/component=opensearch-local-dev-master <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-w</span></span></code></pre></div></div>
</section>
<section id="deploy-opensearch-dashboards" class="level3">
<h3 class="anchored" data-anchor-id="deploy-opensearch-dashboards">Deploy Opensearch Dashboards</h3>
<p>Deploy Opensearch dashboard and configure it to connect to the Opensearch single node deployment.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">helm</span> install opensearch-dashboard opensearch/opensearch-dashboards <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-f</span> https://raw.githubusercontent.com/NomadXD/samples/refs/heads/main/opensearch-distributed-tracing/values-opensearch-dashboard.yaml <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--namespace</span> opensearch-stack</span>
<span id="cb3-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">NAME:</span> opensearch-dashboard</span>
<span id="cb3-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">LAST</span> DEPLOYED: Wed Jul 30 10:55:57 2025</span>
<span id="cb3-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">NAMESPACE:</span> opensearch-stack</span>
<span id="cb3-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">STATUS:</span> deployed</span>
<span id="cb3-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">REVISION:</span> 1</span>
<span id="cb3-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">TEST</span> SUITE: None</span>
<span id="cb3-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">NOTES:</span></span>
<span id="cb3-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">1.</span> Get the application URL by running these commands:</span>
<span id="cb3-10">  <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">export</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">POD_NAME</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kubectl</span> get pods <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--namespace</span> opensearch-stack <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-l</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"app.kubernetes.io/name=opensearch-dashboards,app.kubernetes.io/instance=opensearch-dashboard"</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> jsonpath=<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"{.items[0].metadata.name}"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb3-11">  <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">export</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">CONTAINER_PORT</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kubectl</span> get pod <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--namespace</span> opensearch-stack <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$POD_NAME</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> jsonpath=<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"{.spec.containers[0].ports[0].containerPort}"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb3-12">  <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">echo</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Visit http://127.0.0.1:8080 to use your application"</span></span>
<span id="cb3-13">  <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kubectl</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--namespace</span> opensearch-stack port-forward <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$POD_NAME</span> 8080:<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$CONTAINER_PORT</span></span></code></pre></div></div>
</section>
<section id="deploy-opensearch-dataprepper" class="level3">
<h3 class="anchored" data-anchor-id="deploy-opensearch-dataprepper">Deploy Opensearch DataPrepper</h3>
<p>Instead of deploying a single node of the Opensearch DataPrepper, multiple nodes are deployed in the peer forwarder configuration to demonstrate the scaling capabilities of the Opensearch DataPrepper.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/distributed-tracing-infrastructure-for-cloud-native-applications/opensearch-peer-forwarder.svg" class="img-fluid figure-img" alt="Opensearch DataPrepper Peer Forwarder"></p>
<figcaption>Figure 4: Opensearch DataPrepper Peer Forwarder Configuration</figcaption>
</figure>
</div>
<p>The Peer Forwarder component in OpenSearch Data Prepper logically implements the 2 Tier collector architecture commonly used for scalable distributed tracing. While the classic model describes a Tier 1 that load balances spans and a Tier 2 that performs tail sampling, Peer Forwarder achieves this in a peer-to-peer fashion: Data Prepper nodes communicate directly with each other, using a hash-ring approach to aggregate events and ensure all spans for a given trace are routed to the same node for sampling and processing. This design provides the benefits of load balancing and stateful trace aggregation without explicit tier separation.</p>
<p>For peer discovery, Data Prepper supports DNS-based configuration, where a DNS provider returns a list of Data Prepper hosts for a given domain name. In Kubernetes environments, this is typically implemented using a headless service, which exposes the individual pod IPs via DNS A records, allowing Data Prepper nodes to discover and communicate with all peers in the cluster.</p>
<ul>
<li>Initially deploy the Opensearch DataPrepper nodes without peer forwarding as we will face the <em>Chicken and Egg problem</em> if we try to deploy in peer forwader configuration at once. The reason for that is because upon startup the dataprepper nodes will try to connect to other peers using the provided domain name and since every other node will wait for others to start up, this causes a deadlock. To mitigate that scenario, first let’s deploy the dataprepper nodes without peer forwarding.</li>
</ul>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb4-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">helm</span> install opensearch-data-prepper opensearch/data-prepper <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-f</span> https://raw.githubusercontent.com/NomadXD/samples/317e716c4ec3f3d2d846ef2f268d7fcefab7eb94/opensearch-distributed-tracing/values-opensearch-dataprepper.yaml <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--version</span> 0.3.1 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--namespace</span> opensearch-stack</span>
<span id="cb4-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">I0730</span> 13:26:13.197723   68838 warnings.go:110] <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Warning: spec.template.spec.containers[0].ports[5]: duplicate port definition with spec.template.spec.containers[0].ports[4]"</span></span>
<span id="cb4-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">NAME:</span> opensearch-data-prepper</span>
<span id="cb4-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">LAST</span> DEPLOYED: Wed Jul 30 13:26:12 2025</span>
<span id="cb4-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">NAMESPACE:</span> opensearch-stack</span>
<span id="cb4-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">STATUS:</span> deployed</span>
<span id="cb4-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">REVISION:</span> 1</span>
<span id="cb4-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">TEST</span> SUITE: None</span>
<span id="cb4-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">NOTES:</span></span>
<span id="cb4-10"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">1.</span> Get the application URL by running these commands:</span>
<span id="cb4-11">  <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">export</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">POD_NAME</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kubectl</span> get pods <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--namespace</span> opensearch-stack <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-l</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"app.kubernetes.io/name=data-prepper,app.kubernetes.io/instance=opensearch-data-prepper"</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> jsonpath=<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"{.items[0].metadata.name}"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb4-12">  <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">export</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">CONTAINER_PORT</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kubectl</span> get pod <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--namespace</span> opensearch-stack <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$POD_NAME</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> jsonpath=<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"{.spec.containers[0].ports[0].containerPort}"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb4-13">  <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">echo</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Visit http://127.0.0.1:8080 to use your application"</span></span>
<span id="cb4-14">  <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kubectl</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--namespace</span> opensearch-stack port-forward <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$POD_NAME</span> 8080:<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$CONTAINER_PORT</span></span>
<span id="cb4-15"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Inline</span> pipeline configuration is enabled. Please refer to the values.yaml file for the configuration.</span></code></pre></div></div>
<ul>
<li>Create a Headless service for the DataPrepper peers to connect with each other.</li>
</ul>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb5-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apiVersion</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> v1</span></span>
<span id="cb5-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">kind</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Service</span></span>
<span id="cb5-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">metadata</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb5-4"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">name</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> data-prepper-headless</span></span>
<span id="cb5-5"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">namespace</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> opensearch-stack</span></span>
<span id="cb5-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">spec</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb5-7"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">clusterIP</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> None</span></span>
<span id="cb5-8"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">selector</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb5-9"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">app.kubernetes.io/instance</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> opensearch-data-prepper</span></span>
<span id="cb5-10"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">app.kubernetes.io/name</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> data-prepper</span></span>
<span id="cb5-11"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ports</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb5-12"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">name</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> peer-forwarder</span></span>
<span id="cb5-13"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">port</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4994</span></span>
<span id="cb5-14"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">targetPort</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4994</span></span>
<span id="cb5-15"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">protocol</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> TCP</span></span></code></pre></div></div>
<ul>
<li>Configure Opensearch DataPrepper to run in peer forwarder configuration.</li>
</ul>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb6-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">helm</span> upgrade opensearch-data-prepper opensearch/data-prepper <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-f</span> https://raw.githubusercontent.com/NomadXD/samples/ca9a5e0c17cd479e40064fb490a22292c022db64/opensearch-distributed-tracing/values-opensearch-dataprepper.yaml <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--namespace</span> opensearch-stack</span>
<span id="cb6-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">I0730</span> 13:37:09.117548   73798 warnings.go:110] <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Warning: spec.template.spec.containers[0].ports[5]: duplicate port definition with spec.template.spec.containers[0].ports[4]"</span></span>
<span id="cb6-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Release</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"opensearch-data-prepper"</span> has been upgraded. Happy Helming!</span>
<span id="cb6-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">NAME:</span> opensearch-data-prepper</span>
<span id="cb6-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">LAST</span> DEPLOYED: Wed Jul 30 13:37:08 2025</span>
<span id="cb6-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">NAMESPACE:</span> opensearch-stack</span>
<span id="cb6-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">STATUS:</span> deployed</span>
<span id="cb6-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">REVISION:</span> 2</span>
<span id="cb6-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">TEST</span> SUITE: None</span>
<span id="cb6-10"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">NOTES:</span></span>
<span id="cb6-11"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">1.</span> Get the application URL by running these commands:</span>
<span id="cb6-12">  <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">export</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">POD_NAME</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kubectl</span> get pods <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--namespace</span> opensearch-stack <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-l</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"app.kubernetes.io/name=data-prepper,app.kubernetes.io/instance=opensearch-data-prepper"</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> jsonpath=<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"{.items[0].metadata.name}"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb6-13">  <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">export</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">CONTAINER_PORT</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kubectl</span> get pod <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--namespace</span> opensearch-stack <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$POD_NAME</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> jsonpath=<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"{.spec.containers[0].ports[0].containerPort}"</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb6-14">  <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">echo</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Visit http://127.0.0.1:8080 to use your application"</span></span>
<span id="cb6-15">  <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kubectl</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--namespace</span> opensearch-stack port-forward <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$POD_NAME</span> 8080:<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">$CONTAINER_PORT</span></span>
<span id="cb6-16"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Inline</span> pipeline configuration is enabled. Please refer to the values.yaml file for the configuration.</span></code></pre></div></div>
</section>
<section id="analyse-trace-data-using-opensearch-dashboard" class="level3">
<h3 class="anchored" data-anchor-id="analyse-trace-data-using-opensearch-dashboard">Analyse trace data using Opensearch Dashboard</h3>
<p>Now that you have a complete end-to-end distributed tracing system running, you can instrument your applications with OpenTelemetry SDKs and configure them to publish traces to the Opensearch Data Prepper OTLP trace endpoint. Once traces are flowing, you can use Opensearch Dashboards Trace Analytics to visualize, search, and analyze your distributed traces in real time.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/distributed-tracing-infrastructure-for-cloud-native-applications/opensearch-dashboard.png" class="img-fluid figure-img" alt="Opensearch Dashboard"></p>
<figcaption>Figure 5: Opensearch Dashboard Trace Analytics</figcaption>
</figure>
</div>
<hr>
<p><strong>Helm Charts values.yaml:</strong> <a href="https://github.com/NomadXD/samples/tree/main/opensearch-distributed-tracing">Opensearch Distributed Tracing Helm Charts</a></p>


</section>
</section>

 ]]></description>
  <category>Observability</category>
  <category>Cloud Native</category>
  <category>Opensearch</category>
  <guid>https://lahirudesilva.com/posts/distributed-tracing-infrastructure-for-cloud-native-applications/</guid>
  <pubDate>Wed, 30 Jul 2025 00:00:00 GMT</pubDate>
  <media:content url="https://lahirudesilva.com/posts/distributed-tracing-infrastructure-for-cloud-native-applications/distributed-tracing-cover.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Multi cluster networking with Cilium Cluster Mesh</title>
  <dc:creator>Lahiru De Silva</dc:creator>
  <link>https://lahirudesilva.com/posts/multi-cluster-networking-with-cilium-cluster-mesh/</link>
  <description><![CDATA[ 






<p>As organizations increasingly adopt distributed architectures and scale their Kubernetes deployments, the need for robust networking and security solutions that can seamlessly operate across multiple clusters becomes paramount. In this blog, we will go through how you can use Cilium Cluster Mesh to effectively manage a fleet of Kubernetes clusters spanning across availability zones or regions, thereby achieving unparalleled levels of high availability and fault tolerance across your infrastructure.</p>
<section id="cilium-cluster-mesh-in-a-nutshell" class="level2">
<h2 class="anchored" data-anchor-id="cilium-cluster-mesh-in-a-nutshell">🐝 Cilium Cluster Mesh in a nutshell 🐝</h2>
<p>Cilium Cluster Mesh allows you to connect the networks of multiple clusters in such as way that pods in each cluster can discover and access services in all other clusters of the mesh, provided all the clusters run Cilium as their CNI. This allows effectively joining multiple clusters into a large unified network, regardless of the Kubernetes distribution or location each of them is running.</p>
<p>This is done by deploying an additional API server called <code>clustermesh-apiserver</code> to synchronize the shared state among the kubernetes clusters. Each kubernetes cluster holds its state in the etcd and the kubernetes clusters in the cluster mesh can access other cluster’s state via the <code>clustermesh-apiserver</code>. For this each cluster should expose its <code>clustermesh-apiserver</code> as a Load balancer service. Cilium agents running in the kubernetes clusters connect to the <code>clustermesh-apiserver</code> of other clusters, watch for changes and replicate the multi-cluster relevant state into their own cluster.</p>
<p>Cilium Cluster Mesh provides the following features as stated in the Cilium documentation.</p>
<ul>
<li>Pod IP routing across multiple Kubernetes clusters at native performance via tunneling or direct-routing without requiring any gateways or proxies.</li>
<li>Transparent service discovery with standard Kubernetes services and coredns/kube-dns.</li>
<li>Network policy enforcement spanning multiple clusters. Policies can be specified as Kubernetes NetworkPolicy resource or the extended CiliumNetworkPolicy CRD.</li>
<li>Transparent encryption for all communication between nodes in the local cluster as well as across cluster boundaries.</li>
</ul>
</section>
<section id="time-to-get-our-hands-dirty." class="level2">
<h2 class="anchored" data-anchor-id="time-to-get-our-hands-dirty.">Time to get our hands dirty…. 👨‍🔧</h2>
<p>In this blog, we are going to deploy the following setup in your laptop using <code>kind (Kubernetes IN Docker)</code> and demonstrate the multi cluster load balancing and fault tolerance capabilities supported by Cilium Cluster Mesh.</p>
<p>The setup consists of 2 kubernetes clusters which are named as US and EU for ease of relating to real world scenario of multi region clusters. We are going to install Cilium in both of the clusters and then enable Cilium Cluster Mesh on both. Then we are going to deploy a hello world application in both of the clusters along with a busybox pod to access the application within the cluster. Then we are going to make the hello world service accessible across clusters enabling load balancing across clusters. Finally we are going to use service affinity rules in Cilium to demonstrate the fault tolerant capabilities across clusters.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/multi-cluster-networking-with-cilium-cluster-mesh/multi-cluster.png" class="img-fluid figure-img"></p>
<figcaption>Multi cluster networking</figcaption>
</figure>
</div>
<section id="create-two-kubernetes-clusters-using-kind." class="level3">
<h3 class="anchored" data-anchor-id="create-two-kubernetes-clusters-using-kind.">1. Create two Kubernetes clusters using kind.</h3>
<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>We will be using 3 terminals for the hands on lab. Terminal 1 has access to the US cluster and the Terminal 2 has access to the EU cluster. Terminal 3 has access to the both clusters.</p>
</div>
</div>
<ul>
<li>Create a new directory to host the kubernetes manifests. Let’s name it as <code>cilium-cluster-mesh</code>.</li>
<li>Open a terminal session (Terminal 1) and set the environment variable <code>KUBECONFIG</code> to <code>export KUBECONFIG=./kubeconfig-us.yaml</code></li>
<li>Create a file with the following content and save it as <code>kind-us-cluster.yaml</code></li>
</ul>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb1-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">---</span></span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apiVersion</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> kind.x-k8s.io/v1alpha4</span></span>
<span id="cb1-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">kind</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Cluster</span></span>
<span id="cb1-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">networking</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb1-5"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">disableDefaultCNI</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">true</span></span>
<span id="cb1-6"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">podSubnet</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> 10.1.0.0/16</span></span>
<span id="cb1-7"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">serviceSubnet</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> 172.20.1.0/24</span></span>
<span id="cb1-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nodes</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb1-9"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">role</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> control-plane</span></span>
<span id="cb1-10"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">extraPortMappings</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb1-11"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">containerPort</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">32042</span></span>
<span id="cb1-12"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">hostPort</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">32042</span></span>
<span id="cb1-13"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">containerPort</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">31234</span></span>
<span id="cb1-14"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">hostPort</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">31234</span></span>
<span id="cb1-15"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">containerPort</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">31235</span></span>
<span id="cb1-16"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">hostPort</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">31235</span></span>
<span id="cb1-17"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">role</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> worker</span></span>
<span id="cb1-18"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">role</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> worker</span></span></code></pre></div></div>
<ul>
<li>Execute the following command to create the US cluster. If the cluster creation is successful, following logs can be seen.</li>
</ul>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># US cluster (Terminal 1)</span></span>
<span id="cb2-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> kind create cluster <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--name</span> us <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--config</span> kind-us-cluster.yaml</span>
<span id="cb2-3"></span>
<span id="cb2-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Creating</span> cluster <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"us"</span> ...</span>
<span id="cb2-5"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✓</span> Ensuring node image <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kindest/node:v1.27.3</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">🖼</span></span>
<span id="cb2-6"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✓</span> Preparing nodes 📦 📦 📦</span>
<span id="cb2-7"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✓</span> Writing configuration 📜</span>
<span id="cb2-8"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✓</span> Starting control-plane 🕹️</span>
<span id="cb2-9"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✓</span> Installing StorageClass 💾</span>
<span id="cb2-10"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✓</span> Joining worker nodes 🚜</span>
<span id="cb2-11"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Set</span> kubectl context to <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"kind-us"</span></span>
<span id="cb2-12"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">You</span> can now use your cluster with:</span>
<span id="cb2-13"></span>
<span id="cb2-14"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kubectl</span> cluster-info <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--context</span> kind-us</span>
<span id="cb2-15"></span>
<span id="cb2-16"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Not</span> sure what to do next<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">?</span> 😅  Check out https://kind.sigs.k8s.io/docs/user/quick-start/</span></code></pre></div></div>
<ul>
<li>Next open a new terminal (Terminal 2) and set the environment variable <code>KUBECONFIG</code> to <code>export KUBECONFIG=./kubeconfig-eu.yaml</code></li>
<li>Create a file with the following content and save it as <code>kind-eu-cluster.yaml</code></li>
</ul>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb3-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">---</span></span>
<span id="cb3-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apiVersion</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> kind.x-k8s.io/v1alpha4</span></span>
<span id="cb3-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">kind</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> Cluster</span></span>
<span id="cb3-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">networking</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb3-5"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">disableDefaultCNI</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">true</span></span>
<span id="cb3-6"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">podSubnet</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> 10.2.0.0/16</span></span>
<span id="cb3-7"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">serviceSubnet</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> 172.20.2.0/24</span></span>
<span id="cb3-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">nodes</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb3-9"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">role</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> control-plane</span></span>
<span id="cb3-10"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">role</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> worker</span></span>
<span id="cb3-11"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">role</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> worker</span></span></code></pre></div></div>
<ul>
<li>Execute the following command to create the EU cluster. If the cluster creation is successful, following logs can be seen.</li>
</ul>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb4-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># EU cluster (Terminal 2)</span></span>
<span id="cb4-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> kind create cluster <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--name</span> eu <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--config</span> kind-eu-cluster.yaml</span>
<span id="cb4-3"></span>
<span id="cb4-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Creating</span> cluster <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"eu"</span> ...</span>
<span id="cb4-5"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✓</span> Ensuring node image <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kindest/node:v1.27.3</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">🖼</span></span>
<span id="cb4-6"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✓</span> Preparing nodes 📦 📦 📦</span>
<span id="cb4-7"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✓</span> Writing configuration 📜</span>
<span id="cb4-8"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✓</span> Starting control-plane 🕹️</span>
<span id="cb4-9"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✓</span> Installing StorageClass 💾</span>
<span id="cb4-10"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✓</span> Joining worker nodes 🚜</span>
<span id="cb4-11"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Set</span> kubectl context to <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"kind-eu"</span></span>
<span id="cb4-12"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">You</span> can now use your cluster with:</span>
<span id="cb4-13"></span>
<span id="cb4-14"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kubectl</span> cluster-info <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--context</span> kind-eu</span>
<span id="cb4-15"></span>
<span id="cb4-16"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Not</span> sure what to do next<span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">?</span> 😅  Check out https://kind.sigs.k8s.io/docs/user/quick-start/</span></code></pre></div></div>
</section>
<section id="install-cilium-cni-in-the-two-clusters." class="level3">
<h3 class="anchored" data-anchor-id="install-cilium-cni-in-the-two-clusters.">2. Install Cilium CNI in the two clusters.</h3>
<ul>
<li>In the terminal 1 (US), execute the following command to install the Cilium CNI in the US cluster.</li>
</ul>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb5-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># US cluster (Terminal 1)</span></span>
<span id="cb5-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">cilium</span> install <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb5-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--set</span> cluster.name=us <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb5-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--set</span> cluster.id=1 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb5-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--set</span> ipam.mode=kubernetes</span>
<span id="cb5-6"></span>
<span id="cb5-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">🔮</span> Auto-detected Kubernetes kind: kind</span>
<span id="cb5-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✨</span> Running <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"kind"</span> validation checks</span>
<span id="cb5-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✅</span> Detected kind version <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"0.20.0"</span></span>
<span id="cb5-10"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ℹ️</span>  Using Cilium version 1.15.4</span>
<span id="cb5-11"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ℹ️</span>  Using cluster name <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"eu"</span></span>
<span id="cb5-12"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">🔮</span> Auto-detected kube-proxy has been installed</span></code></pre></div></div>
<ul>
<li>Execute the command <code>cilium status</code> to check the status of the Cilium installation.</li>
</ul>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb6-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># US cluster (Terminal 1)</span></span>
<span id="cb6-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> cilium status   </span>
<span id="cb6-3">    <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">/¯¯</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb6-4"> /¯¯\__/¯¯\    Cilium:             OK</span>
<span id="cb6-5"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">\__/¯¯\__/</span>    Operator:           OK</span>
<span id="cb6-6"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">/¯¯\__/¯¯\ </span>   Envoy DaemonSet:    disabled <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">using</span> embedded mode<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span></span>
<span id="cb6-7"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">\__/¯¯\__/</span>    Hubble Relay:       disabled</span>
<span id="cb6-8">    <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">\__/</span>       ClusterMesh:        disabled</span>
<span id="cb6-9"></span>
<span id="cb6-10"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Deployment</span>             cilium-operator    Desired: 1, Ready: 1/1, Available: 1/1</span>
<span id="cb6-11"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">DaemonSet</span>              cilium             Desired: 3, Ready: 3/3, Available: 3/3</span>
<span id="cb6-12"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Containers:</span>            cilium             Running: 3</span>
<span id="cb6-13">                       <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">cilium-operator</span>    Running: 1</span>
<span id="cb6-14"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Cluster</span> Pods:          3/3 managed by Cilium</span>
<span id="cb6-15"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Helm</span> chart version:    </span>
<span id="cb6-16"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Image</span> versions         cilium             quay.io/cilium/cilium:v1.15.4@sha256:b760a4831f5aab71c711f7537a107b751d0d0ce90dd32d8b358df3c5da385426: 3</span>
<span id="cb6-17">                       <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">cilium-operator</span>    quay.io/cilium/operator-generic:v1.15.4@sha256:404890a83cca3f28829eb7e54c1564bb6904708cdb7be04ebe69c2b60f164e9a: 1</span></code></pre></div></div>
<ul>
<li>In the terminal 2 (EU), execute the following command to install the Cilium CNI in the EU cluster.</li>
</ul>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb7-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># EU cluster (Terminal 2)</span></span>
<span id="cb7-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">cilium</span> install <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb7-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--set</span> cluster.name=eu <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb7-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--set</span> cluster.id=2 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb7-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--set</span> ipam.mode=kubernetes</span>
<span id="cb7-6"></span>
<span id="cb7-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">🔮</span> Auto-detected Kubernetes kind: kind</span>
<span id="cb7-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✨</span> Running <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"kind"</span> validation checks</span>
<span id="cb7-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✅</span> Detected kind version <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"0.20.0"</span></span>
<span id="cb7-10"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ℹ️</span>  Using Cilium version 1.15.4</span>
<span id="cb7-11"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ℹ️</span>  Using cluster name <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"eu"</span></span>
<span id="cb7-12"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">🔮</span> Auto-detected kube-proxy has been installed</span></code></pre></div></div>
<p>Now if you followed the instructions upto this point correctly, you would have 2 kubernetes clusters up and running in your laptop with Cilium installed as the CNI.</p>
</section>
<section id="enable-cilium-cluster-mesh-in-both-clusters" class="level3">
<h3 class="anchored" data-anchor-id="enable-cilium-cluster-mesh-in-both-clusters">3. Enable Cilium Cluster Mesh in both clusters</h3>
<p>Next we are going to enable Cilium Cluster Mesh in both US and EU clusters. This will deploy an additional deployment for the <code>clustermesh-apiserver</code> in both of the clusters.</p>
<p>Cilium agents running in the EU cluster will use this <code>clustermesh-apiserver</code> in the US cluster to replicate the states of US cluster to its own EU cluster and vice versa. Therefore this <code>clustermesh-apiserver</code> should be exposed as a Load balancer service for accessing outside the cluster. But for demonstrating purposes, we are going to expose the <code>clustermesh-apiserver</code> as a NodePort service as we don’t have dynamic load balancers available. This is not recommended for production use cases as the service becomes unavailable when the node goes down.</p>
<p>To enable <code>clustermesh-apiserver</code> run the following command in both Terminal 1 (US) and Terminal 2 (EU).</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb8-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># US cluster (Terminal 1) &amp; EU cluster (Terminal 2)</span></span>
<span id="cb8-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">cilium</span> clustermesh enable <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--service-type</span> NodePort</span></code></pre></div></div>
<p>If you execute the <code>cilium status</code> command now, you’ll notice that the <code>ClusterMesh</code> status is changed from <code>disabled</code> to <code>OK</code>.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb9-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># US cluster (Terminal 1) &amp; EU cluster (Terminal 2)</span></span>
<span id="cb9-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> cilium status                                    </span>
<span id="cb9-3">    <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">/¯¯</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb9-4"> /¯¯\__/¯¯\    Cilium:             OK</span>
<span id="cb9-5"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">\__/¯¯\__/</span>    Operator:           OK</span>
<span id="cb9-6"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">/¯¯\__/¯¯\ </span>   Envoy DaemonSet:    disabled <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">using</span> embedded mode<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span></span>
<span id="cb9-7"> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">\__/¯¯\__/</span>    Hubble Relay:       OK</span>
<span id="cb9-8">    <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">\__/</span>       ClusterMesh:        OK</span>
<span id="cb9-9"></span>
<span id="cb9-10"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">DaemonSet</span>              cilium                   Desired: 3, Ready: 3/3, Available: 3/3</span>
<span id="cb9-11"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Deployment</span>             clustermesh-apiserver    Desired: 1, Ready: 1/1, Available: 1/1</span>
<span id="cb9-12"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Deployment</span>             hubble-relay             Desired: 1, Ready: 1/1, Available: 1/1</span>
<span id="cb9-13"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Deployment</span>             hubble-ui                Desired: 1, Ready: 1/1, Available: 1/1</span>
<span id="cb9-14"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Deployment</span>             cilium-operator          Desired: 1, Ready: 1/1, Available: 1/1</span>
<span id="cb9-15"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Containers:</span>            cilium-operator          Running: 1</span>
<span id="cb9-16">                       <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">cilium</span>                   Running: 3</span>
<span id="cb9-17">                       <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">hubble-relay</span>             Running: 1</span>
<span id="cb9-18">                       <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">hubble-ui</span>                Running: 1</span>
<span id="cb9-19">                       <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">clustermesh-apiserver</span>    Running: 1</span>
<span id="cb9-20"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Cluster</span> Pods:          6/6 managed by Cilium</span>
<span id="cb9-21"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Helm</span> chart version:    </span>
<span id="cb9-22"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Image</span> versions         cilium                   quay.io/cilium/cilium:v1.15.4@sha256:b760a4831f5aab71c711f7537a107b751d0d0ce90dd32d8b358df3c5da385426: 3</span>
<span id="cb9-23">                       <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">hubble-relay</span>             quay.io/cilium/hubble-relay:v1.15.4@sha256:03ad857feaf52f1b4774c29614f42a50b370680eb7d0bfbc1ae065df84b1070a: 1</span>
<span id="cb9-24">                       <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">hubble-ui</span>                quay.io/cilium/hubble-ui:v0.13.0@sha256:7d663dc16538dd6e29061abd1047013a645e6e69c115e008bee9ea9fef9a6666: 1</span>
<span id="cb9-25">                       <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">hubble-ui</span>                quay.io/cilium/hubble-ui-backend:v0.13.0@sha256:1e7657d997c5a48253bb8dc91ecee75b63018d16ff5e5797e5af367336bc8803: 1</span>
<span id="cb9-26">                       <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">clustermesh-apiserver</span>    quay.io/cilium/clustermesh-apiserver:v1.15.4@sha256:3fadf85d2aa0ecec09152e7e2d57648bda7e35bdc161b25ab54066dd4c3b299c: 2</span>
<span id="cb9-27">                       <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">cilium-operator</span>          quay.io/cilium/operator-generic:v1.15.4@sha256:404890a83cca3f28829eb7e54c1564bb6904708cdb7be04ebe69c2b60f164e9a: 1</span></code></pre></div></div>
<p>Now if you execute <code>kubectl get pods -A</code>, you’ll notice a new pod is created for the <code>clustermesh-apiserver</code>.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb10-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># US cluster (Terminal 1) &amp; EU cluster (Terminal 2)</span></span>
<span id="cb10-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> kubectl get pods <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-A</span></span>
<span id="cb10-3"></span>
<span id="cb10-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">NAMESPACE</span>            NAME                                         READY   STATUS      RESTARTS   AGE</span>
<span id="cb10-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kube-system</span>          cilium-5glrm                                 1/1     Running     0          4m8s</span>
<span id="cb10-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kube-system</span>          cilium-operator-5d8fb68868-sn9k5             1/1     Running     0          4m8s</span>
<span id="cb10-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kube-system</span>          cilium-rnpmp                                 1/1     Running     0          4m8s</span>
<span id="cb10-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kube-system</span>          cilium-tfjwr                                 1/1     Running     0          4m8s</span>
<span id="cb10-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kube-system</span>          clustermesh-apiserver-68b6c7cc6d-224tw       0/2     Init:0/1    0          14s</span>
<span id="cb10-10"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kube-system</span>          clustermesh-apiserver-generate-certs-hmpdc   0/1     Completed   0          14s</span>
<span id="cb10-11"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kube-system</span>          coredns-5d78c9869d-d8drc                     1/1     Running     0          6m36s</span>
<span id="cb10-12"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kube-system</span>          coredns-5d78c9869d-f85p5                     1/1     Running     0          6m36s</span>
<span id="cb10-13"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kube-system</span>          etcd-us-control-plane                        1/1     Running     0          6m50s</span>
<span id="cb10-14"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kube-system</span>          hubble-relay-64d7c9bb65-zwcfk                1/1     Running     0          79s</span>
<span id="cb10-15"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kube-system</span>          hubble-ui-7b4457996f-pzhtf                   2/2     Running     0          79s</span>
<span id="cb10-16"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kube-system</span>          kube-apiserver-us-control-plane              1/1     Running     0          6m52s</span>
<span id="cb10-17"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kube-system</span>          kube-controller-manager-us-control-plane     1/1     Running     0          6m49s</span>
<span id="cb10-18"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kube-system</span>          kube-proxy-nfmw2                             1/1     Running     0          6m30s</span>
<span id="cb10-19"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kube-system</span>          kube-proxy-pmgnx                             1/1     Running     0          6m36s</span>
<span id="cb10-20"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kube-system</span>          kube-proxy-twjbc                             1/1     Running     0          6m29s</span>
<span id="cb10-21"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kube-system</span>          kube-scheduler-us-control-plane              1/1     Running     0          6m49s</span>
<span id="cb10-22"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">local-path-storage</span>   local-path-provisioner-6bc4bddd6b-qxk2z      1/1     Running     0          6m36s</span></code></pre></div></div>
<p>If you followed everything upto to this point, you would have 2 kubernetes clusters with Cilium installed as the CNI and clustermesh enabled in both the clusters. Next we need to connect the two clusters.</p>
</section>
<section id="connect-the-two-clusters" class="level3">
<h3 class="anchored" data-anchor-id="connect-the-two-clusters">4. Connect the two clusters</h3>
<p>To connect the two clusters, we need to use the global terminal with access to both the clusters. (Terminal 3)</p>
<ul>
<li>Open the terminal 3 and execute the following command to merge the two contexts of the US and EU clusters.</li>
</ul>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb11-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Global terminal (Terminal 3)</span></span>
<span id="cb11-2"><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">KUBECONFIG</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>./kubeconfig-us.yaml:./kubeconfig-eu.yaml </span>
<span id="cb11-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kubectl</span> config view <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--flatten</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> merged-kubeconfig.yaml</span></code></pre></div></div>
<ul>
<li>Next set the <code>KUBECONFIG</code> to the newly created merged kubeconfig.</li>
</ul>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb12-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Global terminal (Terminal 3)</span></span>
<span id="cb12-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">export</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">KUBECONFIG</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>./merged-kubeconfig.yaml</span></code></pre></div></div>
<ul>
<li>Finally execute the following command to connect the two clusters.</li>
</ul>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb13-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Global terminal (Terminal 3)</span></span>
<span id="cb13-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> cilium clustermesh connect <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\ </span>                    </span>
<span id="cb13-3">  <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">--context</span> kind-us <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb13-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--destination-context</span> kind-eu</span>
<span id="cb13-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✨</span> Extracting access information of cluster eu...</span>
<span id="cb13-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">🔑</span> Extracting secrets from cluster eu...</span>
<span id="cb13-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">⚠️</span>  Service type NodePort detected! Service may fail when nodes are removed from the cluster!</span>
<span id="cb13-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ℹ️</span>  Found ClusterMesh service IPs: <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">[</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">172.18.0.7</span><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">]</span></span>
<span id="cb13-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✨</span> Extracting access information of cluster us...</span>
<span id="cb13-10"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">🔑</span> Extracting secrets from cluster us...</span>
<span id="cb13-11"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">⚠️</span>  Service type NodePort detected! Service may fail when nodes are removed from the cluster!</span>
<span id="cb13-12"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ℹ️</span>  Found ClusterMesh service IPs: <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">[</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">172.18.0.4</span><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">]</span></span>
<span id="cb13-13"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">⚠️</span> Cilium CA certificates do not match between clusters. Multicluster features will be limited!</span>
<span id="cb13-14"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ℹ️</span> Configuring Cilium in cluster <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'kind-us'</span> to connect to cluster <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'kind-eu'</span></span>
<span id="cb13-15"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">ℹ️</span> Configuring Cilium in cluster <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'kind-eu'</span> to connect to cluster <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'kind-us'</span></span>
<span id="cb13-16"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✅</span> Connected cluster kind-us and kind-eu!</span></code></pre></div></div>
<p>To check the status of the Cilium Cluster Mesh execute the command <code>cilium clustermesh status</code>. You would see an output like the following if everything is working as expected.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb14-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># US cluster (Terminal 1) &amp; EU cluster (Terminal 2)</span></span>
<span id="cb14-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> cilium clustermesh status</span>
<span id="cb14-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">⚠️</span>  Service type NodePort detected! Service may fail when nodes are removed from the cluster!</span>
<span id="cb14-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✅</span> Service <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"clustermesh-apiserver"</span> of type <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"NodePort"</span> found</span>
<span id="cb14-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✅</span> Cluster access information is available:</span>
<span id="cb14-6">  <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">-</span> 172.18.0.4:32379</span>
<span id="cb14-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✅</span> Deployment clustermesh-apiserver is ready</span>
<span id="cb14-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">✅</span> All 3 nodes are connected to all clusters [min:1 / avg:1.0 / max:1]</span>
<span id="cb14-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">🔌</span> Cluster Connections:</span>
<span id="cb14-10">  <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">-</span> eu: 3/3 configured, 3/3 connected</span>
<span id="cb14-11"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">🔀</span> Global services: [ min:0 / avg:0.0 / max:0 ]</span></code></pre></div></div>
</section>
<section id="deploy-the-sample-hello-world-application" class="level3">
<h3 class="anchored" data-anchor-id="deploy-the-sample-hello-world-application">5. Deploy the sample hello world application</h3>
<p>Deploy the sample hello world application by executing the following commands in each of Terminal 1 (US) and Terminal 2(EU).</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb15-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># US cluster (Terminal 1)</span></span>
<span id="cb15-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kubectl</span> apply <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-f</span> deployment-us.yaml</span>
<span id="cb15-3"></span>
<span id="cb15-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># EU cluster (Terminal 2)</span></span>
<span id="cb15-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kubectl</span> apply <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-f</span> deployment-eu.yaml</span></code></pre></div></div>
<p>Check whether sample hello world is working as expected by executing the following command in both US and EU clusters to invoke the hello world service from the busybox pod.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb16" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb16-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># US cluster (Terminal 1)</span></span>
<span id="cb16-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> kubectl exec <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-it</span> busybox-deployment-b7bc87c95-t4z2c <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--</span> /bin/sh <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-c</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'for i in $(seq 1 10); do wget -qO- hello-world:80; echo ""; done'</span></span>
<span id="cb16-3"></span>
<span id="cb16-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from US!"</span>}</span>
<span id="cb16-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from US!"</span>}</span>
<span id="cb16-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from US!"</span>}</span>
<span id="cb16-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from US!"</span>}</span>
<span id="cb16-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from US!"</span>}</span>
<span id="cb16-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from US!"</span>}</span>
<span id="cb16-10"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from US!"</span>}</span>
<span id="cb16-11"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from US!"</span>}</span>
<span id="cb16-12"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from US!"</span>}</span>
<span id="cb16-13"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from US!"</span>}</span>
<span id="cb16-14"></span>
<span id="cb16-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># EU cluster (Terminal 2)</span></span>
<span id="cb16-16"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> kubectl exec <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-it</span> busybox-deployment-b7bc87c95-xhc6l <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--</span> /bin/sh <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-c</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'for i in $(seq 1 10); do wget -qO- hello-world:80; echo ""; done'</span></span>
<span id="cb16-17"></span>
<span id="cb16-18"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb16-19"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb16-20"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb16-21"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb16-22"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb16-23"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb16-24"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb16-25"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb16-26"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb16-27"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span></code></pre></div></div>
<p>Did you notice that all the responses in the US are returned from the hello world service in US ? And all the responses in the EU are returned from the hello world service in EU ? Eventhough we have enabled Cilium Cluster Mesh in both clusters and connected the two clusters, we haven’t enabled the hello world service as a global service. So the requests are load balanced among the pods within the same cluster.</p>
</section>
<section id="enable-hello-world-service-as-a-global-service-to-enable-cross-cluster-service-discovery-and-load-balancing." class="level3">
<h3 class="anchored" data-anchor-id="enable-hello-world-service-as-a-global-service-to-enable-cross-cluster-service-discovery-and-load-balancing.">6. Enable hello world service as a global service to enable cross cluster service discovery and load balancing.</h3>
<p>To enable hello world service as a global service, execute the following command in both US and EU clusters.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/multi-cluster-networking-with-cilium-cluster-mesh/multi-cluster-active.png" class="img-fluid figure-img"></p>
<figcaption>Cross cluster load balancing</figcaption>
</figure>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb17-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># US cluster (Terminal 1) &amp; EU cluster (Terminal 2)</span></span>
<span id="cb17-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kubectl</span> annotate service hello-world service.cilium.io/global=<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"true"</span></span></code></pre></div></div>
<p>Now invoke the hello world service again and notice the responses received.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb18" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb18-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># US cluster (Terminal 1)</span></span>
<span id="cb18-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> kubectl exec <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-it</span> busybox-deployment-b7bc87c95-t4z2c <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--</span> /bin/sh <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-c</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'for i in $(seq 1 10); do wget -qO- hello-world:80; echo ""; done'</span></span>
<span id="cb18-3"></span>
<span id="cb18-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from US!"</span>}</span>
<span id="cb18-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb18-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb18-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb18-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb18-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from US!"</span>}</span>
<span id="cb18-10"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb18-11"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb18-12"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from US!"</span>}</span>
<span id="cb18-13"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb18-14"></span>
<span id="cb18-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># EU cluster (Terminal 2)</span></span>
<span id="cb18-16"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> kubectl exec <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-it</span> busybox-deployment-b7bc87c95-xhc6l <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--</span> /bin/sh <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-c</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'for i in $(seq 1 10); do wget -qO- hello-world:80; echo ""; done'</span></span>
<span id="cb18-17"></span>
<span id="cb18-18"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb18-19"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb18-20"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from US!"</span>}</span>
<span id="cb18-21"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb18-22"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from US!"</span>}</span>
<span id="cb18-23"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb18-24"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb18-25"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from US!"</span>}</span>
<span id="cb18-26"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb18-27"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span></code></pre></div></div>
<p>Now you can see that the requests from the US cluster are load balanced to US and EU and vice versa. Tadaaa!!! We have successfully enabled cross cluster service discovery and load balacing using Cilium Cluster Mesh.</p>
<p>Now in an ideal scenario, we want to load balance globally for fault tolerance only if the local services are not available. Load balancing cross cluster is not ideal always as the latency may get higher comapared to local services. To achive such behaviour, we can use the service affinity rules in Cilium.</p>
</section>
<section id="specify-hello-world-service-affinity-as-local-for-fault-tolerant-cross-cluster-load-balancing." class="level3">
<h3 class="anchored" data-anchor-id="specify-hello-world-service-affinity-as-local-for-fault-tolerant-cross-cluster-load-balancing.">7. Specify hello world service affinity as local for fault tolerant cross cluster load balancing.</h3>
<p>Execute the following command to specify the hello world service affinity as <code>local</code> in the US cluster. This will load balance requests to the hello world service among the pods in the US cluster only and route requests to the other cluster (EU) <strong>only if</strong> the local service is not available.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb19" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb19-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># US cluster (Terminal 1)</span></span>
<span id="cb19-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kubectl</span> annotate service hello-world service.cilium.io/affinity=<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"local"</span></span></code></pre></div></div>
<p>Now if you invoke the hello world service from the US cluster, you will receive responses only from the hello world service in the US cluster.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb20" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb20-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># US cluster (Terminal 1)</span></span>
<span id="cb20-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> kubectl exec <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-it</span> busybox-deployment-b7bc87c95-t4z2c <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--</span> /bin/sh <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-c</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'for i in $(seq 1 10); do wget -qO- hello-world:80; echo ""; done'</span></span>
<span id="cb20-3"></span>
<span id="cb20-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from US!"</span>}</span>
<span id="cb20-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from US!"</span>}</span>
<span id="cb20-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from US!"</span>}</span>
<span id="cb20-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from US!"</span>}</span>
<span id="cb20-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from US!"</span>}</span>
<span id="cb20-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from US!"</span>}</span>
<span id="cb20-10"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from US!"</span>}</span>
<span id="cb20-11"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from US!"</span>}</span>
<span id="cb20-12"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from US!"</span>}</span>
<span id="cb20-13"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from US!"</span>}</span></code></pre></div></div>
<p>To demonstrate the fault tolerant behaviour, scale down the hello world service in US cluster and invoke the hello world service from the US cluster.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb21" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb21-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># US cluster (Terminal 1)</span></span>
<span id="cb21-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kubectl</span> scale deployment hello-world <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--replicas</span> 0</span></code></pre></div></div>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb22" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb22-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># US cluster (Terminal 1)</span></span>
<span id="cb22-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">➜</span> kubectl exec <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-it</span> busybox-deployment-b7bc87c95-t4z2c <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--</span> /bin/sh <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-c</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'for i in $(seq 1 10); do wget -qO- hello-world:80; echo ""; done'</span></span>
<span id="cb22-3"></span>
<span id="cb22-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb22-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb22-6"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb22-7"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb22-8"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb22-9"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb22-10"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb22-11"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb22-12"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span>
<span id="cb22-13"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"message"</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Hello world from Europe!"</span>}</span></code></pre></div></div>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/multi-cluster-networking-with-cilium-cluster-mesh/multi-cluster-passive.png" class="img-fluid figure-img"></p>
<figcaption>Cross cluster fault tolerance</figcaption>
</figure>
</div>
<p>Eventhough the hello world service is down in the US, the requests get routed to the hello world service in EU making it fault tolerant across clusters.</p>
<p>So we have successfully demonstrated the multi cluster service discovery, load balancing and fault tolerance that can be achieved with Cilium Cluster Mesh using two kubernetes clusters running locally in your laptop.</p>
<p><strong>Kubernetes manifests used for the hands on lab:</strong> <a href="https://github.com/NomadXD/samples/tree/main/cilium-cluster-mesh">cilium-cluster-mesh</a></p>
</section>
</section>
<section id="references" class="level2">
<h2 class="anchored" data-anchor-id="references">References</h2>
<ul>
<li><a href="https://docs.cilium.io/en/stable/network/clustermesh/">Cilium Multi-cluster Networking</a></li>
<li><a href="https://cilium.io/blog/2019/03/12/clustermesh/">Deep Dive into Cilium Multi-cluster</a></li>
<li><a href="https://kind.sigs.k8s.io/docs/user/configuration/">KIND cluster configuration</a></li>
</ul>


</section>

 ]]></description>
  <category>Kubernetes</category>
  <category>Networking</category>
  <category>Cilium</category>
  <guid>https://lahirudesilva.com/posts/multi-cluster-networking-with-cilium-cluster-mesh/</guid>
  <pubDate>Fri, 17 May 2024 00:00:00 GMT</pubDate>
  <media:content url="https://lahirudesilva.com/posts/multi-cluster-networking-with-cilium-cluster-mesh/cilium.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Deep dive into Kubernetes custom controllers</title>
  <dc:creator>Lahiru De Silva</dc:creator>
  <link>https://lahirudesilva.com/posts/deep-dive-into-kubernetes-custom-controllers/</link>
  <description><![CDATA[ 






<p>Kubernetes offers a rich ecosystem of <a href="https://kubernetes.io/docs/concepts/extend-kubernetes/">extension points</a> that allow developers to tailor and extend its functionality. Among these ability to implement Custom Controllers emerge as a powerful mechanism for extending Kubernetes with your own “Kubernetes logic”. While there are frameworks and tools like <a href="https://github.com/kubernetes-sigs/kubebuilder">Kubebuilder</a> and <a href="https://sdk.operatorframework.io/">OperatorSDK</a> that abstracts away the complexity of implementing custom controllers, understanding how custom controllers operate at a fundamental level is crucial for those who wish to harness the full potential of Kubernetes. In this article, we will go through how custom controllers work behind the scenes and how you can leverage the basic building blocks of custom controllers for your use cases.</p>
<section id="kubernetes-controller-overview" class="level2">
<h2 class="anchored" data-anchor-id="kubernetes-controller-overview">Kubernetes controller overview</h2>
<p>Controllers serve as the intelligent core or the brain behind Kubernetes by orchestrating and coordinating the lifecycle of resources to ensure the desired state of applications. When resources like Pods, Deployments, Replicasets are created, the relevant controllers respond by performing the required actions to match the current state of the resource with the desired state of the resource.</p>
<p>For instance, consider the scenario of creating a ReplicaSet using kubectl. The ReplicaSet controller promptly detects this action and delegates the task to the kube-scheduler, which schedules the desired number of pods. Once these pods are up and running, the ReplicaSet controller continuously monitors their status through the Kubernetes API server. If, for any reason, a pod terminates unexpectedly, the ReplicaSet controller initiates a request to the kube-scheduler to replace the terminated pod, ensuring that the desired replica count is maintained.</p>
<p>Similarly, Kubernetes ships with a set of built-in controllers packaged within the <code>kube-controller-manager</code>. Each of these controllers operates by running a reconcile loop, which continuously ensures the alignment of the current state of the watched resource with its desired state.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode go code-with-copy"><code class="sourceCode go"><span id="cb1-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb1-2">  desiredState <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:=</span> getDesiredState<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">()</span></span>
<span id="cb1-3">  currentState <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:=</span> getCurrentState<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">()</span></span>
<span id="cb1-4">  makeChanges<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>desiredState<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> currentState<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb1-5"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span></code></pre></div></div>
<!-- For example, if you create a Replicaset via the `kubectl`, the replication controller will notice this and it will delegate `kube-scheduler` to schedule the desired number of pods. When the pods are up and running, it will continously monitor the status of these pods via the `kube API server`. If a pod get terminated, the replication controller will again ask the `kube-schedular` to schedule a pod to compensate the terminated pod. Similarly Kubernetes is packaged and shipped with built in controllers for the -->
</section>
<section id="kubernetes-custom-controllers" class="level2">
<h2 class="anchored" data-anchor-id="kubernetes-custom-controllers">Kubernetes custom controllers</h2>
<p>It’s essential to be familiar with the following terms to understand the concept of custom controllers in Kubernetes.</p>
<ul>
<li><strong>Custom Resources (CRs)</strong> enable you to extend the Kubernetes API and create domain specific objects that are managed by Kubernetes itself like any other built-in objects like Pods, Deployments etc.</li>
<li><strong>Custom Resource Definition (CRDs)</strong> are simply a Kubenetes resource type that is used to register your Custom Resources (CRs) with the Kubernetes API server.</li>
<li><strong>Custom controllers</strong> extend the functionality of Kubernetes by implementing custom logic for managing Custom Resources (CRs).</li>
</ul>
<p>So if you want to extend Kubernetes with your own custom logic,</p>
<ol type="1">
<li>Define a Custom Resource Definition (CRD) to let Kubernetes know about your Custom Resources (CRs).</li>
<li>Run your own reconcile loop for the custom resource type by implementing a custom controller and deploying it in the Kubernetes cluster.</li>
<li>Create Custom Resources (CRs) via a Kubernetes client like <code>kubectl</code>.</li>
</ol>
<p>Following diagram shows how custom controllers fit in with the Kubernetes control plane components and their interactions.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/deep-dive-into-kubernetes-custom-controllers/custom-controller-overview.png" class="img-fluid figure-img"></p>
<figcaption>Kubernetes Custom Controllers</figcaption>
</figure>
</div>
<p>Custom controllers can be deployed as typical Kubernetes deployments.</p>
<p>Now that you have some basic understading about how the Kubernetes custom controllers fit in with other control plane components, let’s dig deeper into the internals of a custom controller.</p>
</section>
<section id="building-blocks-of-a-kubernetes-custom-controller" class="level2">
<h2 class="anchored" data-anchor-id="building-blocks-of-a-kubernetes-custom-controller">Building blocks of a Kubernetes custom controller</h2>
<p>The internal components of a custom controller can be categorized into <strong>two distinct groups</strong> based on their functionalities and implementation:</p>
<section id="kubernetes-client-go-components-shared-informer" class="level3">
<h3 class="anchored" data-anchor-id="kubernetes-client-go-components-shared-informer">1. Kubernetes client-go components (Shared Informer)</h3>
<ul>
<li>These components are initialized and provided out of the box by the <a href="https://github.com/kubernetes/client-go">Kubernetes Go client</a>.</li>
<li>The developer implementing the custom controller has to initialize these components via the Shared Informer interface.</li>
<li>Responsible for watching the Kubernetes API server for resource changes and notifying the event processing components of the custom controller.</li>
</ul>
<p><strong>Informer vs Shared Informer</strong></p>
<p>Evaluating the current state against the desired state requires the controller to interact with the Kubernetes API server to fetch object details. As the number of Kubernetes resources created grows, the frequency of API server calls made by controllers will significantly rise, potentially increasing exponentially. So to reduce the load on the Kubernetes API server, informers or shared informers are introduced.</p>
<p>Informers address this issue by retrieving object data and storing it in the local cache of the controller. The Informer then watches for any create, modify, and delete events that occur afterward. In scenarios where multiple controllers are monitoring a single object, each controller will independently update its local cache. This can result in excessive memory usage and the creation of multiple, potentially inconsistent cache data stores containing object data. This is where the Sharedinformer comes in.</p>
<p>The SharedInformer, as its name implies, is utilized to create a shared cache data store accessible to all controllers, thus resolving the issue of multiple controllers monitoring and updating a single resource or object within the cluster.</p>
<p>Shared informers consist of 4 main components.</p>
<ol type="1">
<li><a href="https://github.com/kubernetes/client-go/blob/master/tools/cache/reflector.go">Reflector</a></li>
<li><a href="https://github.com/kubernetes/client-go/blob/master/tools/cache/fifo.go">Delta FIFO Queue</a></li>
<li><a href="https://github.com/kubernetes/client-go/blob/master/tools/cache/controller.go">Cache controller</a></li>
<li><a href="https://github.com/kubernetes/client-go/blob/master/tools/cache/index.go">Indexer</a></li>
</ol>
</section>
<section id="custom-controller-components" class="level3">
<h3 class="anchored" data-anchor-id="custom-controller-components">2. Custom controller components</h3>
<ul>
<li>These components are implemented by the developer who’s writting the custom controller.</li>
<li>Responsible for processing the events passed from the Shared Informer.</li>
<li>Contains the actual reconcilation logic of the custom controller.</li>
</ul>
<p>Consist of 3 main components.</p>
<ol type="1">
<li>Resource Event handlers.</li>
<li>Work Queue.</li>
<li>Event processing function (Reconcile)</li>
</ol>
<p>Now let’s see how all these components work together and what tasks each of these components perform to achieve the desired functionality of the custom controller.</p>
</section>
</section>
<section id="internal-functionality-of-a-kubernetes-custom-controller" class="level2">
<h2 class="anchored" data-anchor-id="internal-functionality-of-a-kubernetes-custom-controller">Internal functionality of a Kubernetes custom controller</h2>
<p>Following diagram shows the internal interactions between the components of a custom controller and the data flow between the components.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/deep-dive-into-kubernetes-custom-controllers/K8s-custom-controller.png" class="img-fluid figure-img"></p>
<figcaption>Custom controllers internals</figcaption>
</figure>
</div>
<section id="reflector-watches-the-kubernetes-api-server-using-listandwatch-mechanism." class="level3">
<h3 class="anchored" data-anchor-id="reflector-watches-the-kubernetes-api-server-using-listandwatch-mechanism.">1. Reflector watches the Kubernetes API server using ListAndWatch mechanism.</h3>
<p>Reflectors continuously watch the Kubernetes API server for changes in specific resources like Pods, Deployments or Custom Resources and enqueues the Delta FIFO store with events like <code>Add</code>, <code>Update</code>, <code>Delete</code> related to the resources being watched. To perform this, reflectors use the <code>ListAndWatch</code> mechanism provided by the Kubernetes API server.</p>
<p>When a reflector is initialized, it starts by listing all the resources it’s interested in. This initial listing provides a snapshot of the current state of those resources. After the initial listing, the reflector switches to a watch mode where it establishes a long-lived connection with the API server. The API server then notifies the reflector of any changes to the resources in real-time.</p>
<p>To examine the List and Watch capability of the Kubernetes API server, you can follow the following steps.</p>
<ul>
<li>Execute <code>kubectl proxy</code> to call the Kubernetes API server without certificates or tokens.</li>
<li>Execute <code>curl -s http://localhost:8001/api/v1/namespaces/default/pods</code> to list all the pods in default namespace.</li>
</ul>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode json code-with-copy"><code class="sourceCode json"><span id="cb2-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb2-2">  <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"kind"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PodList"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-3">  <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"apiVersion"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"v1"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-4">  <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"metadata"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb2-5">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"resourceVersion"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"582837"</span></span>
<span id="cb2-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">},</span></span>
<span id="cb2-7">  <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"items"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">[]</span></span>
<span id="cb2-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span></span></code></pre></div></div>
<ul>
<li>Capture a resource version and execute <code>curl -s "http://localhost:8001/api/v1/pods?watch=true&amp;resourceVersion=582837"</code> to watch for pods from a specificed resource version onwards. This will establish a persistence HTTP connection with the Kubernetes API Server and the Kubernetes API server will send the resource updates as chunks.</li>
</ul>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">curl</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-s</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-v</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"http://localhost:8001/api/v1/pods?watch=true&amp;resourceVersion=587961"</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-v</span></span>
<span id="cb3-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">*</span>   Trying 127.0.0.1:8001...</span>
<span id="cb3-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">*</span> Connected to localhost <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">127.0.0.1</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">)</span> <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">port</span> 8001 <span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">(</span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">#0)</span></span>
<span id="cb3-4"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> GET <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">/api/v1/pods?watch=true</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">&amp;</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">resourceVersion</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>587961 <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">HTTP/1.1</span></span>
<span id="cb3-5"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> Host: <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">localhost:8001</span></span>
<span id="cb3-6"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> User-Agent: <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">curl/8.1.2</span></span>
<span id="cb3-7"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> Accept: <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">*/*</span></span>
<span id="cb3-8"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb3-9"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> HTTP/1.1 <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">200</span> OK</span>
<span id="cb3-10"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> Audit-Id: <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">9f25e00a-1d6b-47d6-b818-be84ce7458eb</span></span>
<span id="cb3-11"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> Cache-Control: <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">no-cache,</span> private</span>
<span id="cb3-12"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> Content-Type: <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">application/json</span></span>
<span id="cb3-13"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> Date: <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Sat,</span> 30 Sep 2023 08:33:01 GMT</span>
<span id="cb3-14"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> X-Kubernetes-Pf-Flowschema-Uid: <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">2eeceae7-9692-4905-85ba-1ad01882320d</span></span>
<span id="cb3-15"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> X-Kubernetes-Pf-Prioritylevel-Uid: <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">30e13e51-7784-4c62-acb5-b944f96ae4da</span></span>
<span id="cb3-16"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> Transfer-Encoding: <span class="ex" style="color: null;
background-color: null;
font-style: inherit;">chunked</span></span></code></pre></div></div>
<ul>
<li>Execute <code>kubectl run nginx --image=nginx</code> and notice the <code>CREATE</code> event received through the other terminal in watch mode.</li>
</ul>
<p>The received events via the watch are called deltas and the deltas will be enqueued into the <a href="https://github.com/kubernetes/client-go/blob/master/tools/cache/delta_fifo.go">Delta FIFO Queue</a>, which is an incremental first-in first-out queue.</p>
</section>
<section id="delta-fifo-queue-stores-the-resource-changes-as-deltas." class="level3">
<h3 class="anchored" data-anchor-id="delta-fifo-queue-stores-the-resource-changes-as-deltas.">2. Delta FIFO queue stores the resource changes as deltas.</h3>
<p>This is a special store that maintains deltas, which is a structure containing the changed object and the type of change.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode go code-with-copy"><code class="sourceCode go"><span id="cb4-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">type</span> Delta <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb4-2">    Type   DeltaType</span>
<span id="cb4-3">    Object <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">interface</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{}</span></span>
<span id="cb4-4"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span></code></pre></div></div>
<p>The Delta objects in the queue will be eventually popped out and processed by the cache controller.</p>
</section>
<section id="cache-controller-popping-deltas-and-processing-deltas" class="level3">
<h3 class="anchored" data-anchor-id="cache-controller-popping-deltas-and-processing-deltas">3. Cache controller popping deltas and processing deltas</h3>
<p>When the cache controller is initiated, <a href="https://github.com/kubernetes/client-go/blob/6b97f71afcff4f2d6560c79e9e304cc31a8b4ef7/tools/cache/controller.go#L129">it starts 2 go routines</a>.</p>
<ol type="1">
<li>Creates a Reflector and runs the reflector in a separate go routine to watch resources in Kubernetes API server.</li>
<li>Blocks its main go routine on the <a href="https://github.com/kubernetes/client-go/blob/6b97f71afcff4f2d6560c79e9e304cc31a8b4ef7/tools/cache/controller.go#L186">processLoop()</a> method which continously pop deltas from the Delta FIFO queue and process deltas.</li>
</ol>
<p><a href="https://github.com/kubernetes/client-go/blob/6b97f71afcff4f2d6560c79e9e304cc31a8b4ef7/tools/cache/controller.go#L186">processLoop()</a> method will invoke <a href="https://github.com/kubernetes/client-go/blob/6b97f71afcff4f2d6560c79e9e304cc31a8b4ef7/tools/cache/controller.go#L436">processDeltas()</a> method which will perform 2 main functions.</p>
<ol type="1">
<li>Update the indexer according to the detected change retrieved from the delta FIFO queue.</li>
<li>Trigger the pre-registered Resource Event Handlers according to the event type. (These are the resource event handlers registered by the developer when creating a SharedInformer. In the resource event handlers, usually only some simple filtering is done, and then the event is added into the Work Queue)</li>
</ol>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode go code-with-copy"><code class="sourceCode go"><span id="cb5-1">sharedInformer<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>AddEventHandler<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span id="cb5-2">        <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span>cache<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>ResourceEventHandlerFuncs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb5-3">            AddFunc<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>    onAdd<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-4">            DeleteFunc<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> onDelete<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-5">            UpdateFunc<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> onUpdate<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb5-6">        <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">})</span></span></code></pre></div></div>
<p><code>onAdd</code>, <code>onDelete</code> and <code>onUpdate</code> resource event handlers are functions implemented by the developer.</p>
</section>
<section id="resource-event-handlers-enqueue-the-object-key-to-the-work-queue" class="level3">
<h3 class="anchored" data-anchor-id="resource-event-handlers-enqueue-the-object-key-to-the-work-queue">4. Resource event handlers enqueue the object key to the work queue</h3>
<p>Resource event handlers serve as callback functions that the Shared Informer calls to deliver objects to the controller’s event processing functions. The common practice for writing these functions involves retrieving the key associated with the dispatched object (<code>namespace/name</code>) and enqueueing that key in the work queue for subsequent processing.</p>
<p>The work queue <strong>decouples the event arrival from processing</strong>, allowing the controller to process events in a controlled and predictable manner, preventing event processing bottlenecks. For example, Shared Informers may operate at different speeds than controller event processing functions, and work queues help prevent the Shared Informer from overloading a slower controller event processor.</p>
</section>
<section id="dequeueing-events-from-the-work-queue-and-reconciliation" class="level3">
<h3 class="anchored" data-anchor-id="dequeueing-events-from-the-work-queue-and-reconciliation">5. Dequeueing events from the work queue and reconciliation</h3>
<p>Event processing functions are the functions that you implement in your code to process items from the work queue. There can be one or more other functions that do the actual processing.</p>
<p>These functions will typically use the Indexer to retrieve the object corresponding to the key and perform the actual event processing logic you have implemented.</p>
<p>Multiple go routines can be spawned to process event updates and each of these worker go routines will call <code>processNextWorkItem</code> which will dequeue object keys from the work queue and call <code>syncHandler</code> method to perform reconcilation logic.</p>
<p>Depending on the reconcilation logic, you may need to call the Kubernetes API server or any other external services. And mostly importantly, once the reconciliation logic is performed, the status of the resource should be updated and typically the performed actions is added into the Events array.</p>
<p>If you are using a framework like <a href="https://github.com/kubernetes-sigs/kubebuilder">Kubebuilder</a> or <a href="https://sdk.operatorframework.io/">OperatorSDK</a>, this is the point where you write reconciliation logic inside the <code>Reconcile()</code> method of the generated controller code.</p>
</section>
</section>
<section id="summary" class="level2">
<h2 class="anchored" data-anchor-id="summary">Summary</h2>
<p>In summary, the following sequence of events take place inside the Kubernetes custom controller.</p>
<ol type="1">
<li>Reflector watches Kubernetes API server and add resource changes (deltas) to Delta FIFO Queue.</li>
<li>Cache controller pops these changes out from the Delta FIFO Queue and update the indexer.</li>
<li>Cache controller trigger the pre-registered resource event handlers.</li>
<li>Pre-registered resource event handlers filters the events and add the object keys to the work queue.</li>
<li>Custom controller event processing functions pops out the object keys, retrieve the object using the keys from the indexer and perform reconcilation logic.</li>
<li>After performing reconcilation logic, custom controller updates the status of the object by calling the Kubernetes API server.</li>
</ol>
<p>Now to get started with implementing a custom controller, you can use this <a href="https://github.com/kubernetes/sample-controller">sample controller</a> from the Kubernetes community as the starting point.</p>


</section>

 ]]></description>
  <category>Kubernetes</category>
  <category>Controllers</category>
  <guid>https://lahirudesilva.com/posts/deep-dive-into-kubernetes-custom-controllers/</guid>
  <pubDate>Sat, 30 Sep 2023 00:00:00 GMT</pubDate>
  <media:content url="https://lahirudesilva.com/posts/deep-dive-into-kubernetes-custom-controllers/deep-dive-kubernetes-controllers-cover.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>How to implement a K8s operator like a Ninja</title>
  <dc:creator>Lahiru De Silva</dc:creator>
  <link>https://lahirudesilva.com/posts/how-to-implement-a-k8s-operator-like-a-ninja/</link>
  <description><![CDATA[ 






<p>Kubernetes has emerged as the widely accepted standard for deploying and running modern cloud-native applications. With its declarative approach using YAML, it offers a straightforward and intuitive method to define the desired infrastructure state for application deployments. However, managing complex application deployments on Kubernetes requires additional automation and control beyond what Kubernetes provides out of the box. This is where Kubernetes operators come in.</p>
<p>Operators extend the capabilities of Kubernetes by encapsulating domain-specific knowledge and best practices into custom controllers. By leveraging operators, organizations can automate the management of complex application lifecycles, enable self-healing, autoscaling, and perform advanced operations such as backups, upgrades, and rolling deployments. Kubernetes operators help streamline and simplify the deployment and management of applications on Kubernetes, enhancing scalability, reliability, and efficiency.</p>
<p>There are several approaches to building a Kubernetes operator. One option is to develop one from scratch using the <a href="https://github.com/kubernetes/client-go">Kubernetes Go Client</a>, but this can be a challenging and time-consuming task due to the steep learning curve involved. Alternatively, there are tools available that provide boilerplate code and streamline the process of creating operators. Two popular choices are <a href="https://sdk.operatorframework.io/">OperatorSDK</a> and <a href="https://github.com/kubernetes-sigs/kubebuilder">Kubebuilder</a>. In this article, we will primarily focus on utilizing Kubebuilder to create an operator, leveraging its features to expedite the development process.</p>
<section id="scaffolding-the-project-with-kubebuilder" class="level2">
<h2 class="anchored" data-anchor-id="scaffolding-the-project-with-kubebuilder">Scaffolding the project with Kubebuilder</h2>
<div class="callout callout-style-default callout-note callout-titled" title="Prerequisites">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Prerequisites
</div>
</div>
<div class="callout-body-container callout-body">
<ul>
<li>go version v1.20.0+</li>
<li>kubectl version v1.11.3+.</li>
<li>Access to a Kubernetes v1.11.3+ cluster.</li>
</ul>
</div>
</div>
<p>Kubebuilder offers a command-line interface (CLI) that facilitates the creation and management of operator projects. To initiate a new project, all you need to do is execute the following command:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kubebuilder</span> init <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--domain</span> nomadxd.io <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--plugins</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>go/v4-alpha <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--repo</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>github.com/NomadXD/samples/k8s-operator-kube-builder</span></code></pre></div></div>
<p>Once executed, Kubebuilder will generate a directory structure, enabling you to immediately begin developing the operator.</p>
</section>
<section id="creating-the-custom-resource-and-controller" class="level2">
<h2 class="anchored" data-anchor-id="creating-the-custom-resource-and-controller">Creating the Custom Resource and controller</h2>
<p>To enable the desired functionality of an operator, Custom Resource Definitions (CRDs) are utilized in conjunction with a controller. By defining CRDs, you can extend the Kubernetes API and introduce custom resources tailored to your specific application or workload. These CRDs serve as the basis for creating and managing instances of your custom resources.</p>
<p>To ensure the desired state of the custom resources is maintained, a controller is implemented. The controller continuously monitors the state of the custom resources and takes actions to reconcile any differences between the desired state and the actual state of the cluster. This may involve creating, updating, or deleting Kubernetes resources based on changes in the custom resources.</p>
<p>Use the following command to create a new Go type which corresponds to a CRD in K8s. It will prompt for 2 options to create resource and controller and input y to both of the cases.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kubebuilder</span> create api <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--group</span> podrunner <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--version</span> v1alpha1 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--kind</span> PodRunner</span>
<span id="cb2-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Create</span> Resource <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">[</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">y/n</span><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">]</span></span>
<span id="cb2-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">y</span></span>
<span id="cb2-4"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">Create</span> Controller <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">[</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">y/n</span><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">]</span></span>
<span id="cb2-5"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">y</span></span></code></pre></div></div>
</section>
<section id="exploring-the-generated-code" class="level2">
<h2 class="anchored" data-anchor-id="exploring-the-generated-code">Exploring the generated code</h2>
<p>Now all the boilerplate required to implement the operator is generated. The core components of an operator are found in the following locations:</p>
<ul>
<li><strong>/api/v1alpha1/podrunner_types.go</strong></li>
</ul>
<p>Contains the Custom Resource type definition in Go. Spec and Status types should be extended by adding the required feilds. Spec means the desired state and the Status means the current state. A controller basically runs a reconcile loop to match the current state with the desired state.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode go code-with-copy"><code class="sourceCode go"><span id="cb3-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/*</span></span>
<span id="cb3-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">Copyright 2023.</span></span>
<span id="cb3-3"></span>
<span id="cb3-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">Licensed under the Apache License, Version 2.0 (the "License");</span></span>
<span id="cb3-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">you may not use this file except in compliance with the License.</span></span>
<span id="cb3-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">You may obtain a copy of the License at</span></span>
<span id="cb3-7"></span>
<span id="cb3-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    http://www.apache.org/licenses/LICENSE-2.0</span></span>
<span id="cb3-9"></span>
<span id="cb3-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">Unless required by applicable law or agreed to in writing, software</span></span>
<span id="cb3-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">distributed under the License is distributed on an "AS IS" BASIS,</span></span>
<span id="cb3-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span></span>
<span id="cb3-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">See the License for the specific language governing permissions and</span></span>
<span id="cb3-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">limitations under the License.</span></span>
<span id="cb3-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*/</span></span>
<span id="cb3-16"></span>
<span id="cb3-17"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">package</span> v1alpha1</span>
<span id="cb3-18"></span>
<span id="cb3-19"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">import</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span id="cb3-20">    metav1 <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"k8s.io/apimachinery/pkg/apis/meta/v1"</span></span>
<span id="cb3-21"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb3-22"></span>
<span id="cb3-23"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// EDIT THIS FILE!  THIS IS SCAFFOLDING FOR YOU TO OWN!</span></span>
<span id="cb3-24"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// </span><span class="al" style="color: #AD0000;
background-color: null;
font-style: inherit;">NOTE</span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">: json tags are required.  Any new fields you add must have json tags for the fields to be serialized.</span></span>
<span id="cb3-25"></span>
<span id="cb3-26"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// PodRunnerSpec defines the desired state of PodRunner</span></span>
<span id="cb3-27"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">type</span> PodRunnerSpec <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb3-28">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster</span></span>
<span id="cb3-29">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Important: Run "make" to regenerate code after modifying this file</span></span>
<span id="cb3-30"></span>
<span id="cb3-31">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Foo is an example field of PodRunner. Edit podrunner_types.go to remove/update</span></span>
<span id="cb3-32">    Foo <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">string</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`json:"foo,omitempty"`</span></span>
<span id="cb3-33"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb3-34"></span>
<span id="cb3-35"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// PodRunnerStatus defines the observed state of PodRunner</span></span>
<span id="cb3-36"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">type</span> PodRunnerStatus <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb3-37">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster</span></span>
<span id="cb3-38">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Important: Run "make" to regenerate code after modifying this file</span></span>
<span id="cb3-39"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb3-40"></span>
<span id="cb3-41"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//+kubebuilder:object:root=true</span></span>
<span id="cb3-42"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//+kubebuilder:subresource:status</span></span>
<span id="cb3-43"></span>
<span id="cb3-44"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// PodRunner is the Schema for the podrunners API</span></span>
<span id="cb3-45"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">type</span> PodRunner <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb3-46">    metav1<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>TypeMeta   <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`json:",inline"`</span></span>
<span id="cb3-47">    metav1<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>ObjectMeta <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`json:"metadata,omitempty"`</span></span>
<span id="cb3-48"></span>
<span id="cb3-49">    Spec   PodRunnerSpec   <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`json:"spec,omitempty"`</span></span>
<span id="cb3-50">    Status PodRunnerStatus <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`json:"status,omitempty"`</span></span>
<span id="cb3-51"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb3-52"></span>
<span id="cb3-53"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//+kubebuilder:object:root=true</span></span>
<span id="cb3-54"></span>
<span id="cb3-55"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// PodRunnerList contains a list of PodRunner</span></span>
<span id="cb3-56"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">type</span> PodRunnerList <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb3-57">    metav1<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>TypeMeta <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`json:",inline"`</span></span>
<span id="cb3-58">    metav1<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>ListMeta <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`json:"metadata,omitempty"`</span></span>
<span id="cb3-59">    Items           <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">[]</span>PodRunner <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`json:"items"`</span></span>
<span id="cb3-60"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb3-61"></span>
<span id="cb3-62"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">func</span> init<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">()</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb3-63">    SchemeBuilder<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Register<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(&amp;</span>PodRunner<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{},</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span>PodRunnerList<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{})</span></span>
<span id="cb3-64"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span></code></pre></div></div>
<ul>
<li><strong>/controllers/podrunner_controller.go</strong></li>
</ul>
<p>Extend the <code>Reconcile()</code> method to implement reconcile logic to match the current state with the desired state.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode go code-with-copy"><code class="sourceCode go"><span id="cb4-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/*</span></span>
<span id="cb4-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">Copyright 2023.</span></span>
<span id="cb4-3"></span>
<span id="cb4-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">Licensed under the Apache License, Version 2.0 (the "License");</span></span>
<span id="cb4-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">you may not use this file except in compliance with the License.</span></span>
<span id="cb4-6"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">You may obtain a copy of the License at</span></span>
<span id="cb4-7"></span>
<span id="cb4-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    http://www.apache.org/licenses/LICENSE-2.0</span></span>
<span id="cb4-9"></span>
<span id="cb4-10"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">Unless required by applicable law or agreed to in writing, software</span></span>
<span id="cb4-11"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">distributed under the License is distributed on an "AS IS" BASIS,</span></span>
<span id="cb4-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.</span></span>
<span id="cb4-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">See the License for the specific language governing permissions and</span></span>
<span id="cb4-14"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">limitations under the License.</span></span>
<span id="cb4-15"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*/</span></span>
<span id="cb4-16"></span>
<span id="cb4-17"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">package</span> controllers</span>
<span id="cb4-18"></span>
<span id="cb4-19"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">import</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span id="cb4-20">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"context"</span></span>
<span id="cb4-21"></span>
<span id="cb4-22">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"k8s.io/apimachinery/pkg/runtime"</span></span>
<span id="cb4-23">    ctrl <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sigs.k8s.io/controller-runtime"</span></span>
<span id="cb4-24">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sigs.k8s.io/controller-runtime/pkg/client"</span></span>
<span id="cb4-25">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sigs.k8s.io/controller-runtime/pkg/log"</span></span>
<span id="cb4-26"></span>
<span id="cb4-27">    podrunnerv1alpha1 <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"github.com/NomadXD/samples/k8s-operator-kube-builder/api/v1alpha1"</span></span>
<span id="cb4-28"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb4-29"></span>
<span id="cb4-30"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// PodRunnerReconciler reconciles a PodRunner object</span></span>
<span id="cb4-31"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">type</span> PodRunnerReconciler <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb4-32">    client<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Client</span>
<span id="cb4-33">    Scheme <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>runtime<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Scheme</span>
<span id="cb4-34"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb4-35"></span>
<span id="cb4-36"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//+kubebuilder:rbac:groups=podrunner.nomadxd.io,resources=podrunners,verbs=get;list;watch;create;update;patch;delete</span></span>
<span id="cb4-37"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//+kubebuilder:rbac:groups=podrunner.nomadxd.io,resources=podrunners/status,verbs=get;update;patch</span></span>
<span id="cb4-38"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//+kubebuilder:rbac:groups=podrunner.nomadxd.io,resources=podrunners/finalizers,verbs=update</span></span>
<span id="cb4-39"></span>
<span id="cb4-40"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Reconcile is part of the main kubernetes reconciliation loop which aims to</span></span>
<span id="cb4-41"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// move the current state of the cluster closer to the desired state.</span></span>
<span id="cb4-42"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// </span><span class="al" style="color: #AD0000;
background-color: null;
font-style: inherit;">TODO</span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(user): Modify the Reconcile function to compare the state specified by</span></span>
<span id="cb4-43"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// the PodRunner object against the actual cluster state, and then</span></span>
<span id="cb4-44"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// perform operations to make the cluster state reflect the state specified by</span></span>
<span id="cb4-45"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// the user.</span></span>
<span id="cb4-46"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//</span></span>
<span id="cb4-47"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// For more details, check Reconcile and its Result here:</span></span>
<span id="cb4-48"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.13.0/pkg/reconcile</span></span>
<span id="cb4-49"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">func</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>r <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>PodRunnerReconciler<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> Reconcile<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>ctx context<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Context<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> req ctrl<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Request<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>ctrl<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Result<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">error</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb4-50">    _ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> log<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>FromContext<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>ctx<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb4-51"></span>
<span id="cb4-52">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// </span><span class="al" style="color: #AD0000;
background-color: null;
font-style: inherit;">TODO</span><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(user): your logic here</span></span>
<span id="cb4-53"></span>
<span id="cb4-54">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> ctrl<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Result<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{},</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">nil</span></span>
<span id="cb4-55"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb4-56"></span>
<span id="cb4-57"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// SetupWithManager sets up the controller with the Manager.</span></span>
<span id="cb4-58"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">func</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>r <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>PodRunnerReconciler<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> SetupWithManager<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>mgr ctrl<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Manager<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">error</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb4-59">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> ctrl<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>NewControllerManagedBy<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>mgr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">).</span></span>
<span id="cb4-60">        For<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(&amp;</span>podrunnerv1alpha1<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>PodRunner<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{}).</span></span>
<span id="cb4-61">        Complete<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>r<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb4-62"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span></code></pre></div></div>
</section>
<section id="defining-the-desired-state" class="level2">
<h2 class="anchored" data-anchor-id="defining-the-desired-state">Defining the desired state</h2>
<p>For this tutorial, I will implement an operator which can run a Pod based on an image name we provide with the Custom Resource. To implement that, I have extended the <code>PodRunnerSpec</code> as follows.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode go code-with-copy"><code class="sourceCode go"><span id="cb5-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// PodRunnerSpec defines the desired state of PodRunner</span></span>
<span id="cb5-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">type</span> PodRunnerSpec <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb5-3">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// PodName is the name of the pod.</span></span>
<span id="cb5-4">    PodName <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">string</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`json:"podName,omitempty"`</span></span>
<span id="cb5-5"></span>
<span id="cb5-6">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// ImageName is the name of the image used to run the pod.</span></span>
<span id="cb5-7">    ImageName <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">string</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`json:"imageName,omitempty"`</span></span>
<span id="cb5-8"></span>
<span id="cb5-9">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Namespace where the pod is scheduled to run.</span></span>
<span id="cb5-10">    Namespace <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">string</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">`json:"namespace,omitempty"`</span></span>
<span id="cb5-11"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span></code></pre></div></div>
</section>
<section id="generating-and-installing-the-crds" class="level2">
<h2 class="anchored" data-anchor-id="generating-and-installing-the-crds">Generating and installing the CRDs</h2>
<p>After that execute the following commands.</p>
<ol type="1">
<li><code>make generate</code> - This generates the required deep copy methods</li>
<li><code>make manifests</code> - To generate the Kubernetes CRDs from the defined Go types. Generated CRDs are located in <code>config/crd/bases/</code></li>
<li><code>make install</code> - To apply the CRDs to the K8s API server</li>
</ol>
<p>Now the Kubernetes API server knows about the resources of type <code>PodRunner</code>.</p>
</section>
<section id="implementing-the-reconciliation-logic" class="level2">
<h2 class="anchored" data-anchor-id="implementing-the-reconciliation-logic">Implementing the reconciliation logic</h2>
<p>Now to implement the logic for scheduling the pod on the given namespace using the provided image name, extend the <code>Reconcile()</code> method in the controller boilerplate as follows.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode go code-with-copy"><code class="sourceCode go"><span id="cb6-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">func</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>r <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>PodRunnerReconciler<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> Reconcile<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>ctx context<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Context<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> req ctrl<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Request<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>ctrl<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Result<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">error</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb6-2">    logger <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:=</span> log<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>FromContext<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>ctx<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb6-3"></span>
<span id="cb6-4">    podRunner <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span>podrunnerv1alpha1<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>PodRunner<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{}</span></span>
<span id="cb6-5">    err <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:=</span> r<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Get<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>ctx<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> req<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>NamespacedName<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> podRunner<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb6-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> err <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">nil</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb6-7">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Error reading the PodRunner instance, requeue the request</span></span>
<span id="cb6-8">        logger<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Error<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>err<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Failed to get PodRunner"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb6-9">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> ctrl<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Result<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{},</span> client<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>IgnoreNotFound<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>err<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb6-10">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb6-11"></span>
<span id="cb6-12">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Create a Pod based on the PodRunner specification</span></span>
<span id="cb6-13">    podRunnerPod <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span>corev1<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Pod<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb6-14">        ObjectMeta<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> metav1<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>ObjectMeta<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb6-15">            Name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>      podRunner<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Spec<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>PodName<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb6-16">            Namespace<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> podRunner<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Spec<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Namespace<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb6-17">        <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">},</span></span>
<span id="cb6-18">        Spec<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> corev1<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>PodSpec<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb6-19">            Containers<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">[]</span>corev1<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Container<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb6-20">                <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb6-21">                    Name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>            podRunner<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Spec<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>PodName<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb6-22">                    Image<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>           podRunner<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Spec<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>ImageName<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb6-23">                    ImagePullPolicy<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> corev1<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>PullAlways<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb6-24">                <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">},</span></span>
<span id="cb6-25">            <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">},</span></span>
<span id="cb6-26">        <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">},</span></span>
<span id="cb6-27">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb6-28"></span>
<span id="cb6-29">    err <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ctrl<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>SetControllerReference<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>podRunner<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> podRunnerPod<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> r<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Scheme<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb6-30">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> err <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">nil</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb6-31">        logger<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Error<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>err<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Failed to set controller reference for Nginx Pod"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb6-32">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> ctrl<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Result<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{},</span> err</span>
<span id="cb6-33">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb6-34"></span>
<span id="cb6-35">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Check if the Pod already exists</span></span>
<span id="cb6-36">    foundPod <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span>corev1<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Pod<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{}</span></span>
<span id="cb6-37">    err <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> r<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Get<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>ctx<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> types<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>NamespacedName<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>Name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> podRunner<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Spec<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>PodName<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> Namespace<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> podRunner<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Spec<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Namespace<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">},</span> foundPod<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb6-38">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> err <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">nil</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;&amp;</span> errors<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>IsNotFound<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>err<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb6-39">        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Create the Pod</span></span>
<span id="cb6-40">        err <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> r<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Create<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>ctx<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> podRunnerPod<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb6-41">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> err <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">nil</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb6-42">            logger<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Error<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>err<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Failed to create Pod"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb6-43">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> ctrl<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Result<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{},</span> err</span>
<span id="cb6-44">        <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb6-45">        logger<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Info<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Pod created"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb6-46">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> ctrl<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Result<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{},</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">nil</span></span>
<span id="cb6-47">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> err <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">nil</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb6-48">        logger<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Error<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>err<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Failed to get Pod"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb6-49">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> ctrl<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Result<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{},</span> err</span>
<span id="cb6-50">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb6-51"></span>
<span id="cb6-52">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Pod already exists, do nothing</span></span>
<span id="cb6-53">    logger<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Info<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Pod already exists"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb6-54">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> ctrl<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Result<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{},</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">nil</span></span>
<span id="cb6-55"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span></code></pre></div></div>
</section>
<section id="running-and-testing-the-operator" class="level2">
<h2 class="anchored" data-anchor-id="running-and-testing-the-operator">Running and testing the operator</h2>
<p>Now execute the command <code>make run</code> to run the operator locally. If you have followed everything correctly upto now, you should have a Kubernetes operator up and running. Now to run a pod, create a Custom Resource of type <code>PodRunner</code> and do a <code>kubectl apply -f</code>.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb7-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">kubectl apply -f - &lt;&lt;EOF</span></span>
<span id="cb7-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">apiVersion</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> podrunner.nomadxd.io/v1alpha1</span></span>
<span id="cb7-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">kind</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> PodRunner</span></span>
<span id="cb7-4"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">metadata</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb7-5"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">name</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> podrunner-sample</span></span>
<span id="cb7-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">spec</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb7-7"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">podName</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> test-pod</span></span>
<span id="cb7-8"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">imageName</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> nginx:latest</span></span>
<span id="cb7-9"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">namespace</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> default</span></span>
<span id="cb7-10"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">EOF</span></span></code></pre></div></div>
<p>If everything is in place, you will see <code>podrunner.podrunner.nomadxd.io/podrunner-sample created</code>. Next execute <code>kubectl get pods</code> to see whether the pod is scheduled by the controller we implemented.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode sh code-with-copy"><code class="sourceCode bash"><span id="cb8-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">kubectl</span> get pods</span>
<span id="cb8-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">NAME</span>       READY   STATUS    RESTARTS   AGE</span>
<span id="cb8-3"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">test-pod</span>   1/1     Running   0          6s</span></code></pre></div></div>
<p>If you execute <code>kubectl describe pod test-pod | grep -i "Controlled By"</code>, you will get <code>Controlled By:  PodRunner/podrunner-sample</code>. So it proves that the pod is scheduled by the controller we implemented.</p>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>By leveraging Kubebuilder’s user-friendly CLI and code generation capabilities, developers can rapidly bring their Kubernetes operators to life within a matter of minutes. With just a few simple commands and a bit of code, complex processes and application management can be streamlined and automated without the need for complex time consuming implementation.</p>
<p><strong>Complete source code for the above setup with Kubebuilder generated files:</strong> <a href="https://github.com/NomadXD/samples/tree/main/k8s-operator-kube-builder">k8s-operator-kube-builder</a></p>


</section>

 ]]></description>
  <category>Kubernetes</category>
  <category>Operators</category>
  <guid>https://lahirudesilva.com/posts/how-to-implement-a-k8s-operator-like-a-ninja/</guid>
  <pubDate>Fri, 14 Jul 2023 00:00:00 GMT</pubDate>
  <media:content url="https://lahirudesilva.com/posts/how-to-implement-a-k8s-operator-like-a-ninja/k8s-operator-kube-builder.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>How I passed my CKA exam on the first attempt</title>
  <dc:creator>Lahiru De Silva</dc:creator>
  <link>https://lahirudesilva.com/posts/my-cka-story/</link>
  <description><![CDATA[ 






<p>Passing the Certified Kubernetes Administrator (CKA) exam was an exhilarating milestone in my career. In this article, I’ll take you through my journey of preparing for and cracking the CKA exam.</p>
<p>I passed the CKA exam in July, 2023 in my first attempt after practising for roughly 4 weeks. I had a good level of Kubernetes experience beforehand the exam practise from my work at the company. I worked on Kubernetes native API gateways for the past 1 year and had a solid understanding about the basic concepts in Kubernetes and how everything works. But there were some missing pieces of the puzzle and I decided to systematically learn the concepts from the beginning by following a course.</p>
<section id="exam-preparation" class="level2">
<h2 class="anchored" data-anchor-id="exam-preparation">Exam preparation</h2>
<p>Regardless of your prior experience working with Kubernetes, I would recommend to purchase a well structured course made in parallel with the CKA syallabus. There are couple of options out there and I chose to go with Mumshad Mannambeth’s CKA course on Udemy as it offers access to KodeCloud practise tests which will help you to practise in a real Kubernetes environment and get hands on experience. If you are well experienced in Kubernetes and feel the videos are too lengthty or time consuming, you can complete the practise tests and get an idea about your current state.</p>
<p>After completing the practise tests, you get 3 mock exams and you can try to complete the exams on the given time and check your grade. But these exams are just for you to practise your skills in a provided time limit and do not simulate the actual exam environment or can’t be considered as a measure to predict your score in the actual CKA exam.</p>
<p>Once you complete the mock exams in KodeCloud, you can try the Killercoda pratise exercises which are completly free. The playgrounds in Killercoda are much closer to the real environment you get in the real CKA exam and the difficulty of the questions are also more closer to the real CKA exam.</p>
<p>After completing the Killercoda practise scenarios, you can try the Killer.sh mock exams you get with the CKA certification. You get 2 free sessions when you purchase the CKA cerfification. These practise environmemt will be active for 36 hours but the timer will be disabled after the first 120 mins and you’ll be graded after that. Try to time for 90 mins and complete all the questions. But keep in mind that the questions on Killer.sh is way more harder than the actual exam and you will be completly fine even if you does not get a passing score. I got 87 out of 120 in my first try which is equivalent to 72.5%. Ideally use your first session before 1 week of the scheduled date of your CKA exam and use the second session like 2 days or 1 day before your scheduled exam.</p>
</section>
<section id="exam-questions" class="level2">
<h2 class="anchored" data-anchor-id="exam-questions">Exam questions</h2>
<p>You will get somewhere between 15 to 20 questions with different difficulty levels. I got 17 questions and out of them around 6 or 7 of them were difficult like the ones in Killer.sh. Another 6 of the questions were pretty easy and doable within 2 mins. The rest of the questions were like the ones you get in KodeCloud mock exams. I completed all the questions within 90 mins and spend the next 30 mins trying to do 3 of the flagged questions which I wasn’t sure what I have done wrong.</p>
</section>
<section id="exam-tips-and-tricks" class="level2">
<h2 class="anchored" data-anchor-id="exam-tips-and-tricks">Exam tips and tricks</h2>
<ul>
<li>First do all the easy and moderate quetions and leave the ones that are difficult and requires more time. You can flag the ones that you have left and come back to them after you finish the easy ones.</li>
<li>Always keep in mind to switch the K8s context, otherwise even though your answers are correct, you won’t get marks</li>
<li>Use <code>--dry-run=client -o yaml</code> to get the K8s manifest as a YAML and edit/add the required info. You can use <code>export do="--dry-run=client -o yaml"</code> alias to save time</li>
<li>Always use imperative way and only use declarative way when it’s absoluelty required</li>
<li>Don’t mess up with the namespaces. Sometimes you run a basic command and wonder what’s wrong or why the resource is not there.</li>
<li>Get comfortable with Vim and know the basics like how to write, delete, copy etc.</li>
<li>Use K8s short names as much as possible</li>
<li>Delete pods without waiting by using <code>--force</code>. You can setup an alias for this also. <code>export now="--force --grace-period 0"</code></li>
<li>Get familiar with the K8s documentation. Specially Concepts, Tasks and Reference sections. You can always search in the K8s docs.</li>
<li>Use <code>kubectl explain</code> to quickly find the feilds of a certain resource.</li>
<li>Remember which node and which context you are in before executing the commands.</li>
<li>Use <code>kubectl -h</code> option to get help for the commands and arguments.</li>
<li>Learn how to do troubleshooting by viewing pod, container and systemd logs. If the kubelet is running in systemd, you’ll need to use <code>journalctl -u kubelet</code> to view kubelet logs. Know how to restart the kubelet with <code>systemctl</code>.</li>
<li>Practise and be ready to complete trivial tasks like backing up and restoring etcd, creating Network policies, PV &amp; PVC etc.</li>
<li>Learn how to view processes with <code>ps</code> and <code>netstat</code>. Also learn how to view network interface details with <code>ip addr</code>.</li>
</ul>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/my-cka-story/cka-cert.png" class="img-fluid figure-img"></p>
<figcaption>My CKA certificate</figcaption>
</figure>
</div>


</section>

 ]]></description>
  <category>Kubernetes</category>
  <category>Certification</category>
  <guid>https://lahirudesilva.com/posts/my-cka-story/</guid>
  <pubDate>Thu, 13 Jul 2023 00:00:00 GMT</pubDate>
  <media:content url="https://lahirudesilva.com/posts/my-cka-story/cka-cover.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Building a Secure and Scalable API layer using Envoy Proxy</title>
  <dc:creator>Lahiru De Silva</dc:creator>
  <link>https://lahirudesilva.com/posts/building-secure-scalable-api-layer/</link>
  <description><![CDATA[ 






<p>APIs (Application Programming Interfaces) have become an integral part of modern software development. They allow different applications to communicate and exchange data, enabling developers to create complex systems that integrate multiple services and technologies. APIs are used by companies of all sizes to power their digital products and services, from social media platforms to financial systems.</p>
<p>However, APIs can also be complex and challenging to manage, particularly when it comes to security and scalability. As APIs are exposed to the internet, they are vulnerable to attacks such as injection, denial of service, and man-in-the-middle attacks. Furthermore, as API usage grows, it becomes increasingly challenging to scale them to meet the demands of growing user bases and increasing traffic. This article aims to demonstrate the use of open source technologies, such as Envoy Proxy, to build a secure, scalable, and resilient Application Programming Interface (API) layer for organizations that depend heavily on APIs.</p>
<p>The following design will be implemented within the scope of this article to demonstrate the creation of a secure and scalable API layer.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/building-secure-scalable-api-layer/secure-scalable-design.png" class="img-fluid figure-img"></p>
<figcaption>Solid lines show the request/response flow and dotted lines show the telemetry data flow</figcaption>
</figure>
</div>
<p>First, let’s start with the external authentication service and the related proxy configuration, as it is the first service that Envoy Proxy calls when a request is received.</p>
<section id="external-authorization-with-external-authorization-grpc-service" class="level2">
<h2 class="anchored" data-anchor-id="external-authorization-with-external-authorization-grpc-service">External authorization with external authorization gRPC service</h2>
<p>Envoy Proxy supports external authorization through its built-in external authorization filter. The external authorization filter should be added to the filter chain with a reference to the relevant external gRPC/HTTP service. When a request is received, it is propagated through the filter chain, and upon reaching the external authorization filter, Envoy Proxy sends an authorization check request to the configured external authorization service. The authorization service receives the request, which includes information about the original request from the client/downstream, such as headers and body. After performing authorization, the external authorization service must return the response in the expected format for Envoy Proxy. Based on the response, Envoy Proxy will either pass the request to the next filter or return an unauthorized response to the client/downstream.</p>
<p>This approach allows for a flexible and modular authorization architecture, where the authorization logic can be separated from the core application logic, making it easier to manage and scale. Additionally, it enables integration with a wide range of authorization providers, such as OAuth, LDAP, and more.</p>
<p>Let’s go through the relevant envoy proxy configuration and the sample external authorization gRPC service.</p>
<section id="external-authorization-filter-configuration" class="level3">
<h3 class="anchored" data-anchor-id="external-authorization-filter-configuration">External authorization filter configuration</h3>
<p>Add external authorization filter to the filter chain with a reference to the cluster that represents the external authorization service.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">http_filters</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb1-2"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">name</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> envoy.filters.http.ext_authz</span></span>
<span id="cb1-3"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">typed_config</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb1-4"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">"@type"</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz</span></span>
<span id="cb1-5"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">grpc_service</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb1-6"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">envoy_grpc</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb1-7"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">          </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cluster_name</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> ext_authz</span></span>
<span id="cb1-8"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">timeout</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> 2s</span></span>
<span id="cb1-9"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">transport_api_version</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> V3</span></span></code></pre></div></div>
</section>
<section id="external-authorization-service-configuration" class="level3">
<h3 class="anchored" data-anchor-id="external-authorization-service-configuration">External authorization service configuration</h3>
<p>Add the external authorization cluster to the cluster configuration.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb2-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">clusters</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb2-2"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">name</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> ext_authz</span></span>
<span id="cb2-3"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">type</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> STRICT_DNS</span></span>
<span id="cb2-4"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lb_policy</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> ROUND_ROBIN</span></span>
<span id="cb2-5"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">typed_extension_protocol_options</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb2-6"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">envoy.extensions.upstreams.http.v3.HttpProtocolOptions</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb2-7"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">          </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">"@type"</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions</span></span>
<span id="cb2-8"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">          </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">explicit_http_config</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb2-9"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">            </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">http2_protocol_options</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">{}</span></span>
<span id="cb2-10"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">load_assignment</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb2-11"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cluster_name</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> ext_authz</span></span>
<span id="cb2-12"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">endpoints</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb2-13"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">          </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lb_endpoints</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb2-14"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">              </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">endpoint</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb2-15"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">                  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">address</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb2-16"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">                    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">socket_address</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb2-17"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">                      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">address</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> ext_authz</span></span>
<span id="cb2-18"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">                      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">port_value</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50051</span></span></code></pre></div></div>
</section>
<section id="sample-grpc-authorization-service-written-in-go" class="level3">
<h3 class="anchored" data-anchor-id="sample-grpc-authorization-service-written-in-go">Sample gRPC authorization service written in go</h3>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode go code-with-copy"><code class="sourceCode go"><span id="cb3-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">package</span> main</span>
<span id="cb3-2"></span>
<span id="cb3-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">import</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span id="cb3-4">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"context"</span></span>
<span id="cb3-5">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fmt"</span></span>
<span id="cb3-6">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"log"</span></span>
<span id="cb3-7">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"net"</span></span>
<span id="cb3-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"net/http"</span></span>
<span id="cb3-9">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"strings"</span></span>
<span id="cb3-10">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"time"</span></span>
<span id="cb3-11"></span>
<span id="cb3-12">    auth <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"github.com/envoyproxy/go-control-plane/envoy/service/auth/v3"</span></span>
<span id="cb3-13">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"github.com/golang-jwt/jwt"</span></span>
<span id="cb3-14">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"google.golang.org/genproto/googleapis/rpc/code"</span></span>
<span id="cb3-15">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"google.golang.org/genproto/googleapis/rpc/status"</span></span>
<span id="cb3-16">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"google.golang.org/grpc"</span></span>
<span id="cb3-17"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb3-18"></span>
<span id="cb3-19"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">type</span> AuthServer <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">struct</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{}</span></span>
<span id="cb3-20"> </span>
<span id="cb3-21"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> secretKey <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">[]</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">byte</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">[]</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">byte</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"my_secret_key"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb3-22"></span>
<span id="cb3-23"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">func</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>authServer <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>AuthServer<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> Check<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>ctx context<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Context<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> request <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>auth<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>CheckRequest<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(*</span>auth<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>CheckResponse<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">error</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb3-24">    log<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Printf<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Auth server received auth request: %v"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> request<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>String<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">())</span></span>
<span id="cb3-25">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Extract the authorization token from the request</span></span>
<span id="cb3-26">    authHeader<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> ok <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:=</span> request<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Attributes<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Request<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Http<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Headers<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">[</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"authorization"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">]</span></span>
<span id="cb3-27">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> tokenString <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">string</span></span>
<span id="cb3-28"></span>
<span id="cb3-29">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> ok <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb3-30">        tokenString <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> strings<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>TrimPrefix<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>authHeader<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Bearer "</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb3-31">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb3-32">    fmt<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Printf<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Token: %s"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> tokenString<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb3-33">    _<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> err <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:=</span> jwt<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Parse<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>tokenString<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">func</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>token <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>jwt<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Token<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">interface</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{},</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">error</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb3-34">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> _<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> ok <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:=</span> token<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Method<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.(*</span>jwt<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>SigningMethodHMAC<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">);</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>ok <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb3-35">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">nil</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> fmt<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Errorf<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"unexpected signing method: %v"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> token<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Header<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">[</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"alg"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">])</span></span>
<span id="cb3-36">        <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb3-37">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> secretKey<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">nil</span></span>
<span id="cb3-38">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">})</span></span>
<span id="cb3-39">    fmt<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Printf<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Error: %v"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> err<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb3-40">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// If valid token, returns Code_OK</span></span>
<span id="cb3-41">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> err <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">nil</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb3-42">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span>auth<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>CheckResponse<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb3-43">            Status<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span>status<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Status<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb3-44">                Code<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">int32</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>code<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Code_OK<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">),</span></span>
<span id="cb3-45">                Message<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AuthServer authentication successful"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb3-46">            <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">},</span></span>
<span id="cb3-47">        <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">},</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">nil</span></span>
<span id="cb3-48">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb3-49">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// If invalid token, returns Code_PERMISSION_DENIED </span></span>
<span id="cb3-50">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span>auth<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>CheckResponse<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb3-51">        Status<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span>status<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Status<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb3-52">            Code<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">int32</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>code<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Code_PERMISSION_DENIED<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">),</span></span>
<span id="cb3-53">            Message<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AuthServer authentication unsuccessful"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb3-54">        <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">},</span></span>
<span id="cb3-55">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">},</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">nil</span> </span>
<span id="cb3-56"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb3-57"></span>
<span id="cb3-58"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">func</span> main<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">()</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb3-59">    lis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> err <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:=</span> net<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Listen<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"tcp"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">":50051"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb3-60">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> err <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">nil</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb3-61">        log<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Fatalf<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"failed to listen: %v"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> err<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb3-62">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb3-63">    opts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">[]</span>grpc<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>ServerOption<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>grpc<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>MaxConcurrentStreams<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)}</span></span>
<span id="cb3-64">    s <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:=</span> grpc<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>NewServer<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>opts<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">...)</span></span>
<span id="cb3-65"></span>
<span id="cb3-66">    auth<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>RegisterAuthorizationServer<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>s<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span>AuthServer<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{})</span></span>
<span id="cb3-67"></span>
<span id="cb3-68">    log<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Println<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Starting gRPC Server at 50051"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb3-69">    s<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Serve<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>lis<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb3-70"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span></code></pre></div></div>
</section>
</section>
<section id="rate-limiting-with-envoy-ratelimit-grpc-service" class="level2">
<h2 class="anchored" data-anchor-id="rate-limiting-with-envoy-ratelimit-grpc-service">Rate limiting with Envoy ratelimit gRPC service</h2>
<p>Envoy Proxy offers multiple rate limiting strategies, including local rate limiting, circuit breaking, and global rate limiting. For this article, we will focus on global rate limiting using the Envoy External Rate Limit Service. Local rate limiting and circuit breakers can also be used in cases where network connection level rate limiting is needed, in addition to application level rate limiting enforced by the global rate limit service.</p>
<section id="add-ratelimit-filter-to-the-http-filter-chain" class="level3">
<h3 class="anchored" data-anchor-id="add-ratelimit-filter-to-the-http-filter-chain">Add ratelimit filter to the HTTP filter chain</h3>
<p>Similar to external authorization, we need to add the Envoy Rate Limit filter to the filter chain to enable the Envoy Proxy to call the global rate limit service. It’s important to add the Rate Limit filter after the External Authorization filter to reduce the load on the external ratelimit service.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb4-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">http_filters</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb4-2"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">name</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> envoy.filters.http.ext_authz</span></span>
<span id="cb4-3"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">typed_config</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb4-4"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">"@type"</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz</span></span>
<span id="cb4-5"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">grpc_service</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb4-6"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">envoy_grpc</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb4-7"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">          </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cluster_name</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> ext_authz</span></span>
<span id="cb4-8"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">timeout</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> 2s</span></span>
<span id="cb4-9"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">transport_api_version</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> V3</span></span>
<span id="cb4-10"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">name</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> envoy.filters.http.ratelimit</span></span>
<span id="cb4-11"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">typed_config</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb4-12"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">"@type"</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit</span></span>
<span id="cb4-13"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">domain</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> default</span></span>
<span id="cb4-14"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">failure_mode_deny</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">true</span></span>
<span id="cb4-15"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">enable_x_ratelimit_headers</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> DRAFT_VERSION_03</span></span>
<span id="cb4-16"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rate_limit_service</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb4-17"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">grpc_service</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb4-18"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">          </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">envoy_grpc</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb4-19"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">            </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cluster_name</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> ratelimit</span></span>
<span id="cb4-20"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">transport_api_version</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> V3</span></span></code></pre></div></div>
</section>
<section id="provide-ratelimit-configuration-to-the-external-ratelimit-service" class="level3">
<h3 class="anchored" data-anchor-id="provide-ratelimit-configuration-to-the-external-ratelimit-service">Provide ratelimit configuration to the external ratelimit service</h3>
<p>Envoy Rate Limit Service uses descriptors which are basically key, value pairs to perform rate limiting. In order to use the Envoy Rate Limit Service, we need to provide rate limits related to the descriptors as configuration to the Rate Limit Service.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb5-1"><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">---</span></span>
<span id="cb5-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">domain</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> default</span></span>
<span id="cb5-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">descriptors</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb5-4"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">key</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> version</span></span>
<span id="cb5-5"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">value</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> v1</span></span>
<span id="cb5-6"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rate_limit</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb5-7"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unit</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> second</span></span>
<span id="cb5-8"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">requests_per_unit</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span></span>
<span id="cb5-9"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">key</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> version</span></span>
<span id="cb5-10"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">value</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> v2</span></span>
<span id="cb5-11"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rate_limit</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb5-12"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unit</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> second</span></span>
<span id="cb5-13"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">requests_per_unit</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span></span></code></pre></div></div>
</section>
<section id="add-ratelimit-descriptors-to-the-routes" class="level3">
<h3 class="anchored" data-anchor-id="add-ratelimit-descriptors-to-the-routes">Add ratelimit descriptors to the routes</h3>
<p>Additionally, we need a mechanism for Envoy Proxy to inform the External Rate Limit Service to increment a specific descriptor when a resource is accessed. To achieve this, we need to define descriptors for each resource.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb6-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">route_config</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb6-2"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">name</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> local_route</span></span>
<span id="cb6-3"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">virtual_hosts</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb6-4"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">name</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> upstream</span></span>
<span id="cb6-5"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">domains</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb6-6"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"*"</span></span>
<span id="cb6-7"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">routes</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb6-8"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">match</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb6-9"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">          </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">prefix</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"/api/v1"</span></span>
<span id="cb6-10"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">route</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb6-11"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">          </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cluster</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> upstream_service</span></span>
<span id="cb6-12"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">          </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rate_limits</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb6-13"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">            </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">actions</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb6-14"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">                </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">generic_key</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb6-15"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">                    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">descriptor_key</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> version</span></span>
<span id="cb6-16"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">                    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">descriptor_value</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> v1</span></span>
<span id="cb6-17"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">match</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb6-18"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">          </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">prefix</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"/api/v2"</span></span>
<span id="cb6-19"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">route</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb6-20"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">          </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cluster</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> upstream_service</span></span>
<span id="cb6-21"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">          </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rate_limits</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb6-22"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">            </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">actions</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb6-23"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">                </span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">generic_key</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb6-24"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">                    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">descriptor_key</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> version</span></span>
<span id="cb6-25"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">                    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">descriptor_value</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> v2  </span></span></code></pre></div></div>
<p>In this scenario, we have defined two rate limit keys. When resources with prefix <code>/api/v1</code> are accessed, the rate limit policy with descriptor value <code>v1</code> is applied. Similarly, for resources with prefix <code>/api/v2</code>, the rate limit policy with descriptor value <code>v2</code> is applied. This means that API v1 can be accessed 5 times per minute, while API v2 can be accessed 10 times per minute. If the quota is exceeded, Envoy Proxy returns a 429 error response without processing the request any further.</p>
</section>
</section>
<section id="collecting-telemetry-data-for-distributed-tracing" class="level2">
<h2 class="anchored" data-anchor-id="collecting-telemetry-data-for-distributed-tracing">Collecting telemetry data for distributed tracing</h2>
<p>As demonstrated in the above scenario, Envoy Proxy makes multiple gRPC/HTTP requests to external services during request processing. Therefore, it’s important to have better visibility into what’s happening behind the scenes for debugging errors or monitoring purposes. In the above scenario, we can configure Envoy Proxy, External Authorization Service, and Rate Limit Service to publish telemetry data to a telemetry backend. For this example, we use Jaeger as the telemetry backend and OpenTelemetry to generate telemetry data.</p>
<section id="envoy-proxy-tracer-configuration" class="level3">
<h3 class="anchored" data-anchor-id="envoy-proxy-tracer-configuration">Envoy proxy tracer configuration</h3>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode yaml code-with-copy"><code class="sourceCode yaml"><span id="cb7-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">-</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">name</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> envoy.filters.network.http_connection_manager</span></span>
<span id="cb7-2"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">  </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">typed_config</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb7-3"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">"@type"</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager</span></span>
<span id="cb7-4"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">codec_type</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> AUTO</span></span>
<span id="cb7-5"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">stat_prefix</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> ingress_http</span></span>
<span id="cb7-6"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">generate_request_id</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">true</span></span>
<span id="cb7-7"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">    </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">tracing</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb7-8"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">      </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">provider</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb7-9"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">name</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> envoy.tracers.opentelemetry</span></span>
<span id="cb7-10"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">        </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">typed_config</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb7-11"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">          </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">"@type"</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> type.googleapis.com/envoy.config.trace.v3.OpenTelemetryConfig</span></span>
<span id="cb7-12"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">          </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">grpc_service</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb7-13"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">            </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">envoy_grpc</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span></span>
<span id="cb7-14"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">              </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cluster_name</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> jaeger</span></span>
<span id="cb7-15"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">            </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">timeout</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> 1s</span></span>
<span id="cb7-16"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">          </span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">service_name</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">:</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;"> proxy</span></span></code></pre></div></div>
</section>
<section id="publishing-telemetry-data-from-external-authorization-service" class="level3">
<h3 class="anchored" data-anchor-id="publishing-telemetry-data-from-external-authorization-service">Publishing telemetry data from external authorization service</h3>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode go code-with-copy"><code class="sourceCode go"><span id="cb8-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">func</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>authServer <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>AuthServer<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> Check<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>ctx context<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Context<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> request <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>auth<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>CheckRequest<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(*</span>auth<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>CheckResponse<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">error</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb8-2">    tracer <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:=</span> otel<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Tracer<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ext-authz"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb8-3">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// create span</span></span>
<span id="cb8-4">    _<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> span <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:=</span> tracer<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Start<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>ctx<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ext-authz-span"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb8-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">defer</span> span<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>End<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">()</span></span>
<span id="cb8-6">    log<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Printf<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Auth server received auth request: %v"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> request<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>String<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">())</span></span>
<span id="cb8-7">    authHeader<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> ok <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:=</span> request<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Attributes<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Request<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Http<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Headers<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">[</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"authorization"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">]</span></span>
<span id="cb8-8">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> tokenString <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">string</span></span>
<span id="cb8-9"></span>
<span id="cb8-10">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> ok <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb8-11">        tokenString <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> strings<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>TrimPrefix<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>authHeader<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Bearer "</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb8-12">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb8-13">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// set attributes to span</span></span>
<span id="cb8-14">    span<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>SetAttributes<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span></span>
<span id="cb8-15">        attribute<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>String<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"example-key"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"example-value"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">),</span></span>
<span id="cb8-16">        attribute<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>String<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"guid:x-request-id"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> request<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Attributes<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Request<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Http<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Headers<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">[</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"x-request-id"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">]),</span></span>
<span id="cb8-17">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb8-18">    fmt<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Printf<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Token: %s"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> tokenString<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb8-19">    _<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> err <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:=</span> jwt<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Parse<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>tokenString<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">func</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>token <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>jwt<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Token<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">interface</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{},</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">error</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb8-20">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> _<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> ok <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:=</span> token<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Method<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.(*</span>jwt<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>SigningMethodHMAC<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">);</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>ok <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb8-21">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">nil</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> fmt<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Errorf<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"unexpected signing method: %v"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> token<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Header<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">[</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"alg"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">])</span></span>
<span id="cb8-22">        <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb8-23">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> secretKey<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">nil</span></span>
<span id="cb8-24">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">})</span></span>
<span id="cb8-25">    fmt<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Printf<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Error: %v"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> err<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">)</span></span>
<span id="cb8-26">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Span end</span></span>
<span id="cb8-27">    span<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>End<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">()</span></span>
<span id="cb8-28">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> err <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">nil</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb8-29">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span>auth<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>CheckResponse<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb8-30">            Status<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span>status<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Status<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb8-31">                Code<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">int32</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>code<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Code_OK<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">),</span></span>
<span id="cb8-32">                Message<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AuthServer authentication successful"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb8-33">            <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">},</span></span>
<span id="cb8-34">        <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">},</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">nil</span></span>
<span id="cb8-35">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb8-36">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span>auth<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>CheckResponse<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb8-37">        Status<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;</span>status<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Status<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb8-38">            Code<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">int32</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">(</span>code<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>Code_PERMISSION_DENIED<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">),</span></span>
<span id="cb8-39">            Message<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"AuthServer authentication unsuccessful"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb8-40">        <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">},</span></span>
<span id="cb8-41">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">},</span> <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">nil</span> </span>
<span id="cb8-42"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span></span></code></pre></div></div>
</section>
</section>
<section id="summary" class="level2">
<h2 class="anchored" data-anchor-id="summary">Summary</h2>
<p>This article mainly focuses on the application-level security and scalability of the API layer. We achieve application-level security using the External Authorization Service, which deals with identity verification and authorization, and the External Rate Limit Service, which ensures the availability of upstream services by performing the configured rate limits.</p>
<p>Scalability can be achieved by scaling the necessary components based on requirements. It’s recommended to identify the bottleneck and scale the components accordingly. For example, if the rate limit service is causing a bottleneck in request processing and adding high latency, the external rate limit service can be scaled independently without scaling other components.</p>
<p>This kind of API layer helps application developers focus on writing business logic in their microservices without worrying about security and scalability.</p>
<p><strong>Complete source code for the above setup with a docker-compose deployment:</strong> <a href="https://github.com/NomadXD/samples/tree/main/secure-scalable-api-layer">secure-scalable-api-layer</a></p>


</section>

 ]]></description>
  <category>Envoy</category>
  <category>API</category>
  <category>Security</category>
  <guid>https://lahirudesilva.com/posts/building-secure-scalable-api-layer/</guid>
  <pubDate>Wed, 12 Apr 2023 00:00:00 GMT</pubDate>
  <media:content url="https://lahirudesilva.com/posts/building-secure-scalable-api-layer/secure-scalable-cover.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>A Beginner’s Guide to gRPC and protobuf</title>
  <dc:creator>Lahiru De Silva</dc:creator>
  <link>https://lahirudesilva.com/posts/grpc-protobuf/</link>
  <description><![CDATA[ 






<p>Since both protocol buffers and gRPC framework are developed internally at Google and then open sourced, let’s first see what google says about them.</p>
<section id="protocol-buffers" class="level3">
<h3 class="anchored" data-anchor-id="protocol-buffers">Protocol buffers</h3>
<blockquote class="blockquote">
<p>Protocol buffers are Google’s language-neutral, platform-neutral, <strong>extensible mechanism for serializing structured data</strong> – think XML, but smaller, faster, and simpler. You define how you want your data to be structured once, then you can use special generated source code to easily write and read your structured data to and from a variety of data streams and using a variety of languages.</p>
</blockquote>
<p>So the highlighted text defines exactly what protobufs do. But what is data serialization ? Data serialization is the process of converting some in-memory object to another format that could be used to either store in a file or sent over the network. In layman terms, protocol buffers convert application level data objects to binary data that can be stored or transmitted over the wire. So this is where gRPC comes to play. gRPC deals with the process of transmitting the binary data generated from protocol buffers. Let’s see what google says about gRPC.</p>
</section>
<section id="grpc" class="level3">
<h3 class="anchored" data-anchor-id="grpc">gRPC</h3>
<blockquote class="blockquote">
<p>gRPC is a modern open source <strong>high performance RPC framework</strong> that can run in any environment. It can efficiently connect services in and across data centers with pluggable support for load balancing, tracing, health checking and authentication.</p>
</blockquote>
<p>So from the above definition, it is clear that gRPC is a RPC framework which has several improvements over traditional RPC frameworks. If you don’t know what a RPC framework is, simply it’s a set of tools that enable the programmer to call a piece of code in a remote process, be it on a different machine or just another process on the same machine.</p>
</section>
<section id="developer-workflow" class="level2">
<h2 class="anchored" data-anchor-id="developer-workflow">Developer workflow</h2>
<ol type="1">
<li><p>Create a <code>.proto</code> file and define the message types and services that we want to work with.A message is analogous to a request/response in the REST world. We have to define messages by using the in-built <a href="https://developers.google.com/protocol-buffers/docs/proto3#simple">data types</a>. And then we have to define services. In gRPC there are 4 types of services that we can use.</p>
<ul>
<li>gRPC unary</li>
<li>gRPC client streaming</li>
<li>gRPC server streaming</li>
<li>gRPC bi-directional streaming</li>
</ul>
<p>Since this is an introductory article, I am not going to explain about them further.</p></li>
<li><p>Then we have to use the <code>protoc</code> compiler and compile the <code>.proto</code> file that we created in the previous step. For this step, you have to install the protoc compiler. Follow the official installation guide for protoc compiler installation.</p></li>
<li><p>After compiling the proto file in the previous step, proto generated files will be there in a location that you specified. For example in <code>C++</code>, two files will be generated with file extensions <code>.pb.h</code> and <code>.pb.cc</code>. In <code>golang</code> it will be a single file with <code>.pb.go</code>. Other programming languages that support protocol buffers will generate one or more files with different file extensions based on the language. These files contain methods that can be used to create messages, send and receive messages etc.</p></li>
<li><p>As the final step, the generated files can be imported from the application source files and the relevant methods can be used to build, send and receive messages.</p></li>
</ol>
<p>Since this is an introductory article, I’m not going to add an example here. I hope to publish separate articles for the different types of gRPC services with examples.</p>
</section>
<section id="grpc-vs-rest" class="level2">
<h2 class="anchored" data-anchor-id="grpc-vs-rest">gRPC vs REST</h2>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/grpc-protobuf/grpc-vs-rest.png" class="img-fluid figure-img"></p>
<figcaption>gRPC vs REST</figcaption>
</figure>
</div>
<p>Now, let’s do a quick comparison of gRPC and REST to see their differences.</p>
<ol type="1">
<li>gRPC uses HTTP/2 which is, as you know, much faster than HTTP/1.1 used in REST by default. Note that today we can enable HTTP/2 in REST as well, but normally it often goes with HTTP/1.1. Binary framing, compression and multiplexing capabilities of HTTP/2 improves the performance of gRPC significantly when compared to REST with HTTP/1.x.</li>
<li>gRPC uses Protocol buffer to serialize payload data, which is binary and smaller, while REST uses JSON, which is text and larger.
<ul>
<li>One of the common questions that arises when you learn about binary serialization of protocol buffers is that <strong>“does it matter when everything that is transferred through the wire is binary ?”</strong> In trying to answear that question, let’s see how text based serializers work. A text based serializer, serialize everything as text to make it more human readable. This process will add several symbols to make it more clean and human readable which adds more bytes.Since at the bytes level, a string values usually takes more space than other data types,compared to binary serializers, text based serializers generates more bytes. So a text based serializer will first serialize application data objects into a text and then the bytes relevant to that text is transferred through the wire. In contrast to text based serializers, binary serializers serialize application data objects to binary data which lives more closer to the hardware. For example let’s consider the integer 42.</li>
</ul></li>
</ol>
<ul>
<li><pre><code>json - {"id":42} - 9 bytes if we assume ASCII or UTF-8 encoding and no whitespace.</code></pre></li>
<li><pre><code>xml - &lt;id&gt;42&lt;/id&gt; - 11 bytes if we assume ASCII or UTF-8 encoding and no whitespace - and no namespace noise like namespaces.</code></pre></li>
<li><pre><code>protobuf - 0x08 0x2a - 2 bytes</code></pre>
Due to small payloads, fast and efficient serialization in protocol buffers, gRPC performs better than REST with HTTP/1.x in most of the scenarios. But at the same time binary serialization makes it more difficult to work with/debug a gRPC API than a REST based API.</li>
</ul>
<ol start="3" type="1">
<li>The API contract in gRPC is strict, and required to be clearly defined in the proto file. While in REST, it’s often loose and optional. We can define it via OpenAPI if we want, but it’s not mandatory. Having a strict contract makes it easy for the developers to develop and maintain the API when several teams are involved in the process. However for simple APIs, gRPC can consume extra unnecessary time and effort. Also protobuf field numbers can be used to evolve the API with versions while making the API backward compatible.</li>
<li>Code generation is built-in in gRPC with the help of protocol buffer compiler. While in REST, we must use third-party tools like OpenAPI and Swagger. gRPC support is not available in all of the programming languages. gRPC is currently <a href="https://grpc.io/docs/languages/">officially</a> supported in most of the widely used programming languages and there are several other community based implementations.</li>
<li>gRPC APIs are not strictly resource/entity oriented although they can be defined in a resource/entity oriented way. In contrast REST APIs are mostly entity/resource oriented and must be resource/entity oriented if it is defined as a RESTful API. Resource/entity orientedness of REST APIs can be a performance bottleneck when several resources are needed to perform a certain operation since a HTTP call is required per operation per resource. <em>(Only if the API is resource/entity oriented)</em>. For example if resource B is needed to be updated after creation of resource A, then a POST request is required for resource A and a PUT request is required for resource B. We can implement both of those under one gRPC service since gRPC is not strictly resource/entity oriented.</li>
<li>With the HTTP/2 streams, gRPC has better support for streaming than the HTTP/1.x. With HTTP/1.x server streaming can be achieved using server sent events (SSE) or by maintaining a persistent connection by specifying <code>Transfer Encoding: chunked</code> in the response header. Compared to that, gRPC offers better support for streaming by providing client streaming, server streaming and bi-directional streaming out of the box.</li>
</ol>
</section>
<section id="when-to-use-grpc" class="level2">
<h2 class="anchored" data-anchor-id="when-to-use-grpc">When to use gRPC</h2>
<p>From the previous section it is pretty obvious that gRPC has a lot of new features and strengths when compared to HTTP/1.1x based REST APIs. However with the current state of gRPC, browser support is not yet available. It’s impossible to directly call a gRPC service from a browser today. gRPC heavily uses HTTP/2 features and no browser provides the level of control required over web requests to support a gRPC client. For example, browsers do not allow a caller to require that HTTP/2 be used, or provide access to underlying HTTP/2 frames. To overcome this issue, <a href="https://grpc.io/blog/state-of-grpc-web/">grpc-web</a> was introduced but not all grpc features are supported in grpc-web. The basic idea of grpc-web is to have the browser send normal HTTP requests (with Fetch or XHR) and have a small proxy in front of the gRPC server to translate the requests and responses to something the browser can use. Due to this limitation , grpc is mostly used for internal service to service communication.</p>
<p>gRPC is well suited to the following scenarios.</p>
<ul>
<li><strong>Microservices</strong>: gRPC is designed for low latency and high throughput communication. gRPC is great for lightweight microservices where efficiency is critical.</li>
<li><strong>Point-to-point real-time communication</strong>: gRPC has excellent support for bi-directional streaming. gRPC services can push messages in real-time without polling.</li>
<li><strong>Polyglot environments</strong>: gRPC tooling supports all popular development languages, making gRPC a good choice for multi-language environments.</li>
<li><strong>Network constrained environments</strong>: gRPC messages are serialized with Protobuf, a lightweight message format. A gRPC message is always smaller than an equivalent JSON message.</li>
<li><strong>Inter-process communication (IPC)</strong>: IPC transports such as Unix domain sockets and named pipes can be used with gRPC to communicate between apps on the same machine. For more information, see Inter-process communication with gRPC.</li>
</ul>
</section>
<section id="references" class="level2">
<h2 class="anchored" data-anchor-id="references">References</h2>
<ul>
<li><a href="https://cloud.google.com/blog/products/api-management/understanding-grpc-openapi-and-rest-and-when-to-use-them">gRPC vs REST: Understanding gRPC, OpenAPI and REST and when to use them in API design</a></li>
<li><a href="https://cloud.google.com/blog/products/application-development/rest-vs-rpc-what-problems-are-you-trying-to-solve-with-your-apis">REST vs RPC: What problems are you trying to solve with your APIs?</a></li>
<li><a href="https://www.pubnub.com/learn/glossary/what-is-http-streaming/">What is HTTP Streaming?</a></li>
<li><a href="https://grpc.io/blog/state-of-grpc-web/">The state of gRPC in the browser</a></li>
<li><a href="https://docs.microsoft.com/en-us/aspnet/core/grpc/comparison?view=aspnetcore-5.0">Compare gRPC services with HTTP APIs</a></li>
</ul>


</section>

 ]]></description>
  <category>gRPC</category>
  <category>Protobuf</category>
  <guid>https://lahirudesilva.com/posts/grpc-protobuf/</guid>
  <pubDate>Sat, 25 Feb 2023 00:00:00 GMT</pubDate>
  <media:content url="https://lahirudesilva.com/posts/grpc-protobuf/welcome.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>How we implemented an authorization cache for Envoy proxy</title>
  <dc:creator>Lahiru De Silva</dc:creator>
  <link>https://lahirudesilva.com/posts/how-we-implemented-authorization-cache-envoy-proxy/</link>
  <description><![CDATA[ 






<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>This article was originally published on <a href="https://developers.redhat.com/">Red Hat Developer Blogs</a> and co-authored by Rahul Anand and Lahiru De Silva (myself). Read the original article here: <a href="https://developers.redhat.com/articles/2021/11/25/how-we-implemented-authorization-cache-envoy-proxy">Original Article on Red Hat Developer Blogs</a></p>
</div>
</div>
<p>This is the second article in a two-part series about an authorization cache we developed for the Envoy open source proxy as a part of <a href="https://summerofcode.withgoogle.com/archive/2021/projects/6205479449001984">Google Summer of Code 2021</a>. The <a href="http://nomadxd.github.io/blog/design-authorization-cache-envoy-proxy-using-webassembly">first article</a> in the series showed the design of our cache, based on <a href="https://github.com/proxy-wasm/">Proxy-Wasm</a> and integrated with <a href="https://developers.redhat.com/products/3scale/overview">Red Hat 3scale API Management</a>. In this part, we focus on the implementation aspect of the design described in the previous article (check it out if you haven’t already).</p>
<section id="proxy-wasm-extensions" class="level2">
<h2 class="anchored" data-anchor-id="proxy-wasm-extensions">Proxy-Wasm extensions</h2>
<p>As mentioned in the first part of the series, at this time of writing Proxy-Wasm supports two main types of extensions: filters and singleton services. A filter executes in a worker thread and a singleton service executes in the main thread.</p>
<p>The Proxy-Wasm specification currently defines two types of filters: network filters and HTTP filters. There are also three types of contexts:</p>
<ul>
<li><code>RootContext</code>: This context takes care of such tasks as reading the virtual machine (VM) configuration, reading plugin configurations, setting tick periods, creating contexts, and any work outside the request lifecycle. One <code>RootContext</code> gets created for each thread in each plugin.</li>
<li><code>StreamContext</code>: This context is used when writing network filters. One <code>StreamContext</code> gets created for each request.</li>
<li><code>HTTPContext</code>: This context is used when writing HTTP filters. One <code>HTTPContext</code> gets created for each request.</li>
</ul>
<p>Our design uses a singleton service and an HTTP filter. So our implementation uses only a <code>RootContext</code> and an <code>HTTPContext</code>.</p>
</section>
<section id="cache-filter" class="level2">
<h2 class="anchored" data-anchor-id="cache-filter">Cache filter</h2>
<p>A filter object has the same lifecycle as a request. Therefore, to reduce request latency, our implementation shifts any task that can tolerate a delay to the singleton service. The filter does only the bare minimum work required. As mentioned in the first part of the series, there are two main flows for the filter:</p>
<ul>
<li><p><strong>Cache miss:</strong> Whenever a cache record is not present in the shared data, the filter proceeds with this path. Because the task is to authorize an HTTP request, the service ID and application ID are combined into a string into the format <code>{ServiceID}_{AppID}</code> to create the key in the cache. The filter calls out to the 3scale Service Management API to obtain the latest application state. Following the call-out response, the fetched state is stored as the cache entry value after deserialization, and future requests for the same service and application benefit from cache hits.</p></li>
<li><p><strong>Cache hit:</strong> If a cache entry is present, its serialized string value is fetched and deserialized into Rust structs. The decision to authorize the request is based on the left quota for each method and metric, which are already configured on the 3scale API Management dashboard. If authorized, the request is allowed to proceed to the next filter in the filter chain, and if not, a local response from the cache filter is sent back with appropriate response headers.</p></li>
</ul>
<p>If any anomaly is found during the processing of the request, such as crucial missing information, a failure to serialize or deserialize the application state, or a processing failure by the host proxy, appropriate status codes are sent back.</p>
<p>Figure 1 shows how we map the XML entities in the authorization response to Rust variables and structs.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/how-we-implemented-authorization-cache-envoy-proxy/map.webp" class="img-fluid figure-img"></p>
<figcaption>Relationships between XML entities in the authorization response and Rust variables</figcaption>
</figure>
</div>
<p><em>Figure 1: Relationships between XML entities in the authorization response and Rust variables</em></p>
</section>
<section id="singleton-service" class="level2">
<h2 class="anchored" data-anchor-id="singleton-service">Singleton service</h2>
<p>The singleton service is responsible for two major functions: flushing the cache and updating the cache. These support the metrics we report on the use of different resources based on endpoints, URLs, etc.</p>
<p>Without the cache, all the request metrics are sent to 3scale API Management’s Software-as-a-Service (SaaS) platform using the <code>authrep.xml</code> endpoint. The rapid updating of metrics allows users to see usage in almost real-time and hence with higher accuracy of reported metrics and higher latencies of the request being served. By design, if the cache is used, metrics are shown a bit later than the real-time request being served because of batching.</p>
<p>Our cache project eliminates the HTTP calls from the proxy to an external service on each request received. Instead, we rely on the stored cache records inside the proxy to minimize request processing time. To support the reporting of request usage and other related information to an external management service, we aggregate request usage over a particular time duration or based on a memory limit and then send bulk HTTP requests to the management service using the <code>report.xml</code> endpoint.</p>
<p>The local cache is flushed to an external service on a periodic basis or based on a predefined policy. Because we are using a singleton service, this cache flushing process runs in the main thread as a background task without blocking the worker threads.</p>
<p>The singleton service also updates the local cache with new snapshots of the applications and services. After flushing the local cache based on a configured policy, the local cache update process gets initiated. This process fetches the latest state of an application using the <code>authorize.xml</code> endpoint and updates the cache record stored inside the proxy with that latest data.</p>
</section>
<section id="integration-of-cache-with-singleton" class="level2">
<h2 class="anchored" data-anchor-id="integration-of-cache-with-singleton">Integration of cache with singleton</h2>
<p>The first part of this series mentioned that the cache filter sends events to the singleton service via a message queue. Let’s discuss that queue in more detail.</p>
<p>Our implementation uses the shared queue feature in the Proxy-Wasm ABI. The shared queue is one of the most under-represented features of Proxy-Wasm. Still, it can be used for more complex applications such as sharing data between worker threads, cross-VM communication, etc. In our case, we use it to transfer request metadata from the cache filter to the singleton service.</p>
<p>A shared queue supports basic enqueue and dequeue operations, as well as a callback that notifies the recipient whenever data is available in the queue. We effectively used this callback mechanism to implement an event-passing system between the filter and the singleton, so the singleton service doesn’t have to check the shared queue for messages.</p>
</section>
<section id="testing" class="level2">
<h2 class="anchored" data-anchor-id="testing">Testing</h2>
<p>For a project with several interconnected components, integration tests and end-to-end tests are essential to verify the functionality of the features and ensure that new development does not break previously implemented functionality. So we invested time and effort to develop a complete end-to-end testing framework that runs all the tests in a Docker Compose setup with all the required services running in Docker containers.</p>
<p>The integration testing framework has the following key features:</p>
<ul>
<li>Using everything as we use in a real production environment without mocking</li>
<li>Flexibility to start new proxy instances per each test or per each test suite</li>
<li>Generating an Envoy configuration from a common template</li>
</ul>
</section>
<section id="additional-cache-features" class="level2">
<h2 class="anchored" data-anchor-id="additional-cache-features">Additional cache features</h2>
<p>Some of the other neat capabilities of our cache include:</p>
<ul>
<li><strong>Custom metrics:</strong> One of the primary goals of the Envoy proxy is to make the network understandable. Envoy can emit a large number of statistics, depending on how it is configured. We made use of Envoy’s metrics API to define custom metrics that are more related to business logic. For example, we defined custom metrics to record the total number of applications stored in the cache, total Authorize calls to the 3scale Service Management API, total timeouts for the Authorize calls, etc. The metrics defined here can be scraped by Prometheus and visualized with a Grafana dashboard.</li>
<li><strong>Unique call-out:</strong> The unique call-out feature ensures that, for a single record, there is only one call-out to the 3scale Service Management API. Because there is no synchronization mechanism between worker threads, we created an <a href="https://github.com/envoyproxy/envoy/issues/17576">issue</a> in the upstream envoy proxy project to request a solution for this use case. But because any change in the ABI will take more time than we had at Google Summer of Code, we found a way to use shared data as a placeholder for the lock and message queues to signify the resumption of waiting contexts between different threads. This use required us to bend the expected use of <code>set_shared_data</code> by sending some non-zero CAS value to avoid the initialization of the entry by multiple threads. There is still a nearly infinitesimal chance of multiple initializations, but their eventual correction is assured.</li>
<li><strong>Visible logs:</strong> Writing unit tests for Proxy-Wasm modules was not reasonable because it requires a runtime that is available during only integration, and at that stage, we cannot check individual functions. So we decided to blur the line between unit and integration tests by developing a feature called visible logs. If enabled, trace logs are sent in the response header, which is later matched against regular expressions to see whether the expected strings appear and thus verify the function’s inner workings as unit tests do. This feature was implemented by intercepting and storing the logs for each request and dumping them into a response header when the response is ready.</li>
</ul>
</section>
<section id="benchmarks" class="level2">
<h2 class="anchored" data-anchor-id="benchmarks">Benchmarks</h2>
<p>Performing reliable and accurate benchmarks is crucial for our project because the main goal of the project is to improve the performance of request latency. So we performed extensive benchmarks for different traffic profiles and configurations. Results clearly show that the proxy with our internal cache outperformed the proxy without the cache. Figure 2 shows results from the proxy without the internal cache, while Figure 3 shows the proxy with our cache.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/how-we-implemented-authorization-cache-envoy-proxy/without.webp" class="img-fluid figure-img"></p>
<figcaption>Response times are noticeably high without the cache</figcaption>
</figure>
</div>
<p><em>Figure 2: Response times are noticeably high without the cache</em></p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/how-we-implemented-authorization-cache-envoy-proxy/with.webp" class="img-fluid figure-img"></p>
<figcaption>Response times stay low with the cache in place</figcaption>
</figure>
</div>
<p><em>Figure 3: Response times stay low with the cache in place</em></p>
<p>Also, we can see the transition from cache miss to cache hit in the request latency diagram of the proxy, where it is marked by a sudden drop in the maximum latency curve.</p>
<p>Apart from benchmarking request latencies, we also benchmarked the unique call-out feature to prove that it improves performance during the initial cache miss stage by preventing multiple HTTP calls. Figure 4 compares request latencies for the setup with and without unique call-outs.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/how-we-implemented-authorization-cache-envoy-proxy/unique.webp" class="img-fluid figure-img"></p>
<figcaption>Latencies are improved by the unique call-outs feature</figcaption>
</figure>
</div>
<p><em>Figure 4: Latencies are improved by the unique call-outs feature</em></p>
<p>The blue and red lines represent two loads without enabling unique callout, and the rest of them are with unique callout enabled. It shows 99% of the request latencies are similar for both of the setups, but the setup with unique call-outs outperforms the default proxy setup during the initial cache miss period. (The final 1% of the diagram denotes the high latency requests during the initial cache miss period.)</p>
<p>All our benchmark results can be found in the <a href="https://github.com/3scale-labs/gsoc-wasm-filters/tree/main/benchmark">3scale-labs repository</a>.</p>
</section>
<section id="limitations-and-planned-improvements" class="level2">
<h2 class="anchored" data-anchor-id="limitations-and-planned-improvements">Limitations and planned improvements</h2>
<p>For the most part, our modules do what they are supposed to do But some limitations exist and we can see areas for improvement. Here is a non-exhaustive list:</p>
<ul>
<li>Under the hood, the cache is just a C++ hashmap. Any problems hashmaps produce at scale are present in our cache as well. One way to improve this scaling problem is to run a dedicated database process such as Redis run alongside the envoy process. However, the dedicated process would also marginally reduce the savings in latency.</li>
<li>Proxy-Wasm’s host implementation uses mutexes per access type (read/write) for concurrency control on the cache, which means that at most one write and one read can have concurrent access to the cache. To improve parallelism, we can define an atomic operation on each entry (slightly increasing memory use). If we made this change, multiple threads would be able to access different entries concurrently, whereas now only one thread at a time has access to one entry.</li>
<li>With the current implementation, the singleton service can be configured to operate in three modes: container, periodic, and default. These modes define how the cache’s flush and update operations are performed. However, these simple configurations don’t allow the developer to define the behavior of individual stages in the cache flush/update process. The singleton service can be made more intelligent and fault-tolerant by implementing a policy-based system for cache flushes and updates.</li>
<li>To overcome the issues and constraints imposed by Wasm, Proxy-Wasm, and Envoy, we could implement an external service extension based on a local remote procedure call (RPC) mechanism.</li>
<li>As of right now, there is no ability to delete an entry fully in the cache due to limitations in the ABI. But this will be fixed soon in the next ABI update by the maintainers.</li>
</ul>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>We worked hard during the Google Summer of Code to get this project where it is today. The cache will hopefully be in production during the next release cycle of <a href="https://www.redhat.com/en/technologies/cloud-computing/openshift/what-is-openshift-service-mesh">Red Hat OpenShift Service Mesh</a>. But without the help of the great 3scale API Management team, especially our mentor Alejandro Martinez Ruiz, it wouldn’t have been possible for us to complete this project and then write an article about it. We would also like to thank Andrew Mackenzie for his support and rigorous reviews of this series.</p>
<p>Finally, we highly encourage students to consider applying to Google Summer of Code, because it changed our lives and careers for the better and can help others too.</p>


</section>

 ]]></description>
  <category>Envoy</category>
  <category>WebAssembly</category>
  <category>Security</category>
  <guid>https://lahirudesilva.com/posts/how-we-implemented-authorization-cache-envoy-proxy/</guid>
  <pubDate>Thu, 25 Nov 2021 00:00:00 GMT</pubDate>
  <media:content url="https://lahirudesilva.com/posts/how-we-implemented-authorization-cache-envoy-proxy/implement-authz-cache.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Design an authorization cache for Envoy proxy using WebAssembly</title>
  <dc:creator>Lahiru De Silva</dc:creator>
  <link>https://lahirudesilva.com/posts/design-authorization-cache-envoy-proxy-using-webassembly/</link>
  <description><![CDATA[ 






<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>This article was originally published on <a href="https://developers.redhat.com/">Red Hat Developer Blogs</a> and co-authored by Rahul Anand and Lahiru De Silva (myself). Read the original article here: <a href="https://developers.redhat.com/articles/2021/11/18/design-authorization-cache-envoy-proxy-using-webassembly">Original Article on Red Hat Developer Blogs</a></p>
</div>
</div>
<p>This article introduces a high-level design to implement an authorization cache associated with the Envoy proxy using WebAssembly. The goal of this project is to reduce the latencies of HTTP requests passing through the Envoy proxy by reducing the traffic to the service responsible for authentication and authorization of requests. The cache stores data about authorization so that the external service needs to be contacted only on cache misses, instead of for every HTTP request.</p>
<p>We also provide the source code of an authorization cache that interacts with <a href="https://developers.redhat.com/products/3scale/overview">Red Hat 3scale API Management</a>. The cache was implemented as a part of the <a href="https://summerofcode.withgoogle.com/archive/2021/projects/6205479449001984">Google Summer of Code 2021 project</a>.</p>
<p>This article is the first in a two-part series. This first article introduces a high-level, generic design that will give you a basic idea of the cache’s overall functionality. The second part explains the major design decisions and implementation details.</p>
<section id="what-is-envoy-proxy" class="level2">
<h2 class="anchored" data-anchor-id="what-is-envoy-proxy">What is Envoy proxy?</h2>
<p><a href="https://www.envoyproxy.io/">Envoy</a> is an <a href="https://developers.redhat.com/topics/open-source-communities">open source</a> <a href="https://developers.redhat.com/topics/edge-computing">edge</a> and service proxy for applications running in the cloud. Envoy is valuable for many use cases, including edge proxy, middle proxy, sidecar for service mesh deployments, and a daemon set within <a href="https://developers.redhat.com/topics/kubernetes">Kubernetes</a>. Among Envoy’s compelling features, performance, extensibility, and <a href="https://developers.redhat.com/topics/api-management">API configurability</a> are the most prominent, making it unique in the proxy space. This article mainly focuses on extensibility.</p>
</section>
<section id="the-envoy-proxy-authorization-cache-in-action" class="level2">
<h2 class="anchored" data-anchor-id="the-envoy-proxy-authorization-cache-in-action">The Envoy proxy authorization cache in action</h2>
<p>The implementation uses <a href="https://github.com/proxy-wasm/">Proxy-Wasm</a>, implementing the extensions as WebAssembly modules. We made this choice based on the flexibility, portability, maintainability, and isolation (for fault tolerance) that WebAssembly offers when compared with native Envoy filters. At the time of writing this article, Proxy-Wasm supports two types of extensions: Filters and singleton services.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/design-authorization-cache-envoy-proxy-using-webassembly/overview.webp" class="img-fluid figure-img"></p>
<figcaption>Envoy communicates through the Wasm virtual machines with the 3scale Service Management API</figcaption>
</figure>
</div>
<p><em>Figure 1: Envoy communicates through the Wasm virtual machines with the 3scale Service Management API</em></p>
<p>Figure 1 shows the interactions between the proxy, the 3scale Service Management API, and the upstream services when a client sends a request. The request is propagated through the Envoy filter chain. For access to Wasm filters and services, the request interacts with the Wasm Virtual machine (VM) to execute the Wasm plugins.</p>
</section>
<section id="designing-the-authorization-cache" class="level2">
<h2 class="anchored" data-anchor-id="designing-the-authorization-cache">Designing the authorization cache</h2>
<p>In our design, the cache inside the proxy is implemented through two main components: A filter and a singleton service.</p>
<p>The filter is responsible for intercepting HTTP requests, authorizing them based on the stored cache, and performing rate limiting. In the context of the envoy, this component is an HTTP filter and gets executed in the worker threads. For each request, a context object gets created.</p>
<p>The singleton service is responsible for the background synchronization of cached data between the proxy and the 3scale Service Management API. In the context of the envoy, this is a singleton service and gets executed in the main thread outside the request lifecycle. Only one instance of this service gets instantiated in each Envoy process.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/design-authorization-cache-envoy-proxy-using-webassembly/overall.webp" class="img-fluid figure-img"></p>
<figcaption>The filter’s threads and the singleton service share data and a message queue</figcaption>
</figure>
</div>
<p><em>Figure 2: The filter’s threads and the singleton service share data and a message queue</em></p>
<p>Figure 2 shows how the HTTP filter and singleton service interact with the other internal and external components to provide the expected functionality of the in-proxy cache. Shared data is an in-memory key-value store specified by the Proxy-Wasm ABI and provided by the proxy. Each VM contains a shared datastore. Because the two extensions (filter and singleton) are running in the same Wasm VM, both extensions have direct access to the shared data.</p>
<p>I/O between the host and VM is done in binary format and thus requires serialization and deserialization. The Proxy-Wasm ABI provides a shared queue that is also unique per VM. In our design, the shared queue is the main communication channel between the singleton service and filter. Any message enqueued is broadcast to all threads, but only one thread can dequeue the message. The singleton service updates the cache records saved in the shared data, either periodically or based on policies defined in the configuration. The HTTP filter uses the cache records in the shared data to perform authorization and rate-limiting.</p>
<section id="filter-design" class="level3">
<h3 class="anchored" data-anchor-id="filter-design">Filter design</h3>
<p>The default Envoy proxy makes an external HTTP call to the 3scale Service Management API for every HTTP request to perform authorization and reporting. But with the internal cache, we eliminate this need and limit the external HTTP calls to cache misses (Figure 3). That way, we reduce the traffic on the 3scale Service Management API and therefore overall request latency, to a great extent.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://lahirudesilva.com/posts/design-authorization-cache-envoy-proxy-using-webassembly/filter.webp" class="img-fluid figure-img"></p>
<figcaption>Envoy proxy filter chain with and without cache filter</figcaption>
</figure>
</div>
<p><em>Figure 3: Envoy proxy filter chain with and without cache filter</em></p>
<p>The filter serves as the entry point for the request authorization with the help of cached data. The filter takes one of two pathways for each request:</p>
<ul>
<li><strong>Cache miss</strong>: This happens when a cache record is not found in the shared data. The filter calls out to the 3scale Service Management API to fetch the latest state.</li>
<li><strong>Cache hit</strong>: This happens when a cache record is present. Based on authorization results, metrics are passed to the singleton for reporting to the 3scale Service Management API.</li>
</ul>
<p>The filter is equipped with an opt-in feature called unique-callout, which ensures that there is only one callout to the 3scale Service Management API on a cache miss. This feature increases performance and accuracy under high load, without any impact under low-load conditions. We’ll look at the results with and without the unique callout feature in the second part of this series, when we get to examine the benchmarks.</p>
</section>
<section id="singleton-design" class="level3">
<h3 class="anchored" data-anchor-id="singleton-design">Singleton design</h3>
<p>The singleton service serves two main functions for the proposed in-proxy cache design:</p>
<ul>
<li>Collect metrics based on a predefined policy and report them to the external management service.</li>
<li>Update the local cache stored in the proxy by pulling the latest states of applications and services from the external management service.</li>
</ul>
<p>In our case, the external management service is the 3scale Service Management API.</p>
<p>In Envoy, almost all the functions in worker threads and the main thread get executed in a non-blocking manner. So the methods get invoked as callbacks. In the singleton service, we use two types of events to perform the required functionality:</p>
<ul>
<li>Periodic events, triggered at predefined intervals via the <code>on_tick()</code> callback</li>
<li>Events triggered by the filter through the message queue</li>
</ul>
<p>Events that are sent from the filter pass through the message queue to the singleton service. The second part of this article offers further details about the integration of cache with the singleton section.</p>
</section>
</section>
<section id="coming-up-implementing-the-cache" class="level2">
<h2 class="anchored" data-anchor-id="coming-up-implementing-the-cache">Coming up: Implementing the cache</h2>
<p>In the next part of this series, we’ll dive into the implementation details of the cache, data modeling, various features that made the cache work better, limitations, and planned improvements.</p>
<p><strong>Next article in the series:</strong> <a href="http://nomadxd.github.io/blog/how-we-implemented-authorization-cache-envoy-proxy">How we implemented an authorization cache for Envoy proxy</a></p>


</section>

 ]]></description>
  <category>Envoy</category>
  <category>WebAssembly</category>
  <category>Security</category>
  <guid>https://lahirudesilva.com/posts/design-authorization-cache-envoy-proxy-using-webassembly/</guid>
  <pubDate>Thu, 18 Nov 2021 00:00:00 GMT</pubDate>
  <media:content url="https://lahirudesilva.com/posts/design-authorization-cache-envoy-proxy-using-webassembly/design-authz-cache.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Our journey to open source during Google Summer of Code</title>
  <dc:creator>Lahiru De Silva</dc:creator>
  <link>https://lahirudesilva.com/posts/gsoc-opensource-redhat/</link>
  <description><![CDATA[ 






<div class="callout callout-style-default callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
Note
</div>
</div>
<div class="callout-body-container callout-body">
<p>This article was originally published on <a href="https://opensource.com/">Opensource.com</a> and co-authored by Rahul Anand and Lahiru De Silva (myself). Read the original article here: <a href="https://opensource.com/article/21/10/google-summer-code">Original Article on Opensource.com</a></p>
</div>
</div>
<section id="how-we-made-it-to-gsoc-and-what-we-learned-about-open-source-code." class="level2">
<h2 class="anchored" data-anchor-id="how-we-made-it-to-gsoc-and-what-we-learned-about-open-source-code.">How we made it to GSoC and what we learned about open source code.</h2>
<p>Every year, Google organizes a program called Summer of Code (GSoC). Students worldwide can write open source code under an open source mentoring organization and get paid to do so! You get to work on cool open source projects, network with talented engineers, and get paid during the summer break. How cool is that!?</p>
<p>In this blog post, we’ll guide you through our GSoC experience and give you tips and tricks so that you can have a fantastic experience like we did. We’ll also share our differing perspectives based on our different interests and challenges.</p>
</section>
<section id="about-us" class="level2">
<h2 class="anchored" data-anchor-id="about-us">About us</h2>
<p><strong>Rahul</strong>: My name is Rahul Anand, and, at the time of writing this, I am in my senior year of college, majoring in computer engineering at Thapar University, Patiala, India. My interest is in distributed computing because it’s one of the significant areas allowing scalability of applications worldwide. Computer vision is sprinkled on top just because AI will take over the world.</p>
<p><strong>Lahiru</strong>: I am Lahiru Udayanga, currently a final-year undergraduate at the Department of Computer Science and Engineering, University of Moratuwa, Sri Lanka. My main focus areas in computer science are distributed systems, API gateways, proxies, and cloud-native technologies.</p>
</section>
<section id="choosing-the-proper-organization-and-project" class="level2">
<h2 class="anchored" data-anchor-id="choosing-the-proper-organization-and-project">Choosing the proper organization and project</h2>
<p>The first and the most crucial decision you’ll make during this journey is choosing the most suitable organization and the project you want to contribute to. This decision will heavily influence your experience, so be very diligent here. Don’t worry—at the end of this section, we have listed factors you should consider for this stage.</p>
<p>We both decided to apply for the same project: 3scale-envoy proxy authorization cache. However, we each had a slightly different thought process behind choosing this project.</p>
<p><strong>Rahul</strong>: I discussed the options with a senior who participated in GSoC’20 under the JBoss umbrella and described his experience as very enriching. That’s how I decided which organization I wanted to participate with. I advise juniors to focus on one good organization and start exploring different projects in it. Regarding project choice, a mix of various factors influenced me. Most important was my first interaction with my mentor, Alejandro Martinez Ruiz. I asked him numerous questions, and he was always ready with detailed replies to all of them. (Tip: Be concise in your questions and respect your mentor’s time.) I also wanted to work with distributed systems, learn Rust, and build a project from the ground up.</p>
<p><strong>Lahiru</strong>: The main reason I applied to this project is my deep interest in middleware, API gateways, and proxies. Also, I had some previous experience with envoy proxy from my internship project. I believe that envoy proxy will revolutionize the domain of proxies and that there will be a lot of opportunities for envoy-proxy-related technologies. Like Rahul, my first interaction with Alex and the conversations we had before the proposal-submitting phase also had a significant impact on my decision to apply.</p>
</section>
<section id="tips-for-this-period" class="level2">
<h2 class="anchored" data-anchor-id="tips-for-this-period">Tips for this period:</h2>
<ul>
<li>If you find any technology cool or want to learn more about it, look for those projects.</li>
<li>Ask seniors about their experiences with different organizations.</li>
<li>Consider the future of this project: do you see a future for this area of research?</li>
<li>If you have a good initial connection with a potential mentor, continue to build rapport.</li>
</ul>
</section>
<section id="developing-the-proposal" class="level2">
<h2 class="anchored" data-anchor-id="developing-the-proposal">Developing the proposal</h2>
<p>After deciding on which project we wanted to work on, we put our research caps on and started digging for any information related to the problem and possible solutions. During this phase, we were constantly interacting with our mentor about any questions, resources, and solution designs that we were thinking of going forward with independently. It’s best to come as close as possible to the actual outcome and document everything in a separate document for your reference, because it will help immensely during your proposal-creation phase.</p>
<p>After researching for about one to two months, as we neared the opening of proposal submissions, our mentor asked us to start putting everything into a separate Google Doc to be presented as a proposal in front of a committee. It was time to make friends with Shakespeare and type hard work into a document that would change our lives forever!</p>
<p>Jokes aside, it’s imperative to have this document look presentable, with excellent diagrams. We used and recommend draw.io (now diagrams.net), an open source diagramming software. Remember that no one can write a perfect document the first time through, and have a few review cycles with your mentor to get their feedback. You can look at our proposals for an example.</p>
<p><a href="https://drive.google.com/file/d/1R7uwJd6kohBC9xHzUFjmzsCWA6CoSesN/view">Rahul’s Proposal</a></p>
<p><a href="https://docs.google.com/document/d/1WpW-UUSwgVVvSFZvJaIpXNZB0DRUSQGDFOJCoM88h9k/edit?usp=sharing">Lahiru’s Proposal</a></p>
<p>We remember the day we clicked the submit button on the GSoC dashboard—it was raining fire from the sky in the Indian subcontinent. With our fates now in the hands of the JBoss organization and the 3scale team at Red Hat, we waited until that fateful day when our parents awoke at 2AM to newly minted adults screaming at top of their lungs, “GSOC BABY!!”</p>
</section>
<section id="learning-by-doing" class="level2">
<h2 class="anchored" data-anchor-id="learning-by-doing">Learning by doing</h2>
<p>The next day, we received our first email with onboarding information, each other’s proposal to refer to, and an invitation to a call between Alex and us. During the first call, we learned about each other, our respective cultures, and the 3scale team, and we were tasked with creating a shared document with a realistic timeline. Since this project was massive compared to other GSoC projects and we found clashing obligations in the future, we decided to start working before the coding period began. We were able to finalize a design with proofs-of-concept (POCs) showcasing certain guarantees required by our use cases and an initialized GitHub repository before the official start.</p>
<p>To progress faster, we separated our concerns. Rahul took the responsibility of the Cache-Filter and Lahiru of the Singleton-Service, and with a standard interface finalized during an online meeting. To make sure that we were on the same page and to find blockers early on, Alex scheduled two meetings: weekly syncs for progress, blockers, possible design changes, and POCs, and biweekly syncs for just talking about anything other than work. He also asked us to create weekly reports in a separate Google Doc to be shared with other members of the community. We used these reports to give updates and receive advice or any heads-ups. Both of us struggled during this stage at different places.</p>
<p><strong>Rahul</strong>: At the start, I struggled a bit with following a standard workflow and using tools (including Git!) because I wanted to move fast. In hindsight, that helped us avoid future pains, so I am glad I learned them early on. The best advice I got from Alex was that it was our project, and we were free to make final decisions after his feedback. That gave me a sense of ownership, and I started experimenting more, creating more POCs, and bending specs to work with us. This change in attitude allowed me to implement features like visible logs and unique callouts that made integration testing easier and increased performance.</p>
<p><strong>Lahiru</strong>: For me, the most irritating thing at the beginning was the steeper learning curve of the Rust programming language. When I started programming in Rust, I was mostly yelling at the compiler instead of writing code. But a few weeks later, we were slowly becoming friends. (I think the Rust compiler is more like an overprotective nanny. It has no interest in being your friend, but it will do everything it can to stop you from hurting yourself.) Also, there are vast differences among the Rust code written by a beginner, an intermediate, and an expert. These differences exist in other programming languages, like Java, Golang, and C++, but not to the same extent. So one of the challenges I had was implementing not only something that works but something that works in the most Rustic way possible.</p>
</section>
<section id="what-we-learned" class="level2">
<h2 class="anchored" data-anchor-id="what-we-learned">What we learned</h2>
<p>If you want a list of things we learned that you can learn too if you participate in the Summer of Code, here it is:</p>
<ul>
<li>Collaboration: How to interact with the open source community, how to give context to a person new to your work</li>
<li>Best practices for developing software: How to structure PRs and commits, how to set up and write integration or unit tests</li>
<li>New technologies: Rust, Golang, Proxy-WASM, Envoy, etc.</li>
<li>Soft skills: How to interact with senior engineers, how to introduce yourself</li>
<li>Distributed computing theory in action and problem-solving skills in general</li>
</ul>
<p>Google Summer of Code 2021 was an enriching experience for both of us. We got to interact with great engineers like Piotr Sikora (some say CPP is a language from hell, but he turns it into beautiful prose), Takeshi Yoneda (our savior when we needed it the most), David Ortiz (the myth, the legend, the co-creator of Limitador), and (obviously) Alex Martinez, along with the whole 3scale team. Without these people, we don’t think we could have made it to the final stages and be listed on the GSoC website.</p>


</section>

 ]]></description>
  <category>Open Source</category>
  <category>Envoy</category>
  <category>WebAssembly</category>
  <guid>https://lahirudesilva.com/posts/gsoc-opensource-redhat/</guid>
  <pubDate>Sat, 23 Oct 2021 00:00:00 GMT</pubDate>
  <media:content url="https://lahirudesilva.com/posts/gsoc-opensource-redhat/gsoc.jpg" medium="image" type="image/jpeg"/>
</item>
</channel>
</rss>
