<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Gursimar Singh - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Gursimar Singh - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sun, 24 May 2026 22:24:01 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/author/gursimar/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Automate Alert Provisioning with the SigNoz Terraform Provider ]]>
                </title>
                <description>
                    <![CDATA[ Modern infrastructure requires continuous monitoring and rapid incident response. However, manually configuring and managing alerts is not only labor-intensive but also susceptible to human error. Automating alert provisioning allows you to enforce c... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/automate-alert-provisioning-with-the-signoz-terraform-provider/</link>
                <guid isPermaLink="false">67d87353b13a6fd9fb559ada</guid>
                
                    <category>
                        <![CDATA[ observability ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Terraform ]]>
                    </category>
                
                    <category>
                        <![CDATA[ automation ]]>
                    </category>
                
                    <category>
                        <![CDATA[ signoz ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Gursimar Singh ]]>
                </dc:creator>
                <pubDate>Mon, 17 Mar 2025 19:09:07 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1742237716002/3e7d07f8-39f7-45ba-aac3-d421f61a8785.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Modern infrastructure requires continuous monitoring and rapid incident response. However, manually configuring and managing alerts is not only labor-intensive but also susceptible to human error.</p>
<p>Automating alert provisioning allows you to enforce consistency, secure sensitive credentials, and integrate monitoring into your deployment pipelines.</p>
<p>This guide dives deep into how you can use the SigNoz Terraform Provider to define and manage alert configurations as code, making your observability setup resilient and adaptable.</p>
<h3 id="heading-heres-what-well-cover">Here’s what we’ll cover:</h3>
<ol>
<li><p><a class="post-section-overview" href="#heading-why-automate-alert-provisioning">Why Automate Alert Provisioning?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-are-signoz-and-terraform">What are SigNoz and Terraform?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-overview-of-the-setup">Overview of the Setup</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-steps-to-setup-the-project">Steps to Set Up the Project</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-best-practices-and-security-considerations">Best Practices and Security Considerations</a></p>
</li>
<li><p><a class="post-section-overview" href="#integrating-with-cicd-pipelines">Integrating with CI/CD Pipelines</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-advanced-customizations-and-troubleshooting">Advanced Customizations and Troubleshooting</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-why-automate-alert-provisioning">Why Automate Alert Provisioning?</h2>
<p>It’s a good idea to automate your alert provisioning for various reasons.</p>
<p>First of all, configuring things manually often leads to discrepancies between environments (development, staging, production). Automating alerts ensures that all environments adhere to the same monitoring standards, reducing the likelihood of configuration drift and improving consistency and uniformity.</p>
<p>Also, when alerts are defined as code, every change is tracked in your version control system. This audit trail makes it easier to trace and review changes, collaborate with team members, and roll back configurations if issues arise.</p>
<p>Something else to consider is that as your infrastructure grows, manually managing alerts becomes unsustainable. Automation allows you to quickly and efficiently update your alerting rules across multiple services without the need for repetitive manual intervention.</p>
<p>Automation also helps improve security. Storing sensitive information like API tokens as environment variables or in secret management systems helps maintain security. Automating the process also minimizes human exposure to critical credentials.</p>
<p>And finally, defining alerts as code enables you to integrate monitoring configurations into your CI/CD pipelines. This leads to continuous testing, validation, and deployment of alert rules alongside application updates.</p>
<p>So as you can see, there are many compelling reasons to go the automation route. Now let’s see how you can do this in practice.</p>
<h2 id="heading-what-are-signoz-and-terraform">What Are SigNoz and Terraform?</h2>
<p>SigNoz is an open-source observability platform designed to collect, analyze, and visualize metrics, logs, and traces from your applications. Its most helpful features include:</p>
<ul>
<li><p>It has comprehensive monitoring abilities: Provides detailed insights into system performance, error rates, and user behaviors.</p>
</li>
<li><p>It comes equipped with real-time analytics: Enables proactive issue detection and performance optimization.</p>
</li>
<li><p>It’s community-driven: As an open-source solution, it benefits from community contributions, transparency, and customization.</p>
</li>
<li><p>It’s cost-effective: Offers powerful observability capabilities without the hefty licensing fees of proprietary solutions.</p>
</li>
</ul>
<p>Terraform is an Infrastructure as Code (IaC) tool developed by HashiCorp. It allows you to define and provision infrastructure using declarative configuration files. Terraform’s core advantages include:</p>
<ul>
<li><p>Its declarative syntax: You specify the desired state of your infrastructure, and Terraform handles the implementation.</p>
</li>
<li><p>Its version Control: Configuration files can be managed in Git repositories, enabling traceability and rollback of changes.</p>
</li>
<li><p>Powerful automation: Facilitates automated provisioning and updates, reducing manual effort and errors.</p>
</li>
<li><p>Multi-cloud support: Manages resources across different cloud providers with a consistent workflow.</p>
</li>
</ul>
<p>So you might be wondering: why should you use Terraform with SigNoz?</p>
<p>First of all, Terraform ensures that your infrastructure is managed consistently across different environments, reducing the risk of configuration drift. It also simplifies managing multiple alerts and resources, making it easier to scale your observability setup.</p>
<p>Beyond this, automating the provisioning process reduces manual setup efforts and minimizes the potential for human error.</p>
<p>And finally, Terraform configurations can be version-controlled, allowing teams to track changes over time and collaborate more effectively.</p>
<h2 id="heading-overview-of-the-setup">Overview of the Setup</h2>
<p>This setup utilizes the SigNoz Terraform Provider to manage alerts and notification channels within SigNoz Cloud. The configuration includes:</p>
<ul>
<li><p><strong>Provider configuration:</strong> Establishes the connection to SigNoz using the API endpoint and a securely provided API token.</p>
</li>
<li><p><strong>Notification channels:</strong> Defines where alerts are sent (for example, via email) to ensure the right teams are notified.</p>
</li>
<li><p><strong>Alert rules:</strong> Specifies the conditions under which alerts are triggered, including thresholds and evaluation windows.</p>
</li>
<li><p><strong>External variables:</strong> Enhances flexibility by allowing critical values (like CPU thresholds and email addresses) to be managed externally.</p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before diving into the setup, make sure you have the following:</p>
<ol>
<li><p><strong>SigNoz Cloud account</strong>: If you don't have one, sign up for SigNoz Cloud to host your observability data and configure alerts.</p>
</li>
<li><p><strong>Terraform installed</strong>: Install Terraform on your machine. Terraform is the tool you'll use to manage your infrastructure as code.</p>
</li>
<li><p><strong>SigNoz API token</strong>:</p>
<ul>
<li><p>Log in to your SigNoz Cloud dashboard.</p>
</li>
<li><p>Navigate to Settings &gt; API Tokens.</p>
</li>
<li><p>Click Generate API Token.</p>
</li>
<li><p>Copy the token, as you'll need it to authenticate Terraform with SigNoz.</p>
</li>
</ul>
</li>
<li><p><strong>Basic knowledge of Terraform</strong>: Familiarity with Terraform's syntax and concepts, including writing configuration files and running Terraform commands, is essential.</p>
</li>
<li><p><strong>Text editor</strong>: Use any code editor like Visual Studio Code or Sublime Text to write your Terraform configuration files.</p>
</li>
</ol>
<h2 id="heading-steps-to-set-up-the-project">Steps to Set Up the Project</h2>
<h3 id="heading-1-understand-the-signozalert-resource">1. Understand the <code>signoz_alert</code> Resource</h3>
<p>The <code>signoz_alert</code> resource allows you to create and manage alert rules in SigNoz via Terraform. It supports various alert types, conditions, and configurations. Understanding this resource is crucial as it forms the basis of your alert configuration.</p>
<h3 id="heading-2-set-up-your-terraform-configuration">2. Set Up Your Terraform Configuration</h3>
<p>Create a new directory for your Terraform configuration:</p>
<pre><code class="lang-bash">mkdir signoz-terraform
<span class="hljs-built_in">cd</span> signoz-terraform
</code></pre>
<p>Create a <a target="_blank" href="http://main.tf"><code>main.tf</code></a> file with the following content:</p>
<pre><code class="lang-json">terraform {
  required_providers {
    signoz = {
      source  = <span class="hljs-attr">"SigNoz/signoz"</span>
      version = <span class="hljs-attr">"0.1.3"</span> # Use the latest version from the Terraform Registry
    }
  }
}

provider <span class="hljs-string">"signoz"</span> {
  endpoint  = <span class="hljs-attr">"https://api.us.signoz.cloud"</span> # Replace with your SigNoz Cloud API endpoint
  api_token = var.signoz_api_token
}

variable <span class="hljs-string">"signoz_api_token"</span> {}
</code></pre>
<p>The <code>provider</code> block configures the SigNoz provider, where <code>endpoint</code> specifies the API endpoint and <code>api_token</code> is passed through a variable for security.</p>
<h3 id="heading-3-define-a-notification-channel-optional">3. Define a Notification Channel (Optional)</h3>
<p>If you plan to send alerts to specific channels, define them using <code>signoz_notification_channel</code>. For example, create a <a target="_blank" href="http://channels.tf"><code>channels.tf</code></a> file:</p>
<pre><code class="lang-json">resource <span class="hljs-string">"signoz_notification_channel"</span> <span class="hljs-string">"email_channel"</span> {
  name = <span class="hljs-attr">"Email Channel"</span>
  type = <span class="hljs-attr">"email"</span>

  receivers {
    email_config {
      to = [<span class="hljs-attr">"alerts@example.com"</span>]
    }
  }
}
</code></pre>
<p>Defining a notification channel ensures that alerts are sent to the correct recipients, enhancing the utility of your alerting system.</p>
<h3 id="heading-4-create-an-alert-using-the-signozalert-resource">4. Create an Alert Using the <code>signoz_alert</code> Resource</h3>
<p>Create an <a target="_blank" href="http://alerts.tf"><code>alerts.tf</code></a> file to define your alert:</p>
<pre><code class="lang-json">resource <span class="hljs-string">"signoz_alert"</span> <span class="hljs-string">"cpu_high_usage"</span> {
  alert            = <span class="hljs-attr">"High CPU Usage Alert"</span>
  alert_type       = <span class="hljs-attr">"METRIC_BASED_ALERT"</span>
  severity         = <span class="hljs-attr">"critical"</span>
  description      = <span class="hljs-attr">"Alert when CPU usage exceeds 80% over 5 minutes"</span>
  rule_type        = <span class="hljs-attr">"threshold_rule"</span>
  broadcast_to_all = false
  disabled         = false
  eval_window      = <span class="hljs-attr">"5m0s"</span>
  frequency        = <span class="hljs-attr">"1m0s"</span>
  version          = <span class="hljs-attr">"v4"</span>

  condition = jsonencode({
    compositeQuery = {
      builderQueries = {
        A = {
          aggregateOperator = <span class="hljs-attr">"avg"</span>
          dataSource        = <span class="hljs-attr">"metrics"</span>
          metricName        = <span class="hljs-attr">"cpu_usage_user"</span>
          reduceTo          = <span class="hljs-attr">"avg"</span>
          filters           = {
            items = []
            op    = <span class="hljs-attr">"AND"</span>
          }
          groupBy = []
        }
      }
      queryType = <span class="hljs-string">"builder"</span>
      panelType = <span class="hljs-string">"graph"</span>
      unit      = <span class="hljs-string">"%"</span>
    }
    op                = <span class="hljs-string">"&gt;"</span>
    target            = <span class="hljs-number">80</span>
    matchType         = <span class="hljs-string">"EQUALS"</span>
    selectedQueryName = <span class="hljs-string">"A"</span>
    targetUnit        = <span class="hljs-string">"%"</span>
  })

  preferred_channels = [signoz_notification_channel.email_channel.name]

  labels = {
    severity = <span class="hljs-attr">"critical"</span>
    team     = <span class="hljs-attr">"DevOps"</span>
  }
}
</code></pre>
<p>This configuration creates a high CPU usage alert with specific conditions and notifications. The <code>condition</code> parameter is crucial as it defines the alert triggering logic.</p>
<h3 id="heading-5-provide-the-api-token">5. Provide the API Token</h3>
<p>Set the <code>signoz_api_token</code> as an environment variable:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">export</span> TF_VAR_signoz_api_token=<span class="hljs-string">"YOUR_SIGNOZ_API_TOKEN"</span>
</code></pre>
<p>This ensures that your API token is securely used by Terraform without hardcoding it in your configuration files.</p>
<h3 id="heading-6-initialize-terraform">6. Initialize Terraform</h3>
<p>Run:</p>
<pre><code class="lang-bash">terraform init
</code></pre>
<p>This command initializes your Terraform working directory, downloading necessary plugins, and preparing the environment.</p>
<h3 id="heading-7-review-the-execution-plan">7. Review the Execution Plan</h3>
<p>Generate the execution plan:</p>
<pre><code class="lang-bash">terraform plan
</code></pre>
<p>This step previews the changes Terraform will make, allowing you to verify the configuration before applying it.</p>
<h3 id="heading-8-apply-the-configuration">8. Apply the Configuration</h3>
<p>Apply the changes:</p>
<pre><code class="lang-bash">terraform apply
</code></pre>
<p>Type <code>yes</code> when prompted. This command applies the configuration, creating or updating resources as specified.</p>
<h3 id="heading-9-verify-the-alert-in-signoz-cloud">9. Verify the Alert in SigNoz Cloud</h3>
<p>To do this, follow these steps:</p>
<ul>
<li><p>Log in to your SigNoz Cloud dashboard.</p>
</li>
<li><p>Navigate to Alerts.</p>
</li>
<li><p>Confirm that the "High CPU Usage Alert" is listed.</p>
</li>
<li><p>Click on the alert to view its details and ensure it matches your configuration.</p>
</li>
</ul>
<h3 id="heading-10-modify-the-alert-optional">10. Modify the Alert (Optional)</h3>
<p>To change the CPU usage threshold to 75%, follow these steps:</p>
<ul>
<li><p>Update the target in <a target="_blank" href="http://alerts.tf"><code>alerts.tf</code></a>:</p>
<pre><code class="lang-json">  target = <span class="hljs-number">75</span>
</code></pre>
</li>
<li><p>Apply the changes:</p>
<pre><code class="lang-bash">  terraform apply
</code></pre>
</li>
</ul>
<h3 id="heading-11-destroy-the-resources-optional">11. Destroy the Resources (Optional)</h3>
<p>To remove the alert and notification channel:</p>
<pre><code class="lang-bash">terraform destroy
</code></pre>
<p>Type <code>yes</code> to confirm. This command will delete the resources created by Terraform.</p>
<h2 id="heading-best-practices-and-security-considerations">Best Practices and Security Considerations</h2>
<p>In modern infrastructure automation, robust best practices and security measures are paramount.</p>
<h3 id="heading-use-version-pinning">Use version pinning</h3>
<p>To ensure your alert provisioning remains reliable and maintainable, start with strict version control. Avoid using the latest tag and instead specify an exact version number. This ensures your infrastructure configuration remains consistent and predictable.</p>
<p>By pinning your provider version (for example, use version = "0.1.3" instead of version = "&gt;= 0.1.3".), you eliminate unexpected behavior that can arise from upstream changes. This practice is critical for long-term stability, especially when your infrastructure scales across multiple environments.</p>
<h3 id="heading-externalize-credentials"><strong>Externalize Credentials</strong></h3>
<p>Security is non-negotiable. Instead of embedding sensitive details like API tokens in your codebase, leverage environment variables or dedicated secret management tools such as HashiCorp Vault or AWS Secrets Manager.</p>
<p>For instance, storing your SigNoz API token as an environment variable (TF_VAR_signoz_api_token) not only mitigates the risk of credential exposure but also simplifies the process of credential rotation. Also, enforce access control policies around your configuration repositories and CI/CD pipelines to further secure these secrets.</p>
<h3 id="heading-use-version-control"><strong>Use Version Control</strong></h3>
<p>A mature setup also demands rigorous infrastructure version control. Hosting your Terraform configuration in a Git repository with branch protection and code review policies allows you to track changes meticulously, roll back problematic updates, and maintain an audit trail. This traceability is essential when troubleshooting issues or validating compliance during audits.</p>
<p>You should also document your configuration decisions extensively—explain why a particular CPU threshold was chosen or why specific labels (like severity and team) are used. Such documentation becomes invaluable for onboarding new team members or when revisiting configurations months later.</p>
<h2 id="heading-integrating-with-cicd-pipelines">Integrating with CI/CD Pipelines</h2>
<p>Integrating Terraform with your CI/CD pipeline is a cornerstone of a modern, automated deployment strategy. A well-architected pipeline not only validates your infrastructure changes but also ensures that your alerting rules remain in sync with your evolving application environment.</p>
<p>Continuous Integration (CI) involves automatically merging code changes into a shared repository and running automated tests on each commit. In practice, embedding Terraform plan into your pull request workflow provides early feedback, catching misconfigurations before they reach production. For instance, a GitHub Actions workflow can automatically check your changes:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">name:</span> <span class="hljs-string">Terraform</span> <span class="hljs-string">CI/CD</span>

<span class="hljs-attr">on:</span>
  <span class="hljs-attr">push:</span>
    <span class="hljs-attr">branches:</span> [<span class="hljs-string">main</span>]
  <span class="hljs-attr">pull_request:</span>
    <span class="hljs-attr">branches:</span> [<span class="hljs-string">main</span>]

<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">terraform:</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>
    <span class="hljs-attr">steps:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Checkout</span> <span class="hljs-string">Repository</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v3</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Setup</span> <span class="hljs-string">Terraform</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">hashicorp/setup-terraform@v2</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Terraform</span> <span class="hljs-string">Init</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">terraform</span> <span class="hljs-string">init</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Terraform</span> <span class="hljs-string">Plan</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">terraform</span> <span class="hljs-string">plan</span> <span class="hljs-string">-no-color</span>
        <span class="hljs-attr">env:</span>
          <span class="hljs-attr">TF_VAR_signoz_api_token:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.SIGNOZ_API_TOKEN</span> <span class="hljs-string">}}</span>
</code></pre>
<p>This workflow uses GitHub secrets to securely manage your API tokens while validating the configuration changes. Continuous Delivery (CD) takes this further by automating deployments. Once your plan is approved, an automated Terraform apply step (often scheduled during off-peak hours or coordinated with application deployments) ensures smooth, coordinated rollouts.</p>
<p>Advanced pipelines can also include automated rollback mechanisms. For example, if a deployment triggers an anomaly, scripts can automatically revert to a previous version using your version control history—minimizing downtime and reinforcing the feedback loop between application performance and infrastructure configuration.</p>
<h2 id="heading-advanced-customizations-and-troubleshooting">Advanced Customizations and Troubleshooting</h2>
<p>As your observability requirements evolve, you may need to implement advanced customizations. One powerful approach is using multi-metric composite alerts. Instead of triggering an alert on a single threshold, you can design rules that combine multiple conditions—for example, firing only when both CPU usage and memory consumption exceed critical levels. This nuanced alerting minimizes false positives and ensures alerts are issued only during genuine performance issues.</p>
<p>Terraform’s modular design is especially useful here. By creating reusable modules that encapsulate your alert configurations, you can parameterize key variables—such as thresholds, evaluation windows, and notification channels—across a microservices architecture. This modularity enforces consistency while simplifying management and scaling.</p>
<p>Troubleshooting advanced configurations starts with reviewing your <code>terraform plan</code> output to ensure every change aligns with expectations. If an alert isn’t triggering as expected, inspect the JSON structure generated by the <code>jsonencode</code> function. Even minor syntax errors can cause significant issues.</p>
<p>When integrating with incident management tools like PagerDuty or Opsgenie, run comprehensive end-to-end tests in a staging environment. For example, deploy a test alert to a dedicated channel to verify that the complete alerting pipeline—from condition detection to incident escalation—is functioning correctly.</p>
<p>In one real-world scenario, a misconfigured composite query in an alert’s JSON payload led to intermittent failures. By enabling detailed provider logs and iteratively validating the JSON output, the issue was rapidly isolated and resolved. Such experiences underscore the importance of rigorous logging, validation, and testing in production-grade setups.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Automating alert provisioning is a transformative approach to managing observability in modern infrastructures.</p>
<p>By defining alerts and notification channels as code, you make your systems more consistent, scalable, secure, and easily integratabtle with CI/CD. You can set up uniform alert rules across all environments, quickly update and deploy monitoring configs, easily handle secure credentials, and automate CI/CD workflows that stay in sync with application changes. They also become easier to integrate with CI/CD workflows.</p>
<p>I hope you’ve enjoyed this tutorial and have learned something new. I’m always open to suggestions and discussions on <a target="_blank" href="https://www.linkedin.com/in/gursimarsm">LinkedIn</a>. Hit me up with direct messages.</p>
<p>If you’ve enjoyed my writing and want to keep me motivated, consider leaving starts on <a target="_blank" href="https://github.com/gursimarsm">GitHub</a> and endorsing me for relevant skills on <a target="_blank" href="https://www.linkedin.com/in/gursimarsm">LinkedIn</a>.</p>
<p>Till the next one, happy coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Choose a Cloud Development Environment – Harness CDE, Gitpod, and Coder Compared ]]>
                </title>
                <description>
                    <![CDATA[ Cloud Development Environments (CDEs) have become essential tools in modern software development, offering enhanced productivity and streamlined workflows. This article compares three leading CDEs: Harness CDE, Gitpod, and Coder. My goal here is to o... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-choose-a-cloud-development-environment/</link>
                <guid isPermaLink="false">67a22fc0b7eb4acc424cb220</guid>
                
                    <category>
                        <![CDATA[ Cloud ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Gitpod ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Harness ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Cloud Development  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Environment ]]>
                    </category>
                
                    <category>
                        <![CDATA[ coder ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Gursimar Singh ]]>
                </dc:creator>
                <pubDate>Tue, 04 Feb 2025 15:18:24 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1738612280310/a3e39db8-66e9-45f5-9bc1-60cfa426a001.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Cloud Development Environments (CDEs) have become essential tools in modern software development, offering enhanced productivity and streamlined workflows.</p>
<p>This article compares three leading CDEs: Harness CDE, Gitpod, and Coder. My goal here is to offer an objective analysis to help you make informed decisions based on your specific needs.</p>
<h2 id="heading-what-is-a-cloud-development-environment-cde">What is a Cloud Development Environment (CDE)?</h2>
<p>A <strong>Cloud Development Environment (CDE)</strong> is a cloud-hosted workspace where developers can write, test, and deploy code without relying on local machines. Unlike traditional setups, CDEs provide pre-configured environments accessible via a browser or IDE, eliminating the "it works on my machine" problem.</p>
<p>How CDEs differ from traditional development environments</p>
<ul>
<li><p>CDEs are more consistent and help standardize tools, dependencies, and configurations across teams.</p>
</li>
<li><p>They’re also accessible from anywhere, enabling remote collaboration.</p>
</li>
<li><p>They’re more scalable, as resources (CPU, memory) scale dynamically based on workload.</p>
</li>
<li><p>And they’re secure, with centralized security controls and compliance adherence (for example, SOC 2, GDPR).</p>
</li>
</ul>
<h3 id="heading-common-cde-features"><strong>Common CDE Features</strong></h3>
<p>Most CDEs come with a variety of helpful features. They typically have pre-built environment templates (for example, Python, Node.js) and integrate easily with Git repositories and CI/CD pipelines. They also have various real-time collaboration tools, as well as the ability to automate backups and recovery.</p>
<p>You’ll learn more about specific features when we discuss each of our CDE options below.</p>
<h2 id="heading-the-case-for-cloud-based-development"><strong>The Case for Cloud-Based Development</strong></h2>
<p>CDEs can help you and your team solve some critical pain points:</p>
<h3 id="heading-cdes-make-setup-easier">CDEs make setup easier</h3>
<p>When using a CDE, you don’t have the hassle of setting up local machines. Instead, you have a pre-configured development environment that’s ready to go in minutes. With a traditional setup, you have to install dependencies, configure environments, and resolve compatibility issues – and this can take hours or even days. CDEs make this process much easier.</p>
<p>Let’s say a new developer joins your project that requires a complex stack – it needs a specific Python version, multiple frameworks, and environment variables. Instead of spending hours configuring their local machine, they can just launch a cloud-based workspace (like one of the tools we’ll discuss here), which comes pre-loaded with everything they need.</p>
<h3 id="heading-cdes-help-reduce-costs">CDEs help reduce costs</h3>
<p>CDEs can reduce your costs by making sure that development resources are allocated only when they’re needed. Unlike local machines, which require upfront investment in high-performance hardware, cloud environments help you scale resources dynamically and pay only for the compute power you and your team use.</p>
<p>Perhaps your team is developing a resource-intensive AI application. If you’re using a CDE, you’ll no longer need to provide every developer with an expensive workstation. Instead, you can just provision high-performance cloud instances when needed and shut them down when idle. This cuts down on unnecessary spending.</p>
<h3 id="heading-cdes-enhance-security">CDEs enhance security</h3>
<p>With cloud-based environments, code and sensitive data remain on secure, centralized servers rather than being stored on individual developer machines. This helps reduce the risk of data loss or theft. CDEs also provide audit logs, identity management, and automated backups, all of which help make things more security.</p>
<p>Let’s say a financial services company requires strict security controls over customer data. By using a CDE, the developers on the team can access code via secure connections without storing sensitive files locally. This helps ensure compliance with industry regulations like SOC 2 or GDPR.</p>
<h3 id="heading-cdes-enable-global-collaboration">CDEs enable global collaboration</h3>
<p>CDEs make collaboration among distributed teams much easier by allowing multiple developers to work in the same environment with shared configurations. Remote developers can contribute from anywhere without worrying about compatibility issues or inconsistent setups.</p>
<p>For example, perhaps your global development team is working on a SaaS product. They can use a CDE to collaborate in real time. A member of your dev team in India can start debugging an issue, and then a teammate in the US can pick up where they left off hours later without needing to set up the same environment locally.</p>
<h2 id="heading-methodology"><strong>Methodology</strong></h2>
<p>This analysis is based on official documentation, user reviews, and independent testing. All information is current as of the last update date. The article is focused on key aspects such as features, deployment options, security, pricing, and use cases.</p>
<h2 id="heading-overview-of-each-tool"><strong>Overview of Each Tool</strong></h2>
<h3 id="heading-harness-cde">Harness CDE</h3>
<p>Harness CDE is part of the broader Harness platform, designed to streamline software delivery with integrated CI/CD pipelines, feature flags, and cloud cost management. It provides enterprise-grade security, a user-friendly interface, and robust integration capabilities, making it ideal for large-scale applications.</p>
<p>With its comprehensive suite of tools and advanced cost management, Harness CDE helps enterprises efficiently manage their entire development lifecycle. Harness CDE's intuitive interface and detailed documentation further enhance its suitability for large-scale applications.</p>
<h4 id="heading-drawbacks"><strong>Drawbacks</strong></h4>
<p>Despite its many strengths, Harness CDE is relatively new to the market, meaning its features and capabilities are still evolving. Deep integration with the Harness platform could make switching challenging.</p>
<h3 id="heading-gitpod">Gitpod</h3>
<p>Gitpod is a SaaS solution that provides automated, ready-to-code development environments. It integrates seamlessly with popular version control systems like GitHub, GitLab, and Bitbucket, offering fast and consistent setups.</p>
<p>Gitpod is known for its user-friendly web interface and quick onboarding process, which significantly reduces setup times and lets devs focus on coding rather than environment configuration. This makes it ideal for agile development teams and startups.</p>
<h4 id="heading-drawbacks-1"><strong>Drawbacks</strong></h4>
<p>Gitpod's SaaS model offers limited control over infrastructure, which can be a disadvantage for teams needing more customization and control. Also, dedicated instances can be more costly, potentially offsetting some of the benefits of its free plan.</p>
<h3 id="heading-coder">Coder</h3>
<p>Coder is an open-source platform offering both free and self-managed (paid) options. It provides highly customizable, secure, and scalable development environments that you can host on your infrastructure. This makes it suitable for organizations needing tailored solutions.</p>
<p>Coder excels in environments where stringent security and compliance requirements are paramount, offering extensive control and customization.</p>
<h4 id="heading-drawbacks-2"><strong>Drawbacks</strong></h4>
<p>Coder requires more setup time and maintenance compared to Gitpod and Harness CDE. Its reliance on self-managed infrastructure can also increase complexity and cost, particularly for smaller teams or startups without dedicated DevOps resources.</p>
<h2 id="heading-detailed-feature-comparison">Detailed Feature Comparison</h2>
<p>Now let’s compare some basic features to see how these three tools stack up against each other.</p>
<h3 id="heading-deployment-and-scalability">Deployment and Scalability</h3>
<ul>
<li><p><strong>Harness CDE</strong>: Integrated with the Harness &amp; Gitness platforms, offering high scalability within the Harness ecosystem.</p>
</li>
<li><p><strong>Gitpod</strong>: SaaS model with easy scalability and options for managed dedicated instances.</p>
</li>
<li><p><strong>Coder</strong>: Self-managed deployment with full control over infrastructure, providing high scalability for tailored environments.</p>
</li>
</ul>
<h3 id="heading-integration-and-user-experience">Integration and User Experience</h3>
<ul>
<li><p><strong>Harness CDE</strong>: Comprehensive suite of development tools, intuitive interface, and detailed documentation.</p>
</li>
<li><p><strong>Gitpod</strong>: Seamless integration with GitHub, GitLab, and Bitbucket, featuring automated setups and excellent documentation.</p>
</li>
<li><p><strong>Coder</strong>: Integrates with existing infrastructure and various tech stacks, providing detailed documentation and customizable configurations.</p>
</li>
</ul>
<h3 id="heading-security-and-compliance">Security and Compliance</h3>
<ul>
<li><p><strong>Harness CDE</strong>: Enterprise-grade security features, including SOC 2 compliance, role-based access control, and advanced secrets management. Offers comprehensive audit logging and governance with policy-as-code support.</p>
</li>
<li><p><strong>Gitpod</strong>: Secure environments with data encryption, SOC 2 compliant.</p>
</li>
<li><p><strong>Coder</strong>: Focuses on security and compliance, supporting various standards like HIPAA and GDPR.</p>
</li>
</ul>
<h3 id="heading-costpricing">Cost/Pricing</h3>
<ul>
<li><p><strong>Harness CDE</strong>: Competitive pricing with integrated platform features. A lot of features are free to use. Pricing varies based on scale and needs – contact Harness for details.</p>
</li>
<li><p><strong>Gitpod</strong>: Varies with free and paid plans, limited customization based on SaaS offerings. The free plan includes 50 hours/month, while paid plans offer unlimited hours.</p>
</li>
<li><p><strong>Coder</strong>: Costs depend on self-managed infrastructure, offering high customization and control over environment setup. The tool is free for open-source use, and paid for self-managed deployments.</p>
</li>
</ul>
<h3 id="heading-setup-time-and-user-interface">Setup Time and User Interface</h3>
<ul>
<li><p><strong>Harness CDE</strong>: Fast setup with integrated CI/CD pipeline and modern, intuitive interface.</p>
</li>
<li><p><strong>Gitpod</strong>: Quick setup in minutes with a user-friendly, web-based interface.</p>
</li>
<li><p><strong>Coder</strong>: Setup time varies based on custom configurations, offering a flexible and customizable interface.</p>
</li>
</ul>
<h3 id="heading-availability">Availability</h3>
<ul>
<li><p><strong>Harness CDE</strong>: Part of the Harness platform, typically targeted at enterprise users.</p>
</li>
<li><p><strong>Gitpod</strong>: SaaS model with both free and paid plans.</p>
</li>
<li><p><strong>Coder</strong>: Open-source with both free and self-managed (paid) options.</p>
</li>
</ul>
<h3 id="heading-specs">Specs</h3>
<ul>
<li><p><strong>Harness CDE</strong>: Integrated CI/CD, feature flags, cloud cost management, enterprise-grade security, and so on.</p>
</li>
<li><p><strong>Gitpod</strong>: Automated setups, seamless integration with VCS, user-friendly interface.</p>
</li>
<li><p><strong>Coder</strong>: Highly customizable, secure, scalable, extensive control.</p>
</li>
</ul>
<h3 id="heading-additional-features"><strong>Additional Features</strong></h3>
<p>Here’s a detailed table that includes info on a bunch of other features that might help you make your decision as to which tool is best for you.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Feature</td><td>Harness CDE</td><td>Gitpod</td><td>Coder</td></tr>
</thead>
<tbody>
<tr>
<td><strong>Data Storage</strong></td><td>Integrated with Harness</td><td>External, cloud-based storage</td><td>On-premises, cloud options available</td></tr>
<tr>
<td><strong>Resource Management</strong></td><td>Automated scaling</td><td>Easy resource allocation</td><td>Customizable resource allocation</td></tr>
<tr>
<td><strong>Monitoring and Logging</strong></td><td>Integrated monitoring tools</td><td>External tools (e.g., Grafana)</td><td>Integrated and external options</td></tr>
<tr>
<td><strong>Performance</strong></td><td>High, optimized for enterprise use</td><td>High, optimized for cloud</td><td>High, depends on infrastructure</td></tr>
<tr>
<td><strong>Updates and Maintenance</strong></td><td>Automated updates</td><td>Regular updates, easy maintenance</td><td>Manual updates, customizable maintenance</td></tr>
<tr>
<td><strong>Community Support</strong></td><td>Growing community, active forums</td><td>Active community, strong documentation</td><td>Large community, extensive documentation</td></tr>
<tr>
<td><strong>Learning Curve</strong></td><td>Moderate, user-friendly</td><td>Low, easy to start</td><td>Moderate, flexible setup</td></tr>
<tr>
<td><strong>CI/CD Integration</strong></td><td>Built-in CI/CD pipelines</td><td>Supports CI/CD via third-party integrations</td><td>Requires custom setup for CI/CD</td></tr>
<tr>
<td><strong>Collaboration Features</strong></td><td>Integrated collaboration tools</td><td>Collaboration through VCS integrations</td><td>Customizable collaboration tools</td></tr>
<tr>
<td><strong>Container Support</strong></td><td>Native Docker support</td><td>Supports containerized environments</td><td>Full containerization support</td></tr>
<tr>
<td><strong>Cost Management</strong></td><td>Integrated cost management</td><td>No built-in cost management</td><td>Requires external tools for cost management</td></tr>
<tr>
<td><strong>Workflow Automation</strong></td><td>Extensive automation features</td><td>Basic automation through scripts</td><td>High customizability for automation</td></tr>
<tr>
<td><strong>Version Control Support</strong></td><td>Seamless VCS integration</td><td>Native support for Git-based VCS</td><td>Customizable VCS integration</td></tr>
<tr>
<td><strong>API Access</strong></td><td>Comprehensive API access</td><td>Robust API for integration</td><td>Full API support for custom integration</td></tr>
<tr>
<td><strong>Code Reviews</strong></td><td>Built-in code review tools</td><td>Code reviews through VCS integrations</td><td>Customizable code review processes</td></tr>
<tr>
<td><strong>Branch Management</strong></td><td>Advanced branch management</td><td>Supports branch management through VCS</td><td>Customizable branch management</td></tr>
<tr>
<td><strong>Testing Tools</strong></td><td>Integrated testing tools</td><td>Requires third-party testing tools</td><td>Full integration with various testing tools</td></tr>
<tr>
<td><strong>Data Backup and Recovery</strong></td><td>Automated backup and recovery</td><td>Limited backup options</td><td>Requires custom setup for backup and recovery</td></tr>
<tr>
<td><strong>Cloud Provider Compatibility</strong></td><td>Supports multiple cloud providers</td><td>Primarily cloud-agnostic</td><td>Fully compatible with various cloud providers</td></tr>
<tr>
<td><strong>Onboarding Time</strong></td><td>Fast, guided onboarding</td><td>Quick, automated onboarding</td><td>Varies, depending on custom configurations</td></tr>
<tr>
<td><strong>Multi-language Support</strong></td><td>Extensive support for multiple languages</td><td>Supports many languages</td><td>Full support for various programming languages</td></tr>
<tr>
<td><strong>User Authentication</strong></td><td>Integrated authentication options</td><td>Basic authentication options</td><td>Comprehensive, customizable authentication</td></tr>
<tr>
<td><strong>Secrets Management</strong></td><td>Built-in secrets management</td><td>Requires third-party tools</td><td>Full support for secrets management</td></tr>
<tr>
<td><strong>Pipeline Visualization</strong></td><td>Advanced, intuitive pipeline visualization</td><td>Basic pipeline visualization</td><td>Customizable pipeline visualization</td></tr>
<tr>
<td><strong>Environment Provisioning</strong></td><td>Automated, scalable environment provisioning</td><td>Fast, on-demand environment provisioning</td><td>Flexible environment provisioning</td></tr>
<tr>
<td><strong>License Model</strong></td><td>Open-source and commercial licenses</td><td>Open-source and commercial licenses</td><td>Open-source and commercial licenses</td></tr>
<tr>
<td><strong>Network Isolation</strong></td><td>Built-in network isolation features</td><td>Limited network isolation</td><td>Advanced network isolation options</td></tr>
<tr>
<td><strong>Role-based Access Control</strong></td><td>Comprehensive RBAC</td><td>Basic RBAC</td><td>Advanced RBAC</td></tr>
<tr>
<td><strong>Audit Logging</strong></td><td>Detailed audit logging</td><td>Basic audit logging</td><td>Extensive audit logging</td></tr>
<tr>
<td><strong>Governance with Policy as Code</strong></td><td>Supports OPA-based policies</td><td>Limited</td><td>Advanced governance features</td></tr>
<tr>
<td><strong>Feature Flags</strong></td><td>Integrated, robust feature flag management</td><td>Requires third-party tools</td><td>Full support for feature flag management</td></tr>
<tr>
<td><strong>Internal Developer Portal</strong></td><td>Comprehensive internal developer portal</td><td>Limited</td><td>Advanced portal capabilities</td></tr>
<tr>
<td><strong>Software Supply Chain Management</strong></td><td>Integrated, secure supply chain features</td><td>Limited</td><td>Requires custom setup</td></tr>
<tr>
<td><strong>Service Reliability Management</strong></td><td>Real-time insights and reliability</td><td>Limited</td><td>Requires third-party tools</td></tr>
<tr>
<td><strong>Chaos Engineering</strong></td><td>Built-in chaos engineering tools</td><td>Requires third-party tools</td><td>Full support for chaos engineering</td></tr>
<tr>
<td><strong>Self-Managed Options</strong></td><td>Available for enterprise</td><td>Not available</td><td>Available</td></tr>
<tr>
<td><strong>Code Repository Integration</strong></td><td>Seamless integration with Git-based repositories</td><td>Limited</td><td>Full support for various repositories</td></tr>
<tr>
<td><strong>APM Integration</strong></td><td>Comprehensive APM integration</td><td>Requires third-party tools</td><td>Full support for APM integration</td></tr>
<tr>
<td><strong>Artifact Management</strong></td><td>Integrated artifact management</td><td>Limited</td><td>Full support for artifact management</td></tr>
<tr>
<td><strong>Cloud Cost Management</strong></td><td>Advanced cloud cost management features</td><td>No built-in cost management</td><td>Requires third-party tools</td></tr>
<tr>
<td><strong>AI and ML Support</strong></td><td>Built-in tools for AI/ML workflows</td><td>Requires third-party tools</td><td>Extensive support for AI/ML</td></tr>
</tbody>
</table>
</div><h3 id="heading-how-to-choose-the-right-tool"><strong>How to Choose the Right Tool</strong></h3>
<p>As you can see, each of these cloud development environments has its strengths. It’s up to you to analyze them and decide which tool is right for you. Here’s a quick summary:</p>
<ul>
<li><p>Harness CDE offers the fastest startup times and a straightforward, performance-focused approach.</p>
</li>
<li><p>Gitpod provides the widest language support and a large community, with competitive pricing.</p>
</li>
<li><p>Coder excels in security, compliance, and customization.</p>
</li>
</ul>
<p>When choosing a CDE, consider the following factors:</p>
<ul>
<li><p>Team size and structure</p>
</li>
<li><p>Existing technology stack</p>
</li>
<li><p>Security and compliance requirements</p>
</li>
<li><p>Budget constraints</p>
</li>
<li><p>Customization needs</p>
</li>
<li><p>Scalability requirements</p>
</li>
<li><p>Integration with existing tools and workflows</p>
</li>
</ul>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>In this guide, you learned about three CDE tools and their main features. Which of these tools you choose will largely depend on your specific needs.</p>
<p>Ultimately, I recommend that you take advantage of any free trials or demos offered by these platforms to get hands-on experience before making a decision. Consider your team's specific workflows, the technologies you use, and your scalability needs when choosing a cloud development environment.</p>
<h3 id="heading-references"><strong>References</strong></h3>
<ul>
<li><p><a target="_blank" href="https://developer.harness.io/docs/">Harness Docs</a></p>
</li>
<li><p><a target="_blank" href="https://www.gitpod.io/docs/introduction">Gitpod Docs</a></p>
</li>
<li><p><a target="_blank" href="https://coder.com/docs">Coder Docs</a></p>
</li>
</ul>
<p>Note: This article is for informational purposes only. Everyone should conduct their own thorough evaluation based on their specific requirements before making a decision.</p>
<p>I hope you’ve enjoyed it and have learned something new. I’m always open to suggestions and discussions on <a target="_blank" href="https://www.linkedin.com/in/gursimarsm">LinkedIn</a>. Hit me up with direct messages.</p>
<p>If you’ve enjoyed my writing and want to keep me motivated, consider leaving starts on <a target="_blank" href="https://github.com/gursimarsm">GitHub</a> and endorsing me for relevant skills on <a target="_blank" href="https://www.linkedin.com/in/gursimarsm">LinkedIn</a>.</p>
<p>Till the next one, happy coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build an EKS Cluster Across AWS Local Zones using the AWS CDK ]]>
                </title>
                <description>
                    <![CDATA[ AWS Local Zones are a new type of infrastructure that enables you to build and run applications closer to end-users, providing low latency and improved performance.  They are designed to provide the same high availability and reliability as an AWS Re... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-an-eks-cluster-using-aws-local-zones-with-aws-cdk/</link>
                <guid isPermaLink="false">66c4c5a3d788a9c53d88d2d9</guid>
                
                    <category>
                        <![CDATA[ AWS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Cloud Computing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Gursimar Singh ]]>
                </dc:creator>
                <pubDate>Tue, 28 May 2024 14:34:30 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/05/pexels-pixabay-357742.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>AWS Local Zones are a new type of infrastructure that enables you to build and run applications closer to end-users, providing low latency and improved performance. </p>
<p>They are designed to provide the same high availability and reliability as an AWS Region, but with the added benefit of low-latency connections for applications that require it.</p>
<p>Using Local Zones can be particularly helpful if you have end users located in specific geographic areas and want to provide them with low-latency access to their applications. This can be especially important for applications that require real-time data processing or have strict performance requirements.</p>
<p>Local Zones can also minimize network expenses, which is an additional advantage. By executing applications in a Local Zone closer to end users, you can limit the quantity of data that must be transferred over long distances, which reduces network costs.</p>
<p>In this tutorial, we will see how to build a hybrid edge EKS cluster that spans across the AWS Regions and AWS Local Zones using both AWS Management Console and AWS Cloud Development Kit (CDK).</p>
<p>Before getting started, it's important to note that AWS Local Zones are physically separate locations that are connected to the main AWS region through high-speed links. They allow you to run certain services closer to your customers and reduce latency.</p>
<p>To build your EKS cluster across Local Zones, you will need to:</p>
<ol>
<li>Create an EKS cluster in the main region</li>
<li>Create a VPC and associated resources in the Local Zones</li>
<li>Connect the Local Zone VPCs to the main region VPC</li>
<li>Launch worker nodes in the Local Zone VPCs</li>
</ol>
<p>We'll walk through these steps in this guide.</p>
<p><img src="https://lh3.googleusercontent.com/-kdtf6vkPfxVY3aLcGpqQI5wczBZXfcScdCz2z1bhNSuawjGEJyLEznPfB5mqnupfuVsPCNybRHJViCjLTxKmF5F2zq82LdHvRmnItjDFTrPDtTRhAzAgr7ToL8bhuymqSkCpVei2VcPyFdjz7YQC_w" alt="Image" width="860" height="640" loading="lazy">
<em>Architecture Diagram</em></p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>Before we begin, you need to have the following:</p>
<ol>
<li>An AWS account with permissions to create resources in AWS Wavelength and AWS Local Zones.</li>
<li>AWS CDK installed on your local machine. If you don't have it installed, you can follow the instructions in the AWS CDK documentation to install it.</li>
<li>AWS CLI installed on your local machine. If you don't have it installed, you can follow the instructions in the AWS CLI documentation to install it.</li>
</ol>
<p>Finally, let’s get started.</p>
<h2 id="heading-step-1-create-an-aws-local-zone">Step 1: Create an AWS Local Zone</h2>
<p>The first step is to opt-in to AWS Local Zones in the region of your choice. You can follow the instructions in the <a target="_blank" href="https://docs.aws.amazon.com/local-zones/latest/ug/getting-started.html">AWS Local Zones documentation</a> to opt-in to these zones.</p>
<h2 id="heading-step-2-create-a-cdk-project">Step 2: Create a CDK Project</h2>
<p>To start, we need to create a new CDK project using the following command:</p>
<pre><code>cdk init --language=javascript
</code></pre><p>This will create a new directory with the required files and directories for a CDK project.</p>
<p>Next, install the required dependencies using the following command:</p>
<pre><code>npm install
</code></pre><p>Now, let's create a new file called local-zone-eks.js in the lib directory and add the following code:</p>
<pre><code><span class="hljs-keyword">const</span> cdk = <span class="hljs-built_in">require</span>(<span class="hljs-string">'aws-cdk-lib'</span>);
<span class="hljs-keyword">const</span> ec2 = <span class="hljs-built_in">require</span>(<span class="hljs-string">'aws-cdk-lib/aws-ec2'</span>);
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> autoscaling <span class="hljs-keyword">from</span> <span class="hljs-string">'@aws-cdk/aws-autoscaling'</span>;
<span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> ecs <span class="hljs-keyword">from</span> <span class="hljs-string">'@aws-cdk/aws-eks'</span>;

<span class="hljs-built_in">require</span>(<span class="hljs-string">'dotenv'</span>).config();
<span class="hljs-keyword">const</span> config = {
  <span class="hljs-attr">env</span>: {
    <span class="hljs-attr">account</span>: process.env.AWS_ACCOUNT_NUMBER,
    <span class="hljs-attr">region</span>: process.env.AWS_REGION,
  },
};


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">VPCStack</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">cdk</span>.<span class="hljs-title">Stack</span> </span>{
  <span class="hljs-keyword">constructor</span>(scope, id, props) {
    <span class="hljs-built_in">super</span>(scope, id, props);

    <span class="hljs-comment">// Create a VPC </span>
    <span class="hljs-keyword">const</span> vpc = <span class="hljs-keyword">new</span> ec2.Vpc(<span class="hljs-built_in">this</span>, <span class="hljs-string">'VPC'</span>, {
      <span class="hljs-attr">cidr</span>: <span class="hljs-string">'10.0.0.0/16'</span>,
      <span class="hljs-attr">maxAzs</span>: <span class="hljs-number">2</span>,
      <span class="hljs-attr">subnetConfiguration</span>: [
        {
          <span class="hljs-attr">cidrMask</span>: <span class="hljs-number">24</span>,
          <span class="hljs-attr">name</span>: <span class="hljs-string">'Public'</span>,
          <span class="hljs-attr">subnetType</span>: ec2.SubnetType.PRIVATE,
        },
        {
          <span class="hljs-attr">cidrMask</span>: <span class="hljs-number">24</span>,
          <span class="hljs-attr">name</span>: <span class="hljs-string">'Private'</span>,
          <span class="hljs-attr">subnetType</span>: ec2.SubnetType.PRIVATE,
        },
      ],
    });
  }
}

<span class="hljs-built_in">module</span>.exports = { VPCStack };
</code></pre><p>This code creates a new VPC with a CIDR block of 10.0.0.0/16, which spans across two private subnets. </p>
<p>Next, let’s export the environment variable for our AWS Local Zone, which we will use to create the only public subnet in our VPC. In this example, we have selected the Las Vegas Local Zone and have configured the subnet accordingly.</p>
<pre><code><span class="hljs-keyword">const</span> localZone: string = <span class="hljs-string">'us-west-2-las-1a’

 // Create Local Zone Public Subnet
    const LocalZoneSubnet = new ec2.PublicSubnet(this, '</span>localzone-public-subnet<span class="hljs-string">', {
      availabilityZone: localZone,
      cidrBlock: '</span><span class="hljs-number">10.0</span><span class="hljs-number">.3</span><span class="hljs-number">.0</span>/<span class="hljs-number">26</span><span class="hljs-string">',
      vpcId: vpc.vpcId,
      mapPublicIpOnLaunch: true,
    });

    // Add Local Zone Subnet to VPC
    vpc.publicSubnets.push(LocalZoneSubnet);</span>
</code></pre><h2 id="heading-step-3-create-an-amazon-eks-cluster">Step 3: Create an Amazon EKS Cluster</h2>
<p>Now that we have a VPC, we can create an Amazon Elastic Container Service for Kubernetes (Amazon EKS) cluster.</p>
<p>Add the following code to the local-zone-eks.js file:</p>
<pre><code><span class="hljs-keyword">const</span> eks = <span class="hljs-built_in">require</span>(<span class="hljs-string">'aws-cdk-lib/aws-eks'</span>);

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">EKSStack</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">cdk</span>.<span class="hljs-title">Stack</span> </span>{
  <span class="hljs-keyword">constructor</span>(scope, id, props) {
    <span class="hljs-built_in">super</span>(scope, id, props);
    <span class="hljs-comment">// Create the EKS cluster</span>
    <span class="hljs-keyword">const</span> cluster = <span class="hljs-keyword">new</span> eks.Cluster(<span class="hljs-built_in">this</span>, <span class="hljs-string">'EKSCluster'</span>, {
      <span class="hljs-attr">vpc</span>: vpc,
      <span class="hljs-attr">defaultCapacity</span>: <span class="hljs-number">0</span>,
      <span class="hljs-attr">version</span>: <span class="hljs-string">'1.21'</span>,
      <span class="hljs-attr">clusterName</span>: <span class="hljs-string">'local-zone-eks-demo-cluster'</span>,
    });
  }
}
<span class="hljs-built_in">module</span>.exports = { EKSStack };
</code></pre><p>This code creates a new EKS cluster using the VPC we created earlier. It also specifies the Kubernetes version to use and the name of the cluster.</p>
<h2 id="heading-step-4-create-worker-nodes">Step 4: Create Worker Nodes</h2>
<p>Next, we need to create worker nodes to run our applications on the EKS cluster.</p>
<p>Add the following code to the local-zone-eks.js file:</p>
<pre><code><span class="hljs-comment">// Define EKS-optimized image for Launch Template</span>
    <span class="hljs-keyword">const</span> image = <span class="hljs-keyword">new</span> ecs.EksOptimizedAmi();

    <span class="hljs-comment">// Create Launch Template for Auto Scaling group to reference</span>
    <span class="hljs-keyword">const</span> lzLaunchTemplate = <span class="hljs-keyword">new</span> ec2.CfnLaunchTemplate(
      <span class="hljs-built_in">this</span>,
      <span class="hljs-string">'eks-launch-template'</span>,
      {
        <span class="hljs-attr">launchTemplateName</span>: <span class="hljs-string">'lz-launch-template'</span>,
        <span class="hljs-attr">launchTemplateData</span>: {
          <span class="hljs-attr">networkInterfaces</span>: [
            {
              <span class="hljs-attr">deviceIndex</span>: <span class="hljs-number">0</span>,
              <span class="hljs-attr">associatePublicIpAddress</span>: <span class="hljs-literal">true</span>,
              <span class="hljs-attr">deleteOnTermination</span>: <span class="hljs-literal">true</span>,
              <span class="hljs-attr">subnetId</span>: LocalZoneSubnet.subnetId!,
            },
          ],
          <span class="hljs-attr">imageId</span>: image.getImage(<span class="hljs-built_in">this</span>).imageId,
          <span class="hljs-attr">instanceType</span>: <span class="hljs-string">'t3.medium'</span>,
          <span class="hljs-attr">userData</span>: cdk.Fn.base64(
            <span class="hljs-string">`#!/bin/bash -xe
          set -o xtrace
          /etc/eks/bootstrap.sh ‘local-zone-eks-demo-cluster’}
            )
        },
      }
    );

 // Create Auto Scaling Group
    const lz_asg = new autoscaling.AutoScalingGroup(this, 'LocalZoneWorkerNodes', {
      instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.MEDIUM),
      machineImage: new ecs.EksOptimizedAmi(),
      updateType: autoscaling.UpdateType.REPLACING_UPDATE,
      desiredCapacity: 1,
      vpc: vpc,
    launchTemplate: lzLaunchTemplate
    });</span>
</code></pre><p>This code creates a new auto-scaling group to manage the worker nodes, and adds the worker nodes to the EKS cluster using the instance bootstrap script.</p>
<h2 id="heading-step-5-deploy-the-cdk-app">Step 5: Deploy the CDK App</h2>
<p>Now that we have all the required code, we can deploy it using the following command:</p>
<pre><code>cdk deploy
</code></pre><p>With your EKS cluster up and running, you can start deploying your applications. You can use Kubernetes manifests or Helm charts to deploy your applications to the cluster.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>AWS Local Zones provide a robust mechanism for providing high-performance applications to end users, independent of their location. They also give end users a better experience and deliver great performance.</p>
<p>I’m always open to suggestions and discussions on <a target="_blank" href="https://www.linkedin.com/in/gursimarsm">LinkedIn</a>. Hit me up with direct messages.</p>
<p>If you’ve enjoyed my writing and want to keep me motivated, consider leaving stars on <a target="_blank" href="https://github.com/gursimarsm">GitHub</a> and endorse me for relevant skills on <a target="_blank" href="https://www.linkedin.com/in/gursimarsm">LinkedIn</a>.</p>
<p>Till the next one, stay safe and keep learning.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ What is RAM? How to Access Your Computer's RAM and Read the Contents ]]>
                </title>
                <description>
                    <![CDATA[ This article is a comprehensive guide on how to read the contents of your computer's RAM.  Random Access Memory (RAM) is a crucial component of any computer system, and it is responsible for temporarily storing data that is required by the system to ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-access-and-read-ram-contents/</link>
                <guid isPermaLink="false">66c4c5a926a77d9936ef0a61</guid>
                
                    <category>
                        <![CDATA[ Computer Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ hardware ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Gursimar Singh ]]>
                </dc:creator>
                <pubDate>Mon, 24 Apr 2023 19:31:18 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/04/ram-article.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>This article is a comprehensive guide on how to read the contents of your computer's RAM. </p>
<p>Random Access Memory (RAM) is a crucial component of any computer system, and it is responsible for temporarily storing data that is required by the system to carry out its functions. But the contents of RAM can be quite volatile, and they are usually lost when the system is shut down.</p>
<p>One way to preserve the contents of RAM is by performing a RAM dump, which is a process of copying the contents of RAM onto a storage device, such as a hard drive. You can analyze the RAM dump, and the data contained within it can provide valuable insights into the system's state at the time the dump was taken.</p>
<p>In this article, I will walk you through the process of reading the contents of RAM, as well as explain what a RAM dump is and how it can be useful in analyzing a computer system. I will also provide you with step-by-step instructions on how to perform a RAM dump and how to analyze the resulting data.</p>
<h2 id="heading-why-read-ram-data">Why Read RAM Data?</h2>
<p>Reading data from the disc is something you might be familiar with doing. But can we also read data straight from the RAM, where the most essential information is stored?</p>
<p>As developers, we can investigate the space complexity and delve further into the RAM to understand what is going on.</p>
<p>Accessing and reading the contents of RAM can be useful in a variety of scenarios. One common use case is for troubleshooting and diagnosing issues with a computer system. By examining the contents of RAM, you can gain insights into the state of the system at a particular point in time. </p>
<p>For example, if your computer suddenly crashes, examining the contents of RAM can help you identify the cause of the crash.</p>
<p>Another use case is for forensic analysis. When investigating a computer system for evidence of wrongdoing, examining the contents of RAM can provide valuable insights into the activities that were being carried out on the system. </p>
<p>For example, a security professional may use RAM analysis to determine whether a particular process was running on the system or to identify files that were recently accessed.</p>
<p>In addition, accessing and reading the contents of RAM can also be useful for software developers and researchers. By analyzing the data stored in RAM, developers can gain insights into the performance of their software and identify potential issues or bottlenecks. Researchers can also use RAM analysis to study the behavior of malware or to develop new security tools and techniques.</p>
<p>Overall, accessing and reading the contents of RAM can be useful for troubleshooting, forensic analysis, software development, and research. It provides a valuable way to gain insights into the inner workings of a computer system and can help identify issues and potential security threats.</p>
<p>Before we move further into the specifics, let's take a short look at the nomenclature. This may be common knowledge, but you'll need to understand the terminology as you go through this guide, so it's worth a review.</p>
<h2 id="heading-what-is-ram">What is RAM?</h2>
<p>There's a physical hardware device called RAM (which stands for Random Access Memory): the physical memory, a CPU, a hard disk, and other physical components.</p>
<p>On top of this, we have the operating system. The operating system is always in conversation with the piece of hardware known as the "kernel" – and this is one of the most critical aspects of this software.</p>
<p>If we consider things from the user's point of view, we initially log in to the operating system so that we can carry out our tasks, the majority of which include executing applications.</p>
<h3 id="heading-what-is-the-kernel">What is the Kernel?</h3>
<p>A kernel is a fundamental portion of an operating system that accepts the instructions from the user with the aid of the program we run behind the scenes. This may happen regardless of the program that we run behind the scenes.</p>
<p>Everything that has to be computed is handled by the central processing unit (CPU), but whatever we do and however we manage the services provided by the CPU, the data, instructions, code, and program must all go via the random access memory (RAM).</p>
<p>This implies that the results of anything we do with the data at any given moment in time will be available on top of the memory. If you are a programmer and you're constructing some kind of data structure, this indicates that all of the data will live on top of the RAM.</p>
<p>We can directly go to the RAM and see how the data structures have been created and how they align, and we can see how the space complexity works there.</p>
<p>For instance, if we are discussing any web browser, such as Chrome, there may have been security flaws generated in an application. So the most effective method is to navigate to the RAM and investigate how the data has been operating.</p>
<p>Let's say you open any secure website in Chrome (or any browser), like gmail.com. Any information you enter into Gmail, including your username and password, is sent over the internet to a server run by Google. That data has been fully encrypted, and it will be challenging, if not impossible, to crack the password.</p>
<p>But in order to enter your password, you likely use a computer with a keyboard attached to it. After that, some programs will encrypt the data and send it to the internet. This means that initially, your data was present in the RAM.</p>
<p>First, the password is standard data, and the password goes and lands on the top of the RAM. Then, some programs will encrypt the data and send it to the internet. If you can access the RAM, you can examine it to determine whether or not your password has been encrypted. And this process is pretty straightforward.</p>
<p>Let's look at an example to see how this works. We'll pretend that "a" is a variable and "9" is the data. When we execute the program, this data loads onto the RAM. When the program ends, the data from the RAM will be gone, although nobody has proven it yet. But this is the case, and we can prove it with a little investigation.</p>
<p>So how can we check whether or not this data is still present in the RAM after the application has finished running if it was loaded at the very top of the memory?</p>
<p>Well, the RAM will be cleared of these contents shortly. A "RAM dump" is the process of capturing all of the RAM. This demonstrates the actual form in which the entire data set is made accessible and loaded onto the RAM for the first time. And you'll learn how to capture or extract the data from memory next.</p>
<p>In order to accomplish this, you'll need some form of software. As a result, the goal of this program is to travel further into the memory. It will go into memory and retrieve all of the stored data from memory before continuing.</p>
<h3 id="heading-what-is-lime">What is LiME?</h3>
<p>The Linux memory extractor, sometimes referred to as LiME, is a powerful piece of software. It's what you use to extract the memory from Linux. This piece of software is also known as the driver, also referred to as the module. This is because RAM is a device, which complicates things further.</p>
<p>We need some form of driver to access the device so we can try to read the contents of it. LiME is an example of a driver, and if you're familiar with Linux you may know that in order to make any driver function, you need to load that driver with the assistance of the kernel.</p>
<p>Within the context of Linux, a driver is also referred to as a module. So LiME is a Linux kernel module. We have access to what is known as a kernel loadable module, which allows us to install the module on the operating system.</p>
<p>We have covered enough background. Now, let's look at how we can extract the contents of the RAM. We'll go through the process step-by-step in a hands-on way.</p>
<h2 id="heading-setup-and-installations"><strong>Setup</strong> and <strong>Installations</strong></h2>
<p>So, the only thing we need is the LiME driver. Here's the link to download this particular module: <a target="_blank" href="https://github.com/gursimarsm/LiME">https://github.com/gursimarsm/LiME</a>.</p>
<p>Now, boot up your Linux system (I use RedHat Enterprise Linux). You can use the <strong><code>free -h</code></strong> command to check the amount of RAM memory that's being used, that's available, and other details. Mine looks like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-186.png" alt="Image" width="600" height="400" loading="lazy">
<em>Output from running the <code>free -m</code> command</em></p>
<p>To access RAM, we need some software where the kernel can load some extra modules. In our case, the module name is LiME. So, the software we install are called “<strong>kernel-devel</strong>”, and “<strong>kernel-headers</strong>”. These two pieces of software are what we need to install in order to perform our subsequent actions, that is to use the LiME module.</p>
<p>If you want to install the software, you should have "yum" configured. For context, <strong>yum</strong> is a command you can use to install the software in the RedHat Linux operating system. I'll demo how to configure it in the appendix for reference.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-187.png" alt="Image" width="600" height="400" loading="lazy">
<em>Installation</em></p>
<p>So, now that you've installed that software, you need one more piece of software because you have to download some drivers from GitHub. So, now you need to install Git if you don't already have it. You can do this using the command <strong><code>yum install git</code></strong>. You also need to configure your account so that you can work with it.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># git config --global user.name "Your Name" </span>

<span class="hljs-comment"># git config --global user.email "you@example.com"</span>
</code></pre>
<p>I shared the repository above. It's a loadable kernel module (LKM). It lets you acquire the entire memory from your Linux operating system or any kind of language operating system (including Android devices because Android is based on Linux as well).</p>
<p>You can download the module using the <code>**# g**it clone**** [**https://github.com/gursimar**sm**/LiME**](https://github.com/gursimarsm/LiME)</code> command.</p>
<p>After downloading that, you need to move into the directory of the software. You'll find multiple folders there. But, to run the main code, you need to move to the "src" directory.</p>
<p>In this directory, you'll find multiple programs based on the C language. So, in order to make use of the files, you'll need to compile them. To do that, you can use the <strong><code>make</code></strong> command. Install that like this:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># yum install make </span>

<span class="hljs-comment"># yum install gcc</span>
</code></pre>
<p>In the directory /LiME/src/, run the <strong><code>make</code></strong> command to compile the entire code.</p>
<p>If you encounter an error, it might be because we are using the latest version of LiME, and it comes with a new feature called orc metadata generate. To implement this feature, you have to install one more thing that's part of LiME called <strong><code>elfutils-libelf-devel</code></strong>. You can do that using yum like you can see below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-188.png" alt="Image" width="600" height="400" loading="lazy">
<em>How to install <strong><code>elfutils-libelf-devel</code></strong></em></p>
<p>After that's done, if we now run the <code>make</code> command it will ask the GCC compiler to compile the entire code. After the compilation, it will create one final object file called the kernel object file, and that is the final module in LiME.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-189.png" alt="Image" width="600" height="400" loading="lazy">
<em>Output</em></p>
<p>You can find this file in the same directory by using the <strong><code>ls</code></strong> command.</p>
<h2 id="heading-how-to-use-the-module"><strong>How to Use the Module</strong></h2>
<p>With this module, the kernel now has the capability to capture or read the entire RAM. By default, we can't read the entire RAM in one go, but now because of the LiME module, we can.</p>
<p>To learn more about the LiME module, you can use the <strong><code>modinfo</code></strong> command. Type <code>modinfo</code> along with <code>lime</code>. This will show you some more details like where the file is available, and it also displays all the modules or drivers that come with some kind of extra parameters. Every parameter has some benefits.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-190.png" alt="Image" width="600" height="400" loading="lazy">
<em>modinfo</em></p>
<p>Here we are going to use two parameters which are very important: <code>path</code> and <code>format</code>.</p>
<p><code>path</code> means when we read the entire RAM, we have to store the data of the RAM in some file. So, to specify the destination file we would like to create, we have to give that particular information over here.</p>
<p>The next parameter, <code>format</code>, specifies the format in which we want to read the RAM data. So, in this case, we want to read the format of the RAM as it is. The data stored in the RAM is mostly in binary, and we want to read the entire data in that binary format only and capture it in its raw form.</p>
<p>So, the format will be raw and stored in the file wherever we give the path.</p>
<p>Finally, it's time to read the data from the RAM. So, let's come to the main command that will help us start reading the entire RAM.</p>
<h3 id="heading-demonstration">Demonstration</h3>
<p>Type in your password for your Gmail account in Chrome for this demonstration. This will help you learn how to capture the data from the RAM and also if your password is encrypted.</p>
<p>To verify these two things, move to the command prompt and check if the data is still on the RAM. You'll have to load a particular module using the command <strong><code>insmod</code></strong>. This will help you insert the module.</p>
<p>Copy the complete path of the module and paste it along with the <code>insmod</code> command.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-191.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>insmod</code> command</em></p>
<p>This module will get loaded with the help of the kernel. The module will start capturing the entire data from the RAM and it'll store it in a file, for example, myram.data</p>
<p>It will also load the entire memory dump or RAM dump into this file and which format we want to capture. So, the format will be the raw format.</p>
<p>We'll use these two parameters (don't worry about this for now). We need only two parameters to perform, and now as soon as we hit this command, whatever data we have will be captured and stored in this particular file. This command typically takes a few seconds, depending on the CPU speed and the amount of data we have in the RAM.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-192.png" alt="Image" width="600" height="400" loading="lazy">
<em>Command</em></p>
<h3 id="heading-how-to-read-the-data">How to read the data</h3>
<p>Now, we have this file myram.data and the entire data of the RAM is stored in this file. Because we captured this data in the raw format, the data is going to be in binary. If we try to read this data from this file directly, as human beings, we can't read it even if we try it with the initial lines using the head command to read some of the top 10 lines.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-193.png" alt="Image" width="600" height="400" loading="lazy">
<em>Output</em></p>
<p>So, we can use the “cat” command, which will read the entire data. But, again, the same thing is going to happen – it will read the entire data, but the data will be displayed in the binary format. Then we need to use the pipe function with this command and combine it with another new command called <code>strings</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-194.png" alt="Image" width="600" height="400" loading="lazy">
<em>Command</em></p>
<p>String is a command that will convert the data into regular text in a human-readable format.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-195.png" alt="Image" width="600" height="400" loading="lazy">
<em>Output</em></p>
<p>The list will go on and on. You can interrupt it using <strong>Ctl+C</strong>.</p>
<p>Right now, it won't mean much seeing and reading the entire data. We know some data that are there on the RAM is the password called mywebpasswordgmail. So, just to confirm that this data is available on the RAM we can use one more pipe along with the <code>grep</code> command. The grep command helps us sort the data.</p>
<pre><code class="lang-bash">cat /myram.data | strings | grep mywebpasswordgmail
</code></pre>
<p>Now, we are searching for this string in the entire data. It will convert the data into regular text, and wherever that particular string shows up, grep will grab that line and let us start searching, then show us this data.</p>
<p>So, as you can see from this simple example, whatever you type on your keyboard can also go into the RAM – even if it's your password or any kind of secure site you are surfing, your data is there on the RAM. It doesn't matter what program you run. If you type using the keyboard everything will load on the RAM and can be extracted. This is called the memory dump.</p>
<p>LiME provides us with many other powerful capabilities. Right now, we are capturing the data directly from the system where we perform the actions. But we can also run LiME on the system and it can capture the data in real-time and send the data over the network to another computer.</p>
<p>What does this mean? Think of it this way: for example, somebody opens a website and they're typing something in real-time. This entire message is being transmitted in real-time to another computer.</p>
<p>We're not talking about key loggers, we are just talking about the RAM. Whatever is happening when any program is running, the database is storing some data. Programs are reading data from other parts of the hard disk. And whatever is happening on the RAM can be captured in real-time by the system and sent over the network to other computers.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>We’ve finally come to the end of this article. I hope you've enjoyed it and have learned something new.</p>
<p>I’m always open to suggestions and discussions on <a target="_blank" href="https://www.linkedin.com/in/gursimarsm">LinkedIn</a>. Hit me up with direct messages.</p>
<p>If you’ve enjoyed my writing and want to keep me motivated, consider leaving starts on <a target="_blank" href="https://github.com/gursimarsm">GitHub</a> and endorse me for relevant skills on <a target="_blank" href="https://www.linkedin.com/in/gursimarsm">LinkedIn</a>.</p>
<p>Till the next one, stay safe and keep learning.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Docker Engine-like Custom Container without Any Software ]]>
                </title>
                <description>
                    <![CDATA[ This article will discuss every aspect of containers, including how they operate in the background and their various component elements. We will also discover why Docker is so lightning-fast. By the end, you'll be able to create your own custom conta... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-your-on-custom-container-without-docker/</link>
                <guid isPermaLink="false">66c4c5a6e7521bfd6862b3a9</guid>
                
                    <category>
                        <![CDATA[ containerization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ containers ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Docker ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Kubernetes ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Gursimar Singh ]]>
                </dc:creator>
                <pubDate>Wed, 10 Aug 2022 16:45:36 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/08/image-12-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>This article will discuss every aspect of containers, including how they operate in the background and their various component elements. We will also discover why Docker is so lightning-fast.</p>
<p>By the end, you'll be able to create your own custom container. We'll also examine why Kubernetes deprecated Docker and embraced CRI-O, as well as how to configure a multi-node Kubernetes cluster using CRI-O.</p>
<p>In the end, we will look at the list of available container runtimes.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-11.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><a class="post-section-overview" href="#heading-what-are-containers">What are containers</a>?</li>
<li><a class="post-section-overview" href="#heading-why-do-we-need-containers">Why do we need containers</a>?</li>
<li><a class="post-section-overview" href="#heading-whats-the-difference-between-containers-and-virtualization">What's the difference between containers and virtualization</a>?</li>
<li><a class="post-section-overview" href="#heading-is-there-a-standard-format-for-containers">Is there a standard format for containers</a>?</li>
<li><a class="post-section-overview" href="#heading-types-of-container-platforms">Types of container platforms</a></li>
<li><a class="post-section-overview" href="#heading-how-to-launch-a-container">How to launch a container</a></li>
<li><a class="post-section-overview" href="#heading-why-did-kubernetes-depreciate-docker">Why did Kubernetes deprecate Docker</a>?</li>
<li><a class="post-section-overview" href="#heading-challenges-of-using-docker">Challenges of using Docker</a></li>
<li><a class="post-section-overview" href="#heading-what-is-a-cri-container-runtime-interface">What is a CRI (Container Runtime Interface)</a>?</li>
<li><a class="post-section-overview" href="#heading-how-to-build-a-multi-node-cluster-using-cri-o">How to build a multi-node cluster using CRI-O</a></li>
</ol>
<p>Alright, let's dive in.</p>
<h2 id="heading-what-are-containers">What Are Containers?</h2>
<p>Containers allow you to reliably move software from one computing environment to another.  </p>
<p>The technology behind containers is nearly as old as that behind virtual machines. But the information technology industry didn't begin using containers until around 2013–14, when Docker, Kubernetes, and other innovations that disrupted the sector became popular. </p>
<p>Containers have emerged as a critical tool in the process of developing software. They can serve either as a replacement for Virtual Machines or as a supplement to them. </p>
<p>Containerisation helps developers construct apps more rapidly and securely while also deploying them more easily.</p>
<h2 id="heading-why-do-we-need-containers">Why Do We Need Containers?</h2>
<p>As we learned above, containers provide a solution to the problem of transporting software from one computer environment to another in a reliable manner. This can be just from a developer's workstation to a test environment, from a staging environment to production, or even from a real system in a data center to a private or public cloud virtual machine. </p>
<p>Containerization makes possible all of these transformations. And these are just some of the viewpoint alterations that can happen.</p>
<p>This quote gives a little perspective on why containers are helpful:</p>
<blockquote>
<p>"You’re going to test using Python 2.7, and then it’s going to run on Python 3 in production and something weird will happen.   </p>
<p>Or you’ll rely on the behavior of a certain version of an SSL library and another one will be installed.   </p>
<p>You’ll run your tests on Debian and production is on Red Hat and all sorts of weird things happen.   </p>
<p>The network topology might be different, or the security policies and storage might be different but the software has to run on it." – Solomon Hykes</p>
</blockquote>
<h2 id="heading-how-do-containers-solve-this-issue">How Do Containers Solve This Issue?</h2>
<p>A more straightforward interpretation is that a container is an all-encompassing runtime environment. </p>
<p>This means that a piece of software, together with all of its dependencies, libraries, other binaries, and configuration files, is packed and distributed to customers as a single package. </p>
<p>The application platform and its dependencies can be protected from the consequences of changes in operating system distribution and underlying infrastructure if they are bundled within containers.</p>
<h2 id="heading-whats-the-difference-between-containers-and-virtualization">What’s the Difference Between Containers and Virtualization?</h2>
<p>A virtual machine is a package that may be shared when employing virtualization technology. This package includes both the program and the operating system being used. </p>
<p>On top of a physical server running three virtual machines, you'd have an installation of a hypervisor, as well as three distinct operating systems.</p>
<p>On the other hand, a Docker server that hosts three containerized programs only needs to run a single operating system because all of the containers share the same kernel. The standard components of the operating system can only be read, but each container has its own mount or access mechanism, which allows it to store and retrieve data. </p>
<p>This hints that containers are far lighter than virtual machines and make considerably less use of their resources.</p>
<h2 id="heading-is-there-a-standard-format-for-containers">Is There a Standard Format for Containers?</h2>
<p>When CoreOS published its own App Container Image (ACI) specification in 2015, some people worried that the rapidly growing container movement might splinter into different Linux container formats. This was because ACI stood for "App Container Image."</p>
<p>In contrast, the Open Container Project, which would subsequently become the Open Container Initiative (OCI), was not made public until the latter half of the same year.</p>
<p>The <a target="_blank" href="https://opencontainers.org/">Open Container Initiative</a>, which the Linux Foundation leads, aims to establish an industry standard for container formats as well as container runtime software that is compatible with all operating systems (OCI).</p>
<p>Docker technology was used to develop the Open Container Project (OCP) guidelines, and Docker gave around 5 percent of their software to help get the effort off the ground.</p>
<h3 id="heading-what-is-open-container-initiative">What is Open Container Initiative?</h3>
<p>The Open Container Initiative (OCI) is an organization whose mission is to ensure that the fundamental aspects of container technology, such as the container's format, are standardized so that anyone can use them.</p>
<p>As a result, companies can concentrate their efforts on developing the supplementary software they need in order to use standardized containers in an enterprise or cloud environment (instead of developing competing technologies for containers). </p>
<p>Software components called container orchestration and management solutions, as well as container security systems, are essential components.</p>
<h2 id="heading-types-of-container-platforms">Types of Container Platforms</h2>
<p>As a result of the development and expansion of container technology, a number of different choices are currently available. </p>
<p>Docker is, without a doubt, the most common and widely used container platform available. </p>
<p>On the other hand, the landscape of container technologies includes other technologies, each of which has its own use cases and benefits.</p>
<p>We will look at the two most famous ones, i.e., Docker and Podman.</p>
<h3 id="heading-docker">Docker</h3>
<p>Docker is the container platform that's currently the most popular and is used the most widely. It allows you to develop and use Linux containers. </p>
<p>Docker is a piece of software that, by using containers, simplifies the processes of creating, deploying, and operating software applications. It does this by minimising the number of steps in each process. </p>
<p>Docker has gained support not just from the most major Linux distributions, such as Red Hat and Canonical, but also from large organisations, such as Microsoft, Amazon, and Oracle. </p>
<p>Virtually all businesses concerned with information technology and cloud computing use Docker.</p>
<h5 id="heading-docker-architecture-and-components">Docker Architecture and Components</h5>
<p>Docker is built on a client-server architecture. The Docker daemon enables the creation, operation, and distribution of Docker containers. </p>
<p>The Docker client and Docker daemon can interact through a REST application programming interface (API), UNIX sockets, or network interface.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-34.png" alt="Image" width="600" height="400" loading="lazy">
<em>Source: docs.docker.com</em></p>
<p>Docker's architecture is comprised of the following five primary components:</p>
<ol>
<li><strong>Docker Daemon</strong> manages Docker objects like images, containers, networks, and volumes. It also responds to Docker API inquiries.</li>
<li><strong>Docker Clients</strong> enables users to interact with Docker by allowing the user to connect with Docker. Docker client supplies a CLI interface that allows users to send application commands to a Docker daemon and start and halt such operations.</li>
<li><strong>Docker Host</strong> provides a complete software program execution and operation environment. This system comprises the Docker daemon, Images, Containers, Networks, and Storage components.</li>
<li><strong>Docker Registry</strong> maintains Docker Images. Docker Hub is a public registry, and by default, Docker is configured to use images saved on Docker Hub. You can use it to administer your own register.</li>
<li><strong>Docker Images</strong> are templates that can only be read and produced by following a Dockerfile's set of instructions. Images specify the appearance we want for our packaged program, its dependencies, and the processes that should run when the application is launched.</li>
</ol>
<h4 id="heading-resource-isolation-components-in-docker">Resource Isolation components in Docker</h4>
<h5 id="heading-namespaces">Namespaces:</h5>
<ul>
<li>PID namespace for process isolation.</li>
<li>NET namespace for managing network interfaces.</li>
<li>IPC namespace for managing access to IPC resources.</li>
<li>MNT namespace for managing filesystem mount points.</li>
<li>UTS namespace for isolating kernel and version identifiers.</li>
</ul>
<h5 id="heading-control-groups">Control groups</h5>
<ul>
<li>Memory cgroup that oversees accounting as well as restrictions and alerts</li>
<li>HugeTBL is a cgroup that keeps track of each process group's use of huge pages.</li>
<li>CPU group is responsible for regulating the time users and the system spend using CPU.</li>
<li>CPUSet cgroup lets you associate a group with a certain CPU. Utilized for real-time workloads and NUMA systems with localised memory for each CPU.</li>
<li>BlkIO cgroup for measuring and limiting the amount of blkIO each group produces.</li>
<li>the net cls and net prio cgroups are utilised for traffic control tagging.</li>
<li>Devices cgroup for accessing devices that can both read and write data.</li>
<li>Cgroup for the freezing of a group referred to as the freezer. It is useful for scheduling cluster batches, relocating processes, and troubleshooting.</li>
</ul>
<h5 id="heading-union-filesystem">Union Filesystem</h5>
<ul>
<li>Docker images are composed of layered filesystems, allowing them to be extremely lightweight and speedy. Union file systems are layering-based file systems.</li>
<li>Docker Engine has the ability to use several different versions of UnionFS, such as AUFS, btrfs, vfs, and devicemapper.</li>
<li>For executing five 250MB image containers, we would require 1.25GB of disc space if we didn't have UnionFS.</li>
</ul>
<p>The Docker interface may appear to be a mysterious black box holding a variety of unknown technologies when seen from the outside. Despite their relative obscurity, these technologies are both highly intriguing and useful.  </p>
<p>Despite the fact that we do not need to grasp these technologies in order to utilise Docker effectively, it is still beneficial to learn about and have an awareness of these technologies.   </p>
<p>If we have a deeper understanding of the instrument, it will be much easier for us to make the proper decisions, such as those regarding performance optimization or security implications.   </p>
<p>In addition, this facilitates the discovery of innovative new technologies, which may have many more uses for the organisation than initially thought.</p>
<h3 id="heading-just-a-note">Just a note:</h3>
<p>Docker does not require cgroupfs as the control group driver. The cgroup can be changed to systemd. </p>
<p>Docker's own control group manager is cgroupfs. Nevertheless, for most Linux distributions, systemd is the default init system, and systemd has tight interaction with Linux control groups. </p>
<p>For Kubernetes, it is recommended to use systemd, as utilising cgroupfs in conjunction with systemd appears to be suboptimal.</p>
<p>So systemd is preferable for cgroup management. kubelet is set to utilise systemd by default. Therefore, Docker should be modified to utilise the systemd driver. </p>
<h5 id="heading-docker-engine-sparked-the-containerization-movement">Docker Engine Sparked the Containerization Movement</h5>
<p>The Docker Engine is the de-facto container runtime for Linux and Windows Server platforms. </p>
<p>Docker develops simple tools and a uniform packaging strategy that encapsulates all application requirements into a container, which is then executed by Docker Engine. </p>
<p>The Docker Engine enables containerized apps to operate anywhere reliably on any infrastructure, resolving "dependency hell" for developers and operations teams and removing the "it works on my laptop!" issue.</p>
<h3 id="heading-podman">Podman</h3>
<p>Podman is RedHat's product. Docker and Podman are fairly comparable to one another in many ways. </p>
<p>Podman provides a Docker-compatible command-line interface that you can alias to the Docker command-line interface with the <code>$ alias docker = podman</code>. Also, Podman provides a socket-activated REST API service that makes it possible for remote apps to launch containers whenever they want. </p>
<p>Users of docker-py and docker-compose are able to connect with Podman as a service because this REST API also supports the Docker API.</p>
<p>By using the libpod library, Podman is able to handle the entirety of the container ecosystem, which includes pods, containers, container images, and container volumes. </p>
<p>Podman is distinct from Docker in that it does not require a server and has a lightweight and Daemon-less design. This means that it makes direct contact with runC to start containers, which eliminates the need for an overhead server.</p>
<p>Containers managed by Podman can either be operated by the root user or by a user with fewer privileges than root. </p>
<p>While working with Docker, the Docker Command Line Interface is how we interface with the daemon that Docker runs in the background. The daemon, which operates on containers and produces pictures, is where the majority of the program's functionality can be found. </p>
<p>This daemon runs with the permissions of the root user. This also suggests that a Docker container may have access to the file system of the host computer if the configuration is not done appropriately. </p>
<p>In contrast, the architecture of Podman makes it possible for us to collaborate with the user who is responsible for running the container, and this user does not need to have root access in order to execute the application. </p>
<p>When compared to containers that run with root capabilities, non-privileged containers provide a substantial advantage. This is because if an intruder breaks into a non-privileged container and flees, the intruder will still be an unprivileged host user. Using this approach provides an additional safeguard for our data.</p>
<p>Just replace Docker with Podman in the instructions to use it. It has the same commands as Docker.</p>
<pre><code>$ alias docker=podman
</code></pre><h5 id="heading-what-other-advantages-does-podman-have">What other advantages does Podman have?</h5>
<ul>
<li>Integrated support for systemd makes it possible to run container processes in the background without the need for a separate daemon process.</li>
<li>Provides us with the ability to build and manage Podami, a collection consisting of one or more functional containers. Because of this, future workload migration to Kubernetes and the orchestration of Podman containers is now possible.</li>
<li>It is possible to implement UID separation using namespaces, providing an additional layer of security isolation while containers are being executed.</li>
<li>Can create a YAML file for Kubernetes from a container that is currently operating (with the command <code>$ podman generate kube</code>).</li>
</ul>
<h2 id="heading-how-to-launch-a-container">How to Launch a Container</h2>
<p>To launch any container we need two things: Image and RunTime.</p>
<p>Container engines such as Docker and Podman are only an additional software layer that sits on top of the runtimes. They are not responsible for actually launching the containers themselves. </p>
<p>They also initiate interaction with the runtimes in the background to start the container processes.</p>
<p>A Container Runtime is a software that runs and manages the components required to run containers.</p>
<p>Runtime is actually a program/software which launches, deletes, and removes containers.</p>
<p>runC is a very famous Runtime, but we have many other Runtimes like gvisor and kata.</p>
<p>Docker connects to this runtime behind the scenes.</p>
<p>The runtime spec file is a configuration file where we give all the important things for the container to be launch like CMD, folder, network, and so on. It is the file that the container runtime uses to launch the container.</p>
<p>We can verify that Docker is using runC as its default runtime engine like this:</p>
<pre><code>$ docker info
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-35.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-how-to-use-runc-the-universal-container-runtime">How to use runC – the universal container runtime</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-36.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Because "containers" are a collection of complex and occasionally obscure system elements, they are combined into a single low-level component. This is runC.<br>As a standalone tool, infrastructure plumbers all around the world utilise runC as plumbing.</p>
<p>runC is a lightweight, portable runtime for containers. It is a command-line tool for creating and running containers according to the Open Container Initiative (OCI) specification. It has libcontainer, which is the original lower-layer library interface that the Docker engine used to set up what we call an operating system container.</p>
<p>runC is designed with the principles of security, usability at large scale, and no dependency on Docker in mind.</p>
<p>Whenever we launch a container, it starts within a second. It looks like a new OS has launched because it has all the things an OS would have (like all the commands, network card, and more). It looks like an independent OS.</p>
<h4 id="heading-how-can-a-container-be-launched-in-one-second">How can a container be launched in one second?</h4>
<p>As you may know, when you run any program, it becomes a process. So even here, every running container is a process in the host system. So whenever we launch a container, it means we have started some process.</p>
<p>It looks like that container is a different OS with its own file system, network, and so on, as I mentioned above. But the kernel runs this entire setup inside a process by using the concept of namespaces. We'll discuss namespaces further in a minute.</p>
<p>So, as the container is a process, it launches quickly.</p>
<p>A container is just a process running in the RAM. This process looks like it is running a full-flash OS inside an OS. Typically, the process (container) runs the bash command, which has an infinite lifetime till someone gives an exit command.</p>
<p>If we inspect the container, we can find the PID of the /bin/bash command running in the base OS. Now, if we kill the process of the /bin/bash, the container will also be terminated.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-37.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h4 id="heading-what-is-a-namespace">What is a namespace?</h4>
<p>Again, running a container is also a process. But with Docker, a container is given with its own principal user, network configuration, mount folders, filesystem, and so on which they get as a common component of the baseOS. As a result, the container now has its own isolated environment, known as a namespace.</p>
<pre><code>$ lsns

# To list down all the namespace <span class="hljs-keyword">in</span> the baseOS
</code></pre><p>To launch a container, Docker Creates a Runtime Spec file for runC, and then runC uses that to launch the container. runC creates Namespaces for the container process.</p>
<p>The Image works as a Hard Drive – that is, it contains the entire file system for the container. A Container Image bundles all the data which is mounted on a storage namespace (that is, mount namespace).</p>
<p>The Image creates the entire bundle in the "/" directory of the containers. We have to unbundle it by untaring it.</p>
<p>Note that runC will not download, unzip, or untar the images for us. It can launch the container and mount the files for us to the container. For the images, we need some image management tools.</p>
<p>Also, runC only provides us with a network namespace, but Docker has to manage the network (that is, specify the IP range, provide IPs, and so on).</p>
<p>Docker can download, unzip, or unbundle the images. It can also do the required networking setup. It can also connect to the storage for us, and many such features are provided by Docker. Typically, Docker can do almost all the stuff provided by Kubernetes via its commands.</p>
<p>In Docker, we have a client-server architecture in which we have Docker CLI working as the client program and the container as the server. The server will now connect to the runtime and launch the container for us.</p>
<p>If we want to launch the container directly, we can do so with the help of runC. </p>
<p>First, we need to install runC using yum.</p>
<pre><code>$ runc list 

# This will list the available containers.
</code></pre><pre><code>$ runc spec

# To create a runtime spec file <span class="hljs-keyword">in</span> current directory.
</code></pre><p>runC is written in the Go language. So, generally it supports Go programs (images are also written in the Go language).</p>
<p><code>$ go build -o name</code> is the command to compile a Go program.</p>
<h3 id="heading-runc-commands">runC Commands:</h3>
<pre><code>$ runc create &lt;cont_name&gt;

# To launch a container (This will take config file <span class="hljs-keyword">from</span> current directory).
</code></pre><pre><code>$ runc start &lt;cont_name&gt;

# This command will run and give the output <span class="hljs-keyword">of</span> the program that we’ve specified <span class="hljs-keyword">in</span> container.
</code></pre><p>In the workspace we use the following:</p>
<pre><code>$ runc spec

# This will create a config.json file <span class="hljs-keyword">for</span> the runC configuration.
</code></pre><p>In the congif.json file, we must change the parameters-values according to our requirements. </p>
<p>For example, if we don’t want the terminal, we need to make it false. For that we can give the command to run in the arg, we can set the hostname, and so on.</p>
<p>We can connect to this container namespace by doing the following:</p>
<pre><code>$ nsenter -u -t -n &lt;pid_of_container&gt;

# To enter user and network namespace <span class="hljs-keyword">of</span> specific process ID.
</code></pre><h4 id="heading-to-create-a-container-just-by-using-runc">To create a container just by using runC:</h4>
<ol>
<li>Install runC.</li>
<li>Create config.json by running the runC spec command.</li>
<li>Mention all the important things in the above file. We also have to give process by writing its code in the Go language.</li>
<li>Create a rootfs folder in the current workspace and move the compiled Go code into this folder.</li>
<li>Now, to launch the container:</li>
</ol>
<pre><code>$ start runc create &lt;container_name&gt;
</code></pre><p>To start the container and print on the console whatever is there in the go file, run this command:</p>
<pre><code>$ runc start &lt;container_name&gt;
</code></pre><h3 id="heading-how-to-generate-an-example-specification-with-runc">How to generate an example specification with runC:</h3>
<pre><code>&gt; runc spec
&gt; cat config.json
{
  <span class="hljs-string">"ociVersion"</span>: <span class="hljs-string">"1.0.0"</span>,
  <span class="hljs-string">"process"</span>: {
    <span class="hljs-string">"terminal"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-string">"user"</span>: { <span class="hljs-string">"uid"</span>: <span class="hljs-number">0</span>, <span class="hljs-string">"gid"</span>: <span class="hljs-number">0</span> },
    <span class="hljs-string">"args"</span>: [<span class="hljs-string">"sh"</span>],
    <span class="hljs-string">"env"</span>: [
      <span class="hljs-string">"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"</span>,
      <span class="hljs-string">"TERM=xterm"</span>
    ],
    <span class="hljs-string">"cwd"</span>: <span class="hljs-string">"/"</span>,
    <span class="hljs-string">"capabilities"</span>: {
      <span class="hljs-string">"bounding"</span>: [<span class="hljs-string">"CAP_AUDIT_WRITE"</span>, <span class="hljs-string">"CAP_KILL"</span>, <span class="hljs-string">"CAP_NET_BIND_SERVICE"</span>],
      [...]
    },
    <span class="hljs-string">"rlimits"</span>: [ { <span class="hljs-string">"type"</span>: <span class="hljs-string">"RLIMIT_NOFILE"</span>, <span class="hljs-string">"hard"</span>: <span class="hljs-number">1024</span>, <span class="hljs-string">"soft"</span>: <span class="hljs-number">1024</span> } ],
    <span class="hljs-string">"noNewPrivileges"</span>: <span class="hljs-literal">true</span>
  },
  <span class="hljs-string">"root"</span>: { <span class="hljs-string">"path"</span>: <span class="hljs-string">"rootfs"</span>, <span class="hljs-string">"readonly"</span>: <span class="hljs-literal">true</span> },
  <span class="hljs-string">"hostname"</span>: <span class="hljs-string">"runc"</span>,
  <span class="hljs-string">"mounts"</span>: [
    {
      <span class="hljs-string">"destination"</span>: <span class="hljs-string">"/proc"</span>,
      <span class="hljs-string">"type"</span>: <span class="hljs-string">"proc"</span>,
      <span class="hljs-string">"source"</span>: <span class="hljs-string">"proc"</span>
    },
    [...]
  ],
  <span class="hljs-string">"linux"</span>: {
    <span class="hljs-string">"resources"</span>: { <span class="hljs-string">"devices"</span>: [ { <span class="hljs-string">"allow"</span>: <span class="hljs-literal">false</span>, <span class="hljs-string">"access"</span>: <span class="hljs-string">"rwm"</span> } ] },
    <span class="hljs-string">"namespaces"</span>: [
      { <span class="hljs-string">"type"</span>: <span class="hljs-string">"pid"</span> },
      { <span class="hljs-string">"type"</span>: <span class="hljs-string">"network"</span> },
      { <span class="hljs-string">"type"</span>: <span class="hljs-string">"ipc"</span> },
      { <span class="hljs-string">"type"</span>: <span class="hljs-string">"uts"</span> },
      { <span class="hljs-string">"type"</span>: <span class="hljs-string">"mount"</span> }
    ],
    <span class="hljs-string">"maskedPaths"</span>: [
      <span class="hljs-string">"/proc/kcore"</span>,
      [...]
    ],
    <span class="hljs-string">"readonlyPaths"</span>: [
      <span class="hljs-string">"/proc/asound"</span>,
      [...]
    ]
  }
}
</code></pre><h2 id="heading-why-did-kubernetes-depreciate-docker">Why Did Kubernetes Depreciate Docker?</h2>
<p>Docker is often the first choice when it comes to managing and creating containers and images. It is extremely fast – so you might be wondering why Kubernetes dropped Docker and went on to use the CRI-O container engine? Let’s explore.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/0_jh4jUOjPPNS-bfU0.png" alt="Image" width="600" height="400" loading="lazy">
<em>Source: https://www.sumologic.com/blog/kubernetes-vs-docker/</em></p>
<p>We can check the Docker container engine like this:</p>
<pre><code>$ systemctl status docker
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-41.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Here it shows Docker Application Container Engine but conntainerD is the actual engine running.</p>
<p>In Docker, when kubelet needs to connect to the ContainerD it has to go through an API Docker shim to contact runC. This acts as an interface between Docker and Kubernetes. This makes the whole process fairly complex.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-40.png" alt="Image" width="600" height="400" loading="lazy">
<em>Source: Tutorial Works</em></p>
<h3 id="heading-what-is-conatinerd">What is ConatinerD?</h3>
<p>ContainerD is an industry standard container runtime that emphasises simplicity, durability, and portability.</p>
<p>You can find a daemon-based implementation of containerD on both Linux and Windows. It is responsible for managing the whole container lifecycle of the system that it is hosted on, which includes image transfer and storage, container execution and monitoring, low-level storage, and network attachments.</p>
<h4 id="heading-features-of-containerd">Features of ContainerD:</h4>
<ul>
<li>OCI Image Spec support</li>
<li>Image push and pull support</li>
<li>Network primitives for creation, modification, and deletion of interfaces</li>
<li>Multi-tenant supported with CAS storage for global images</li>
<li>OCI Runtime Spec support (aka runC)</li>
<li>Container runtime and lifecycle support</li>
<li>Management of network namespaces containers to join existing namespaces</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-42.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-what-is-dockerd">What is dockerd?</h3>
<p>Docker's daemon may be kicked off with the help of dockerd (so you can command the daemon to manage images, containers, and so on). Dockerd is a server that runs in the background as a daemon.</p>
<p>To run the Docker daemon we can specify dockerd. After the dockerd keyword, you should supply the daemon parameters you want to use. </p>
<p>dockerd (Docker Daemon) can listen for Docker Engine API requests via three different types of Sockets: <code>unix</code>, <code>tcp</code>, and <code>fd</code>.</p>
<h3 id="heading-challenges-of-using-docker">Challenges of Using Docker</h3>
<h4 id="heading-overhead">Overhead</h4>
<p>Docker is a fairly developed platform in the container market. Along with container management, it offers many other capabilities like storage, security, and network infrastructure, among other things.</p>
<p>When compared to Cri-O and Podman, Docker's performance suffers as a direct result of the overhead caused by these additional functionalities. </p>
<p>But Kubernetes and OpenShift come equipped with all of these functions. Therefore, they want only one thing from the container engine: the ability to launch and manage the containers. In other words, they do not need any other functions.</p>
<h4 id="heading-dockershim">Dockershim</h4>
<p>In Kubernetes, the process of launching containers begins when kubelet communicates with containerD, which then contacts runC.</p>
<p>Because separate businesses are responsible for the production of containerD and kubelet, kubelet must have an additional layer in order to contact containerD (an API like layer). And inside the Docker ecosystem, this layer is referred to as Dockershim.</p>
<p>Kubernetes had depreciated dockershim because of the complexities and burden created by Docker updates.</p>
<h4 id="heading-whats-the-issue-with-dockershim">What's the issue with dockershim?</h4>
<p>Kubernetes suggested a temporary solution to include support for Docker so that it could serve as its container runtime. Dockershim's deprecation just signifies that Dockershim's code will no longer be maintained in the Kubernetes source repository. </p>
<p>Dockershim has become a significant problem for Kubernetes developers. Following this change, the Kubernetes community will only be permitted to maintain the Kubernetes Container Runtime Interface (CRI). </p>
<p>Kubernetes supports all CRI-compliant runtimes, such as containerD and CRI-O.</p>
<p>Kubernetes has come up with CRI-O as its interface to contact with runC. Kubelet will now be contacting CRI-O. Further, it will contact the runC, and the container will be launched.</p>
<p>However, like CRI-O and Docker, there are many container engines present. So, the Kubernetes community decided to create an abstraction layer on top of all container engines. So, a client can use any container engine according to their requirements.</p>
<p>This abstraction layer is called CRI (container runtime interface).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-44.png" alt="Image" width="600" height="400" loading="lazy">
<em>Kubernetes using Docker vs Kubernetes using CRI-O</em></p>
<h3 id="heading-what-is-a-cri-container-runtime-interface">What is a CRI (Container Runtime Interface)?</h3>
<p>The Kubelet program abstracts the underlying container engines. The Container Runtime Interface (CRI) is a plugin interface that lets kubelet use several container runtimes without recompilation. </p>
<p>In addition to protocol buffers, the gRPC API, and libraries, other specifications and tools are in active development for CRI.</p>
<p>Kubelet establishes a connection with CRI over the gRPC Protocol.</p>
<h3 id="heading-what-is-cri-o">What is CRI-O?</h3>
<p>CRI-OCI is an abbreviation that stands for the Container Runtime Interface and OCI, which stands for the Open Container Initiative.</p>
<p>The term CRI-O was chosen after taking into account references made by members of the CRI and CIO communities.</p>
<p>CRI-O is another container engine, but it is more lightweight than Docker since it does not include the additional capabilities that Docker has, such as networking, storage, and so on.</p>
<p>CRI-O provides a foundation that is more secure, stable, and performant for the execution of runtimes that are compatible with the Open Container Initiative (OCI). Runtimes that are OCI-compliant can be used in conjunction with the CRI-O container engine to launch containers and pods. </p>
<p>Examples of such runtimes include runC, which is the default OCI runtime, and Kata Containers. But you can use any OCI-conformant runtime in its place. </p>
<p>The goal of the CRI-O project is to replace Docker as the container engine that implements the Kubernetes Container Runtime Interface (CRI) for OpenShift Container Platform and Kubernetes.</p>
<p>The stability of CRI-O may be attributed to the fact that it is developed, tested, and distributed in tandem with major and minor versions of Kubernetes and complies with OCI standards. </p>
<p>The O's in CRI-scope are reliant on the Container Runtime Interface (CRI). The actual container engine specifications of a Kubernetes service (kubelet) were compiled and specified by CRI. </p>
<p>In light of the fact that several container engines were being developed, the CRI team decided to take this measure in order to settle Kubernetes' requirements for container engines.</p>
<p>According to the OpenShift Docs, the tools that help replace and extend what the Docker command and service provided are:</p>
<ul>
<li>crictl: For working directly with CRI-O container engines &amp; troubleshooting</li>
<li>runc: For running container images</li>
<li>podman: For managing pods and container images (run, stop, start, ps, attach, exec, and so on) outside of the container engine</li>
<li>buildah: For building, pushing and signing container images</li>
<li>skopeo: For copying, inspecting, deleting, and signing images</li>
</ul>
<h3 id="heading-cri-o-architecture">CRI-O Architecture</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-49.png" alt="Image" width="600" height="400" loading="lazy">
<em>Source: cri-o.io</em></p>
<h2 id="heading-how-to-build-a-multi-node-cluster-using-cri-o">How to Build a Multi-Node Cluster using CRI-O</h2>
<p>Following are the commands you'd use to create a multi-node Kubernetes cluster using CRI-O in Ubuntu 20.04.</p>
<p>Here's the repository that contains the set of commands: </p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/gursimarh/Kubernetes-CRIO/blob/main/commands">https://github.com/gursimarh/Kubernetes-CRIO/blob/main/commands</a></div>
<pre><code>OS=xUbuntu_20<span class="hljs-number">.04</span>
VERSION=<span class="hljs-number">1.20</span>

cat &gt;&gt;<span class="hljs-regexp">/etc/</span>apt/sources.list.d/devel:kubic:libcontainers:stable.list&lt;&lt;EOF
deb https:<span class="hljs-comment">//download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/ /</span>
EOF

cat &gt;&gt;<span class="hljs-regexp">/etc/</span>apt/sources.list.d/devel:kubic:libcontainers:stable:cri-o:$VERSION.list&lt;&lt;EOF
deb http:<span class="hljs-comment">//download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/$VERSION/$OS/ /</span>
EOF

curl -L https:<span class="hljs-comment">//download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/Release.key | apt-key --keyring /etc/apt/trusted.gpg.d/libcontainers.gpg add -</span>

curl -L https:<span class="hljs-comment">//download.opensuse.org/repositories/devel:kubic:libcontainers:stable:cri-o:$VERSION/$OS/Release.key | apt-key --keyring /etc/apt/trusted.gpg.d/libcontainers-cri-o.gpg add -</span>

apt update

apt install -qq -y cri-o cri-o-runc cri-tools

systemctl daemon-reload

systemctl enable --now crio

curl -s https:<span class="hljs-comment">//packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -</span>


apt-add-repository <span class="hljs-string">"deb http://apt.kubernetes.io/ kubernetes-xenial main"</span>

apt install -qq -y kubeadm=<span class="hljs-number">1.20</span><span class="hljs-number">.5</span><span class="hljs-number">-00</span> kubelet=<span class="hljs-number">1.20</span><span class="hljs-number">.5</span><span class="hljs-number">-00</span> kubectl=<span class="hljs-number">1.20</span><span class="hljs-number">.5</span><span class="hljs-number">-00</span>

cat &gt;&gt;<span class="hljs-regexp">/etc/m</span>odules-load.d/crio.conf&lt;&lt;EOF
overlay
br_netfilter
EOF

modprobe overlay

modprobe br_netfilter

cat &gt;&gt;<span class="hljs-regexp">/etc/</span>sysctl.d/kubernetes.conf&lt;&lt;EOF
net.bridge.bridge-nf-call-ip6tables = <span class="hljs-number">1</span>
net.bridge.bridge-nf-call-iptables  = <span class="hljs-number">1</span>
net.ipv4.ip_forward                 = <span class="hljs-number">1</span>
EOF

sysctl --system

cat &gt;&gt;<span class="hljs-regexp">/etc/</span>crio/crio.conf.d/<span class="hljs-number">02</span>-cgroup-manager.conf&lt;&lt;EOF
[crio.runtime]
conmon_cgroup = <span class="hljs-string">"pod"</span>
cgroup_manager = <span class="hljs-string">"cgroupfs"</span>
EOF

systemctl daemon-reload

systemctl enable --now crio

systemctl restart crio

sed -i <span class="hljs-string">'/swap/d'</span> /etc/fstab

swapoff -a

systemctl disable --now ufw

kubeadm init --apiserver-advertise-address=<span class="hljs-number">172.16</span><span class="hljs-number">.16</span><span class="hljs-number">.100</span> --pod-network-cidr=<span class="hljs-number">192.168</span><span class="hljs-number">.0</span><span class="hljs-number">.0</span>/<span class="hljs-number">16</span>

kubectl --kubeconfig=<span class="hljs-regexp">/etc/</span>kubernetes/admin.conf create -f https:<span class="hljs-comment">//docs.projectcalico.org/v3.18/manifests/calico.yaml</span>

kubeadm token create --print-join-command
</code></pre><p>We can use the join command to connect the nodes to the cluster and we're ready with a multi-node cluster of Kubernetes.</p>
<h3 id="heading-heres-an-illustration-of-how-docker-kubernetes-cri-o-containerd-and-runc-work-together">Here's an illustration of how Docker, Kubernetes, CRI-O, containerD and runC work together</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-43.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-container-runtimes">Container Runtimes</h3>
<p>We have seen a lot of details on how containers work, we have defined container runtimes and how we can build our custom container using runC. Now, are there any other tools in hand for us like runC?</p>
<p>Here we will look at landscape of all the container runtimes that are available.</p>
<p>Generally, they fall into two main categories: </p>
<ol>
<li>Open Container Initiative (OCI) runtimes</li>
</ol>
<p>The OCI runtimes are further classified in two broader categories: Native Runtimes and Sandboxed &amp; Virtualized Runtimes</p>
<ol start="2">
<li>Container Runtime Interface (CRI)</li>
</ol>
<p>The CRI consists of containerD and CRI-O.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-47.png" alt="Image" width="600" height="400" loading="lazy">
<em>1. Open Container Initiative (OCI) runtimes</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/08/image-48.png" alt="Image" width="600" height="400" loading="lazy">
<em>2. Container Runtime Interface (CRI)</em></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Here we saw how we can build our custom images and the various tool available at our disposal. It was a long one but I hope you've enjoyed it and have learned something new.</p>
<p>I'm always open to suggestions and discussions on <a target="_blank" href="https://www.linkedin.com/in/gursimarh">LinkedIn</a>. Hit me up with direct messages.</p>
<p>If you've enjoyed my writing and want to keep me motivated, consider leaving starts on <a target="_blank" href="https://github.com/gursimarh">GitHub</a> and endorse me for relevant skills on <a target="_blank" href="https://www.linkedin.com/in/gursimarh">LinkedIn</a>.</p>
<p>Till the next one, stay safe and keep learning.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
