<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Arsh Sharma</title>
    <description>The latest articles on DEV Community by Arsh Sharma (@rinkiyakedad).</description>
    <link>https://dev.to/rinkiyakedad</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F488212%2F66d9df7f-f08b-481a-8a26-509ab225f79a.jpeg</url>
      <title>DEV Community: Arsh Sharma</title>
      <link>https://dev.to/rinkiyakedad</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rinkiyakedad"/>
    <language>en</language>
    <item>
      <title>Wrote a new blog!</title>
      <dc:creator>Arsh Sharma</dc:creator>
      <pubDate>Thu, 04 Sep 2025 10:54:59 +0000</pubDate>
      <link>https://dev.to/rinkiyakedad/wrote-a-new-blog-4d9c</link>
      <guid>https://dev.to/rinkiyakedad/wrote-a-new-blog-4d9c</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/metalbear/new-features-we-find-exciting-in-the-kubernetes-134-release-2mhl" class="crayons-story__hidden-navigation-link"&gt;New Features We Find Exciting in the Kubernetes 1.34 Release&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;
          &lt;a class="crayons-logo crayons-logo--l" href="/metalbear"&gt;
            &lt;img alt="MetalBear logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F10935%2F5e6a0e22-733f-4582-8243-d0dfdbc47bba.png" class="crayons-logo__image"&gt;
          &lt;/a&gt;

          &lt;a href="/rinkiyakedad" class="crayons-avatar  crayons-avatar--s absolute -right-2 -bottom-2 border-solid border-2 border-base-inverted  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F488212%2F66d9df7f-f08b-481a-8a26-509ab225f79a.jpeg" alt="rinkiyakedad profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/rinkiyakedad" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Arsh Sharma
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Arsh Sharma
                
              
              &lt;div id="story-author-preview-content-2819466" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/rinkiyakedad" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F488212%2F66d9df7f-f08b-481a-8a26-509ab225f79a.jpeg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Arsh Sharma&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

            &lt;span&gt;
              &lt;span class="crayons-story__tertiary fw-normal"&gt; for &lt;/span&gt;&lt;a href="/metalbear" class="crayons-story__secondary fw-medium"&gt;MetalBear&lt;/a&gt;
            &lt;/span&gt;
          &lt;/div&gt;
          &lt;a href="https://dev.to/metalbear/new-features-we-find-exciting-in-the-kubernetes-134-release-2mhl" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Sep 4 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/metalbear/new-features-we-find-exciting-in-the-kubernetes-134-release-2mhl" id="article-link-2819466"&gt;
          New Features We Find Exciting in the Kubernetes 1.34 Release
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/kubernetes"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;kubernetes&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devops"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devops&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/cloud"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;cloud&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/docker"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;docker&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/metalbear/new-features-we-find-exciting-in-the-kubernetes-134-release-2mhl" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;10&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/metalbear/new-features-we-find-exciting-in-the-kubernetes-134-release-2mhl#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            8 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>cloud</category>
      <category>docker</category>
    </item>
    <item>
      <title>New Features We Find Exciting in the Kubernetes 1.34 Release</title>
      <dc:creator>Arsh Sharma</dc:creator>
      <pubDate>Thu, 04 Sep 2025 10:54:31 +0000</pubDate>
      <link>https://dev.to/metalbear/new-features-we-find-exciting-in-the-kubernetes-134-release-2mhl</link>
      <guid>https://dev.to/metalbear/new-features-we-find-exciting-in-the-kubernetes-134-release-2mhl</guid>
      <description>&lt;p&gt;The Kubernetes 1.34 release, “Of Wind &amp;amp; Will (O’ WaW)”, sets sail with a collection of features that may not grab headlines, but instead improve the day-to-day experience of running and managing clusters. Think of it as steady winds filling the sails, incremental but powerful improvements that help cluster administrators navigate smoother waters. And since combing through the full release notes can feel like charting a course through rough seas, we’ve pulled together some of the most useful highlights from this release to keep you on course.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Features Moving to Stable: Anchored and Ready for the Voyage
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Dynamic Resource Allocation with Structured Parameters
&lt;/h3&gt;

&lt;p&gt;Today where most companies are running (or trying to) run AI workloads on Kubernetes, we feel this feature is going to be the most important one from this release. &lt;/p&gt;

&lt;p&gt;Before this change, Kubernetes didn’t really “see” specialized hardware devices like GPUs. Instead, the device drivers running on each node were responsible for keeping track of hardware availability and assigning it to pods. Kubernetes itself had no awareness of what devices existed, how many were available, or where they were located.&lt;/p&gt;

&lt;p&gt;This lack of visibility introduced a number of challenges. For example, if two pods requested a GPU on the same node, the driver had to resolve the conflict on its own, without the scheduler knowing what was going on. Sharing GPU resources across pods was equally messy, since Kubernetes couldn’t reason about device capacity or availability and only knew that a pod needed “a GPU,” not whether the hardware was free or oversubscribed.&lt;/p&gt;

&lt;p&gt;With Kubernetes v1.34, this changes. The new &lt;a href="https://kubernetes.io/docs/concepts/scheduling-eviction/dynamic-resource-allocation/" rel="noopener noreferrer"&gt;Dynamic Resource Allocation (DRA)&lt;/a&gt; framework, along with by structured parameters, lets Kubernetes manage specialized hardware devices directly. Structured parameters let hardware drivers describe the exact capabilities and constraints of a device in a standardized format that Kubernetes can understand. For example, instead of just saying “this node has 1 GPU,” the driver can specify details like GPU memory, supported features, or whether the device can be shared across multiple pods.&lt;/p&gt;

&lt;p&gt;With this feature, instead of drivers silently handling everything, they now publish available devices as Kubernetes objects called &lt;code&gt;ResourceSlice&lt;/code&gt;. These slices describe what hardware exists on each node and expose details that Kubernetes can use to make better scheduling decisions.&lt;/p&gt;

&lt;p&gt;In other words, Kubernetes is no longer “blind” to hardware like GPUs, it can see what’s available, allocate it fairly, and even support sharing more reliably. Here’s a simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;resource.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ResourceSlice&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;resourceslice&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;nodeName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;worker-1&lt;/span&gt;
  &lt;span class="na"&gt;pool&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gpu-pool&lt;/span&gt;
    &lt;span class="na"&gt;generation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="na"&gt;resourceSliceCount&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dra.example.com&lt;/span&gt;
  &lt;span class="na"&gt;sharedCounters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gpu-memory&lt;/span&gt;
      &lt;span class="na"&gt;counters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;8Gi&lt;/span&gt;
  &lt;span class="na"&gt;devices&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gpu-1&lt;/span&gt;
      &lt;span class="na"&gt;consumesCounters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;counterSet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gpu-memory&lt;/span&gt;
          &lt;span class="na"&gt;counters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;8Gi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example shows a single GPU on node &lt;code&gt;worker-1&lt;/code&gt;, grouped into a pool called &lt;code&gt;gpu-pool&lt;/code&gt;. The GPU has 8 GB of memory, published through &lt;code&gt;sharedCounters&lt;/code&gt;. Because this information is now visible to Kubernetes, the scheduler knows exactly how much memory the device provides and can place pods accordingly, instead of relying on the driver to manage it behind the scenes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Allowing Only Anonymous Authentication for Configured Endpoints
&lt;/h3&gt;

&lt;p&gt;With Kubernetes v1.34, you can now safely expose specific API server endpoints like &lt;code&gt;/healthz&lt;/code&gt;, &lt;code&gt;/readyz&lt;/code&gt;, and &lt;code&gt;/livez&lt;/code&gt; without accidentally granting broader anonymous access.&lt;/p&gt;

&lt;p&gt;By default, Kubernetes treats unauthenticated requests as anonymous, assigning them the identity &lt;code&gt;system:anonymous&lt;/code&gt; and group &lt;code&gt;system:unauthenticated&lt;/code&gt;. While this design supports useful cases such as health checks, it also comes with risks. If a &lt;code&gt;RoleBinding&lt;/code&gt; or &lt;code&gt;ClusterRoleBinding&lt;/code&gt; is accidentally applied to &lt;code&gt;system:anonymous&lt;/code&gt;, even unauthenticated code running in a pod could gain access to the API server. &lt;/p&gt;

&lt;p&gt;The new update fixes scenarios like these by giving administrators fine-grained control over which paths are available to anonymous users. Instead of having to disable anonymous access entirely, which can break important functionality, you can now define a safe list of allowed endpoints using the new &lt;code&gt;AuthenticationConfiguration&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;Here’s an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apiserver.config.k8s.io/v1beta1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AuthenticationConfiguration&lt;/span&gt;
&lt;span class="na"&gt;anonymous&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;conditions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/livez&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/readyz&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/healthz&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this configuration, anonymous requests are permitted only to the health check endpoints, while all other anonymous requests are denied, even if misconfigured RoleBindings exist. &lt;/p&gt;

&lt;h3&gt;
  
  
  Relaxed DNS Search String Validation
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;dnsConfig.searches&lt;/code&gt; field in a Pod manifest controls how short hostnames are resolved. If your pod looks up &lt;code&gt;myserver&lt;/code&gt;, Kubernetes will automatically append each domain listed under &lt;code&gt;dnsConfig.searches&lt;/code&gt; and try them in order. For example, &lt;code&gt;myserver.first-domain&lt;/code&gt;, then &lt;code&gt;myserver.second-domain&lt;/code&gt;, and so on until it finds a match. This mechanism is especially important when migrating legacy applications into Kubernetes since many older services rely on custom DNS search domains, sometimes with underscores (&lt;code&gt;_&lt;/code&gt;) or leading dots (&lt;code&gt;.&lt;/code&gt;). &lt;/p&gt;

&lt;p&gt;Until now, Kubernetes didn’t allow these in &lt;code&gt;dnsConfig.searches&lt;/code&gt;, which meant some services simply couldn’t be deployed without changing their DNS assumptions which is a task that can be both risky and time-consuming.&lt;/p&gt;

&lt;p&gt;With Kubernetes v1.34, these restrictions are lifted. You can now include underscores and dots in DNS search domains, which makes it much easier to bring legacy workloads into Kubernetes without rewriting configurations or service names.&lt;/p&gt;

&lt;p&gt;Here’s what that looks like in practice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;           
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;          
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;app-1&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;app-1&lt;/span&gt;
      &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
  &lt;span class="na"&gt;dnsPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;None"&lt;/span&gt;
  &lt;span class="na"&gt;dnsConfig&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;nameservers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;10.244.0.69&lt;/span&gt;
    &lt;span class="na"&gt;searches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;abc_d.staging.com&lt;/span&gt;  &lt;span class="c1"&gt;# Now valid&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;           
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;          
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;app-2&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;app-2&lt;/span&gt;
      &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
  &lt;span class="na"&gt;dnsPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;None"&lt;/span&gt;
  &lt;span class="na"&gt;dnsConfig&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;nameservers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;10.244.0.69&lt;/span&gt;
    &lt;span class="na"&gt;searches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;   &lt;span class="c1"&gt;# Now valid&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;default.svc.cluster.local&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;svc.cluster.local&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cluster.local&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this update:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;app-1&lt;/code&gt; can now resolve fully qualified names like &lt;code&gt;test.abc_d.staging.com&lt;/code&gt; without issue.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;app-2&lt;/code&gt; can use the special &lt;code&gt;"."&lt;/code&gt; search entry to resolve hostnames exactly as written **before Kubernetes appends cluster defaults like &lt;code&gt;svc.cluster.local&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So to sum up, if you’re migrating older workloads or working with services that depend on unconventional DNS naming conventions, Kubernetes no longer forces you to rework your DNS setup. &lt;/p&gt;

&lt;h2&gt;
  
  
  Features Moving to Beta: Stronger Winds Filling the Sails
&lt;/h2&gt;

&lt;h3&gt;
  
  
  PreferSameNode Traffic Distribution
&lt;/h3&gt;

&lt;p&gt;Routing traffic efficiently in Kubernetes can be challenging, especially when services span multiple nodes or zones. By default, Kubernetes load-balances traffic across all healthy endpoints of a service, even if some are farther away. This can create unnecessary cross-node or cross-zone hops, which add latency and waste bandwidth. For many workloads, especially latency-sensitive applications like real-time inference, gaming backends, or high-throughput APIs, those extra hops can noticeably hurt performance.&lt;/p&gt;

&lt;p&gt;Kubernetes v1.34 introduces new traffic distribution policies to address this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;PreferSameNode&lt;/code&gt;: Services can now prefer pods on the same node when the traffic originates from that node. This reduces latency and avoids network overhead from cross-node traffic.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PreferSameZone&lt;/code&gt;: The existing &lt;code&gt;PreferClose&lt;/code&gt; policy has been renamed to &lt;code&gt;PreferSameZone&lt;/code&gt; to make its behavior clearer. This helps workloads prioritize pods in the same zone for lower latency and reduced cross-zone costs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s an example of both in action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http-echo-service-1&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http-echo-pod-1&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
      &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
      &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5678&lt;/span&gt;
  &lt;span class="na"&gt;trafficDistribution&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PreferSameNode&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http-echo-service-2&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http-echo-pod-2&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
      &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
      &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5678&lt;/span&gt;
  &lt;span class="na"&gt;trafficDistribution&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PreferSameZone&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this configuration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;http-echo-service-1&lt;/code&gt; routes traffic to a pod on the same node when possible. If none are available, it will fall back to another node.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;http-echo-service-2&lt;/code&gt; routes traffic to a pod in the same zone first, and only if necessary, sends it to a different zone.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  VolumeSource: OCI Artifact and/or Image
&lt;/h3&gt;

&lt;p&gt;In some deployments, multiple pods need access to the same configuration or data files. Traditionally, this might mean baking files into a ConfigMap or copying them into each pod, which can get messy as files grow larger or more complex.&lt;/p&gt;

&lt;p&gt;With Kubernetes v1.34, you now have a cleaner option: image volumes. This feature lets Kubernetes mount an OCI image as a read-only volume that can be shared across multiple pods. Instead of duplicating files or manually syncing them, you package the files once into an image and then mount them wherever they’re needed.&lt;/p&gt;

&lt;p&gt;Here’s an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx-container&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
    &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;POD_NAME&lt;/span&gt;
      &lt;span class="na"&gt;valueFrom&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;fieldRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
          &lt;span class="na"&gt;fieldPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;metadata.name&lt;/span&gt;
    &lt;span class="na"&gt;volumeMounts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;oci-volume&lt;/span&gt;
      &lt;span class="na"&gt;mountPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/data&lt;/span&gt;
      &lt;span class="na"&gt;subPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hello.txt&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;oci-volume&lt;/span&gt;
      &lt;span class="na"&gt;mountPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/data/&lt;/span&gt;
      &lt;span class="na"&gt;subPathExpr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$(POD_NAME).txt&lt;/span&gt;
  &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;oci-volume&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;reference&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;your-oci-image&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the &lt;code&gt;oci-volume&lt;/code&gt; references an OCI image that contains files. The pod mounts specific files from that image, &lt;code&gt;hello.txt&lt;/code&gt;, into its container. Since the volume is read-only, multiple pods can safely share the same source without conflicts. &lt;/p&gt;

&lt;p&gt;For developers using &lt;a href="https://metalbear.co/mirrord/" rel="noopener noreferrer"&gt;mirrord&lt;/a&gt;, this also means that you can now run your local code against a pod that already mounts an image volume in the cluster. Your local process will gain the same access to the shared files, so you can test how your code interacts with the data without deploying or modifying the cluster setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features Moving to Alpha: New Currents on the Horizon
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Allows Setting any FQDN as the Pod's Hostname
&lt;/h3&gt;

&lt;p&gt;Prior to this feature, setting a pod’s fully qualified domain name (FQDN) wasn’t straightforward. You had to combine multiple fields: &lt;code&gt;hostname&lt;/code&gt;, &lt;code&gt;subdomain&lt;/code&gt;, and &lt;code&gt;setHostnameAsFQDN: true&lt;/code&gt;, to build an FQDN. The result always followed Kubernetes’ enforced pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;hostname&amp;gt;.&amp;lt;subdomain&amp;gt;.&amp;lt;namespace&amp;gt;.svc.&amp;lt;cluster-domain&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If any part of that was misconfigured, the final FQDN wouldn’t resolve as expected. This could cause serious issues for systems that rely on strict hostname matching, such as &lt;a href="https://www.ibm.com/docs/en/aix/7.1.0?topic=network-kerberos" rel="noopener noreferrer"&gt;Kerberos&lt;/a&gt;, where authentication breaks if hostnames don’t line up exactly.&lt;/p&gt;

&lt;p&gt;This pain point is now addressed through a new field: &lt;code&gt;hostnameOverride&lt;/code&gt;. This field allows you to explicitly set the pod’s internal kernel hostname to whatever value you need, bypassing Kubernetes’ enforced DNS naming convention.&lt;/p&gt;

&lt;p&gt;Here’s an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;           
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;          
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;app&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;hostnameOverride&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;app.nginx.example.domain&lt;/span&gt;
  &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;app&lt;/span&gt;
      &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this configuration, the pod’s internal hostname is set directly to &lt;code&gt;app.nginx.example.domain&lt;/code&gt;. Unlike before, you don’t need to stitch together multiple fields or follow Kubernetes’ strict naming rules. &lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways From Of Wind &amp;amp; Will Kubernetes Release
&lt;/h2&gt;

&lt;p&gt;The &lt;em&gt;Of Wind &amp;amp; Will&lt;/em&gt; release is not about grand, sweeping changes, but it’s about steady progress. The kind of refinements that make Kubernetes a sturdier ship for the long journey ahead. One of the standout improvements is the graduation of Dynamic Resource Allocation (DRA), a huge step forward for teams running AI workloads. With DRA, Kubernetes finally gains proper visibility into GPUs and other specialized hardware, making scheduling and sharing these resources far more reliable. For anyone working on machine learning or high-performance computing, this is a game-changer.&lt;/p&gt;

&lt;p&gt;Security also gets tighter with more fine-grained anonymous access controls, ensuring only the right endpoints are exposed without weakening cluster safety. And for those migrating legacy systems, features like &lt;code&gt;hostnameOverride&lt;/code&gt; and expanded DNS search support smooth out long-standing pain points, making Kubernetes more welcoming to applications that weren’t originally built for it.&lt;br&gt;
Together, these updates may feel like adjustments to the rigging rather than rebuilding the ship, but that’s what makes them powerful. They reduce friction, close gaps, and make Kubernetes more adaptable to the real-world seas we sail in. With 1.34, the community hands cluster administrators and developers not just new features, but stronger winds and steadier will to keep moving forward.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>cloud</category>
      <category>docker</category>
    </item>
    <item>
      <title>How to Provide Secure Access to Your Kubernetes Clusters Using an Overlay Network</title>
      <dc:creator>Arsh Sharma</dc:creator>
      <pubDate>Mon, 02 Jun 2025 18:30:00 +0000</pubDate>
      <link>https://dev.to/rinkiyakedad/how-to-provide-secure-access-to-your-kubernetes-clusters-using-an-overlay-network-281g</link>
      <guid>https://dev.to/rinkiyakedad/how-to-provide-secure-access-to-your-kubernetes-clusters-using-an-overlay-network-281g</guid>
      <description>&lt;p&gt;Kubernetes is complex. Securing Kubernetes clusters is even more complex. Striking the right balance between granting developers and administrators access to Kubernetes clusters and services while taking care of security is a significant challenge. &lt;a href="https://www.techtarget.com/searchnetworking/definition/overlay-network" rel="noopener noreferrer"&gt;Overlay networks&lt;/a&gt; offer a solution by providing secure, controlled access to your clusters without compromising their protection. In this blog, we’ll explore the challenges of providing secure access to Kubernetes clusters, how overlay networks can address these issues, and a step-by-step tutorial on implementing this using &lt;a href="https://netbird.io/" rel="noopener noreferrer"&gt;NetBird&lt;/a&gt;, an open-source &lt;a href="https://www.wireguard.com/" rel="noopener noreferrer"&gt;WireGuard&lt;/a&gt;-based overlay VPN.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenges of Providing Secure Remote Access to Kubernetes Clusters
&lt;/h2&gt;

&lt;p&gt;Your organization might have different Kubernetes clusters for different needs: development, staging, testing, and production. Configuring who can access which cluster or which services on a particular cluster can be a really complicated process. It would also require you to work around the existing firewall rules your IT team might have set in place. Safe to say, it’s not a fun experience.&lt;/p&gt;

&lt;p&gt;But why is it important to have this type of fine-grained access?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reducing the Attack Surface&lt;/strong&gt; : Allowing everyone to have full access to all clusters and all services is a recipe for disaster. You’re basically increasing the attack surface for things to go wrong. Even if you don’t get attacked, you are still prone to accidents. For example, someone on your team accidentally making a change to a different cluster or service than the one they’re responsible for, leading to costly downtime or data loss.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplifying Access for Non-Developers&lt;/strong&gt; : There are scenarios where stakeholders other than developers and administrators (e.g., QA testers or product managers) need access to specific services in staging or testing environments. Setting up and remembering to revoke firewall rules for such users can be cumbersome and prone to oversight, creating potential security risks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Securing Staging and Testing Clusters&lt;/strong&gt; : Staging and testing clusters should not be exposed to the public internet. However, developers still need secure access to these environments to perform their tasks. Traditional methods of providing this access are often complicated and insecure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All these are reasons to establish a way to provide fine-grained access to your Kubernetes clusters and the services they’re running. Everyone should be able to access what they need but nothing more. At the same time, you need a way to respect your existing firewall and networking rules instead of having to modify them each time a different person or team needs access. The good part is that an overlay network like NetBird makes all of this really easy!&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are Overlay Networks?
&lt;/h2&gt;

&lt;p&gt;Overlay networks are virtual networks that operate on top of your existing physical network infrastructure. &lt;a href="https://netbird.io/use-cases/remote-access" rel="noopener noreferrer"&gt;NetBird&lt;/a&gt;, for example, is an overlay network built on &lt;a href="https://en.wikipedia.org/wiki/WireGuard" rel="noopener noreferrer"&gt;WireGuard&lt;/a&gt; technology. It enables secure remote access and connectivity between different parts of your infrastructure (whether it’s on-premises, your local machine, in a cloud provider, or anywhere else) without requiring changes to existing firewall rules.&lt;/p&gt;

&lt;p&gt;This is achieved by leveraging peer-to-peer communications, which means devices in the overlay network can communicate directly with each other through encrypted tunnels. This provides a secure and efficient way to connect your infrastructure while maintaining isolation from the underlying physical network. Let’s understand this visually by taking the example of providing access to a Kubernetes cluster securely.&lt;/p&gt;

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

&lt;p&gt;In this case, as you see, we run the NetBird agent on the developers’ machines, and we have the NetBird Kubernetes operator running in the cluster. The NetBird control plane then takes care of ensuring secure peer-to-peer communication between each of the machines and the services on the cluster. You can configure which machine (or sets of machines) have access to which services without giving everybody full access to the cluster. You can also also specify:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What ports can be accessed by what groups of machines&lt;/li&gt;
&lt;li&gt;What geolocations are allowed access&lt;/li&gt;
&lt;li&gt;What operating systems are allowed access (example: macOS devices only)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;NetBird does all of this with the help of &lt;a href="https://docs.netbird.io/how-to/manage-posture-checks" rel="noopener noreferrer"&gt;Posture Checks&lt;/a&gt;. The best part is that since this is an overlay network, it respects any existing firewall or network rules you already have in place and doesn’t require you to modify them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Securing Remote Access to Kubernetes Clusters
&lt;/h2&gt;

&lt;p&gt;Now, let’s walk through the step-by-step process of configuring secure remote access from a developer’s machine to a service running in a Kubernetes cluster using NetBird. There are a few things you’ll need to follow along:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Kubernetes cluster. I’m going to be using a &lt;a href="https://cloud.google.com/kubernetes-engine?hl=en" rel="noopener noreferrer"&gt;GKE&lt;/a&gt; cluster, but feel free to use any cloud provider.&lt;/li&gt;
&lt;li&gt;A NetBird cloud account. This is completely &lt;a href="https://docs.netbird.io/how-to/getting-started" rel="noopener noreferrer"&gt;free to get started&lt;/a&gt; with, and the setup process hardly takes 5 minutes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Installing the NetBird Kubernetes Operator
&lt;/h3&gt;

&lt;p&gt;Once you’re done with the above prerequisites, we can begin installing the NetBird Kubernetes operator on the cluster. The first thing you need to do is add the Helm repository where the NetBird operator chart is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm repo add netbirdio &amp;lt;https://netbirdio.github.io/kubernetes-operator&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The NetBird operator requires &lt;a href="https://cert-manager.io/" rel="noopener noreferrer"&gt;cert-manager&lt;/a&gt; in order to communicate with the Kubernetes API. You can install the latest version of cert-manager by following the instructions &lt;a href="https://cert-manager.io/docs/installation/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. One thing I would recommend before proceeding is using the &lt;a href="https://cert-manager.io/docs/reference/cmctl/#installation" rel="noopener noreferrer"&gt;cmctl CLI&lt;/a&gt; to check if the cert-manager API is ready or not.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f &amp;lt;https://github.com/cert-manager/cert-manager/releases/download/v1.17.0/cert-manager.yaml&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, we need an API token to connect this operator to our NetBird account. You can find instructions on how to create a service account user and generate a token for it in the &lt;a href="https://docs.netbird.io/how-to/access-netbird-public-api#creating-a-service-user" rel="noopener noreferrer"&gt;docs here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once you’ve generated your token, copy it and put it in a file named &lt;code&gt;nb-pat.secret&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now we’re ready to create a &lt;a href="https://kubernetes.io/docs/concepts/configuration/secret/" rel="noopener noreferrer"&gt;Kubernetes Secret&lt;/a&gt; which stores this token in a new namespace called &lt;code&gt;netbird&lt;/code&gt;. We’ll be installing the NetBird operator in this same namespace later. The operator would be reading the API token from this secret we create:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl create namespace netbird
kubectl -n netbird create secret generic netbird-mgmt-api-key --from-literal=NB_API_KEY=$(cat ./nb-pat.secret)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this, create a &lt;code&gt;values.yaml&lt;/code&gt; which has the configuration for the operator we’re going to install. Here’s a minimal configuration to help you get started:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ingress:
  enabled: true
  router:
    enabled: true

netbirdAPI:
  keyFromSecret: "netbird-mgmt-api-key"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can run &lt;code&gt;helm show values netbirdio/kubernetes-operator&lt;/code&gt; to get complete information on all the fields you can configure in this file. What the above configuration does is first enable &lt;code&gt;ingress&lt;/code&gt; so that we’re able to expose services from our cluster.&lt;/p&gt;

&lt;p&gt;Enabling &lt;code&gt;routing&lt;/code&gt; deploys &lt;a href="https://docs.netbird.io/how-to/routing-peers-and-kubernetes" rel="noopener noreferrer"&gt;routing peers&lt;/a&gt; in the form of Kubernetes pods in the NetBird namespace. These routing peers are what allow access between your machine and the services on the cluster. By default, if you enable them, NetBird will create three of these so that you have high availability and even if one of them fails, your connection isn’t interrupted.&lt;/p&gt;

&lt;p&gt;Once you’ve created this file, it’s now time to install the operator by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm install --create-namespace -f values.yaml -n netbird netbird-operator netbirdio/kubernetes-operator

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the installation is complete check if everything is working correctly or not by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get pods -n netbird

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deploying a service
&lt;/h3&gt;

&lt;p&gt;Once we have the operator installed, let’s deploy an &lt;a href="https://nginx.org/" rel="noopener noreferrer"&gt;Nginx&lt;/a&gt; deployment and create a Kubernetes service for it. We expose the Nginx deployment using the &lt;code&gt;ClusterIP&lt;/code&gt; service type in Kubernetes. By default, &lt;code&gt;ClusterIP&lt;/code&gt; restricts access to the service from &lt;strong&gt;within&lt;/strong&gt; the cluster only, meaning it won’t be accessible from outside the cluster. Later in this guide, we’ll see how to enable secure external access to this service from our local machine using NetBird (without changing the service type). For now, deploy the following Kubernetes configuration which creates an Nginx deployment and a service for it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - image: nginx
          imagePullPolicy: Always
          name: nginx
---
apiVersion: v1
kind: Service
metadata:
  annotations:
    netbird.io/expose: "true"
    netbird.io/policy: default
    netbird.io/resource-name: nginx
    netbird.io/groups: nginx-k8s-gke
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  ports:
    - name: http
      port: 80
      protocol: TCP
      targetPort: 80
  selector:
    app: nginx
  type: ClusterIP

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I want to call out your attention to the annotations for the service we create. This is what the following annotations do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;netbird.io/expose: "true"&lt;/code&gt; - This tells the operator that this service is to be exposed by NetBird. Any service that doesn’t have this annotation won’t be discovered by NetBird, and you’ll not be able to access it in the NetBird console.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;netbird.io/policy: default&lt;/code&gt; - This specifies the default policy to apply to the service. Policies in NetBird define who can access the service and under what conditions.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;netbird.io/resource-name: nginx&lt;/code&gt; - This is what the name of the service will be shown as in the NetBird console. We’ll see a screenshot which shows this later.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;netbird.io/groups: nginx-k8s-gke&lt;/code&gt; - This specifies what group the service belongs to in the NetBird console. &lt;a href="https://docs.netbird.io/how-to/manage-network-access#groups" rel="noopener noreferrer"&gt;Groups&lt;/a&gt; in NetBird are a way to club different resources together based on things like which teams are responsible for taking care of them, which application they belong to, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Create the Nginx deployment and service by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f nginx.yaml

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you have the service created, it’s now time to head over to the NetBird console and configure a secure connection from our dev machine to this service.&lt;/p&gt;

&lt;h3&gt;
  
  
  Establishing a secure connection with the deployed service
&lt;/h3&gt;

&lt;p&gt;In many cases, developers need access to a service running inside a Kubernetes cluster (like the one we deployed) to test functionality from their local machines. However, exposing internal services publicly is not ideal due to security concerns. This is where an overlay network solution like NetBird comes in, allowing developers to securely connect to internal services without opening them up to the internet or modifying the service type itself.&lt;/p&gt;

&lt;p&gt;I’ll demonstrate how to establish a secure connection to the Nginx service from your own local machine. However, it’s worth noting that NetBird allows you to provide access to this service from multiple machines which could belong to different developers in your organization.&lt;/p&gt;

&lt;p&gt;The first step is to install the NetBird agent on the machines that need access. Since I’m using macOS, I followed the &lt;a href="https://docs.netbird.io/how-to/getting-started#install-net-bird" rel="noopener noreferrer"&gt;installation instructions&lt;/a&gt; for Mac. Once installed, your local machine should appear in the “Peers” section of the NetBird console. I created a &lt;a href="https://docs.netbird.io/how-to/manage-network-access#groups" rel="noopener noreferrer"&gt;Group&lt;/a&gt; called “Backend Devs” and added my machine to it.&lt;/p&gt;

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

&lt;h4&gt;
  
  
  Creating an Access Policy
&lt;/h4&gt;

&lt;p&gt;Next, navigate to the “Networks” section in the NetBird console:&lt;/p&gt;

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

&lt;p&gt;Here, you’ll see a network named &lt;code&gt;kubernetes&lt;/code&gt;, which was automatically created by the NetBird operator when it was installed in the cluster. &lt;a href="https://docs.netbird.io/how-to/networks" rel="noopener noreferrer"&gt;Networks&lt;/a&gt; in NetBird simplify secure communication with resources in scenarios where installing the NetBird agent isn’t feasible for each resource. For example, by creating a network for the entire cluster, we can easily establish secure communication with individual services within the cluster. This means that any device with the NetBird agent installed can securely access the services running in the cluster (given it has the required permissions) without requiring additional configuration for each service from our side.&lt;/p&gt;

&lt;p&gt;Once you open the &lt;code&gt;kubernetes&lt;/code&gt; network, you’ll see the &lt;code&gt;nginx&lt;/code&gt; service as a resource. You’ll also see that it gets automatically assigned to a group called &lt;code&gt;nginx-k8s-gke&lt;/code&gt;, which is what we specified in the annotations when creating the service.&lt;/p&gt;

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

&lt;p&gt;The next step for us is to create a policy that allows access to this service from our local machine.&lt;/p&gt;

&lt;p&gt;Now, when you click the “Add Policy” button for the Nginx resource, the following popup should show up:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnmw0amyz6fi40bxbej9t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnmw0amyz6fi40bxbej9t.png" alt="New NetBird policy popup" width="796" height="693"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, I’ve selected “Backend Devs” as the source group. This is the group that has our local machine in it. The advantage of using &lt;a href="https://docs.netbird.io/how-to/manage-network-access#concepts" rel="noopener noreferrer"&gt;Groups&lt;/a&gt; is that you can easily add or remove different developers’ machines without modifying the policy itself. For the destination, I selected the &lt;code&gt;nginx-k8s-gke&lt;/code&gt; group, which has the deployed Nginx service. I chose TCP as the protocol and opened port &lt;code&gt;80&lt;/code&gt;, which is the port the Nginx service listens on.&lt;/p&gt;

&lt;p&gt;It’s important to note that the policy is configured for one-way communication: from the “Backend Devs” group to the Nginx service. This ensures that the service cannot initiate connections back to the local machines, which is a security best practice. NetBird excels in providing fine-grained access control, allowing you to define exactly what is needed and nothing more.&lt;/p&gt;

&lt;p&gt;Finish creating the policy by clicking continue and giving it an appropriate name.&lt;/p&gt;

&lt;h4&gt;
  
  
  Adding a Nameserver
&lt;/h4&gt;

&lt;p&gt;At this point, the Nginx service is accessible, but its address (&lt;code&gt;nginx.default.svc.cluster.local&lt;/code&gt;) needs to be resolvable from the local machines. To enable this, we’ll configure a DNS resolver in NetBird. Navigate to the “Nameservers” section under DNS and click “Add Nameserver”:&lt;/p&gt;

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

&lt;p&gt;Since our cluster is in GKE, choose Google DNS, and in the configuration for the nameserver, make sure to add the “Backend Devs” under distribution groups. Leaving everything else as it is, continue creating the nameserver.&lt;/p&gt;

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

&lt;p&gt;One final thing you need to do is enable DNS wildcard routing in your NetBird settings. The steps for that can be found &lt;a href="https://docs.netbird.io/how-to/networks#enable-dns-wildcard-routing" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Testing the Connection
&lt;/h4&gt;

&lt;p&gt;Once this is done, head over to the &lt;code&gt;nginx.default.svc.cluster.local&lt;/code&gt; URL in your browser. You should see the default Nginx welcome page:&lt;/p&gt;

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

&lt;p&gt;To verify the security of the setup, go back to the “Policies” section in the NetBird console (under Access Control) and disable the policy you just created. After doing so, you’ll no longer be able to access the Nginx service from your local machine.&lt;/p&gt;

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

&lt;p&gt;Now, you can even disable access to your cluster using the external public endpoint in the GKE settings, and you’ll still be able to access the service from all machines that have the NetBird agent installed and are part of the “Backend Devs” group.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ejcoerbbdkp28caz28a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ejcoerbbdkp28caz28a.png" alt="making the cluster endpoint private" width="800" height="284"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This approach is a recommended security best practice for clusters where public access isn’t necessary, such as those used for development, testing, or staging environments.&lt;/p&gt;

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

&lt;p&gt;I think now you can start to see the benefits of using an overlay network like NetBird to securely access resources and services in a Kubernetes cluster. As your organization grows, managing access to different clusters and services for different teams can become complex. NetBird simplifies this process by allowing you to create groups for teams and grant them access only to the things they need. This approach significantly reduces the attack surface and minimizes the potential for things to go wrong.&lt;/p&gt;

&lt;p&gt;As a next step, I recommend trying out the NetBird Kubernetes operator yourself by replicating the steps in this tutorial. &lt;a href="https://github.com/netbirdio/netbird" rel="noopener noreferrer"&gt;NetBird&lt;/a&gt; and their &lt;a href="https://github.com/netbirdio/kubernetes-operator" rel="noopener noreferrer"&gt;Kubernetes operator&lt;/a&gt; are open-source, so feel free to explore the project and contribute if you find it useful. Don’t forget to give the project a star on GitHub if it helps you in your work!&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>networking</category>
    </item>
    <item>
      <title>Introduction to Object Oriented Programming (OOP) in Golang</title>
      <dc:creator>Arsh Sharma</dc:creator>
      <pubDate>Sun, 15 Dec 2024 18:30:00 +0000</pubDate>
      <link>https://dev.to/rinkiyakedad/introduction-to-object-oriented-programming-oop-in-golang-4l5d</link>
      <guid>https://dev.to/rinkiyakedad/introduction-to-object-oriented-programming-oop-in-golang-4l5d</guid>
      <description>&lt;p&gt;When we talk about programming, we usually mean writing a bunch of functions that modify and interact with some data. Object Oriented Programming (OOP) is a programming model that instead focuses on “objects” that contain data and and have some relevant functions attached to them. Object Oriented Programming has four pillars: Inheritance, Encapsulation, Polymorphism, and Abstraction. In this blog, we’ll take a look at how you can implement each of them in Golang with examples. Some basic idea about OOP is recommended, but if not, I will be giving a brief introduction to what all the four pillars mean.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Classes, Objects, and Methods
&lt;/h2&gt;

&lt;p&gt;The core idea of Object Oriented Programming can be summed up in these bullet points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You define “classes” which are a collection of data and functions you can call on that data.&lt;/li&gt;
&lt;li&gt;These specific functions are called “methods” of that particular class.&lt;/li&gt;
&lt;li&gt;An actual instance of a class is called an “object.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s look at some code in Golang to understand these three concepts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Batman&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;actor&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;year&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;Batman&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SayImBatman&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I'm %s and I'm Batman from year %d&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;actor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;b1&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Batman&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;actor&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Michael Keaton"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1989&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;b2&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Batman&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;actor&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Christian Bale"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2005&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;b1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SayImBatman&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;b2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SayImBatman&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Golang, classes are nothing but &lt;a href="https://www.practical-go-lessons.com/chap-13-types#how-to-create-new-types-type-definition" rel="noopener noreferrer"&gt;types&lt;/a&gt; defined by us. These types don’t necessarily have to be a &lt;a href="https://gobyexample.com/structs" rel="noopener noreferrer"&gt;struct&lt;/a&gt; but usually they are since in OOP we work with a collection of data, which could be of any type (string, int, etc.).&lt;/p&gt;

&lt;p&gt;Classes are blueprints for objects. Whenever you instantiate a class, an object is formed. In this example, &lt;code&gt;b1&lt;/code&gt; and &lt;code&gt;b2&lt;/code&gt; are objects of the Batman class.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;SayImBatman&lt;/code&gt; function can be called on any object of the class. Since it’s tied to the Batman class, instead of calling it a regular function, it’s called a &lt;em&gt;method of the class&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I feel this should clear out the basics of OOP enough for you to move on to the next section, where we look at the four pillars of OOP.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inheritance
&lt;/h2&gt;

&lt;p&gt;Inheritance introduces the concepts of &lt;em&gt;parent&lt;/em&gt; and &lt;em&gt;child&lt;/em&gt; classes in OOP. A child class is a class derived from a parent class and inherits all its methods and properties (data). Let us look at some code which will help us understand this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Hero&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;team&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Batman&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Hero&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Ironman&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Hero&lt;/span&gt;
    &lt;span class="n"&gt;power&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="n"&gt;Hero&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SayTeam&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"My Team is"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;Batman&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SayImBatman&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I'm %s and I'm Batman&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="n"&gt;Ironman&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SayPowerLevel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I'm Ironman and my powerlevel is %d&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;power&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;b1&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Batman&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Hero&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Justice League"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="s"&gt;"Christian Bale"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;i1&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Ironman&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Hero&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Avengers"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="m"&gt;23&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;b1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SayImBatman&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;b1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SayTeam&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;i1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SayPowerLevel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;i1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SayTeam&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, Batman and Ironman are child classes of the Hero parent class. They have access to their parent class’s properties, that is, &lt;code&gt;team&lt;/code&gt;, and its methods, that is, &lt;code&gt;SayTeam&lt;/code&gt;. Like you can see when declaring the &lt;code&gt;b1&lt;/code&gt; and &lt;code&gt;i1&lt;/code&gt; instances, we specify the parent class properties as well as their specific properties for respective classes. Both of them are able to call the &lt;code&gt;SayTeam&lt;/code&gt; method that is defined on the parent class. But they also have separate properties and methods which are unique to each of them.&lt;/p&gt;

&lt;p&gt;Golang implements inheritance using &lt;a href="https://www.codecademy.com/resources/docs/go/composition" rel="noopener noreferrer"&gt;composition&lt;/a&gt; (using a struct inside a struct). It doesn’t have inbuilt class based inheritance like other OOP languages such as C++ or Java.&lt;/p&gt;

&lt;h2&gt;
  
  
  Encapsulation
&lt;/h2&gt;

&lt;p&gt;Encapsulation is the principle of hiding an object’s internal properties and not allowing them to be modified directly. Instead, it relies on providing methods to get and update these properties. Let’s look at an example to understand this better:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;//oops-in-go/utils/utils.go&lt;/span&gt;

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;utils&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Batman&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;actor&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;year&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Batman&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetActor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;actor&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Batman&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetYear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Batman&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SetActor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;actor&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;actor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;actor&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Batman&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SetYear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;year&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// oops-in-go/main.go&lt;/span&gt;

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"oops-in-go/utils"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;b1&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;utils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Batman&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;b1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetActor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Michael Keaton"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;b1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetYear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1989&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I'm %s and I'm Batman from year %d&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetActor&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;b1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetYear&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="n"&gt;b1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetActor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Christian Bale"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;b1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetYear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2005&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I'm %s and I'm Batman from year %d&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetActor&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;b1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetYear&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Golang, properties and methods that are exported out of the package begin with a capital letter. When we define &lt;code&gt;actor&lt;/code&gt; and &lt;code&gt;year&lt;/code&gt; with a lowercase in the &lt;code&gt;utils&lt;/code&gt; package, we ensure that they can’t be modified directly. Instead, like you see in the &lt;code&gt;main.go&lt;/code&gt; file, you need to use the exported methods (which begin with a capital letter) - &lt;code&gt;GetActor&lt;/code&gt;, &lt;code&gt;SetActor&lt;/code&gt;, etc., to fetch and modify them.&lt;/p&gt;

&lt;p&gt;This is what encapsulation is all about - making sure that you prevent accidental changes to data and instead provide methods to safely interact with the data.&lt;/p&gt;

&lt;p&gt;One thing you’ll notice different is that in all the methods for the Batman class, we’re using a pointer receiver &lt;code&gt;*Batman&lt;/code&gt; instead of a value receiver &lt;code&gt;Batman&lt;/code&gt; like we were in the earlier examples. This is because we want to be able to modify the original struct in the &lt;code&gt;Set&lt;/code&gt; methods. And in Golang, it’s best practice that if some methods need a pointer receiver, you make all the methods use a pointer receiver for consistency. That’s why the &lt;code&gt;Get&lt;/code&gt; methods are using a pointer receiver as well even though they aren’t modifying the original struct.&lt;/p&gt;

&lt;p&gt;Also, one more thing to note is that just because we’re using a pointer receiver, we don’t have to do this: &lt;code&gt;(&amp;amp;b1).GetActor&lt;/code&gt;. In Golang, functions with a pointer argument must take a pointer, but methods with a pointer receiver can either take a value or pointer as the receiver.&lt;/p&gt;

&lt;p&gt;TL;DR: Golang automatically translates &lt;code&gt;b1.GetActor&lt;/code&gt; as &lt;code&gt;(&amp;amp;b1).GetActor&lt;/code&gt; since the &lt;code&gt;GetActor&lt;/code&gt; method has a pointer receiver, but it would not translate &lt;code&gt;GetActor(b1)&lt;/code&gt; to &lt;code&gt;GetActor(&amp;amp;b1)&lt;/code&gt; had the &lt;code&gt;GetActor&lt;/code&gt; been a normal function taking a pointer argument.&lt;/p&gt;

&lt;h2&gt;
  
  
  Polymorphism and Abstraction
&lt;/h2&gt;

&lt;p&gt;The next two pillars of OOP can be clubbed because the code samples for them would look pretty similar. Polymorphism refers to the programming practice where two different objects of two different classes can be treated as objects of the same common superclass. That means you can call the same function on two different objects as if they were objects of the same class. This should start giving you a scent of &lt;a href="https://go.dev/tour/methods/9" rel="noopener noreferrer"&gt;interfaces&lt;/a&gt; being involved :)&lt;/p&gt;

&lt;p&gt;Let’s look at some code to understand this better:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Hero&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Fight&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Batman&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;weapon&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Ironman&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;weapon&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;Batman&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Fight&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Batman hits with a %s&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;weapon&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="n"&gt;Ironman&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Fight&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Ironman hits with a %s&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;weapon&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;StartFight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="n"&gt;Hero&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Fight has started."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fight&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;b1&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Batman&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"Batarang"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;i1&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Ironman&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"Repulsor rays"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;StartFight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;StartFight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the &lt;code&gt;StartFight&lt;/code&gt; function can be passed both the &lt;code&gt;b1&lt;/code&gt; and &lt;code&gt;i1&lt;/code&gt; objects even though they are related in no way to each other. Try to understand how this is different from Inheritance, where the child classes had access to the parent class’s &lt;em&gt;methods&lt;/em&gt;. In this example, there are no child and parent classes (and no methods being shared as well). Instead, two different objects are being treated as the same by a &lt;em&gt;function&lt;/em&gt;: this is called Polymorphism.&lt;/p&gt;

&lt;p&gt;Now, this can also be treated as an example of Abstraction. Abstraction, like the name suggests, is the programming practice of hiding away implementation details and instead just providing functions that take care of things for you. In this example, you don’t need to care how the individual hero’s methods are configured. You can continue using the &lt;code&gt;StartFight&lt;/code&gt; function anytime you want to use any of the heroes’ &lt;code&gt;Fight&lt;/code&gt; function. This way, the implementation details remain hidden from the user, and only the essential details are exposed.&lt;/p&gt;

&lt;p&gt;Now coming back to Polymorphism, there are two more common examples, and those are method overriding and overloading.&lt;/p&gt;

&lt;h3&gt;
  
  
  Method Overriding
&lt;/h3&gt;

&lt;p&gt;Method overriding refers to child classes defining their own implementation of methods defined on the parent class. This implementation now gets used instead of the original parent class’s implementation. Let’s take the code we used for inheritance earlier and see how it looks with method overriding:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Hero&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;team&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Batman&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Hero&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Ironman&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Hero&lt;/span&gt;
    &lt;span class="n"&gt;power&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="n"&gt;Hero&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SayTeam&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"My Team is"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;Batman&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SayImBatman&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I'm %s and I'm Batman&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="n"&gt;Ironman&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SayPowerLevel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I'm Ironman and my powerlevel is %d&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;power&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="n"&gt;Batman&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;SayTeam&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I'm Batman and my team is %s&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;b1&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Batman&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Hero&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Justice League"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="s"&gt;"Christian Bale"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;i1&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Ironman&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Hero&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Avengers"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="m"&gt;23&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;b1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SayImBatman&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;b1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SayTeam&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;i1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SayPowerLevel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;i1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SayTeam&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output of this program is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I'm Christian Bale and I'm Batman
I'm Batman and my team is Justice League
I'm Ironman and my powerlevel is 23
My Team is Avengers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The objects of the Batman class now use their own &lt;code&gt;SayTeam&lt;/code&gt; method instead of that of the parent Hero class. Since the Ironman class has no &lt;code&gt;SayTeam&lt;/code&gt; method of its own, its object still uses the method of their parent class. This is what Method Overriding means, child classes “overriding” the methods defined on the parent class.&lt;/p&gt;

&lt;h3&gt;
  
  
  Method Overloading
&lt;/h3&gt;

&lt;p&gt;This refers to the same function being able to take multiple different arguments. These arguments could be different in number or type. Golang provides two ways to achieve this: through variadic functions and the other through interfaces.&lt;/p&gt;

&lt;p&gt;Let’s look at the code for both, which will help you understand better:&lt;/p&gt;

&lt;h4&gt;
  
  
  Using Variadic Functions
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;listMembers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;team&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;members&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;member&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;members&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I'm %s and I'm part of the %s&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;listMembers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Justice League"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Batman"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Superman"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Flash"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;listMembers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Avengers"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Ironman"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Captain America"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here you can “overload” the &lt;code&gt;listMembers&lt;/code&gt; function with any &lt;em&gt;number&lt;/em&gt; of arguments.&lt;/p&gt;

&lt;h4&gt;
  
  
  Using Interfaces
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;saySomething&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;batman&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;batman&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"My name is %s and I'm Batman&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"My powerlevel is %d and I'm Batman&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"I'm Batman"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;saySomething&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Christian Bale"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;saySomething&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;saySomething&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;12.3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output of this program is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;My name is Christian Bale and I'm Batman
My powerlevel is 42 and I'm Batman
I'm Batman
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we are “overloading” the &lt;code&gt;saySomething&lt;/code&gt; method to take arguments of different types. We take an empty interface as an argument, which could be any type, and then check for its type using a switch case and print the output accordingly.&lt;/p&gt;

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

&lt;p&gt;I’m well aware that this was a lengthy read, and if you stuck till the end, I want you to know I’m really happy :) I sincerely hope you learned a lot of new things about Object-Oriented Programming and how to implement it in Golang. I write blogs on different technical concepts on my website, and if you’re interested in learning new things, I’d recommend signing up for my &lt;a href="https://arshsharma.com/newsletter/" rel="noopener noreferrer"&gt;newsletter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>go</category>
      <category>oop</category>
      <category>beginners</category>
    </item>
    <item>
      <title>What Is Network Address Translation (NAT)</title>
      <dc:creator>Arsh Sharma</dc:creator>
      <pubDate>Wed, 04 Dec 2024 18:30:00 +0000</pubDate>
      <link>https://dev.to/rinkiyakedad/what-is-network-address-translation-nat-1epp</link>
      <guid>https://dev.to/rinkiyakedad/what-is-network-address-translation-nat-1epp</guid>
      <description>&lt;p&gt;If you’ve been &lt;a href="https://arshsharma.com/writing/" rel="noopener noreferrer"&gt;following my blog&lt;/a&gt;, you know I recently wrote a three-part series on the &lt;a href="https://arshsharma.com/posts/2024-11-11-osi-layers-one-two/" rel="noopener noreferrer"&gt;OSI Model&lt;/a&gt;. Continuing that trend of networking blogs, in this one, I’ll be covering a very important topic in the world of networking, and that’s NAT (Network Address Translation). I promise this is easier to understand than the OSI Model haha :P&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem That NAT Solves: Shortages of IPv4 Address
&lt;/h2&gt;

&lt;p&gt;Before we learn about what NAT is and does, it’s important to discuss why we even need it in the first place. &lt;a href="https://arshsharma.com/posts/2024-11-25-osi-layer-three/#ipv4-address-structure" rel="noopener noreferrer"&gt;IPv4 addresses&lt;/a&gt; can be either publicly routable or in the private address space for IPv4. Publicly routable addresses are assigned by &lt;a href="https://www.iana.org/" rel="noopener noreferrer"&gt;The Internet Assigned Numbers Authority&lt;/a&gt; (IANA) to &lt;a href="https://www.techtarget.com/whatis/definition/ISP-Internet-service-provider" rel="noopener noreferrer"&gt;ISP&lt;/a&gt;s, which then further allocate them to end users like AWS or even you or me. These publicly routable addresses need to be unique for the internet to function correctly.&lt;/p&gt;

&lt;p&gt;On the other hand, private address space for IPv4 only has to be unique over that particular private network and can be reused across multiple private networks. They include the following ranges: &lt;code&gt;10.0.0.0/8&lt;/code&gt;, &lt;code&gt;172.16.0.0/12&lt;/code&gt;, and &lt;code&gt;192.168.0.0/16&lt;/code&gt;. If you’re not sure how to interpret this range, you should check out &lt;a href="https://arshsharma.com/posts/2024-11-25-osi-layer-three/#subnet-masks" rel="noopener noreferrer"&gt;this particular section&lt;/a&gt; in my previous blog where I explain this. Being able to assign reusable private addresses to devices instead of a unique publicly routable IP address to each device helps overcome the shortage of limited IPv4 addresses.&lt;/p&gt;

&lt;p&gt;But what do we do when a device with a private IP address wants to talk to a device on the public internet? This is the problem that NAT solves. NAT takes a private IP address and figures out how to translate it to a public IP address so that packets can flow over the internet and back to the device in the private network. So NAT basically allows devices on a private network to not occupy the limited number of unique public IP addresses yet still be able to communicate with the internet.&lt;/p&gt;

&lt;p&gt;Let’s see the different types of NATs as that will help you understand them better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Static NAT
&lt;/h2&gt;

&lt;p&gt;Now this would seem counterintuitive to the discussion we were having about how NAT solves the problem of limited IPv4 addresses, but just imagine that you had somehow acquired a bunch of public IPv4 addresses - more than or equal to the number of devices you have on your private network. Well, in this case, you could simply just assign each device a public IP whenever it wants to communicate with the internet.&lt;/p&gt;

&lt;p&gt;The device would send an IP packet to the default gateway (the router), and then the router would have a NAT Table that has a 1:1 mapping of &lt;code&gt;private IP&lt;/code&gt; : &lt;code&gt;public IP&lt;/code&gt;. So it will modify the source IP of this packet to a publicly addressable one and send it to the destination. When the destination sends a response back, the NAT device will again do the translation from the IP the destination device used and translate it back to the private IP of the original source device.&lt;/p&gt;

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

&lt;p&gt;Here’s what the NAT table for this would look like:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Private IP&lt;/th&gt;
&lt;th&gt;Public IP&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;10.3.4.5&lt;/td&gt;
&lt;td&gt;35.23.44.21&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10.3.4.6&lt;/td&gt;
&lt;td&gt;35.23.44.22&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Now you might be wondering, if we have extra public IPs, why not assign them to devices instead of using private IPs and a NAT. Well, there are a couple of reasons for that. First is security. Static NAT offers isolation between the private network and the public internet. Devices have their private IPs, which they can use to communicate internally, and the NAT device comes into the picture when some external communication is required. If you assign public IPs to all devices, then they will be communicating over the public internet with each other as well, thus increasing the attack surface for your network. The other reason is that public IPs can change due to ISP updates, and if you’re using them, that would mean you have to reconfigure every device on your network. With a static NAT, you only need to change the NAT configuration, which is much more convenient.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dynamic NAT
&lt;/h2&gt;

&lt;p&gt;Dynamic NAT is pretty similar to Static NAT, with the difference being that devices aren’t allocated a fixed permanent IP. Instead, there is a pool of public IPs, and one gets allotted temporarily to the device that needs it. The &lt;code&gt;private IP&lt;/code&gt; : &lt;code&gt;public IP&lt;/code&gt; mapping is temporary. That means two devices could share the same public IP but at different times. But it also means that if all the IPs in the pool of public IPs have already been allocated and a device tries to communicate with the internet, there won’t be any IPs left to assign to it, and it will fail to access the internet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Port Address Translation
&lt;/h2&gt;

&lt;p&gt;Port Address Translation is my favorite type of NAT. It allows a large number of private devices to share one public IP address. This is likely what’s being used on your home network as well.&lt;/p&gt;

&lt;p&gt;If the name didn’t already give you a hint, PAT uses ports to manage multiple private IP addresses and map them to a single public IP address. Any time a packet reaches the NAT device, it assigns it the one public IP it has available and a random port (refer to the &lt;a href="https://arshsharma.com/posts/2024-11-28-osi-layer-four-seven/#tcp-segments" rel="noopener noreferrer"&gt;blog on Segments&lt;/a&gt; if you aren’t familiar with ports). This random port is what allows multiple devices, even with the same IP, to communicate with the public internet while still being seen as different devices. If the port number were the same for all these devices, then there would’ve been no way to differentiate between the traffic addressed to each device, and this wouldn’t work.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ygf96yu20jxaiqpeviu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ygf96yu20jxaiqpeviu.png" alt="diagram showing how Port Address Translation works" width="800" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here’s what a NAT table looks like when using Port Address Translation.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Private IP&lt;/th&gt;
&lt;th&gt;Private Port&lt;/th&gt;
&lt;th&gt;Public IP&lt;/th&gt;
&lt;th&gt;Public Port&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;10.3.4.5&lt;/td&gt;
&lt;td&gt;7465&lt;/td&gt;
&lt;td&gt;35.23.44.21&lt;/td&gt;
&lt;td&gt;2434&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10.3.4.6&lt;/td&gt;
&lt;td&gt;6979&lt;/td&gt;
&lt;td&gt;35.23.44.21&lt;/td&gt;
&lt;td&gt;3244&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This NAT table maintains the extra fields related to the private (original) port and public (assigned) port for each device in addition to the IP fields we saw in the NAT table for Static NAT. It then does the appropriate translation for the packets as they come and go.&lt;/p&gt;

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

&lt;p&gt;In this article, we studied what Network Address Translation is, what problems it solves, and the three common types of NATs. I hope you now have an understanding of how different NAT types work and when each of them is useful. I’ll be covering a couple of other networking topics in the coming blogs, so subscribe to my &lt;a href="https://arshsharma.com/newsletter/" rel="noopener noreferrer"&gt;newsletter&lt;/a&gt; if you’re interested in remaining up to date about them!&lt;/p&gt;

</description>
      <category>networking</category>
    </item>
    <item>
      <title>Understanding the OSI Model: Layer 4 to Layer 7</title>
      <dc:creator>Arsh Sharma</dc:creator>
      <pubDate>Wed, 27 Nov 2024 18:30:00 +0000</pubDate>
      <link>https://dev.to/rinkiyakedad/understanding-the-osi-model-layer-4-to-layer-7-4ol7</link>
      <guid>https://dev.to/rinkiyakedad/understanding-the-osi-model-layer-4-to-layer-7-4ol7</guid>
      <description>&lt;p&gt;Welcome to the final blog in the series on the &lt;a href="https://arshsharma.com/posts/2024-11-11-osi-layers-one-two/" rel="noopener noreferrer"&gt;OSI Model&lt;/a&gt;. In the last blog, we discussed &lt;a href="https://arshsharma.com/posts/2024-11-25-osi-layer-three/" rel="noopener noreferrer"&gt;Layer 3&lt;/a&gt; and how IP packets move from source to destination. In this one, we’ll cover the shortcomings of Layer 3 and then discuss all the Layers from 4 to 7!&lt;/p&gt;

&lt;h2&gt;
  
  
  Problems with Layer 3
&lt;/h2&gt;

&lt;p&gt;While Layer 3 allows devices to communicate across different networks, there are still some problems that can occur with it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In an ideal world, &lt;a href="https://arshsharma.com/posts/2024-11-25-osi-layer-three/#how-ip-packets-move" rel="noopener noreferrer"&gt;packets&lt;/a&gt; would reach their destination, but it’s not uncommon for them to get lost. If you remember, we discussed in the last blog that packets have a time to live or hop limit after which they are discarded. So if, for any reason, a packet isn’t able to reach the destination before this, it will be discarded and lost.&lt;/li&gt;
&lt;li&gt;It’s not necessary for all packets to follow the same route. This means that different packets can reach the destination at different times and could be “out of order.” This is a big problem if your application requires packets to be delivered in order, like, for example, when streaming a video over the internet, we need things to be delivered in sequence.&lt;/li&gt;
&lt;li&gt;Layer 3 doesn’t offer separate communication channels. Packets have a source and destination IP but no way to differentiate them by app or channel. This means that if you have two applications running, there is no way to identify between the packets meant for one app vs. the other.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Layer 4 - Transport Layer
&lt;/h2&gt;

&lt;p&gt;Layer 4 fixes the problems we discussed above by building on top of Layer 3. Two common Layer 4 protocols are TCP (Transmission Control Protocol) and UDP (User Datagram Protocol). Both of them add features over IP (Internet Protocol). You’ll often see “&lt;a href="https://www.cloudflare.com/learning/ddos/glossary/tcp-ip/" rel="noopener noreferrer"&gt;TCP/IP&lt;/a&gt;” written in places, and what this means is that TCP (Layer 4) which is running on top of IP (Layer 3). Let’s learn more about TCP to understand the benefits of Layer 4.&lt;/p&gt;

&lt;h3&gt;
  
  
  TCP Segments
&lt;/h3&gt;

&lt;p&gt;TCP introduces Segments, which are another container for data, just like &lt;a href="https://arshsharma.com/posts/2024-11-25-osi-layer-three/#ip-packet-structure" rel="noopener noreferrer"&gt;Packets&lt;/a&gt; and &lt;a href="https://arshsharma.com/posts/2024-11-11-osi-layers-one-two/#layer-2---data-link-layer" rel="noopener noreferrer"&gt;Frames&lt;/a&gt;. Layer 4 takes data provided to it and chops that up into Segments, which are encapsulated in IP Packets. Segments have no information about the source and destination IP address; that is taken care of by the Packets which encapsulate them.&lt;/p&gt;

&lt;p&gt;But just like Packets have Source and Destination IP Address, TCP Segments have Source and Destination Ports. Ports are what give the ability to have different channels of communication between the same devices. One application could be running on one port, whereas a different port can be used by another application. This way, when packets are decapsulated, the device knows which application to send the segment to based on the port number.&lt;/p&gt;

&lt;p&gt;When using TCP, a connection is established between a random port on the client machine and a known port on the server. Once established, both can communicate with each other. Segments are what make this connection possible.&lt;/p&gt;

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

&lt;p&gt;When you see this stream or channel between devices, it’s important to understand that this channel isn’t an actual channel but a way of visualizing things. The “channel” simply exists thanks to segments. From a Layer 4 perspective, we’ll have two sets of segments. One with a source port of 234 and a destination of 12789 and the other with the reverse. From a Layer 4 perspective, these are two different things.&lt;/p&gt;

&lt;p&gt;Segments also have a Sequence Number, which means their order can be identified and maintained. So even if packets arrive out of order, the segments can be reordered. This also means that if a packet isn’t received for some reason, the destination machine can simply request for that sequence number, and another segment can be sent in a different packet by the source.&lt;/p&gt;

&lt;p&gt;TCP Segments also have an Acknowledgment Number. This tells the sender what is the next byte expected by the receiver so that the sender can know the last received byte. In case an IP packet got “lost,” then this way, the sender will know it wasn’t received and will send it again.&lt;/p&gt;

&lt;p&gt;Segments also have “Flags N Things.” These are flags that can be set to make changes to the connection: things like closing the connection (FIN), synchronizing sequence numbers (SYN), and for acknowledgements (ACK). More on this in the next section.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  TCP 3 Way Handshake
&lt;/h3&gt;

&lt;p&gt;Before any data can be transferred using TCP, a connection needs to be established. And this uses a &lt;a href="https://www.coursera.org/articles/three-way-handshake" rel="noopener noreferrer"&gt;three-way handshake&lt;/a&gt;. The first step of this is the client sending a segment with a random sequence number to the server. The flag for this is SYN. The server then receives this segment and responds with its own segment. This segment that it responds with has its own random sequence number, but the acknowledgment number is the sequence number it received from the client + 1, effectively telling the client that that’s the next sequence it expects. The flag for this is SYN ACK since it’s used to synchronize sequence numbers but also to acknowledge the receipt of the client sequence number.&lt;/p&gt;

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

&lt;p&gt;The client then receives this segment and then, to acknowledge to the server that it received that information, sends the corresponding sequence and acknowledgment numbers. This is of type ACK, basically acknowledging that things are good to go. At this point, both the client and server have acknowledged the initial sequence values sent by each other. And from this point on, data can flow between the two. Any time either side sends data, they increment the sequence by 1, and the other side acknowledges the sequence value + 1.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 5 - Session Layer
&lt;/h2&gt;

&lt;p&gt;The lines start to get kind of blurry between Layer 4 and Layer 5. Layer 4 provides the foundation for a channel of communication, but Layer 5 builds on top of this and adds additional functionality. Layer 5 is responsible for establishing, maintaining, and terminating the communication sessions between applications. It introduces the concept of checkpoints, which basically ensure that if there is an interruption in a session for whatever reason, the session is able to resume from the last checkpoint instead of starting over. &lt;a href="https://www.javatpoint.com/session-layer-in-osi-model" rel="noopener noreferrer"&gt;Session Layer&lt;/a&gt; also controls how the communication will proceed between the devices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;simplex: one-way communication&lt;/li&gt;
&lt;li&gt;half-duplex: two-way communication that can only flow in one direction at a time&lt;/li&gt;
&lt;li&gt;full-duplex: simultaneous two-way communication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some commonly used Layer 5 protocols are RPC (Remote Procedure Call), NetBIOS, and SMB (Server Message Block).&lt;/p&gt;

&lt;p&gt;Another thing Layer 5 takes care of is distinguishing user sessions. Layer 5 is able to identify a user independent from the address of the layers below it, such as MAC address, IP address, and ports. A very common example of this is the cookies we see in modern browsers.&lt;/p&gt;

&lt;h3&gt;
  
  
  How HTTP Cookies Work at Layer 5
&lt;/h3&gt;

&lt;p&gt;Browser &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies" rel="noopener noreferrer"&gt;HTTP cookies&lt;/a&gt; are considered to be at Layer 5. They are responsible for managing and maintaining user sessions. Let’s say you’re connected to Wi-Fi A and then switch to Wi-Fi B. In doing so, your IP address and port both are likely to change. How is it still that you don’t have to log in to whatever website you were already logged into? That’s all thanks to cookies.&lt;/p&gt;

&lt;p&gt;Cookies are arbitrary text strings that store user information created by the server. When a user logs in to the website, the server generates one of these cookies and sends it to the user, and it stays with the user. So even when the user switches to a new Wi-Fi network with new Layer 2, 3, 4 information, that user still has the same cookie stored on their device. So the website can still identify this user independently of the Layer 2, 3, 4 address. This is one of the ways how Layer 5 plays a role in modern-day networking.&lt;/p&gt;

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

&lt;p&gt;Do note that this is in the context of HTTP. HTTP uses HTTP cookies at Layer 5 to store user session info. A different protocol might have a different implementation (or none) for Layer 5. For example, FTP (File Transfer Protocol) has no implementation of Layer 5, which means it has no way of identifying user sessions other than IP address or ports. This implies that if your network changes, you’ll have to log back in to the FTP server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 6 - Presentation Layer
&lt;/h2&gt;

&lt;p&gt;The Presentation Layer of the OSI model is all about how to interpret the raw data. The data received by Layer 6 is all in the form of 1s and 0s. It needs to know what protocol to use to interpret this data: it could be ASCII characters represented as binary, or it might be a JPEG file, or it could be JSON data. All of this translation to the correct data format is taken care of by Layer 6, which then passes this information to the Application Layer (Layer 7). This is really important because we want to make sure that the data sent by the Application Layer of one device is able to be read by the Application Layer of another device.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzznen1ewz8clmyhtiduy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzznen1ewz8clmyhtiduy.png" alt="how translation takes place at layer 6" width="800" height="96"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 7 - Application Layer
&lt;/h2&gt;

&lt;p&gt;Layer 7 (the topmost layer!) of the OSI model provides the interface that users use to interact with the applications that have access to the network. It includes protocols like HTTP and HTTPS, which we use for browsing the web, FTP and TFTP for file sharing, SSH for remote access, among many others. To continue the example above, while Layer 6 converted the binary to ASCII characters, someone still needs to know what “G,” “E,” and “T” together mean and what action to take on seeing those. That is the role fulfilled by Layer 7.&lt;/p&gt;

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

&lt;p&gt;Congrats! You made it to the end of this three-part series on the &lt;a href="https://arshsharma.com/posts/2024-11-11-osi-layers-one-two/" rel="noopener noreferrer"&gt;OSI Model&lt;/a&gt;. I really hope you learned as much as I did when learning about this on my own. This series was a way for me to distill down in simpler terms the things I found confusing when studying the OSI model. One final thing I want you to take away from this is that you shouldn’t get too caught up in putting things into layers when you come across networking concepts. Fussing about what belongs in which layer isn’t the point of this model. The OSI model is meant to help you visualize how two devices can communicate across the internet, and the biggest takeaway for you should be the concept of abstraction in this model: how each layer has a responsibility, and that means the other layers can abstract over it and not worry about that responsibility.&lt;/p&gt;

&lt;p&gt;Thanks for reading! If you found this series useful, consider signing up for my &lt;a href="https://arshsharma.com/newsletter/" rel="noopener noreferrer"&gt;newsletter&lt;/a&gt; to get notified whenever I post something!&lt;/p&gt;

</description>
      <category>networking</category>
      <category>osi</category>
    </item>
    <item>
      <title>Understanding the OSI Model: Layer 3</title>
      <dc:creator>Arsh Sharma</dc:creator>
      <pubDate>Sun, 24 Nov 2024 18:30:00 +0000</pubDate>
      <link>https://dev.to/rinkiyakedad/understanding-the-osi-model-layer-3-10gk</link>
      <guid>https://dev.to/rinkiyakedad/understanding-the-osi-model-layer-3-10gk</guid>
      <description>&lt;p&gt;In the last blog, we looked at &lt;a href="https://arshsharma.com/posts/2024-11-11-osi-layers-one-two/" rel="noopener noreferrer"&gt;Layer 1 and Layer 2&lt;/a&gt; of the OSI Model. While Layer 2 (Data Link Layer) adds a lot of improvements over Layer 1, like the ability to identify individual devices in the local network with the help of MAC addresses, it still only works best over local area networks (LAN). In this blog, let’s see some shortcomings of Layer 2 and how Layer 3 of the OSI Model improves upon them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problems with Layer 2
&lt;/h2&gt;

&lt;p&gt;Layer 2 makes it easy to communicate between devices on the same network, but it has some problems when it comes to communicating between two different networks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MAC addresses aren’t suitable for inter-network connectivity. Given a MAC address, there’s no way to identify if it’s of a device on the same local network or outside the network. Layer 3 fixes this with IP addresses (more on that soon).&lt;/li&gt;
&lt;li&gt;Layer 2 networks using a protocol, for example, Ethernet, can only be connected via the same protocol. This means if you need to communicate between two devices really far away using just a Layer 2 network, you’d need a really, really long Ethernet wire (or some very strong radio signals).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since the internet connects different devices all across the globe, we need something more that fixes these problems. And this is where Layer 3 comes to save the day :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 3 - Network Layer
&lt;/h2&gt;

&lt;p&gt;Layer 3, or the Network Layer of the OSI model, is responsible for transferring data between devices on two different networks. Layer 3 has a few different protocols, but we’ll limit our discussion to the most common one to make understanding this easier - and that’s the &lt;a href="https://www.cloudflare.com/learning/network-layer/internet-protocol/" rel="noopener noreferrer"&gt;Internet Protocol&lt;/a&gt; (IP).&lt;/p&gt;

&lt;p&gt;Just like Layer 2 added MAC addresses, Layer 3 adds IP addresses, which are cross-network addresses and can be used to identify devices on a network outside of your Local Area Network (LAN). IP packets are moved from one source IP address to the destination IP address via a bunch of intermediate networks. Routers are the Layer 3 devices responsible for this.&lt;/p&gt;

&lt;h2&gt;
  
  
  How IP Packets Move
&lt;/h2&gt;

&lt;p&gt;Let’s understand how routers move IP packets from one network to another. Let’s take Router A and Router B, which are part of their local area networks that use Ethernet. When a device on Router A’s local network needs to send some data to a device on Router B’s network, it encapsulates that data in a frame and sends it to Router A via Layer 2. Router A takes the IP packet out of the frame and sees that it needs to be sent to Router B’s network.&lt;/p&gt;

&lt;p&gt;Now understand that while Router A and Router B are part of individual local networks, the two of them themselves also form a Layer 2 network, which might be connected by Wi-Fi (a different protocol than Ethernet). In this case, there are three Layer 2 networks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Router A and devices connected to it via Ethernet&lt;/li&gt;
&lt;li&gt;Router B and devices connected to it via Ethernet&lt;/li&gt;
&lt;li&gt;Router A and Router B connected via Wi-Fi&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these Layer 2 networks is using the same protocol to connect devices in that network, so it’s not a problem.&lt;/p&gt;

&lt;p&gt;So Router A again encapsulates the IP packet in a new frame and sends it to Router B via Layer 2 (using radio waves this time instead of Ethernet). Router B takes out the packet from the frame, sees it’s for a device on its network, and puts it in a new Ethernet frame again to send it to the device. So, long story short, we keep changing the frame around the packet so that we can use a different protocol when we need to do cross-network communication. The IP packet itself never changes and remains constant throughout the journey.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  IP Packet Structure
&lt;/h2&gt;

&lt;p&gt;There are two versions of the Internet Protocol that are being used: &lt;a href="https://www.uptrends.com/what-is/ipv4" rel="noopener noreferrer"&gt;IPv4&lt;/a&gt; and &lt;a href="https://www.cisco.com/c/en/us/solutions/ipv6/overview.html" rel="noopener noreferrer"&gt;IPv6&lt;/a&gt;. We won’t go into too much detail about their structures, but some important parts to know are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Source IP Address&lt;/strong&gt; : IP address of the device that generates the packet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Destination IP Address&lt;/strong&gt; : IP address of the intended destination for the packet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Protocol&lt;/strong&gt; : IP is a Layer 3 protocol, which means the data contained in it is provided by Layer 4. This field stores which Layer 4 protocol was used. Examples are ICMP, TCP, UDP. This is important for the Layer 3 component at the destination to know which Layer 4 protocol to pass the data into.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data&lt;/strong&gt; : This is provided by Layer 4.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time to Live&lt;/strong&gt; : Since IP packets move between many different networks between the source and destination, it is important to define a maximum number of “hops” (jumps between different networks) they can make. If the limit is crossed and they’re not able to reach their destination, they are discarded. If there is no such limit, then we would have a lot of stray IP packets.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The difference between IPv4 and IPv6 is that IPv6 has bigger addresses for source and destination. This allows more possible IPv6 addresses. Another difference is that Time to Live is called Hop Limit for IPv6. Both of them are the same functionality-wise, though.&lt;/p&gt;

&lt;h2&gt;
  
  
  IPv4 Address Structure
&lt;/h2&gt;

&lt;p&gt;Now let’s understand what an IP address looks like. An example of an IP address is: &lt;code&gt;124.12.23.9&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So basically four numbers, where each number can be from 0 to 255. Why 255? Because these are 8-bit numbers. And the biggest 8-bit number is &lt;code&gt;11111111&lt;/code&gt; (all bits being 1), which in decimal notation is 255.&lt;/p&gt;

&lt;p&gt;Okay, so now that we know what an IP address looks like, let’s understand how devices know whether they need to move an IP packet to a local address or to a different network. This is where subnet masks come into play. These subnet masks are configured on Layer 3 devices along with IP addresses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Subnet Masks
&lt;/h2&gt;

&lt;p&gt;There are two very common ways to denote a subnet mask. One is using dotted decimal notation like we saw for IP addresses above, and the other is using a &lt;a href="https://aws.amazon.com/what-is/cidr/" rel="noopener noreferrer"&gt;Classless Inter-Domain Routing&lt;/a&gt; (CIDR) notation. Let’s understand this with an example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let’s suppose the subnet mask is &lt;code&gt;255.255.0.0&lt;/code&gt;, which in CIDR notation is written as &lt;code&gt;/16&lt;/code&gt;. A subnet mask denotes which part of the IP address is reserved for the network and which is for the individual host machines. When converted to binary, the 1s in a subnet mask denote the network, whereas the rest are available for the hosts. So both &lt;code&gt;255.255.0.0&lt;/code&gt; and &lt;code&gt;/16&lt;/code&gt; translate to &lt;code&gt;11111111.11111111.00000000.00000000&lt;/code&gt; (16 ones starting from the left). This means that given an IP address like &lt;code&gt;124.12.23.9&lt;/code&gt;, the &lt;code&gt;124.12&lt;/code&gt; part denotes the network, and &lt;code&gt;23.9&lt;/code&gt; points to a specific machine.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now I think you can start to see how machines identify whether the IP address is on their local network or part of another network. For the above example, an IP address from the range &lt;code&gt;124.12.0.0&lt;/code&gt; to &lt;code&gt;124.12.255.255&lt;/code&gt; means that the device is on the same network, whereas any device with an IP address where the network part isn’t the same (for example, &lt;code&gt;111.12.0.3&lt;/code&gt;) is on a different network.&lt;/p&gt;

&lt;h2&gt;
  
  
  Default Gateway
&lt;/h2&gt;

&lt;p&gt;On a local network of devices, the router (Layer 3 device) connected to the devices serves as the “Default Gateway” for those devices. That means whenever the devices don’t know where to send the packet (that means it needs to be sent to a device not on the local network), they forward it to the router. Routers maintain a route table, which tells what the next hop or the target should be for a particular range of IP addresses. For example:&lt;/p&gt;

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

&lt;p&gt;In this example above, packets intended for any IP addresses from &lt;code&gt;23.34.0.0&lt;/code&gt; to &lt;code&gt;23.34.255.255&lt;/code&gt; get forwarded to &lt;code&gt;23.34.0.1&lt;/code&gt;, which then takes care of routing them forward to the final destination. If a route isn’t in the table, then it matches &lt;code&gt;0.0.0.0/0&lt;/code&gt; as the destination and is sent to a different network where another route table is responsible for making it reach its destination. And this is how packets hop from network to network and reach the device they’re intended for.&lt;/p&gt;

&lt;p&gt;Now we know that Layer 3 devices encapsulate IP packets in frames to be sent over Layer 2 networks. So how does the frame know what MAC address to take the packet to? This is where the Address Resolution Protocol (ARP) comes into the picture. The ARP components send a broadcast to all devices (FF-FF-FF-FF-FF-FF), basically asking which of them has that particular IP address. When the correct device receives it, it replies back with its MAC address. Then the Layer 3 IP packet is put inside a Layer 2 frame, which has the source and destination MAC addresses.&lt;/p&gt;

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

&lt;p&gt;Pheww. So I know we covered a lot in this one, but I do hope that you found it as fun and fascinating as I did when I was learning about all this stuff. It’s pretty cool to understand how the things we take for granted (the internet) actually work behind the scenes. Take some time to digest this, and I’ll see you in the next one, where we’ll cover Layer 4 and Layer 5 of the OSI model. 🙂&lt;/p&gt;

&lt;p&gt;Sign up for my &lt;a href="https://arshsharma.com/newsletter/" rel="noopener noreferrer"&gt;newsletter&lt;/a&gt; to avoid missing when I upload a new blog!&lt;/p&gt;

</description>
      <category>networking</category>
      <category>osi</category>
    </item>
    <item>
      <title>Understanding the OSI Model: Layer 1 and Layer 2</title>
      <dc:creator>Arsh Sharma</dc:creator>
      <pubDate>Sun, 10 Nov 2024 18:30:00 +0000</pubDate>
      <link>https://dev.to/rinkiyakedad/understanding-the-osi-model-layer-1-and-layer-2-14gj</link>
      <guid>https://dev.to/rinkiyakedad/understanding-the-osi-model-layer-1-and-layer-2-14gj</guid>
      <description>&lt;p&gt;The OSI (Open Systems Interconnection) Model is a framework that helps understand how communication between computers takes place in a network. It consists of 7 layers, and each layer builds on top of the ones below it and adds additional functionality. In this blog, we’ll understand the different layers part of this model, starting from Layer 1 at the bottom. All layers rely on the layers below them to continue functioning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 1 - Physical Layer
&lt;/h2&gt;

&lt;p&gt;Layer 1 of the OSI model deals with how devices communicate across a shared physical medium. For example, if devices are connected by an Ethernet cable, then the shared medium is the cable; if devices are connected by Wi-Fi, then the shared physical medium is radio frequencies.&lt;/p&gt;

&lt;p&gt;When communication takes place over the physical medium in Layer 1, it is in the form of raw bit streams (that is, 0s and 1s). For example, if devices are connected by a cable, then a certain voltage (say +1V) can be defined as binary 1, and another voltage (say -1V) could be defined as binary 0. All devices part of this Layer 1 network need to have this shared understanding, that is, have the same standards in order to communicate.&lt;/p&gt;

&lt;p&gt;A hub is a device that can be used to connect multiple Layer 1 devices together and allow communication between them. Hubs take electrical signals on one port and distribute them across all other ports without any checks.&lt;/p&gt;

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

&lt;p&gt;Important things to note about the Physical Layer are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;There are no individual device addresses. A device cannot specifically address traffic to another device part of a Layer 1 network. It is broadcasted to all the devices part of the network connected by a hub.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If multiple devices transmit at once, a collision will occur. Layer 1 has no way of detecting collisions. And since anything received on any port of a layer 1 hub is transmitted to every other port, the collisions get repeated across all devices as well.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There is no method to control which devices can transmit over Layer 1 (also called having “no media access control”).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So I think you can start to see that while the Physical Layer of the OSI model forms the foundation of network communication, it on its own isn’t very useful. As you connect more Layer 1 devices together with the help of a hub, the chances of collisions increase even more. Let’s see how Layer 2 fixes this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 2 - Data link Layer
&lt;/h2&gt;

&lt;p&gt;The Data link Layer of the OSI model builds on top of the Physical Layer. This means a Layer 2 network requires a functional Layer 1 network to operate.&lt;/p&gt;

&lt;p&gt;Layer 2 devices have a Media Access Control (MAC) address. MAC addresses for devices are unique and generally not software-assigned. Instead, they’re attached to that particular piece of hardware.&lt;/p&gt;

&lt;p&gt;Layer 2 also introduces the concept of “frames,” which are a way of sending information over the network. Let’s see the parts of a frame:&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Preamble: This is the start of a frame. Knowing the start allows devices to figure out where the other parts of the frame are.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Destination MAC address: MAC address of the device the frame is intended to be received by. If the MAC address is FF-FF-FF-FF-FF-FF (all Fs), that means it’s meant to be received by all the devices on the network, also known as a broadcast.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Source MAC address: This is important because it allows the receiving devices to send back replies to the device that was the source of the frame.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ether type: This is used to specify which Layer 3 protocol is putting the data inside the frame. A common example of this is IP (Internet Protocol).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Payload: This is the data the device wants to send. Layer 3 generates some data, which is put inside the payload in the frame (a process called encapsulation). The frame then delivers the data to different Layer 2 devices. On the destination Layer 2 device, the frame is analyzed, and the Layer 3 data is extracted and given back to the Layer 3 at the destination device. Please note that the frame is still being transferred by Layer 1. Layer 1 sees the frame as just another piece of data to send over the physical medium.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Frame check sequence: This is used to identify errors in the frame and lets the destination check if any corruption has occurred.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Layer 2 vs Layer 1 of the OSI Model
&lt;/h2&gt;

&lt;p&gt;We just learned that Layer 2 uses Layer 1 to transport frames. How does that solve the problems of collisions we discussed earlier in Layer 1? This is because Layer 2 provides controlled access to the physical medium. Layer 2 devices have the ability to check if any carrier (signal) is already present or not and then accordingly instruct Layer 1 to do any transmission. This is how collisions are avoided. This method is called Carrier Sense Multiple Access (CSMA). Also note that Layer 1 does indeed send all frames to all connected devices. It’s just that Layer 2 devices analyze those frames and discard them if they’re not the intended recipient after checking the MAC address.&lt;/p&gt;

&lt;p&gt;Just like a hub is used to connect multiple devices in a Layer 1 network, for Layer 2, we use a device called “Switch”. This is because hubs don’t understand frames. If a Layer 2 device sends a frame to a hub, it would repeat it to all connected devices. This is inefficient and can be solved by a device that understands MAC addresses: the switch.&lt;/p&gt;

&lt;p&gt;Switches maintain a MAC Address Table, which starts off empty. But over time, as they receive frames, they populate the table. The table stores which device (by storing its MAC address) is connected to which port. Once this is populated, they don’t blindly forward frames like hubs. So if a frame is transmitted, the switch will send it only to the port whose MAC address is the intended destination. If in case the destination MAC address isn’t in the table, the frame will be transported to all ports. With switches, even if a collision occurs, it remains isolated on the port it occurred on instead of being transmitted to all ports, as in the case of hubs.&lt;/p&gt;

&lt;p&gt;Switches also have an aging time for MAC addresses. When switches first store a MAC address they store it with a timestamp. Anytime the switch detects some traffic from this stored MAC address it updates the timestamp. If after a fixed amount of time there has been no traffic detected from the last saved timestamp in the switch for that MAC address the switch removes entries for it. This is known as the aging process for MAC addresses in a switch.&lt;/p&gt;

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

&lt;p&gt;In this blog, we learned about Layer 1 and Layer 2 of the OSI model. Layer 2 devices are still connected to each other over a Local Area Network (LAN). But how do you send data from a Layer 2 device part of a LAN in India to one in the US? This is where Layer 3 starts to come into the picture. To avoid making the blog lengthy (and give you some time to digest all this information), I’ll be covering that in the next blog. I hope you found this one useful, and if you’d like to stay updated on whenever I post a new blog, consider signing up for my newsletter!&lt;/p&gt;

</description>
      <category>networking</category>
    </item>
    <item>
      <title>AWS Root User vs IAM Users</title>
      <dc:creator>Arsh Sharma</dc:creator>
      <pubDate>Fri, 01 Nov 2024 18:30:00 +0000</pubDate>
      <link>https://dev.to/rinkiyakedad/aws-root-user-vs-iam-users-53in</link>
      <guid>https://dev.to/rinkiyakedad/aws-root-user-vs-iam-users-53in</guid>
      <description>&lt;p&gt;Welcome to the first in a series of blog posts about AWS! Throughout this series, I’ll be covering various AWS topics as &lt;a href="https://x.com/RinkiyaKeDad" rel="noopener noreferrer"&gt;I prepare&lt;/a&gt; for the &lt;a href="https://aws.amazon.com/certification/certified-solutions-architect-associate/" rel="noopener noreferrer"&gt;AWS Solutions Architect&lt;/a&gt; exam. I thought what better place to start than with one of the most fundamental steps when beginning with AWS: creating an account. In this post, I’ll discuss the root user that’s created with your AWS account and how it differs from IAM users.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Root User in AWS?
&lt;/h2&gt;

&lt;p&gt;When you first create an AWS account, you’ll enter an email, and AWS will create a root user with this email by default. Initially, this root user is used to sign in and access your AWS account. Root user is the first user identity in an AWS account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdo46x8a1ndq5ctw6ddz8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdo46x8a1ndq5ctw6ddz8.png" alt="loggin in AWS as the root user" width="800" height="477"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every AWS account has only one &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html" rel="noopener noreferrer"&gt;root user&lt;/a&gt; associated with it, which has the permissions to do anything and everything in the account. The permissions of the root user &lt;strong&gt;&lt;em&gt;cannot&lt;/em&gt;&lt;/strong&gt; be restricted. Because of these reasons, it is not recommended that you use this root user unless absolutely necessary (for things like changing billing information, your AWS support plan, etc., that is, things only root users can do).&lt;/p&gt;

&lt;p&gt;Other than these root user specific tasks, whenever you want to interact with your AWS account, it is recommended you do so via an IAM user. It is very common to create an IAM user with admin privileges right after creating your AWS account and use that IAM user instead of the root user for any subsequent interactions with the AWS account.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is an IAM User in AWS?
&lt;/h2&gt;

&lt;p&gt;IAM stands for Identity and Access Management, and it’s a way in AWS to create users (among other things as well, but more on that later). &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html" rel="noopener noreferrer"&gt;IAM users&lt;/a&gt;, unlike the root user who uses email to sign in, use an account ID and their IAM username and password to log into the AWS console.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvi16bapwj0st22wqp153.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvi16bapwj0st22wqp153.png" alt="loggin in AWS as an IAM user" width="800" height="475"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can create as many IAM users for your AWS account as you want. You can (and should) give them different levels of permissions. But it is a common practice to have one or two IAM users with &lt;a href="https://kloudle.com/academy/how-to-create-an-iam-admin-user-in-aws/" rel="noopener noreferrer"&gt;admin privileges&lt;/a&gt; which are to be used by people managing the overall AWS infra in your organization.&lt;/p&gt;

&lt;p&gt;These IAM users with admin privileges can do almost everything you would want to do within AWS. AWS recommends that you use them instead of ever using the root user. This is because it’s in line with the &lt;a href="https://www.paloaltonetworks.com/cyberpedia/what-is-the-principle-of-least-privilege" rel="noopener noreferrer"&gt;principle of least privilege&lt;/a&gt;. A root user still has more permissions to do things which an IAM admin user won’t, things like deleting your AWS account, subscribing to a different support tier (which would cost you more money), and because of these reasons if the root user credentials are compromised you’ll be in much greater trouble. You can find a complete list of the extra things a root user can do as compared to an IAM user with admin privileges &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html#root-user-tasks" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So long story short, as soon as you create your AWS account, use the root user credentials to create an IAM user with admin privileges and henceforth use this IAM user for any further resources/users you want to create in your AWS account.&lt;/p&gt;

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

&lt;p&gt;So to sum up here are the differences between the root user vs. an IAM user in AWS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The root user has unrestricted access and can do &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html#root-user-tasks" rel="noopener noreferrer"&gt;much more&lt;/a&gt; than an IAM user (even with admin privileges). This includes important things like changing your support plan, billing information, closing your account, enabling or disabling security controls like MFA.&lt;/li&gt;
&lt;li&gt;There’s only one root user per AWS account whereas you can have multiple IAM users.&lt;/li&gt;
&lt;li&gt;The root user’s permissions can’t be restricted at all, and it can do anything related to your account. IAM user permissions can be limited with the help of &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html" rel="noopener noreferrer"&gt;policies&lt;/a&gt; (will cover in detail in a future blog)&lt;/li&gt;
&lt;li&gt;You should avoid using the root user unless absolutely necessary for a task. Instead, use an IAM user with admin privileges.&lt;/li&gt;
&lt;li&gt;IAM users don’t have access to the Billing and Management Console by default, even if you attach the right policies. The root user needs to specifically enable access to the Billing and Management Console for IAM users, only after which they can access it (assuming they have the correct policies attached to them).&lt;/li&gt;
&lt;li&gt;Root user signs in using the email used when creating the AWS account, whereas the IAM users have a username which they login with.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you liked this guide and would like to stay updated on when I post next in this AWS series, consider signing up for my newsletter: &lt;a href="https://arshsharma.com/newsletter/" rel="noopener noreferrer"&gt;https://arshsharma.com/newsletter/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>devops</category>
    </item>
    <item>
      <title>Coding Bugs with ChatGPT</title>
      <dc:creator>Arsh Sharma</dc:creator>
      <pubDate>Wed, 31 Jul 2024 18:30:00 +0000</pubDate>
      <link>https://dev.to/rinkiyakedad/coding-bugs-with-chatgpt-39h2</link>
      <guid>https://dev.to/rinkiyakedad/coding-bugs-with-chatgpt-39h2</guid>
      <description>&lt;p&gt;Recently I was tinkering around with creating a &lt;a href="https://developer.chrome.com/docs/extensions" rel="noopener noreferrer"&gt;Chrome extension&lt;/a&gt;. Not having a lot of experience with this, I did what the cool kids these days are doing: I decided to use &lt;a href="https://openai.com/chatgpt/" rel="noopener noreferrer"&gt;ChatGPT&lt;/a&gt; for helping me write code. And don’t get me wrong, ChatGPT (or other AI tools for that matter) does a decent job of helping you create things and spot bugs. But it’s a gun that can easily backfire if you don’t know what you’re doing with it. This blog is going to be about one such incident that happened to me when working on this project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Toggle Functionality to the Chrome Extension
&lt;/h2&gt;

&lt;p&gt;The feature I wanted to work on was adding an on/off switch for the Chrome extension. This is a common feature in a lot of extensions where, when you click the extension icon from the menu, you see a button that lets you toggle the state of the extension. I couldn’t find any step-by-step guide on how to do this online, and I was feeling a little lazy to figure it out on my own by reading docs, so I decided to take the help of our friendly neighborhood AI.&lt;/p&gt;

&lt;p&gt;Before I show you the code, let me give you some &lt;a href="https://itnext.io/all-youll-ever-need-to-know-about-chrome-extensions-ceede9c28836" rel="noopener noreferrer"&gt;basic idea&lt;/a&gt; about how Chrome extensions work, in case you’re unfamiliar. There are three main files you need to know about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;popup: This has the code related to the window you see when you click the extension icon from the extensions tab in the top right corner of your browser window.&lt;/li&gt;
&lt;li&gt;content: This is the stuff that gets rendered on a particular browser page. For example, the extension could add elements, change the color of things, or anything else.&lt;/li&gt;
&lt;li&gt;background: This is the stuff that keeps running in the background. It has nothing to do with the page you are on or the user clicking the extension to open the popup. This is very useful to implement cross-page stuff.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So here’s the code ChatGPT gave me for implementing the toggle functionality:&lt;/p&gt;

&lt;p&gt;First of all, in the &lt;code&gt;popup.js&lt;/code&gt; to change the state of the button shown in the &lt;code&gt;popup.html&lt;/code&gt; when it is clicked:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;document.addEventListener("DOMContentLoaded", function () {
  const toggleButton = document.getElementById("toggleButton");

  chrome.runtime.sendMessage({ action: "getStatus" }, (response) =&amp;gt; {
    if (response &amp;amp;&amp;amp; typeof response.isEnabled !== "undefined") {
      updateButtonText(response.isEnabled);
    } else {
      console.error("Invalid response:", response);
    }
  });

  toggleButton.addEventListener("click", () =&amp;gt; {
    chrome.runtime.sendMessage({ action: "toggle" }, (response) =&amp;gt; {
      if (response &amp;amp;&amp;amp; typeof response.isEnabled !== "undefined") {
        updateButtonText(response.isEnabled);
      } else {
        console.error("Invalid response:", response);
      }
    });
  });

  function updateButtonText(isEnabled) {
    toggleButton.textContent = isEnabled ? "Turn Off" : "Turn On";
    toggleButton.style.backgroundColor = isEnabled ? "#f44336" : "#4caf50";
  }
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in the &lt;code&gt;background.js&lt;/code&gt;, to have listeners that store the state in the Chrome local storage and send the latest state back when asked for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// background.js
let isEnabled = true;

chrome.runtime.onInstalled.addListener(() =&amp;gt; {
  console.log("Extension installed");
  chrome.storage.local.set({ isEnabled: true }, () =&amp;gt; {
    if (chrome.runtime.lastError) {
      console.error("Error setting initial state:", chrome.runtime.lastError);
    }
  });
});

chrome.runtime.onMessage.addListener((message, sender, sendResponse) =&amp;gt; {
  if (message.action === "toggle") {
    isEnabled = !isEnabled;
    chrome.storage.local.set({ isEnabled }, () =&amp;gt; {
      sendResponse({ isEnabled });
    });
    return true;
  } else if (message.action === "getStatus") {
    sendResponse({ isEnabled });
    return true;
  }
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally, in the &lt;code&gt;content.js&lt;/code&gt;, I added this function which would send a message to the Chrome runtime to check if the extension is enabled or not and run a callback function if enabled:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function checkOnOff(callback) {
  chrome.runtime.sendMessage({ action: "getStatus" }, (response) =&amp;gt; {
    if (response &amp;amp;&amp;amp; typeof response.isEnabled !== "undefined") {
      callback(response.isEnabled); // Pass the state back to the caller via the callback
    } else {
      console.error("Invalid response:", response);
      callback(null);
    }
  });
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now on paper, this looks good, right? The code makes sense when you read it. And when I ran it as well, it worked perfectly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hidden Bug in ChatGPT’s Code
&lt;/h2&gt;

&lt;p&gt;Only a few days after I had merged this code, I noticed a weird bug. I would turn the extension off, but after some time, it would turn back on. And I wasn’t able to reproduce this accurately each time. I didn’t know what was causing it to turn on again: was it just after a fixed period of time, was it me clicking somewhere on the screen, or me changing tabs, or something else completely? No idea.&lt;/p&gt;

&lt;p&gt;I knew it was this PR which introduced this bug (benefits of using version control for personal projects as well), so I went back. I decided I’m going to make the culprit fix their own mistake. I did have a slight idea of what might be going wrong, but I still decided to run it by our flawed expert. And what it caught was exactly along the lines of what I was thinking. If you look at the earlier code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// background.js
let isEnabled = true;

...

chrome.runtime.onMessage.addListener((message, sender, sendResponse) =&amp;gt; {
        if (message.action === 'toggle') {
        isEnabled = !isEnabled;
        chrome.storage.local.set({ isEnabled }, () =&amp;gt; {
            sendResponse({ isEnabled });
        });
        return true;
    } else if (message.action === 'getStatus') {
        sendResponse({ isEnabled });
        return true;
    }
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you see that when the content script asks for status, we send the &lt;code&gt;isEnabled&lt;/code&gt; variable instead of retrieving the set value from local storage. Now, this theoretically should still work since we change the value of the &lt;code&gt;isEnabled&lt;/code&gt; variable when a toggle event occurs. I don’t understand the Chrome extension lifecycle enough to be sure, but what I suspect is that somehow this background script gets reset and so the value of &lt;code&gt;isEnabled&lt;/code&gt; becomes &lt;code&gt;true&lt;/code&gt; again, and that’s what gets sent as a response, causing the extension to toggle on again after some time/event.&lt;/p&gt;

&lt;p&gt;The way to fix that is what I mentioned earlier. Returning the value of &lt;code&gt;isEnabled&lt;/code&gt; after fetching it from the local storage, and that’s what ChatGPT suggested as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// background.js
let isEnabled = true;

...

chrome.runtime.onMessage.addListener((message, sender, sendResponse) =&amp;gt; {
        if (message.action === 'toggle') {
        isEnabled = !isEnabled;
        chrome.storage.local.set({ isEnabled }, () =&amp;gt; {
            sendResponse({ isEnabled });
        });
        return true;
    } else if (message.action === 'getStatus') {
        chrome.storage.local.get('isEnabled', (result) =&amp;gt; {
            sendResponse({ isEnabled: result.isEnabled });
        });
        return true;
    }
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And after merging this, I had no problems!&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons Learned Using AI for Coding
&lt;/h2&gt;

&lt;p&gt;It always amuses me how these AI coding assistants give you code which has bugs but also have the capability to debug that very same code when given in a different prompt. No doubt they are useful, especially when bootstrapping a project or feature. They’re great at giving you boilerplate code. But the lesson I’ve learned is to treat it just like that - code to help get you started. Make sure you type that code on your own instead of just copying and pasting it. Because when copying and pasting, like I did here, everything makes sense on the screen, but when you put it in your codebase thinking it should work, it actually might not.&lt;/p&gt;

&lt;p&gt;Instead, when you type it out, I think you’re much more aware of what you’re doing, and it’s much harder to fall into the trap of adding bug-filled AI code to your project.&lt;/p&gt;

&lt;p&gt;Thanks for reading! I hope this was a fun read, and if you enjoyed reading it or learned something from it, consider subscribing to my newsletter so you get notified every time I post something!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>chrome</category>
      <category>webdev</category>
    </item>
    <item>
      <title>You Don’t Need To Pay for the OpenAI API During Development</title>
      <dc:creator>Arsh Sharma</dc:creator>
      <pubDate>Tue, 09 Jul 2024 18:30:00 +0000</pubDate>
      <link>https://dev.to/rinkiyakedad/you-dont-need-to-pay-for-the-openai-api-during-development-172a</link>
      <guid>https://dev.to/rinkiyakedad/you-dont-need-to-pay-for-the-openai-api-during-development-172a</guid>
      <description>&lt;p&gt;If you’re developing or thinking of creating an app that leverages the OpenAI API but don’t want to put down your credit card until you’re sure you have something, I have good news for you. In this article I’m going to show you how you can create a backend API which is compatiable with the OpenAI API. However, when running this API locally during development, we will use the &lt;a href="https://llama.meta.com/llama3/" rel="noopener noreferrer"&gt;Llama3&lt;/a&gt; model &lt;strong&gt;running locally on your laptop&lt;/strong&gt;. When you want to use this in production, all you need to do is change the environment variables, and everything else will remain the same :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Why would you want to do this?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://ollama.com/" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt;, for those of you who don’t know, is one of the simplest ways to get started with running large language models locally on your machine. Earlier this year, they announced compatibility with the OpenAI &lt;a href="https://github.com/ollama/ollama/blob/main/docs/openai.md" rel="noopener noreferrer"&gt;Chat Completions API&lt;/a&gt;. This means you can keep writing code for your application as if you were developing using the OpenAI API, but when running things locally, you can use a language model provided by Ollama running locally on your machine.&lt;/p&gt;

&lt;p&gt;This is very useful because it allows you to get started easily with developing AI applications without creating an account or paying for the OpenAI API. This means that during development, your API costs would be zero, so you can iterate freely and as much as you want without worrying about it. When you’re ready to take your application to production, you don’t need to change any of your code because it’s already compatible with the OpenAI. All you need to do is swap out your API keys and endpoints, and you’re ready to go!&lt;/p&gt;

&lt;p&gt;Let’s see this in action in this blog :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up the project
&lt;/h2&gt;

&lt;p&gt;Create a new folder, and inside it, create a new virtual environment by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python -m venv openai-api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Activate the virtual environment by running (on MacOS or Unix):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;source openai-env/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and (on Windows):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;openai-env\Scripts\activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install the dependencies we’ll need for this project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install --upgrade openai Flask python-dotenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need &lt;code&gt;openai&lt;/code&gt; to interact with the OpenAI/Ollama API, &lt;code&gt;Flask&lt;/code&gt; to create our backend API server, and &lt;code&gt;python-dotenv&lt;/code&gt; to automatically load the &lt;code&gt;.env&lt;/code&gt; file we will create, which will allow us to easily swap environment variables.&lt;/p&gt;

&lt;p&gt;Once you have all this, we’re ready to move to the development phase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing the code for our server
&lt;/h2&gt;

&lt;p&gt;Here’s what the code for a simple backend that talks to the OpenAI API could look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import os
from flask import Flask, request, jsonify
from openai import OpenAI
from dotenv import load_dotenv

load_dotenv() # take environment variables from .env.

app = Flask( __name__ )

client = OpenAI(
    api_key=os.environ.get("OPENAI_API_KEY"),
    base_url=os.environ.get("LLM_ENDPOINT")
)

@app.route("/api/chat", methods=["POST"])
def chat():
    try:
        data = request.get_json()
        input_message = data["input"]

        # Create chat completion
        response = client.chat.completions.create(
            model=os.environ.get("MODEL"),
            messages=[
                {"role": "system", "content": "You are an AI chatbot who specializes in writing poems."},
                {"role": "user", "content": input_message}
            ]
        )

        output = response.choices[0].message.content
        return jsonify({"output": output})
    except Exception as e:
        print("Error:", str(e))
        return jsonify({"error": "Internal Server Error"}), 500

if __name__ == " __main__":
    port = int(os.getenv("PORT", 3000))
    app.run(host="0.0.0.0", port=port)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code should be fairly easy to understand if you’ve ever worked with the OpenAI API before. I want to keep the focus of this article on showing you how to use Ollama to develop AI apps, so I won’t go into detail about this code. You can refer to the &lt;a href="https://platform.openai.com/docs/quickstart/quickstart-language-selection" rel="noopener noreferrer"&gt;OpenAI docs&lt;/a&gt; for that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting the right environment variables
&lt;/h2&gt;

&lt;p&gt;f you noticed in the above code, we used three environment variables. These make all the difference in enabling you to use the Ollama API during development and easily switching to OpenAI when you’re done building an MVP.&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;.env&lt;/code&gt; file and put the following in it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# for development

OPENAI_API_KEY=doesntmatteryaar
LLM_ENDPOINT="http://localhost:11434/v1"
MODEL=llama3

# for production

# OPENAI_API_KEY=youropenapikey
# LLM_ENDPOINT="https://api.openai.com/v1"
# MODEL=gpt-3.5-turbo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The production section should be obvious if you’ve worked with the OpenAI API before. In the development section, we provide a dummy key. Unlike OpenAI, the Ollama API doesn’t care what key you provide; it just needs there to be some value. The endpoint we provide is the default one where Ollama serves. For the model, you can pick any of the ones Ollama supports. Now that we have this, we’re ready to get our API up and running!&lt;/p&gt;

&lt;h2&gt;
  
  
  Running our code
&lt;/h2&gt;

&lt;p&gt;Before we run the code we wrote, we need to start our Ollama server. Installing Ollama is very simple, and you can find the instructions for that &lt;a href="https://ollama.com/download" rel="noopener noreferrer"&gt;on their website&lt;/a&gt;. Once you have it installed and have pulled an LLM model (in this case, &lt;code&gt;llama3&lt;/code&gt;), run the following command to start the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ollama serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once this is done, we’re all ready to go. Start the Python server by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python server.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now our server, which talks with the LLM model, should be up and running. We can test that by running the following &lt;code&gt;curl&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -X POST http://localhost:3000/api/chat \
     -H "Content-Type: application/json" \
     -d '{"input": "Compose a poem on LLMs."}'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And ta-da! This is the response I got back if you want to have a chuckle as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"output":"In silicon halls, where data reigns,
Linguistic Lightweights weave their refrains.
With weights that dance upon the scales,
They grasp the nuances of human gales.

Their language flows, both pure and bright,
A tapestry of meaning, woven with might.
From words to wisdom, they unfold the page,
A lexicon of knowledge, in digital age.

Like sages of old, they hold the key,
To secrets hidden, yet to be free.
In realms of reason, they guide our way,
Through mazes of complexity, night and day.

With each new prompt, a challenge laid,
They summon forth, their cognitive shade.
A whirlwind of words, in rapid fire,
As meaning blooms, like petals on a pyre.

Linguistic Lightweights, oh so fine,
Weaving worlds from code, and data's shrine.
In harmony with humans, they entwine,
The threads of thought, where understanding is divine.

Their poetic grasp, on language true,
A reflection of our own, anew.
For in their digital heartbeats lies,
A promise of progress, for humanity's sighs."}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if you swap the environment variables with the OpenAI ones and restart your server, you should still see a response. Except this time, you’d be pinging the OpenAI API instead of the locally running Llama3 model via Ollama. So you can easily continue developing your applications locally without paying for any API costs, and when ready to push your app to production, easily switch to the OpenAI API :)&lt;/p&gt;

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

&lt;p&gt;I hope this was useful in making it easier for you to get started developing AI powered applications without incurring any costs for the model during development. If this was helpful, subscribe to my newsletter to get notified whenever I post more such content! :)&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>api</category>
    </item>
    <item>
      <title>Things I've Learned About Conference Speaking</title>
      <dc:creator>Arsh Sharma</dc:creator>
      <pubDate>Wed, 03 Jan 2024 18:30:00 +0000</pubDate>
      <link>https://dev.to/rinkiyakedad/things-ive-learned-about-conference-speaking-e5n</link>
      <guid>https://dev.to/rinkiyakedad/things-ive-learned-about-conference-speaking-e5n</guid>
      <description>&lt;p&gt;On the wall across from my desk, I’ve got badges from all the conferences I’ve been to. The collection has grown quite a bit over the past two years. Recently, taking a look at it made me take a trip down memory lane and reflect on the first few talks I gave, as well as the ones I’m giving now - what’s changed, what I do differently, and the things I’ve learned. This blog is gonna be about some of those learnings.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  My First Conference Talk
&lt;/h2&gt;

&lt;p&gt;The first time I spoke at an in-person conference was in May 2022 in Valencia at KubeCon Europe. I had spoken at a bunch of online conferences and webinars during the Covid lockdown, but never in person. And it was a big deal for me because it was at &lt;a href="https://events.linuxfoundation.org/kubecon-cloudnativecon-europe/" rel="noopener noreferrer"&gt;KubeCon&lt;/a&gt;! I still remember how nervous I was walking up to that stage, seeing all the people filling up the room to hear our talk. I don’t think anybody noticed, but my legs were seriously trembling. Part of it was the usual fear of public speaking that most people experience, but part of it was imposter syndrome. I had only been contributing to &lt;a href="https://kubernetes.io/" rel="noopener noreferrer"&gt;Kubernetes&lt;/a&gt; for a year, and here were all these people who had been working with Kubernetes for so long, coming to listen to &lt;strong&gt;me&lt;/strong&gt; talk? What if they find my talk irrelevant or already know everything I’m saying? What if I mess up and say something completely stupid on stage? What if they start thinking I’m a total hack and don’t know anything?&lt;/p&gt;

&lt;p&gt;I honestly can’t remember how, but somehow I managed to push those thoughts away and just went for it on stage that day. I probably told myself that there was no turning back now, and that this was it. And you know what? It turned out pretty great!&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;A photo from my first conference talk. Yes I was really skinny back then xD&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After the talk, people actually came up to us and said they learned a lot from it! We had some interesting conversations, and they even shared their own struggles with the &lt;a href="https://www.youtube.com/watch?v=sdU-3cqiJmg" rel="noopener noreferrer"&gt;tool I was discussing&lt;/a&gt;. I could relate to them, and it felt really good. Turns out, I didn’t embarrass myself as much as I thought I would. No one thought I didn’t belong or didn’t know anything. The world didn’t end, and everything was just fine :)&lt;/p&gt;

&lt;p&gt;So, I did it again. And again. &lt;a href="https://arshsharma.com/speaking/" rel="noopener noreferrer"&gt;And again&lt;/a&gt;. Since then, I’ve had the privilege of speaking at several conferences and meetups. I’m really grateful for that exposure. Now, I can confidently say that my legs no longer shake (sometimes?) when I have to go up on stage. But for those of you who are just starting out, here are some things I learned the hard way that I wish I knew earlier. Just a heads up, these are based on my personal experience speaking at tech conferences. Don’t take them as absolute truths :))&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Is Forgotten, Stories Are Remembered
&lt;/h2&gt;

&lt;p&gt;I put this first because it’s been my biggest learning this year. When I started giving talks, I used to include a lot of code and technical details. I think part of that was because of imposter syndrome. I felt like I had to appear “smart” for people to listen to me. But I’ve realized how silly that was. While the topics I talk about today are still technical, I’ve learned that the main purpose of technology is solving problems, and that’s what people want to hear about. Stories about the problems you’re trying to solve, and why solving them is important, resonate more with attendees than lines of code. If they get inspired by the problem your tool solves, you can always talk about the implementation later :)&lt;/p&gt;

&lt;p&gt;I’ve also started applying this approach to demos. Before, I used to show every single step maybe in an attempt to prove that I know what I’m talking about. But I’ve realized that it only dilutes the demos. Attention spans are limited, and when there are so many moving pieces, people lose track. So now, while I provide detailed steps and instructions in a README, I focus my demo on highlighting the “wow” moment - the moment that captures everyone’s attention and connects the demo to the pain point mentioned in the story.&lt;/p&gt;

&lt;p&gt;People want to be heard, to see themselves in stories and struggles. They want to relate. As a speaker, it’s your job to try and inspire them. In retrospect, this is something I should’ve learned way earlier, because many conversations I had after my talks were not about the code I showed, but about how people struggled to find similar solutions or the problems they faced when trying to implement them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Everyone Is Unique, and That Makes Your Story More Valuable Than You Might Think!
&lt;/h2&gt;

&lt;p&gt;I feel like this applies more to life in general than just conference speaking. Realizing that even though there may be more experienced people in the room, they haven’t had the same set of experiences as me, helped me overcome my imposter syndrome a lot. The beauty of life is that everyone has a unique story and a unique understanding of different things based on their life experiences. So, the best way to keep your talk interesting is by being yourself! Tell your story in your own way.&lt;/p&gt;

&lt;p&gt;Oh, and here’s another thing to keep in mind. People attend conferences to be exposed to new ideas and things. Sure, they might be subject matter experts on topic A and have decades more experience than you, but that doesn’t mean they might be equally knowledgeable about the topic you’re presenting.&lt;/p&gt;

&lt;p&gt;Sometimes, we get so caught up in our own little bubble, working on that one thing with our colleagues, and assume that everyone knows about it. But trust me, that’s almost never the case. For example, in one of my recent talks, we were discussing DevX. Since that’s what I mainly focus on in my day job, I was very familiar with it. But when I asked the audience to show hands, turns out 70% of them weren’t familiar with it. Lesson learned? It’s easy to fall into a silo and assume everyone knows what you’re talking about, but don’t let that imposter syndrome get the best of you!&lt;/p&gt;

&lt;p&gt;You’re unique, your story is unique, and the way you tell it will be unique too. So, you have a lot of value to offer. Just go out there and be yourself! :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Your Slides Don’t Matter…
&lt;/h2&gt;

&lt;p&gt;…as much as you think. Now that I have your attention with a provocative heading, let me clarify. Of course, your slides matter and they’re an important visual aid to complement your talk. But they shouldn’t steal the spotlight. Avoid turning your slides into a word-for-word script or a list of lengthy bullet points.&lt;/p&gt;

&lt;p&gt;I used to cram my slide with bullet points, but that just diverted attention. The key is to keep the focus on what you’re saying. Slides should simply support your storytelling process, nothing more. Throw in some GIFs, ask questions, and if you have to include text, keep it short and bold the important stuff.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;A slide from one of my recent talks, made with Deckset.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One tool I’ve grown fond of is &lt;a href="https://www.deckset.com/" rel="noopener noreferrer"&gt;Deckset&lt;/a&gt;. It really helps me think about my slides in the way I talked about above. Plus, keeping my slides short has pushed me to practice my content more. It makes me more flexible to adjust based on audience response rather than sticking to a rigid script.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep It Interactive
&lt;/h2&gt;

&lt;p&gt;If you’re speaking for more than 30 minutes, it’s really easy to lose people’s attention. That’s why it’s very important to make your talks interactive. How do you do that? Well, start by asking questions. Get the audience involved by asking them to raise their hands in response to a question. Throw in a few jokes here and there. Another thing I’ve learned is to make my demos as interactive as possible. For instance, I often use a todo list app for my demos and I deploy a live copy of it. I ask the audience to scan the QR code so they can see the app live and add todos to it.&lt;/p&gt;

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

&lt;p&gt;Think about how you can make your presentation engaging and make the attendees feel like they’re part of the talk, rather than just passive listeners!&lt;/p&gt;

&lt;h2&gt;
  
  
  And Lastly, Remember to Breathe and Have Fun!
&lt;/h2&gt;

&lt;p&gt;I had a habit of rushing and talking non-stop when giving talks. Silences made me uncomfortable. But now I make sure to take a moment and add some pauses to my talks. Because I’ve learned that not only does it give the attendees time to process, but it also helps you collect your thoughts. Look at the attendees and try to read the room - see if they’re following what you’re talking about or not. If they’re finding it hard to follow, don’t hesitate to repeat things and give more examples.&lt;/p&gt;

&lt;p&gt;Lastly and most importantly, don’t forget to have fun! You’ve got a platform to share your knowledge and inspire others, so make the most of it and enjoy the experience. Engage with the attendees, throw in some questions, take breaks for laughter, and don’t take yourself too seriously. Treat every talk as a learning experience, so no matter how it goes, use it to improve and do better for your next one. And above all, believe in yourself and your &lt;strong&gt;unique&lt;/strong&gt; story. You’ve got this :)&lt;/p&gt;

&lt;p&gt;If you like my articles, you can follow me on &lt;a href="https://twitter.com/RinkiyaKeDad" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; or &lt;a href="https://www.linkedin.com/in/arsh4/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; to get notified whenever I post something new!&lt;/p&gt;

</description>
      <category>techtalks</category>
      <category>devrel</category>
      <category>publicspeaking</category>
    </item>
  </channel>
</rss>
