<?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: Dixon Gunasekara</title>
    <description>The latest articles on DEV Community by Dixon Gunasekara (@dixonaws).</description>
    <link>https://dev.to/dixonaws</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%2F2944342%2Fd3421c04-32a0-4824-9067-65577d281d4a.png</url>
      <title>DEV Community: Dixon Gunasekara</title>
      <link>https://dev.to/dixonaws</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dixonaws"/>
    <language>en</language>
    <item>
      <title>From React Basics to Production Next.js: The Complete Roadmap</title>
      <dc:creator>Dixon Gunasekara</dc:creator>
      <pubDate>Sat, 22 Aug 2026 16:17:10 +0000</pubDate>
      <link>https://dev.to/dixonaws/from-react-basics-to-production-nextjs-the-complete-roadmap-22i6</link>
      <guid>https://dev.to/dixonaws/from-react-basics-to-production-nextjs-the-complete-roadmap-22i6</guid>
      <description>&lt;p&gt;Here is a structured, fast-track study guide to take you from React fundamentals all the way to building production-grade applications using Next.js.&lt;/p&gt;

&lt;p&gt;This flow ensures you build a rock-solid mental model of the "older" core React concepts before layering on the powerful server-side paradigms of modern Next.js.&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase 1: Core React Essentials
&lt;/h2&gt;

&lt;p&gt;Before touching a meta-framework, you need a deep understanding of standard client-side React. If you are coming from an MVC background or another framework like Angular, focus on React's one-way data flow.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;JSX &amp;amp; Component Architecture&lt;/strong&gt;: Understand how to write declarative UI. Learn how to break down complex interfaces into small, reusable functional components.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;State &amp;amp; Props (&lt;code&gt;useState&lt;/code&gt;)&lt;/strong&gt;: Master how data moves down the component tree via props, and how local component memory is managed using state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Component Lifecycle (&lt;code&gt;useEffect&lt;/code&gt;)&lt;/strong&gt;: This is often the trickiest part for beginners. Learn how to synchronize a component with an external system (like fetching data on mount or subscribing to an event) and how to write cleanup functions to prevent memory leaks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Essential Hooks Toolkit&lt;/strong&gt;:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;-&amp;gt; &lt;code&gt;useRef&lt;/code&gt;: For persisting values between renders without triggering a re-render, or directly accessing DOM elements.&lt;br&gt;
   -&amp;gt; &lt;code&gt;useContext&lt;/code&gt;: For avoiding "prop drilling" by sharing state globally (like a UI theme or user session) across the component tree.&lt;br&gt;
   -&amp;gt; Custom Hooks: Learn to extract reusable logic (e.g., a &lt;code&gt;useFetch&lt;/code&gt; hook) out of your UI components.&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase 2: Advanced React Patterns
&lt;/h2&gt;

&lt;p&gt;Once you can build a basic React app, you need to learn how to make it scale and perform well.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance Optimization&lt;/strong&gt;: Learn when not to render. Master &lt;code&gt;useMemo&lt;/code&gt; (caching expensive calculations), &lt;code&gt;useCallback&lt;/code&gt; (caching function definitions), and &lt;code&gt;React.memo&lt;/code&gt; (preventing child components from re-rendering if their props haven't changed).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Global State Management&lt;/strong&gt;: While Context API is great, for complex state, learn a modern lightweight state manager like Zustand (or Redux Toolkit if you need enterprise-level strictness).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Client-Side Data Fetching&lt;/strong&gt;: Learn React Query (TanStack Query). It handles caching, deduplication, background fetching, and loading states—replacing standard &lt;code&gt;useEffect&lt;/code&gt; data fetching entirely.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Phase 3: The Next.js Paradigm Shift
&lt;/h2&gt;

&lt;p&gt;Next.js shifts React from being just a client-side library to a full-stack framework. The modern standard is the App Router (&lt;code&gt;/app&lt;/code&gt; directory).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;React Server Components (RSC)&lt;/strong&gt;: Understand the difference between Server Components (rendered on the server, zero bundle size, direct backend access) and Client Components (marked with "use client", standard React components with state/effects). Default to Server Components.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;File-Based Routing&lt;/strong&gt;: Learn how folders define routes. Understand page.tsx (the UI for a route) and layout.tsx (shared UI like navbars that persist across routes).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Advanced Routing&lt;/strong&gt;: Master dynamic routes ([id]), route groups ((auth)), and intercepting routes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Phase 4: Modern Data Architecture
&lt;/h2&gt;

&lt;p&gt;Next.js fundamentally changes how you interact with databases and APIs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server-Side Fetching&lt;/strong&gt;: Learn how to use the native &lt;code&gt;fetch&lt;/code&gt; API inside Server Components. Understand caching strategies (&lt;code&gt;force-cache&lt;/code&gt;, &lt;code&gt;no-store&lt;/code&gt;) and Time-Based/On-Demand Revalidation (ISR).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server Actions&lt;/strong&gt;: This replaces traditional API routes. Learn how to write asynchronous server functions that can be called directly from client-side forms to mutate data (e.g., submitting a form directly to a database without building a REST endpoint).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Streaming &amp;amp; Suspense&lt;/strong&gt;: Learn how to use &lt;code&gt;loading.tsx&lt;/code&gt; and React &lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt; boundaries to progressively stream UI to the user while backend data is still fetching.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Phase 5: Production-Grade Implementation
&lt;/h2&gt;

&lt;p&gt;To build an enterprise-ready application, you need to integrate external tooling for security, data modeling, and deployment.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;Concept&lt;/th&gt;
&lt;th&gt;Industry Standard Tools to Learn&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authentication&lt;/td&gt;
&lt;td&gt;Auth.js (NextAuth) for OAuth/Credentials, or integrating a robust identity provider like AWS Cognito.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database ORM&lt;/td&gt;
&lt;td&gt;Prisma (excellent developer experience) or Drizzle ORM (high performance, SQL-like syntax).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Styling&lt;/td&gt;
&lt;td&gt;Tailwind CSS. It is the default standard for modern React/Next.js development.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Error Handling&lt;/td&gt;
&lt;td&gt;Master error.tsx for granular error boundaries and not-found.tsx for 404s.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deployment&lt;/td&gt;
&lt;td&gt;Vercel (the creators of Next.js, zero-config) or deploying via containerized pipelines to infrastructure like AWS ECS/Amplify depending on your cloud strategy.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>frontend</category>
      <category>javascript</category>
      <category>nextjs</category>
      <category>react</category>
    </item>
    <item>
      <title>Create React App is Dead. What’s Next? (Vite vs. Next.js)</title>
      <dc:creator>Dixon Gunasekara</dc:creator>
      <pubDate>Sat, 22 Aug 2026 03:49:15 +0000</pubDate>
      <link>https://dev.to/dixonaws/create-react-app-is-dead-whats-next-vite-vs-nextjs-2608</link>
      <guid>https://dev.to/dixonaws/create-react-app-is-dead-whats-next-vite-vs-nextjs-2608</guid>
      <description>&lt;p&gt;For years, &lt;code&gt;npx create-react-app my-app&lt;/code&gt; was the undisputed starting point for almost every React developer. It was the golden standard—a zero-configuration miracle that abstracted away the painful complexities of Webpack and Babel.&lt;/p&gt;

&lt;p&gt;But times have changed. As the web evolved, the tools needed to evolve with it. The React core team officially removed Create React App (CRA) from their recommended starting guides, signaling the end of an era. It was slow, bloated, and relied on aging bundler technology.&lt;/p&gt;

&lt;p&gt;So, if CRA is dead, what is the new standard? The React community has largely coalesced around two major players: Vite and Next.js.&lt;/p&gt;

&lt;p&gt;Here is a breakdown of what they are, how they differ, and which one we should choose for our next project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Did CRA Die?
&lt;/h2&gt;

&lt;p&gt;Before we look forward, let's briefly look back. Create React App fell out of favor for a few key reasons:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sluggish Performance&lt;/strong&gt;: CRA relied on Webpack. As our project grew, spinning up the local development server could take excruciatingly long seconds (or minutes).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lack of Flexibility&lt;/strong&gt;: It was a "black box." If we needed to tweak the underlying Webpack configuration, we had to &lt;code&gt;eject&lt;/code&gt;—a chaotic, one-way operation that exposed massive configuration files and ruined the simplicity CRA promised.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Client-Side Rendering (CSR) Only&lt;/strong&gt;: CRA only built Single Page Applications (SPAs). As SEO and initial page load speeds became paramount, the industry shifted toward Server-Side Rendering (SSR) and Static Site Generation (SSG)—features CRA didn't support natively.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Speed Demon: Vite
&lt;/h2&gt;

&lt;p&gt;Created by Evan You (the creator of Vue.js), Vite (French for "fast") is a build tool that aims to provide a significantly faster and leaner development experience for modern web projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it Works&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Unlike Webpack, which crawls our entire application and builds a massive bundle before serving it to the browser, Vite leverages native ES modules in the browser. It only compiles the code we are currently looking at. This means the development server starts almost instantly, regardless of our project's size, and Hot Module Replacement (HMR) is incredibly snappy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to Choose Vite&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Vite is the true spiritual successor to Create React App. If we want to build a traditional Client-Side Rendered (CSR) Single Page Application, Vite is our best bet.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Blazing Fast&lt;/strong&gt;: Near-instant dev server startup and HMR.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Framework Agnostic&lt;/strong&gt;: It supports React, Vue, Svelte, and vanilla JavaScript.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easy Configuration&lt;/strong&gt;: vite.config.js is highly customizable and much simpler than Webpack.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SEO Challenges&lt;/strong&gt;: Like CRA, it builds SPAs, which can be harder for search engines to index effectively without additional work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Backend Magic&lt;/strong&gt;: It is strictly a frontend build tool. We have to bring our own backend and routing solution (like React Router).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;How to start&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm create vite@latest my-app -- --template react&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Full-Stack Powerhouse: Next.js
&lt;/h2&gt;

&lt;p&gt;Built and maintained by Vercel, Next.js is a comprehensive React framework. It doesn't just bundle our code; it dictates an architecture for building robust, production-ready applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it Works&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next.js provides built-in solutions for routing, data fetching, and rendering. Its biggest selling point is its rendering flexibility. We can choose to render pages on the server (SSR), generate them statically at build time (SSG), or stick to traditional client-side rendering (CSR)—often mixing and matching these strategies within the same application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to Choose Next.js&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next.js is the heavy hitter. It is the go-to choice if we are building an e-commerce site, a blog, a SaaS product, or any application where SEO, initial load performance, and robust routing are critical.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Out-of-the-Box SEO&lt;/strong&gt;: Server-side rendering ensures search engines can read our content immediately.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File-Based Routing&lt;/strong&gt;: The App Router (or Pages Router) makes creating new routes as simple as adding a file to a directory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full-Stack Capabilities&lt;/strong&gt;: We can write serverless functions and API routes directly within our Next.js project.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Steeper Learning Curve&lt;/strong&gt;: We have to learn the "Next.js way" of doing things (caching, data fetching, routing), which is more complex than standard React.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Potential Overkill&lt;/strong&gt;: For a simple dashboard or internal tool, Next.js can be more architecture than our actually need.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;How to start&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx create-next-app@latest&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Verdict: Which Should We Choose?
&lt;/h2&gt;

&lt;p&gt;The decision ultimately comes down to the scope and requirements of our project.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;tbody&gt;
&lt;tr&gt;
    &lt;th&gt;Feature&lt;/th&gt;
    &lt;th&gt;Vite&lt;/th&gt;
    &lt;th&gt;Next.js&lt;/th&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Best For&lt;/td&gt;
    &lt;td&gt;Dashboards, Internal Tools, Simple SPAs&lt;/td&gt;
    &lt;td&gt;E-commerce, Blogs, SaaS, Public-facing Sites&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Primary Rendering&lt;/td&gt;
    &lt;td&gt;Client-Side (CSR)&lt;/td&gt;
    &lt;td&gt;Server-Side (SSR) / Static (SSG)&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Routing&lt;/td&gt;
    &lt;td&gt;Bring our own (e.g., React Router)&lt;/td&gt;
    &lt;td&gt;Built-in File-Based Routing&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;SEO Focus&lt;/td&gt;
    &lt;td&gt;Low&lt;/td&gt;
    &lt;td&gt;High&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Learning Curve&lt;/td&gt;
    &lt;td&gt;Low (Similar to standard React)&lt;/td&gt;
    &lt;td&gt;Medium to High&lt;/td&gt;
  &lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>react</category>
      <category>vite</category>
      <category>nextjs</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Kubernetes for Beginners</title>
      <dc:creator>Dixon Gunasekara</dc:creator>
      <pubDate>Wed, 19 Aug 2026 02:26:02 +0000</pubDate>
      <link>https://dev.to/dixonaws/kubernetes-for-beginners-2hga</link>
      <guid>https://dev.to/dixonaws/kubernetes-for-beginners-2hga</guid>
      <description>&lt;p&gt;&lt;strong&gt;1. Why was Kubernetes invented?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before Kubernetes, the way companies ran applications went through three major phases:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Physical Server Era&lt;/strong&gt;: Applications were run on physical hardware. If one app took up too much memory, other apps on that server would crash. It was expensive and wasteful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Virtual Machine (VM) Era&lt;/strong&gt;: To solve the hardware problem, VMs allowed to run multiple isolated "virtual" computers on one physical server. This was better, but VMs were heavy and slow to start because each one needed its own full operating system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Container Era (Docker)&lt;/strong&gt;: Developers realized they didn't need a whole operating system for every app. They created "containers"—lightweight, isolated packages containing just the app and what it needs to run.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Breaking Point&lt;/strong&gt;: Containers were brilliant, and companies started using them for everything. But suddenly, instead of managing 10 large VMs, a company had to manage 1,000 tiny containers. If a container crashed in the middle of the night, someone had to manually restart it. If a website went viral, someone had to manually start 50 more containers to handle the traffic. It became a logistical nightmare.&lt;/p&gt;

&lt;p&gt;Kubernetes was invented to be the automated "pilot" for the containers. &lt;/p&gt;

&lt;p&gt;It handles the things humans are too slow to do:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automated Scaling&lt;/strong&gt;: If the app suddenly gets a spike in traffic, Kubernetes automatically creates more containers to handle the load, then scales them back down to save money when traffic drops.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Self-Healing&lt;/strong&gt;:&lt;br&gt;
If a container crashes, the server dies, or a network drops, Kubernetes instantly notices and starts a replacement container somewhere else without a human having to intervene.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automated Rollouts&lt;/strong&gt;:&lt;br&gt;
It allows developers to release new versions of an application slowly, behind the scenes. If the new version has a bug, Kubernetes automatically rolls it back to the old one before users notice.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ultimately, Kubernetes was invented so developers could stop worrying about how their apps were running and get back to actually writing the code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The main two components of Kubernetes architecture&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Control Plane Node&lt;/strong&gt; (The Brain)&lt;br&gt;
The Control Plane is responsible for making global decisions about the cluster. It does not run our applications; it manages the machines that do. Its job is to maintain the desired state of the cluster, respond to events (like a node crashing), and schedule workloads.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Worker Node&lt;/strong&gt; (The Muscle)&lt;br&gt;
A Worker Node is the machine (virtual or physical) where our actual application workloads (Pods and Containers) are executed. Its sole job is to do what the Control Plane tells it to do and report back on its status.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In a production cluster, we will have many worker nodes to distribute the load and provide redundancy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. The components of the Kubernetes Control Plane&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;kube-apiserver&lt;/strong&gt; (The Front Door)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the only component that interacts directly with the user (via kubectl) and the only component that talks directly to the database (etcd).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Function&lt;/strong&gt;: It exposes the Kubernetes REST API. When we want to create, read, update, or delete any resource (like a Pod or a Deployment), we send that request here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security&lt;/strong&gt;: It acts as the gatekeeper. It handles authentication, authorization, and admission control.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scale&lt;/strong&gt;: It is designed to scale horizontally. In a highly available (HA) cluster, we will run multiple instances of the API server behind a load balancer.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;etcd&lt;/strong&gt; (The Source of Truth)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a consistent, highly-available, distributed key-value backing store.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Function&lt;/strong&gt;: It holds the entire state of our cluster. Every configuration, every secret, and the desired state of every application is saved here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The "Watch" Pattern&lt;/strong&gt;: etcd allows the API server to "watch" for changes. If a change occurs in the database, the API server is immediately notified, which then notifies the other control plane components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Crucial Rule&lt;/strong&gt;: No other component (not the scheduler, not the controllers, not the worker nodes) is allowed to query etcd directly. They all must ask the API server.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;kube-scheduler&lt;/strong&gt; (The Dispatcher)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When a new Pod is created in etcd, it doesn't have a node assigned to it yet. The scheduler's job is to find it a home.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Function&lt;/strong&gt;: It watches the API server for newly created Pods with no assigned node, and selects a healthy worker node for them to run on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Decision Making&lt;/strong&gt;: It doesn't pick nodes randomly. It runs a two-step process:&lt;/p&gt;

&lt;p&gt;-&amp;gt; &lt;strong&gt;Filtering&lt;/strong&gt;: It eliminates nodes that can't run the Pod (e.g., the node doesn't have enough RAM, or the Pod requires a GPU that the node lacks).&lt;br&gt;
   -&amp;gt; &lt;strong&gt;Scoring&lt;/strong&gt;: It ranks the remaining nodes to find the optimal placement (e.g., preferring a node that already has the required container image downloaded).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;kube-controller-manager&lt;/strong&gt; (The Enforcer)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is actually a single binary that compiles several distinct, infinite control loops (controllers) into one process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Function&lt;/strong&gt;: It continuously watches the current state of the cluster (via the API server) and compares it to the desired state (stored in etcd). If they don't match, it takes action to fix it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Examples of internal controllers&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;-&amp;gt; &lt;strong&gt;Node Controller&lt;/strong&gt;: Notices when a worker node goes offline and responds.&lt;/p&gt;

&lt;p&gt;-&amp;gt; &lt;strong&gt;ReplicaSet Controller&lt;/strong&gt;: Ensures the correct number of Pods are running for a given application.&lt;/p&gt;

&lt;p&gt;-&amp;gt; &lt;strong&gt;Job Controller&lt;/strong&gt;: Watches for Job objects (one-off tasks) and creates Pods to run those tasks to completion.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;cloud-controller-manager&lt;/strong&gt; (The Liaison - Optional)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If our cluster is running in the cloud (AWS, GCP, Azure), this component lets Kubernetes talk directly to the cloud provider's API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Function&lt;/strong&gt;: It separates cloud-specific control logic from the core Kubernetes code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Examples&lt;/strong&gt;: If we create a Kubernetes Service of type LoadBalancer, the cloud-controller-manager talks to AWS/GCP to actually spin up a physical load balancer resource in our cloud account and route traffic to our nodes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. The components of a Worker Node&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;kubelet&lt;/strong&gt; (The Node Captain)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The kubelet is the primary "agent" that runs on every single worker node in the cluster.&lt;/p&gt;

&lt;p&gt;-&amp;gt; &lt;strong&gt;The Job&lt;/strong&gt;: It constantly listens to the Control Plane's kube-apiserver for instructions. When the Scheduler assigns a Pod to its node, the kubelet is responsible for making sure the containers described in that Pod are actually running and healthy.&lt;/p&gt;

&lt;p&gt;-&amp;gt; &lt;strong&gt;The Watchdog&lt;/strong&gt;: It doesn't just start containers; it monitors them. If a container crashes, the kubelet tries to restart it based on its defined restart policy. It also continuously reports the node's health and resource usage (CPU/Memory) back to the Control Plane.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Container Runtime&lt;/strong&gt; (The Engine)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While the kubelet manages the concept of a Pod, it doesn't know how to actually run a container. That is the job of the Container Runtime.&lt;/p&gt;

&lt;p&gt;-&amp;gt; &lt;strong&gt;The Job&lt;/strong&gt;: It handles the low-level mechanics of pulling container images from a registry (like Docker Hub or AWS ECR), unpacking them, and running the isolated processes on the host operating system.&lt;/p&gt;

&lt;p&gt;-&amp;gt; &lt;strong&gt;Examples&lt;/strong&gt;: Kubernetes used to rely heavily on Docker, but today it uses runtimes that comply with the Container Runtime Interface (CRI), such as containerd or CRI-O.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;kube-proxy&lt;/strong&gt; (The Network Traffic Cop)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since Pods are constantly being created, destroyed, and moved around, their internal IP addresses are always changing. The kube-proxy ensures that network traffic still finds its way to the right place.&lt;/p&gt;

&lt;p&gt;-&amp;gt; &lt;strong&gt;The Job&lt;/strong&gt;: It runs on every node and maintains network rules (usually by manipulating iptables or IPVS on Linux).&lt;/p&gt;

&lt;p&gt;-&amp;gt; &lt;strong&gt;The Routing&lt;/strong&gt;: If an external request comes in for your web application, or if a backend service needs to talk to a database Pod on another node, kube-proxy ensures that the traffic is routed dynamically to the correct, currently active Pod, no matter which worker node it happens to be living on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Nodes vs Pods&lt;/strong&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhkcmn5jv83tqw2hf31ma.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%2Fhkcmn5jv83tqw2hf31ma.png" alt=" " width="800" height="668"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Node&lt;/strong&gt;&lt;br&gt;
-&amp;gt; A physical or virtual machine.&lt;br&gt;
-&amp;gt; The Cloud Provider (if managed K8s) or Cluster Admin.&lt;br&gt;
-&amp;gt; Long-lived.&lt;br&gt;
-&amp;gt; Gets a host IP on the internal network.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pod&lt;/strong&gt;&lt;br&gt;
-&amp;gt; An abstraction wrapping one or more containers.&lt;br&gt;
-&amp;gt; Kubernetes Control Plane (specifically the Scheduler).&lt;br&gt;
-&amp;gt; Short-lived / Ephemeral.&lt;br&gt;
-&amp;gt; Gets its own unique cluster-internal IP address.&lt;br&gt;
-&amp;gt; Many run on a single Node.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;6. ConfigMaps vs Secrets&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;ConfigMap&lt;/th&gt;
&lt;th&gt;Secret&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best for&lt;/td&gt;
&lt;td&gt;Non-sensitive data (URLs, port numbers, config files)&lt;/td&gt;
&lt;td&gt;Sensitive data (passwords, API keys, TLS certificates)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage Format&lt;/td&gt;
&lt;td&gt;Plain text&lt;/td&gt;
&lt;td&gt;Base64 encoded&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Size Limit&lt;/td&gt;
&lt;td&gt;1 MiB&lt;/td&gt;
&lt;td&gt;1 MiB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Volume Mount&lt;/td&gt;
&lt;td&gt;Standard disk storage&lt;/td&gt;
&lt;td&gt;tmpfs (RAM-backed filesystem, never hits disk)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;7. Full Architecture of the Production Kubernetes Cluster&lt;/strong&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9ply0ji2jbqgjdrzbtqv.jpeg" 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%2F9ply0ji2jbqgjdrzbtqv.jpeg" alt=" " width="799" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>docker</category>
    </item>
    <item>
      <title>How to Track Configuration Changes and Compliance of AWS Resources</title>
      <dc:creator>Dixon Gunasekara</dc:creator>
      <pubDate>Sun, 16 Mar 2025 12:24:48 +0000</pubDate>
      <link>https://dev.to/dixonaws/how-to-track-configuration-changes-and-compliance-of-aws-resources-h44</link>
      <guid>https://dev.to/dixonaws/how-to-track-configuration-changes-and-compliance-of-aws-resources-h44</guid>
      <description>&lt;p&gt;&lt;strong&gt;AWS Config&lt;/strong&gt; is the most comprehensive service for tracking configuration changes and compliance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resource Configuration Tracking:&lt;/strong&gt; Monitors and records configurations of supported AWS resources over time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Change History:&lt;/strong&gt; Stores historical configuration data and changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compliance Auditing:&lt;/strong&gt; Uses Config Rules to assess compliance with desired configurations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automatic Remediation:&lt;/strong&gt; Triggers AWS Systems Manager Automation to correct non-compliant resources.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Setup Steps:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, go to AWS Config. If it's not enabled, it will be shown as bellow. Hit &lt;strong&gt;Get started&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%2Fwvcczoev46w79z3uwg3y.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%2Fwvcczoev46w79z3uwg3y.png" alt=" " width="800" height="363"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Then, we get into the first step and we have to select &lt;strong&gt;Recording strategy&lt;/strong&gt;. There are two options from which one should be selected. I'm selecting the first option (All resource types with customisable overrides).&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;All resource types with customisable overrides&lt;/li&gt;
&lt;li&gt;Specific resource type&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When selecting one out of these two, we should consider our use case and the pricing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Next, we have to select &lt;strong&gt;Recording frequency&lt;/strong&gt;. Here also, there are two options from which one should be selected. Here also, I'm selecting the first option (Continuous recording).&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Continuous recording&lt;/li&gt;
&lt;li&gt;Daily recording&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When selecting one out of these two, we should consider our use case and the pricing.&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%2F4xl0wm6158p4sblf7v4z.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%2F4xl0wm6158p4sblf7v4z.png" alt=" " width="799" height="259"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Then, we have the option &lt;strong&gt;Override settings&lt;/strong&gt; where we can override settings. By default, we get one override as shown in the bellow. According to our use case we can remove it or add more.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, we can select existing role or let to create a new role for this service. It's under &lt;strong&gt;Data governance&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, we can select an existing s3 bucket or let to create a new s3 bucket for storing configuration history and snapshots. It's under &lt;strong&gt;Delivery channel&lt;/strong&gt;.&lt;/p&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%2F47qhmbpfoxxokckk0ef0.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%2F47qhmbpfoxxokckk0ef0.png" alt=" " width="800" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Then, we have optional setting to set up SNS topic.&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%2F8rgkxm1x6ys1l8fsedyz.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%2F8rgkxm1x6ys1l8fsedyz.png" alt=" " width="800" height="76"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;I'm not selecting a SNS topic here and hit &lt;strong&gt;Next&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, we come into the second step, where we have to Rules. I'm selecting restricted-ssh rule which is an AWS managed rule. However, We can create Custom Rules using AWS Lambda for specific use cases.&lt;/p&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%2F9cix7d5pjtoff9l2iunw.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%2F9cix7d5pjtoff9l2iunw.png" alt=" " width="799" height="182"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Then, hit the &lt;strong&gt;Next&lt;/strong&gt; and we come into the third step where we can review. If everything is fine, we can hit &lt;strong&gt;Confirm&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%2Fb1o4fcar8cj0nacrufza.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%2Fb1o4fcar8cj0nacrufza.png" alt=" " width="800" height="335"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Next, it will be shown as bellow.&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%2F6nuc2go0x3ti83flx40w.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%2F6nuc2go0x3ti83flx40w.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For my account currently, there are no noncompliant rules or resources. Therefore, I'm launch an EC2 instance allowing SSH access from any IP.&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%2F9ob4m0tyobfl37e3rxwk.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%2F9ob4m0tyobfl37e3rxwk.png" alt=" " width="799" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Next, again check AWS config dashboard. If it's same as it was earlier, refresh after some time. Then, we'll be able to see it like this. Note that now we can see that there are one noncompliant rule and one noncompliant resource.&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%2Fpv5xt72xwr94wo7gavde.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%2Fpv5xt72xwr94wo7gavde.png" alt=" " width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We can use Aggregators to collect data across multiple accounts/regions (if we're using AWS Organizations).&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>security</category>
      <category>monitoring</category>
    </item>
  </channel>
</rss>
