<?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>Forem: Master</title>
    <description>The latest articles on Forem by Master (@sharadregoti).</description>
    <link>https://forem.com/sharadregoti</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%2F333205%2Fddf2ff5c-7d38-424e-9155-26caea4bcfdb.png</url>
      <title>Forem: Master</title>
      <link>https://forem.com/sharadregoti</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/sharadregoti"/>
    <language>en</language>
    <item>
      <title>Platform Setup : How To Structure Your Infrastructure Repository</title>
      <dc:creator>Master</dc:creator>
      <pubDate>Wed, 21 Jun 2023 16:13:27 +0000</pubDate>
      <link>https://forem.com/sharadregoti/platform-setup-how-to-structure-your-infrastructure-repository-19ih</link>
      <guid>https://forem.com/sharadregoti/platform-setup-how-to-structure-your-infrastructure-repository-19ih</guid>
      <description>&lt;p&gt;Welcome to the Platform Setup series, a collection of blog posts where I'll be sharing my insights and experiences from deploying applications in enterprises. With a particular focus on &lt;strong&gt;Banking and Insurance&lt;/strong&gt; companies.&lt;/p&gt;

&lt;p&gt;I've been part of dynamic teams ranging in size from 20 to 40 talented individuals, each one contributing to the grand mosaic of software development. We've journeyed from traditional software development methodologies to the cutting-edge vistas of DevOps, Kubernetes, and beyond, fostering an environment of continuous learning and growth.&lt;/p&gt;

&lt;p&gt;However, with new methodologies come new challenges. This transition isn't always a smooth sail and in this series, we'll delve deep into the unique struggles faced by teams as they migrate towards more modern, streamlined ways of operation.&lt;/p&gt;

&lt;p&gt;This immersive series will touch on an array of topics. We'll dive into the nuts and bolts of secrets management, demystify config management, discuss governance and policy enforcements, and explore the crucial areas of observability and developer enablement. &lt;/p&gt;

&lt;p&gt;Keeping all these engaging discussions on the horizon, let's kick-start our journey with an exploration of the infrastructure repository. This initial piece, a relatively short yet informative post, will shed light on how we've structured our infra repositories.&lt;/p&gt;

&lt;p&gt;Here is an glimpse of what the repo structure looks like&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--R3v0lWy9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2pg3wvyw3rlt0cg805ik.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R3v0lWy9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2pg3wvyw3rlt0cg805ik.png" alt="01-strucutre.png" width="800" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the vast expanse of our technology-driven operations, a typical service project employs four distinct repositories to house our source code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mobile App:&lt;/strong&gt; This repository is home to our React Native application. The code here is the heart of our mobile app, powering our operations on handheld devices.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Web App:&lt;/strong&gt; Next up, we have the Web App repository. This is where we host our ReactJS application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Microservices:&lt;/strong&gt; This is where we host our microservices—small, autonomous services that work together. Each microservice encapsulates a specific business capability, and collectively they bring our applications to life.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infrastructure:&lt;/strong&gt; Herein resides our Infrastructure as Code (IaC). By treating our infrastructure as code, we maintain consistency, enable version control, and reduce manual error, all while streamlining our IT infrastructure processes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Environments In IAC
&lt;/h1&gt;

&lt;p&gt;A software application goes through various stages of development before reaching the end users. Each stage is accompanied by an environment, where different set of users approve the progression to a higher environment.&lt;/p&gt;

&lt;p&gt;In our repo structure, we represent an environment as a directory inside the &lt;code&gt;envs&lt;/code&gt; folder, the contents of each folder represents the current state of that environment.&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="s"&gt;envs/&lt;/span&gt;
&lt;span class="pi"&gt;|&lt;/span&gt;
&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="s"&gt;-- dev/&lt;/span&gt;
&lt;span class="err"&gt;|&lt;/span&gt;
&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="s"&gt;-- uat/&lt;/span&gt;
&lt;span class="err"&gt;|&lt;/span&gt;
&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="s"&gt;-- prod/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s now see, what goes into these directories?&lt;/p&gt;

&lt;h1&gt;
  
  
  Infrastructure &amp;amp; Applications
&lt;/h1&gt;

&lt;p&gt;An environment consists of base infrastructure (like VMs, DBs &amp;amp; other cloud services) on top of which our application runs.&lt;/p&gt;

&lt;p&gt;In our repository, infrastructure resides in the &lt;code&gt;01-infra&lt;/code&gt; directory and is defined using IAC tools (like terraform). As we use Kubernetes as the defacto base infra layer for orchestrating containerized applications.&lt;/p&gt;

&lt;p&gt;All our software applications reside in these 3 folders and are installed using helm&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;02-k8s-tools:&lt;/strong&gt; Contains a set of cloud native tools like Istio, Prometheus, OPA etc… which helps us manage the Kubernetes clusters&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;03-dev-tools:&lt;/strong&gt; Contains a set of dev tools like PGAdmin, Keycloack which helps developers in their development activity.
&lt;strong&gt;Note:&lt;/strong&gt; The segregation between &lt;code&gt;02-k8s-tools&lt;/code&gt; &amp;amp; &lt;code&gt;03-dev-tools&lt;/code&gt; is totally optional.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;04-services:&lt;/strong&gt; Contains all the services required to run the application.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The diagram below shows how we segregate infrastructure and applications.&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="s"&gt;envs/&lt;/span&gt;
&lt;span class="pi"&gt;|&lt;/span&gt;
&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="s"&gt;-- dev/&lt;/span&gt;
    &lt;span class="s"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;|-- 01-infra/&lt;/span&gt;
    &lt;span class="s"&gt;|   |-- 01-networking/&lt;/span&gt;
    &lt;span class="s"&gt;|   |-- 02-rds/&lt;/span&gt;
    &lt;span class="s"&gt;|   |-- 03-eks/&lt;/span&gt;
    &lt;span class="s"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;|-- 02-k8s-tools/&lt;/span&gt;
    &lt;span class="s"&gt;|   |-- 01-opa-gatekeeper/&lt;/span&gt;
    &lt;span class="s"&gt;|   |-- 02-istio/&lt;/span&gt;
    &lt;span class="s"&gt;|   |-- 03-fluent-bit/&lt;/span&gt;
    &lt;span class="s"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;|-- 03-dev-tools/&lt;/span&gt;
    &lt;span class="s"&gt;|   |-- 01-keycloak/&lt;/span&gt;
    &lt;span class="s"&gt;|   |-- 02-pg-admin/&lt;/span&gt;
    &lt;span class="s"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;|-- 04-services/&lt;/span&gt;
        &lt;span class="s"&gt;|-- 01-serviceA/&lt;/span&gt;
        &lt;span class="s"&gt;|-- 02-serviceB/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why prefix numbers?
&lt;/h2&gt;

&lt;p&gt;In our repository structure, directories are prefixed with numbers. This is optional but it provides a visual hierarchy and a logical order for the creation and deletion of environment components.&lt;/p&gt;

&lt;h1&gt;
  
  
  Keeping Your Code DRY (Don't Repeat Yourself)
&lt;/h1&gt;

&lt;p&gt;Up until now, we have seen how environments &amp;amp; applications are organized using directories, but what goes inside in each application/infra directory? Where is the actual IAAC code written?&lt;/p&gt;

&lt;p&gt;In order to maintain a DRY codebase and avoid code duplication, the code is organized in modules or packages that can be reused.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;01-infra&lt;/code&gt; directory, the concept of terraform modules is used to encapsulate infrastructure code that can be reused across different environments. Terraform modules are stored under the top level directory called &lt;code&gt;terraform-modules&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Similarly, for applications directories. Helm charts are used and these chart are stored in the &lt;code&gt;helm-charts&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;An organization can create their own terraform modules or helm charts by building on top of existing open source modules &amp;amp; charts to suit their specific needs.&lt;/p&gt;

&lt;p&gt;The diagram below shows how we use Terraform modules and Helm charts.&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="s"&gt;helm-charts/&lt;/span&gt;
&lt;span class="pi"&gt;|&lt;/span&gt;
&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="s"&gt;-- service-chart/&lt;/span&gt;
&lt;span class="err"&gt;|&lt;/span&gt;
&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="s"&gt;-- opa-gatekeeper-chart/&lt;/span&gt;
&lt;span class="err"&gt;|&lt;/span&gt;
&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="s"&gt;-- keycloak-chart/&lt;/span&gt;
&lt;span class="err"&gt;|&lt;/span&gt;
&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="s"&gt;-- nginx-ingress-controller-chart/&lt;/span&gt;
&lt;span class="err"&gt;|&lt;/span&gt;
&lt;span class="err"&gt;t&lt;/span&gt;&lt;span class="s"&gt;erraform-modules/&lt;/span&gt;
&lt;span class="err"&gt;|&lt;/span&gt;
&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="s"&gt;-- networking/&lt;/span&gt;
&lt;span class="err"&gt;|&lt;/span&gt;
&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="s"&gt;-- redis/&lt;/span&gt;
&lt;span class="err"&gt;|&lt;/span&gt;
&lt;span class="err"&gt;e&lt;/span&gt;&lt;span class="s"&gt;nvs/&lt;/span&gt;
&lt;span class="err"&gt;|&lt;/span&gt;
&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="s"&gt;-- dev/&lt;/span&gt;
    &lt;span class="s"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;|-- 01-infra/&lt;/span&gt;
    &lt;span class="s"&gt;|   |-- 01-networking/&lt;/span&gt;
    &lt;span class="s"&gt;|   |   |-- terragrunt.hcl # Refers to ../../../../terraform-modules/networking&lt;/span&gt;
    &lt;span class="s"&gt;|   |-- 02-rds/&lt;/span&gt;
    &lt;span class="s"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;|-- 02-k8s-tools/&lt;/span&gt;
    &lt;span class="s"&gt;|   |-- 01-opa-gatekeeper/&lt;/span&gt;
    &lt;span class="s"&gt;|   |   |-- values.yaml # Refers to ../../../../helm-charts/opa-gatekeeper-chart&lt;/span&gt;
    &lt;span class="s"&gt;|   |-- 02-istio/&lt;/span&gt;
    &lt;span class="s"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;|-- 03-dev-tools/&lt;/span&gt;
    &lt;span class="s"&gt;|   |-- 01-keycloak/&lt;/span&gt;
    &lt;span class="s"&gt;|   |   |-- values.yaml # Refers to ../../../../helm-charts/keycloak-chart&lt;/span&gt;
    &lt;span class="s"&gt;|   |-- 02-pg-admin/&lt;/span&gt;
    &lt;span class="s"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;|-- 04-services/&lt;/span&gt;
        &lt;span class="s"&gt;|-- 01-serviceA/&lt;/span&gt;
        &lt;span class="s"&gt;|   |-- values.yaml # Refers to ../../../../helm-charts/service-chart&lt;/span&gt;
        &lt;span class="s"&gt;|-- 02-serviceB/&lt;/span&gt;
            &lt;span class="s"&gt;|-- values.yaml # Refers to ../../../../helm-charts/service-chart&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Within each application or infrastructure directory, there are just configuration &amp;amp; CI/CD files. No IAC code is present in this directory.&lt;/p&gt;

&lt;p&gt;This config files are used with the terraform module or helm charts to create the actual infrastructure.&lt;br&gt;
This can be compared to calling a function with parameters, where the function to be called is defined inside &lt;code&gt;helm-charts&lt;/code&gt; or &lt;code&gt;terraform-modules&lt;/code&gt; directory &amp;amp; the actual call to the function exists in the infra/application directory.&lt;/p&gt;

&lt;p&gt;Let’s now see, how we manage common configuration?&lt;/p&gt;

&lt;h1&gt;
  
  
  Managing Common Configuration
&lt;/h1&gt;

&lt;p&gt;In complex systems, it's quite common to have configurations that are shared across different components of the infrastructure and applications. Organizing these configurations efficiently can be challenging but crucial for maintainability and understanding the system's behavior.&lt;/p&gt;

&lt;p&gt;In our repository structure, these shared configurations are identified and stored in dedicated &lt;strong&gt;&lt;code&gt;_base&lt;/code&gt;&lt;/strong&gt; directories. This helps in reducing redundancy and maintaining consistency across the components or applications.&lt;/p&gt;

&lt;p&gt;Let's dive into this in more detail:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Common configuration per environments:&lt;/strong&gt; If there is a configuration common across an environment (like a cloud region or an AWS role), it is stored in the &lt;strong&gt;&lt;code&gt;_base&lt;/code&gt;&lt;/strong&gt; directory under an environment directory like &lt;code&gt;dev&lt;/code&gt;. This makes it accessible to all components &amp;amp; applications in  that environment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Common configuration across individual infrastructure components or applications:&lt;/strong&gt; If there's a configuration common to individual infrastructure components or applications (like a kubernetes namespace or cloud credentials), it is stored in the &lt;strong&gt;&lt;code&gt;_base&lt;/code&gt;&lt;/strong&gt; directory which is present for every application &amp;amp; infrastructure directory. This makes the shared configuration easily accessible to all services.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;envs/&lt;/span&gt;
&lt;span class="pi"&gt;|&lt;/span&gt;
&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="s"&gt;-- dev/&lt;/span&gt;
    &lt;span class="s"&gt;|-- _base/&lt;/span&gt;
    &lt;span class="s"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;|-- 01-infra/&lt;/span&gt;
    &lt;span class="s"&gt;|   |-- _base/&lt;/span&gt;
    &lt;span class="s"&gt;|   |-- 01-networking/&lt;/span&gt;
    &lt;span class="s"&gt;|   |-- 02-rds/&lt;/span&gt;
    &lt;span class="s"&gt;|   |-- 03-eks/&lt;/span&gt;
    &lt;span class="s"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;|-- 02-k8s-tools/&lt;/span&gt;
    &lt;span class="s"&gt;|   |-- _base/&lt;/span&gt;
    &lt;span class="s"&gt;|   |-- 01-opa-gatekeeper/&lt;/span&gt;
    &lt;span class="s"&gt;|   |-- 02-istio/&lt;/span&gt;
    &lt;span class="s"&gt;|   |-- 03-fluent-bit/&lt;/span&gt;
    &lt;span class="s"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;|-- 03-dev-tools/&lt;/span&gt;
    &lt;span class="s"&gt;|   |-- _base/&lt;/span&gt;
    &lt;span class="s"&gt;|   |-- 01-keycloak/&lt;/span&gt;
    &lt;span class="s"&gt;|   |-- 02-pg-admin/&lt;/span&gt;
    &lt;span class="s"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;|-- 04-services/&lt;/span&gt;
        &lt;span class="s"&gt;|-- _base/&lt;/span&gt;
        &lt;span class="s"&gt;|-- 01-serviceA/&lt;/span&gt;
        &lt;span class="s"&gt;|-- 02-serviceB/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's also important to note the precedence of the configurations. Any configuration defined in the component or application directory itself has the highest priority and will override what is defined in the respective &lt;strong&gt;&lt;code&gt;_base&lt;/code&gt;&lt;/strong&gt; directory. This allows for more specific configurations when needed, without disturbing the shared configuration's general consistency.&lt;/p&gt;

&lt;p&gt;This approach ensures a balance between avoiding redundancy and allowing customizations where necessary, making the system robust and adaptable.&lt;/p&gt;




&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;In conclusion, we've explored how to effectively structure our infrastructure repositories to manage complex environments and application deployments. We've examined the purpose of different directories and how shared configurations are organized for maintainability and adaptability.&lt;/p&gt;

&lt;p&gt;Join me in the next blog post where we'll delve deeper into Infrastructure as Code, specifically focusing on using Terraform and Terragrunt for infrastructure management. We'll discuss how these powerful tools can automate and simplify the provisioning of cloud resources, and explore how they fit into the repository structure we've outlined in this post.&lt;/p&gt;

&lt;p&gt;Stay tuned for more insights and practical tips on optimizing your platform setup. See you in the next post!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>ia</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>Guide: How to Mask Sensitive Information Using Fluent Bit</title>
      <dc:creator>Master</dc:creator>
      <pubDate>Wed, 14 Jun 2023 03:00:00 +0000</pubDate>
      <link>https://forem.com/sharadregoti/guide-how-to-mask-sensitive-information-using-fluent-bit-31jj</link>
      <guid>https://forem.com/sharadregoti/guide-how-to-mask-sensitive-information-using-fluent-bit-31jj</guid>
      <description>&lt;p&gt;Fluent Bit is a popular open-source log processor and forwarder that allows you to collect data from different sources, filter, and transform it before forwarding it to different destinations. In some cases, the data collected may contain sensitive information like passwords, credit card numbers, social security numbers, and other personal identifiable information (PII). To protect such information, you need to mask or obfuscate it before forwarding it to the destination. In this document, we will discuss how to mask sensitive information using Fluent Bit.&lt;/p&gt;

&lt;p&gt;The goal of this guide is convert structured logs that contain PII information like (mobile numbers, identity information, name etc…)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{"timestamp":"2023-06-05T17:04:33.505+05:30","requestURI":"/api/user","message":"Sending SMS to mobileNumber=1234512345 registered on aadhaarNumber=1234512345"}&lt;/code&gt; &lt;br&gt;
to a format where this information is masked.&lt;br&gt;
&lt;code&gt;{"@timestamp":"2023-06-05T17:04:33.505+05:30","requestURI":"/api/user","message":"Sending SMS to mobileNumber=******** registered on aadhaarNumber=********"}&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Prerequisites &amp;amp; Constraints
&lt;/h2&gt;

&lt;p&gt;This guides assumes the following&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Docker is installed on your machine&lt;/li&gt;
&lt;li&gt;You have knowledge of fluent-bit concepts like inputs, outputs, parsers, filters etc..&lt;/li&gt;
&lt;li&gt;We will be constraining our selves to not introduce any 3rd party service other than fluent-bit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s start with an initial configuration on your machine that reproduce the behavior where sensitive information is not masked yet.&lt;/p&gt;

&lt;p&gt;Create an empty directory on your computer &amp;amp; save the below fluent-bit configuration in a file name &lt;code&gt;fluent-bit.conf&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;INPUT&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="s"&gt;Name   dummy&lt;/span&gt;
    &lt;span class="s"&gt;dummy  {"@timestamp":"2023-06-05T17:04:33.505+05:30","message":"Staring server on port 8080"}&lt;/span&gt;
    &lt;span class="s"&gt;Tag    dummy.log&lt;/span&gt;

&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;INPUT&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="s"&gt;Name   dummy&lt;/span&gt;
    &lt;span class="s"&gt;dummy  {"@timestamp":"2023-06-05T17:04:33.505+05:30","requestURI":"/api/user","message":"Sending SMS to mobileNumber=1234512345, registered on aadhaarNumber=1234512345"}&lt;/span&gt;
    &lt;span class="s"&gt;Tag    dummy.log&lt;/span&gt;

&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;INPUT&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="s"&gt;Name   dummy&lt;/span&gt;
    &lt;span class="s"&gt;dummy  {"@timestamp":"2023-06-05T17:04:33.505+05:30","requestURI":"/api/bank","message":"Successfully registered mobileNumber=1234512345, to panNumber=1234512345"}&lt;/span&gt;
    &lt;span class="s"&gt;Tag    dummy.log&lt;/span&gt;

&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;OUTPUT&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="s"&gt;Name   stdout&lt;/span&gt;
    &lt;span class="s"&gt;Match  *&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now run the below command from the same directory to start the fluent-bit process in a docker container.&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="s"&gt;docker run \&lt;/span&gt;
  &lt;span class="s"&gt;-v $(pwd)/fluent-bit.conf:/fluent-bit/etc/fluent-bit.conf \&lt;/span&gt;
  &lt;span class="s"&gt;-ti cr.fluentbit.io/fluent/fluent-bit:2.0 \&lt;/span&gt;
  &lt;span class="s"&gt;/fluent-bit/bin/fluent-bit \&lt;/span&gt;
  &lt;span class="s"&gt;-c /fluent-bit/etc/fluent-bit.conf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After running the command, the expected output should look like this 👇&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lQqHswTj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hu0nbz0qyntt4cep46md.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lQqHswTj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hu0nbz0qyntt4cep46md.png" alt="Initial-Logs-Image" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see &lt;code&gt;mobileNumber&lt;/code&gt; &amp;amp; &lt;code&gt;aadhaarNumber&lt;/code&gt; are clearly visible in the application logs. Let’s start masking this information.&lt;/p&gt;

&lt;p&gt;The problem of masking PII information can be logically solved by search &amp;amp; replace operation. Where we first search the required information from logs, once found we apply replace operation where the value of replace can be as simple as replacing with ******** or &lt;strong&gt;hashing the value.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In Fluent-Bit, the above mentioned operations can be performed at the Filter stage. Now, let’s select the right plugin for this stage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Selecting the Right Fluent-Bit Plugin
&lt;/h2&gt;

&lt;p&gt;Out of the box fluent-bit provides &lt;code&gt;Nightfall&lt;/code&gt; plugin, which interacts with a 3rd party component called &lt;a href="https://www.nightfall.ai/"&gt;Nightfall&lt;/a&gt; to process the PII information. We won’t be using &lt;code&gt;Nightfall&lt;/code&gt; plugin as we don’t want to introduce any 3rd party component in our system. &lt;/p&gt;

&lt;p&gt;Search &amp;amp; Replace can be performed by these 3 filter plugins:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Record Modifier&lt;/strong&gt;: This plugin gives us the ability to modify our structured logs by replacing entire key, values with something else. But does not allow replacing a small part of the value. For example, take the below structured log
&lt;code&gt;{"timestamp":"2023-06-05T17:04:33.505+05:30","requestURI":"/api/user","message":"Sending SMS to mobileNumber=1234512345 registered on aadhaarNumber=1234512345"}&lt;/code&gt;
in our case the &lt;code&gt;message&lt;/code&gt; field of type string has &lt;code&gt;mobileNumber&lt;/code&gt; in it. We just want to replace this value. But this filter can only replace the entire message content.
So, we won’t using this filter plugin&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modify&lt;/strong&gt;: This has the same drawback as &lt;code&gt;Record Modifier&lt;/code&gt; plugin. So, we won’t using this filter plugin&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lua&lt;/strong&gt;: This filter allows you to modify the incoming records using custom &lt;a href="https://www.lua.org/"&gt;Lua&lt;/a&gt; scripts. This helps us to extend Fluent Bit capabilities by writing custom filters using Lua programming language.
We can use this to write custom Lua script to perform search &amp;amp; replace operation for us.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Writing the Lua Script
&lt;/h2&gt;

&lt;p&gt;Create a file called &lt;code&gt;mask.lua&lt;/code&gt; in the same directory where &lt;code&gt;fluent-bit.conf&lt;/code&gt; exists. Copy the below content inside &lt;code&gt;mask.lua&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;mask_sensitive_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
        &lt;span class="c1"&gt;-- Match "aadhaarNumber:xxxx," and replace with "aadhaarNumber:****,"&lt;/span&gt;
        &lt;span class="kd"&gt;local&lt;/span&gt; &lt;span class="n"&gt;masked_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;string.gsub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'aadhaarNumber=[^,]*'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'aadhaarNumber=****'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;-- Match "mobileNumber:xxxx," and replace with "mobileNumber:****,"&lt;/span&gt;
        &lt;span class="n"&gt;masked_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;string.gsub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;masked_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'mobileNumber=[^,]*'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'mobileNumber=****'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;masked_message&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's a breakdown of what this Lua function does:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;function mask_sensitive_info(tag, timestamp, record)&lt;/code&gt;: This line defines a new Lua function named &lt;code&gt;mask_sensitive_info&lt;/code&gt;. This function takes three parameters: &lt;code&gt;tag&lt;/code&gt;, &lt;code&gt;timestamp&lt;/code&gt;, and &lt;code&gt;record&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;message = record["message"]&lt;/code&gt;: This line retrieves the value of the "message" field from the &lt;code&gt;record&lt;/code&gt; parameter and assigns it to a local variable named &lt;code&gt;message&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;if message then&lt;/code&gt;: This line starts an if statement that only executes the enclosed block of code if &lt;code&gt;message&lt;/code&gt; is not &lt;code&gt;nil&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;local masked_message = string.gsub(message, 'aadhaarNumber[^,]*', 'aadhaarNumber:****')&lt;/code&gt;: This line creates a new local variable named &lt;code&gt;masked_message&lt;/code&gt;. It assigns to this variable the result of calling the &lt;code&gt;string.gsub&lt;/code&gt; function on &lt;code&gt;message&lt;/code&gt;. The &lt;code&gt;string.gsub&lt;/code&gt; function is used to replace all occurrences of the pattern 'aadhaarNumber[^,]&lt;em&gt;' (which matches the string "aadhaarNumber" followed by any sequence of characters that are not a comma) with the string 'aadhaarNumber:&lt;/em&gt;**'.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;masked_message = string.gsub(masked_message, 'mobileNumber[^,]*', 'mobileNumber:****')&lt;/code&gt;: This line reassigns &lt;code&gt;masked_message&lt;/code&gt; with the result of another call to &lt;code&gt;string.gsub&lt;/code&gt;, this time replacing all occurrences of the pattern 'mobileNumber[^,]&lt;em&gt;' (which matches the string "mobileNumber" followed by any sequence of characters that are not a comma) with the string 'mobileNumber:&lt;/em&gt;**'.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;record["message"] = masked_message&lt;/code&gt;: This line updates the "message" field of &lt;code&gt;record&lt;/code&gt; with the value of &lt;code&gt;masked_message&lt;/code&gt;, which at this point should have all sensitive data replaced with asterisks.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;end&lt;/code&gt;: This line closes the if statement.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;return 2, timestamp, record&lt;/code&gt;: This line specifies what the function should return when called. In this case, it returns three values: the number 2, the value of &lt;code&gt;timestamp&lt;/code&gt;, and the updated &lt;code&gt;record&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;end&lt;/code&gt;: This line closes the function definition.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, the overall purpose of this function is to replace any sensitive data (like Aadhaar numbers and mobile numbers) in the "message" field of a record with asterisks, for privacy reasons.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the Lua Script In Lua Plugin
&lt;/h2&gt;

&lt;p&gt;To enable the &lt;code&gt;lua&lt;/code&gt; plugin, you need to add it to the Fluent Bit configuration file. Below is an example of how to configure the lua pugin to mask the PII field in the log data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;INPUT&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="s"&gt;Name   dummy&lt;/span&gt;
    &lt;span class="s"&gt;dummy  {"@timestamp":"2023-06-05T17:04:33.505+05:30","message":"Staring server on port 8080"}&lt;/span&gt;
    &lt;span class="s"&gt;Tag    dummy.log&lt;/span&gt;

&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;INPUT&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="s"&gt;Name   dummy&lt;/span&gt;
    &lt;span class="s"&gt;dummy  {"@timestamp":"2023-06-05T17:04:33.505+05:30","requestURI":"/api/user","message":"Sending SMS to mobileNumber=1234512345, registered on aadhaarNumber=1234512345"}&lt;/span&gt;
    &lt;span class="s"&gt;Tag    dummy.log&lt;/span&gt;

&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;INPUT&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="s"&gt;Name   dummy&lt;/span&gt;
    &lt;span class="s"&gt;dummy  {"@timestamp":"2023-06-05T17:04:33.505+05:30","requestURI":"/api/bank","message":"Successfully registered mobileNumber=1234512345, to panNumber=1234512345"}&lt;/span&gt;
    &lt;span class="s"&gt;Tag    dummy.log&lt;/span&gt;

&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;FILTER&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="s"&gt;Name    lua&lt;/span&gt;
    &lt;span class="s"&gt;Match   *&lt;/span&gt;
    &lt;span class="s"&gt;call    mask_sensitive_info&lt;/span&gt;
    &lt;span class="s"&gt;script  /fluent-bit/scripts/mask.lua&lt;/span&gt;

&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;OUTPUT&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="s"&gt;Name   stdout&lt;/span&gt;
    &lt;span class="s"&gt;Match  *&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above configuration, we have added the lua plugin in the filter state. We set the &lt;code&gt;Match&lt;/code&gt; parameter to &lt;code&gt;*&lt;/code&gt; to match all incoming log data. We then specify the &lt;code&gt;script&lt;/code&gt; parameter to &lt;code&gt;/fluent-bit/scripts/mask.lua&lt;/code&gt; which specifies the path to the lua script file . We also set the &lt;code&gt;call&lt;/code&gt; parameter to &lt;code&gt;mask_sensitive_info&lt;/code&gt; to specify the function name which has to be loaded from the lua script file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing
&lt;/h3&gt;

&lt;p&gt;To test the above configuration, run below command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run \
  -v $(pwd)/fluent-bit.conf:/fluent-bit/etc/fluent-bit.conf \
  -v $(pwd)/mask.lua:/fluent-bit/scripts/mask.lua \
  -ti cr.fluentbit.io/fluent/fluent-bit:2.0 \
  /fluent-bit/bin/fluent-bit \
  -c /fluent-bit/etc/fluent-bit.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The expected output should contain masked valued like this 👇&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bfs_S5w_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wxo4w7kj0f54ccwj0lxr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bfs_S5w_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wxo4w7kj0f54ccwj0lxr.png" alt="Final-Logs-Image" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Masking sensitive information is an important security measure that helps protect personal identifiable information from unauthorized access or disclosure. Fluent Bit provides a simple and effective way of masking sensitive information using the &lt;code&gt;lua&lt;/code&gt; filter plugin. By configuring the plugin to mask specific fields or patterns in the log data, you can ensure that no sensitive information is leaked to external systems or logs.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Kubernetes Services Explained: Cluster IP, NodePort, Loadbalancer, Ingress, Ingress Controllers</title>
      <dc:creator>Master</dc:creator>
      <pubDate>Sat, 09 Jul 2022 09:33:04 +0000</pubDate>
      <link>https://forem.com/sharadregoti/kubernetes-services-explained-cluster-ip-nodeport-loadbalancer-ingress-ingress-controllers-470a</link>
      <guid>https://forem.com/sharadregoti/kubernetes-services-explained-cluster-ip-nodeport-loadbalancer-ingress-ingress-controllers-470a</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Kubernetes networking principles are really confusing 😖, especially if you're a beginner. &lt;/p&gt;

&lt;p&gt;Regardless of how well I follow the official documentation. I honestly didn’t understand a single damn thing !!!&lt;/p&gt;

&lt;p&gt;After watching some tutorials on Youtbube I was able to write &amp;amp; duplicate the tutorials, but core understanding of Kubernetes networking concepts was still missing, as sometimes I myself used to get confused about what to use where...&lt;/p&gt;

&lt;p&gt;This blog post is my take to explain kubernetes networking concepts in depth &amp;amp; answer the below questions that I had that always confused me...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How Kubernetes networking resource solves &lt;strong&gt;Service Discovery&lt;/strong&gt; problem in Kubernetes?&lt;/li&gt;
&lt;li&gt;Does a Load Balancer Service really provisions a Load Balancer automatically? What will happen if I create this service locally?&lt;/li&gt;
&lt;li&gt;How does a production ready Kubernetes cluster expose it’s applications?&lt;/li&gt;
&lt;li&gt;What is the difference between Ingress &amp;amp; Ingress Controller?&lt;/li&gt;
&lt;li&gt;and more...&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Let’s Get Started
&lt;/h2&gt;

&lt;p&gt;Throughout the entire blog post, we will assume the following. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have familiarity with the structure of Kubernetes YAML resource definition&lt;/li&gt;
&lt;li&gt;You have deployed an imaginary Kubernetes cluster on the cloud across 3 VMs, the VMs/nodes have the following &lt;strong&gt;Public IP addresses&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Node A (192.168.0.1)&lt;/li&gt;
&lt;li&gt;Node B (192.168.0.2)&lt;/li&gt;
&lt;li&gt;Node C (192.168.0.3)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;A microservices application having 4 services is deployed on that K8s cluster. the application is deployed in such a way that each VM has at least 1 replica of that service running

&lt;ul&gt;
&lt;li&gt;Products&lt;/li&gt;
&lt;li&gt;Reviews&lt;/li&gt;
&lt;li&gt;Details&lt;/li&gt;
&lt;li&gt;Ratings&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Notations

&lt;ul&gt;
&lt;li&gt;$Reviews_A$ denotes that the &lt;code&gt;Reviews&lt;/code&gt; service is running on node A&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;K8s&lt;/strong&gt; denotes Kubernetes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LBs&lt;/strong&gt; denotes Load Balancers&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KjOoaaH4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sharadregoti/sharadregoti.github.io/main/images/2022-06-24-01-explained-kubernetes-services-ingress/blog-architecture.drawio_%282%29.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KjOoaaH4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sharadregoti/sharadregoti.github.io/main/images/2022-06-24-01-explained-kubernetes-services-ingress/blog-architecture.drawio_%282%29.svg" alt="Kubernetes Cluster" width="527" height="287"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kubernetes Cluster&lt;/p&gt;

&lt;p&gt;Let's start with answering the &lt;strong&gt;why&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  🤔 Why do we need services in the first place?
&lt;/h1&gt;

&lt;p&gt;In the K8s cluster, our application code is running inside containers using the K8s &lt;strong&gt;Deployment&lt;/strong&gt; resource. This deployment resource internally creates a K8s &lt;strong&gt;Pod&lt;/strong&gt; resource which in turn actually runs the containers.&lt;/p&gt;

&lt;p&gt;K8s assigns an IP address whenever a pod is created. The command below shows you an example IP address of the Pod&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="s"&gt;kubectl get pods &amp;lt;pod-name&amp;gt; -o wide&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1k3CDHGd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sharadregoti/sharadregoti.github.io/main/images/2022-06-24-01-explained-kubernetes-services-ingress/pod-ip.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1k3CDHGd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sharadregoti/sharadregoti.github.io/main/images/2022-06-24-01-explained-kubernetes-services-ingress/pod-ip.png" alt="Example Pod IP" width="880" height="67"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Example Pod IP&lt;/p&gt;

&lt;p&gt;In our application, $Products_A$ Pod can use the IP address assigned to $Reviews_A$ Pod for communication. Well this technique works..., but it's not an elegant solution the reason being &lt;strong&gt;K8s pods are short-lived/ephemeral.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So if a pod dies for any reason, K8s will automatically restart the Pod, but the IP address assigned to that pod also changes. This in turn will lead to communication failure between the $Products_A$ &amp;amp; $Reviews_A$ micro-service as the IP address of $Reviews_A$ service is hardcoded in the configuration file of $Products_A$ service. This is problematic !!!&lt;/p&gt;

&lt;p&gt;Wouldn’t it be great if somehow a static IP address or a DNS name gets assigned to the Pod? This will solve our above problem.&lt;/p&gt;

&lt;p&gt;That’s where the &lt;strong&gt;Service&lt;/strong&gt; resource of K8s comes to the rescue. I know the name Service sounds deceiving. A Service *&lt;strong&gt;*resource doesn't run our containers. **It merely provides and maintains a network identity for our Pod resource.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This &lt;strong&gt;Service&lt;/strong&gt; network identity provides both a static IP address &amp;amp; a DNS name, we just need to specify the ports on which the incoming request will be received &amp;amp; the port of the pod on which the request has to be sent.&lt;/p&gt;

&lt;p&gt;Services listen on a static address that doesn't change &amp;amp; forwards the request to the unreliable container address. The way it works is that internally it keeps a map that always contains the latest IP address of the Pod. so whenever a Pod restarts it updates that map automatically so you get a seamless connection.&lt;/p&gt;

&lt;p&gt;Another benefit of using services is load balancing between replicas of the same application, With our imaginary application as there are 3 instances of each micro-service running on separate VMs, A service will load balance the request between the replicas of  $Products_A$ $Proudcts_B$ $Products_C$.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--t7vP_DjV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sharadregoti/sharadregoti.github.io/main/images/2022-06-24-01-explained-kubernetes-services-ingress/kubernetes-service-load-balancing.drawio.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--t7vP_DjV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sharadregoti/sharadregoti.github.io/main/images/2022-06-24-01-explained-kubernetes-services-ingress/kubernetes-service-load-balancing.drawio.svg" alt="Load Balancing between Pods in K8s using Service Resource" width="880" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Load Balancing between Pods in K8s using Service Resource&lt;/p&gt;

&lt;p&gt;Till now we have understood what are services &amp;amp; why are they needed, Let's check out the different services that K8s offers with their use cases&lt;/p&gt;

&lt;h1&gt;
  
  
  🤔 How do I make $Products_A$ service talk to $Reviews_A$ service?
&lt;/h1&gt;

&lt;h3&gt;
  
  
  ClusterIP Service to the rescue
&lt;/h3&gt;

&lt;p&gt;The following YAML defines a service of type ClusterIP&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;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;reviews&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;reviews&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;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;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5000&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;targetPort&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;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;reviews&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterIP&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important fields in these YAML are&lt;/p&gt;

&lt;p&gt;&lt;code&gt;targetPort&lt;/code&gt;: denotes the container port on which the request has to be forwarded&lt;/p&gt;

&lt;p&gt;&lt;code&gt;port&lt;/code&gt;: denotes the port on which the service accepts incoming requests&lt;/p&gt;

&lt;p&gt;&lt;code&gt;selector&lt;/code&gt;: This field is used for associating/attaching a K8s &lt;strong&gt;Service&lt;/strong&gt; resource to a K8s &lt;strong&gt;Pod&lt;/strong&gt; resource, this is done by matching labels (key-value pairs) of the pod with selectors labels specified in the selector section.&lt;/p&gt;

&lt;p&gt;📌 Selectors labels defined in the service performs &lt;strong&gt;AND&lt;/strong&gt; operation for attaching a service to a pod, meaning all the labels must match for attachment to be done&lt;/p&gt;

&lt;p&gt;The command below shows you the static IP address of the service which can be used by other Pods&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get service &amp;lt;service-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2W9BiH1X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sharadregoti/sharadregoti.github.io/main/images/2022-06-24-01-explained-kubernetes-services-ingress/clusterip-kubectl-service.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2W9BiH1X--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sharadregoti/sharadregoti.github.io/main/images/2022-06-24-01-explained-kubernetes-services-ingress/clusterip-kubectl-service.png" alt="clusterip-kubectl-service.png" width="880" height="92"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can use the above IP address for communication between $Products_A$ &amp;amp; $Reviews_A$ micro-service &lt;/p&gt;

&lt;p&gt;To communicate using DNS, there are 2 ways&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pods residing in the same K8s &lt;strong&gt;Namespace&lt;/strong&gt; can use the name of the service for DNS resolution'

&lt;ul&gt;
&lt;li&gt;Example → &lt;code&gt;http://reviews:5000&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Pods residing in other namespaces can use the following DNS notation → &lt;code&gt;&amp;lt;service-name&amp;gt;.&amp;lt;namespace&amp;gt;.svc.cluster.local&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Let's say $Products$ Pod resides in &lt;strong&gt;products namespaces&lt;/strong&gt; &amp;amp; $Reviews$ pod resides in &lt;strong&gt;reviews namespace&lt;/strong&gt;, then for $Products$ pod to communicate with $Reviews$ pod you would use the following DNS → &lt;code&gt;http://reviews.reviews.svc.cluster.local:5000&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now you can pass these addresses to your microservice for communication.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iZ4g1Rw0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sharadregoti/sharadregoti.github.io/main/images/2022-06-24-01-explained-kubernetes-services-ingress/kubernetes-cluster-ip.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iZ4g1Rw0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sharadregoti/sharadregoti.github.io/main/images/2022-06-24-01-explained-kubernetes-services-ingress/kubernetes-cluster-ip.svg" alt="Internal Communication Using Cluster IP Service" width="880" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Internal Communication Using Cluster IP Service&lt;/p&gt;

&lt;p&gt;Till now we understood how applications inside the K8s cluster talk to each other, but you made your application to be consumed by users on the internet. Let’s check out how it is done.&lt;/p&gt;

&lt;h1&gt;
  
  
  🤔 How do I expose $Products_A$ service over the internet?
&lt;/h1&gt;

&lt;p&gt;Every application that is deployed in K8s by default cannot be accessed over the network/internet, they need to be exposed Via a &lt;strong&gt;Services&lt;/strong&gt;. K8s provides 2 &lt;strong&gt;Services&lt;/strong&gt; to do just that&lt;/p&gt;

&lt;h3&gt;
  
  
  NodePort Service
&lt;/h3&gt;

&lt;p&gt;The following YAML can be used to create a service of type NodePort&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;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;reviews&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;reviews&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;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;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5000&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;targetPort&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;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;reviews&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NodePort&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above YAML definition is very similar to the &lt;strong&gt;ClusterIP Service&lt;/strong&gt; definition, the only field that has changed is the &lt;code&gt;type&lt;/code&gt; field from &lt;strong&gt;ClusterIP to NodePort&lt;/strong&gt;. When you create a NodePort service, K8s will randomly select any available port on the node/VM between &lt;strong&gt;30000 - 32767&lt;/strong&gt; and listen on it for incoming requests.&lt;/p&gt;

&lt;p&gt;📌 You can specify the nodeport field yourself in the service definition, but you have to deal with hassle checking if the port is available on every node&lt;/p&gt;

&lt;p&gt;After creating the service, To get the port on which this NodePort service is listening for requests use the below command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get service &amp;lt;service-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5mipAx8s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sharadregoti/sharadregoti.github.io/main/images/2022-06-24-01-explained-kubernetes-services-ingress/node-port-service.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5mipAx8s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sharadregoti/sharadregoti.github.io/main/images/2022-06-24-01-explained-kubernetes-services-ingress/node-port-service.png" alt="node-port-service.png" width="880" height="99"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In our imaginary K8s cluster, this will happen on all the nodes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node A (192.168.0.1:30519)&lt;/li&gt;
&lt;li&gt;Node B (192.168.0.2:30519)&lt;/li&gt;
&lt;li&gt;Node C (192.168.0.3:30519)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can access your application using the address &lt;strong&gt;nodeIP:30519&lt;/strong&gt;, for Node A it would be 192.168.0.1:30519.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gHfIbCtm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sharadregoti/sharadregoti.github.io/main/images/2022-06-24-01-explained-kubernetes-services-ingress/kubernetes-nodeport-service.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gHfIbCtm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sharadregoti/sharadregoti.github.io/main/images/2022-06-24-01-explained-kubernetes-services-ingress/kubernetes-nodeport-service.svg" alt="Exposing Application Using Nodeport Service" width="880" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Exposing Application Using Nodeport Service&lt;/p&gt;

&lt;p&gt;But this is not practical, users of your application won’t remember your IP address &amp;amp; port for accessing your app. They need a domain name like &lt;a href="http://myapp.com"&gt;&lt;code&gt;myapp.com&lt;/code&gt;&lt;/a&gt; to access your app. We solve this by putting an external load balancer in front of our VMs. The load balancers public IP is mapped to myapp.com. So when you type myapp.com on the browser it resolves to load balancer Ip, Then the load balancer forwards these requests to any of our 3 nodes according algorithm configured in load balancer.&lt;/p&gt;

&lt;p&gt;K8s provides another service to expose your application, it is called the Load Balancer service.&lt;/p&gt;

&lt;h3&gt;
  
  
  Load Balancer
&lt;/h3&gt;

&lt;p&gt;Following Yaml can be used a create a service of type Load Balancer&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;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;reviews&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;reviews&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;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;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5000&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;targetPort&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;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;reviews&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;LoadBalancer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above YAML definition is very similar to the &lt;strong&gt;ClusterIP Service&lt;/strong&gt; definition, the only field that has changed is the &lt;code&gt;type&lt;/code&gt; field from &lt;strong&gt;ClusterIP to LoadBalancer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Load Balancer service is an abstraction over the NodePort service, What’s special about this service is that If you are using a managed Kubernetes service like EKS(AWS), GKS(GCP), AKS(Azure) or any other cloud provider, it provisions a load balancer by itself so that you don’t have to hassle setting up a load balancer yourself.&lt;/p&gt;

&lt;p&gt;After creating the service, To get the public IP address of the load balancer provisioned by this service use the below command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get service &amp;lt;service-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mObjyjBl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sharadregoti/sharadregoti.github.io/main/images/2022-06-24-01-explained-kubernetes-services-ingress/load-balancer-ip.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mObjyjBl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sharadregoti/sharadregoti.github.io/main/images/2022-06-24-01-explained-kubernetes-services-ingress/load-balancer-ip.png" alt="Load Balancer Service Example" width="880" height="89"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Load Balancer Service Example&lt;/p&gt;

&lt;p&gt;But what happens if you create a LoadBalancer service on your local K8s cluster or configured your own K8s from scratch on the cloud?&lt;/p&gt;

&lt;p&gt;The answer is it won’t do anything, you will see a &lt;strong&gt;&lt;/strong&gt; state for the IP address section. The reason is cloud-specific K8s clusters add other special programs/controllers which detects the Load Balancer service creation and takes the appropriate action accordingly.&lt;/p&gt;

&lt;p&gt;One thing to note here, Loadbalancer service doesn’t expose any ports by itself like the NodePort service&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LoadBalancer&lt;/strong&gt; is a superset of &lt;strong&gt;NodePort&lt;/strong&gt; is a superset of &lt;strong&gt;clusterIP&lt;/strong&gt; service, which means when you create a service of type Nodeport a ClusterIP service also gets created implicitly. So if you create a NodePort service for $Products$ microservice, then this same service can be used for both internal communications by other pods &amp;amp; accessing the $Products$ service on the internet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5x8KZlY9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sharadregoti/sharadregoti.github.io/main/images/2022-06-24-01-explained-kubernetes-services-ingress/superset.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5x8KZlY9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sharadregoti/sharadregoti.github.io/main/images/2022-06-24-01-explained-kubernetes-services-ingress/superset.svg" alt="Service Superset" width="201" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Service Superset&lt;/p&gt;

&lt;h1&gt;
  
  
  🤔 What should we use NodePort or LoadBalancer service?
&lt;/h1&gt;

&lt;p&gt;If you read carefully, you will observe there is not much difference between the NodePort &amp;amp; LoadBalancer service. Except for some automation being done in the latter one. &lt;/p&gt;

&lt;p&gt;Using a Load Balancer service takes away the trivial task of configuring &amp;amp; provisioning LBs. Whereas using a NodePort gives you the freedom to set up your own load-balancing solution, such that to configure environments that are not fully supported by Kubernetes, or even to expose one or more nodes' IPs directly.&lt;/p&gt;

&lt;p&gt;So it depends upon the situation you are in, but the general rule of thumb is to try to use LoadBalancer service first if it doesn’t work for your environment go for NodePort service&lt;/p&gt;

&lt;p&gt;That is it, these two services are used to expose your application outside of the cluster. But there is a slight problem. &lt;/p&gt;

&lt;p&gt;If you want to expose more than one application, you end up creating multiple NodePort / LoadBalancer Services. This gets the job done but you have to face some consequences because with each NodePort service you need to deal with the hassle of manually managing the IPs &amp;amp; ports. And with each LoadBalancer service, you go on increasing your cloud bill.&lt;/p&gt;

&lt;p&gt;No worries 😟, K8s has addressed this issue with the use of &lt;strong&gt;Ingress &amp;amp; Ingress controllers.&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  🤔 How to expose multiple applications without creating multiple services
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Ingress &amp;amp; Ingress controller
&lt;/h3&gt;

&lt;p&gt;Ingress &amp;amp; Ingress controller are two different things, people usually get confused with these terms&lt;/p&gt;

&lt;p&gt;An Ingress controller is just another K8s Deployment resource (an app running in a container), but what is special about this deployment is that it provides a single point of control for all incoming traffic into the Kubernetes cluster&lt;/p&gt;

&lt;p&gt;Think of &lt;strong&gt;Ingress controller&lt;/strong&gt; as a smart proxy running in K8s &amp;amp; &lt;strong&gt;Ingress&lt;/strong&gt; is a K8s resource that configures the routing logic of &lt;strong&gt;Ingress controller.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;💡 Analogy, For people who have worked with Nginx (Nginx the webserver will be your Ingress controller, the nginx.conf file will be your Ingress resource)&lt;/p&gt;

&lt;p&gt;With these, you can specify what request needs to be routed to which service in your k8s cluster on the basis of any request parameter like host, URL path, sub domain etc...&lt;/p&gt;

&lt;p&gt;Following Yaml can be used to create Ingress resource&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Ingress&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ingress-wildcard-host&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;ingressClassName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;products.myapp.com"&lt;/span&gt;
    &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;pathType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Prefix&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/products"&lt;/span&gt;
        &lt;span class="na"&gt;backend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;products-app&lt;/span&gt;
            &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;number&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ratings.foo.com"&lt;/span&gt;
    &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;pathType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Prefix&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/ratings"&lt;/span&gt;
        &lt;span class="na"&gt;backend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ratings-app&lt;/span&gt;
            &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;number&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the above YAML, we have exposed two services, if a request comes from &lt;code&gt;products.myapp.com&lt;/code&gt; and the request path starts with &lt;code&gt;/proudcts&lt;/code&gt; we send it to our products-app &lt;strong&gt;K8s Service&lt;/strong&gt; which in turn forwards the request to our container. &lt;/p&gt;

&lt;p&gt;Similarly, if a request comes from &lt;code&gt;ratings.bar.com&lt;/code&gt; it is forwarded to ratings-app&lt;/p&gt;

&lt;h3&gt;
  
  
  Ingress YAML Explaination
&lt;/h3&gt;

&lt;p&gt;The important fields in these YAML are&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ingressClassName&lt;/code&gt;: Usually there is only one ingress controller in the cluster, but no one has stopped you from creating many. So this field is used for the selection of ingress controller, similar to the selector field of services&lt;/p&gt;

&lt;p&gt;&lt;code&gt;service&lt;/code&gt;: denotes the name of service on which the request has to be forwarded&lt;/p&gt;

&lt;p&gt;An ingress resource should be created in the same namespace where the corresponding &lt;strong&gt;K8s Service&lt;/strong&gt; resides, But an ingress controller can be placed in any namespace, it will automatically detect Ingresess defined in other namespaces on the basis of &lt;code&gt;ingressClassName&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;An important thing to remember an Ingress by itself doesn’t expose any port. In the end, it's just a K8s deployment resource. You need a service(NodePort/LoadBalancer) in front of it to expose it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6BvCsSbK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sharadregoti/sharadregoti.github.io/main/images/2022-06-24-01-explained-kubernetes-services-ingress/production-setup.drawio.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6BvCsSbK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/sharadregoti/sharadregoti.github.io/main/images/2022-06-24-01-explained-kubernetes-services-ingress/production-setup.drawio.svg" alt="Exposing Application Using Load Balancer Service" width="880" height="284"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Exposing Application Using Load Balancer Service&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclustion
&lt;/h2&gt;

&lt;p&gt;Congratulation for sticking to the end, Let’s summarize what we have learned so far.&lt;br&gt;
Kubernetes gives us 3 types of Service Resource Object&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cluster IP Service&lt;/strong&gt;→

&lt;ul&gt;
&lt;li&gt;Used for internal communication amoung workloads &amp;amp; solves &lt;strong&gt;Service Discovery.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nodeport Service&lt;/strong&gt; →

&lt;ul&gt;
&lt;li&gt;Used for exposing applications over the internet, mostly used in development environments&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load Balancer Service&lt;/strong&gt; →

&lt;ul&gt;
&lt;li&gt;Used for exposing applications over the internet&lt;/li&gt;
&lt;li&gt;Provision actual load balancer on the cloud, on supported cloud platforms&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ingress Resource&lt;/strong&gt; →

&lt;ul&gt;
&lt;li&gt;Used for controlling incoming traffic in the Kubernetes cluster&lt;/li&gt;
&lt;li&gt;Various implementations are available each with it’s pros &amp;amp; cons&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s it in this blog post, If you liked this blog post. You can also checkout my YouTube channel where we talk about M*&lt;em&gt;icroservices, Cloud &amp;amp; Kubernetes,&lt;/em&gt;* you can check it out here 👉&lt;a href="https://l.linklyhq.com/l/KhmP"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have any questions you can reach me on Twitter at &lt;a href="https://twitter.com/SharadRegoti"&gt;@SharadRegoti&lt;/a&gt;&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
