<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sunny Bhambhani</title>
    <description>The latest articles on DEV Community by Sunny Bhambhani (@sunnybhambhani).</description>
    <link>https://dev.to/sunnybhambhani</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1005168%2Fe3697725-f1bf-4345-883a-30d23e3446f2.jpeg</url>
      <title>DEV Community: Sunny Bhambhani</title>
      <link>https://dev.to/sunnybhambhani</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sunnybhambhani"/>
    <language>en</language>
    <item>
      <title>Using Firehose as a Lambda Log Destination</title>
      <dc:creator>Sunny Bhambhani</dc:creator>
      <pubDate>Thu, 15 Oct 2026 07:43:05 +0000</pubDate>
      <link>https://dev.to/aws-builders/using-firehose-as-a-lambda-log-destination-22po</link>
      <guid>https://dev.to/aws-builders/using-firehose-as-a-lambda-log-destination-22po</guid>
      <description>&lt;h1&gt;
  
  
  Using Firehose as a Lambda Log Destination
&lt;/h1&gt;

&lt;p&gt;The last logging option available in the Lambda configuration is Amazon Data Firehose.&lt;/p&gt;

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

&lt;p&gt;This option becomes interesting when CloudWatch Logs is not the final destination and you want Lambda logs to keep moving through a delivery pipeline.&lt;/p&gt;

&lt;p&gt;Instead of just storing logs in one place, Firehose is built to receive data, optionally transform it, and then deliver it to another system.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Firehose works at a high level
&lt;/h2&gt;

&lt;p&gt;The flow is fairly straightforward:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ingest: choose where the incoming data comes from, such as Amazon Kinesis Data Streams, Amazon MSK, or Direct PUT&lt;/li&gt;
&lt;li&gt;Transform: optionally process or enrich the data before delivery&lt;/li&gt;
&lt;li&gt;Deliver: send the data to a destination such as Amazon S3, Splunk, Dynatrace, and others&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That flexibility is the main reason Firehose is useful. It can sit between the source and the final storage or observability platform without needing you to build the delivery logic yourself.&lt;/p&gt;

&lt;p&gt;For this example, I kept things simple and used Amazon S3 as the destination.&lt;/p&gt;

&lt;p&gt;If you want to see the full list of supported destinations, AWS documents them here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/firehose/latest/dev/create-destination.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/firehose/latest/dev/create-destination.html&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Firehose stream
&lt;/h2&gt;

&lt;p&gt;Before sending Lambda logs to Firehose, I created a delivery stream with the following setup:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Source: &lt;code&gt;Direct PUT&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Destination: &lt;code&gt;Amazon S3&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;ARN: &lt;code&gt;arn:aws:firehose:eu-central-1:ACCOUNT_ID:deliverystream/PUT-S3-QdzyI&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Make sure the status is &lt;code&gt;Active&lt;/code&gt; after it is created.&lt;/p&gt;

&lt;h2&gt;
  
  
  Destination settings
&lt;/h2&gt;

&lt;p&gt;The S3 delivery stream was configured like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;S3 bucket: &lt;code&gt;s3-lambda-logs&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;S3 bucket error output prefix: &lt;code&gt;fh_err_&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;S3 bucket prefix: &lt;code&gt;fh_&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;S3 bucket and error output prefix time zone: &lt;code&gt;UTC&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;New line delimiter: &lt;code&gt;Enabled&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This setup is useful because it separates normal output from delivery errors and keeps the objects written to S3 organized under a predictable prefix.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the logs land in S3
&lt;/h2&gt;

&lt;p&gt;After the stream is configured and Lambda starts sending logs through Firehose, the delivered files appear in S3 under a path like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Amazon S3 -&amp;gt; Buckets -&amp;gt; s3-lambda-logs -&amp;gt; fh_2026/ -&amp;gt; 10/ -&amp;gt; 11/ -&amp;gt; 12/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That structure makes it easier to find logs by date and process them later with downstream tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  A quick note about delivery log classes
&lt;/h2&gt;

&lt;p&gt;If you send logs to Amazon S3 or Amazon Data Firehose, Lambda requires a log group with the delivery log class.&lt;/p&gt;

&lt;p&gt;That is an important detail because this log class is designed for delivery, not for the full CloudWatch Logs experience. In other words, you trade some CloudWatch features for simpler forwarding.&lt;/p&gt;

&lt;p&gt;For example, delivery log class does not support standard CloudWatch Logs features such as Logs Insights and Live Tail.&lt;/p&gt;

&lt;p&gt;It is also worth remembering that log events are only kept in CloudWatch Logs for two days when this class is used. That retention period is fixed and cannot be changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Function
&lt;/h2&gt;

&lt;p&gt;The function remains the same which we discussed in the first article.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Dummy Lambda output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Dummy Lambda output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  In this example:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A new log group is created named &lt;code&gt;dummy_lambda_logs_to_firehose&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;I also created an IAM role for the Lambda function. The trust relationship and permissions are defined below:

&lt;ul&gt;
&lt;li&gt;03_iam_role_trust_relationships.json
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Principal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"Service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"logs.amazonaws.com"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sts:AssumeRole"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Condition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"StringLike"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"aws:SourceArn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:logs:eu-central-1:ACCOUNT_ID:*"&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;03_iam_role_permissiones.json
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"firehose:PutRecord"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"firehose:PutRecordBatch"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:firehose:eu-central-1:ACCOUNT_ID:deliverystream/*"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notes:&lt;/p&gt;

&lt;p&gt;Log delivery to Amazon Data Firehose requires using a log group with the delivery log class. This enables efficient routing, but it does not support standard CloudWatch Logs features such as Logs Insights and Live Tail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;If CloudWatch Logs is where you troubleshoot, S3 is where you archive, then Firehose is the option you use when logs need to travel.&lt;/p&gt;

&lt;p&gt;For a simple demo, using Firehose with S3 keeps the architecture easy to understand. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In a larger environment, the same pattern can be extended to feed analytics, security, or observability platforms without changing the Lambda function itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feel free to add your thoughts, happy learning!&lt;/p&gt;

</description>
      <category>lambda</category>
      <category>logging</category>
      <category>operations</category>
      <category>aws</category>
    </item>
    <item>
      <title>Moving Lambda Logs to a Centralized Location [S3]</title>
      <dc:creator>Sunny Bhambhani</dc:creator>
      <pubDate>Thu, 15 Oct 2026 07:19:33 +0000</pubDate>
      <link>https://dev.to/aws-builders/moving-lambda-logs-to-a-centralized-location-s3-17i5</link>
      <guid>https://dev.to/aws-builders/moving-lambda-logs-to-a-centralized-location-s3-17i5</guid>
      <description>&lt;h1&gt;
  
  
  Moving Lambda Logs to a Centralized Location[S3]
&lt;/h1&gt;

&lt;p&gt;AWS Lambda gives you logs out of the box, but once an application starts growing, the real question becomes: where should those logs go?&lt;/p&gt;

&lt;p&gt;If you are only testing a function, CloudWatch Logs is usually enough. But if you want long-term storage, centralized analysis, or integration with downstream systems, AWS gives you a few different ways to send Lambda logs somewhere else.&lt;/p&gt;

&lt;h2&gt;
  
  
  The available options
&lt;/h2&gt;

&lt;p&gt;Inside the Lambda console, you can go to:&lt;/p&gt;

&lt;p&gt;Configuration -&amp;gt; Monitoring and operational tools -&amp;gt; Logging configuration -&amp;gt; Edit -&amp;gt; Log Destination&lt;/p&gt;

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

&lt;p&gt;From there, you get three choices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Amazon CloudWatch Logs: the default option&lt;/li&gt;
&lt;li&gt;Amazon S3: a simple choice for long-term archiving&lt;/li&gt;
&lt;li&gt;Amazon Data Firehose: useful when you want to stream logs in near real time to other destinations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each option solves a different problem, so the right one depends on what you want to do with the logs after Lambda writes them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Function
&lt;/h2&gt;

&lt;p&gt;The function remains the same which we discussed in the first article.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Dummy Lambda output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Dummy Lambda output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A quick note about delivery log classes
&lt;/h2&gt;

&lt;p&gt;If you send logs to Amazon S3 or Amazon Data Firehose, Lambda requires a log group with the delivery log class.&lt;/p&gt;

&lt;p&gt;That is an important detail because this log class is designed for delivery, not for the full CloudWatch Logs experience. In other words, you trade some CloudWatch features for simpler forwarding.&lt;/p&gt;

&lt;p&gt;For example, delivery log class does not support standard CloudWatch Logs features such as Logs Insights and Live Tail.&lt;/p&gt;

&lt;p&gt;It is also worth remembering that log events are only kept in CloudWatch Logs for two days when this class is used. That retention period is fixed and cannot be changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  In this example, I used Amazon S3
&lt;/h2&gt;

&lt;p&gt;For this setup, I created a new log group using the delivery class and named it &lt;code&gt;dummy_lambda_logs_to_s3&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then I selected this bucket:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;arn:aws:s3:::s3-lambda-logs&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I also created an IAM role for the Lambda function. The trust relationship and permissions are defined in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;02_iam_role_trust_relationships.json
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2008-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Principal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"Service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"logs.amazonaws.com"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sts:AssumeRole"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Condition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"StringLike"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"aws:SourceArn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:logs:eu-central-1:ACCOUNT_ID:*"&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;02_iam_role_permissions.json
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"s3:PutObject"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::s3-lambda-logs/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::s3-lambda-logs"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After saving the configuration, Lambda starts delivering logs to the S3 bucket.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the S3 path looks like
&lt;/h2&gt;

&lt;p&gt;When you invoke the function again, the logs show up in the bucket under a path like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Amazon S3 -&amp;gt; Buckets -&amp;gt; s3-lambda-logs -&amp;gt; AWSLogs/ -&amp;gt; ACCOUNT_ID/ -&amp;gt; eu-central-1/ -&amp;gt; dummy_lambda_logs_to_s3/ -&amp;gt; 2026/ -&amp;gt; 10/ -&amp;gt; 11/ -&amp;gt; 12/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That layout is useful because it keeps the logs organized by account, region, log group, and time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;This is the part that often gets overlooked.&lt;/p&gt;

&lt;p&gt;CloudWatch Logs is great for day-to-day debugging, but not every team wants to keep everything there forever. Sometimes you want a cheaper archive. Sometimes you want to move logs into a data lake. Sometimes you want to push them to another analytics pipeline.&lt;/p&gt;

&lt;p&gt;That is where S3 and Firehose start making sense.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use CloudWatch Logs when you want convenience and fast troubleshooting&lt;/li&gt;
&lt;li&gt;Use S3 when you want simple long-term storage and archiving&lt;/li&gt;
&lt;li&gt;Use Firehose when you want logs flowing into another system in near real time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notes:&lt;/p&gt;

&lt;p&gt;Log delivery to Amazon S3 requires using a log group with the delivery log class. This enables efficient routing, but it does not support standard CloudWatch Logs features such as Logs Insights and Live Tail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;There is no single best destination for Lambda logs. The best option depends on what you are trying to do with them.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you need quick operational visibility, keep them in CloudWatch Logs.&lt;/li&gt;
&lt;li&gt;If you need long-term retention, move them to S3. &lt;/li&gt;
&lt;li&gt;If you need streaming delivery to another platform, Firehose is the better fit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this example, S3 is a clean middle ground because it keeps the setup simple while still giving you centralized storage.&lt;/p&gt;

&lt;p&gt;Feel free to share your thoughts, happy learning!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>logging</category>
      <category>operations</category>
      <category>lambda</category>
    </item>
    <item>
      <title>Lambda Logging in AWS [Default]</title>
      <dc:creator>Sunny Bhambhani</dc:creator>
      <pubDate>Thu, 15 Oct 2026 07:01:03 +0000</pubDate>
      <link>https://dev.to/aws-builders/lambda-logging-in-aws-default-1nl5</link>
      <guid>https://dev.to/aws-builders/lambda-logging-in-aws-default-1nl5</guid>
      <description>&lt;h1&gt;
  
  
  Lambda Logging in AWS
&lt;/h1&gt;

&lt;p&gt;This example uses a very small AWS Lambda function named &lt;code&gt;dummy_output&lt;/code&gt; to show what Lambda logs look like by default, why plain-text logs are sometimes not enough, and why structured logging becomes important once you need centralized observability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lambda function
&lt;/h2&gt;

&lt;p&gt;The function prints a dummy message and returns a simple success response.&lt;/p&gt;

&lt;h2&gt;
  
  
  Function
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Dummy Lambda output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Dummy Lambda output&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Response
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"statusCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Dummy Lambda output"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Default log output
&lt;/h2&gt;

&lt;p&gt;When the function runs, AWS Lambda automatically sends logs to CloudWatch. By default, those logs are often plain text and include both application output and platform/runtime details.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;START RequestId: d386d5a9-2a75-41d1-TRIMMED Version: &lt;span class="nv"&gt;$LATEST&lt;/span&gt;
Dummy Lambda output
END RequestId: d386d5a9-2a75-41d1-TRIMMED
REPORT RequestId: d386d5a9-2a75-41d1-TRIMMED
Duration: 2.40 ms   
Billed Duration: 110 ms 
Memory Size: 128 MB 
Max Memory Used: 38 MB  
Init Duration: 106.81 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, these logs usually appear in a CloudWatch log group such as &lt;code&gt;/aws/lambda/FUNCTION_NAME&lt;/code&gt;, In our case its &lt;code&gt;/aws/lambda/dummy_output&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why plain text is limited
&lt;/h2&gt;

&lt;p&gt;Plain text is fine for quick debugging and small experiments. The problem starts when you need to centralize logs across multiple Lambda functions, search them efficiently, correlate events, or build dashboards and alerts.&lt;/p&gt;

&lt;p&gt;At that point, unstructured text becomes harder to query and harder to enrich. A log pipeline can still ingest plain text, but it will usually need extra parsing rules to make the data useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why structured logs help
&lt;/h2&gt;

&lt;p&gt;If your application is fully Lambda-based and you want to understand how it behaves in production, structured logs are a better default.&lt;/p&gt;

&lt;p&gt;JSON logs make it easier to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;search by fields like &lt;code&gt;Level&lt;/code&gt;, &lt;code&gt;RequestId&lt;/code&gt;, &lt;code&gt;Service&lt;/code&gt;, etc&lt;/li&gt;
&lt;li&gt;filter application errors without parsing free-form text&lt;/li&gt;
&lt;li&gt;send logs to a centralized platform&lt;/li&gt;
&lt;li&gt;build dashboards, alerts, and retention policies&lt;/li&gt;
&lt;li&gt;correlate application logs with platform and tracing data&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Lambda logging configuration
&lt;/h2&gt;

&lt;p&gt;AWS Lambda supports changing log formatting from the console:&lt;/p&gt;

&lt;p&gt;Configuration -&amp;gt; Monitoring and operational tools -&amp;gt; Logging configuration -&amp;gt; Edit -&amp;gt; Log format -&amp;gt; JSON&lt;/p&gt;

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

&lt;p&gt;A practical starting point is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application log level: &lt;code&gt;INFO&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;System log level: &lt;code&gt;WARN&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That keeps routine noise down while still preserving useful runtime and platform information.&lt;/p&gt;

&lt;h2&gt;
  
  
  JSON log output
&lt;/h2&gt;

&lt;p&gt;When JSON logging is enabled, the response from the function does not change, but the logs become much richer and easier to work with.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-11T11:48:32.684Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"platform.initStart"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"record"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"initializationType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"on-demand"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"phase"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"init"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"runtimeVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"python:3.14.mainline.v75"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"runtimeVersionArn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:lambda:eu-central-1::runtime:TRIMMED"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"functionName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dummy_output"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"functionVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$LATEST"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"instanceId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026/10/11/dummy_output[$LATEST]TRIMMED"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"instanceMaxMemory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;134217728&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also see the runtime start, execution, and final report details separately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-11T11:48:32.807Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"platform.report"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"record"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"requestId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"5adc1477-4705-4710-TRIMMED"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"metrics"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"durationMs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.914&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"billedDurationMs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;102&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"memorySizeMB"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"maxMemoryUsedMB"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;38&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"initDurationMs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;99.535&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"success"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What this shows
&lt;/h2&gt;

&lt;p&gt;This is not about doubting AWS Lambda itself. Lambda is already a managed serverless compute service, and AWS handles the platform for us.&lt;/p&gt;

&lt;p&gt;The real reason to monitor it is different: our application logic is still ours. We still need to know when it fails, how it behaves under load?, what it returns?, and how it performs over time?.&lt;/p&gt;

&lt;p&gt;If 100% or majority of our application runs on Lambda, centralized logging becomes essential for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;troubleshooting failures&lt;/li&gt;
&lt;li&gt;tracing request paths across services&lt;/li&gt;
&lt;li&gt;understanding latency and cold starts&lt;/li&gt;
&lt;li&gt;detecting patterns in errors or retries&lt;/li&gt;
&lt;li&gt;supporting audit and operational visibility&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notes:&lt;/p&gt;

&lt;p&gt;The default CloudWatch Logs destination keeps the standard CloudWatch Logs experience, including Logs Insights and Live Tail. Query cost is separate, so broad or repeated searches can increase the total.&lt;/p&gt;

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

&lt;p&gt;For quick experiments, plain text logs are acceptable.&lt;/p&gt;

&lt;p&gt;For production, JSON logs are usually a better choice because they are easier to aggregate, query, and route into a centralized observability stack.&lt;/p&gt;

&lt;p&gt;If the goal is to operate a Lambda-based application at scale, structured logging should be the default rather than an afterthought.&lt;/p&gt;

&lt;p&gt;Feel free to share your thoughts, happy learning!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>lambda</category>
      <category>logging</category>
      <category>operations</category>
    </item>
    <item>
      <title>Python - Stop storing passwords in plain text! A guide to werkzeug.security</title>
      <dc:creator>Sunny Bhambhani</dc:creator>
      <pubDate>Mon, 05 Jan 2026 18:27:12 +0000</pubDate>
      <link>https://dev.to/aws-builders/python-stop-storing-passwords-in-plain-text-a-guide-to-werkzeugsecurity-179i</link>
      <guid>https://dev.to/aws-builders/python-stop-storing-passwords-in-plain-text-a-guide-to-werkzeugsecurity-179i</guid>
      <description>&lt;h2&gt;
  
  
  Problem
&lt;/h2&gt;

&lt;p&gt;Storing passwords in plain text presents numerous dangers.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What happens if your database is compromised? &lt;/li&gt;
&lt;li&gt;What if you accidentally reveal the wrong window while demonstrating and sharing your screen? &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Such mistakes can result in serious issues, including losing the trust of customers, damaging brand value, financial repercussions, legal penalties, etc. These kinds of incidents are not rare; news reports about data breaches frequently appear worldwide. &lt;/p&gt;

&lt;p&gt;Refer to &lt;a href="https://databreaches.net/" rel="noopener noreferrer"&gt;https://databreaches.net/&lt;/a&gt; for more details around data breaches worldwide.&lt;/p&gt;

&lt;p&gt;Therefore, we should consider security in each aspect of application development, starting from planning, coding, building, deployment, etc. &lt;/p&gt;

&lt;p&gt;And in this article, we will be talking about hashing passwords, but how do we actually do that? What options are available, etc.?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There are numerous options available, out of which some of the famous ones are werkzeug.security, argon2, bcrypt, etc.&lt;/li&gt;
&lt;li&gt;Here we will see what werkzeug.security is and its practical implementation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Working Python setup.&lt;/li&gt;
&lt;li&gt;Werkzeug Library installed.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install werkzeug
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Basics
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;How does this work?&lt;/strong&gt;&lt;br&gt;
werkzeug.security provides helper functions for secure password storage and verification, and the two most commonly used functions are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;generate_password_hash(password, method=XXX, salt_length=XXX)&lt;/li&gt;
&lt;li&gt;check_password_hash(PASSWORD_HASH, ACTUAL_PASSWORD)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More details around this can be found in its official documentation, refer: &lt;a href="https://werkzeug.palletsprojects.com/en/stable/utils/" rel="noopener noreferrer"&gt;https://werkzeug.palletsprojects.com/en/stable/utils/&lt;/a&gt; for more details.&lt;/p&gt;

&lt;p&gt;The basic principle behind it is, &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;generate_password_hash&lt;/strong&gt; takes the actual plain-text password as an input. &lt;/li&gt;
&lt;li&gt;Further generates a salt of specified length. &lt;/li&gt;
&lt;li&gt;The password + salt is processed through the chosen algorithm.

&lt;ul&gt;
&lt;li&gt;scrypt(default)&lt;/li&gt;
&lt;li&gt;pbkdf2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Finally, it generates the output as a structured, hashed string.&lt;/li&gt;
&lt;li&gt;Then &lt;strong&gt;check_password_hash&lt;/strong&gt; comes into the picture, it securely checks if the given password and the stored password hash match or not.&lt;/li&gt;
&lt;li&gt;Once that is evaluated, it produces a Boolean result, either true or false.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  HOWTO
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;generate_password_hash&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Import generate_password_hash
from werkzeug.security import generate_password_hash

# Plain text password, if using Flask, it can come from any web form
plain_password = "SHH_SECRET"

# Generate a hashed string using default parameters
hashed = generate_password_hash(plain_password)

# Printing a hashed string
print("Hashed String: ", hashed)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Output
Hashed String:  scrypt:32768:8:1$A2qi9GPp8Ut3cESv$31e31ffc4d21251396b391c31f09f6637e9169d4c5541a790cf0d9fcae3d58d2ba8a2df51e13f2601ba77fabe2e68d517fe845c63b489418309791ae1e350d3b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you observe, the hashed string contains multiple sections&lt;br&gt;
scrypt:N:r:p(METHOD_and_PARAMETERS)$salt(RANDOM_SALT)$derived_hash(ACTUAL_HASHED_PASSWORD)&lt;/p&gt;

&lt;p&gt;In the above example, we just used the default values to generate the password hash.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Method: scrypt
N: 32768
r: 8
p: 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Quick note about the parameters: Based on my understanding, the parameters N, r, and p in scrypt directly control how much compute and memory are required to derive a single password hash. The larger the numbers, the harder and more computationally intensive it is to break the password.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you want to use custom parameters, this is how we can use them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;generate_password_hash(plain_password, method="scrypt:32768:16:1", salt_length=32)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will produce the output as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scrypt:32768:16:1$0hkax1LolbhqTyEN9rMSi8MC2MoF5B8w$85a7175deab3795db17898d17f03e3164df0ae1d158081ca3ed1680f9f940ff9cac76df18a71595160fd39963f4b4811c82348354e0c4a67a328104c56900230
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;if you want to use another method, this is how we can use it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;generate_password_hash(plain_password, method="pbkdf2:sha256")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The execution of generate_password_hash function generates a string that needs to be stored and checked for verification.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;check_password_hash&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Import generate_password_hash and check_password_hash
from werkzeug.security import generate_password_hash, check_password_hash

# Plain text password, if using Flask, it can come from any web form
plain_password = "SHH_SECRET"
# Generate a hashed string using default parameters
hashed = generate_password_hash(plain_password)

# Login attempt 1 with wrong password
# If using Flask, it can come from any web form, like a login screen
login_attempt_1 = "SHH_WRONG_SECRET"
is_valid = check_password_hash(hashed, login_attempt_1)
print("Password correct?", is_valid)

# Login attempt 2 with correct password
# If using Flask, it can come from any web form, like a login screen
login_attempt_2 = "SHH_SECRET"
is_valid = check_password_hash(hashed, login_attempt_2)
print("Password correct?", is_valid)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Output
# This is the first attempt in which we used the wrong password, and it concluded that it was incorrect, hence it gave the output as false
Password correct? False
# This is the second attempt in which we used the correct password, and it concluded that it was correct, hence it gave the output as true
Password correct? True
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;Never store plaintext passwords; store only the hash strings.&lt;/li&gt;
&lt;li&gt;Do not re-invent the wheel; we can easily rely on vetted libraries and generate hash strings.&lt;/li&gt;
&lt;li&gt;Keep your dependencies up-to-date.&lt;/li&gt;
&lt;li&gt;Don’t compare strings manually; we can easily leverage functions like check_password_hash, which handle secure comparison.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Soon, I will be adding details about other libraries and functions as well. I hope this will be helpful.&lt;/p&gt;

&lt;p&gt;Feel free to add your thoughts and experiences. Also, since I am still learning, correct me if I am wrong or have misinterpreted anything. Happy Learning! 😄&lt;/p&gt;

</description>
      <category>python</category>
      <category>devops</category>
      <category>beginners</category>
      <category>linux</category>
    </item>
    <item>
      <title>A smarter way to use imagePullSecrets in Kubernetes Cluster using ServiceAccounts</title>
      <dc:creator>Sunny Bhambhani</dc:creator>
      <pubDate>Mon, 12 May 2025 12:16:05 +0000</pubDate>
      <link>https://dev.to/aws-builders/simplify-imagepullsecrets-with-serviceaccounts-in-kubernetes-2oc8</link>
      <guid>https://dev.to/aws-builders/simplify-imagepullsecrets-with-serviceaccounts-in-kubernetes-2oc8</guid>
      <description>&lt;p&gt;Kubernetes is everywhere now a days, so does the container images and fetching the images from a private registry is a norm because of N number of reasons including security, that being the topmost.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Recap
&lt;/h2&gt;

&lt;p&gt;Just to give you a heads up before we dive further, let's assume I fire &lt;code&gt;kubectl create deployment nginx --image nginx&lt;/code&gt; what do you think happens?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Using &lt;code&gt;kubeconfig&lt;/code&gt;, &lt;code&gt;kubectl&lt;/code&gt; first authenticates with the API server. &lt;/li&gt;
&lt;li&gt;It then constructs a &lt;code&gt;deployment object&lt;/code&gt; using the values which we provided like deployment name as &lt;code&gt;nginx&lt;/code&gt;, image to be used as &lt;code&gt;nginx&lt;/code&gt; and some default values and then sends a request to the API server.&lt;/li&gt;
&lt;li&gt;API server then validates the request and the object definition.&lt;/li&gt;
&lt;li&gt;This is further stored in &lt;code&gt;etcd&lt;/code&gt; datastore.&lt;/li&gt;
&lt;li&gt;Then the &lt;code&gt;controller manager&lt;/code&gt; specifically &lt;code&gt;deployment controller&lt;/code&gt; comes into the picture which creates a &lt;code&gt;replica set&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Then the &lt;code&gt;replica set&lt;/code&gt; creates a pod (this is where our nginx image will be used).&lt;/li&gt;
&lt;li&gt;Then the &lt;code&gt;schedular&lt;/code&gt; assigns the pod to a node, where it will run based on multiple conditions. If interested please check out my previous article on what all things happens in the background: &lt;a href="https://kubernetes.io/blog/2023/01/12/protect-mission-critical-pods-priorityclass/#resource-management-in-kubernetes" rel="noopener noreferrer"&gt;Resource management in Kubernetes&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Once the node is identified, the &lt;code&gt;kubelet&lt;/code&gt; running on the node is responsible for the management of the pod.&lt;/li&gt;
&lt;li&gt;Once the pod is scheduled on a specific node, the &lt;code&gt;kubelet&lt;/code&gt; looks for the image to be used and if it is already present.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;if that is present locally, it will use it.&lt;/p&gt;

&lt;p&gt;If not, it pulls the image from the registry.&lt;/p&gt;

&lt;p&gt;If the registry is public, there are no issues, it just pulls the image, runs the pods, and we are done.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  When imagePullSecrets are used?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Assume the registry is private, this is where &lt;code&gt;imagePullSecrets&lt;/code&gt; come into play. &lt;/li&gt;
&lt;li&gt;Kubernetes will need the secrets to authenticate the registry, so that it can pull the image.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How it works?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Firstly, we need to create a &lt;code&gt;secret&lt;/code&gt; which contains the credentials and some details of our docker registry like server-name, username, password, email, etc.&lt;/li&gt;
&lt;li&gt;It can be &lt;em&gt;created both imperative as well as declarative way&lt;/em&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ k get secrets  -o yaml dockersec
apiVersion: v1
data:
  .dockerconfigjson: ENCODED JSON OBJECT
kind: Secret
metadata:
  name: dockersec
  namespace: default
type: kubernetes.io/dockerconfigjson 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ k create secret docker-registry dockersec --docker-server=DOCKER_REGISTRY --docker-username=USERNAME --docker-password=PASSWORD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Quick note:&lt;/strong&gt; The secret must be of a type &lt;strong&gt;kubernetes.io/dockerconfigjson&lt;/strong&gt; or &lt;strong&gt;docker-registry&lt;/strong&gt; based on the way you choose to create the secret.&lt;/li&gt;
&lt;li&gt;Once the &lt;code&gt;secret&lt;/code&gt; is created, it must be &lt;code&gt;attached to a pod&lt;/code&gt; so that it can use it.&lt;/li&gt;
&lt;li&gt;Just add below content in your pod/deployment/statefulset yaml files, the name of the secret for me is dockersec but you can change based on your requirements.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spec:
  imagePullSecrets:
    - name: dockersec
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Before pulling the image, the &lt;code&gt;kubelet&lt;/code&gt; checks if the image is from a private registry. If so, it looks for &lt;code&gt;imagePullSecrets&lt;/code&gt; in the spec.&lt;/li&gt;
&lt;li&gt;Without proper &lt;code&gt;imagePullSecrets&lt;/code&gt;, the image pull will fail with &lt;code&gt;ImagePullBackOff&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Problem
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Now assume you have hundreds of &lt;code&gt;YAML&lt;/code&gt; files and hundreds of Kubernetes Object where we have to use this &lt;code&gt;imagePullSecrets&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Just for the sake of doing once, you thought to do it manually but just imagine there was a change in the name of the Kubernetes secret.&lt;/li&gt;
&lt;li&gt;Maybe because the organization now decides to streamline the naming convention of all the Kubernetes objects based on environments like prod/preprod/staging/etc.

&lt;ul&gt;
&lt;li&gt;Or your org is now moving to a different registry or a different provider.&lt;/li&gt;
&lt;li&gt;Or the application is getting re-factored based on different namespaces or functions.&lt;/li&gt;
&lt;li&gt;There can be N number of reasons and doing all these changes again is a tricky and tiresome task.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;One way to look at it is, use of &lt;code&gt;helm&lt;/code&gt; charts which can help us to manage all the Kubernetes objects and this kind of a change can be pretty straight forward provided the helm charts are structured correctly and using values file we can just update the name of the secret and then can upgrade the chart, and we are done.&lt;/p&gt;

&lt;p&gt;But if in case we are not using and package manager like &lt;code&gt;helm&lt;/code&gt; and we are just working with vanilla &lt;code&gt;YAML&lt;/code&gt; files then for that as well there is a neat way to do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The NEAT way!
&lt;/h2&gt;

&lt;p&gt;We can attach the &lt;code&gt;imagePullSecrets&lt;/code&gt; with the &lt;code&gt;serviceaccounts&lt;/code&gt; and where-ever the &lt;code&gt;serviceaccount&lt;/code&gt; is used, it will automatically populate the &lt;code&gt;imagePullSecrets&lt;/code&gt; in the respective object like Pods.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Below is the current status of my Kubernetes objects, no secrets, a default serviceaccount and no imagePullSecrets updated in the pod.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ k get secrets
No resources found in default namespace.
$ k get sa
NAME      SECRETS   AGE
default   0         33m
$ k get pods
NAME                     READY   STATUS             RESTARTS   AGE
nginx-65fd88fc88-8xjc9   0/1     ImagePullBackOff   0          32m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create the &lt;code&gt;docker-registry&lt;/code&gt; secret
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ k create secret docker-registry dockersec --docker-server=DOCKER_REGISTRY --docker-username=USERNAME --docker-password=PASSWORD
secret/dockersec created
$ k get secret
NAME        TYPE                             DATA   AGE
dockersec   kubernetes.io/dockerconfigjson   1      3s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Patch the default &lt;code&gt;serviceaccount&lt;/code&gt; to have the &lt;code&gt;imagePullSecrets&lt;/code&gt;. It can be any serviceaccount based on your requirements.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "dockersec"}]}'
serviceaccount/default patched
$ k get sa
NAME      SECRETS   AGE
default   0         35m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Or you can manually edit the &lt;code&gt;serviceaccount&lt;/code&gt; as well and add below content.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ k get sa default -o yaml
apiVersion: v1
imagePullSecrets:   # ADD
- name: dockersec   # ADD
kind: ServiceAccount
metadata:
  name: default
  namespace: default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;To see this in action now, delete the pod which is in failed state.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ k delete pod nginx-65fd88fc88-8xjc9 --force
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Check the events of the pod, now it was successfully able to pull the image from the private registry.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Events:
  Type     Reason     Age                From               Message
  ----     ------     ----               ----               -------
  Normal   Scheduled  65s                default-scheduler  Successfully assigned default/nginx-65fd88fc88-w8mph to minikube
  Normal   Pulling    64s                kubelet            Pulling image "sunnybhambhani/test:v1"
  Normal   Pulled     37s                kubelet            Successfully pulled image "sunnybhambhani/test:v1" in 30.288s (30.288s including waiting). Image size: 567185619 bytes.
  Normal   Created    21s (x3 over 36s)  kubelet            Created container: test
  Normal   Started    21s (x3 over 36s)  kubelet            Started container test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Interesting bit is &lt;code&gt;imagePullSecrets&lt;/code&gt; are automatically added to the object.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ k get pods nginx-65fd88fc88-w8mph -o yaml | grep -i serviceaccountname
serviceAccountName: default
$ k get pods nginx-65fd88fc88-w8mph -o yaml | grep -i imagepullse -A 1
  imagePullSecrets:
  - name: dockersec
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Bonus Tip
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;In case the pod is not in running status, it can be due to multiple reasons.&lt;/li&gt;
&lt;li&gt;Just describe the pod to see what is happening in the background.&lt;/li&gt;
&lt;li&gt; &lt;code&gt;kubectl describe pod POD_NAME | awk '/^Events:/ {found=1; next} found'&lt;/code&gt;, it looks for the line starting with Events, once found prints the remaining lines.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ kubectl describe pod nginx-65fd88fc88-8xjc9 | awk '/^Events:/ {found=1; next} found'
  Type     Reason     Age                     From               Message
  ----     ------     ----                    ----               -------
  Normal   Scheduled  7m21s                   default-scheduler  Successfully assigned default/nginx-65fd88fc88-8xjc9 to minikube
  Normal   Pulling    4m17s (x5 over 7m20s)   kubelet            Pulling image "REGISTRY/test:v1"
  Warning  Failed     4m14s (x5 over 7m17s)   kubelet            Failed to pull image "REGISTRY/test:v1": Error response from daemon: pull access denied for REGISTRY/test, repository does not exist or may require 'docker login': denied: requested access to the resource is denied
  Warning  Failed     4m14s (x5 over 7m17s)   kubelet            Error: ErrImagePull
  Warning  Failed     2m41s (x19 over 7m16s)  kubelet            Error: ImagePullBackOff
  Normal   BackOff    2m20s (x21 over 7m16s)  kubelet            Back-off pulling image "REGISTRY/test:v1"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Here the logs clearly state, &lt;strong&gt;requested access to the resource is denied&lt;/strong&gt; and in-turn the status of the pod is &lt;code&gt;ImagePullBackOff&lt;/code&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ k get pods
NAME                     READY   STATUS             RESTARTS   AGE
nginx-65fd88fc88-8xjc9   0/1     ImagePullBackOff   0          76s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;References:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Google.&lt;/li&gt;
&lt;li&gt;Kubernetes docs (&lt;a href="https://kubernetes.io/docs/home/" rel="noopener noreferrer"&gt;https://kubernetes.io/docs/home/&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;kubectl explain.&lt;/li&gt;
&lt;li&gt;Linux man pages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;PS: This works with any flavor of Kubernetes: minikube, Elastic Kubernetes Service(EKS), Azure Kubernetes Service(AKS), Google Kubernetes Engine(GKE), etc.&lt;/p&gt;

&lt;p&gt;I hope this will be helpful, feel free to add your thoughts and experiences, Happy Learning! 😄&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>linux</category>
      <category>security</category>
    </item>
    <item>
      <title>Kubernetes hardening made easy: Running CIS Benchmarks with kube-bench</title>
      <dc:creator>Sunny Bhambhani</dc:creator>
      <pubDate>Mon, 03 Mar 2025 04:41:17 +0000</pubDate>
      <link>https://dev.to/aws-builders/kubernetes-hardening-made-easy-running-cis-benchmarks-with-kube-bench-38ne</link>
      <guid>https://dev.to/aws-builders/kubernetes-hardening-made-easy-running-cis-benchmarks-with-kube-bench-38ne</guid>
      <description>&lt;p&gt;In today's world, where security risks and breaches are growing daily, it is crucial to maintain our applications and infrastructure's compliance with security standards and that is where CIS benchmarks from CIS (Center for Internet Security) comes in. And with kube-bench, running these checks becomes straightforward, helping you strengthen your Kubernetes clusters with confidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  CIS Benchmarks
&lt;/h2&gt;

&lt;p&gt;Here is the mission statement from CIS's website.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Our mission is to make the connected world a safer place by developing, validating, and promoting timely best practice solutions that help people, businesses, and governments protect themselves against pervasive cyber threats.&lt;/p&gt;

&lt;p&gt;Ref. &lt;a href="https://www.cisecurity.org/" rel="noopener noreferrer"&gt;https://www.cisecurity.org/&lt;/a&gt; for more details.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It basically helps us to jot down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What all best practices/guidelines to use?&lt;/li&gt;
&lt;li&gt;Which tools are available to assist us in scanning our application or infrastructure?&lt;/li&gt;
&lt;li&gt;Making sure the best practices are updated on timely manner.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The benchmarks are basically available for multiple platforms including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All the public cloud providers.&lt;/li&gt;
&lt;li&gt;Softwares&lt;/li&gt;
&lt;li&gt;DevSecOps tools&lt;/li&gt;
&lt;li&gt;Mobile devices&lt;/li&gt;
&lt;li&gt;Operating Systems&lt;/li&gt;
&lt;li&gt;and much more.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find their extensive list here: &lt;a href="https://learn.cisecurity.org/benchmarks" rel="noopener noreferrer"&gt;https://learn.cisecurity.org/benchmarks&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  CIS Benchmarks: Download PDF for your platform
&lt;/h2&gt;

&lt;p&gt;For downloading the PDF files you just need to provide some general details about yourself.&lt;/p&gt;

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

&lt;p&gt;Once done, press "Submit" and you will receive an email with the link from where you can download all kinds of benchmarks.&lt;/p&gt;

&lt;p&gt;It looks something like this: &lt;/p&gt;

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

&lt;p&gt;Upon pressing "Access PDFs" you will be routed to their extensive list of benchmarks which looks something like this:&lt;/p&gt;

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

&lt;p&gt;You can choose whatever you want to, but since we are interested in Kubernetes as of now, we will scroll down to the Kubernetes section.&lt;/p&gt;

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

&lt;p&gt;And the good part here is, this is not limited to vanilla Kubernetes, we can even download benchmarks for all the Kubernetes flavours like EKS from AWS, AKS from Azure, GKE from Google, etc.&lt;/p&gt;

&lt;p&gt;Once you download a specific PDF, you will see it contains a great amount of details including recommendations, problem statement, impact, remediation, etc.&lt;/p&gt;

&lt;p&gt;Now, if you have observed the PDF contains thousands of recommendations and going thru them and applying them one by one is a time-consuming task and just imagine you have 100s of clusters. Though I would recommend you to at-least go thru it once and get an idea of what all details it contains and how we can make use of it.&lt;/p&gt;

&lt;p&gt;To make our lives easier there are couple of tools which can help us to automate this process and help us to identify where we are lacking. So that we can fix them quickly.&lt;/p&gt;

&lt;h2&gt;
  
  
  CIS Benchmarks: Tools
&lt;/h2&gt;

&lt;p&gt;There are couple of tools which are managed by CIS itself like CIS-CAT Lite/CIS-CAT Pro/etc. CIS-CAT Lite is a free version and it supports a limited options excluding Kubernetes. CIS-CAT Pro is the one which supports Kubernetes but it is just available for CIS SecureSuite Members.&lt;/p&gt;

&lt;p&gt;Ref. &lt;a href="https://www.cisecurity.org/cybersecurity-tools" rel="noopener noreferrer"&gt;https://www.cisecurity.org/cybersecurity-tools&lt;/a&gt; for more details about the tools.&lt;/p&gt;

&lt;p&gt;Now, let's talk about the good part, the community has given us couple of opensource tools which does the same 😉 the most used one is kube-bench (from Aqua Security).&lt;/p&gt;

&lt;h2&gt;
  
  
  HOWTO: kube-bench
&lt;/h2&gt;

&lt;p&gt;kube-bench is a tool that checks whether Kubernetes is deployed securely by running the checks documented in the CIS Kubernetes Benchmark.&lt;/p&gt;

&lt;h2&gt;
  
  
  There are multiple ways to run kube-bench
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Install it via a package manager&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download the latest package based on your OS from github releases page and install it.&lt;/li&gt;
&lt;li&gt;Ref: &lt;a href="https://github.com/aquasecurity/kube-bench/releases" rel="noopener noreferrer"&gt;https://github.com/aquasecurity/kube-bench/releases&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Since, I am using Ubuntu, I will use dpkg to get this package installed.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ wget https://github.com/aquasecurity/kube-bench/releases/download/v0.10.2/kube-bench_0.10.2_linux_amd64.deb
$ sudo dpkg -i kube-bench_0.10.2_linux_amd64.deb
Selecting previously unselected package kube-bench.
(Reading database ... 41333 files and directories currently installed.)
Preparing to unpack kube-bench_0.10.2_linux_amd64.deb ...
Unpacking kube-bench (0.10.2) ...
Setting up kube-bench (0.10.2) ...
$ kube-bench version
0.10.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Run as a job in the Kubernetes Cluster&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get the job.yaml from the same github link and deploy it on your cluster.&lt;/li&gt;
&lt;li&gt;Ref: &lt;a href="https://github.com/aquasecurity/kube-bench/blob/main/job.yaml" rel="noopener noreferrer"&gt;https://github.com/aquasecurity/kube-bench/blob/main/job.yaml&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Based on your platforms there are multiple job*.yaml files available like for EKS, AKS, GKE, etc.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ kubectl apply -f https://raw.githubusercontent.com/aquasecurity/kube-bench/main/job.yaml
job.batch/kube-bench created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ k get pods
NAME               READY   STATUS      RESTARTS   AGE
kube-bench-n22k9   0/1     Completed   0          96s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ k logs kube-bench-n22k9 | head -n 20
[INFO] 1 Control Plane Security Configuration
[INFO] 1.1 Control Plane Node Configuration Files
[PASS] 1.1.1 Ensure that the API server pod specification file permissions are set to 600 or more restrictive (Automated)
[PASS] 1.1.2 Ensure that the API server pod specification file ownership is set to root:root (Automated)
[PASS] 1.1.3 Ensure that the controller manager pod specification file permissions are set to 600 or more restrictive (Automated)
[PASS] 1.1.4 Ensure that the controller manager pod specification file ownership is set to root:root (Automated)
[PASS] 1.1.5 Ensure that the scheduler pod specification file permissions are set to 600 or more restrictive (Automated)
[PASS] 1.1.6 Ensure that the scheduler pod specification file ownership is set to root:root (Automated)

OUTPUT TRIMMED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ k logs kube-bench-n22k9 | tail -n 20
OUTPUT TRIMMED

5.7.3 Follow the Kubernetes documentation and apply SecurityContexts to your Pods. For a
suggested list of SecurityContexts, you may refer to the CIS Security Benchmark for Docker
Containers.

5.7.4 Ensure that namespaces are created to allow for appropriate segregation of Kubernetes
resources and that all new resources are created in a specific namespace.


== Summary policies ==
0 checks PASS
6 checks FAIL
29 checks WARN
0 checks INFO

== Summary total ==
57 checks PASS
19 checks FAIL
54 checks WARN
0 checks INFO
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Just check the logs of the pod for all the recommendations. These logs contain multiple sections for different-different Kubernetes components like Controlplane, ETCD, Worker nodes, etc.&lt;/li&gt;
&lt;li&gt;At the end of each section you can see statistics about the checks and at the end of the logs you will see a quick summary about the total (as mentioned above).
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;== Summary node ==
14 checks PASS
2 checks FAIL
8 checks WARN
0 checks INFO
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Run as a docker container&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run --rm --net host --pid host --user 0 \
  -v /etc:/etc:ro \
  -v /var:/var:ro \
  -v /usr/bin:/usr/bin:ro \
  -v /usr/lib:/usr/lib:ro \
  aquasec/kube-bench:latest --benchmark cis-1.24
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;You can change the version based on your requirement, 1.24 is the latest one.&lt;/li&gt;
&lt;li&gt;More details about the versions can be found here: &lt;a href="https://github.com/aquasecurity/kube-bench/tree/main/cfg" rel="noopener noreferrer"&gt;https://github.com/aquasecurity/kube-bench/tree/main/cfg&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;For this as well, just check the logs of the container you will find the same results as we described in earlier section.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is how the remediation steps look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;== Remediations master ==
1.1.9 Run the below command (based on the file location on your system) on the control plane node.
For example, chmod 600 &amp;lt;path/to/cni/files&amp;gt;

1.1.11 On the etcd server node, get the etcd data directory, passed as an argument --data-dir,
from the command 'ps -ef | grep etcd'.
Run the below command (based on the etcd data directory found above). For example,
chmod 700 /var/lib/etcd

1.1.12 On the etcd server node, get the etcd data directory, passed as an argument --data-dir,
from the command 'ps -ef | grep etcd'.
Run the below command (based on the etcd data directory found above).
For example, chown etcd:etcd /var/lib/etcd

1.1.19 Run the below command (based on the file location on your system) on the control plane node.
For example,
chown -R root:root /etc/kubernetes/pki/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;References:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.cisecurity.org/" rel="noopener noreferrer"&gt;https://www.cisecurity.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/aquasecurity/kube-bench" rel="noopener noreferrer"&gt;https://github.com/aquasecurity/kube-bench&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feel free to add your thoughts and experiences, Happy Learning! 😄 &lt;/p&gt;

</description>
      <category>security</category>
      <category>kubernetes</category>
      <category>docker</category>
      <category>devops</category>
    </item>
    <item>
      <title>k9s - manage your Kubernetes cluster and it’s objects like a pro!</title>
      <dc:creator>Sunny Bhambhani</dc:creator>
      <pubDate>Sat, 30 Nov 2024 06:56:46 +0000</pubDate>
      <link>https://dev.to/aws-builders/k9s-manage-your-kubernetes-cluster-like-a-pro-lko</link>
      <guid>https://dev.to/aws-builders/k9s-manage-your-kubernetes-cluster-like-a-pro-lko</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;br&gt;
k9s is a terminal based GUI to manage any Kubernetes(k8s) cluster. Using this single utility, we can manage, traverse, watch all our Kubernetes objects.&lt;/p&gt;

&lt;p&gt;More information around k9s can be found here: &lt;a href="https://k9scli.io/" rel="noopener noreferrer"&gt;https://k9scli.io/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will dive a bit into k9s and see how it can help us in our day-to-day life, how we can get started, etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Features&lt;/strong&gt;&lt;br&gt;
Before we go into the example on how it can help, what it can do for us, let's see some of its features, it has a ton of features, but we will focus on the ones which can help us in our day-to-day activities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shows a helicopter view of all the Kubernetes objects.&lt;/li&gt;
&lt;li&gt;Easily we can move from one namespace to another.&lt;/li&gt;
&lt;li&gt;Watch/observe the state of Kubernetes objects using &lt;code&gt;pulses&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Get the &lt;code&gt;tree&lt;/code&gt; kind of structure using &lt;code&gt;xrays&lt;/code&gt; to identify objects co-relation.&lt;/li&gt;
&lt;li&gt;Manage the objects directly from the CLI, operations like deleting, editing, restarting is just one button away.&lt;/li&gt;
&lt;li&gt;Interestingly using a single button, you can get shell access to the pods.&lt;/li&gt;
&lt;li&gt;Check the logs from any of the pod without actually remembering the name of the pod, just select the pod and the logs are just one button away.&lt;/li&gt;
&lt;li&gt;Sanitize/clean up all the pods which are in completed/error state. &lt;/li&gt;
&lt;li&gt;Works with any flavor of Kubernetes &lt;code&gt;minikube&lt;/code&gt;, &lt;code&gt;Elastic Kubernetes Service(EKS)&lt;/code&gt;, &lt;code&gt;Azure Kubernetes Service(AKS)&lt;/code&gt;, &lt;code&gt;Google Kubernetes Engine(GKE)&lt;/code&gt;, etc.&lt;/li&gt;
&lt;li&gt;.... and a lot more.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Installation&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Its installation is straight forward and is available for almost all the platforms.&lt;/li&gt;
&lt;li&gt;Refer &lt;a href="https://k9scli.io/topics/install/" rel="noopener noreferrer"&gt;https://k9scli.io/topics/install/&lt;/a&gt; for more details.&lt;/li&gt;
&lt;li&gt;We will be doing this on Ubuntu.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Download the latest version of k9s binary, you can use the same URL/version if required or get the latest version released and update below URL accordingly. &lt;/p&gt;

&lt;p&gt;For latest version, refer: &lt;a href="https://github.com/derailed/k9s/releases" rel="noopener noreferrer"&gt;https://github.com/derailed/k9s/releases&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ wget https://github.com/derailed/k9s/releases/download/v0.32.7/k9s_linux_amd64.deb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install it using apt package manager.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sudo apt install ./k9s_linux_amd64.deb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once done it will get the k9s binary installed here: &lt;code&gt;/usr/bin/k9s&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HOWTO&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Launch k9s&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ k9s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once k9s is launched you will be presented with the beautiful layout with lots of options.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Press 0 to view all the pods from all the namespaces.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Navigate between Kubernetes objects&lt;/strong&gt;&lt;br&gt;
Navigating is pretty easy; it is more or less like &lt;code&gt;vi&lt;/code&gt; or &lt;code&gt;vim&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For example, if you want to view deployments then press &lt;code&gt;:&lt;/code&gt; it will bring the cursor to a text area where you can write the object which you are interested in, for instance in current example deployments.&lt;/li&gt;
&lt;li&gt;The short forms too are accepted i.e. deploy in case of deployment, svc in case of service, etc.&lt;/li&gt;
&lt;li&gt;This also supports crds :)&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;&lt;strong&gt;Pods management&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Press &lt;code&gt;:&lt;/code&gt; and type in pods, it will show you all the pods in selected namespace, if you want to see the &lt;strong&gt;pods from all namespaces press &lt;code&gt;0&lt;/code&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;There are times where we have to &lt;strong&gt;delete the pods on the fly&lt;/strong&gt;. Just select the pod and press &lt;code&gt;ctrl+d&lt;/code&gt; and you are done.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;There are times when you have to &lt;strong&gt;login to a pod&lt;/strong&gt;. Just select the pod and press &lt;code&gt;s&lt;/code&gt; and you are done. If you want to exit, press &lt;code&gt;ctrl+d&lt;/code&gt; or type in &lt;code&gt;exit&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Want to &lt;strong&gt;describe the pod details&lt;/strong&gt;, press &lt;code&gt;d&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Want to get the yaml output of the Kubernetes objects, just select the object and press &lt;code&gt;y&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Want to see the logs of a specific pod, select the pod and press &lt;code&gt;l&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;You can even do port-forward from the same UI, isn't it cool :), Just press &lt;code&gt;shift+f&lt;/code&gt; and if you want to see any existing port-forward are present or not, press &lt;code&gt;f&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

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

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

&lt;ul&gt;
&lt;li&gt;Sanitize/Clean up pods: For instance in below screen dump we can see there are 2 pods which are in &lt;code&gt;Completed&lt;/code&gt; and we want to clean them up.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Just press &lt;code&gt;z&lt;/code&gt;, you will be asked "if you are sure", type in "Yes Please!" and the job is done.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;XRAY&lt;/strong&gt;&lt;br&gt;
Xray gives you a great detail in terms of co-relation between k8s objects, it basically provides a &lt;code&gt;tree&lt;/code&gt; like structure.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Pulses&lt;/strong&gt;&lt;br&gt;
Pulses give a great dashboard to see what exactly is happening in your cluster, what all objects are there, health of your objects, etc?&lt;/p&gt;

&lt;p&gt;NOTE: Make sure metrics-server is installed and running in the cluster otherwise you won't see proper results. In my case it was not installed, therefore it was just stating blank results.&lt;/p&gt;

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

&lt;p&gt;After installing metrics-server and launching &lt;code&gt;pulses&lt;/code&gt; it shows an awesome dashboard.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;The great part about it is, it shows the current status of your cluster.&lt;/li&gt;
&lt;li&gt;It even shows what all objects are healthy and what all objects are unhealthy.&lt;/li&gt;
&lt;li&gt;Legend: GREEN/HEALTHY &amp;amp; YELLOW/UNHEALTHY&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;References: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://k9scli.io/" rel="noopener noreferrer"&gt;https://k9scli.io/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/derailed/k9s" rel="noopener noreferrer"&gt;https://github.com/derailed/k9s&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feel free add your thoughts, Happy learning :)&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>linux</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Helmister: Updated the logic to allow custom path</title>
      <dc:creator>Sunny Bhambhani</dc:creator>
      <pubDate>Thu, 28 Nov 2024 07:53:31 +0000</pubDate>
      <link>https://dev.to/aws-builders/helmister-updated-the-logic-to-allow-custom-path-lfn</link>
      <guid>https://dev.to/aws-builders/helmister-updated-the-logic-to-allow-custom-path-lfn</guid>
      <description>&lt;p&gt;Its a follow-up post on &lt;code&gt;helmister&lt;/code&gt;, refer here for more details: &lt;a href="https://dev.to/aws-builders/installing-multiple-helm-charts-in-one-go-approach-3-using-simple-bash-utility-2795"&gt;https://dev.to/aws-builders/installing-multiple-helm-charts-in-one-go-approach-3-using-simple-bash-utility-2795&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Updated the logic allowing users to specify a custom path for config.yaml. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Log entry: [2024-11-27 12:30:06] [INFO] Generic/common values based on /home/sunny/config.yaml file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;-f | --file&lt;br&gt;
Helps you to mention explicit/specific config.yaml. If not provided it will consider the default one which is placed in the base folder.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Example: ./helmister install -f /opt/app/config-dev.yaml&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/aws-builders" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F2794%2F88da75b6-aadd-4ea1-8083-ae2dfca8be94.png" alt="AWS Community Builders " width="350" height="350"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1005168%2Fe3697725-f1bf-4345-883a-30d23e3446f2.jpeg" alt="" width="468" height="476"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/aws-builders/installing-multiple-helm-charts-in-one-go-approach-3-using-simple-bash-utility-2795" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Installing multiple helm charts in one go [Approach 3 - using simple bash utility]&lt;/h2&gt;
      &lt;h3&gt;Sunny Bhambhani for AWS Community Builders  ・ Jul 23 '24&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#helm&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#kubernetes&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#devops&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#eks&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>helm</category>
      <category>linux</category>
      <category>devops</category>
      <category>automation</category>
    </item>
    <item>
      <title>sftp refresher - 101</title>
      <dc:creator>Sunny Bhambhani</dc:creator>
      <pubDate>Tue, 29 Oct 2024 11:34:22 +0000</pubDate>
      <link>https://dev.to/aws-builders/sftp-refresher-101-4ni9</link>
      <guid>https://dev.to/aws-builders/sftp-refresher-101-4ni9</guid>
      <description>&lt;p&gt;This is just a very basic refresher around sftp server, I know there are lots of other and on-cloud solutions available for file transfer and sftp server is &lt;strong&gt;&lt;em&gt;rarely&lt;/em&gt;&lt;/strong&gt; used.&lt;/p&gt;

&lt;p&gt;But since I got a query yesterday about it, I thought to create a small write-up :)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;sftp server&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There was a time when sftp was widely used for secure file transfers, though now there are many options available, but this used to be a hero service then and was commonly asked during interviews.&lt;/li&gt;
&lt;li&gt;The name itself expands to 'Secure File Transfer Protocol'.&lt;/li&gt;
&lt;li&gt;This allows for a secure file transfer over SSH (On port 22).&lt;/li&gt;
&lt;li&gt;It is quite fast and efficient.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pre-requisites&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Any linux machine with internet access (here I am using Ubuntu).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;HOWTO&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Update the package lists on your Ubuntu(debian based) machine.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ apt update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Install ssh/openssh-sftp-server/vim(if not present).
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ apt install ssh openssh-sftp-server vim -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Edit the sshd config file and append below details
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ vim /etc/ssh/sshd_config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Match group sftp
ChrootDirectory /home
X11Forwarding no
AllowTcpForwarding no
ForceCommand internal-sftp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Match group sftp&lt;/strong&gt;&lt;/em&gt;: This statement states below settings will be applicable to all the users who belong to sftp group.&lt;br&gt;
&lt;strong&gt;&lt;em&gt;ChrootDirectory&lt;/em&gt;&lt;/strong&gt;: This basically changes the root directory to mentioned path.&lt;br&gt;
&lt;strong&gt;&lt;em&gt;X11Forwarding&lt;/em&gt;&lt;/strong&gt;: This disables X11 forwarding (this is enabled in some GUI use-cases) and for sftp this is not required. &lt;br&gt;
&lt;strong&gt;&lt;em&gt;AllowTcpForwarding&lt;/em&gt;&lt;/strong&gt;: Disables TCP forwarding.&lt;br&gt;
&lt;strong&gt;&lt;em&gt;ForceCommand&lt;/em&gt;&lt;/strong&gt;: This forcefully mandates that the used of this group should be only allowed to use sftp and nothing else.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Restart the service, you can use this way or use systemctl based on your distribution.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ /etc/init.d/ssh restart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Add a new group called sftp to the system.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ addgroup sftp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create a new user with sftp group attached to it.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ useradd -m sunny -g sftp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Change the password of the newly created user.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ passwd sunny
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Change the permission of the directory to USER/OWNER only.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ chmod 700 /home/sunny/ -R
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Try connecting to sftp server
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sftp sunny@HOST_IP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Enter the password and try using get and put commands.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;*&lt;em&gt;Feel free to add any details which I might have missed, happy learning :) *&lt;/em&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>beginners</category>
      <category>bash</category>
    </item>
    <item>
      <title>Quick guide to install minikube, kubectl, helm and enable ingress controller on Ubuntu</title>
      <dc:creator>Sunny Bhambhani</dc:creator>
      <pubDate>Mon, 21 Oct 2024 12:39:29 +0000</pubDate>
      <link>https://dev.to/aws-builders/quick-guide-to-install-minikube-and-enable-ingress-controller-on-ubuntu-3g1p</link>
      <guid>https://dev.to/aws-builders/quick-guide-to-install-minikube-and-enable-ingress-controller-on-ubuntu-3g1p</guid>
      <description>&lt;p&gt;This is just a quick guide to install minikube and enable ingress controller on Ubuntu.&lt;/p&gt;

&lt;p&gt;The purpose of this post is to consolidate all the commands in one place for quick reference.&lt;/p&gt;

&lt;p&gt;Minikube is a lightweight Kubernetes cluster that enables you to run Kubernetes clusters locally. It's ideal for learning Kubernetes while developing and testing on a single machine.&lt;/p&gt;

&lt;p&gt;More information about minikube can be found here: &lt;a href="https://minikube.sigs.k8s.io/docs/" rel="noopener noreferrer"&gt;https://minikube.sigs.k8s.io/docs/&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install minikube (Ref: &lt;a href="https://minikube.sigs.k8s.io/docs/start" rel="noopener noreferrer"&gt;https://minikube.sigs.k8s.io/docs/start&lt;/a&gt;)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube &amp;amp;&amp;amp; rm minikube-linux-amd64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Install docker (Ref: &lt;a href="https://docs.docker.com/engine/install/ubuntu/" rel="noopener noreferrer"&gt;https://docs.docker.com/engine/install/ubuntu/&lt;/a&gt;)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release &amp;amp;&amp;amp; echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list &amp;gt; /dev/null
sudo apt-get update

sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Add current user to docker group
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo usermod -aG docker $USER &amp;amp;&amp;amp; newgrp docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Install kubectl (Ref: &lt;a href="https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/" rel="noopener noreferrer"&gt;https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/&lt;/a&gt;)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl
sudo chmod +x kubectl
sudo mv kubectl /usr/local/bin
alias k=kubectl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Install helm (Ref: &lt;a href="https://helm.sh/docs/intro/install/" rel="noopener noreferrer"&gt;https://helm.sh/docs/intro/install/&lt;/a&gt;)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Start minikube
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;minikube start
# Once started
k get nodes
# To get a list of underlying nodes
k get pods -A
# To get a list of all the pods from all namespaces
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Get minikube's IP and enable ingress controller
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;minikube ip
minikube addons enable ingress
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>kubernetes</category>
      <category>linux</category>
      <category>beginners</category>
      <category>bash</category>
    </item>
    <item>
      <title>Installing multiple helm charts in one go [Approach 3 - using simple bash utility]</title>
      <dc:creator>Sunny Bhambhani</dc:creator>
      <pubDate>Tue, 23 Jul 2024 10:34:55 +0000</pubDate>
      <link>https://dev.to/aws-builders/installing-multiple-helm-charts-in-one-go-approach-3-using-simple-bash-utility-2795</link>
      <guid>https://dev.to/aws-builders/installing-multiple-helm-charts-in-one-go-approach-3-using-simple-bash-utility-2795</guid>
      <description>&lt;p&gt;In this article, we will be talking about Approach 3 i.e. how to get multiple helm charts installed using a simple bash utility.&lt;/p&gt;

&lt;p&gt;If you haven't read the previous article where I discussed other approaches, feel free to read it over.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ref: &lt;a href="https://dev.to/aws-builders/installing-multiple-helm-charts-in-one-go-approach-1-5d1p"&gt;Installing multiple helm charts in one go [Approach 1 - using parent/child charts]&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Ref: &lt;a href="https://dev.to/aws-builders/installing-multiple-helm-charts-in-one-go-approach-2-using-helmfile-4e4h"&gt;Installing multiple helm charts in one go [Approach 2 - using helmfile]&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Motive&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Why I thought of a simple bash utility?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In some of the air-gapped environments it is sometimes a bit difficult to use the tools/utilities available because moving things inside an air-gapped environment is a challenge.&lt;/li&gt;
&lt;li&gt;Some of the environments are so secure that one may need to follow a whole process of getting all the security clearances and approval before using a tool/utility, which altogether is a nightmare.&lt;/li&gt;
&lt;li&gt;I chose bash, the reason being it is pretty common among engineers and it is easily understandable.&lt;/li&gt;
&lt;li&gt;The source code can be found here: &lt;a href="https://github.com/sunnybhambhani/helmister" rel="noopener noreferrer"&gt;https://github.com/sunnybhambhani/helmister&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;You can copy it, and tweak it based on your requirements.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;PS: I chose a name for this utility as well &lt;code&gt;helmister&lt;/code&gt; or &lt;code&gt;helm-minister&lt;/code&gt;  but you can call it whatever you want 🙂&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A running Kubernetes cluster with proper permissions, it can be any  flavor of Kubernetes &lt;code&gt;minikube&lt;/code&gt;, &lt;code&gt;Elastic Kubernetes Service(EKS)&lt;/code&gt;, &lt;code&gt;Azure Kubernetes Service(AKS)&lt;/code&gt;, &lt;code&gt;Google Kubernetes Engine(GKE)&lt;/code&gt;, etc.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kubectl&lt;/code&gt; and &lt;code&gt;helm&lt;/code&gt; installed on your machine to interact with the Kubernetes cluster.

&lt;ul&gt;
&lt;li&gt;Ref: &lt;a href="https://kubernetes.io/docs/tasks/tools/" rel="noopener noreferrer"&gt;https://kubernetes.io/docs/tasks/tools/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Ref: &lt;a href="https://helm.sh/docs/intro/install/" rel="noopener noreferrer"&gt;https://helm.sh/docs/intro/install/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;A clone of helmister repository.&lt;/li&gt;

&lt;li&gt;yq(required) and cowsay(optional) packages installed on your machine.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Helmister&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is a small bash utility that can help to install and uninstall multiple helm charts in one go. The idea is inspired by &lt;code&gt;helmfile&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Its usage is quite simple, just run the utility followed by the option like install or uninstall i.e. &lt;code&gt;./helmister [install/uninstall]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Under the hood, it calls &lt;code&gt;helm&lt;/code&gt; binary. Therefore it is kind of a wrapper around &lt;code&gt;helm&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It consumes a &lt;code&gt;config.yaml&lt;/code&gt; file which contains all the necessary details about the releases, and common parameters.&lt;/li&gt;
&lt;li&gt;This supports both &lt;code&gt;oci://&lt;/code&gt; and &lt;code&gt;https://&lt;/code&gt; helm registries.&lt;/li&gt;
&lt;li&gt;PS: In the future, I am planning to add some more options/functionalities to this.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Directory structure&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
├── config.yaml
├── helmister
├── logs
│   ├── archive
│   │   └── helmister_20240227_170201.tar.gz
│   └── helmister.log
├── README.md
└── values
    ├── argo-cd.yaml
    └── nginx-values.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;helmister&lt;/em&gt;, this is the script written in bash you can just cat and see what all things it contains.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;config.yaml&lt;/em&gt;, this is the main configuration file or you can call the state file which contains the list of all releases you want to install in a cluster, plus it also contains some additional key:value pairs that are generic and common across all the releases. I first kept this configuration file in csv format, but later decided to convert it to yaml because it is more readable.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;logs&lt;/em&gt;, this is a directory that holds the logs of this utility, it contains the information about the execution of the last iteration, plus any archived/past logs (if required for reference).&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;README.md&lt;/em&gt;, contains bit of a documentation about this utility, and what options are present.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;values&lt;/em&gt;, this is the directory where all the values files are placed (it can be anywhere in your system but for simplicity, I have placed them in the same directory).&lt;/li&gt;
&lt;li&gt;Now let's talk about &lt;code&gt;config.yaml&lt;/code&gt; which is the main ingredient.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;config.yaml&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dry_run: false
create_namespace: true
wait: false
timeout: false # If true, defaults to 20 mins
charts:
  - release_name: nginx
    chart_name: nginx
    chart_repo: oci://registry-1.docker.io/bitnamicharts
    values_file: values/nginx-values.yaml
  - release_name: argocd
    chart_name: argo-cd
    chart_repo: https://argoproj.github.io/argo-helm
    values_file: values/argo-cd.yaml
    version: 6.4.0
    namespace: argo-cd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The initial key:value pairs are common across all the releases.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;charts&lt;/em&gt;, is an array that contains a list of what all releases need to be installed in a Kubernetes cluster.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;dry_run&lt;/em&gt;, it is a boolean [true or false], and if true, none of the Kubernetes resources will be created it will just do a dry_run.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;create_namespace&lt;/em&gt;, it is a boolean [true or false], and if true it will automatically create a namespace for the release specified in the charts array.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;wait&lt;/em&gt;, it is a boolean [true or false], and if true it acts similar to &lt;code&gt;helm --wait&lt;/code&gt; wherein the shell will be kept occupied until all the Kubernetes resources are created.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;timeout&lt;/em&gt;, it is a boolean [true or false], and if true it acts similar to &lt;code&gt;helm --timeout=20m&lt;/code&gt; i.e. if all the resources are not created within 20 mins the execution will fail. By default, I have kept the timeout as 20 minutes which is more than enough.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;charts&lt;/em&gt;, it is an array that contains details around individual releases. Except for version and namespace all the key:value pairs are mandatory.

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;release_name&lt;/em&gt;, this is the name of the release.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;chart_name&lt;/em&gt;, this is the name of the chart that needs to be installed.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;chart_repo&lt;/em&gt;, this is the helm registry where the chart is located. It can be any &lt;code&gt;oci://&lt;/code&gt; or &lt;code&gt;https://&lt;/code&gt; registry.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;values_file&lt;/em&gt;, which contains the path of the values file for individual releases.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;version&lt;/em&gt;, this is the version of the chart that needs to be installed. This is optional and if not provided, It will consider the &lt;code&gt;latest&lt;/code&gt; chart version.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;namespace&lt;/em&gt;, this is where the chart will be installed. This is optional as well and if not provided it will be installed in the &lt;code&gt;default&lt;/code&gt; namespace.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Let's see this in action&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I will use the same &lt;code&gt;config.yaml&lt;/code&gt; which will install one helm release from an &lt;code&gt;oci://&lt;/code&gt; registry in &lt;code&gt;default&lt;/code&gt; namespace (since I haven't specified any namespace for that release) and another one from &lt;code&gt;https://&lt;/code&gt; registry in &lt;code&gt;argo-cd&lt;/code&gt; namespace. Note the version as well for nginx, there as well I haven't specified any version, it will pick the latest available one automatically.&lt;/li&gt;
&lt;li&gt;This is my cluster's current status.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ k get ns
NAME              STATUS   AGE
default           Active   28s
kube-node-lease   Active   28s
kube-public       Active   29s
kube-system       Active   29s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ helm list -A
NAME    NAMESPACE       REVISION        UPDATED STATUS  CHART   APP VERSION
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ./helmister install
[2024-07-23 15:02:47] [INFO] Using file: config.yaml
 ____________________________
&amp;lt; Helmister, Install charts! &amp;gt;
 ----------------------------
   \
    \
        .--.
       |o_o |
       |:_/ |
      //   \ \
     (|     | )
    /'\_   _/`\
    \___)=(___/

[2024-07-23 15:02:47] [INFO] Generic/common values based on config.yaml file
[2024-07-23 15:02:48] [INFO] Dry Run: false
[2024-07-23 15:02:48] [INFO] Create Namespace: true
[2024-07-23 15:02:48] [INFO] Wait: false
[2024-07-23 15:02:48] [INFO] Timeout: false
[2024-07-23 15:02:48] [INFO] ****************************
[2024-07-23 15:02:48] [INFO] Chart specific values based on config.yaml file
[2024-07-23 15:02:48] [INFO] Release Name: nginx
[2024-07-23 15:02:48] [INFO] Chart Name: nginx
[2024-07-23 15:02:48] [INFO] Chart Repo: oci://registry-1.docker.io/bitnamicharts
[2024-07-23 15:02:48] [INFO] Values File: values/nginx-values.yaml
[2024-07-23 15:02:48] [INFO] Version: null
[2024-07-23 15:02:48] [INFO] Namespace: null
[2024-07-23 15:02:48] [INFO] ****************************
[2024-07-23 15:02:48] [INFO] Installing nginx with release name nginx from oci://registry-1.docker.io/bitnamicharts with version null using values file: values/nginx-values.yaml in default namespace
...
...
OUTPUT TRIMMED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Actual stdout output can be &lt;a href="https://github.com/sunnybhambhani/helmister/blob/main/artifacts/sample_logs/during_installation_on_stdout.log" rel="noopener noreferrer"&gt;found here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Here you will see that it provides all the minute details of what exactly it is doing.&lt;/li&gt;
&lt;li&gt;For example: Generic values

&lt;ul&gt;
&lt;li&gt;Here I have marked create_namespace as true because I don't already have argo-cd namespace wherein I want to install argocd release.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[2024-07-23 15:02:47] [INFO] Generic/common values based on config.yaml file
[2024-07-23 15:02:48] [INFO] Dry Run: false
[2024-07-23 15:02:48] [INFO] Create Namespace: true
[2024-07-23 15:02:48] [INFO] Wait: false
[2024-07-23 15:02:48] [INFO] Timeout: false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Next, you will see, chart/release specific values of all the items in charts array one by one:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[2024-07-23 15:03:31] [INFO] Chart specific values based on config.yaml file
[2024-07-23 15:03:31] [INFO] Release Name: argocd
[2024-07-23 15:03:31] [INFO] Chart Name: argo-cd
[2024-07-23 15:03:31] [INFO] Chart Repo: https://argoproj.github.io/argo-helm
[2024-07-23 15:03:31] [INFO] Values File: values/argo-cd.yaml
[2024-07-23 15:03:31] [INFO] Version: 6.4.0
[2024-07-23 15:03:31] [INFO] Namespace: argo-cd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Here I have explicitly added an additional check that will check if the pods are up and healthy (this is just specific to pods it won't consider any other k8s objects).&lt;/li&gt;
&lt;li&gt;It will continuously check for next 20mins and will check every 5 secs. If the pods are still in non-running state it will terminate the process.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[2024-07-23 15:03:47] [WARN] Pods for release argocd are not yet in Running state, checking again in 5 seconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Once all the pods are in running state and it has deployed all the releases it will show a successful message.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[2024-07-23 15:05:20] [INFO] All actions completed successfully
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Once this is done, if required you can see the logs as well from the logs directory. A sample can be &lt;a href="https://github.com/sunnybhambhani/helmister/blob/main/artifacts/sample_logs/actual_log_file.log" rel="noopener noreferrer"&gt;found here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;And here is my cluster's current status now:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ helm list -A
NAME    NAMESPACE       REVISION        UPDATED                                 STATUS          CHART           APP VERSION
argocd  argo-cd         1               2024-07-23 15:03:34.46715742 +0530 IST  deployed        argo-cd-6.4.0   v2.10.1
nginx   default         1               2024-07-23 15:02:53.590367521 +0530 IST deployed        nginx-18.1.5    1.27.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ k get ns
NAME              STATUS   AGE
argo-cd           Active   58m
default           Active   62m
kube-node-lease   Active   62m
kube-public       Active   62m
kube-system       Active   62m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ k get pods -n argo-cd
NAME                                                READY   STATUS    RESTARTS   AGE
argocd-application-controller-0                     1/1     Running   0          58m
argocd-applicationset-controller-68cd75bc89-d4q8x   1/1     Running   0          58m
argocd-dex-server-84b5bbdcbf-c4qv2                  1/1     Running   0          58m
argocd-notifications-controller-7bc55c495d-xz6gt    1/1     Running   0          58m
argocd-redis-5d5cdcfd54-2rx26                       1/1     Running   0          58m
argocd-repo-server-756ff4cd7d-rpvh7                 1/1     Running   0          58m
argocd-server-7587d49b7b-9h47l                      1/1     Running   0          58m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ k get pods -n default
NAME                     READY   STATUS    RESTARTS   AGE
nginx-569b6bc698-48qqt   1/1     Running   0          59m
nginx-569b6bc698-9qzpv   1/1     Running   0          59m
nginx-569b6bc698-wflrj   1/1     Running   0          59m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;If you want to uninstall it, simply do:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ./helmister uninstall
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;It will get everything cleaned for all the releases that are specified in &lt;code&gt;config.yaml&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The sample log can be &lt;a href="https://github.com/sunnybhambhani/helmister/blob/main/artifacts/sample_logs/during_uninstallation_on_stdout.log" rel="noopener noreferrer"&gt;found here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feel free to use it, and tweak it based on your requirements.&lt;/p&gt;

&lt;p&gt;I will soon add some more functionalities to it.&lt;/p&gt;

&lt;p&gt;Happy learning!&lt;/p&gt;

&lt;p&gt;References:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Google/Stackoverflow/Linux man pages/etc&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>helm</category>
      <category>kubernetes</category>
      <category>devops</category>
      <category>eks</category>
    </item>
    <item>
      <title>Update multiple Kubernetes objects/configmaps in one go!</title>
      <dc:creator>Sunny Bhambhani</dc:creator>
      <pubDate>Wed, 22 May 2024 12:54:25 +0000</pubDate>
      <link>https://dev.to/aws-builders/update-multiple-kubernetes-objectsconfigmaps-in-one-go-5417</link>
      <guid>https://dev.to/aws-builders/update-multiple-kubernetes-objectsconfigmaps-in-one-go-5417</guid>
      <description>&lt;p&gt;There may be cases wherein we just need to update a Kubernetes configmap or any other Kubernetes object based on our requirements.&lt;/p&gt;

&lt;p&gt;And let's say it's just one or two configmaps(here we will be talking about configmaps just for simplicity but its applicable for other Kubernetes objects as well) then that's fine, right? We can simply do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;kubectl edit -n NAMESPACE_NAME configmap CONFIGMAP_NAME&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Update it based on our requirements.&lt;/li&gt;
&lt;li&gt;Save it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But think about a scenario, wherein we need to update +100 configmaps with the same values how to do it?&lt;/p&gt;

&lt;p&gt;We cannot update or edit each and every object since that would be a bit tedious and will be error-prone as well. Plus there might be chances we might skip some of them.&lt;/p&gt;

&lt;p&gt;So, the best way to do it is by using &lt;code&gt;patch&lt;/code&gt; command in an automated way.&lt;/p&gt;

&lt;p&gt;Refer: &lt;a href="https://kubernetes.io/docs/reference/kubectl/generated/kubectl_patch/" rel="noopener noreferrer"&gt;https://kubernetes.io/docs/reference/kubectl/generated/kubectl_patch/&lt;/a&gt; for more details about it.&lt;/p&gt;

&lt;p&gt;Let's see this in action:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I have a very minimal configmap which contains some DATABASE details.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: v1
data:
  DATABASE_HOST: "api01.ybdb.io"
  DATABASE_NAME: "api01"
  DATABASE_PORT: "5433"
kind: ConfigMap
metadata:
  name: api01-configmap
  namespace: default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Now, let's assume there is an update instead of port number 5433. Our database now listens on port 5444.&lt;/li&gt;
&lt;li&gt;We can easily accomplish this using &lt;code&gt;kubectl edit&lt;/code&gt; but let's see &lt;code&gt;patch&lt;/code&gt; in action:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ kubectl patch configmap api01-configmap -n default -p '{"data":{"DATABASE_PORT":"5444"}}'
configmap/api01-configmap patched
$ kubectl get cm -n default -o yaml api01-configmap
apiVersion: v1
data:
  DATABASE_HOST: api01.ybdb.io
  DATABASE_NAME: api01
  DATABASE_PORT: "5444"
kind: ConfigMap
metadata:
  creationTimestamp: "2024-05-22T10:06:39Z"
  name: api01-configmap
  namespace: default
  resourceVersion: "67651"
  uid: 2d49a0ea-6910-420c-b2bf-00e42e6c08d7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The command is pretty straight forward &lt;code&gt;kubectl patch configmap api01-configmap -n default -p '{"data":{"DATABASE_PORT":"5444"}}'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;-n is to specify the namespace name where the configmap resides.&lt;/li&gt;
&lt;li&gt;-p is to specify what patch/update we want in the Kubernetes object.&lt;/li&gt;
&lt;li&gt;Here, under &lt;code&gt;data:&lt;/code&gt; we are updating a key called &lt;code&gt;DATABASE_PORT:&lt;/code&gt; to &lt;code&gt;5444&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Note: If in case &lt;code&gt;DATABASE_PORT:&lt;/code&gt; key doesn't exist, it will create that key for us.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Assume you want to see the output as well in the same command then add -o or --output flag with the type [json,name,yaml,etc].&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ kubectl patch configmap api01-configmap -n default -p '{"data":{"DATABASE_PORT":"5444"}}' -o yaml
apiVersion: v1
data:
  DATABASE_HOST: api01.ybdb.io
  DATABASE_NAME: api01
  DATABASE_PORT: "5444"
kind: ConfigMap
metadata:
  creationTimestamp: "2024-05-22T10:47:41Z"
  name: api01-configmap
  namespace: default
  resourceVersion: "69416"
  uid: a303bd0e-7f61-49c0-b671-06649ecdf999
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But there is another catch, you can also not run the patch command +100 times, I mean definitely you can but again that might be error-prone too.&lt;/p&gt;

&lt;p&gt;So, in that case we can write a simple reusable bash script that can do the job for us and can help us to update +100 configmaps in one go.&lt;/p&gt;

&lt;p&gt;It can be in any language but I have chosen &lt;code&gt;bash&lt;/code&gt;, since it's pretty common.&lt;/p&gt;

&lt;p&gt;Quick rundown of the script:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Here I have three variables, NAMESPACE (where the object resides), CONFIGMAP_FILE (input file which contains a list of all the configmaps that need to be updated), DATA (a set of key:value pair which needs to be replaced/added).&lt;/li&gt;
&lt;li&gt;Here I am creating log files as well (update_cm.log - contains generic readable information, patch.log - contains output of patch command).&lt;/li&gt;
&lt;li&gt;As of now, I just have added action as add but we can have other actions as well like replace or remove (based on our requirements).
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

NAMESPACE="default"
CONFIGMAP_FILE="configmaps"
DATA='{"data":{"DATABASE_PORT":"5444"}}'

rm patch.log update_cm.log

if [ ! -f "$CONFIGMAP_FILE" ]; then
  echo "File $CONFIGMAP_FILE not found."
  exit 1
fi

echo `date` &amp;gt;&amp;gt; update_cm.log
echo "----------------------------" &amp;gt;&amp;gt; update_cm.log

action=$1

if [ "$action" == "add" ]; then
  echo "Action: $action"
  echo "Action: $action" &amp;gt;&amp;gt; update_cm.log
  while IFS= read -r cm; do
    echo "Updating ConfigMap: $cm"
    echo "Updating ConfigMap: $cm" &amp;gt;&amp;gt; update_cm.log
    kubectl patch configmap "$cm" -n "$NAMESPACE" -p $DATA &amp;gt;&amp;gt; patch.log 2&amp;gt;&amp;amp;1
  done &amp;lt; "$CONFIGMAP_FILE"

else
  echo "Invalid action, please specify add".
  exit 1
fi

echo "----------------------------" &amp;gt;&amp;gt; update_cm.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Feel free to use it, tweak it, based on your requirements. This script is for configmaps but similar logic we can write for other objects as well if required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy learning :)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;References:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Google.&lt;/li&gt;
&lt;li&gt;Kubernetes docs (&lt;a href="https://kubernetes.io/docs/home/" rel="noopener noreferrer"&gt;https://kubernetes.io/docs/home/&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;kubectl explain&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We should not manually update/patch the Kubernetes objects, this should be done when absolutely necessary or needed on the fly.&lt;/li&gt;
&lt;li&gt;Ideally these all values should come from the version control system wherein the values files are maintained.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;PS: This works with any flavor of Kubernetes &lt;code&gt;minikube&lt;/code&gt;, &lt;code&gt;Elastic Kubernetes Service(EKS)&lt;/code&gt;, &lt;code&gt;Azure Kubernetes Service(AKS)&lt;/code&gt;, &lt;code&gt;Google Kubernetes Engine(GKE)&lt;/code&gt;, etc.&lt;/p&gt;

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