<?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: LearnSome.tech</title>
    <description>The latest articles on DEV Community by LearnSome.tech (learnsome-tech).</description>
    <link>https://dev.to/learnsome-tech</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%2Forganization%2Fprofile_image%2F15853%2Faef7b808-e50a-4612-a7a5-6c7c86807161.png</url>
      <title>DEV Community: LearnSome.tech</title>
      <link>https://dev.to/learnsome-tech</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/learnsome-tech"/>
    <language>en</language>
    <item>
      <title>What the new Security+ (SY0-801) exam actually is, and what it doesn't prove</title>
      <dc:creator>Ayodele</dc:creator>
      <pubDate>Thu, 05 Nov 2026 15:24:35 +0000</pubDate>
      <link>https://dev.to/learnsome-tech/what-the-new-security-sy0-801-exam-actually-is-and-what-it-doesnt-prove-3bce</link>
      <guid>https://dev.to/learnsome-tech/what-the-new-security-sy0-801-exam-actually-is-and-what-it-doesnt-prove-3bce</guid>
      <description>&lt;p&gt;&lt;em&gt;AI-assisted: written with an AI tool from CompTIA's own Security+ V8 page, then checked line by line against it. I run LearnSome.tech, which has a Security+ course; this post stands on its own.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;CompTIA's Security+ V8, exam code SY0-801, has a launch date of 17 November 2026 on CompTIA's exam page. If you are deciding whether to sit it, here is what it is, from that page rather than from forum lore.&lt;/p&gt;

&lt;h2&gt;
  
  
  The format
&lt;/h2&gt;

&lt;p&gt;As listed on CompTIA's V8 exam page:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Questions:&lt;/strong&gt; a maximum of 90, a mix of multiple-choice and performance-based questions (PBQs).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time:&lt;/strong&gt; 90 minutes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Passing score:&lt;/strong&gt; 750 on a scale of 100 to 900.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recommended experience:&lt;/strong&gt; a security administrator with two years of hands-on experience. That's a recommendation, not an entry requirement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lifetime:&lt;/strong&gt; CompTIA estimates the version will retire about 3 years after launch.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;PBQs are the part people underestimate. Instead of picking a letter, you classify, order or configure things in a small simulated environment. They take longer than a multiple-choice question, so plan your time around them rather than discovering them at minute 70.&lt;/p&gt;

&lt;h2&gt;
  
  
  The five domains
&lt;/h2&gt;

&lt;p&gt;The weights, from CompTIA's published V8 objectives summary:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Domain&lt;/th&gt;
&lt;th&gt;Weight&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Security Operations&lt;/td&gt;
&lt;td&gt;27%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Threats, Vulnerabilities, and Attacks&lt;/td&gt;
&lt;td&gt;24%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security Architecture&lt;/td&gt;
&lt;td&gt;19%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;General Security Concepts&lt;/td&gt;
&lt;td&gt;16%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security Program Management and Oversight&lt;/td&gt;
&lt;td&gt;14%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two things stand out in V8. Security Operations is the largest domain: monitoring, identity and access, incident response, investigations. And the threats domain now has an objective on the security risks of AI systems: models, prompts, privacy and data exposure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read the qualifier word
&lt;/h2&gt;

&lt;p&gt;Many Security+ questions offer several answers that are all good security. One word decides which one scores: &lt;strong&gt;BEST&lt;/strong&gt;, &lt;strong&gt;FIRST&lt;/strong&gt;, &lt;strong&gt;MOST&lt;/strong&gt;, &lt;strong&gt;LEAST&lt;/strong&gt; or &lt;strong&gt;NOT&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Try this one, in that style:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A user reports they approved an MFA prompt they did not start. What should you do &lt;strong&gt;FIRST&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;A. Revoke the user's sessions and reset the password&lt;br&gt;
B. Check the mail gateway for the phish&lt;br&gt;
C. Send an awareness reminder to all staff&lt;br&gt;
D. Disable MFA for the user&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Every option except one is something a team might do at some point. The question only asks about the first move. Read the qualifier, then the options, and you'll stop losing marks to answers that are right but not &lt;em&gt;first&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a pass does and doesn't show
&lt;/h2&gt;

&lt;p&gt;A pass shows you know core security practice across those five domains, and the PBQs show you can apply some of it in a simulation. It doesn't replace security work on real systems: nobody's first incident looks like an exam item.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before you book
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Download CompTIA's full V8 objectives and mark each one you couldn't explain to a colleague. That list is your study plan.&lt;/li&gt;
&lt;li&gt;Practise PBQ-style tasks (ordering, matching, filling in tables), not just question banks.&lt;/li&gt;
&lt;li&gt;Do a timed run of 90 questions in 90 minutes at least once. A minute a question goes fast.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Are you sitting V8, or did you take V7 before the switch?&lt;/p&gt;

</description>
      <category>security</category>
      <category>cybersecurity</category>
      <category>certification</category>
      <category>career</category>
    </item>
    <item>
      <title>Terraform Associate (004): what the exam is, and the one thing it can't check</title>
      <dc:creator>Ayodele</dc:creator>
      <pubDate>Thu, 05 Nov 2026 15:24:27 +0000</pubDate>
      <link>https://dev.to/learnsome-tech/terraform-associate-004-what-the-exam-is-and-the-one-thing-it-cant-check-2fop</link>
      <guid>https://dev.to/learnsome-tech/terraform-associate-004-what-the-exam-is-and-the-one-thing-it-cant-check-2fop</guid>
      <description>&lt;p&gt;&lt;em&gt;AI-assisted: I put this together from HashiCorp's Terraform Associate (004) page with help from an AI tool, and checked each fact against that page. I run LearnSome.tech, which teaches Terraform; you can prepare without us.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The Terraform Associate is HashiCorp's foundational Terraform certification. The current version is 004. Here is what the official page says, and what it leaves out.&lt;/p&gt;

&lt;h2&gt;
  
  
  The facts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Format:&lt;/strong&gt; multiple choice, online proctored.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Duration:&lt;/strong&gt; 1 hour.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terraform version tested:&lt;/strong&gt; 1.12.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Price:&lt;/strong&gt; USD 70.50 plus local taxes and fees. A free retake is not included.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Valid for:&lt;/strong&gt; 2 years.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prerequisites:&lt;/strong&gt; basic terminal skills and an understanding of on-premises and cloud architecture. HashiCorp says professional experience is recommended, but you can also prepare by practising the objectives in a personal demo setup.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What the page doesn't publish: the number of questions, the pass mark, or any weighting between the objective areas. So you can't game it by skipping a "small" domain. Every area can matter.&lt;/p&gt;

&lt;h2&gt;
  
  
  The eight objective areas
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Infrastructure as Code with Terraform&lt;/li&gt;
&lt;li&gt;Terraform fundamentals (providers, and how Terraform uses state)&lt;/li&gt;
&lt;li&gt;The core workflow: init, validate, plan, apply, destroy, fmt&lt;/li&gt;
&lt;li&gt;Terraform configuration: resources and data blocks, variables and outputs, complex types, expressions and functions, dependencies, custom conditions, sensitive data&lt;/li&gt;
&lt;li&gt;Modules: sources, variable scope, versions&lt;/li&gt;
&lt;li&gt;State management: the local backend, locking, remote state, drift&lt;/li&gt;
&lt;li&gt;Maintaining infrastructure: import, inspecting state from the CLI, verbose logging&lt;/li&gt;
&lt;li&gt;HCP Terraform: workspaces and projects, collaboration and governance&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How I'd study for a one-hour, unweighted exam
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Do the workflow with your hands, even though the exam won't ask you to.&lt;/strong&gt; Questions about &lt;code&gt;plan&lt;/code&gt; and &lt;code&gt;apply&lt;/code&gt; are far easier when you have watched a plan want to replace something you didn't expect. A free local setup is enough: a &lt;code&gt;local_file&lt;/code&gt; or a &lt;code&gt;random&lt;/code&gt; provider resource lets you practise state, &lt;code&gt;import&lt;/code&gt; and drift with no cloud bill.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Know the state questions cold.&lt;/strong&gt; State, backends and locking appear in two separate areas (2 and 6). Be clear that not every backend locks, that a &lt;code&gt;backend&lt;/code&gt; block takes literal values only, and that marking a value &lt;code&gt;sensitive&lt;/code&gt; hides it from output but not from the state file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Read the HCP Terraform area properly.&lt;/strong&gt; It's a whole objective area, and people who only use the CLI tend to skim it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The thing it can't check
&lt;/h2&gt;

&lt;p&gt;Multiple choice shows you know Terraform's workflow and language. It doesn't test hands-on skill, and it doesn't replace managing real infrastructure: reading a plan carefully before you approve it is a habit, and no exam can see habits.&lt;/p&gt;

&lt;p&gt;What's the Terraform concept that took you longest to really get?&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>certification</category>
      <category>devops</category>
      <category>beginners</category>
    </item>
    <item>
      <title>AWS Solutions Architect Associate (SAA-C03): the exam in plain numbers, and how its questions are built</title>
      <dc:creator>Ayodele</dc:creator>
      <pubDate>Thu, 05 Nov 2026 15:24:18 +0000</pubDate>
      <link>https://dev.to/learnsome-tech/aws-solutions-architect-associate-saa-c03-the-exam-in-plain-numbers-and-how-its-questions-are-523o</link>
      <guid>https://dev.to/learnsome-tech/aws-solutions-architect-associate-saa-c03-the-exam-in-plain-numbers-and-how-its-questions-are-523o</guid>
      <description>&lt;p&gt;&lt;em&gt;AI-assisted: compiled with an AI tool from AWS's exam page and the SAA-C03 exam guide, and checked against both. I run LearnSome.tech, which has an AWS Solutions Architect course; the advice here doesn't need it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The AWS Certified Solutions Architect – Associate is often the first "real" AWS certification people sit. Here is the exam as AWS describes it, and the question pattern that trips up people who know the services well.&lt;/p&gt;

&lt;h2&gt;
  
  
  The numbers
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Questions:&lt;/strong&gt; 65, each multiple choice (one right answer) or multiple response (two or more).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scored:&lt;/strong&gt; 50 of the 65. The other 15 are unscored pretest questions, and you can't tell which are which.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time:&lt;/strong&gt; 130 minutes, so two minutes a question.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pass mark:&lt;/strong&gt; 720 on a scaled score of 100 to 1,000.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost:&lt;/strong&gt; USD 150.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Valid for:&lt;/strong&gt; 3 years.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recommended:&lt;/strong&gt; at least 1 year of hands-on experience designing cloud solutions on AWS. AWS also suggests the Cloud Practitioner first for people with no IT experience.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The four domains
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Domain&lt;/th&gt;
&lt;th&gt;Weight&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Design Secure Architectures&lt;/td&gt;
&lt;td&gt;30%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Design Resilient Architectures&lt;/td&gt;
&lt;td&gt;26%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Design High-Performing Architectures&lt;/td&gt;
&lt;td&gt;24%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Design Cost-Optimized Architectures&lt;/td&gt;
&lt;td&gt;20%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Security is the biggest single domain, which surprises people who expect an architecture exam to be mostly about compute and storage.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the questions are built
&lt;/h2&gt;

&lt;p&gt;Most questions describe a requirement and then add a qualifier: &lt;strong&gt;least operational overhead&lt;/strong&gt;, &lt;strong&gt;most cost-effective&lt;/strong&gt;, &lt;strong&gt;highest availability&lt;/strong&gt;. Often every option would technically work. The qualifier decides which one scores.&lt;/p&gt;

&lt;p&gt;Here's one in that shape:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An orders database must fail over to another Availability Zone automatically, with no change to the address the application connects to, and with the &lt;strong&gt;least operational overhead&lt;/strong&gt;. What should the team do?&lt;/p&gt;

&lt;p&gt;A. Convert the database to a Multi-AZ deployment&lt;br&gt;
B. Create a read replica in another zone and write a script that promotes it on failure&lt;br&gt;
C. Take a snapshot every hour and restore the latest one in another zone after a failure&lt;br&gt;
D. Move the database to a larger instance&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before you pick, underline the three requirements: &lt;em&gt;automatic&lt;/em&gt;, &lt;em&gt;same address&lt;/em&gt;, &lt;em&gt;least overhead&lt;/em&gt;. Then strike out each option that misses any one of them. That habit, more than memorising service limits, is what the exam rewards.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two pacing habits worth practising
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Flag and move.&lt;/strong&gt; Two minutes a question is tight. When one runs long, choose your best option, flag it, and come back on a second pass with the time you saved.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Answer everything.&lt;/strong&gt; An unanswered question is simply wrong, so never leave one blank at the end.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What it proves
&lt;/h2&gt;

&lt;p&gt;Passing shows you can choose sound AWS designs from a description. It doesn't test hands-on skill, and it doesn't replace building on AWS: the console, the bill and the 2 a.m. alarm teach things a multiple-choice exam can't.&lt;/p&gt;

&lt;p&gt;Which domain did you find hardest?&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>certification</category>
      <category>career</category>
    </item>
    <item>
      <title>Linux permissions beyond rwx: umask, the sticky bit, setuid and hard links</title>
      <dc:creator>Ayodele</dc:creator>
      <pubDate>Thu, 05 Nov 2026 15:24:12 +0000</pubDate>
      <link>https://dev.to/learnsome-tech/linux-permissions-beyond-rwx-umask-the-sticky-bit-setuid-and-hard-links-3d05</link>
      <guid>https://dev.to/learnsome-tech/linux-permissions-beyond-rwx-umask-the-sticky-bit-setuid-and-hard-links-3d05</guid>
      <description>&lt;p&gt;&lt;em&gt;This is AI-assisted: I built it from our Linux glossary entries with an AI tool's help and checked the behaviour against the man pages. I run LearnSome.tech, where the glossary lives; nothing below needs an account anywhere.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Everyone learns &lt;code&gt;rwx&lt;/code&gt; and &lt;code&gt;chmod 644&lt;/code&gt; early. Then something odd happens: a new file comes out with permissions nobody set, or you can write to a directory but can't delete a file in it. These four words explain most of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  umask: where default permissions come from
&lt;/h2&gt;

&lt;p&gt;New files start from &lt;code&gt;666&lt;/code&gt; and new directories from &lt;code&gt;777&lt;/code&gt;, and the &lt;strong&gt;umask&lt;/strong&gt; removes bits from both. With the common umask &lt;code&gt;022&lt;/code&gt;, files come out &lt;code&gt;644&lt;/code&gt; and directories &lt;code&gt;755&lt;/code&gt;. With &lt;code&gt;077&lt;/code&gt;, nobody but you gets any access.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;umask&lt;/span&gt;          &lt;span class="c"&gt;# show the current mask, e.g. 0022&lt;/span&gt;
&lt;span class="nb"&gt;umask &lt;/span&gt;077      &lt;span class="c"&gt;# this shell and the programs it starts: private by default&lt;/span&gt;
&lt;span class="nb"&gt;touch &lt;/span&gt;secret.txt &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; secret.txt   &lt;span class="c"&gt;# -rw-------&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The umask is inherited by child processes, so a service started with a loose umask writes loose files.&lt;/p&gt;

&lt;h2&gt;
  
  
  The sticky bit: why you can't delete someone else's file in /tmp
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;/tmp&lt;/code&gt; is writable by everyone, yet you can't remove another user's file in it. That's the &lt;strong&gt;sticky bit&lt;/strong&gt;: on a directory, it lets users delete or rename only their own files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-ld&lt;/span&gt; /tmp    &lt;span class="c"&gt;# drwxrwxrwt: the trailing t is the sticky bit&lt;/span&gt;
&lt;span class="nb"&gt;chmod &lt;/span&gt;1777 shared/   &lt;span class="c"&gt;# the leading 1 sets it in octal&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It adds a rule about removing names. It doesn't replace the normal read, write and search permissions.&lt;/p&gt;

&lt;h2&gt;
  
  
  setuid: running as the file's owner
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;setuid&lt;/strong&gt; executable runs with its owner's identity, not the identity of whoever started it. That's how &lt;code&gt;passwd&lt;/code&gt;, owned by root, can update a file an ordinary user can't touch.&lt;/p&gt;

&lt;p&gt;It also means every setuid-root program is part of your security perimeter: a flaw in one can hand an attacker root. Keep them few, owned by root, not writable by anyone else, and know which ones you have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;find / &lt;span class="nt"&gt;-xdev&lt;/span&gt; &lt;span class="nt"&gt;-perm&lt;/span&gt; &lt;span class="nt"&gt;-4000&lt;/span&gt; &lt;span class="nt"&gt;-type&lt;/span&gt; f 2&amp;gt;/dev/null   &lt;span class="c"&gt;# list setuid files on this filesystem&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Hard links: one file, two equal names
&lt;/h2&gt;

&lt;p&gt;A file's data and metadata live in an &lt;strong&gt;inode&lt;/strong&gt;; a name in a directory just points at it. A &lt;strong&gt;hard link&lt;/strong&gt; is a second name for the same inode. Neither name is the "original": edit through one and the other sees it, because there's only one file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ln &lt;/span&gt;report.txt report-copy.txt
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-li&lt;/span&gt; report&lt;span class="k"&gt;*&lt;/span&gt;.txt   &lt;span class="c"&gt;# same inode number, link count 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That explains a classic surprise: deleting a name doesn't free the space while another hard link still points at the inode. It also explains why a filesystem can run out of inodes while it still has free space.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one-line takeaway
&lt;/h2&gt;

&lt;p&gt;When permissions surprise you, check four things: the umask that created the file, any special bits on the directory, any special bits on the program, and how many names point at the inode (&lt;code&gt;ls -li&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Which of these surprised you most when you first ran into it?&lt;/p&gt;

</description>
      <category>linux</category>
      <category>beginners</category>
      <category>security</category>
      <category>sysadmin</category>
    </item>
    <item>
      <title>Write a one-page responsibility map for every cloud service you run</title>
      <dc:creator>Ayodele</dc:creator>
      <pubDate>Thu, 05 Nov 2026 15:24:07 +0000</pubDate>
      <link>https://dev.to/learnsome-tech/write-a-one-page-responsibility-map-for-every-cloud-service-you-run-197o</link>
      <guid>https://dev.to/learnsome-tech/write-a-one-page-responsibility-map-for-every-cloud-service-you-run-197o</guid>
      <description>&lt;p&gt;&lt;em&gt;AI-assisted: written with an AI tool and checked against the AWS, Microsoft Azure and Google Cloud pages on shared responsibility. I run LearnSome.tech, which teaches cloud certifications; this exercise needs nothing from it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Everyone can recite "the provider secures the cloud, you secure what's in it". The trouble starts when a real service lands on your bill and nobody can say who patches what. So here is the model as an exercise you can finish in an afternoon.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one rule that never moves
&lt;/h2&gt;

&lt;p&gt;Whatever the service, &lt;strong&gt;your data and your identities are yours&lt;/strong&gt;. Classifying and protecting the data, deciding who has an account, enforcing MFA, removing leavers: no provider does those for you, in IaaS, PaaS or SaaS.&lt;/p&gt;

&lt;p&gt;Everything else moves depending on the kind of service:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;IaaS (a VM)&lt;/th&gt;
&lt;th&gt;PaaS (a managed platform)&lt;/th&gt;
&lt;th&gt;SaaS (an application)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Your data&lt;/td&gt;
&lt;td&gt;You&lt;/td&gt;
&lt;td&gt;You&lt;/td&gt;
&lt;td&gt;You&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Accounts and access&lt;/td&gt;
&lt;td&gt;You&lt;/td&gt;
&lt;td&gt;You&lt;/td&gt;
&lt;td&gt;You&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Applications&lt;/td&gt;
&lt;td&gt;You&lt;/td&gt;
&lt;td&gt;Shared&lt;/td&gt;
&lt;td&gt;Shared&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network controls&lt;/td&gt;
&lt;td&gt;You&lt;/td&gt;
&lt;td&gt;Shared&lt;/td&gt;
&lt;td&gt;Provider&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Operating system&lt;/td&gt;
&lt;td&gt;You&lt;/td&gt;
&lt;td&gt;Provider&lt;/td&gt;
&lt;td&gt;Provider&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hosts, hypervisor, data centre&lt;/td&gt;
&lt;td&gt;Provider&lt;/td&gt;
&lt;td&gt;Provider&lt;/td&gt;
&lt;td&gt;Provider&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That table follows Microsoft's breakdown; AWS and Google describe the same split in their own words.&lt;/p&gt;

&lt;h2&gt;
  
  
  The exercise
&lt;/h2&gt;

&lt;p&gt;For each service on your bill, write four lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Amazon EC2 (orders web server)&lt;/span&gt;
&lt;span class="na"&gt;patches the OS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;us (the guest OS is ours on EC2)&lt;/span&gt;
&lt;span class="na"&gt;network rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;us (security groups, VPC)&lt;/span&gt;
&lt;span class="na"&gt;holds the keys&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;us (SSH keys, IAM roles)&lt;/span&gt;
&lt;span class="na"&gt;leads an incident&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;us, with AWS for anything below the hypervisor&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;managed database (orders DB)&lt;/span&gt;
&lt;span class="na"&gt;patches the OS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;provider&lt;/span&gt;
&lt;span class="na"&gt;network rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;shared (we decide what may connect; security groups again)&lt;/span&gt;
&lt;span class="na"&gt;holds the keys&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;us (database users, encryption key choices)&lt;/span&gt;
&lt;span class="na"&gt;leads an incident: depends&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write down which cases are ours&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;email and documents suite (SaaS)&lt;/span&gt;
&lt;span class="na"&gt;patches the OS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;provider&lt;/span&gt;
&lt;span class="na"&gt;network rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;provider&lt;/span&gt;
&lt;span class="na"&gt;holds the keys&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;us (accounts, MFA, sharing settings)&lt;/span&gt;
&lt;span class="na"&gt;leads an incident&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;us, for anything an account or a share setting caused&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any line you can't fill in from the provider's own documentation is a question for your team, not a gap to leave blank.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three mistakes the map catches
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"Managed" read as "secured for you".&lt;/strong&gt; Even in PaaS and SaaS, application configuration, code security and access controls stay with you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One split for everything.&lt;/strong&gt; Your share changes per service. EC2 and a managed database sit on very different rows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Incidents left to the provider.&lt;/strong&gt; Incident handling is often the least clearly divided area. Many incidents start with a misconfigured resource or stolen credentials, and both of those are on your side.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The map is also a good onboarding document: a new engineer reads it and knows which alerts are theirs.&lt;/p&gt;

&lt;p&gt;What's the service where your team disagreed most about who owns what?&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>security</category>
      <category>aws</category>
      <category>devops</category>
    </item>
    <item>
      <title>Four Git words that get your work back: reflog, detached HEAD, stash and the index</title>
      <dc:creator>Ayodele</dc:creator>
      <pubDate>Thu, 05 Nov 2026 15:24:03 +0000</pubDate>
      <link>https://dev.to/learnsome-tech/four-git-words-that-get-your-work-back-reflog-detached-head-stash-and-the-index-30ec</link>
      <guid>https://dev.to/learnsome-tech/four-git-words-that-get-your-work-back-reflog-detached-head-stash-and-the-index-30ec</guid>
      <description>&lt;p&gt;&lt;em&gt;AI-assisted: these definitions come from the Git glossary we keep at LearnSome.tech, turned into a post with help from an AI tool and checked against the Git documentation. I run LearnSome.tech; you don't need it to use any of this.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you committed it, it's very likely still there, even after a bad reset or rebase; you just need the words to find it. (Changes you never committed or stashed are another story, which is why the last section matters.) Here are four words worth knowing.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The reflog
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it is:&lt;/strong&gt; Git's local record of every position &lt;code&gt;HEAD&lt;/code&gt; and each branch has pointed at.&lt;/p&gt;

&lt;p&gt;Every commit, checkout, reset, rebase and merge adds an entry such as &lt;code&gt;HEAD@{2}&lt;/code&gt;. So after a bad &lt;code&gt;reset --hard&lt;/code&gt; or a rebase that went wrong, the old commit is usually one command away:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git reflog                        &lt;span class="c"&gt;# find the line from before the mistake&lt;/span&gt;
git branch rescued &amp;lt;commit-id&amp;gt;    &lt;span class="c"&gt;# put a branch on it so it can't get lost&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Know its limits:&lt;/strong&gt; it lives only in your clone (a teammate's reflog won't help you), and entries expire, by default after about 90 days, or 30 for commits nothing points at any more.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Detached HEAD
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it is:&lt;/strong&gt; &lt;code&gt;HEAD&lt;/code&gt; holding a commit ID directly instead of a branch name.&lt;/p&gt;

&lt;p&gt;You get there by checking out a commit, a tag or a remote-tracking branch. It's a normal state for looking around, not an error. The catch: if you make commits while detached, no branch moves to follow them, and Git warns you when you leave because they'll only survive while something points at them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git switch &lt;span class="nt"&gt;-c&lt;/span&gt; keep-this-work      &lt;span class="c"&gt;# before or after leaving: give the commits a branch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. git stash
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it is:&lt;/strong&gt; a command that saves your uncommitted changes aside and returns the working tree to the last commit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git stash          &lt;span class="c"&gt;# staged and unstaged changes to tracked files&lt;/span&gt;
git stash list     &lt;span class="c"&gt;# what's saved&lt;/span&gt;
git stash pop      &lt;span class="c"&gt;# reapply the newest entry and drop it from the list&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The gotcha:&lt;/strong&gt; untracked files stay where they are unless you add &lt;code&gt;-u&lt;/code&gt;. People stash, switch branch, and then wonder why a new file followed them.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. The staging area (the index)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What it is:&lt;/strong&gt; Git's list of exactly what the next commit will contain, kept in &lt;code&gt;.git/index&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It holds a complete tree, not just a list of changed names. &lt;code&gt;git add&lt;/code&gt; copies a file into it &lt;em&gt;as it is at that moment&lt;/em&gt;, so if you edit the file again after adding it, the staged copy stays as it was. That's why &lt;code&gt;git status&lt;/code&gt; can show the same file as both "staged" and "modified".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git diff            &lt;span class="c"&gt;# working tree vs the index: what you haven't staged&lt;/span&gt;
git diff &lt;span class="nt"&gt;--staged&lt;/span&gt;   &lt;span class="c"&gt;# the index vs the last commit: what will be committed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The habit that ties them together
&lt;/h2&gt;

&lt;p&gt;Before any command that rewrites history (&lt;code&gt;reset&lt;/code&gt;, &lt;code&gt;rebase&lt;/code&gt;, &lt;code&gt;commit --amend&lt;/code&gt;), run &lt;code&gt;git status&lt;/code&gt; and glance at &lt;code&gt;git log --oneline -5&lt;/code&gt;. If something goes wrong, you'll recognise the commit you need in the reflog.&lt;/p&gt;

&lt;p&gt;Which of these four have you had to look up in a panic?&lt;/p&gt;

</description>
      <category>git</category>
      <category>beginners</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>CKA or CKAD first? Let your ticket queue decide</title>
      <dc:creator>Ayodele</dc:creator>
      <pubDate>Thu, 05 Nov 2026 15:23:58 +0000</pubDate>
      <link>https://dev.to/learnsome-tech/cka-or-ckad-first-let-your-ticket-queue-decide-25hb</link>
      <guid>https://dev.to/learnsome-tech/cka-or-ckad-first-let-your-ticket-queue-decide-25hb</guid>
      <description>&lt;p&gt;&lt;em&gt;AI-assisted: I drafted this from the Linux Foundation's exam pages and FAQ and used an AI tool to edit it. I run LearnSome.tech, where we have CKA and CKAD courses; you can make this decision without them.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;People ask "which is harder?" The more useful question is "which one looks like my job?" Here is why.&lt;/p&gt;

&lt;h2&gt;
  
  
  The format is the same
&lt;/h2&gt;

&lt;p&gt;Both are online, proctored, performance-based exams: around 15 to 20 tasks solved on the command line, on Linux hosts with &lt;code&gt;kubectl&lt;/code&gt; already set up (with the &lt;code&gt;k&lt;/code&gt; alias and Bash completion). Both give you 2 hours, both need 66% to pass, and each costs USD 445 including one free retake. Neither has a prerequisite. Both certifications are valid for 2 years.&lt;/p&gt;

&lt;p&gt;So difficulty comes down to which tasks feel further from your day.&lt;/p&gt;

&lt;h2&gt;
  
  
  The work is different
&lt;/h2&gt;

&lt;p&gt;The CKA is about running the cluster. Its heaviest domain is Troubleshooting at 30%, then Cluster Architecture, Installation and Configuration at 25%: kubeadm, upgrades, RBAC, a highly available control plane.&lt;/p&gt;

&lt;p&gt;The CKAD is about the apps on the cluster. Its heaviest domain is Application Environment, Configuration and Security at 25%, with Design and Build, Deployment, and Services and Networking at 20% each: building images, probes, rolling updates, ConfigMaps and Secrets.&lt;/p&gt;

&lt;p&gt;A CKA-style task:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# "worker-1 is NotReady. Make it Ready, and keep it Ready after a reboot."&lt;/span&gt;
kubectl describe node worker-1          &lt;span class="c"&gt;# conditions and taints first&lt;/span&gt;
ssh worker-1
&lt;span class="nb"&gt;sudo &lt;/span&gt;journalctl &lt;span class="nt"&gt;-u&lt;/span&gt; kubelet &lt;span class="nt"&gt;-n&lt;/span&gt; 50        &lt;span class="c"&gt;# why the kubelet stopped&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; &lt;span class="nt"&gt;--now&lt;/span&gt; kubelet     &lt;span class="c"&gt;# fix it and make it survive a reboot&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A CKAD-style task:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# "The web app in namespace shop is Running but gets no traffic. Fix it."&lt;/span&gt;
kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; shop get pods,endpointslices &lt;span class="c"&gt;# Running pods, empty endpoints&lt;/span&gt;
kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; shop describe pod &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;web &lt;span class="c"&gt;# readiness probe on the wrong port&lt;/span&gt;
kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; shop edit deployment web     &lt;span class="c"&gt;# fix the probe, then verify endpoints&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The decision
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You mostly ship apps to a cluster someone else runs: &lt;strong&gt;CKAD first&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;You build images and write manifests: &lt;strong&gt;CKAD first&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;You upgrade, repair or secure clusters and nodes: &lt;strong&gt;CKA first&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The CKS is your goal: &lt;strong&gt;CKA first&lt;/strong&gt;, because the CKS requires a passed CKA.&lt;/li&gt;
&lt;li&gt;Not sure: look at the last ten tickets you closed and count which list they fit.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  If you plan both
&lt;/h2&gt;

&lt;p&gt;They overlap more than people expect: rolling updates, ConfigMaps and Secrets appear in both curricula. Book the second exam soon after the first, while that shared ground is fresh, and spend the new study time on what the first one didn't cover.&lt;/p&gt;

&lt;p&gt;One honest caveat: passing either shows you can do the tasks under time. It doesn't replace running clusters or apps in production.&lt;/p&gt;

&lt;p&gt;Which one did you take first, and would you choose the same again?&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>certification</category>
      <category>career</category>
      <category>devops</category>
    </item>
    <item>
      <title>My Kubernetes Service gets no traffic: the five checks I run, in order</title>
      <dc:creator>Ayodele</dc:creator>
      <pubDate>Thu, 05 Nov 2026 15:23:53 +0000</pubDate>
      <link>https://dev.to/learnsome-tech/my-kubernetes-service-gets-no-traffic-the-five-checks-i-run-in-order-3nnl</link>
      <guid>https://dev.to/learnsome-tech/my-kubernetes-service-gets-no-traffic-the-five-checks-i-run-in-order-3nnl</guid>
      <description>&lt;p&gt;&lt;em&gt;AI-assisted note: I wrote the checks from the ones I actually run, and an AI tool helped with the wording. The behaviour is checked against the Kubernetes documentation on Services. I run LearnSome.tech, where we teach Kubernetes; nothing here depends on it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Most "my Service is broken" problems aren't about the Service type at all. They are a selector that matches nothing, pods that aren't Ready, or a port that points at the wrong place. But it helps to know what each type promises first.&lt;/p&gt;

&lt;h2&gt;
  
  
  The types in one table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Who can reach it&lt;/th&gt;
&lt;th&gt;Builds on&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ClusterIP (the default)&lt;/td&gt;
&lt;td&gt;Clients inside the cluster&lt;/td&gt;
&lt;td&gt;Nothing, it's the base&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NodePort&lt;/td&gt;
&lt;td&gt;Anyone who can reach a node, on a port from 30000-32767 by default&lt;/td&gt;
&lt;td&gt;ClusterIP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LoadBalancer&lt;/td&gt;
&lt;td&gt;Clients of the cloud load balancer&lt;/td&gt;
&lt;td&gt;NodePort&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ExternalName&lt;/td&gt;
&lt;td&gt;Not a proxy: in-cluster clients get a DNS alias to another name&lt;/td&gt;
&lt;td&gt;No cluster IP at all&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The types nest: a NodePort Service also gets a cluster IP, and a LoadBalancer Service still allocates a node port by default. That last one surprises people when they look at firewall rules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ kubectl get svc web
NAME   TYPE           CLUSTER-IP    EXTERNAL-IP    PORT(S)
web    LoadBalancer   10.96.12.40   203.0.113.10   80:31234/TCP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;80&lt;/code&gt; is the Service port; &lt;code&gt;31234&lt;/code&gt; is a node port that is open on every node too. Pick the narrowest type that still reaches your clients.&lt;/p&gt;

&lt;h2&gt;
  
  
  The five checks
&lt;/h2&gt;

&lt;p&gt;When a Service exists but its pods never see a request, I go through these in order and stop at the first one that fails.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Does the Service exist, with the type and ports I expect?&lt;/span&gt;
kubectl get svc web &lt;span class="nt"&gt;-o&lt;/span&gt; wide

&lt;span class="c"&gt;# 2. Did its selector find any pods? An empty endpoint list means no.&lt;/span&gt;
kubectl get endpointslices &lt;span class="nt"&gt;-l&lt;/span&gt; kubernetes.io/service-name&lt;span class="o"&gt;=&lt;/span&gt;web

&lt;span class="c"&gt;# 3. Selector vs pod labels, character by character&lt;/span&gt;
kubectl get svc web &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.spec.selector}'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;echo
&lt;/span&gt;kubectl get pods &lt;span class="nt"&gt;--show-labels&lt;/span&gt;

&lt;span class="c"&gt;# 4. Are the pods Ready? Pods that aren't Ready don't get Service traffic.&lt;/span&gt;
kubectl get pods &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;web

&lt;span class="c"&gt;# 5. Does targetPort match the port the container listens on?&lt;/span&gt;
kubectl get svc web &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.spec.ports[*].targetPort}'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2 is the one that saves the most time. Kubernetes keeps EndpointSlice objects in step with each Service's selector and with pod readiness, so an empty slice tells you the problem is the selector or readiness, not DNS and not the network.&lt;/p&gt;

&lt;p&gt;Step 4 catches a sneaky one: a readiness probe pointed at the wrong port. The pods show &lt;code&gt;Running&lt;/code&gt;, nothing restarts, and the Service still has no endpoints, because a failing readiness probe only takes the pod out of rotation.&lt;/p&gt;

&lt;p&gt;If all five pass, bypass the Service and call a pod directly. If that fails too, the problem is in the app, not in Kubernetes.&lt;/p&gt;

&lt;h2&gt;
  
  
  When a Service isn't the answer
&lt;/h2&gt;

&lt;p&gt;If what you need is HTTP routing from outside the cluster (several paths or hostnames behind one entry point), you want an Ingress or a Gateway in front of ClusterIP Services, not a LoadBalancer per app. The Kubernetes project now recommends Gateway over Ingress, whose API is frozen.&lt;/p&gt;

&lt;p&gt;Which of the five checks has caught you most often?&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>networking</category>
      <category>debugging</category>
    </item>
    <item>
      <title>Reviewing a multi-stage Dockerfile: six things I check</title>
      <dc:creator>Ayodele</dc:creator>
      <pubDate>Thu, 05 Nov 2026 15:23:47 +0000</pubDate>
      <link>https://dev.to/learnsome-tech/reviewing-a-multi-stage-dockerfile-six-things-i-check-5282</link>
      <guid>https://dev.to/learnsome-tech/reviewing-a-multi-stage-dockerfile-six-things-i-check-5282</guid>
      <description>&lt;p&gt;&lt;em&gt;AI-assisted: the checklist and the example are mine, and an AI tool helped tighten the wording. Every behaviour below is checked against Docker's own documentation on multi-stage builds and build secrets. I run LearnSome.tech, where we teach Docker; you don't need it for anything here.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A multi-stage build is a Dockerfile with more than one &lt;code&gt;FROM&lt;/code&gt;. Each &lt;code&gt;FROM&lt;/code&gt; starts a new stage from a clean slate, and &lt;code&gt;COPY --from=&amp;lt;stage&amp;gt;&lt;/code&gt; carries only the files you name into the next one. The compiler, the test tools and the source stay behind.&lt;/p&gt;

&lt;p&gt;Here is the smallest useful shape, a Go program shipped on an empty base:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# syntax=docker/dockerfile:1&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;golang:1.24&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;build&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /src&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="c"&gt;# a static binary, so it runs on the empty scratch image&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nv"&gt;CGO_ENABLED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0 go build &lt;span class="nt"&gt;-o&lt;/span&gt; /bin/hello .

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; scratch&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=build /bin/hello /bin/hello&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["/bin/hello"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When I review someone else's multi-stage Dockerfile, these are the six questions I ask.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Are the stages named?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;FROM golang:1.24 AS build&lt;/code&gt; and &lt;code&gt;COPY --from=build&lt;/code&gt; keep working when someone reorders the file later. A numbered stage (&lt;code&gt;--from=0&lt;/code&gt;) points at whatever stage is first, so adding a stage above it quietly changes what gets copied.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. What does the last stage actually contain?
&lt;/h2&gt;

&lt;p&gt;Only the last stage ships by default. Check that it starts from a small base and copies in the built output and nothing else: no &lt;code&gt;COPY . .&lt;/code&gt; in the final stage. A smaller image means fewer packages, which means fewer vulnerabilities to patch.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Can I build one stage on its own?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;docker build --target build -t app:build .&lt;/code&gt; stops at the stage called &lt;code&gt;build&lt;/code&gt;, which is handy for running tests inside it or debugging a failing step. With BuildKit, only the stages the target depends on are built; the legacy builder runs every stage before the target.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. How does a secret reach the build?
&lt;/h2&gt;

&lt;p&gt;Build arguments and environment variables persist in the final image, so they are the wrong way to hand a build a token. Use a secret mount, which exists only for the one &lt;code&gt;RUN&lt;/code&gt; that asks for it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nt"&gt;--mount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;secret,id&lt;span class="o"&gt;=&lt;/span&gt;npmtoken &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nv"&gt;NPM_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /run/secrets/npmtoken&lt;span class="si"&gt;)&lt;/span&gt; npm ci
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;--secret&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;npmtoken,src&lt;span class="o"&gt;=&lt;/span&gt;./npmtoken &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copying a secret in and deleting it in a later step doesn't work either: the earlier layer still holds it.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Is every &lt;code&gt;ARG&lt;/code&gt; declared in the stage that uses it?
&lt;/h2&gt;

&lt;p&gt;An &lt;code&gt;ARG&lt;/code&gt; declared in one stage isn't visible in an unrelated stage. If two stages need &lt;code&gt;VERSION&lt;/code&gt;, both need the &lt;code&gt;ARG VERSION&lt;/code&gt; line. This one causes a lot of "why is my variable empty?" questions.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Is the base pinned when it needs to be, and is there a &lt;code&gt;.dockerignore&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;Image tags are mutable, so pin the base to a digest when you need the exact same bytes every time. And a &lt;code&gt;.dockerignore&lt;/code&gt; that leaves out &lt;code&gt;.git&lt;/code&gt;, local environments and &lt;code&gt;.env&lt;/code&gt; files keeps the build context small and stops a broad &lt;code&gt;COPY&lt;/code&gt; from picking up something private.&lt;/p&gt;

&lt;p&gt;If you only take one thing from this: open your final stage and list every file in it. Anything you can't explain shouldn't be there.&lt;/p&gt;

&lt;p&gt;What's the biggest image you've shrunk this way?&lt;/p&gt;

</description>
      <category>docker</category>
      <category>devops</category>
      <category>containers</category>
      <category>security</category>
    </item>
    <item>
      <title>Terraform state gotchas I wish someone had told me on day one</title>
      <dc:creator>Ayodele</dc:creator>
      <pubDate>Thu, 05 Nov 2026 15:23:38 +0000</pubDate>
      <link>https://dev.to/learnsome-tech/terraform-state-gotchas-i-wish-someone-had-told-me-on-day-one-541i</link>
      <guid>https://dev.to/learnsome-tech/terraform-state-gotchas-i-wish-someone-had-told-me-on-day-one-541i</guid>
      <description>&lt;p&gt;&lt;em&gt;AI-assisted: I wrote the outline and the examples, and used an AI tool to tighten the wording. I checked the behaviour below against HashiCorp's documentation. I run LearnSome.tech, where we teach Terraform; this post doesn't need anything from it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Terraform's state file is easy to ignore until it bites. It's the record that says "this address in my code owns that real thing in the cloud". Lose it or share it carelessly and Terraform's view of the world stops matching reality. These are the gotchas I see most often.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Deleting state doesn't delete anything, and that's the problem
&lt;/h2&gt;

&lt;p&gt;Delete &lt;code&gt;terraform.tfstate&lt;/code&gt; and your cloud resources are untouched. But Terraform has forgotten they're yours. The next &lt;code&gt;apply&lt;/code&gt; plans to create everything again, and you either get duplicates or name clashes.&lt;/p&gt;

&lt;p&gt;If you've lost state but the resources exist, don't recreate them. Bring them back under management with &lt;code&gt;terraform import&lt;/code&gt; or an &lt;code&gt;import&lt;/code&gt; block, then check &lt;code&gt;terraform plan&lt;/code&gt; shows no changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Local state on a team is a race
&lt;/h2&gt;

&lt;p&gt;Two people with their own local state for the same infrastructure will each believe their copy is the truth. The second &lt;code&gt;apply&lt;/code&gt; quietly undoes the first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do instead:&lt;/strong&gt; a remote backend everyone shares (HCP Terraform, S3, GCS, azurerm and so on), set up before the second person ever runs Terraform.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Assuming locking is on
&lt;/h2&gt;

&lt;p&gt;Locking stops two runs writing state at the same time. Many people assume every backend locks by default. Not all backends support locking, and on S3 it's opt-in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;backend&lt;/span&gt; &lt;span class="s2"&gt;"s3"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;bucket&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"acme-terraform-state"&lt;/span&gt;
    &lt;span class="nx"&gt;key&lt;/span&gt;          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"network/terraform.tfstate"&lt;/span&gt;
    &lt;span class="nx"&gt;region&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"eu-west-2"&lt;/span&gt;
    &lt;span class="nx"&gt;encrypt&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="nx"&gt;use_lockfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;   &lt;span class="c1"&gt;# S3-native locking; the DynamoDB table approach is deprecated&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also note that a backend block takes literal values only: no variables or locals.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Reaching for force-unlock too quickly
&lt;/h2&gt;

&lt;p&gt;A run says the state is locked. The tempting move is &lt;code&gt;terraform force-unlock &amp;lt;ID&amp;gt;&lt;/code&gt;. If the lock belongs to a teammate's apply that's still running, you've just allowed two writers on the same state.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do instead:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform plan &lt;span class="nt"&gt;-lock-timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5m   &lt;span class="c"&gt;# wait for a running job to finish&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use &lt;code&gt;force-unlock&lt;/code&gt; only for your own lock, when you know the run that held it has died (a crashed CI job, for example), and with the exact lock ID Terraform printed. The command doesn't change infrastructure, but it can let two runs corrupt state.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Committing state to Git
&lt;/h2&gt;

&lt;p&gt;It feels like a free backup. It isn't: Git has no locking, everyone's copy diverges, and state contains every attribute Terraform knows about your resources, including secrets (next point). HashiCorp advises against it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do instead:&lt;/strong&gt; a private, versioned bucket (or HCP Terraform). Versioning gives you the history Git would have, without the leaks.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Believing &lt;code&gt;sensitive = true&lt;/code&gt; keeps secrets out of state
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;sensitive = true&lt;/code&gt; hides a value in plan and apply output. It's still in the state file. If you pass a database password into a resource, that password is in state in plain text.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do instead:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Treat the state file as a secret: encrypted at rest, tight access control, never in Git.&lt;/li&gt;
&lt;li&gt;Where your Terraform and provider versions support them, use ephemeral values and write-only arguments, which Terraform leaves out of state and plan files.&lt;/li&gt;
&lt;li&gt;Better still, let the cloud generate and store the secret (a secrets manager), and pass Terraform a reference rather than the value.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A quick health check for any Terraform repo
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Is there a &lt;code&gt;backend&lt;/code&gt; block, and does it lock?&lt;/li&gt;
&lt;li&gt;Is &lt;code&gt;*.tfstate&lt;/code&gt; in &lt;code&gt;.gitignore&lt;/code&gt;, and absent from history?&lt;/li&gt;
&lt;li&gt;Who can read the state bucket? Would you be happy if that list could read your production passwords?&lt;/li&gt;
&lt;li&gt;Does &lt;code&gt;terraform plan&lt;/code&gt; on &lt;code&gt;main&lt;/code&gt; show no changes? If not, something changed outside Terraform.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Which of these caught you out first?&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>devops</category>
      <category>aws</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Five Kubernetes probe mistakes that turn a slow start into a restart loop</title>
      <dc:creator>Ayodele</dc:creator>
      <pubDate>Thu, 05 Nov 2026 15:23:23 +0000</pubDate>
      <link>https://dev.to/learnsome-tech/five-kubernetes-probe-mistakes-that-turn-a-slow-start-into-a-restart-loop-m28</link>
      <guid>https://dev.to/learnsome-tech/five-kubernetes-probe-mistakes-that-turn-a-slow-start-into-a-restart-loop-m28</guid>
      <description>&lt;p&gt;&lt;em&gt;AI-assisted: I wrote the outline and the examples, and used an AI tool to tighten the wording. I checked every behaviour below against the Kubernetes documentation. I run LearnSome.tech, where we teach Kubernetes; this post doesn't need anything from it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Most probe problems I see aren't exotic. A Pod restarts every few minutes, &lt;code&gt;kubectl get pods&lt;/code&gt; shows a climbing RESTARTS count, and the app logs look fine. Nine times out of ten the probes are doing exactly what they were told to do. Here are the five mistakes I look for first.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Using liveness to protect a slow start
&lt;/h2&gt;

&lt;p&gt;A JVM service takes 70 seconds to start. Someone adds a liveness probe with the defaults (&lt;code&gt;periodSeconds: 10&lt;/code&gt;, &lt;code&gt;failureThreshold: 3&lt;/code&gt;, no initial delay), and the kubelet kills the container at about 30 seconds, before it ever listens. It restarts, takes 70 seconds again, and is killed again. After a few rounds you get &lt;code&gt;CrashLoopBackOff&lt;/code&gt;, with back-off delays doubling from 10 s up to a 5-minute cap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; add a startup probe. Until it succeeds, Kubernetes doesn't run liveness or readiness at all. Size it so &lt;code&gt;failureThreshold × periodSeconds&lt;/code&gt; covers your worst start, not your average one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;startupProbe&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;httpGet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;/healthz&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;http&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;periodSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
  &lt;span class="na"&gt;failureThreshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;18&lt;/span&gt;   &lt;span class="c1"&gt;# up to 3 minutes to start&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then liveness can stay strict, because it only begins after the start is done.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Checking the database in the liveness probe
&lt;/h2&gt;

&lt;p&gt;If &lt;code&gt;/healthz&lt;/code&gt; queries Postgres and Postgres has a bad minute, every replica fails liveness together and Kubernetes restarts all of them. Restarting your app doesn't fix your database; it adds a thundering herd of reconnects on top of the outage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; liveness answers one question: "is this process stuck?" Keep it in-process and cheap. Put dependency checks in the readiness probe, where a failure only takes the Pod out of the Service's endpoints. Nothing gets killed.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Trusting the 1-second timeout
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;timeoutSeconds&lt;/code&gt; defaults to 1. A health endpoint that answers in 40 ms on your laptop can take 1.5 s under load, during a GC pause, or on a noisy node. Three slow answers in a row and the container is restarted, right when it's busiest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; time the endpoint under realistic load and set &lt;code&gt;timeoutSeconds&lt;/code&gt; from that, or make the endpoint cheaper. Health endpoints should return a tiny body; the kubelet stops reading after 10 KiB anyway.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Expecting liveness to wait for readiness
&lt;/h2&gt;

&lt;p&gt;It doesn't. Liveness and readiness run independently. A Pod can be "not ready" and still have its liveness probe firing, and failing, the whole time. People add a readiness probe and assume it "protects" the container during warm-up. It doesn't protect it from liveness.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; that's the startup probe's job again (mistake 1), or an &lt;code&gt;initialDelaySeconds&lt;/code&gt; on liveness if you really can't add one.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Copying the same probe for all three
&lt;/h2&gt;

&lt;p&gt;Same path, same port, same thresholds, pasted three times. It looks tidy, but it erases the difference between "restart me", "don't send me traffic" and "I'm still booting".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; a reasonable starting point:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Startup:&lt;/strong&gt; the same cheap check as liveness, with a long &lt;code&gt;failureThreshold&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Liveness:&lt;/strong&gt; cheap, in-process, a few failures before a restart.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Readiness:&lt;/strong&gt; its own endpoint, may check required dependencies, fails fast (&lt;code&gt;periodSeconds: 5&lt;/code&gt;, &lt;code&gt;failureThreshold: 2&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How I debug it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl describe pod &amp;lt;pod&amp;gt;          &lt;span class="c"&gt;# Events: "Liveness probe failed: ..." and "Killing"&lt;/span&gt;
kubectl get pod &amp;lt;pod&amp;gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.status.containerStatuses[0].lastState}'&lt;/span&gt;
kubectl get endpointslices &lt;span class="nt"&gt;-l&lt;/span&gt; kubernetes.io/service-name&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;svc&amp;gt;   &lt;span class="c"&gt;# is the Pod in the Service?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the Events show "Liveness probe failed" just before each restart, it's the probe and not the app. If the Pod is running but gets no traffic, look at readiness and the EndpointSlices.&lt;/p&gt;

&lt;p&gt;One habit worth building: before you ship a new liveness probe, run it against a deliberately slow copy of the app. If that copy gets restarted, so will production on a bad day.&lt;/p&gt;

&lt;p&gt;What's the strangest probe failure you've had to debug?&lt;/p&gt;

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