<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:hashnode="https://hashnode.com/rss"><channel><title><![CDATA[Maxat Akbanov's blog]]></title><description><![CDATA[Maxat Akbanov devops sysops systems engineering cybersecurity software engineering amazon web services aws linux kubernetes containers docker terraform]]></description><link>https://maxat-akbanov.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1706901955708/0IxOYElpi.png</url><title>Maxat Akbanov&apos;s blog</title><link>https://maxat-akbanov.com</link></image><generator>RSS for Node</generator><lastBuildDate>Tue, 03 Dec 2024 08:37:43 GMT</lastBuildDate><atom:link href="https://maxat-akbanov.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><atom:link rel="next" href="https://maxat-akbanov.com/rss.xml?page=2"/><atom:link rel="previous" href="https://maxat-akbanov.com/rss.xml"/><item><title><![CDATA[Linux Namespaces and cgroups: Building Blocks of Modern Containerization]]></title><description><![CDATA[Linux Namespaces and cgroups: Building Blocks of Modern Containerization]]></description><link>https://maxat-akbanov.com/linux-namespaces-and-cgroups-building-blocks-of-modern-containerization</link><guid isPermaLink="true">https://maxat-akbanov.com/linux-namespaces-and-cgroups-building-blocks-of-modern-containerization</guid><category><![CDATA[Devops]]></category><category><![CDATA[Linux]]></category><category><![CDATA[containers]]></category><category><![CDATA[containerization]]></category><category><![CDATA[#namespaces]]></category><category><![CDATA[cgroups]]></category><category><![CDATA[sysops]]></category><category><![CDATA[System administration]]></category><dc:creator><![CDATA[Maxat Akbanov]]></dc:creator><pubDate>Fri, 29 Nov 2024 18:37:13 GMT</pubDate><content:encoded>&lt;![CDATA[&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Linux_namespaces&quot;&gt;&lt;strong&gt;Linux&lt;/strong&gt; &lt;strong&gt;namespaces&lt;/strong&gt;&lt;/a&gt; and &lt;a target=&quot;_blank&quot; href=&quot;https://docs.kernel.org/admin-guide/cgroup-v2.html&quot;&gt;&lt;strong&gt;cgroups&lt;/strong&gt; (&lt;strong&gt;control groups&lt;/strong&gt;)&lt;/a&gt; are foundational Linux kernel features used to provide process isolation and resource management. They are core components of containerization technologies like &lt;a target=&quot;_blank&quot; href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt;, &lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/&quot;&gt;Kubernetes&lt;/a&gt;, &lt;a target=&quot;_blank&quot; href=&quot;https://podman.io/&quot;&gt;Podman&lt;/a&gt; and other orchestration platforms.&lt;/p&gt;&lt;div data-node-type=&quot;callout&quot;&gt;&lt;div data-node-type=&quot;callout-emoji&quot;&gt;💡&lt;/div&gt;&lt;div data-node-type=&quot;callout-text&quot;&gt;According to the &lt;a target=&quot;_self&quot; href=&quot;https://docs.kernel.org/admin-guide/cgroup-v2.html&quot;&gt;official documentation of Control Group v2&lt;/a&gt; - &lt;strong&gt;cgroup&lt;/strong&gt; is never capitalized. The singular form is used to designate the whole feature and also as a qualifier as in cgroup controllers. When explicitly referring to multiple individual control groups, the plural form cgroups is used.&lt;/div&gt;&lt;/div&gt;&lt;p&gt;These features were first introduced into Linux kernel back in 2002. However, the real container support was added into Linux kernel in 2013.&lt;/p&gt;&lt;h3 id=&quot;heading-linux-namespaces&quot;&gt;&lt;strong&gt;Linux Namespaces&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;According to &lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Linux_namespaces&quot;&gt;Wikipedia&lt;/a&gt;, &lt;strong&gt;Linux namespaces&lt;/strong&gt;:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;are a feature of the Linux kernel that partition kernel resources such that one set of processes sees one set of resources, while another set of processes sees a different set of resources.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;By resources Linux kernel sees as &lt;strong&gt;process IDs&lt;/strong&gt;, &lt;strong&gt;hostnames&lt;/strong&gt;, &lt;strong&gt;user IDs&lt;/strong&gt;, &lt;strong&gt;file names&lt;/strong&gt;, some &lt;strong&gt;names associated with network access&lt;/strong&gt;, and &lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Inter-process_communication&quot;&gt;&lt;strong&gt;Inter-process communication&lt;/strong&gt;.&lt;/a&gt;&lt;/p&gt;&lt;h3 id=&quot;heading-types-of-namespaces&quot;&gt;&lt;strong&gt;Types of Namespaces&lt;/strong&gt;&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;mnt&lt;/code&gt; (&lt;a target=&quot;_blank&quot; href=&quot;https://man7.org/linux/man-pages/man7/mount_namespaces.7.html&quot;&gt;Mount Namespace&lt;/a&gt;):&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Isolates the file system mount points.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Processes in different mount namespaces can have different views of the file system hierarchy.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;pid&lt;/code&gt; (&lt;a target=&quot;_blank&quot; href=&quot;https://man7.org/linux/man-pages/man7/pid_namespaces.7.html&quot;&gt;Process ID Namespace&lt;/a&gt;):&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Isolates the process ID number space.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Processes in a PID namespace see a separate set of process IDs, starting at 1 for the init process of that namespace.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;net&lt;/code&gt; (&lt;a target=&quot;_blank&quot; href=&quot;https://man7.org/linux/man-pages/man7/network_namespaces.7.html&quot;&gt;Network Namespace&lt;/a&gt;):&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Isolates network-related resources like network interfaces, routing tables, and IP addresses.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Each namespace can have its own network stack.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;ipc&lt;/code&gt; (&lt;a target=&quot;_blank&quot; href=&quot;https://man7.org/linux/man-pages/man7/ipc_namespaces.7.html&quot;&gt;Inter-Process Communication Namespace&lt;/a&gt;):&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Isolates IPC resources such as shared memory, semaphores, and message queues.&lt;/p&gt;  &lt;div data-node-type=&quot;callout&quot;&gt;  &lt;div data-node-type=&quot;callout-emoji&quot;&gt;💡&lt;/div&gt;  &lt;div data-node-type=&quot;callout-text&quot;&gt;To learn more about IPC, check out this video: &lt;a target=&quot;_self&quot; href=&quot;https://www.youtube.com/watch?v=BU9m45WWqjM&quot;&gt;&lt;strong&gt;Linux Internals: Interprocess Communication&lt;/strong&gt;&lt;/a&gt;&lt;/div&gt;  &lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;uts&lt;/code&gt; (&lt;a target=&quot;_blank&quot; href=&quot;https://man7.org/linux/man-pages/man7/uts_namespaces.7.html&quot;&gt;UNIX Timesharing System Namespace&lt;/a&gt;):&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Isolates hostname and domain name.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Allows containers to have their own hostname.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;As a result, it allows a single system to appear to have different host and domain names to different processes.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;user&lt;/code&gt; (&lt;a target=&quot;_blank&quot; href=&quot;https://man7.org/linux/man-pages/man7/user_namespaces.7.html&quot;&gt;User Namespace&lt;/a&gt;):&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Isolates user and group IDs.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Processes in a user namespace can have a different set of user IDs, including root privileges, without affecting the host system. The first process created in a new namespace has PID 1 and child processes are assigned subsequent PIDs. If a child process is created with its own PID namespace, it has PID 1 in that namespace as well as its PID in the parent process namespace.&lt;/p&gt;&lt;p&gt;  &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1732876486695/0717ccb9-8773-4260-8039-1c7f4393e1a3.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;  Image credits: &lt;a target=&quot;_blank&quot; href=&quot;https://blog.nginx.org/blog/what-are-namespaces-cgroups-how-do-they-work&quot;&gt;blog.nginx.org&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;hr /&gt;&lt;h3 id=&quot;heading-namespace-example&quot;&gt;&lt;strong&gt;Namespace Example&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;To create a namespace for isolating the process ID space:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;unshare --user --pid --map-root-user --mount-proc --fork bash&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This command creates a new namespace with its own user and PID namespaces.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;--map-root-user&lt;/code&gt; - maps the root user to the new namespace. The user in new namespace will have root permissions&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;--mount-proc&lt;/code&gt; - mounts a new proc filesystem&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;--fork&lt;/code&gt; - ensures that a new process is started immediately in the newly created namespace(s), separating it from the parent process&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;bash&lt;/code&gt; - run the &lt;code&gt;bash&lt;/code&gt; command as the new process in the newly created namespace&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;As you can see, the new namespace only sees its own processes:&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1732877119916/a96711bf-d732-41b7-8525-1624c7f6673e.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;hr /&gt;&lt;h3 id=&quot;heading-linux-control-groups-cgroups&quot;&gt;&lt;strong&gt;Linux Control Groups (cgroups)&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;cgroups&lt;/strong&gt; provide resource management by allowing you to allocate, prioritize, deny, or limit system resources (CPU, memory, disk I/O, etc.) for processes. The official definition is:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;cgroup - is a mechanism to organize processes hierarchically and distribute system resources along the hierarchy in a controlled and configurable manner.&lt;/p&gt;&lt;/blockquote&gt;&lt;h4 id=&quot;heading-key-features&quot;&gt;&lt;strong&gt;Key Features&lt;/strong&gt;&lt;/h4&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resource Limiting&lt;/strong&gt;:&lt;/p&gt;&lt;p&gt; You can configure cgroup to set limits on CPU, memory, disk I/O, and network bandwidth a process can use.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Prioritization&lt;/strong&gt;:&lt;/p&gt;&lt;p&gt; You can control how much of a resource (CPU, disk, or network) a process can use compared to processes in another cgroup when there is resource contention.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Accounting&lt;/strong&gt;:&lt;/p&gt;&lt;p&gt; Track resource usage of processes or groups of processes at the cgroup level&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Control&lt;/strong&gt;:&lt;/p&gt;&lt;p&gt; Change the status (freeze, stopped, or restarted) of processes or terminate groups of processes.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h4 id=&quot;heading-hierarchy-and-controllers&quot;&gt;&lt;strong&gt;Hierarchy and Controllers&lt;/strong&gt;&lt;/h4&gt;&lt;p&gt;&lt;em&gt;cgroups&lt;/em&gt; is largely composed of two parts - the core and controllers. &lt;em&gt;cgroup core&lt;/em&gt; is primarily responsible for hierarchically organizing processes. A &lt;em&gt;cgroup controller&lt;/em&gt; is usually responsible for distributing a specific type of system resource along the hierarchy although there are controllers which can serve purposes other than resource distribution.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Limits CPU usage.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Limits memory usage and manages swapping behavior.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Controls block device I/O.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Tags network packets for Quality of Service (QoS).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Manages access to device nodes.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;So basically you use cgroups to control how much of a given key resource (CPU, memory, network, and disk I/O) can be accessed or used by a process or set of processes. Cgroups are a key component of containers because there are often multiple processes running in a container that you need to control together. In a Kubernetes environment, cgroups can be used to implement resource requests and limits and corresponding QoS classes at the pod level.&lt;/p&gt;&lt;p&gt;The following diagram illustrates how when you allocate a particular percentage of available system resources to a cgroup (in this case &lt;strong&gt;cgroup1&lt;/strong&gt;), the remaining percentage is available to other cgroups (and individual processes) on the system.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1732877886113/6b679fef-d57e-41af-94e9-52f734055389.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;Image credits: &lt;a target=&quot;_blank&quot; href=&quot;https://blog.nginx.org/blog/what-are-namespaces-cgroups-how-do-they-work&quot;&gt;blog.nginx.org&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;h4 id=&quot;heading-practical-example-of-using-cgroup&quot;&gt;&lt;strong&gt;Practical example of using cgroup&lt;/strong&gt;&lt;/h4&gt;&lt;p&gt;Heres an example of the script to create a cgroup, limit CPU usage to 50%, and validate the behavior of the restricted process.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;#!/bin/bash&lt;/span&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Define variables&lt;/span&gt;CGROUP_NAME=&lt;span class=&quot;hljs-string&quot;&gt;&quot;my_cgroup&quot;&lt;/span&gt;CGROUP_PATH=&lt;span class=&quot;hljs-string&quot;&gt;&quot;/sys/fs/cgroup/cpu/&lt;span class=&quot;hljs-variable&quot;&gt;$CGROUP_NAME&lt;/span&gt;&quot;&lt;/span&gt;CPU_LIMIT=50000       &lt;span class=&quot;hljs-comment&quot;&gt;# 50% CPU usage (quota in microseconds)&lt;/span&gt;CPU_PERIOD=100000     &lt;span class=&quot;hljs-comment&quot;&gt;# Period in microseconds (default is 100ms)&lt;/span&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Step 1: Create a new cgroup&lt;/span&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Creating cgroup at &lt;span class=&quot;hljs-variable&quot;&gt;$CGROUP_PATH&lt;/span&gt;...&quot;&lt;/span&gt;mkdir -p &lt;span class=&quot;hljs-variable&quot;&gt;$CGROUP_PATH&lt;/span&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Step 2: Set CPU usage limits&lt;/span&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Setting CPU limits...&quot;&lt;/span&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;$CPU_LIMIT&lt;/span&gt; &amp;gt; &lt;span class=&quot;hljs-variable&quot;&gt;$CGROUP_PATH&lt;/span&gt;/cpu.cfs_quota_us&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;$CPU_PERIOD&lt;/span&gt; &amp;gt; &lt;span class=&quot;hljs-variable&quot;&gt;$CGROUP_PATH&lt;/span&gt;/cpu.cfs_period_us&lt;span class=&quot;hljs-comment&quot;&gt;# Step 3: Launch a process to test the CPU limit&lt;/span&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Starting a CPU-intensive process (infinite loop)...&quot;&lt;/span&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Launch a background CPU-intensive process&lt;/span&gt;bash -c &lt;span class=&quot;hljs-string&quot;&gt;&quot;while :; do :; done&quot;&lt;/span&gt; &amp;amp;PROCESS_PID=$!&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Process started with PID &lt;span class=&quot;hljs-variable&quot;&gt;$PROCESS_PID&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Step 4: Add the process to the cgroup&lt;/span&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Adding process &lt;span class=&quot;hljs-variable&quot;&gt;$PROCESS_PID&lt;/span&gt; to cgroup...&quot;&lt;/span&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;$PROCESS_PID&lt;/span&gt; &amp;gt; &lt;span class=&quot;hljs-variable&quot;&gt;$CGROUP_PATH&lt;/span&gt;/cgroup.procs&lt;span class=&quot;hljs-comment&quot;&gt;# Step 5: Monitor CPU usage for the process&lt;/span&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Monitoring CPU usage (press Ctrl+C to exit)...&quot;&lt;/span&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;; &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;    CPU_USAGE=$(ps -p &lt;span class=&quot;hljs-variable&quot;&gt;$PROCESS_PID&lt;/span&gt; -o %cpu=)    &lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;CPU Usage of PID &lt;span class=&quot;hljs-variable&quot;&gt;$PROCESS_PID&lt;/span&gt;: &lt;span class=&quot;hljs-variable&quot;&gt;$CPU_USAGE&lt;/span&gt;%&quot;&lt;/span&gt;    sleep 2&lt;span class=&quot;hljs-keyword&quot;&gt;done&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Execute the script:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;sudo ./cgroup.sh&lt;/code&gt;&lt;/pre&gt;&lt;hr /&gt;&lt;p&gt;&lt;strong&gt;Explanation of the Script&lt;/strong&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create a cgroup&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The script creates a directory in &lt;code&gt;/sys/fs/cgroup/cpu/&lt;/code&gt; for the new cgroup.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Set CPU limits&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/6/html/resource_management_guide/sec-cpu#sect-cfs:~:text=is%201000%20microseconds.-,cpu.cfs_quota_us,-specifies%20the%20total&quot;&gt;&lt;code&gt;cpu.cfs_quota_us&lt;/code&gt;&lt;/a&gt;: Specifies the total time (in microseconds) the cgroup is allowed to run on the CPU within each &lt;code&gt;cpu.cfs_period_us&lt;/code&gt; period.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/6/html/resource_management_guide/sec-cpu#sect-cfs:~:text=Enforcement%20Tunable%20Parameters-,cpu.cfs_period_us,-specifies%20a%20period&quot;&gt;&lt;code&gt;cpu.cfs_period_us&lt;/code&gt;&lt;/a&gt;: Defines the time period (in microseconds) used to calculate CPU quotas. Default is 1000 microseconds.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Run a CPU-intensive process&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;An infinite loop (&lt;code&gt;while :; do :; done&lt;/code&gt;) generates a CPU load for testing.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Assign the process to the cgroup&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The script uses &lt;code&gt;echo $PROCESS_PID &amp;gt; $CGROUP_PATH/cgroup.procs&lt;/code&gt; to attach the process to the cgroup.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Monitor the CPU usage&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The &lt;code&gt;ps&lt;/code&gt; command checks the process&apos;s CPU usage percentage in real time.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;strong&gt;Observe the CPU Usage&lt;/strong&gt;:&lt;/p&gt;&lt;p&gt;The script displays the CPU usage of the process every 2 seconds. The &lt;code&gt;%CPU&lt;/code&gt; value should not exceed 50%, confirming the limitation.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1732904555363/8cca7a07-244f-455e-8dc6-f351bfe06cc4.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;hr /&gt;&lt;h3 id=&quot;heading-summary-table-for-namespaces-vs-cgroups&quot;&gt;&lt;strong&gt;Summary table for namespaces vs. cgroups&lt;/strong&gt;&lt;/h3&gt;&lt;div class=&quot;hn-table&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;td&gt;Feature&lt;/td&gt;&lt;td&gt;Namespaces&lt;/td&gt;&lt;td&gt;cgroups&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Purpose&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Isolates system resources.&lt;/td&gt;&lt;td&gt;Manages and limits resource usage.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Scope&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Provides isolation.&lt;/td&gt;&lt;td&gt;Provides control and accounting.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Examples&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Process ID, filesystem, network.&lt;/td&gt;&lt;td&gt;CPU, memory, disk I/O.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Use Case&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Container isolation.&lt;/td&gt;&lt;td&gt;Resource allocation for containers.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;h3 id=&quot;heading-references&quot;&gt;References:&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://blog.nginx.org/blog/what-are-namespaces-cgroups-how-do-they-work&quot;&gt;Nginx Blog: What Are Namespaces and cgroups, and How Do They Work?&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://github.com/Brain2life/bash-cookbook/tree/main/linux-namespaces-cgroups&quot;&gt;https://github.com/Brain2life/bash-cookbook/tree/main/linux-namespaces-cgroups&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://man7.org/linux/man-pages/man7/namespaces.7.html&quot;&gt;Linux man7 page: Namespaces&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://man7.org/linux/man-pages/man7/cgroups.7.html&quot;&gt;Linux man7 page: cgroups&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/6/html/resource_management_guide/sec-cpu#sec-cpu&quot;&gt;CPU cgroup tunable parametes&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;]]&gt;</content:encoded><hashnode:content>&lt;![CDATA[&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Linux_namespaces&quot;&gt;&lt;strong&gt;Linux&lt;/strong&gt; &lt;strong&gt;namespaces&lt;/strong&gt;&lt;/a&gt; and &lt;a target=&quot;_blank&quot; href=&quot;https://docs.kernel.org/admin-guide/cgroup-v2.html&quot;&gt;&lt;strong&gt;cgroups&lt;/strong&gt; (&lt;strong&gt;control groups&lt;/strong&gt;)&lt;/a&gt; are foundational Linux kernel features used to provide process isolation and resource management. They are core components of containerization technologies like &lt;a target=&quot;_blank&quot; href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt;, &lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/&quot;&gt;Kubernetes&lt;/a&gt;, &lt;a target=&quot;_blank&quot; href=&quot;https://podman.io/&quot;&gt;Podman&lt;/a&gt; and other orchestration platforms.&lt;/p&gt;&lt;div data-node-type=&quot;callout&quot;&gt;&lt;div data-node-type=&quot;callout-emoji&quot;&gt;💡&lt;/div&gt;&lt;div data-node-type=&quot;callout-text&quot;&gt;According to the &lt;a target=&quot;_self&quot; href=&quot;https://docs.kernel.org/admin-guide/cgroup-v2.html&quot;&gt;official documentation of Control Group v2&lt;/a&gt; - &lt;strong&gt;cgroup&lt;/strong&gt; is never capitalized. The singular form is used to designate the whole feature and also as a qualifier as in cgroup controllers. When explicitly referring to multiple individual control groups, the plural form cgroups is used.&lt;/div&gt;&lt;/div&gt;&lt;p&gt;These features were first introduced into Linux kernel back in 2002. However, the real container support was added into Linux kernel in 2013.&lt;/p&gt;&lt;h3 id=&quot;heading-linux-namespaces&quot;&gt;&lt;strong&gt;Linux Namespaces&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;According to &lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Linux_namespaces&quot;&gt;Wikipedia&lt;/a&gt;, &lt;strong&gt;Linux namespaces&lt;/strong&gt;:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;are a feature of the Linux kernel that partition kernel resources such that one set of processes sees one set of resources, while another set of processes sees a different set of resources.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;By resources Linux kernel sees as &lt;strong&gt;process IDs&lt;/strong&gt;, &lt;strong&gt;hostnames&lt;/strong&gt;, &lt;strong&gt;user IDs&lt;/strong&gt;, &lt;strong&gt;file names&lt;/strong&gt;, some &lt;strong&gt;names associated with network access&lt;/strong&gt;, and &lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Inter-process_communication&quot;&gt;&lt;strong&gt;Inter-process communication&lt;/strong&gt;.&lt;/a&gt;&lt;/p&gt;&lt;h3 id=&quot;heading-types-of-namespaces&quot;&gt;&lt;strong&gt;Types of Namespaces&lt;/strong&gt;&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;mnt&lt;/code&gt; (&lt;a target=&quot;_blank&quot; href=&quot;https://man7.org/linux/man-pages/man7/mount_namespaces.7.html&quot;&gt;Mount Namespace&lt;/a&gt;):&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Isolates the file system mount points.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Processes in different mount namespaces can have different views of the file system hierarchy.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;pid&lt;/code&gt; (&lt;a target=&quot;_blank&quot; href=&quot;https://man7.org/linux/man-pages/man7/pid_namespaces.7.html&quot;&gt;Process ID Namespace&lt;/a&gt;):&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Isolates the process ID number space.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Processes in a PID namespace see a separate set of process IDs, starting at 1 for the init process of that namespace.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;net&lt;/code&gt; (&lt;a target=&quot;_blank&quot; href=&quot;https://man7.org/linux/man-pages/man7/network_namespaces.7.html&quot;&gt;Network Namespace&lt;/a&gt;):&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Isolates network-related resources like network interfaces, routing tables, and IP addresses.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Each namespace can have its own network stack.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;ipc&lt;/code&gt; (&lt;a target=&quot;_blank&quot; href=&quot;https://man7.org/linux/man-pages/man7/ipc_namespaces.7.html&quot;&gt;Inter-Process Communication Namespace&lt;/a&gt;):&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Isolates IPC resources such as shared memory, semaphores, and message queues.&lt;/p&gt;  &lt;div data-node-type=&quot;callout&quot;&gt;  &lt;div data-node-type=&quot;callout-emoji&quot;&gt;💡&lt;/div&gt;  &lt;div data-node-type=&quot;callout-text&quot;&gt;To learn more about IPC, check out this video: &lt;a target=&quot;_self&quot; href=&quot;https://www.youtube.com/watch?v=BU9m45WWqjM&quot;&gt;&lt;strong&gt;Linux Internals: Interprocess Communication&lt;/strong&gt;&lt;/a&gt;&lt;/div&gt;  &lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;uts&lt;/code&gt; (&lt;a target=&quot;_blank&quot; href=&quot;https://man7.org/linux/man-pages/man7/uts_namespaces.7.html&quot;&gt;UNIX Timesharing System Namespace&lt;/a&gt;):&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Isolates hostname and domain name.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Allows containers to have their own hostname.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;As a result, it allows a single system to appear to have different host and domain names to different processes.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;user&lt;/code&gt; (&lt;a target=&quot;_blank&quot; href=&quot;https://man7.org/linux/man-pages/man7/user_namespaces.7.html&quot;&gt;User Namespace&lt;/a&gt;):&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Isolates user and group IDs.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Processes in a user namespace can have a different set of user IDs, including root privileges, without affecting the host system. The first process created in a new namespace has PID 1 and child processes are assigned subsequent PIDs. If a child process is created with its own PID namespace, it has PID 1 in that namespace as well as its PID in the parent process namespace.&lt;/p&gt;&lt;p&gt;  &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1732876486695/0717ccb9-8773-4260-8039-1c7f4393e1a3.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;  Image credits: &lt;a target=&quot;_blank&quot; href=&quot;https://blog.nginx.org/blog/what-are-namespaces-cgroups-how-do-they-work&quot;&gt;blog.nginx.org&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;hr /&gt;&lt;h3 id=&quot;heading-namespace-example&quot;&gt;&lt;strong&gt;Namespace Example&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;To create a namespace for isolating the process ID space:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;unshare --user --pid --map-root-user --mount-proc --fork bash&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This command creates a new namespace with its own user and PID namespaces.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;--map-root-user&lt;/code&gt; - maps the root user to the new namespace. The user in new namespace will have root permissions&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;--mount-proc&lt;/code&gt; - mounts a new proc filesystem&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;--fork&lt;/code&gt; - ensures that a new process is started immediately in the newly created namespace(s), separating it from the parent process&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;bash&lt;/code&gt; - run the &lt;code&gt;bash&lt;/code&gt; command as the new process in the newly created namespace&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;As you can see, the new namespace only sees its own processes:&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1732877119916/a96711bf-d732-41b7-8525-1624c7f6673e.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;hr /&gt;&lt;h3 id=&quot;heading-linux-control-groups-cgroups&quot;&gt;&lt;strong&gt;Linux Control Groups (cgroups)&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;cgroups&lt;/strong&gt; provide resource management by allowing you to allocate, prioritize, deny, or limit system resources (CPU, memory, disk I/O, etc.) for processes. The official definition is:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;cgroup - is a mechanism to organize processes hierarchically and distribute system resources along the hierarchy in a controlled and configurable manner.&lt;/p&gt;&lt;/blockquote&gt;&lt;h4 id=&quot;heading-key-features&quot;&gt;&lt;strong&gt;Key Features&lt;/strong&gt;&lt;/h4&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resource Limiting&lt;/strong&gt;:&lt;/p&gt;&lt;p&gt; You can configure cgroup to set limits on CPU, memory, disk I/O, and network bandwidth a process can use.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Prioritization&lt;/strong&gt;:&lt;/p&gt;&lt;p&gt; You can control how much of a resource (CPU, disk, or network) a process can use compared to processes in another cgroup when there is resource contention.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Accounting&lt;/strong&gt;:&lt;/p&gt;&lt;p&gt; Track resource usage of processes or groups of processes at the cgroup level&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Control&lt;/strong&gt;:&lt;/p&gt;&lt;p&gt; Change the status (freeze, stopped, or restarted) of processes or terminate groups of processes.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h4 id=&quot;heading-hierarchy-and-controllers&quot;&gt;&lt;strong&gt;Hierarchy and Controllers&lt;/strong&gt;&lt;/h4&gt;&lt;p&gt;&lt;em&gt;cgroups&lt;/em&gt; is largely composed of two parts - the core and controllers. &lt;em&gt;cgroup core&lt;/em&gt; is primarily responsible for hierarchically organizing processes. A &lt;em&gt;cgroup controller&lt;/em&gt; is usually responsible for distributing a specific type of system resource along the hierarchy although there are controllers which can serve purposes other than resource distribution.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Limits CPU usage.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Limits memory usage and manages swapping behavior.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Controls block device I/O.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Tags network packets for Quality of Service (QoS).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Manages access to device nodes.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;So basically you use cgroups to control how much of a given key resource (CPU, memory, network, and disk I/O) can be accessed or used by a process or set of processes. Cgroups are a key component of containers because there are often multiple processes running in a container that you need to control together. In a Kubernetes environment, cgroups can be used to implement resource requests and limits and corresponding QoS classes at the pod level.&lt;/p&gt;&lt;p&gt;The following diagram illustrates how when you allocate a particular percentage of available system resources to a cgroup (in this case &lt;strong&gt;cgroup1&lt;/strong&gt;), the remaining percentage is available to other cgroups (and individual processes) on the system.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1732877886113/6b679fef-d57e-41af-94e9-52f734055389.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;Image credits: &lt;a target=&quot;_blank&quot; href=&quot;https://blog.nginx.org/blog/what-are-namespaces-cgroups-how-do-they-work&quot;&gt;blog.nginx.org&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;h4 id=&quot;heading-practical-example-of-using-cgroup&quot;&gt;&lt;strong&gt;Practical example of using cgroup&lt;/strong&gt;&lt;/h4&gt;&lt;p&gt;Heres an example of the script to create a cgroup, limit CPU usage to 50%, and validate the behavior of the restricted process.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;#!/bin/bash&lt;/span&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Define variables&lt;/span&gt;CGROUP_NAME=&lt;span class=&quot;hljs-string&quot;&gt;&quot;my_cgroup&quot;&lt;/span&gt;CGROUP_PATH=&lt;span class=&quot;hljs-string&quot;&gt;&quot;/sys/fs/cgroup/cpu/&lt;span class=&quot;hljs-variable&quot;&gt;$CGROUP_NAME&lt;/span&gt;&quot;&lt;/span&gt;CPU_LIMIT=50000       &lt;span class=&quot;hljs-comment&quot;&gt;# 50% CPU usage (quota in microseconds)&lt;/span&gt;CPU_PERIOD=100000     &lt;span class=&quot;hljs-comment&quot;&gt;# Period in microseconds (default is 100ms)&lt;/span&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Step 1: Create a new cgroup&lt;/span&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Creating cgroup at &lt;span class=&quot;hljs-variable&quot;&gt;$CGROUP_PATH&lt;/span&gt;...&quot;&lt;/span&gt;mkdir -p &lt;span class=&quot;hljs-variable&quot;&gt;$CGROUP_PATH&lt;/span&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Step 2: Set CPU usage limits&lt;/span&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Setting CPU limits...&quot;&lt;/span&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;$CPU_LIMIT&lt;/span&gt; &amp;gt; &lt;span class=&quot;hljs-variable&quot;&gt;$CGROUP_PATH&lt;/span&gt;/cpu.cfs_quota_us&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;$CPU_PERIOD&lt;/span&gt; &amp;gt; &lt;span class=&quot;hljs-variable&quot;&gt;$CGROUP_PATH&lt;/span&gt;/cpu.cfs_period_us&lt;span class=&quot;hljs-comment&quot;&gt;# Step 3: Launch a process to test the CPU limit&lt;/span&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Starting a CPU-intensive process (infinite loop)...&quot;&lt;/span&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Launch a background CPU-intensive process&lt;/span&gt;bash -c &lt;span class=&quot;hljs-string&quot;&gt;&quot;while :; do :; done&quot;&lt;/span&gt; &amp;amp;PROCESS_PID=$!&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Process started with PID &lt;span class=&quot;hljs-variable&quot;&gt;$PROCESS_PID&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Step 4: Add the process to the cgroup&lt;/span&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Adding process &lt;span class=&quot;hljs-variable&quot;&gt;$PROCESS_PID&lt;/span&gt; to cgroup...&quot;&lt;/span&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;$PROCESS_PID&lt;/span&gt; &amp;gt; &lt;span class=&quot;hljs-variable&quot;&gt;$CGROUP_PATH&lt;/span&gt;/cgroup.procs&lt;span class=&quot;hljs-comment&quot;&gt;# Step 5: Monitor CPU usage for the process&lt;/span&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Monitoring CPU usage (press Ctrl+C to exit)...&quot;&lt;/span&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;; &lt;span class=&quot;hljs-keyword&quot;&gt;do&lt;/span&gt;    CPU_USAGE=$(ps -p &lt;span class=&quot;hljs-variable&quot;&gt;$PROCESS_PID&lt;/span&gt; -o %cpu=)    &lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;CPU Usage of PID &lt;span class=&quot;hljs-variable&quot;&gt;$PROCESS_PID&lt;/span&gt;: &lt;span class=&quot;hljs-variable&quot;&gt;$CPU_USAGE&lt;/span&gt;%&quot;&lt;/span&gt;    sleep 2&lt;span class=&quot;hljs-keyword&quot;&gt;done&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Execute the script:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;sudo ./cgroup.sh&lt;/code&gt;&lt;/pre&gt;&lt;hr /&gt;&lt;p&gt;&lt;strong&gt;Explanation of the Script&lt;/strong&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create a cgroup&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The script creates a directory in &lt;code&gt;/sys/fs/cgroup/cpu/&lt;/code&gt; for the new cgroup.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Set CPU limits&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/6/html/resource_management_guide/sec-cpu#sect-cfs:~:text=is%201000%20microseconds.-,cpu.cfs_quota_us,-specifies%20the%20total&quot;&gt;&lt;code&gt;cpu.cfs_quota_us&lt;/code&gt;&lt;/a&gt;: Specifies the total time (in microseconds) the cgroup is allowed to run on the CPU within each &lt;code&gt;cpu.cfs_period_us&lt;/code&gt; period.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/6/html/resource_management_guide/sec-cpu#sect-cfs:~:text=Enforcement%20Tunable%20Parameters-,cpu.cfs_period_us,-specifies%20a%20period&quot;&gt;&lt;code&gt;cpu.cfs_period_us&lt;/code&gt;&lt;/a&gt;: Defines the time period (in microseconds) used to calculate CPU quotas. Default is 1000 microseconds.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Run a CPU-intensive process&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;An infinite loop (&lt;code&gt;while :; do :; done&lt;/code&gt;) generates a CPU load for testing.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Assign the process to the cgroup&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The script uses &lt;code&gt;echo $PROCESS_PID &amp;gt; $CGROUP_PATH/cgroup.procs&lt;/code&gt; to attach the process to the cgroup.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Monitor the CPU usage&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The &lt;code&gt;ps&lt;/code&gt; command checks the process&apos;s CPU usage percentage in real time.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;strong&gt;Observe the CPU Usage&lt;/strong&gt;:&lt;/p&gt;&lt;p&gt;The script displays the CPU usage of the process every 2 seconds. The &lt;code&gt;%CPU&lt;/code&gt; value should not exceed 50%, confirming the limitation.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1732904555363/8cca7a07-244f-455e-8dc6-f351bfe06cc4.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;hr /&gt;&lt;h3 id=&quot;heading-summary-table-for-namespaces-vs-cgroups&quot;&gt;&lt;strong&gt;Summary table for namespaces vs. cgroups&lt;/strong&gt;&lt;/h3&gt;&lt;div class=&quot;hn-table&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;td&gt;Feature&lt;/td&gt;&lt;td&gt;Namespaces&lt;/td&gt;&lt;td&gt;cgroups&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Purpose&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Isolates system resources.&lt;/td&gt;&lt;td&gt;Manages and limits resource usage.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Scope&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Provides isolation.&lt;/td&gt;&lt;td&gt;Provides control and accounting.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Examples&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Process ID, filesystem, network.&lt;/td&gt;&lt;td&gt;CPU, memory, disk I/O.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Use Case&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Container isolation.&lt;/td&gt;&lt;td&gt;Resource allocation for containers.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;h3 id=&quot;heading-references&quot;&gt;References:&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://blog.nginx.org/blog/what-are-namespaces-cgroups-how-do-they-work&quot;&gt;Nginx Blog: What Are Namespaces and cgroups, and How Do They Work?&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://github.com/Brain2life/bash-cookbook/tree/main/linux-namespaces-cgroups&quot;&gt;https://github.com/Brain2life/bash-cookbook/tree/main/linux-namespaces-cgroups&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://man7.org/linux/man-pages/man7/namespaces.7.html&quot;&gt;Linux man7 page: Namespaces&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://man7.org/linux/man-pages/man7/cgroups.7.html&quot;&gt;Linux man7 page: cgroups&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/6/html/resource_management_guide/sec-cpu#sec-cpu&quot;&gt;CPU cgroup tunable parametes&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;]]&gt;</hashnode:content><hashnode:coverImage>https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/xbEVM6oJ1Fs/upload/4c48cef8a4f31d813b751fd4eec2d86c.jpeg</hashnode:coverImage></item><item><title><![CDATA[Stop Leaving Passwords in Your Linux Shell History]]></title><description><![CDATA[Stop Leaving Passwords in Your Linux Shell History]]></description><link>https://maxat-akbanov.com/stop-leaving-passwords-in-your-linux-shell-history</link><guid isPermaLink="true">https://maxat-akbanov.com/stop-leaving-passwords-in-your-linux-shell-history</guid><category><![CDATA[Devops]]></category><category><![CDATA[Linux]]></category><category><![CDATA[Bash]]></category><category><![CDATA[#bash-history]]></category><category><![CDATA[sysops]]></category><category><![CDATA[administration]]></category><dc:creator><![CDATA[Maxat Akbanov]]></dc:creator><pubDate>Wed, 27 Nov 2024 10:37:57 GMT</pubDate><content:encoded>&lt;![CDATA[&lt;p&gt;Sometimes when you have to check functioning of service or troubleshoot connection of apps in Development or Test environments, you need to SSH into server and run commands with sensitive data.&lt;/p&gt;&lt;p&gt;For example you may run the applications docker container with specific env variables in order to check the containers connection to the database:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;docker run -d --name app \-p 80:3000 \-e DB_HOST=my-db.us-east-1.rds.amazonaws.com \-e DB_USER=&amp;lt;username&amp;gt; \-e DB_PASSWORD=&amp;lt;password&amp;gt;-e DB_NAME=my_dbdkr.ecr.us-east-1.amazonaws.com/app-repo:v1.0.0&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;As you can see, here we type sensitive values of &lt;code&gt;DB_USER&lt;/code&gt; and &lt;code&gt;DB_PASSWORD&lt;/code&gt; right into the shell. If not properly managed, these values end up in shell history where everyone who has access to the server can view it.&lt;/p&gt;&lt;p&gt;To avoid storing sensitive commands in the shell history, follow these best practices:&lt;/p&gt;&lt;h3 id=&quot;heading-use-a-space-before-the-command&quot;&gt;&lt;strong&gt;Use a Space Before the Command&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;If your shell supports it (e.g., &lt;code&gt;bash&lt;/code&gt;), prefix the command with a space. This relies on the &lt;code&gt;HISTCONTROL&lt;/code&gt; environment variable being set to &lt;code&gt;ignorespace&lt;/code&gt;. Using the &lt;code&gt;HISTCONTROL&lt;/code&gt; variable you can control how bash stores your command history. You can tell it to ignore duplicate commands and/or to ignore commands that have leading whitespace.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;export&lt;/span&gt; HISTCONTROL=ignorespace&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If &lt;code&gt;HISTCONTROL&lt;/code&gt; variable has the value of &lt;code&gt;ignoreboth&lt;/code&gt; then the setting for using the space prefix is set.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;$HISTCONTROL&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div data-node-type=&quot;callout&quot;&gt;&lt;div data-node-type=&quot;callout-emoji&quot;&gt;&lt;/div&gt;&lt;div data-node-type=&quot;callout-text&quot;&gt;Remember that this setting is temporary for the duration of running shell session.&lt;/div&gt;&lt;/div&gt;&lt;p&gt;You can set the flags in your &lt;code&gt;~/.bashrc&lt;/code&gt; file or in the global &lt;code&gt;/etc/bash.bashrc&lt;/code&gt; file. The following command would append it to your &lt;code&gt;~/.bashrc&lt;/code&gt; file:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;HISTCONTROL=ignoreboth&quot;&lt;/span&gt; &amp;gt;&amp;gt;~/.bashrc&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-disable-history-temporarily&quot;&gt;&lt;strong&gt;Disable History Temporarily&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;Disable history logging for the current shell session before running the command:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;set&lt;/span&gt; +o &lt;span class=&quot;hljs-built_in&quot;&gt;history&lt;/span&gt;psql -h &amp;lt;db_endpoint&amp;gt; -U &amp;lt;db_name&amp;gt; -p 5432&lt;span class=&quot;hljs-built_in&quot;&gt;set&lt;/span&gt; -o &lt;span class=&quot;hljs-built_in&quot;&gt;history&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-use-a-secure-method-to-read-passwords&quot;&gt;&lt;strong&gt;Use a Secure Method to Read Passwords&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;Use tools like &lt;code&gt;read&lt;/code&gt; with &lt;code&gt;-s&lt;/code&gt; to hide the password input:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;read&lt;/span&gt; -sp &lt;span class=&quot;hljs-string&quot;&gt;&quot;Enter Password: &quot;&lt;/span&gt; PASSWORDdocker run -d --name app \-p 80:3000 \-e DB_HOST=my-db.us-east-1.rds.amazonaws.com \-e DB_USER=&amp;lt;username&amp;gt; \-e DB_PASSWORD=&lt;span class=&quot;hljs-variable&quot;&gt;$PASSWORD&lt;/span&gt;-e DB_NAME=my_dbdkr.ecr.us-east-1.amazonaws.com/app-repo:v1.0.0&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-remove-specific-entries-from-history&quot;&gt;&lt;strong&gt;Remove Specific Entries from History&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;If a sensitive command has been accidentally logged, remove it from the history:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;history&lt;/span&gt; -d &amp;lt;line_number&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Or clear the entire history:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;history&lt;/span&gt; -c&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-set-alias-to-clean-history-after-logout&quot;&gt;Set Alias to Clean History After Logout&lt;/h3&gt;&lt;p&gt;In your &lt;code&gt;.bash_aliases&lt;/code&gt; file set the following &lt;code&gt;logout&lt;/code&gt; command to clean the history and exit the session:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;logout&lt;/span&gt;=&lt;span class=&quot;hljs-string&quot;&gt;&quot;history -c &amp;amp;&amp;amp; exit&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-set-patterns-to-ignore-specific-commands&quot;&gt;Set Patterns to Ignore Specific Commands&lt;/h3&gt;&lt;p&gt;The &lt;code&gt;HISTIGNORE&lt;/code&gt; environment variable controls which commands are entered into the history and which are ignored. It contains a list of patterns separated by colons (:) that when matched, drops a command rather than includes it in the file. For example to ignore all &lt;code&gt;export&lt;/code&gt; commands:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;HISTIGNORE=&lt;span class=&quot;hljs-string&quot;&gt;&quot; :export *&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You do not need to export this variable.&lt;/p&gt;&lt;div data-node-type=&quot;callout&quot;&gt;&lt;div data-node-type=&quot;callout-emoji&quot;&gt;&lt;/div&gt;&lt;div data-node-type=&quot;callout-text&quot;&gt;Be warned however than ignoring an item from the history means that it cannot be recalled by any means  not even with the up and down arrows.&lt;/div&gt;&lt;/div&gt;&lt;h3 id=&quot;heading-use-encrypted-storage-for-sensitive-variables&quot;&gt;&lt;strong&gt;Use Encrypted Storage for Sensitive Variables&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;For frequently used sensitive data, consider using tool like &lt;code&gt;pass&lt;/code&gt;. This is a password manager for Linux systems.&lt;/p&gt;&lt;p&gt;To install &lt;code&gt;pass&lt;/code&gt; on Ubuntu:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;sudo apt-add-repository universesudo apt-get updatesudo apt-get install pass&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For example, to store the API key for a service like GitHub:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;pass init --path=github/api_key gpg-id=&lt;span class=&quot;hljs-string&quot;&gt;&quot;&amp;lt;GPG_ID&amp;gt;&quot;&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Initialize store&lt;/span&gt;pass insert github/api_key/my_pass &lt;span class=&quot;hljs-comment&quot;&gt;# Store password&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Retrieve the API key securely when needed:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;API_KEY=$(pass github/api_key/my_pass)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Use the API key in your command:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;curl -H &lt;span class=&quot;hljs-string&quot;&gt;&quot;Authorization: token &lt;span class=&quot;hljs-variable&quot;&gt;$API_KEY&lt;/span&gt;&quot;&lt;/span&gt; https://api.github.com/user&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-use-gui-tools-to-manage-shell-history&quot;&gt;Use GUI Tools to Manage Shell History&lt;/h3&gt;&lt;p&gt;You can use the open-source shell manager tools like &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/atuinsh/atuin&quot;&gt;&lt;code&gt;altuin&lt;/code&gt;&lt;/a&gt; to manage your shell history.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1732702536716/7228929b-b603-4498-b3bb-dca63d184e1d.gif&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;To delete specific entries in history, select specific command with arrow, type &lt;strong&gt;&amp;lt;CTR-O&amp;gt;&lt;/strong&gt; and then &lt;strong&gt;&amp;lt;CTR-D&amp;gt;&lt;/strong&gt;.&lt;/p&gt;&lt;h3 id=&quot;heading-references&quot;&gt;References:&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://www.techrepublic.com/article/linux-command-line-tips-history-and-histignore-in-bash/&quot;&gt;Linux command line tips: history and HISTIGNORE in Bash&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://dev.to/epranka/hide-the-exported-env-variables-from-the-history-49ni&quot;&gt;Hide the exported ENV variables from the history&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://gist.github.com/Angles/3273505&quot;&gt;https://gist.github.com/Angles/3273505&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://ryan.himmelwright.net/post/setting-up-pass/&quot;&gt;Configuring Pass, the Standard Unix Password Manager&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;]]&gt;</content:encoded><hashnode:content>&lt;![CDATA[&lt;p&gt;Sometimes when you have to check functioning of service or troubleshoot connection of apps in Development or Test environments, you need to SSH into server and run commands with sensitive data.&lt;/p&gt;&lt;p&gt;For example you may run the applications docker container with specific env variables in order to check the containers connection to the database:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;docker run -d --name app \-p 80:3000 \-e DB_HOST=my-db.us-east-1.rds.amazonaws.com \-e DB_USER=&amp;lt;username&amp;gt; \-e DB_PASSWORD=&amp;lt;password&amp;gt;-e DB_NAME=my_dbdkr.ecr.us-east-1.amazonaws.com/app-repo:v1.0.0&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;As you can see, here we type sensitive values of &lt;code&gt;DB_USER&lt;/code&gt; and &lt;code&gt;DB_PASSWORD&lt;/code&gt; right into the shell. If not properly managed, these values end up in shell history where everyone who has access to the server can view it.&lt;/p&gt;&lt;p&gt;To avoid storing sensitive commands in the shell history, follow these best practices:&lt;/p&gt;&lt;h3 id=&quot;heading-use-a-space-before-the-command&quot;&gt;&lt;strong&gt;Use a Space Before the Command&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;If your shell supports it (e.g., &lt;code&gt;bash&lt;/code&gt;), prefix the command with a space. This relies on the &lt;code&gt;HISTCONTROL&lt;/code&gt; environment variable being set to &lt;code&gt;ignorespace&lt;/code&gt;. Using the &lt;code&gt;HISTCONTROL&lt;/code&gt; variable you can control how bash stores your command history. You can tell it to ignore duplicate commands and/or to ignore commands that have leading whitespace.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;export&lt;/span&gt; HISTCONTROL=ignorespace&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If &lt;code&gt;HISTCONTROL&lt;/code&gt; variable has the value of &lt;code&gt;ignoreboth&lt;/code&gt; then the setting for using the space prefix is set.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-variable&quot;&gt;$HISTCONTROL&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div data-node-type=&quot;callout&quot;&gt;&lt;div data-node-type=&quot;callout-emoji&quot;&gt;&lt;/div&gt;&lt;div data-node-type=&quot;callout-text&quot;&gt;Remember that this setting is temporary for the duration of running shell session.&lt;/div&gt;&lt;/div&gt;&lt;p&gt;You can set the flags in your &lt;code&gt;~/.bashrc&lt;/code&gt; file or in the global &lt;code&gt;/etc/bash.bashrc&lt;/code&gt; file. The following command would append it to your &lt;code&gt;~/.bashrc&lt;/code&gt; file:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;HISTCONTROL=ignoreboth&quot;&lt;/span&gt; &amp;gt;&amp;gt;~/.bashrc&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-disable-history-temporarily&quot;&gt;&lt;strong&gt;Disable History Temporarily&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;Disable history logging for the current shell session before running the command:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;set&lt;/span&gt; +o &lt;span class=&quot;hljs-built_in&quot;&gt;history&lt;/span&gt;psql -h &amp;lt;db_endpoint&amp;gt; -U &amp;lt;db_name&amp;gt; -p 5432&lt;span class=&quot;hljs-built_in&quot;&gt;set&lt;/span&gt; -o &lt;span class=&quot;hljs-built_in&quot;&gt;history&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-use-a-secure-method-to-read-passwords&quot;&gt;&lt;strong&gt;Use a Secure Method to Read Passwords&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;Use tools like &lt;code&gt;read&lt;/code&gt; with &lt;code&gt;-s&lt;/code&gt; to hide the password input:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;read&lt;/span&gt; -sp &lt;span class=&quot;hljs-string&quot;&gt;&quot;Enter Password: &quot;&lt;/span&gt; PASSWORDdocker run -d --name app \-p 80:3000 \-e DB_HOST=my-db.us-east-1.rds.amazonaws.com \-e DB_USER=&amp;lt;username&amp;gt; \-e DB_PASSWORD=&lt;span class=&quot;hljs-variable&quot;&gt;$PASSWORD&lt;/span&gt;-e DB_NAME=my_dbdkr.ecr.us-east-1.amazonaws.com/app-repo:v1.0.0&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-remove-specific-entries-from-history&quot;&gt;&lt;strong&gt;Remove Specific Entries from History&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;If a sensitive command has been accidentally logged, remove it from the history:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;history&lt;/span&gt; -d &amp;lt;line_number&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Or clear the entire history:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;history&lt;/span&gt; -c&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-set-alias-to-clean-history-after-logout&quot;&gt;Set Alias to Clean History After Logout&lt;/h3&gt;&lt;p&gt;In your &lt;code&gt;.bash_aliases&lt;/code&gt; file set the following &lt;code&gt;logout&lt;/code&gt; command to clean the history and exit the session:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;alias&lt;/span&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;logout&lt;/span&gt;=&lt;span class=&quot;hljs-string&quot;&gt;&quot;history -c &amp;amp;&amp;amp; exit&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-set-patterns-to-ignore-specific-commands&quot;&gt;Set Patterns to Ignore Specific Commands&lt;/h3&gt;&lt;p&gt;The &lt;code&gt;HISTIGNORE&lt;/code&gt; environment variable controls which commands are entered into the history and which are ignored. It contains a list of patterns separated by colons (:) that when matched, drops a command rather than includes it in the file. For example to ignore all &lt;code&gt;export&lt;/code&gt; commands:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;HISTIGNORE=&lt;span class=&quot;hljs-string&quot;&gt;&quot; :export *&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You do not need to export this variable.&lt;/p&gt;&lt;div data-node-type=&quot;callout&quot;&gt;&lt;div data-node-type=&quot;callout-emoji&quot;&gt;&lt;/div&gt;&lt;div data-node-type=&quot;callout-text&quot;&gt;Be warned however than ignoring an item from the history means that it cannot be recalled by any means  not even with the up and down arrows.&lt;/div&gt;&lt;/div&gt;&lt;h3 id=&quot;heading-use-encrypted-storage-for-sensitive-variables&quot;&gt;&lt;strong&gt;Use Encrypted Storage for Sensitive Variables&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;For frequently used sensitive data, consider using tool like &lt;code&gt;pass&lt;/code&gt;. This is a password manager for Linux systems.&lt;/p&gt;&lt;p&gt;To install &lt;code&gt;pass&lt;/code&gt; on Ubuntu:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;sudo apt-add-repository universesudo apt-get updatesudo apt-get install pass&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For example, to store the API key for a service like GitHub:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;pass init --path=github/api_key gpg-id=&lt;span class=&quot;hljs-string&quot;&gt;&quot;&amp;lt;GPG_ID&amp;gt;&quot;&lt;/span&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Initialize store&lt;/span&gt;pass insert github/api_key/my_pass &lt;span class=&quot;hljs-comment&quot;&gt;# Store password&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Retrieve the API key securely when needed:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;API_KEY=$(pass github/api_key/my_pass)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Use the API key in your command:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;curl -H &lt;span class=&quot;hljs-string&quot;&gt;&quot;Authorization: token &lt;span class=&quot;hljs-variable&quot;&gt;$API_KEY&lt;/span&gt;&quot;&lt;/span&gt; https://api.github.com/user&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-use-gui-tools-to-manage-shell-history&quot;&gt;Use GUI Tools to Manage Shell History&lt;/h3&gt;&lt;p&gt;You can use the open-source shell manager tools like &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/atuinsh/atuin&quot;&gt;&lt;code&gt;altuin&lt;/code&gt;&lt;/a&gt; to manage your shell history.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1732702536716/7228929b-b603-4498-b3bb-dca63d184e1d.gif&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;To delete specific entries in history, select specific command with arrow, type &lt;strong&gt;&amp;lt;CTR-O&amp;gt;&lt;/strong&gt; and then &lt;strong&gt;&amp;lt;CTR-D&amp;gt;&lt;/strong&gt;.&lt;/p&gt;&lt;h3 id=&quot;heading-references&quot;&gt;References:&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://www.techrepublic.com/article/linux-command-line-tips-history-and-histignore-in-bash/&quot;&gt;Linux command line tips: history and HISTIGNORE in Bash&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://dev.to/epranka/hide-the-exported-env-variables-from-the-history-49ni&quot;&gt;Hide the exported ENV variables from the history&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://gist.github.com/Angles/3273505&quot;&gt;https://gist.github.com/Angles/3273505&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://ryan.himmelwright.net/post/setting-up-pass/&quot;&gt;Configuring Pass, the Standard Unix Password Manager&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;]]&gt;</hashnode:content><hashnode:coverImage>https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/em5w9_xj3uU/upload/74de115ad09996220e47101d962e2973.jpeg</hashnode:coverImage></item><item><title><![CDATA[Basics of Remote Procedure Call (RPC)]]></title><description><![CDATA[Basics of Remote Procedure Call (RPC)]]></description><link>https://maxat-akbanov.com/basics-of-remote-procedure-call-rpc</link><guid isPermaLink="true">https://maxat-akbanov.com/basics-of-remote-procedure-call-rpc</guid><category><![CDATA[Devops]]></category><category><![CDATA[sysops]]></category><category><![CDATA[RPC]]></category><category><![CDATA[#IaC]]></category><category><![CDATA[Terraform]]></category><dc:creator><![CDATA[Maxat Akbanov]]></dc:creator><pubDate>Fri, 25 Oct 2024 10:51:30 GMT</pubDate><content:encoded>&lt;![CDATA[&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Remote_procedure_call&quot;&gt;Remote Procedure Call (RPC)&lt;/a&gt; is a powerful technique used in computer networks and distributed systems to enable a program on one computer (the client) to execute code on a remote system (the server) as if it were a local procedure call. By abstracting the complexity of network communication, RPC simplifies the development of distributed applications by allowing developers to write code that looks like standard, local procedure calls.&lt;/p&gt;&lt;h3 id=&quot;heading-how-rpc-works&quot;&gt;How RPC works&lt;/h3&gt;&lt;p&gt;Consider an example of online shop with the payment system for customers. When customer makes payment on online shop website, under the hood it sends request to a third-party service on another server that processes the payment card details.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729771991488/85dc8fd3-bce8-4f2c-bf5d-b6143582c7ea.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;When call is made to the payment service, the code that resides on the online shopping site makes an RPC call to the cardholders bank via the third-party payment processing service.&lt;/p&gt;&lt;p&gt;The pseudo code for such interaction might look like the following:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-javascript&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;// Function to process payment during checkout&lt;/span&gt;&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;processPayment&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;orderDetails, paymentInfo&lt;/span&gt;) &lt;/span&gt;{    &lt;span class=&quot;hljs-comment&quot;&gt;// Prepare the payment request object with necessary details&lt;/span&gt;    paymentRequest = {        &lt;span class=&quot;hljs-attr&quot;&gt;orderId&lt;/span&gt;: orderDetails.orderId,        &lt;span class=&quot;hljs-attr&quot;&gt;amount&lt;/span&gt;: orderDetails.totalAmount,        &lt;span class=&quot;hljs-attr&quot;&gt;currency&lt;/span&gt;: orderDetails.currency,        &lt;span class=&quot;hljs-attr&quot;&gt;paymentMethod&lt;/span&gt;: paymentInfo.method,        &lt;span class=&quot;hljs-comment&quot;&gt;// e.g., &apos;CreditCard&apos;, &apos;PayPal&apos;&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;cardNumber&lt;/span&gt;: paymentInfo.cardNumber,        &lt;span class=&quot;hljs-attr&quot;&gt;cardExpiry&lt;/span&gt;: paymentInfo.cardExpiry,        &lt;span class=&quot;hljs-attr&quot;&gt;cardSVC&lt;/span&gt;: paymentInfo.cardSVC,        &lt;span class=&quot;hljs-attr&quot;&gt;billingAddress&lt;/span&gt;: paymentInfo.billingAddress,        &lt;span class=&quot;hljs-attr&quot;&gt;customerEmail&lt;/span&gt;: orderDetails.customerEmail,        &lt;span class=&quot;hljs-comment&quot;&gt;// Additional fields as required...&lt;/span&gt;    }    &lt;span class=&quot;hljs-comment&quot;&gt;// Create an RPC client proxy to the payment processing service&lt;/span&gt;    paymentService = createRPCProxy(&lt;span class=&quot;hljs-string&quot;&gt;&quot;https://payment-service.com/api&quot;&lt;/span&gt;)    &lt;span class=&quot;hljs-comment&quot;&gt;// Make the remote procedure call to process the payment&lt;/span&gt;    &lt;span class=&quot;hljs-keyword&quot;&gt;try&lt;/span&gt; {        &lt;span class=&quot;hljs-comment&quot;&gt;// Invoke the &apos;processPayment&apos; method on the payment service&lt;/span&gt;        paymentResponse = paymentService.processPayment(paymentRequest)        &lt;span class=&quot;hljs-comment&quot;&gt;// Check the response status&lt;/span&gt;        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (paymentResponse.status == &lt;span class=&quot;hljs-string&quot;&gt;&quot;Success&quot;&lt;/span&gt;) {            &lt;span class=&quot;hljs-comment&quot;&gt;// Payment was successful&lt;/span&gt;            updateOrderStatus(orderDetails.orderId, &lt;span class=&quot;hljs-string&quot;&gt;&quot;Paid&quot;&lt;/span&gt;)            sendConfirmationEmail(orderDetails.customerEmail)            displayMessage(&lt;span class=&quot;hljs-string&quot;&gt;&quot;Your payment was successful. Thank you for your purchase!&quot;&lt;/span&gt;)        } &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; {            &lt;span class=&quot;hljs-comment&quot;&gt;// Payment failed&lt;/span&gt;            displayMessage(&lt;span class=&quot;hljs-string&quot;&gt;&quot;Payment failed: &quot;&lt;/span&gt; + paymentResponse.errorMessage)            &lt;span class=&quot;hljs-comment&quot;&gt;// Optionally, prompt the user to try again or use a different payment method&lt;/span&gt;        }    } &lt;span class=&quot;hljs-keyword&quot;&gt;catch&lt;/span&gt; (rpcError) {        &lt;span class=&quot;hljs-comment&quot;&gt;// Handle any errors that occurred during the RPC call&lt;/span&gt;        displayMessage(&lt;span class=&quot;hljs-string&quot;&gt;&quot;An error occurred while processing your payment. Please try again later.&quot;&lt;/span&gt;)        logError(rpcError)        &lt;span class=&quot;hljs-comment&quot;&gt;// Additional error handling as needed...&lt;/span&gt;    }}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Making the RPC Call&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;The call is made with &lt;code&gt;processPayment(paymentRequest)&lt;/code&gt; as if it were a local function.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The RPC mechanism handles serialization of &lt;code&gt;paymentRequest&lt;/code&gt; and communication over the network (using JSON, XML, etc formats for data representation).&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In detail the communication with payment service involves:&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729845753257/f9a257d6-5587-40b8-9de6-16b2283a8d81.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;h3 id=&quot;heading-core-concepts&quot;&gt;&lt;strong&gt;Core Concepts&lt;/strong&gt;&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Transparency&lt;/strong&gt;: RPC aims to make the remote call appear identical to a local call from the programmer&apos;s perspective. This means handling data serialization, network communication, and error detection behind the scenes.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Client-Server Model&lt;/strong&gt;: The architecture typically involves a client making a request to a server, which performs the desired operation and returns the result to the client.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Stubs and Skeletons&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Client Stub&lt;/strong&gt;: Acts as a proxy for the client, responsible for packaging the procedure call into a message format suitable for transmission over the network (&lt;strong&gt;marshalling&lt;/strong&gt;).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server Skeleton&lt;/strong&gt;: Receives the message on the server side, unpacks it (&lt;strong&gt;unmarshalling&lt;/strong&gt;), and invokes the appropriate procedure.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Marshalling and Unmarshalling&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Marshalling&lt;/strong&gt;: The process of converting procedure parameters into a standard format for transmission.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Unmarshalling&lt;/strong&gt;: The reverse process, converting the received data back into a format usable by the server&apos;s procedure.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-rpc-procedure&quot;&gt;&lt;strong&gt;RPC Procedure&lt;/strong&gt;&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Procedure Call&lt;/strong&gt;: The client invokes a procedure as if it were local.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Client Stub Processing&lt;/strong&gt;: The client stub intercepts the call, marshals the parameters, and sends a message to the server.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Network Communication&lt;/strong&gt;: The message is transmitted over the network using a communication protocol (e.g., TCP/IP).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server Skeleton Processing&lt;/strong&gt;: The server skeleton receives the message, unmarshals the parameters, and invokes the corresponding procedure on the server.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Execution and Response&lt;/strong&gt;: The server executes the procedure and sends the result back through the skeleton.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Result Handling&lt;/strong&gt;: The client stub receives the response, unmarshals the data, and returns it to the client application.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-types-of-rpc&quot;&gt;&lt;strong&gt;Types of RPC&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Synchronous RPC&lt;/strong&gt;: The client waits (blocks) until the server responds. This is the traditional form of RPC.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Asynchronous RPC&lt;/strong&gt;: The client continues processing and can handle the server&apos;s response at a later time, improving concurrency and resource utilization.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-protocols-and-implementations&quot;&gt;&lt;strong&gt;Protocols and Implementations&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Sun_RPC&quot;&gt;&lt;strong&gt;ONC RPC&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;(Open Network Computing RPC)&lt;/strong&gt;: Developed by Sun Microsystems, commonly used in UNIX systems.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/DCE/RPC&quot;&gt;&lt;strong&gt;DCE RPC&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;(Distributed Computing Environment RPC)&lt;/strong&gt;: Developed by the Open Software Foundation, provides additional features like authentication and directory services.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/XML-RPC&quot;&gt;&lt;strong&gt;XML-RPC&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;and&lt;/strong&gt; &lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/JSON-RPC&quot;&gt;&lt;strong&gt;JSON-RPC&lt;/strong&gt;&lt;/a&gt;: Use XML or JSON over HTTP for communication, making them suitable for web-based applications.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://grpc.io/&quot;&gt;&lt;strong&gt;gRPC&lt;/strong&gt;&lt;/a&gt;: An open-source RPC framework developed by Google, which uses HTTP/2 and Protocol Buffers for efficient communication.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-applications-of-rpc&quot;&gt;&lt;strong&gt;Applications of RPC&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Distributed Systems&lt;/strong&gt;: Facilitates communication between different components in a &lt;a target=&quot;_blank&quot; href=&quot;https://www.atlassian.com/microservices/microservices-architecture/distributed-architecture&quot;&gt;distributed architecture&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Microservices&lt;/strong&gt;: Enables services to communicate in a &lt;a target=&quot;_blank&quot; href=&quot;https://microservices.io/&quot;&gt;microservices architecture&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;File Systems&lt;/strong&gt;: NFS (Network File System) uses RPC for remote file operations.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Web Services&lt;/strong&gt;: Underlying mechanism for many &lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/SOAP&quot;&gt;SOAP-based web services&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-advantages&quot;&gt;&lt;strong&gt;Advantages&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simplifies Development&lt;/strong&gt;: Abstracts the complexity of network programming.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Interoperability&lt;/strong&gt;: Allows systems written in different languages to communicate.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Modularity&lt;/strong&gt;: Encourages a modular approach to system design.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-disadvantages&quot;&gt;&lt;strong&gt;Disadvantages&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Latency and Network Issues&lt;/strong&gt;: Network communication introduces latency and potential for failures.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security Risks&lt;/strong&gt;: Exposing procedures over a network can introduce security vulnerabilities.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Complex Debugging&lt;/strong&gt;: Errors may occur in the network layer, making debugging more challenging.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-security-considerations&quot;&gt;&lt;strong&gt;Security Considerations&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Authentication and Authorization&lt;/strong&gt;: Ensuring only authorized clients can make RPC calls.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Encryption&lt;/strong&gt;: Protecting data transmitted over the network using SSL/TLS.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Input Validation&lt;/strong&gt;: Preventing injection attacks by validating input parameters.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-practice-making-an-rpc-call-to-a-service-running-on-ec2-instance&quot;&gt;Practice: Making an RPC call to a Service Running on EC2 Instance&lt;/h3&gt;&lt;p&gt;This example demonstrates how to make a Remote Procedure Call from your local laptop to a service running on a remote AWS EC2 instance. It uses Python&apos;s built-in &lt;code&gt;xmlrpc&lt;/code&gt; library for simplicity. Example also provides Terraform code to provision the necessary AWS infrastructure, including the EC2 instance and networking components.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729852477764/1072247b-79f3-4313-8f7b-53db12ff32af.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;To learn more, checkout this repository:&lt;br /&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://github.com/Brain2life/terraform-cookbook/tree/main/example-rpc-call-to-ec2&quot;&gt;https://github.com/Brain2life/terraform-cookbook/tree/main/example-rpc-call-to-ec2&lt;/a&gt;&lt;/p&gt;&lt;h3 id=&quot;heading-references&quot;&gt;References:&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://www.youtube.com/watch?app=desktop&amp;amp;v=S2osKiqQG9s&quot;&gt;YouTube: Distributed Systems 1.3: RPC (Remote Procedure Call)&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;]]&gt;</content:encoded><hashnode:content>&lt;![CDATA[&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Remote_procedure_call&quot;&gt;Remote Procedure Call (RPC)&lt;/a&gt; is a powerful technique used in computer networks and distributed systems to enable a program on one computer (the client) to execute code on a remote system (the server) as if it were a local procedure call. By abstracting the complexity of network communication, RPC simplifies the development of distributed applications by allowing developers to write code that looks like standard, local procedure calls.&lt;/p&gt;&lt;h3 id=&quot;heading-how-rpc-works&quot;&gt;How RPC works&lt;/h3&gt;&lt;p&gt;Consider an example of online shop with the payment system for customers. When customer makes payment on online shop website, under the hood it sends request to a third-party service on another server that processes the payment card details.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729771991488/85dc8fd3-bce8-4f2c-bf5d-b6143582c7ea.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;When call is made to the payment service, the code that resides on the online shopping site makes an RPC call to the cardholders bank via the third-party payment processing service.&lt;/p&gt;&lt;p&gt;The pseudo code for such interaction might look like the following:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-javascript&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;// Function to process payment during checkout&lt;/span&gt;&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;processPayment&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;orderDetails, paymentInfo&lt;/span&gt;) &lt;/span&gt;{    &lt;span class=&quot;hljs-comment&quot;&gt;// Prepare the payment request object with necessary details&lt;/span&gt;    paymentRequest = {        &lt;span class=&quot;hljs-attr&quot;&gt;orderId&lt;/span&gt;: orderDetails.orderId,        &lt;span class=&quot;hljs-attr&quot;&gt;amount&lt;/span&gt;: orderDetails.totalAmount,        &lt;span class=&quot;hljs-attr&quot;&gt;currency&lt;/span&gt;: orderDetails.currency,        &lt;span class=&quot;hljs-attr&quot;&gt;paymentMethod&lt;/span&gt;: paymentInfo.method,        &lt;span class=&quot;hljs-comment&quot;&gt;// e.g., &apos;CreditCard&apos;, &apos;PayPal&apos;&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;cardNumber&lt;/span&gt;: paymentInfo.cardNumber,        &lt;span class=&quot;hljs-attr&quot;&gt;cardExpiry&lt;/span&gt;: paymentInfo.cardExpiry,        &lt;span class=&quot;hljs-attr&quot;&gt;cardSVC&lt;/span&gt;: paymentInfo.cardSVC,        &lt;span class=&quot;hljs-attr&quot;&gt;billingAddress&lt;/span&gt;: paymentInfo.billingAddress,        &lt;span class=&quot;hljs-attr&quot;&gt;customerEmail&lt;/span&gt;: orderDetails.customerEmail,        &lt;span class=&quot;hljs-comment&quot;&gt;// Additional fields as required...&lt;/span&gt;    }    &lt;span class=&quot;hljs-comment&quot;&gt;// Create an RPC client proxy to the payment processing service&lt;/span&gt;    paymentService = createRPCProxy(&lt;span class=&quot;hljs-string&quot;&gt;&quot;https://payment-service.com/api&quot;&lt;/span&gt;)    &lt;span class=&quot;hljs-comment&quot;&gt;// Make the remote procedure call to process the payment&lt;/span&gt;    &lt;span class=&quot;hljs-keyword&quot;&gt;try&lt;/span&gt; {        &lt;span class=&quot;hljs-comment&quot;&gt;// Invoke the &apos;processPayment&apos; method on the payment service&lt;/span&gt;        paymentResponse = paymentService.processPayment(paymentRequest)        &lt;span class=&quot;hljs-comment&quot;&gt;// Check the response status&lt;/span&gt;        &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; (paymentResponse.status == &lt;span class=&quot;hljs-string&quot;&gt;&quot;Success&quot;&lt;/span&gt;) {            &lt;span class=&quot;hljs-comment&quot;&gt;// Payment was successful&lt;/span&gt;            updateOrderStatus(orderDetails.orderId, &lt;span class=&quot;hljs-string&quot;&gt;&quot;Paid&quot;&lt;/span&gt;)            sendConfirmationEmail(orderDetails.customerEmail)            displayMessage(&lt;span class=&quot;hljs-string&quot;&gt;&quot;Your payment was successful. Thank you for your purchase!&quot;&lt;/span&gt;)        } &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt; {            &lt;span class=&quot;hljs-comment&quot;&gt;// Payment failed&lt;/span&gt;            displayMessage(&lt;span class=&quot;hljs-string&quot;&gt;&quot;Payment failed: &quot;&lt;/span&gt; + paymentResponse.errorMessage)            &lt;span class=&quot;hljs-comment&quot;&gt;// Optionally, prompt the user to try again or use a different payment method&lt;/span&gt;        }    } &lt;span class=&quot;hljs-keyword&quot;&gt;catch&lt;/span&gt; (rpcError) {        &lt;span class=&quot;hljs-comment&quot;&gt;// Handle any errors that occurred during the RPC call&lt;/span&gt;        displayMessage(&lt;span class=&quot;hljs-string&quot;&gt;&quot;An error occurred while processing your payment. Please try again later.&quot;&lt;/span&gt;)        logError(rpcError)        &lt;span class=&quot;hljs-comment&quot;&gt;// Additional error handling as needed...&lt;/span&gt;    }}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Making the RPC Call&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;The call is made with &lt;code&gt;processPayment(paymentRequest)&lt;/code&gt; as if it were a local function.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The RPC mechanism handles serialization of &lt;code&gt;paymentRequest&lt;/code&gt; and communication over the network (using JSON, XML, etc formats for data representation).&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In detail the communication with payment service involves:&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729845753257/f9a257d6-5587-40b8-9de6-16b2283a8d81.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;h3 id=&quot;heading-core-concepts&quot;&gt;&lt;strong&gt;Core Concepts&lt;/strong&gt;&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Transparency&lt;/strong&gt;: RPC aims to make the remote call appear identical to a local call from the programmer&apos;s perspective. This means handling data serialization, network communication, and error detection behind the scenes.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Client-Server Model&lt;/strong&gt;: The architecture typically involves a client making a request to a server, which performs the desired operation and returns the result to the client.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Stubs and Skeletons&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Client Stub&lt;/strong&gt;: Acts as a proxy for the client, responsible for packaging the procedure call into a message format suitable for transmission over the network (&lt;strong&gt;marshalling&lt;/strong&gt;).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server Skeleton&lt;/strong&gt;: Receives the message on the server side, unpacks it (&lt;strong&gt;unmarshalling&lt;/strong&gt;), and invokes the appropriate procedure.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Marshalling and Unmarshalling&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Marshalling&lt;/strong&gt;: The process of converting procedure parameters into a standard format for transmission.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Unmarshalling&lt;/strong&gt;: The reverse process, converting the received data back into a format usable by the server&apos;s procedure.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-rpc-procedure&quot;&gt;&lt;strong&gt;RPC Procedure&lt;/strong&gt;&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Procedure Call&lt;/strong&gt;: The client invokes a procedure as if it were local.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Client Stub Processing&lt;/strong&gt;: The client stub intercepts the call, marshals the parameters, and sends a message to the server.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Network Communication&lt;/strong&gt;: The message is transmitted over the network using a communication protocol (e.g., TCP/IP).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server Skeleton Processing&lt;/strong&gt;: The server skeleton receives the message, unmarshals the parameters, and invokes the corresponding procedure on the server.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Execution and Response&lt;/strong&gt;: The server executes the procedure and sends the result back through the skeleton.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Result Handling&lt;/strong&gt;: The client stub receives the response, unmarshals the data, and returns it to the client application.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-types-of-rpc&quot;&gt;&lt;strong&gt;Types of RPC&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Synchronous RPC&lt;/strong&gt;: The client waits (blocks) until the server responds. This is the traditional form of RPC.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Asynchronous RPC&lt;/strong&gt;: The client continues processing and can handle the server&apos;s response at a later time, improving concurrency and resource utilization.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-protocols-and-implementations&quot;&gt;&lt;strong&gt;Protocols and Implementations&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Sun_RPC&quot;&gt;&lt;strong&gt;ONC RPC&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;(Open Network Computing RPC)&lt;/strong&gt;: Developed by Sun Microsystems, commonly used in UNIX systems.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/DCE/RPC&quot;&gt;&lt;strong&gt;DCE RPC&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;(Distributed Computing Environment RPC)&lt;/strong&gt;: Developed by the Open Software Foundation, provides additional features like authentication and directory services.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/XML-RPC&quot;&gt;&lt;strong&gt;XML-RPC&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;and&lt;/strong&gt; &lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/JSON-RPC&quot;&gt;&lt;strong&gt;JSON-RPC&lt;/strong&gt;&lt;/a&gt;: Use XML or JSON over HTTP for communication, making them suitable for web-based applications.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://grpc.io/&quot;&gt;&lt;strong&gt;gRPC&lt;/strong&gt;&lt;/a&gt;: An open-source RPC framework developed by Google, which uses HTTP/2 and Protocol Buffers for efficient communication.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-applications-of-rpc&quot;&gt;&lt;strong&gt;Applications of RPC&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Distributed Systems&lt;/strong&gt;: Facilitates communication between different components in a &lt;a target=&quot;_blank&quot; href=&quot;https://www.atlassian.com/microservices/microservices-architecture/distributed-architecture&quot;&gt;distributed architecture&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Microservices&lt;/strong&gt;: Enables services to communicate in a &lt;a target=&quot;_blank&quot; href=&quot;https://microservices.io/&quot;&gt;microservices architecture&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;File Systems&lt;/strong&gt;: NFS (Network File System) uses RPC for remote file operations.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Web Services&lt;/strong&gt;: Underlying mechanism for many &lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/SOAP&quot;&gt;SOAP-based web services&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-advantages&quot;&gt;&lt;strong&gt;Advantages&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simplifies Development&lt;/strong&gt;: Abstracts the complexity of network programming.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Interoperability&lt;/strong&gt;: Allows systems written in different languages to communicate.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Modularity&lt;/strong&gt;: Encourages a modular approach to system design.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-disadvantages&quot;&gt;&lt;strong&gt;Disadvantages&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Latency and Network Issues&lt;/strong&gt;: Network communication introduces latency and potential for failures.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security Risks&lt;/strong&gt;: Exposing procedures over a network can introduce security vulnerabilities.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Complex Debugging&lt;/strong&gt;: Errors may occur in the network layer, making debugging more challenging.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-security-considerations&quot;&gt;&lt;strong&gt;Security Considerations&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Authentication and Authorization&lt;/strong&gt;: Ensuring only authorized clients can make RPC calls.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Encryption&lt;/strong&gt;: Protecting data transmitted over the network using SSL/TLS.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Input Validation&lt;/strong&gt;: Preventing injection attacks by validating input parameters.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-practice-making-an-rpc-call-to-a-service-running-on-ec2-instance&quot;&gt;Practice: Making an RPC call to a Service Running on EC2 Instance&lt;/h3&gt;&lt;p&gt;This example demonstrates how to make a Remote Procedure Call from your local laptop to a service running on a remote AWS EC2 instance. It uses Python&apos;s built-in &lt;code&gt;xmlrpc&lt;/code&gt; library for simplicity. Example also provides Terraform code to provision the necessary AWS infrastructure, including the EC2 instance and networking components.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729852477764/1072247b-79f3-4313-8f7b-53db12ff32af.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;To learn more, checkout this repository:&lt;br /&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://github.com/Brain2life/terraform-cookbook/tree/main/example-rpc-call-to-ec2&quot;&gt;https://github.com/Brain2life/terraform-cookbook/tree/main/example-rpc-call-to-ec2&lt;/a&gt;&lt;/p&gt;&lt;h3 id=&quot;heading-references&quot;&gt;References:&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://www.youtube.com/watch?app=desktop&amp;amp;v=S2osKiqQG9s&quot;&gt;YouTube: Distributed Systems 1.3: RPC (Remote Procedure Call)&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;]]&gt;</hashnode:content><hashnode:coverImage>https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/EkC1RcOmfmE/upload/9901f568aa8fe070b9c2c323b2d43e0b.jpeg</hashnode:coverImage></item><item><title><![CDATA[AWS Route 53: Latency-based Routing Policy]]></title><description><![CDATA[AWS Route 53: Latency-based Routing Policy]]></description><link>https://maxat-akbanov.com/aws-route-53-latency-based-routing-policy</link><guid isPermaLink="true">https://maxat-akbanov.com/aws-route-53-latency-based-routing-policy</guid><category><![CDATA[Devops]]></category><category><![CDATA[AWS]]></category><category><![CDATA[sysops]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[dns]]></category><category><![CDATA[route53]]></category><category><![CDATA[latency]]></category><dc:creator><![CDATA[Maxat Akbanov]]></dc:creator><pubDate>Fri, 18 Oct 2024 08:21:34 GMT</pubDate><content:encoded>&lt;![CDATA[&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy-latency.html&quot;&gt;&lt;strong&gt;Latency-based routing (LBR)&lt;/strong&gt;&lt;/a&gt; in AWS Route 53 is designed to route end-user requests to the AWS region that provides the lowest latency. This routing policy ensures that users are connected to the closest and fastest endpoint (in terms of network latency), enhancing performance by reducing delays in the communication path between the users and your application. Data about the latency between users and your resources is based entirely on traffic between users and AWS data centers.&lt;/p&gt;&lt;hr /&gt;&lt;h3 id=&quot;heading-how-it-works&quot;&gt;&lt;strong&gt;How It Works&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;AWS measures &lt;strong&gt;network latency&lt;/strong&gt; between different regions and end users.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;When a DNS request is received, Route 53 determines which endpoint (from your configured set of endpoints) offers the &lt;strong&gt;lowest latency&lt;/strong&gt; to the users location.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Route 53 &lt;strong&gt;returns the IP address&lt;/strong&gt; (or CNAME) of the selected endpoint to the user&apos;s browser or application.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;This helps ensure that users from different parts of the world are connected to the fastest AWS region, reducing response times and improving user experience.&lt;/p&gt;&lt;div data-node-type=&quot;callout&quot;&gt;&lt;div data-node-type=&quot;callout-emoji&quot;&gt;&lt;/div&gt;&lt;div data-node-type=&quot;callout-text&quot;&gt;Latency between hosts on the internet can change over time as a result of changes in network connectivity and routing. Latency-based routing is based on latency measurements taken over a period of time, and the measurements reflect these changes. For example a request that is routed to the Oregon Region this week might be routed to the Singapore Region next week.&lt;/div&gt;&lt;/div&gt;&lt;hr /&gt;&lt;h3 id=&quot;heading-example-scenario&quot;&gt;&lt;strong&gt;Example Scenario&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;Assume your application is deployed in multiple regions:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;US-East (N. Virginia)&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;EU-Central (Frankfurt)&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;AP-Southeast (Singapore)&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;A user from &lt;strong&gt;Canada&lt;/strong&gt; sends a request. Route 53 detects that the &lt;strong&gt;US-East&lt;/strong&gt; region provides the lowest latency and directs the traffic there.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;A user from &lt;strong&gt;Spain&lt;/strong&gt; sends a request. Route 53 determines the &lt;strong&gt;EU-Central&lt;/strong&gt; endpoint has the lowest latency and routes the traffic there.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Similarly, users in &lt;strong&gt;Hong Kong&lt;/strong&gt; will be directed to the &lt;strong&gt;AP-Southeast&lt;/strong&gt; region.&lt;/p&gt;&lt;p&gt;  &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729237365032/57b7b85d-c149-4e89-8982-4b79aa29e730.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr /&gt;&lt;h3 id=&quot;heading-use-case&quot;&gt;&lt;strong&gt;Use Case&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;Latency-based routing is particularly useful when:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;You have a &lt;strong&gt;multi-region&lt;/strong&gt; architecture, with your resources (like EC2 instances, load balancers, or API Gateway) deployed across multiple AWS regions.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;You want to &lt;strong&gt;minimize latency&lt;/strong&gt; and &lt;strong&gt;improve response times&lt;/strong&gt; for users located around the globe.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr /&gt;&lt;h3 id=&quot;heading-steps-to-set-up-latency-based-routing-in-console&quot;&gt;&lt;strong&gt;Steps to Set Up Latency-Based Routing in Console&lt;/strong&gt;&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create your resources&lt;/strong&gt; in multiple AWS regions (like an Application Load Balancer, EC2 instances, or an S3 static website).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Set up a hosted zone&lt;/strong&gt; in Route 53 for your domain.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create latency-based records&lt;/strong&gt; in Route 53:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Choose &lt;strong&gt;A or CNAME record&lt;/strong&gt; type.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Select the &lt;strong&gt;region&lt;/strong&gt; associated with each endpoint.&lt;/p&gt;&lt;p&gt;  &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729238049827/7995e6ed-6ba4-4f59-ab9b-299cc3121ca8.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;AWS will automatically direct traffic based on the latency between the user and your endpoints.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;hr /&gt;&lt;h3 id=&quot;heading-latency-based-routing-example-code-in-terraform&quot;&gt;&lt;strong&gt;Latency-Based Routing Example Code in Terraform&lt;/strong&gt;&lt;/h3&gt;&lt;pre&gt;&lt;code class=&quot;lang-plaintext&quot;&gt;resource &quot;aws_route53_record&quot; &quot;latency_us_east_1&quot; {  zone_id = &quot;Z03242191HGJ5WDONGNAD&quot;  # Replace with your hosted zone ID  name    = &quot;latency-us-east-1&quot;  type    = &quot;A&quot;  ttl     = 60  set_identifier = &quot;us-east-1&quot;  records = [&quot;192.0.2.1&quot;]  # Replace with your IP address or DNS name  latency_routing_policy {    region = &quot;us-east-1&quot;  }}resource &quot;aws_route53_record&quot; &quot;latency_us_west_2&quot; {  zone_id = &quot;Z03242191HGJ5WDONGNAD&quot;  name    = &quot;latency-us-west-2&quot;  type    = &quot;A&quot;  ttl     = 60  set_identifier = &quot;us-west-2&quot;  records = [&quot;192.0.2.2&quot;]  # Replace with your IP address or DNS name  latency_routing_policy {    region = &quot;us-west-2&quot;  }}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This Terraform code creates two latency-based records for the &lt;code&gt;Z03242191HGJ5WDONGNAD&lt;/code&gt; hosted zode in &lt;code&gt;us-east-1&lt;/code&gt; and &lt;code&gt;us-west-2&lt;/code&gt; regions:&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729239480691/4bb2a3fb-59c4-4f97-9267-d9c8693eb818.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;For more information, see &lt;a target=&quot;_blank&quot; href=&quot;https://registry.terraform.io/providers/rgeraskin/aws2/latest/docs/resources/route53_record#latency_routing_policy&quot;&gt;Terraform: aws_route53_record resource&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;h3 id=&quot;heading-health-checks-and-latency-based-routing&quot;&gt;&lt;strong&gt;Health Checks and Latency-Based Routing&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Health checks&lt;/strong&gt; can be integrated with latency-based routing to ensure that Route 53 sends requests only to &lt;strong&gt;healthy endpoints&lt;/strong&gt;. If one of your regions is down, Route 53 will automatically exclude it from routing decisions.&lt;/li&gt;&lt;/ul&gt;&lt;hr /&gt;&lt;h3 id=&quot;heading-limitations&quot;&gt;&lt;strong&gt;Limitations&lt;/strong&gt;&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;Latency-based routing only improves &lt;strong&gt;network performance&lt;/strong&gt;, not application processing time.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Not suitable&lt;/strong&gt; for use cases where traffic should be directed to a specific endpoint (like compliance or regulatory needs).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;AWS regions may experience &lt;strong&gt;dynamic latency changes&lt;/strong&gt; based on internet conditions, so results are not always guaranteed to be consistent.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;hr /&gt;&lt;h3 id=&quot;heading-summary&quot;&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;AWS Route 53s &lt;strong&gt;Latency-Based Routing Policy&lt;/strong&gt; is an excellent way to ensure low-latency experiences by directing traffic to the nearest and fastest AWS region. It is particularly useful for &lt;strong&gt;global applications&lt;/strong&gt; with users distributed across different geographical locations, such as content delivery systems, real-time gaming platforms, and multi-region web applications.&lt;/p&gt;]]&gt;</content:encoded><hashnode:content>&lt;![CDATA[&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy-latency.html&quot;&gt;&lt;strong&gt;Latency-based routing (LBR)&lt;/strong&gt;&lt;/a&gt; in AWS Route 53 is designed to route end-user requests to the AWS region that provides the lowest latency. This routing policy ensures that users are connected to the closest and fastest endpoint (in terms of network latency), enhancing performance by reducing delays in the communication path between the users and your application. Data about the latency between users and your resources is based entirely on traffic between users and AWS data centers.&lt;/p&gt;&lt;hr /&gt;&lt;h3 id=&quot;heading-how-it-works&quot;&gt;&lt;strong&gt;How It Works&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;AWS measures &lt;strong&gt;network latency&lt;/strong&gt; between different regions and end users.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;When a DNS request is received, Route 53 determines which endpoint (from your configured set of endpoints) offers the &lt;strong&gt;lowest latency&lt;/strong&gt; to the users location.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Route 53 &lt;strong&gt;returns the IP address&lt;/strong&gt; (or CNAME) of the selected endpoint to the user&apos;s browser or application.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;This helps ensure that users from different parts of the world are connected to the fastest AWS region, reducing response times and improving user experience.&lt;/p&gt;&lt;div data-node-type=&quot;callout&quot;&gt;&lt;div data-node-type=&quot;callout-emoji&quot;&gt;&lt;/div&gt;&lt;div data-node-type=&quot;callout-text&quot;&gt;Latency between hosts on the internet can change over time as a result of changes in network connectivity and routing. Latency-based routing is based on latency measurements taken over a period of time, and the measurements reflect these changes. For example a request that is routed to the Oregon Region this week might be routed to the Singapore Region next week.&lt;/div&gt;&lt;/div&gt;&lt;hr /&gt;&lt;h3 id=&quot;heading-example-scenario&quot;&gt;&lt;strong&gt;Example Scenario&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;Assume your application is deployed in multiple regions:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;US-East (N. Virginia)&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;EU-Central (Frankfurt)&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;AP-Southeast (Singapore)&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;A user from &lt;strong&gt;Canada&lt;/strong&gt; sends a request. Route 53 detects that the &lt;strong&gt;US-East&lt;/strong&gt; region provides the lowest latency and directs the traffic there.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;A user from &lt;strong&gt;Spain&lt;/strong&gt; sends a request. Route 53 determines the &lt;strong&gt;EU-Central&lt;/strong&gt; endpoint has the lowest latency and routes the traffic there.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Similarly, users in &lt;strong&gt;Hong Kong&lt;/strong&gt; will be directed to the &lt;strong&gt;AP-Southeast&lt;/strong&gt; region.&lt;/p&gt;&lt;p&gt;  &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729237365032/57b7b85d-c149-4e89-8982-4b79aa29e730.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr /&gt;&lt;h3 id=&quot;heading-use-case&quot;&gt;&lt;strong&gt;Use Case&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;Latency-based routing is particularly useful when:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;You have a &lt;strong&gt;multi-region&lt;/strong&gt; architecture, with your resources (like EC2 instances, load balancers, or API Gateway) deployed across multiple AWS regions.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;You want to &lt;strong&gt;minimize latency&lt;/strong&gt; and &lt;strong&gt;improve response times&lt;/strong&gt; for users located around the globe.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr /&gt;&lt;h3 id=&quot;heading-steps-to-set-up-latency-based-routing-in-console&quot;&gt;&lt;strong&gt;Steps to Set Up Latency-Based Routing in Console&lt;/strong&gt;&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create your resources&lt;/strong&gt; in multiple AWS regions (like an Application Load Balancer, EC2 instances, or an S3 static website).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Set up a hosted zone&lt;/strong&gt; in Route 53 for your domain.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create latency-based records&lt;/strong&gt; in Route 53:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Choose &lt;strong&gt;A or CNAME record&lt;/strong&gt; type.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Select the &lt;strong&gt;region&lt;/strong&gt; associated with each endpoint.&lt;/p&gt;&lt;p&gt;  &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729238049827/7995e6ed-6ba4-4f59-ab9b-299cc3121ca8.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;AWS will automatically direct traffic based on the latency between the user and your endpoints.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;hr /&gt;&lt;h3 id=&quot;heading-latency-based-routing-example-code-in-terraform&quot;&gt;&lt;strong&gt;Latency-Based Routing Example Code in Terraform&lt;/strong&gt;&lt;/h3&gt;&lt;pre&gt;&lt;code class=&quot;lang-plaintext&quot;&gt;resource &quot;aws_route53_record&quot; &quot;latency_us_east_1&quot; {  zone_id = &quot;Z03242191HGJ5WDONGNAD&quot;  # Replace with your hosted zone ID  name    = &quot;latency-us-east-1&quot;  type    = &quot;A&quot;  ttl     = 60  set_identifier = &quot;us-east-1&quot;  records = [&quot;192.0.2.1&quot;]  # Replace with your IP address or DNS name  latency_routing_policy {    region = &quot;us-east-1&quot;  }}resource &quot;aws_route53_record&quot; &quot;latency_us_west_2&quot; {  zone_id = &quot;Z03242191HGJ5WDONGNAD&quot;  name    = &quot;latency-us-west-2&quot;  type    = &quot;A&quot;  ttl     = 60  set_identifier = &quot;us-west-2&quot;  records = [&quot;192.0.2.2&quot;]  # Replace with your IP address or DNS name  latency_routing_policy {    region = &quot;us-west-2&quot;  }}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This Terraform code creates two latency-based records for the &lt;code&gt;Z03242191HGJ5WDONGNAD&lt;/code&gt; hosted zode in &lt;code&gt;us-east-1&lt;/code&gt; and &lt;code&gt;us-west-2&lt;/code&gt; regions:&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729239480691/4bb2a3fb-59c4-4f97-9267-d9c8693eb818.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;For more information, see &lt;a target=&quot;_blank&quot; href=&quot;https://registry.terraform.io/providers/rgeraskin/aws2/latest/docs/resources/route53_record#latency_routing_policy&quot;&gt;Terraform: aws_route53_record resource&lt;/a&gt;&lt;/p&gt;&lt;hr /&gt;&lt;h3 id=&quot;heading-health-checks-and-latency-based-routing&quot;&gt;&lt;strong&gt;Health Checks and Latency-Based Routing&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Health checks&lt;/strong&gt; can be integrated with latency-based routing to ensure that Route 53 sends requests only to &lt;strong&gt;healthy endpoints&lt;/strong&gt;. If one of your regions is down, Route 53 will automatically exclude it from routing decisions.&lt;/li&gt;&lt;/ul&gt;&lt;hr /&gt;&lt;h3 id=&quot;heading-limitations&quot;&gt;&lt;strong&gt;Limitations&lt;/strong&gt;&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;Latency-based routing only improves &lt;strong&gt;network performance&lt;/strong&gt;, not application processing time.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Not suitable&lt;/strong&gt; for use cases where traffic should be directed to a specific endpoint (like compliance or regulatory needs).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;AWS regions may experience &lt;strong&gt;dynamic latency changes&lt;/strong&gt; based on internet conditions, so results are not always guaranteed to be consistent.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;hr /&gt;&lt;h3 id=&quot;heading-summary&quot;&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;AWS Route 53s &lt;strong&gt;Latency-Based Routing Policy&lt;/strong&gt; is an excellent way to ensure low-latency experiences by directing traffic to the nearest and fastest AWS region. It is particularly useful for &lt;strong&gt;global applications&lt;/strong&gt; with users distributed across different geographical locations, such as content delivery systems, real-time gaming platforms, and multi-region web applications.&lt;/p&gt;]]&gt;</hashnode:content><hashnode:coverImage>https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/18T72jBinvI/upload/61822630f3309374dcaa8431c7e408b2.jpeg</hashnode:coverImage></item><item><title><![CDATA[Securing Secrets with SOPS: An Introduction]]></title><description><![CDATA[Securing Secrets with SOPS: An Introduction]]></description><link>https://maxat-akbanov.com/securing-secrets-with-sops-an-introduction</link><guid isPermaLink="true">https://maxat-akbanov.com/securing-secrets-with-sops-an-introduction</guid><category><![CDATA[Devops]]></category><category><![CDATA[sysops]]></category><category><![CDATA[#cybersecurity]]></category><category><![CDATA[Security]]></category><category><![CDATA[tools]]></category><category><![CDATA[PGP]]></category><category><![CDATA[SOPS]]></category><category><![CDATA[KeyManagement]]></category><category><![CDATA[secrets]]></category><dc:creator><![CDATA[Maxat Akbanov]]></dc:creator><pubDate>Thu, 17 Oct 2024 11:10:24 GMT</pubDate><content:encoded>&lt;![CDATA[&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://github.com/getsops/sops&quot;&gt;SOPS&lt;/a&gt; (&lt;strong&gt;S&lt;/strong&gt;ecrets &lt;strong&gt;OP&lt;/strong&gt;eration&lt;strong&gt;S&lt;/strong&gt;) is an open-source tool developed by Mozilla for managing secrets  such as passwords, API keys, and confidential configuration data  in a secure and convenient manner. Initially launched in 2015 as a Mozilla project, it has been donated and accepted to CNCF on May 17, 2023. It serves as an editor for encrypted files, supporting various formats including YAML, JSON, ENV, INI, and binary files. SOPS integrates seamlessly with key management systems like &lt;a target=&quot;_blank&quot; href=&quot;https://aws.amazon.com/kms/&quot;&gt;AWS KMS&lt;/a&gt;, &lt;a target=&quot;_blank&quot; href=&quot;https://cloud.google.com/security/products/security-key-management&quot;&gt;GCP KMS&lt;/a&gt;, &lt;a target=&quot;_blank&quot; href=&quot;https://azure.microsoft.com/en-us/products/key-vault&quot;&gt;Azure Key Vault&lt;/a&gt;, &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/FiloSottile/age&quot;&gt;age&lt;/a&gt;, and &lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Pretty_Good_Privacy&quot;&gt;PGP&lt;/a&gt; to encrypt and decrypt data.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729104803942/d05d9eec-e7af-4b17-9434-74b8f580e899.gif&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;The main benefit of the tool is that you dont have to encrypt and decrypt the files with one tool and then read them with another tool. Sops allows you to edit and read the secret values right inside the &lt;code&gt;sops&lt;/code&gt; text editor! Hence, you avoid using two tools and simplify the secret management. The secret values inside the &lt;code&gt;sops&lt;/code&gt; editor are encrypted and decrypted automatically.&lt;/p&gt;&lt;p&gt;SOPS is a powerful tool that bridges the gap between security and usability in secret management. By integrating with industry-standard key management systems and supporting a variety of file formats, it provides a secure and efficient way to handle sensitive information within collaborative and automated environments.&lt;/p&gt;&lt;h2 id=&quot;heading-key-features&quot;&gt;&lt;strong&gt;Key Features&lt;/strong&gt;&lt;/h2&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multi-Format Support&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;YAML, JSON, ENV, INI, and Binary Files&lt;/strong&gt;: SOPS can handle a variety of file formats commonly used in configuration and environment settings.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Encryption Mechanisms&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://aws.amazon.com/kms/&quot;&gt;AWS KMS&lt;/a&gt;&lt;strong&gt;,&lt;/strong&gt; &lt;a target=&quot;_blank&quot; href=&quot;https://cloud.google.com/security/products/security-key-management&quot;&gt;GCP KMS&lt;/a&gt;&lt;strong&gt;,&lt;/strong&gt; &lt;a target=&quot;_blank&quot; href=&quot;https://azure.microsoft.com/en-us/products/key-vault&quot;&gt;Azure Key Vault&lt;/a&gt;: Leverage cloud-based key management services to encrypt and decrypt secrets.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://github.com/FiloSottile/age&quot;&gt;age&lt;/a&gt;: A modern, simple, and secure file encryption tool.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://nsrc.org/workshops/2014/sanog23-security/raw-attachment/wiki/Agenda/2-1-1.pgp-lab.html&quot;&gt;&lt;strong&gt;PGP&lt;/strong&gt;&lt;/a&gt;: Utilize Pretty Good Privacy keys for encryption, supporting both public and private key pairs.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Selective Encryption&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Encrypts Only the Values&lt;/strong&gt;: SOPS encrypts the values within the file while keeping the keys and structure in plaintext. This approach allows the file to remain human-readable in terms of structure and facilitates easier version control and diffing.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Version Control Friendly&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Git Integration&lt;/strong&gt;: Encrypted files can be safely stored in version control systems like Git, enabling collaborative workflows without exposing sensitive information.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ease of Use&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Transparent Editing&lt;/strong&gt;: SOPS allows you to edit encrypted files as if they were unencrypted. It handles the encryption and decryption transparently during the editing process.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Command-Line Interface&lt;/strong&gt;: Provides a CLI &lt;code&gt;sops&lt;/code&gt; tool for easy integration into scripts and automation pipelines.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h2 id=&quot;heading-installation-on-linux&quot;&gt;Installation on Linux&lt;/h2&gt;&lt;p&gt;Binaries and packages of the latest stable release are available at &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/getsops/sops/releases&quot;&gt;https://github.com/getsops/sops/releases.&lt;/a&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;To install &lt;code&gt;sops&lt;/code&gt; on Linux on an AMD64 architecture:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Download the binary&lt;/span&gt; curl -LO https://github.com/getsops/sops/releases/download/v3.9.1/sops-v3.9.1.linux.amd64 &lt;span class=&quot;hljs-comment&quot;&gt;# Move the binary in to your PATH&lt;/span&gt; sudo mv sops-v3.9.1.linux.amd64 /usr/&lt;span class=&quot;hljs-built_in&quot;&gt;local&lt;/span&gt;/bin/sops &lt;span class=&quot;hljs-comment&quot;&gt;# Make the binary executable&lt;/span&gt; sudo chmod +x /usr/&lt;span class=&quot;hljs-built_in&quot;&gt;local&lt;/span&gt;/bin/sops&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Install &lt;a target=&quot;_blank&quot; href=&quot;https://www.sigstore.dev/&quot;&gt;&lt;code&gt;cosign&lt;/code&gt;&lt;/a&gt; tool for checksum and signature verification:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Download the latest release file for your Linux architecutre (e.g. amd64)&lt;/span&gt; wget https://github.com/sigstore/cosign/releases/download/v2.4.1/cosign-linux-amd64 &lt;span class=&quot;hljs-comment&quot;&gt;# Move the binary in to your PATH&lt;/span&gt; sudo mv cosign-linux-amd64 /usr/&lt;span class=&quot;hljs-built_in&quot;&gt;local&lt;/span&gt;/bin/cosign &lt;span class=&quot;hljs-comment&quot;&gt;# Make the binary executable&lt;/span&gt; chmod +x /usr/&lt;span class=&quot;hljs-built_in&quot;&gt;local&lt;/span&gt;/bin/cosign&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Verify the installation:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Download the checksums file, certificate and signature&lt;/span&gt; curl -LO https://github.com/getsops/sops/releases/download/v3.9.1/sops-v3.9.1.checksums.txt curl -LO https://github.com/getsops/sops/releases/download/v3.9.1/sops-v3.9.1.checksums.pem curl -LO https://github.com/getsops/sops/releases/download/v3.9.1/sops-v3.9.1.checksums.sig &lt;span class=&quot;hljs-comment&quot;&gt;# Verify the checksums file&lt;/span&gt; cosign verify-blob sops-v3.9.1.checksums.txt \   --certificate sops-v3.9.1.checksums.pem \   --signature sops-v3.9.1.checksums.sig \   --certificate-identity-regexp=https://github.com/getsops \   --certificate-oidc-issuer=https://token.actions.githubusercontent.com&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h2 id=&quot;heading-how-sops-works&quot;&gt;&lt;strong&gt;How SOPS Works&lt;/strong&gt;&lt;/h2&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data Encryption Key (DEK)&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;SOPS &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/getsops/sops?tab=readme-ov-file#5encryption-protocol&quot;&gt;generates a symmetric Data Encryption Key&lt;/a&gt; for encrypting the actual data within the file.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Master Key Encryption&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The DEK is encrypted using one or more master keys from your chosen key management services (e.g., AWS KMS, GCP KMS, Azure Key Vault, PGP).&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;    &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729160132625/d9690b72-76c5-422f-9710-fd73001792d3.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;ol start=&quot;3&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;File Structure Preservation&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;By encrypting only the values and not the keys or structure, SOPS ensures that the file remains partially readable. This feature is particularly useful for understanding the configuration without exposing sensitive data.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Decryption Process&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;When you open a file with SOPS, it decrypts the values on-the-fly using the appropriate master keys. After editing, it re-encrypts the values before saving.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h2 id=&quot;heading-use-cases&quot;&gt;&lt;strong&gt;Use Cases&lt;/strong&gt;&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Secure Configuration Management&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Store application configurations that contain secrets in a secure manner.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Infrastructure as Code (IaC)&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Embed encrypted secrets within your IaC templates for tools like Kubernetes, Terraform, or Ansible.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Collaborative Environments&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Allow multiple team members to access and edit secrets securely without sharing plaintext secrets.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automated Deployment Pipelines&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Integrate SOPS into CI/CD pipelines to decrypt secrets during the deployment process securely.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&quot;heading-using-sops-with-pgp-and-a-text-file&quot;&gt;&lt;strong&gt;Using SOPS with PGP and a text file&lt;/strong&gt;&lt;/h2&gt;&lt;p&gt;Below is an example of how to encrypt and decrypt a text file using &lt;strong&gt;SOPS with PGP&lt;/strong&gt;.&lt;/p&gt;&lt;h3 id=&quot;heading-prerequisites&quot;&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Install GPG (GNU Privacy Guard):&lt;/strong&gt;&lt;/p&gt;&lt;p&gt; On Ubuntu:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; sudo apt install gnupg&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Generate a PGP key pair&lt;/strong&gt; if you don&apos;t already have one:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; gpg --full-generate-key&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Use RSA encryption (default).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Provide your name, email, and password as requested.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;List the generated key and keep the note of the key fingerprint:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; gpg --list-secret-keys &lt;span class=&quot;hljs-string&quot;&gt;&quot;&amp;lt;your_key_name&amp;gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729161282589/ac29915f-d260-4d78-b274-5f8a1b1e130e.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Export the PGP public key&lt;/strong&gt; to encrypt files:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; gpg --armor --&lt;span class=&quot;hljs-built_in&quot;&gt;export&lt;/span&gt; [key_id] &amp;gt; my-public-key.asc&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Export the PGP private key&lt;/strong&gt; to decrypt files:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; gpg --armor --export-secret-keys [key_id] &amp;gt; my-private-key.asc&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-encrypting-a-text-file-using-sops-and-pgp&quot;&gt;&lt;strong&gt;Encrypting a Text File using SOPS and PGP&lt;/strong&gt;&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create a sample text file&lt;/strong&gt; to encrypt:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;my-secret-password&quot;&lt;/span&gt; &amp;gt; secret.txt&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Configure the default encryption and decryption behavior of SOPS tool&lt;/strong&gt;. Create a file named &lt;code&gt;.sops.yaml&lt;/code&gt; under the &lt;code&gt;$HOME&lt;/code&gt; directory with the Key ID from the previous steps:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; creation_rules:     - pgp: &amp;gt;-         C0B4391E80CDBF4FCE820212F9D999A91B838104&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Encrypt the file using SOPS and your PGP key:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; sops --encrypt secret.txt &amp;gt; secret.enc.txt&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; This will encrypt the &lt;code&gt;secret.txt&lt;/code&gt; file with the default PGP key specified in &lt;code&gt;.sops.yaml&lt;/code&gt; file.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Verify the encrypted content:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; cat secret.enc.txt&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; You should see a YAML structure with encrypted content that looks like this:&lt;/p&gt;&lt;p&gt; &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729162884456/9511ec7e-e458-440f-b6d2-9b481b2b45d2.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-decrypting-the-text-file&quot;&gt;&lt;strong&gt;Decrypting the Text File&lt;/strong&gt;&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use SOPS to decrypt the encrypted file:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; sops --decrypt secret.enc.txt &amp;gt; decrypted.txt&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;View the decrypted content:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; cat decrypted.txt&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; You should see the original text:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; my-secret-password&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-automating-decryption-in-configuration-files&quot;&gt;&lt;strong&gt;Automating Decryption in Configuration Files&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;You can use SOPS-encrypted files in your configuration by decrypting them on the fly, such as:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;export&lt;/span&gt; MY_SECRET=$(sops --decrypt --input-type binary secret.enc.txt)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729163081990/3dbacecd-ff77-426b-b828-cf0838cc1f18.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;This example shows how to use &lt;strong&gt;SOPS&lt;/strong&gt; with &lt;strong&gt;PGP&lt;/strong&gt; to encrypt and decrypt a text file. With PGP encryption, you can ensure that only users with the appropriate private key can decrypt the file, making it ideal for managing secrets in infrastructure code or configuration files.&lt;/p&gt;&lt;h2 id=&quot;heading-references&quot;&gt;References:&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://getsops.io/&quot;&gt;getsops.io&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://blog.gitguardian.com/a-comprehensive-guide-to-sops/&quot;&gt;GitGuardian Blog: A Comprehensive Guide to SOPS: Managing Your Secrets Like A Visionary, Not a Functionary&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://www.youtube.com/watch?v=V2PRhxphH2w&quot;&gt;YouTube: Securing DevOps Show &amp;amp; Tell: Mozilla Sops&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://marketplace.visualstudio.com/items?itemName=signageos.signageos-vscode-sops&quot;&gt;VSCode SOPS extension&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;]]&gt;</content:encoded><hashnode:content>&lt;![CDATA[&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://github.com/getsops/sops&quot;&gt;SOPS&lt;/a&gt; (&lt;strong&gt;S&lt;/strong&gt;ecrets &lt;strong&gt;OP&lt;/strong&gt;eration&lt;strong&gt;S&lt;/strong&gt;) is an open-source tool developed by Mozilla for managing secrets  such as passwords, API keys, and confidential configuration data  in a secure and convenient manner. Initially launched in 2015 as a Mozilla project, it has been donated and accepted to CNCF on May 17, 2023. It serves as an editor for encrypted files, supporting various formats including YAML, JSON, ENV, INI, and binary files. SOPS integrates seamlessly with key management systems like &lt;a target=&quot;_blank&quot; href=&quot;https://aws.amazon.com/kms/&quot;&gt;AWS KMS&lt;/a&gt;, &lt;a target=&quot;_blank&quot; href=&quot;https://cloud.google.com/security/products/security-key-management&quot;&gt;GCP KMS&lt;/a&gt;, &lt;a target=&quot;_blank&quot; href=&quot;https://azure.microsoft.com/en-us/products/key-vault&quot;&gt;Azure Key Vault&lt;/a&gt;, &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/FiloSottile/age&quot;&gt;age&lt;/a&gt;, and &lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Pretty_Good_Privacy&quot;&gt;PGP&lt;/a&gt; to encrypt and decrypt data.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729104803942/d05d9eec-e7af-4b17-9434-74b8f580e899.gif&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;The main benefit of the tool is that you dont have to encrypt and decrypt the files with one tool and then read them with another tool. Sops allows you to edit and read the secret values right inside the &lt;code&gt;sops&lt;/code&gt; text editor! Hence, you avoid using two tools and simplify the secret management. The secret values inside the &lt;code&gt;sops&lt;/code&gt; editor are encrypted and decrypted automatically.&lt;/p&gt;&lt;p&gt;SOPS is a powerful tool that bridges the gap between security and usability in secret management. By integrating with industry-standard key management systems and supporting a variety of file formats, it provides a secure and efficient way to handle sensitive information within collaborative and automated environments.&lt;/p&gt;&lt;h2 id=&quot;heading-key-features&quot;&gt;&lt;strong&gt;Key Features&lt;/strong&gt;&lt;/h2&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multi-Format Support&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;YAML, JSON, ENV, INI, and Binary Files&lt;/strong&gt;: SOPS can handle a variety of file formats commonly used in configuration and environment settings.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Encryption Mechanisms&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://aws.amazon.com/kms/&quot;&gt;AWS KMS&lt;/a&gt;&lt;strong&gt;,&lt;/strong&gt; &lt;a target=&quot;_blank&quot; href=&quot;https://cloud.google.com/security/products/security-key-management&quot;&gt;GCP KMS&lt;/a&gt;&lt;strong&gt;,&lt;/strong&gt; &lt;a target=&quot;_blank&quot; href=&quot;https://azure.microsoft.com/en-us/products/key-vault&quot;&gt;Azure Key Vault&lt;/a&gt;: Leverage cloud-based key management services to encrypt and decrypt secrets.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://github.com/FiloSottile/age&quot;&gt;age&lt;/a&gt;: A modern, simple, and secure file encryption tool.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://nsrc.org/workshops/2014/sanog23-security/raw-attachment/wiki/Agenda/2-1-1.pgp-lab.html&quot;&gt;&lt;strong&gt;PGP&lt;/strong&gt;&lt;/a&gt;: Utilize Pretty Good Privacy keys for encryption, supporting both public and private key pairs.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Selective Encryption&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Encrypts Only the Values&lt;/strong&gt;: SOPS encrypts the values within the file while keeping the keys and structure in plaintext. This approach allows the file to remain human-readable in terms of structure and facilitates easier version control and diffing.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Version Control Friendly&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Git Integration&lt;/strong&gt;: Encrypted files can be safely stored in version control systems like Git, enabling collaborative workflows without exposing sensitive information.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ease of Use&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Transparent Editing&lt;/strong&gt;: SOPS allows you to edit encrypted files as if they were unencrypted. It handles the encryption and decryption transparently during the editing process.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Command-Line Interface&lt;/strong&gt;: Provides a CLI &lt;code&gt;sops&lt;/code&gt; tool for easy integration into scripts and automation pipelines.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h2 id=&quot;heading-installation-on-linux&quot;&gt;Installation on Linux&lt;/h2&gt;&lt;p&gt;Binaries and packages of the latest stable release are available at &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/getsops/sops/releases&quot;&gt;https://github.com/getsops/sops/releases.&lt;/a&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;To install &lt;code&gt;sops&lt;/code&gt; on Linux on an AMD64 architecture:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Download the binary&lt;/span&gt; curl -LO https://github.com/getsops/sops/releases/download/v3.9.1/sops-v3.9.1.linux.amd64 &lt;span class=&quot;hljs-comment&quot;&gt;# Move the binary in to your PATH&lt;/span&gt; sudo mv sops-v3.9.1.linux.amd64 /usr/&lt;span class=&quot;hljs-built_in&quot;&gt;local&lt;/span&gt;/bin/sops &lt;span class=&quot;hljs-comment&quot;&gt;# Make the binary executable&lt;/span&gt; sudo chmod +x /usr/&lt;span class=&quot;hljs-built_in&quot;&gt;local&lt;/span&gt;/bin/sops&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Install &lt;a target=&quot;_blank&quot; href=&quot;https://www.sigstore.dev/&quot;&gt;&lt;code&gt;cosign&lt;/code&gt;&lt;/a&gt; tool for checksum and signature verification:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Download the latest release file for your Linux architecutre (e.g. amd64)&lt;/span&gt; wget https://github.com/sigstore/cosign/releases/download/v2.4.1/cosign-linux-amd64 &lt;span class=&quot;hljs-comment&quot;&gt;# Move the binary in to your PATH&lt;/span&gt; sudo mv cosign-linux-amd64 /usr/&lt;span class=&quot;hljs-built_in&quot;&gt;local&lt;/span&gt;/bin/cosign &lt;span class=&quot;hljs-comment&quot;&gt;# Make the binary executable&lt;/span&gt; chmod +x /usr/&lt;span class=&quot;hljs-built_in&quot;&gt;local&lt;/span&gt;/bin/cosign&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Verify the installation:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Download the checksums file, certificate and signature&lt;/span&gt; curl -LO https://github.com/getsops/sops/releases/download/v3.9.1/sops-v3.9.1.checksums.txt curl -LO https://github.com/getsops/sops/releases/download/v3.9.1/sops-v3.9.1.checksums.pem curl -LO https://github.com/getsops/sops/releases/download/v3.9.1/sops-v3.9.1.checksums.sig &lt;span class=&quot;hljs-comment&quot;&gt;# Verify the checksums file&lt;/span&gt; cosign verify-blob sops-v3.9.1.checksums.txt \   --certificate sops-v3.9.1.checksums.pem \   --signature sops-v3.9.1.checksums.sig \   --certificate-identity-regexp=https://github.com/getsops \   --certificate-oidc-issuer=https://token.actions.githubusercontent.com&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h2 id=&quot;heading-how-sops-works&quot;&gt;&lt;strong&gt;How SOPS Works&lt;/strong&gt;&lt;/h2&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data Encryption Key (DEK)&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;SOPS &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/getsops/sops?tab=readme-ov-file#5encryption-protocol&quot;&gt;generates a symmetric Data Encryption Key&lt;/a&gt; for encrypting the actual data within the file.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Master Key Encryption&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The DEK is encrypted using one or more master keys from your chosen key management services (e.g., AWS KMS, GCP KMS, Azure Key Vault, PGP).&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;    &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729160132625/d9690b72-76c5-422f-9710-fd73001792d3.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;ol start=&quot;3&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;File Structure Preservation&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;By encrypting only the values and not the keys or structure, SOPS ensures that the file remains partially readable. This feature is particularly useful for understanding the configuration without exposing sensitive data.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Decryption Process&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;When you open a file with SOPS, it decrypts the values on-the-fly using the appropriate master keys. After editing, it re-encrypts the values before saving.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h2 id=&quot;heading-use-cases&quot;&gt;&lt;strong&gt;Use Cases&lt;/strong&gt;&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Secure Configuration Management&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Store application configurations that contain secrets in a secure manner.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Infrastructure as Code (IaC)&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Embed encrypted secrets within your IaC templates for tools like Kubernetes, Terraform, or Ansible.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Collaborative Environments&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Allow multiple team members to access and edit secrets securely without sharing plaintext secrets.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automated Deployment Pipelines&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Integrate SOPS into CI/CD pipelines to decrypt secrets during the deployment process securely.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&quot;heading-using-sops-with-pgp-and-a-text-file&quot;&gt;&lt;strong&gt;Using SOPS with PGP and a text file&lt;/strong&gt;&lt;/h2&gt;&lt;p&gt;Below is an example of how to encrypt and decrypt a text file using &lt;strong&gt;SOPS with PGP&lt;/strong&gt;.&lt;/p&gt;&lt;h3 id=&quot;heading-prerequisites&quot;&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Install GPG (GNU Privacy Guard):&lt;/strong&gt;&lt;/p&gt;&lt;p&gt; On Ubuntu:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; sudo apt install gnupg&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Generate a PGP key pair&lt;/strong&gt; if you don&apos;t already have one:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; gpg --full-generate-key&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Use RSA encryption (default).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Provide your name, email, and password as requested.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;List the generated key and keep the note of the key fingerprint:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; gpg --list-secret-keys &lt;span class=&quot;hljs-string&quot;&gt;&quot;&amp;lt;your_key_name&amp;gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729161282589/ac29915f-d260-4d78-b274-5f8a1b1e130e.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Export the PGP public key&lt;/strong&gt; to encrypt files:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; gpg --armor --&lt;span class=&quot;hljs-built_in&quot;&gt;export&lt;/span&gt; [key_id] &amp;gt; my-public-key.asc&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Export the PGP private key&lt;/strong&gt; to decrypt files:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; gpg --armor --export-secret-keys [key_id] &amp;gt; my-private-key.asc&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-encrypting-a-text-file-using-sops-and-pgp&quot;&gt;&lt;strong&gt;Encrypting a Text File using SOPS and PGP&lt;/strong&gt;&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create a sample text file&lt;/strong&gt; to encrypt:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; &lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;my-secret-password&quot;&lt;/span&gt; &amp;gt; secret.txt&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Configure the default encryption and decryption behavior of SOPS tool&lt;/strong&gt;. Create a file named &lt;code&gt;.sops.yaml&lt;/code&gt; under the &lt;code&gt;$HOME&lt;/code&gt; directory with the Key ID from the previous steps:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; creation_rules:     - pgp: &amp;gt;-         C0B4391E80CDBF4FCE820212F9D999A91B838104&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Encrypt the file using SOPS and your PGP key:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; sops --encrypt secret.txt &amp;gt; secret.enc.txt&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; This will encrypt the &lt;code&gt;secret.txt&lt;/code&gt; file with the default PGP key specified in &lt;code&gt;.sops.yaml&lt;/code&gt; file.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Verify the encrypted content:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; cat secret.enc.txt&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; You should see a YAML structure with encrypted content that looks like this:&lt;/p&gt;&lt;p&gt; &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729162884456/9511ec7e-e458-440f-b6d2-9b481b2b45d2.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-decrypting-the-text-file&quot;&gt;&lt;strong&gt;Decrypting the Text File&lt;/strong&gt;&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use SOPS to decrypt the encrypted file:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; sops --decrypt secret.enc.txt &amp;gt; decrypted.txt&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;View the decrypted content:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; cat decrypted.txt&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; You should see the original text:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; my-secret-password&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-automating-decryption-in-configuration-files&quot;&gt;&lt;strong&gt;Automating Decryption in Configuration Files&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;You can use SOPS-encrypted files in your configuration by decrypting them on the fly, such as:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;export&lt;/span&gt; MY_SECRET=$(sops --decrypt --input-type binary secret.enc.txt)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729163081990/3dbacecd-ff77-426b-b828-cf0838cc1f18.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;This example shows how to use &lt;strong&gt;SOPS&lt;/strong&gt; with &lt;strong&gt;PGP&lt;/strong&gt; to encrypt and decrypt a text file. With PGP encryption, you can ensure that only users with the appropriate private key can decrypt the file, making it ideal for managing secrets in infrastructure code or configuration files.&lt;/p&gt;&lt;h2 id=&quot;heading-references&quot;&gt;References:&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://getsops.io/&quot;&gt;getsops.io&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://blog.gitguardian.com/a-comprehensive-guide-to-sops/&quot;&gt;GitGuardian Blog: A Comprehensive Guide to SOPS: Managing Your Secrets Like A Visionary, Not a Functionary&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://www.youtube.com/watch?v=V2PRhxphH2w&quot;&gt;YouTube: Securing DevOps Show &amp;amp; Tell: Mozilla Sops&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://marketplace.visualstudio.com/items?itemName=signageos.signageos-vscode-sops&quot;&gt;VSCode SOPS extension&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;]]&gt;</hashnode:content><hashnode:coverImage>https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/PQi-ydEYVBo/upload/6ea56d343c27ee36942dfb559b62f7b1.jpeg</hashnode:coverImage></item><item><title><![CDATA[AWS Route 53: Weighted Routing Policy]]></title><description><![CDATA[AWS Route 53: Weighted Routing Policy]]></description><link>https://maxat-akbanov.com/aws-route-53-weighted-routing-policy</link><guid isPermaLink="true">https://maxat-akbanov.com/aws-route-53-weighted-routing-policy</guid><category><![CDATA[weighted]]></category><category><![CDATA[Devops]]></category><category><![CDATA[sysops]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[dns]]></category><category><![CDATA[route53]]></category><category><![CDATA[routing]]></category><dc:creator><![CDATA[Maxat Akbanov]]></dc:creator><pubDate>Wed, 16 Oct 2024 10:25:54 GMT</pubDate><content:encoded>&lt;![CDATA[&lt;p&gt;The &lt;a target=&quot;_blank&quot; href=&quot;https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy-weighted.html&quot;&gt;&lt;strong&gt;Weighted Routing Policy&lt;/strong&gt;&lt;/a&gt; allows you to route DNS query traffic to multiple resources in proportions that you specify. By assigning a relative weight (a numerical value) to each DNS record, you can control the percentage of requests that is directed to various endpoints.&lt;/p&gt;&lt;p&gt;Amazon Route 53 sends traffic to a resource based on the weight that you assign to the record as a proportion of the total weight for all records in the group:&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729071259073/c51cf8d6-e3f6-4bb0-9d9c-70c1f0995e77.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; Weights dont need to sum up to 100%. Each record in weighted policy can have a health checks.&lt;/p&gt;&lt;h3 id=&quot;heading-how-it-works&quot;&gt;&lt;strong&gt;How It Works:&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Weights Assignment:&lt;/strong&gt; Each DNS record (e.g., IP addresses, URLs) is assigned a weight between 0 and 255 and it must have the same name and type.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Traffic Distribution:&lt;/strong&gt; Route 53 uses these weights to determine the probability of returning each record in response to DNS queries.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Proportional Routing:&lt;/strong&gt; The proportion of traffic directed to each resource is calculated based on the weight of that resource relative to the total weight.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Suppose you have three servers:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server A:&lt;/strong&gt; Weight 70&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server B:&lt;/strong&gt; Weight 20&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server C:&lt;/strong&gt; Weight 10&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Total weight = 70 + 20 + 10 = 100&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server A&lt;/strong&gt; will receive 70% of the traffic.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server B&lt;/strong&gt; will receive 20% of the traffic.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server C&lt;/strong&gt; will receive 10% of the traffic.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729072621997/e6208df3-a017-4f96-9de5-2b3ad7aece39.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;div data-node-type=&quot;callout&quot;&gt;&lt;div data-node-type=&quot;callout-emoji&quot;&gt;💡&lt;/div&gt;&lt;div data-node-type=&quot;callout-text&quot;&gt;Assigning a weight of 0 to a record will result in stopping sending traffic to a resource. If all records have weight of 0, then all records will be returned equally.&lt;/div&gt;&lt;/div&gt;&lt;h3 id=&quot;heading-use-cases-for-weighted-routing-policy&quot;&gt;&lt;strong&gt;Use Cases for Weighted Routing Policy&lt;/strong&gt;&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Load Balancing Across Resources&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; Distribute traffic between multiple servers or resources to balance the load.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Benefit:&lt;/strong&gt; Improves resource utilization and application performance.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Implementation:&lt;/strong&gt; Assign equal weights for equal distribution or proportional weights based on server capacity.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/A/B_testing&quot;&gt;&lt;strong&gt;A/B Testing&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; Test new features or versions of an application by directing a portion of users to the new version while the rest use the stable version.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Benefit:&lt;/strong&gt; Collect user feedback and performance data with minimal risk.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Implementation:&lt;/strong&gt; Assign a smaller weight to the new version&apos;s DNS record.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Gradual Deployment (Canary Releases)&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; Gradually roll out updates to a small subset of users before a full-scale deployment.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Benefit:&lt;/strong&gt; Detect issues early and minimize impact on the user base.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Implementation:&lt;/strong&gt; Start with a low weight for the new release and incrementally increase it.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Testing Infrastructure Changes&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; Assess how infrastructure changes handle production traffic without affecting all users.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Benefit:&lt;/strong&gt; Validate performance and stability under real-world conditions.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Implementation:&lt;/strong&gt; Divert a controlled percentage of traffic to the updated infrastructure.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resource Scaling Based on Capacity&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; Allocate more traffic to resources with higher capacity or performance.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Benefit:&lt;/strong&gt; Optimizes resource usage and cost-effectiveness.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Implementation:&lt;/strong&gt; Set weights proportional to each resource&apos;s capacity.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Disaster Recovery and Failover&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; Maintain backup resources that can receive traffic if primary resources fail.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Benefit:&lt;/strong&gt; Enhances application availability and resilience.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Implementation:&lt;/strong&gt; Assign a weight of 0 to backup resources, increasing it when needed.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multi-Region Deployment&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; Distribute traffic across different geographic regions.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Benefit:&lt;/strong&gt; Reduces latency and improves user experience globally.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Implementation:&lt;/strong&gt; Assign weights based on desired traffic distribution between regions.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-implementing-weighted-routing-in-route-53&quot;&gt;&lt;strong&gt;Implementing Weighted Routing in Route 53&lt;/strong&gt;&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create Hosted Zone:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Set up a hosted zone for your domain in Route 53.&lt;/p&gt;&lt;p&gt;  &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729073327439/119ef46f-c23d-4838-b3c3-e32ce217013f.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Add DNS Records:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;For each resource (e.g., server, load balancer), create a DNS record with the same name and type.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Example: Multiple &lt;code&gt;A&lt;/code&gt; records for &lt;a target=&quot;_blank&quot; href=&quot;http://www.example.com&quot;&gt;&lt;code&gt;www.example.com&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Assign Weights:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;In each DNS record, specify the desired weight.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The weights determine the traffic proportion.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Optional - Set Health Checks and Record ID:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Associate health checks with DNS records to ensure traffic is only routed to healthy resources.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Set alias names for your DNS record via Record ID&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;    &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729073735554/b59cb2d8-04a3-49d3-b9de-3476971a0c34.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;ol start=&quot;5&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Save Configuration:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Apply the changes to make them active.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-considerations-when-using-weighted-routing&quot;&gt;&lt;strong&gt;Considerations When Using Weighted Routing&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Health Checks:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Purpose:&lt;/strong&gt; Ensure traffic isn&apos;t routed to unhealthy resources.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Implementation:&lt;/strong&gt; Configure Route 53 health checks for each resource.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;DNS Caching and TTL:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Impact:&lt;/strong&gt; Changes in routing may not be immediate due to DNS caching.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Adjust the Time to Live (TTL) settings for quicker propagation.&lt;/p&gt;  &lt;div data-node-type=&quot;callout&quot;&gt;  &lt;div data-node-type=&quot;callout-emoji&quot;&gt;💡&lt;/div&gt;  &lt;div data-node-type=&quot;callout-text&quot;&gt;Not all recursive DNS servers strictly follow TTL values. You cannot force them to update their caches, some DNS resolvers dont respect TTLs at all and just implement their own caching policy however they wish. It may take considerable time, ranging from one to several days, for TTL updates to become effective. You may want to set the TTL to a lower value before making DNS changes such as 60 seconds, but in the real world, the common DNS TTL before making changes is to lower it to 300 seconds, and once the change is done you can set it back to 3600(1 hour) or 86,400 seconds(24 hours). [Source: &lt;a target=&quot;_blank&quot; href=&quot;https://hackernoon.com/inside-aws-route53s-weighted-routing-policy&quot;&gt;Inside AWS Route53&apos;s Weighted Routing Policyby@devgrowth&lt;/a&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://hackernoon.com/u/devgrowth&quot;&gt;&lt;strong&gt;]&lt;/strong&gt;&lt;/a&gt;&lt;/div&gt;  &lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Relative Weights:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Understanding:&lt;/strong&gt; The actual weight values are relative; it&apos;s the ratio that matters.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; Weights of 1 and 3 have the same effect as 10 and 30.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Monitoring and Logging:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Importance:&lt;/strong&gt; Keep track of traffic distribution and resource performance.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tools:&lt;/strong&gt; Use AWS CloudWatch and other monitoring services.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-limitations&quot;&gt;&lt;strong&gt;Limitations&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Complexity:&lt;/strong&gt; Managing multiple weights can become complex in large-scale environments.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;DNS Resolver Behavior:&lt;/strong&gt; Some resolvers may cache DNS responses longer than expected, affecting traffic distribution.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Not Real-Time:&lt;/strong&gt; Changes in weights may take time to reflect due to DNS propagation delays.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Practical Example&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; You run an e-commerce website with servers in the US and Europe.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Objective:&lt;/strong&gt; Direct 70% of global traffic to the US servers and 30% to the European servers.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Implementation Steps:&lt;/strong&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;US Server DNS Record:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Name:&lt;/strong&gt; &lt;a target=&quot;_blank&quot; href=&quot;http://www.example.com&quot;&gt;&lt;code&gt;www.example.com&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Type:&lt;/strong&gt; &lt;code&gt;A&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Value:&lt;/strong&gt; IP address of US server&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Weight:&lt;/strong&gt; 70&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;European Server DNS Record:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Name:&lt;/strong&gt; &lt;a target=&quot;_blank&quot; href=&quot;http://www.example.com&quot;&gt;&lt;code&gt;www.example.com&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Type:&lt;/strong&gt; &lt;code&gt;A&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Value:&lt;/strong&gt; IP address of European server&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Weight:&lt;/strong&gt; 30&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Route 53 routes approximately 70% of the traffic to the US server and 30% to the European server.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The AWS Route 53 Weighted Routing Policy is a powerful feature that provides granular control over how traffic is distributed to your resources. By adjusting weights, you can implement advanced traffic management strategies such as load balancing, A/B testing, and gradual deployments.&lt;/p&gt;]]&gt;</content:encoded><hashnode:content>&lt;![CDATA[&lt;p&gt;The &lt;a target=&quot;_blank&quot; href=&quot;https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy-weighted.html&quot;&gt;&lt;strong&gt;Weighted Routing Policy&lt;/strong&gt;&lt;/a&gt; allows you to route DNS query traffic to multiple resources in proportions that you specify. By assigning a relative weight (a numerical value) to each DNS record, you can control the percentage of requests that is directed to various endpoints.&lt;/p&gt;&lt;p&gt;Amazon Route 53 sends traffic to a resource based on the weight that you assign to the record as a proportion of the total weight for all records in the group:&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729071259073/c51cf8d6-e3f6-4bb0-9d9c-70c1f0995e77.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; Weights dont need to sum up to 100%. Each record in weighted policy can have a health checks.&lt;/p&gt;&lt;h3 id=&quot;heading-how-it-works&quot;&gt;&lt;strong&gt;How It Works:&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Weights Assignment:&lt;/strong&gt; Each DNS record (e.g., IP addresses, URLs) is assigned a weight between 0 and 255 and it must have the same name and type.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Traffic Distribution:&lt;/strong&gt; Route 53 uses these weights to determine the probability of returning each record in response to DNS queries.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Proportional Routing:&lt;/strong&gt; The proportion of traffic directed to each resource is calculated based on the weight of that resource relative to the total weight.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Suppose you have three servers:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server A:&lt;/strong&gt; Weight 70&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server B:&lt;/strong&gt; Weight 20&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server C:&lt;/strong&gt; Weight 10&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Total weight = 70 + 20 + 10 = 100&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server A&lt;/strong&gt; will receive 70% of the traffic.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server B&lt;/strong&gt; will receive 20% of the traffic.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server C&lt;/strong&gt; will receive 10% of the traffic.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729072621997/e6208df3-a017-4f96-9de5-2b3ad7aece39.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;div data-node-type=&quot;callout&quot;&gt;&lt;div data-node-type=&quot;callout-emoji&quot;&gt;💡&lt;/div&gt;&lt;div data-node-type=&quot;callout-text&quot;&gt;Assigning a weight of 0 to a record will result in stopping sending traffic to a resource. If all records have weight of 0, then all records will be returned equally.&lt;/div&gt;&lt;/div&gt;&lt;h3 id=&quot;heading-use-cases-for-weighted-routing-policy&quot;&gt;&lt;strong&gt;Use Cases for Weighted Routing Policy&lt;/strong&gt;&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Load Balancing Across Resources&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; Distribute traffic between multiple servers or resources to balance the load.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Benefit:&lt;/strong&gt; Improves resource utilization and application performance.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Implementation:&lt;/strong&gt; Assign equal weights for equal distribution or proportional weights based on server capacity.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/A/B_testing&quot;&gt;&lt;strong&gt;A/B Testing&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; Test new features or versions of an application by directing a portion of users to the new version while the rest use the stable version.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Benefit:&lt;/strong&gt; Collect user feedback and performance data with minimal risk.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Implementation:&lt;/strong&gt; Assign a smaller weight to the new version&apos;s DNS record.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Gradual Deployment (Canary Releases)&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; Gradually roll out updates to a small subset of users before a full-scale deployment.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Benefit:&lt;/strong&gt; Detect issues early and minimize impact on the user base.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Implementation:&lt;/strong&gt; Start with a low weight for the new release and incrementally increase it.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Testing Infrastructure Changes&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; Assess how infrastructure changes handle production traffic without affecting all users.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Benefit:&lt;/strong&gt; Validate performance and stability under real-world conditions.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Implementation:&lt;/strong&gt; Divert a controlled percentage of traffic to the updated infrastructure.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resource Scaling Based on Capacity&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; Allocate more traffic to resources with higher capacity or performance.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Benefit:&lt;/strong&gt; Optimizes resource usage and cost-effectiveness.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Implementation:&lt;/strong&gt; Set weights proportional to each resource&apos;s capacity.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Disaster Recovery and Failover&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; Maintain backup resources that can receive traffic if primary resources fail.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Benefit:&lt;/strong&gt; Enhances application availability and resilience.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Implementation:&lt;/strong&gt; Assign a weight of 0 to backup resources, increasing it when needed.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multi-Region Deployment&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; Distribute traffic across different geographic regions.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Benefit:&lt;/strong&gt; Reduces latency and improves user experience globally.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Implementation:&lt;/strong&gt; Assign weights based on desired traffic distribution between regions.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-implementing-weighted-routing-in-route-53&quot;&gt;&lt;strong&gt;Implementing Weighted Routing in Route 53&lt;/strong&gt;&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create Hosted Zone:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Set up a hosted zone for your domain in Route 53.&lt;/p&gt;&lt;p&gt;  &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729073327439/119ef46f-c23d-4838-b3c3-e32ce217013f.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Add DNS Records:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;For each resource (e.g., server, load balancer), create a DNS record with the same name and type.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Example: Multiple &lt;code&gt;A&lt;/code&gt; records for &lt;a target=&quot;_blank&quot; href=&quot;http://www.example.com&quot;&gt;&lt;code&gt;www.example.com&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Assign Weights:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;In each DNS record, specify the desired weight.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The weights determine the traffic proportion.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Optional - Set Health Checks and Record ID:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Associate health checks with DNS records to ensure traffic is only routed to healthy resources.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Set alias names for your DNS record via Record ID&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;    &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1729073735554/b59cb2d8-04a3-49d3-b9de-3476971a0c34.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;ol start=&quot;5&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Save Configuration:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Apply the changes to make them active.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-considerations-when-using-weighted-routing&quot;&gt;&lt;strong&gt;Considerations When Using Weighted Routing&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Health Checks:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Purpose:&lt;/strong&gt; Ensure traffic isn&apos;t routed to unhealthy resources.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Implementation:&lt;/strong&gt; Configure Route 53 health checks for each resource.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;DNS Caching and TTL:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Impact:&lt;/strong&gt; Changes in routing may not be immediate due to DNS caching.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Adjust the Time to Live (TTL) settings for quicker propagation.&lt;/p&gt;  &lt;div data-node-type=&quot;callout&quot;&gt;  &lt;div data-node-type=&quot;callout-emoji&quot;&gt;💡&lt;/div&gt;  &lt;div data-node-type=&quot;callout-text&quot;&gt;Not all recursive DNS servers strictly follow TTL values. You cannot force them to update their caches, some DNS resolvers dont respect TTLs at all and just implement their own caching policy however they wish. It may take considerable time, ranging from one to several days, for TTL updates to become effective. You may want to set the TTL to a lower value before making DNS changes such as 60 seconds, but in the real world, the common DNS TTL before making changes is to lower it to 300 seconds, and once the change is done you can set it back to 3600(1 hour) or 86,400 seconds(24 hours). [Source: &lt;a target=&quot;_blank&quot; href=&quot;https://hackernoon.com/inside-aws-route53s-weighted-routing-policy&quot;&gt;Inside AWS Route53&apos;s Weighted Routing Policyby@devgrowth&lt;/a&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://hackernoon.com/u/devgrowth&quot;&gt;&lt;strong&gt;]&lt;/strong&gt;&lt;/a&gt;&lt;/div&gt;  &lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Relative Weights:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Understanding:&lt;/strong&gt; The actual weight values are relative; it&apos;s the ratio that matters.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; Weights of 1 and 3 have the same effect as 10 and 30.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Monitoring and Logging:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Importance:&lt;/strong&gt; Keep track of traffic distribution and resource performance.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tools:&lt;/strong&gt; Use AWS CloudWatch and other monitoring services.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-limitations&quot;&gt;&lt;strong&gt;Limitations&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Complexity:&lt;/strong&gt; Managing multiple weights can become complex in large-scale environments.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;DNS Resolver Behavior:&lt;/strong&gt; Some resolvers may cache DNS responses longer than expected, affecting traffic distribution.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Not Real-Time:&lt;/strong&gt; Changes in weights may take time to reflect due to DNS propagation delays.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Practical Example&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; You run an e-commerce website with servers in the US and Europe.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Objective:&lt;/strong&gt; Direct 70% of global traffic to the US servers and 30% to the European servers.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Implementation Steps:&lt;/strong&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;US Server DNS Record:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Name:&lt;/strong&gt; &lt;a target=&quot;_blank&quot; href=&quot;http://www.example.com&quot;&gt;&lt;code&gt;www.example.com&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Type:&lt;/strong&gt; &lt;code&gt;A&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Value:&lt;/strong&gt; IP address of US server&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Weight:&lt;/strong&gt; 70&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;European Server DNS Record:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Name:&lt;/strong&gt; &lt;a target=&quot;_blank&quot; href=&quot;http://www.example.com&quot;&gt;&lt;code&gt;www.example.com&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Type:&lt;/strong&gt; &lt;code&gt;A&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Value:&lt;/strong&gt; IP address of European server&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Weight:&lt;/strong&gt; 30&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Route 53 routes approximately 70% of the traffic to the US server and 30% to the European server.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The AWS Route 53 Weighted Routing Policy is a powerful feature that provides granular control over how traffic is distributed to your resources. By adjusting weights, you can implement advanced traffic management strategies such as load balancing, A/B testing, and gradual deployments.&lt;/p&gt;]]&gt;</hashnode:content><hashnode:coverImage>https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/Pnm-9vBEQhk/upload/0c993afdf002cd2c0a717af0e1b77836.jpeg</hashnode:coverImage></item><item><title><![CDATA[AWS Route 53: Simple Routing Policy]]></title><description><![CDATA[AWS Route 53: Simple Routing Policy]]></description><link>https://maxat-akbanov.com/aws-route-53-simple-routing-policy</link><guid isPermaLink="true">https://maxat-akbanov.com/aws-route-53-simple-routing-policy</guid><category><![CDATA[Devops]]></category><category><![CDATA[AWS]]></category><category><![CDATA[sysops]]></category><category><![CDATA[dns]]></category><category><![CDATA[routing]]></category><category><![CDATA[route53]]></category><dc:creator><![CDATA[Maxat Akbanov]]></dc:creator><pubDate>Tue, 15 Oct 2024 12:03:59 GMT</pubDate><content:encoded>&lt;![CDATA[&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://aws.amazon.com/route53/&quot;&gt;&lt;strong&gt;AWS Route 53&lt;/strong&gt;&lt;/a&gt; is Amazon&apos;s scalable and highly available Domain Name System (DNS) web service. It translates human-readable domain names (like &lt;code&gt;www.example.com&lt;/code&gt;) into IP addresses (like &lt;code&gt;198.51.100.42&lt;/code&gt;) that computers use to connect to each other. Within Route 53, routing policies determine how DNS queries are answered. One of these policies is the &lt;a target=&quot;_blank&quot; href=&quot;https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy-simple.html&quot;&gt;&lt;strong&gt;Simple Routing policy&lt;/strong&gt;&lt;/a&gt;, which is the default and most straightforward option.&lt;/p&gt;&lt;h3 id=&quot;heading-what-is-the-simple-routing-policy&quot;&gt;&lt;strong&gt;What Is the Simple Routing Policy?&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;The &lt;a target=&quot;_blank&quot; href=&quot;https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy-simple.html&quot;&gt;&lt;strong&gt;Simple Routing policy&lt;/strong&gt;&lt;/a&gt; is used when you want Route 53 to respond to DNS queries with a single record. It&apos;s ideal for straightforward configurations where multiple endpoints or complex traffic management aren&apos;t necessary.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Single Value Record&lt;/strong&gt;: You create one DNS record for a domain or subdomain.&lt;/p&gt;&lt;p&gt;  &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1728991215307/58f3fdde-becc-4e86-8ff1-e12f1550f8e8.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multiple Values Record&lt;/strong&gt;: While it&apos;s called &quot;simple,&quot; you can include multiple IP addresses or endpoints in the same record.&lt;/p&gt;&lt;p&gt;  &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1728991928895/df01965e-af17-4970-b025-48c44d55765b.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;No Advanced Features&lt;/strong&gt;: This policy does not support health checks, weighted distribution, or geographic routing.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-how-does-it-work&quot;&gt;&lt;strong&gt;How Does It Work?&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;When a DNS query is made for your domain:&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1728992914388/80a9dd50-0af6-467e-840f-f34df8d9c72e.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;DNS Query Received&lt;/strong&gt;: A user tries to access your domain (&lt;a target=&quot;_blank&quot; href=&quot;http://www.example.com&quot;&gt;&lt;code&gt;www.example.com&lt;/code&gt;&lt;/a&gt;), initiating a DNS query.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Route 53 Responds&lt;/strong&gt;: Route 53 looks up the DNS record associated with that domain.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Returns Record Values&lt;/strong&gt;: It returns all the IP addresses or endpoints specified in the record, typically in a random order.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Client Chooses Endpoint&lt;/strong&gt;: The client&apos;s DNS resolver selects one of the returned IP addresses to establish a connection.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-key-characteristics&quot;&gt;&lt;strong&gt;Key Characteristics&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Client-Side Load Balancing&lt;/strong&gt;: If multiple IP addresses are provided, the client&apos;s DNS resolver decides which one to use. This can lead to basic load balancing but isn&apos;t as controlled as other routing policies.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;No Health Checks&lt;/strong&gt;: Route 53 doesn&apos;t check whether the endpoints are healthy. If an endpoint is down, its IP address is still included in DNS responses.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simplicity&lt;/strong&gt;: Configuration is straightforward, making it suitable for simple use cases.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;One AWS resource for Alias record&lt;/strong&gt;: When &lt;a target=&quot;_blank&quot; href=&quot;https://maxat-akbanov.com/aws-route-53-alias-vs-cname-records#heading-aws-route-53-alias-records&quot;&gt;Alias record&lt;/a&gt; enabled you can specify only one AWS resource.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-when-to-use-the-simple-routing-policy&quot;&gt;&lt;strong&gt;When to Use the Simple Routing Policy&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Single Endpoint&lt;/strong&gt;: You have one server or resource serving all traffic.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multiple Identical Endpoints&lt;/strong&gt;: Multiple servers serve the same content, and you don&apos;t need to control traffic distribution.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Basic DNS Needs&lt;/strong&gt;: You don&apos;t require advanced features like failover, latency optimization, or geolocation-based routing.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-limitations&quot;&gt;&lt;strong&gt;Limitations&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;No Traffic Control&lt;/strong&gt;: You can&apos;t specify how traffic is distributed among multiple endpoints.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Potential Downtime&lt;/strong&gt;: Without health checks, users may be directed to an unavailable endpoint.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Not Ideal for Complex Architectures&lt;/strong&gt;: Lacks support for advanced routing strategies needed in sophisticated deployments.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-configuration-steps&quot;&gt;&lt;strong&gt;Configuration Steps&lt;/strong&gt;&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Access Route 53 Console&lt;/strong&gt;: Log in to your AWS Management Console and navigate to Route 53.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create or Select a Hosted Zone&lt;/strong&gt;: Choose the hosted zone corresponding to your domain.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create a Record Set&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Click on &quot;Create Record.&quot;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Name&lt;/strong&gt;: Enter the domain or subdomain (e.g., &lt;code&gt;www&lt;/code&gt; for &lt;a target=&quot;_blank&quot; href=&quot;http://www.example.com&quot;&gt;&lt;code&gt;www.example.com&lt;/code&gt;&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Type&lt;/strong&gt;: Choose the record type (e.g., A, AAAA, CNAME).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Value(s)&lt;/strong&gt;: Enter the IP address(es) or endpoint(s).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Routing Policy&lt;/strong&gt;: Select &quot;Simple.&quot;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;TTL (Time to Live)&lt;/strong&gt;: Set how long DNS resolvers cache the record.&lt;/p&gt;&lt;p&gt;  &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1728993680236/6815ffc7-8f32-4b7c-bb1f-4f83b11236c5.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Save&lt;/strong&gt;: Confirm and save the record.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-summary&quot;&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;The &lt;a target=&quot;_blank&quot; href=&quot;https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy-simple.html&quot;&gt;&lt;strong&gt;Simple Routing policy&lt;/strong&gt;&lt;/a&gt; in AWS Route 53 is ideal for basic DNS configurations where advanced routing mechanisms aren&apos;t required. It maps a domain directly to one or more IP addresses or endpoints without considering the health or performance of those endpoints. This simplicity makes it easy to set up and manage but comes with limitations that may not suit more complex or critical applications&lt;/p&gt;]]&gt;</content:encoded><hashnode:content>&lt;![CDATA[&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://aws.amazon.com/route53/&quot;&gt;&lt;strong&gt;AWS Route 53&lt;/strong&gt;&lt;/a&gt; is Amazon&apos;s scalable and highly available Domain Name System (DNS) web service. It translates human-readable domain names (like &lt;code&gt;www.example.com&lt;/code&gt;) into IP addresses (like &lt;code&gt;198.51.100.42&lt;/code&gt;) that computers use to connect to each other. Within Route 53, routing policies determine how DNS queries are answered. One of these policies is the &lt;a target=&quot;_blank&quot; href=&quot;https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy-simple.html&quot;&gt;&lt;strong&gt;Simple Routing policy&lt;/strong&gt;&lt;/a&gt;, which is the default and most straightforward option.&lt;/p&gt;&lt;h3 id=&quot;heading-what-is-the-simple-routing-policy&quot;&gt;&lt;strong&gt;What Is the Simple Routing Policy?&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;The &lt;a target=&quot;_blank&quot; href=&quot;https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy-simple.html&quot;&gt;&lt;strong&gt;Simple Routing policy&lt;/strong&gt;&lt;/a&gt; is used when you want Route 53 to respond to DNS queries with a single record. It&apos;s ideal for straightforward configurations where multiple endpoints or complex traffic management aren&apos;t necessary.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Single Value Record&lt;/strong&gt;: You create one DNS record for a domain or subdomain.&lt;/p&gt;&lt;p&gt;  &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1728991215307/58f3fdde-becc-4e86-8ff1-e12f1550f8e8.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multiple Values Record&lt;/strong&gt;: While it&apos;s called &quot;simple,&quot; you can include multiple IP addresses or endpoints in the same record.&lt;/p&gt;&lt;p&gt;  &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1728991928895/df01965e-af17-4970-b025-48c44d55765b.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;No Advanced Features&lt;/strong&gt;: This policy does not support health checks, weighted distribution, or geographic routing.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-how-does-it-work&quot;&gt;&lt;strong&gt;How Does It Work?&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;When a DNS query is made for your domain:&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1728992914388/80a9dd50-0af6-467e-840f-f34df8d9c72e.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;DNS Query Received&lt;/strong&gt;: A user tries to access your domain (&lt;a target=&quot;_blank&quot; href=&quot;http://www.example.com&quot;&gt;&lt;code&gt;www.example.com&lt;/code&gt;&lt;/a&gt;), initiating a DNS query.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Route 53 Responds&lt;/strong&gt;: Route 53 looks up the DNS record associated with that domain.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Returns Record Values&lt;/strong&gt;: It returns all the IP addresses or endpoints specified in the record, typically in a random order.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Client Chooses Endpoint&lt;/strong&gt;: The client&apos;s DNS resolver selects one of the returned IP addresses to establish a connection.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-key-characteristics&quot;&gt;&lt;strong&gt;Key Characteristics&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Client-Side Load Balancing&lt;/strong&gt;: If multiple IP addresses are provided, the client&apos;s DNS resolver decides which one to use. This can lead to basic load balancing but isn&apos;t as controlled as other routing policies.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;No Health Checks&lt;/strong&gt;: Route 53 doesn&apos;t check whether the endpoints are healthy. If an endpoint is down, its IP address is still included in DNS responses.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simplicity&lt;/strong&gt;: Configuration is straightforward, making it suitable for simple use cases.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;One AWS resource for Alias record&lt;/strong&gt;: When &lt;a target=&quot;_blank&quot; href=&quot;https://maxat-akbanov.com/aws-route-53-alias-vs-cname-records#heading-aws-route-53-alias-records&quot;&gt;Alias record&lt;/a&gt; enabled you can specify only one AWS resource.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-when-to-use-the-simple-routing-policy&quot;&gt;&lt;strong&gt;When to Use the Simple Routing Policy&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Single Endpoint&lt;/strong&gt;: You have one server or resource serving all traffic.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multiple Identical Endpoints&lt;/strong&gt;: Multiple servers serve the same content, and you don&apos;t need to control traffic distribution.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Basic DNS Needs&lt;/strong&gt;: You don&apos;t require advanced features like failover, latency optimization, or geolocation-based routing.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-limitations&quot;&gt;&lt;strong&gt;Limitations&lt;/strong&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;No Traffic Control&lt;/strong&gt;: You can&apos;t specify how traffic is distributed among multiple endpoints.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Potential Downtime&lt;/strong&gt;: Without health checks, users may be directed to an unavailable endpoint.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Not Ideal for Complex Architectures&lt;/strong&gt;: Lacks support for advanced routing strategies needed in sophisticated deployments.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-configuration-steps&quot;&gt;&lt;strong&gt;Configuration Steps&lt;/strong&gt;&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Access Route 53 Console&lt;/strong&gt;: Log in to your AWS Management Console and navigate to Route 53.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create or Select a Hosted Zone&lt;/strong&gt;: Choose the hosted zone corresponding to your domain.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create a Record Set&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Click on &quot;Create Record.&quot;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Name&lt;/strong&gt;: Enter the domain or subdomain (e.g., &lt;code&gt;www&lt;/code&gt; for &lt;a target=&quot;_blank&quot; href=&quot;http://www.example.com&quot;&gt;&lt;code&gt;www.example.com&lt;/code&gt;&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Type&lt;/strong&gt;: Choose the record type (e.g., A, AAAA, CNAME).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Value(s)&lt;/strong&gt;: Enter the IP address(es) or endpoint(s).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Routing Policy&lt;/strong&gt;: Select &quot;Simple.&quot;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;TTL (Time to Live)&lt;/strong&gt;: Set how long DNS resolvers cache the record.&lt;/p&gt;&lt;p&gt;  &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1728993680236/6815ffc7-8f32-4b7c-bb1f-4f83b11236c5.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Save&lt;/strong&gt;: Confirm and save the record.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-summary&quot;&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;The &lt;a target=&quot;_blank&quot; href=&quot;https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy-simple.html&quot;&gt;&lt;strong&gt;Simple Routing policy&lt;/strong&gt;&lt;/a&gt; in AWS Route 53 is ideal for basic DNS configurations where advanced routing mechanisms aren&apos;t required. It maps a domain directly to one or more IP addresses or endpoints without considering the health or performance of those endpoints. This simplicity makes it easy to set up and manage but comes with limitations that may not suit more complex or critical applications&lt;/p&gt;]]&gt;</hashnode:content><hashnode:coverImage>https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/A-NVHPka9Rk/upload/441ea7e460358f67aa8ee2d4c7343ed3.jpeg</hashnode:coverImage></item><item><title><![CDATA[AWS Route 53 Alias vs CNAME Records]]></title><description><![CDATA[AWS Route 53 Alias vs CNAME Records]]></description><link>https://maxat-akbanov.com/aws-route-53-alias-vs-cname-records</link><guid isPermaLink="true">https://maxat-akbanov.com/aws-route-53-alias-vs-cname-records</guid><category><![CDATA[Devops]]></category><category><![CDATA[sysops]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[dns]]></category><category><![CDATA[cname records]]></category><category><![CDATA[alias]]></category><category><![CDATA[route53]]></category><dc:creator><![CDATA[Maxat Akbanov]]></dc:creator><pubDate>Mon, 14 Oct 2024 18:19:14 GMT</pubDate><content:encoded>&lt;![CDATA[&lt;p&gt;A &lt;a target=&quot;_blank&quot; href=&quot;https://www.cloudflare.com/learning/dns/dns-records/dns-cname-record/&quot;&gt;&lt;strong&gt;CNAME (Canonical Name)&lt;/strong&gt; record&lt;/a&gt; is a type of DNS record used to alias one domain name to another. When a DNS resolver encounters a CNAME record, it will replace the original domain with the target domain and make a new DNS query for the target.&lt;/p&gt;&lt;p&gt;For example, suppose &lt;code&gt;blog.example.com&lt;/code&gt; has a CNAME record with a value of &quot;&lt;code&gt;example.com&lt;/code&gt;&quot; (without the &quot;&lt;code&gt;blog&lt;/code&gt;&quot;). This means when a DNS server hits the DNS records for &lt;code&gt;blog.example.com&lt;/code&gt;, it actually triggers another DNS lookup to &lt;code&gt;example.com&lt;/code&gt;, returning &lt;code&gt;example.com&lt;/code&gt;s IP address via its A record. In this case we would say that &lt;code&gt;example.com&lt;/code&gt; is the canonical name (or true name) of &lt;code&gt;blog.example.com&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1728903098943/1556cfd0-4c61-4848-b848-a1dfe2b1782d.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;h4 id=&quot;heading-characteristics-of-cname&quot;&gt;Characteristics of CNAME:&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Aliases one domain to another domain&lt;/strong&gt;: The domain with the CNAME will inherit all records (e.g., A, MX, etc.) from the target domain.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Common Use Case&lt;/strong&gt;: Typically used to map subdomains (e.g., &lt;code&gt;www.example.com&lt;/code&gt;) to the main domain (&lt;code&gt;example.com&lt;/code&gt;) or to an external service.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Limitations&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;MX and NS records cannot point to a CNAME record; they have to point to an A record (for IPv4) or an &lt;a target=&quot;_blank&quot; href=&quot;https://www.cloudflare.com/learning/dns/dns-records/dns-aaaa-record/&quot;&gt;AAAA record (for IPv6)&lt;/a&gt;. An MX record is a mail exchange record that directs email to a mail server. An NS record is a &quot;name server&quot; record and indicates which DNS server is authoritative for that domain.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;It cannot be used for the root domain (also known as the &quot;apex&quot; or &quot;naked&quot; domain, such as &lt;code&gt;example.com&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h4 id=&quot;heading-example&quot;&gt;Example:&lt;/h4&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1728900133355/b67a6f93-7a3c-4d4d-9045-ed84ebb97d2a.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;Reference: &lt;a target=&quot;_blank&quot; href=&quot;https://www.cloudflare.com/learning/dns/dns-records/dns-cname-record/&quot;&gt;Cloudflare&lt;/a&gt;&lt;/p&gt;&lt;p&gt;When a user requests &lt;code&gt;blog.example.com&lt;/code&gt;, DNS will look for the records of &lt;code&gt;example.com&lt;/code&gt; and return them, usually the A/AAAA record.&lt;/p&gt;&lt;hr /&gt;&lt;h3 id=&quot;heading-how-to-create-a-cname-record-in-aws-route-53&quot;&gt;How to Create a CNAME Record in AWS Route 53&lt;/h3&gt;&lt;p&gt;To create a &lt;strong&gt;CNAME&lt;/strong&gt; record in AWS Route 53, follow these steps:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Log in to AWS Console&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Go to &lt;a target=&quot;_blank&quot; href=&quot;https://aws.amazon.com/console/&quot;&gt;AWS Management Console&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Use your credentials to log in.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Open Route 53&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;In the search bar at the top, type &lt;strong&gt;Route 53&lt;/strong&gt; and select it from the results.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Select Hosted Zones&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;In the Route 53 dashboard, click on &lt;strong&gt;Hosted Zones&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Select the &lt;strong&gt;hosted zone&lt;/strong&gt; for the domain where you want to create the CNAME record.&lt;/p&gt;&lt;p&gt;  &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1728903730010/61cd7e09-c279-4235-a0b1-bd01484ec41a.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create a Record&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;In the hosted zone, click the &lt;strong&gt;Create record&lt;/strong&gt; button.&lt;/p&gt;&lt;p&gt;  &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1728905767025/e8246d30-10f5-4be1-81ff-a68d0ff6fc88.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Set Record Type and Details&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Name&lt;/strong&gt;: Enter the subdomain name you want to map (e.g., &lt;code&gt;blog.example.com&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Record Type&lt;/strong&gt;: Select &lt;strong&gt;CNAME - Canonical name&lt;/strong&gt; from the drop-down menu.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Value&lt;/strong&gt;: Enter the target domain (e.g., &lt;a target=&quot;_blank&quot; href=&quot;http://example.com&quot;&gt;&lt;code&gt;example.com&lt;/code&gt;&lt;/a&gt; or another domain like &lt;a target=&quot;_blank&quot; href=&quot;http://service.example.com&quot;&gt;&lt;code&gt;service.example.com&lt;/code&gt;&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Leave the default &lt;strong&gt;TTL (Time to Live)&lt;/strong&gt; or adjust if necessary.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Routing Policy&lt;/strong&gt;: Use the default &lt;strong&gt;Simple routing&lt;/strong&gt; unless you need more advanced options like failover.&lt;/p&gt;&lt;p&gt;  &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1728905841376/f7db9a25-c832-4518-87bf-606a89feccff.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create the Record&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Review your settings and click &lt;strong&gt;Create records&lt;/strong&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;This will create a CNAME record mapping &lt;a target=&quot;_blank&quot; href=&quot;http://www.example.com&quot;&gt;&lt;code&gt;blog.example.com&lt;/code&gt;&lt;/a&gt; to &lt;a target=&quot;_blank&quot; href=&quot;http://example.com&quot;&gt;&lt;code&gt;example.com&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;&lt;h3 id=&quot;heading-aws-route-53-alias-records&quot;&gt;AWS Route 53 Alias Records&lt;/h3&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-choosing-alias-non-alias.html&quot;&gt;&lt;strong&gt;Alias&lt;/strong&gt; records&lt;/a&gt; are AWS-specific and provide functionality similar to CNAME but with additional features tailored to AWS services.&lt;/p&gt;&lt;h4 id=&quot;heading-characteristics-of-aws-alias-records&quot;&gt;Characteristics of AWS Alias Records:&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Integration with AWS Services&lt;/strong&gt;: Alias records allow you to map a domain name to &lt;a target=&quot;_blank&quot; href=&quot;https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-choosing-alias-non-alias.html&quot;&gt;AWS services like&lt;/a&gt; CloudFront distributions, S3 buckets (website mode), Elastic Load Balancers (ELBs), and API Gateways.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Root Domain Support&lt;/strong&gt;: Unlike CNAME records, Alias records &lt;strong&gt;can&lt;/strong&gt; be used at the root domain (e.g., &lt;code&gt;example.com&lt;/code&gt;) to point to an AWS resource. This is because AWS manages the DNS lookup internally.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Free Queries for AWS Targets&lt;/strong&gt;: &lt;a target=&quot;_blank&quot; href=&quot;https://aws.amazon.com/route53/pricing/&quot;&gt;Alias records do not incur additional DNS query charges&lt;/a&gt; when they point to AWS services.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fast Failover&lt;/strong&gt;: Since theyre integrated into Route 53, they can be used for Route 53-specific features like health checks and failover.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h4 id=&quot;heading-example-1&quot;&gt;Example:&lt;/h4&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1728928660188/46e41c60-ba16-4e15-b150-a7e032b8b819.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;In this case, the root domain &lt;code&gt;example.com&lt;/code&gt; can point to an AWS Application Load Balancer using an Alias record, something that isnt possible with a traditional CNAME.&lt;/p&gt;&lt;p&gt;When you use an alias record to route traffic to an AWS resource, Route 53 automatically recognizes changes in the resource. In the given example, an alias record for &lt;code&gt;example.com&lt;/code&gt; points to an Elastic Load Balancing load balancer at &lt;code&gt;my-load-balancer-1234567890.us-west-2.elb.amazonaws.com&lt;/code&gt;. If the IP address of the load balancer changes, Route 53 automatically starts to respond to DNS queries using the new IP address.&lt;/p&gt;&lt;div data-node-type=&quot;callout&quot;&gt;&lt;div data-node-type=&quot;callout-emoji&quot;&gt;&lt;/div&gt;&lt;div data-node-type=&quot;callout-text&quot;&gt;If an alias record points to an AWS resource, you can&apos;t set the time to live (TTL); Route53 uses the default TTL for the resource. If an alias record points to another record in the same hosted zone, Route53 uses the TTL of the record that the alias record points to.&lt;/div&gt;&lt;/div&gt;&lt;hr /&gt;&lt;h3 id=&quot;heading-key-differences-between-cname-and-alias-records&quot;&gt;Key Differences between CNAME and Alias Records&lt;/h3&gt;&lt;div class=&quot;hn-table&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;td&gt;Feature&lt;/td&gt;&lt;td&gt;CNAME&lt;/td&gt;&lt;td&gt;AWS Alias&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;AWS Service Integration&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;No&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Root Domain Support&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;No&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;DNS Query Cost&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Standard DNS pricing applies&lt;/td&gt;&lt;td&gt;Free if pointing to AWS resources&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Works with AWS Services&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;No&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Use Outside AWS&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;td&gt;No (AWS-specific)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Failover &amp;amp; Health Checks&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Not supported&lt;/td&gt;&lt;td&gt;Supported (when using Route 53)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;h3 id=&quot;heading-when-to-use-each&quot;&gt;When to Use Each&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;CNAME Record&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Use it when you want to alias one domain to another domain or subdomain outside AWS, or if you&apos;re mapping subdomains to external services (like &lt;code&gt;app.example.com&lt;/code&gt; pointing to &lt;code&gt;thirdparty.mywebsite.com&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Avoid&lt;/strong&gt; using it at the root domain (&lt;code&gt;example.com&lt;/code&gt;) as DNS specifications do not allow CNAME records at the apex of a domain.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Alias Record&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Use when integrating with AWS resources (like CloudFront, ELB, or S3) to take advantage of AWS-specific optimizations, especially when you need to map a &lt;strong&gt;root domain&lt;/strong&gt; (&lt;code&gt;example.com&lt;/code&gt;) to AWS services.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Preferred when using Route 53 for advanced DNS features like failover, routing policies, and health checks.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;In summary, &lt;strong&gt;CNAME&lt;/strong&gt; records are more universal and suited for general aliasing, while &lt;strong&gt;Alias&lt;/strong&gt; records are AWS-specific and offer extended functionality when dealing with AWS infrastructure and services.&lt;/p&gt;&lt;h3 id=&quot;heading-how-to-create-route-53-alias-record-by-using-console&quot;&gt;How to Create Route 53 Alias Record by using Console&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;Sign in to the AWS Management Console and open the &lt;a target=&quot;_blank&quot; href=&quot;https://console.aws.amazon.com/route53/&quot;&gt;Route 53 console.&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;In the navigation pane, choose &lt;strong&gt;Hosted zones&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Choose the name of the hosted zone that you want to use to route traffic to your App Runner service.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Choose &lt;strong&gt;Create record&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt; &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1728929411748/018637dd-a182-4ecb-b67d-31d7c100091e.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Specify the following values:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Routing policy&lt;/strong&gt;: Choose the applicable routing policy. For more information, see &lt;a target=&quot;_blank&quot; href=&quot;https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy.html&quot;&gt;Choosing a routing policy&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Record name&lt;/strong&gt;: Enter the domain name that you want to use to route traffic to your App Runner service. The default value is the name of the hosted zone. For example, if the name of the hosted zone is &lt;code&gt;example.com&lt;/code&gt; and you want to use &lt;code&gt;acme.example.com&lt;/code&gt; to route traffic to your environment, enter &lt;code&gt;acme&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Value/Route traffic to&lt;/strong&gt;: Choose &lt;strong&gt;Alias to App Runner Application&lt;/strong&gt;, then choose the &lt;strong&gt;Region&lt;/strong&gt; that the endpoint is from. Choose the domain name of the application that you want to route traffic to.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Record type&lt;/strong&gt;: Accept the default, &lt;strong&gt;A  IPv4 address&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Evaluate target health&lt;/strong&gt;: Accept the default value, &lt;strong&gt;Yes&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Choose &lt;strong&gt;Create records&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt; &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1728929675993/ee7f20b2-2906-436a-80e0-0289fd77d582.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The Route 53 alias record that you created gets propagated on all Route 53 servers within 60 seconds. When the Route 53 servers are propagated with your alias record, you can route traffic to your App Runner service by using the name of the alias record that you created.&lt;/p&gt;&lt;h3 id=&quot;heading-references&quot;&gt;References:&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy.html&quot;&gt;AWS Docs: Choos&lt;/a&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-choosing-alias-non-alias.html&quot;&gt;ing between alias and non-alias rec&lt;/a&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy.html&quot;&gt;ords&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.aws.amazon.com/apprunner/latest/dg/manage-custom-domains-route53.html&quot;&gt;AWS Docs: Configure Amazon Route 53 alias record for your target DNS&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy.html&quot;&gt;Guide to DNS CNAM&lt;/a&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://www.mailersend.com/blog/cname-record&quot;&gt;E&lt;/a&gt; &lt;a target=&quot;_blank&quot; href=&quot;https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy.html&quot;&gt;records: Optimize your e&lt;/a&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://www.mailersend.com/blog/cname-record&quot;&gt;mail tracking&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;]]&gt;</content:encoded><hashnode:content>&lt;![CDATA[&lt;p&gt;A &lt;a target=&quot;_blank&quot; href=&quot;https://www.cloudflare.com/learning/dns/dns-records/dns-cname-record/&quot;&gt;&lt;strong&gt;CNAME (Canonical Name)&lt;/strong&gt; record&lt;/a&gt; is a type of DNS record used to alias one domain name to another. When a DNS resolver encounters a CNAME record, it will replace the original domain with the target domain and make a new DNS query for the target.&lt;/p&gt;&lt;p&gt;For example, suppose &lt;code&gt;blog.example.com&lt;/code&gt; has a CNAME record with a value of &quot;&lt;code&gt;example.com&lt;/code&gt;&quot; (without the &quot;&lt;code&gt;blog&lt;/code&gt;&quot;). This means when a DNS server hits the DNS records for &lt;code&gt;blog.example.com&lt;/code&gt;, it actually triggers another DNS lookup to &lt;code&gt;example.com&lt;/code&gt;, returning &lt;code&gt;example.com&lt;/code&gt;s IP address via its A record. In this case we would say that &lt;code&gt;example.com&lt;/code&gt; is the canonical name (or true name) of &lt;code&gt;blog.example.com&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1728903098943/1556cfd0-4c61-4848-b848-a1dfe2b1782d.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;h4 id=&quot;heading-characteristics-of-cname&quot;&gt;Characteristics of CNAME:&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Aliases one domain to another domain&lt;/strong&gt;: The domain with the CNAME will inherit all records (e.g., A, MX, etc.) from the target domain.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Common Use Case&lt;/strong&gt;: Typically used to map subdomains (e.g., &lt;code&gt;www.example.com&lt;/code&gt;) to the main domain (&lt;code&gt;example.com&lt;/code&gt;) or to an external service.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Limitations&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;MX and NS records cannot point to a CNAME record; they have to point to an A record (for IPv4) or an &lt;a target=&quot;_blank&quot; href=&quot;https://www.cloudflare.com/learning/dns/dns-records/dns-aaaa-record/&quot;&gt;AAAA record (for IPv6)&lt;/a&gt;. An MX record is a mail exchange record that directs email to a mail server. An NS record is a &quot;name server&quot; record and indicates which DNS server is authoritative for that domain.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;It cannot be used for the root domain (also known as the &quot;apex&quot; or &quot;naked&quot; domain, such as &lt;code&gt;example.com&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h4 id=&quot;heading-example&quot;&gt;Example:&lt;/h4&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1728900133355/b67a6f93-7a3c-4d4d-9045-ed84ebb97d2a.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;Reference: &lt;a target=&quot;_blank&quot; href=&quot;https://www.cloudflare.com/learning/dns/dns-records/dns-cname-record/&quot;&gt;Cloudflare&lt;/a&gt;&lt;/p&gt;&lt;p&gt;When a user requests &lt;code&gt;blog.example.com&lt;/code&gt;, DNS will look for the records of &lt;code&gt;example.com&lt;/code&gt; and return them, usually the A/AAAA record.&lt;/p&gt;&lt;hr /&gt;&lt;h3 id=&quot;heading-how-to-create-a-cname-record-in-aws-route-53&quot;&gt;How to Create a CNAME Record in AWS Route 53&lt;/h3&gt;&lt;p&gt;To create a &lt;strong&gt;CNAME&lt;/strong&gt; record in AWS Route 53, follow these steps:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Log in to AWS Console&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Go to &lt;a target=&quot;_blank&quot; href=&quot;https://aws.amazon.com/console/&quot;&gt;AWS Management Console&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Use your credentials to log in.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Open Route 53&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;In the search bar at the top, type &lt;strong&gt;Route 53&lt;/strong&gt; and select it from the results.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Select Hosted Zones&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;In the Route 53 dashboard, click on &lt;strong&gt;Hosted Zones&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Select the &lt;strong&gt;hosted zone&lt;/strong&gt; for the domain where you want to create the CNAME record.&lt;/p&gt;&lt;p&gt;  &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1728903730010/61cd7e09-c279-4235-a0b1-bd01484ec41a.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create a Record&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;In the hosted zone, click the &lt;strong&gt;Create record&lt;/strong&gt; button.&lt;/p&gt;&lt;p&gt;  &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1728905767025/e8246d30-10f5-4be1-81ff-a68d0ff6fc88.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Set Record Type and Details&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Name&lt;/strong&gt;: Enter the subdomain name you want to map (e.g., &lt;code&gt;blog.example.com&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Record Type&lt;/strong&gt;: Select &lt;strong&gt;CNAME - Canonical name&lt;/strong&gt; from the drop-down menu.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Value&lt;/strong&gt;: Enter the target domain (e.g., &lt;a target=&quot;_blank&quot; href=&quot;http://example.com&quot;&gt;&lt;code&gt;example.com&lt;/code&gt;&lt;/a&gt; or another domain like &lt;a target=&quot;_blank&quot; href=&quot;http://service.example.com&quot;&gt;&lt;code&gt;service.example.com&lt;/code&gt;&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Leave the default &lt;strong&gt;TTL (Time to Live)&lt;/strong&gt; or adjust if necessary.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Routing Policy&lt;/strong&gt;: Use the default &lt;strong&gt;Simple routing&lt;/strong&gt; unless you need more advanced options like failover.&lt;/p&gt;&lt;p&gt;  &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1728905841376/f7db9a25-c832-4518-87bf-606a89feccff.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create the Record&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Review your settings and click &lt;strong&gt;Create records&lt;/strong&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;This will create a CNAME record mapping &lt;a target=&quot;_blank&quot; href=&quot;http://www.example.com&quot;&gt;&lt;code&gt;blog.example.com&lt;/code&gt;&lt;/a&gt; to &lt;a target=&quot;_blank&quot; href=&quot;http://example.com&quot;&gt;&lt;code&gt;example.com&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;&lt;h3 id=&quot;heading-aws-route-53-alias-records&quot;&gt;AWS Route 53 Alias Records&lt;/h3&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-choosing-alias-non-alias.html&quot;&gt;&lt;strong&gt;Alias&lt;/strong&gt; records&lt;/a&gt; are AWS-specific and provide functionality similar to CNAME but with additional features tailored to AWS services.&lt;/p&gt;&lt;h4 id=&quot;heading-characteristics-of-aws-alias-records&quot;&gt;Characteristics of AWS Alias Records:&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Integration with AWS Services&lt;/strong&gt;: Alias records allow you to map a domain name to &lt;a target=&quot;_blank&quot; href=&quot;https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-choosing-alias-non-alias.html&quot;&gt;AWS services like&lt;/a&gt; CloudFront distributions, S3 buckets (website mode), Elastic Load Balancers (ELBs), and API Gateways.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Root Domain Support&lt;/strong&gt;: Unlike CNAME records, Alias records &lt;strong&gt;can&lt;/strong&gt; be used at the root domain (e.g., &lt;code&gt;example.com&lt;/code&gt;) to point to an AWS resource. This is because AWS manages the DNS lookup internally.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Free Queries for AWS Targets&lt;/strong&gt;: &lt;a target=&quot;_blank&quot; href=&quot;https://aws.amazon.com/route53/pricing/&quot;&gt;Alias records do not incur additional DNS query charges&lt;/a&gt; when they point to AWS services.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fast Failover&lt;/strong&gt;: Since theyre integrated into Route 53, they can be used for Route 53-specific features like health checks and failover.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h4 id=&quot;heading-example-1&quot;&gt;Example:&lt;/h4&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1728928660188/46e41c60-ba16-4e15-b150-a7e032b8b819.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;In this case, the root domain &lt;code&gt;example.com&lt;/code&gt; can point to an AWS Application Load Balancer using an Alias record, something that isnt possible with a traditional CNAME.&lt;/p&gt;&lt;p&gt;When you use an alias record to route traffic to an AWS resource, Route 53 automatically recognizes changes in the resource. In the given example, an alias record for &lt;code&gt;example.com&lt;/code&gt; points to an Elastic Load Balancing load balancer at &lt;code&gt;my-load-balancer-1234567890.us-west-2.elb.amazonaws.com&lt;/code&gt;. If the IP address of the load balancer changes, Route 53 automatically starts to respond to DNS queries using the new IP address.&lt;/p&gt;&lt;div data-node-type=&quot;callout&quot;&gt;&lt;div data-node-type=&quot;callout-emoji&quot;&gt;&lt;/div&gt;&lt;div data-node-type=&quot;callout-text&quot;&gt;If an alias record points to an AWS resource, you can&apos;t set the time to live (TTL); Route53 uses the default TTL for the resource. If an alias record points to another record in the same hosted zone, Route53 uses the TTL of the record that the alias record points to.&lt;/div&gt;&lt;/div&gt;&lt;hr /&gt;&lt;h3 id=&quot;heading-key-differences-between-cname-and-alias-records&quot;&gt;Key Differences between CNAME and Alias Records&lt;/h3&gt;&lt;div class=&quot;hn-table&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;td&gt;Feature&lt;/td&gt;&lt;td&gt;CNAME&lt;/td&gt;&lt;td&gt;AWS Alias&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;AWS Service Integration&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;No&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Root Domain Support&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;No&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;DNS Query Cost&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Standard DNS pricing applies&lt;/td&gt;&lt;td&gt;Free if pointing to AWS resources&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Works with AWS Services&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;No&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Use Outside AWS&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;td&gt;No (AWS-specific)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Failover &amp;amp; Health Checks&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Not supported&lt;/td&gt;&lt;td&gt;Supported (when using Route 53)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;h3 id=&quot;heading-when-to-use-each&quot;&gt;When to Use Each&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;CNAME Record&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Use it when you want to alias one domain to another domain or subdomain outside AWS, or if you&apos;re mapping subdomains to external services (like &lt;code&gt;app.example.com&lt;/code&gt; pointing to &lt;code&gt;thirdparty.mywebsite.com&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Avoid&lt;/strong&gt; using it at the root domain (&lt;code&gt;example.com&lt;/code&gt;) as DNS specifications do not allow CNAME records at the apex of a domain.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Alias Record&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Use when integrating with AWS resources (like CloudFront, ELB, or S3) to take advantage of AWS-specific optimizations, especially when you need to map a &lt;strong&gt;root domain&lt;/strong&gt; (&lt;code&gt;example.com&lt;/code&gt;) to AWS services.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Preferred when using Route 53 for advanced DNS features like failover, routing policies, and health checks.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;In summary, &lt;strong&gt;CNAME&lt;/strong&gt; records are more universal and suited for general aliasing, while &lt;strong&gt;Alias&lt;/strong&gt; records are AWS-specific and offer extended functionality when dealing with AWS infrastructure and services.&lt;/p&gt;&lt;h3 id=&quot;heading-how-to-create-route-53-alias-record-by-using-console&quot;&gt;How to Create Route 53 Alias Record by using Console&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;Sign in to the AWS Management Console and open the &lt;a target=&quot;_blank&quot; href=&quot;https://console.aws.amazon.com/route53/&quot;&gt;Route 53 console.&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;In the navigation pane, choose &lt;strong&gt;Hosted zones&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Choose the name of the hosted zone that you want to use to route traffic to your App Runner service.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Choose &lt;strong&gt;Create record&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt; &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1728929411748/018637dd-a182-4ecb-b67d-31d7c100091e.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Specify the following values:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Routing policy&lt;/strong&gt;: Choose the applicable routing policy. For more information, see &lt;a target=&quot;_blank&quot; href=&quot;https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy.html&quot;&gt;Choosing a routing policy&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Record name&lt;/strong&gt;: Enter the domain name that you want to use to route traffic to your App Runner service. The default value is the name of the hosted zone. For example, if the name of the hosted zone is &lt;code&gt;example.com&lt;/code&gt; and you want to use &lt;code&gt;acme.example.com&lt;/code&gt; to route traffic to your environment, enter &lt;code&gt;acme&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Value/Route traffic to&lt;/strong&gt;: Choose &lt;strong&gt;Alias to App Runner Application&lt;/strong&gt;, then choose the &lt;strong&gt;Region&lt;/strong&gt; that the endpoint is from. Choose the domain name of the application that you want to route traffic to.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Record type&lt;/strong&gt;: Accept the default, &lt;strong&gt;A  IPv4 address&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Evaluate target health&lt;/strong&gt;: Accept the default value, &lt;strong&gt;Yes&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Choose &lt;strong&gt;Create records&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt; &lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1728929675993/ee7f20b2-2906-436a-80e0-0289fd77d582.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The Route 53 alias record that you created gets propagated on all Route 53 servers within 60 seconds. When the Route 53 servers are propagated with your alias record, you can route traffic to your App Runner service by using the name of the alias record that you created.&lt;/p&gt;&lt;h3 id=&quot;heading-references&quot;&gt;References:&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy.html&quot;&gt;AWS Docs: Choos&lt;/a&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-choosing-alias-non-alias.html&quot;&gt;ing between alias and non-alias rec&lt;/a&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy.html&quot;&gt;ords&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.aws.amazon.com/apprunner/latest/dg/manage-custom-domains-route53.html&quot;&gt;AWS Docs: Configure Amazon Route 53 alias record for your target DNS&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy.html&quot;&gt;Guide to DNS CNAM&lt;/a&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://www.mailersend.com/blog/cname-record&quot;&gt;E&lt;/a&gt; &lt;a target=&quot;_blank&quot; href=&quot;https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy.html&quot;&gt;records: Optimize your e&lt;/a&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://www.mailersend.com/blog/cname-record&quot;&gt;mail tracking&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;]]&gt;</hashnode:content><hashnode:coverImage>https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/jG8nlwLRZTM/upload/9d692d8fed66432bde34d07464ef5c0d.jpeg</hashnode:coverImage></item><item><title><![CDATA[Understanding the Risks of Terraform Code Refactoring]]></title><description><![CDATA[Understanding the Risks of Terraform Code Refactoring]]></description><link>https://maxat-akbanov.com/understanding-the-risks-of-terraform-code-refactoring</link><guid isPermaLink="true">https://maxat-akbanov.com/understanding-the-risks-of-terraform-code-refactoring</guid><category><![CDATA[Terraform]]></category><category><![CDATA[#IaC]]></category><category><![CDATA[Devops]]></category><category><![CDATA[sysops]]></category><category><![CDATA[Devops articles]]></category><dc:creator><![CDATA[Maxat Akbanov]]></dc:creator><pubDate>Sat, 05 Oct 2024 14:18:58 GMT</pubDate><content:encoded>&lt;![CDATA[&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://refactoring.com/&quot;&gt;&lt;em&gt;Refactoring&lt;/em&gt;&lt;/a&gt; - is the process of restructuring existing code without altering its external behavior or functionality. The goal is to improve the code&apos;s internal structure, readability, and maintainability.&lt;/p&gt;&lt;p&gt;Refactoring is an essential coding practice that should be done on regularly basis. It is true for general purpose programming languages. But when it comes to IaC like tools (Terraform), changing the internal structure of the code on the purpose of refactoring can be a risky operation. It can alter the external behavior and cause downtimes, crashes and many, many other scary things.&lt;/p&gt;&lt;p&gt;Let me show you how a common and simple refactoring technique such as renaming a resource name, can be a catastrophic in terms of Terraform.&lt;/p&gt;&lt;p&gt;Imagine that you have the following code that defines your EC2 instance:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-plaintext&quot;&gt;resource &quot;aws_instance&quot; &quot;web&quot; {  ami           = &quot;ami-0c55b159cbfafe1f0&quot;  instance_type = &quot;t2.micro&quot;}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;During refactoring process you come up with an idea to change the resource name to a more meaningful name such as &lt;code&gt;web_server&lt;/code&gt; instead of &lt;code&gt;web&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-plaintext&quot;&gt;resource &quot;aws_instance&quot; &quot;web_server&quot; {  ami           = &quot;ami-0c55b159cbfafe1f0&quot;  instance_type = &quot;t2.micro&quot;}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;What will happen when you try to apply this change?&lt;/p&gt;&lt;p&gt;Terraform will recreate the resource. Terraform sees &lt;code&gt;aws_instance.web_server&lt;/code&gt; as a new resource and &lt;code&gt;aws_instance.web&lt;/code&gt; as no longer needed. First Terraform destroys the existing one and then creates a new resource with identifier &lt;code&gt;web_server&lt;/code&gt;. During this process your web server will be in a downtime. Thats not what you wanted.&lt;/p&gt;&lt;p&gt;The proper way of renaming a resource in the example above will be by using a &lt;code&gt;terraform state mv&lt;/code&gt; command:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-plaintext&quot;&gt;terraform state mv aws_instance.web aws_instance.web_server&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: Staring from Terraform v1.1 and above you can use explicit refactoring declarations with &lt;code&gt;moved&lt;/code&gt; blocks instead of &lt;code&gt;terraform state mv&lt;/code&gt; command.&lt;/p&gt;&lt;div data-node-type=&quot;callout&quot;&gt;&lt;div data-node-type=&quot;callout-emoji&quot;&gt;💡&lt;/div&gt;&lt;div data-node-type=&quot;callout-text&quot;&gt;Keep in mind that Terraform is not like a general-purpose programming language and the core nature of it is operating with the &lt;a target=&quot;_blank&quot; href=&quot;https://developer.hashicorp.com/terraform/language/state&quot;&gt;state of the infrastructure&lt;/a&gt;. The default behavior of Terraform is: &lt;em&gt;destroy old then create new&lt;/em&gt;&lt;strong&gt;&lt;em&gt;.&lt;/em&gt;&lt;/strong&gt;&lt;/div&gt;&lt;/div&gt;&lt;h3 id=&quot;heading-safeguards&quot;&gt;Safeguards:&lt;/h3&gt;&lt;p&gt;So, how to keep yourself safeguarded? The main rule is to use &lt;code&gt;terraform plan&lt;/code&gt; and inspect it thoroughly. Verify that your changes are not destroying or creating something new.&lt;/p&gt;&lt;p&gt;The general list of rules are:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Plan Before Applying:&lt;/strong&gt; Always run &lt;code&gt;terraform plan&lt;/code&gt; to see the implications of your changes before applying them.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Update All References:&lt;/strong&gt; Ensure that all usages of renamed variables or resources are updated.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Manage State Carefully:&lt;/strong&gt; Use Terraform state commands to reflect changes in resource names.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Version Control:&lt;/strong&gt; Keep your Terraform code in a version control system to track changes and facilitate rollbacks if necessary.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Test Changes:&lt;/strong&gt; Apply refactoring changes in a non-production environment first to observe any unintended effects.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;By following these rules you can avoid the pitfalls associated with refactoring and maintain a stable infrastructure with Terraform.&lt;/p&gt;&lt;h3 id=&quot;heading-references&quot;&gt;References:&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://developer.hashicorp.com/terraform/language/modules/develop/refactoring&quot;&gt;Terraform Docs: Refactoring&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://medium.com/driven-by-code/the-terrors-and-joys-of-terraform-88bbd1aa4359&quot;&gt;The Terrors and Joys of Terraform&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;]]&gt;</content:encoded><hashnode:content>&lt;![CDATA[&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://refactoring.com/&quot;&gt;&lt;em&gt;Refactoring&lt;/em&gt;&lt;/a&gt; - is the process of restructuring existing code without altering its external behavior or functionality. The goal is to improve the code&apos;s internal structure, readability, and maintainability.&lt;/p&gt;&lt;p&gt;Refactoring is an essential coding practice that should be done on regularly basis. It is true for general purpose programming languages. But when it comes to IaC like tools (Terraform), changing the internal structure of the code on the purpose of refactoring can be a risky operation. It can alter the external behavior and cause downtimes, crashes and many, many other scary things.&lt;/p&gt;&lt;p&gt;Let me show you how a common and simple refactoring technique such as renaming a resource name, can be a catastrophic in terms of Terraform.&lt;/p&gt;&lt;p&gt;Imagine that you have the following code that defines your EC2 instance:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-plaintext&quot;&gt;resource &quot;aws_instance&quot; &quot;web&quot; {  ami           = &quot;ami-0c55b159cbfafe1f0&quot;  instance_type = &quot;t2.micro&quot;}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;During refactoring process you come up with an idea to change the resource name to a more meaningful name such as &lt;code&gt;web_server&lt;/code&gt; instead of &lt;code&gt;web&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-plaintext&quot;&gt;resource &quot;aws_instance&quot; &quot;web_server&quot; {  ami           = &quot;ami-0c55b159cbfafe1f0&quot;  instance_type = &quot;t2.micro&quot;}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;What will happen when you try to apply this change?&lt;/p&gt;&lt;p&gt;Terraform will recreate the resource. Terraform sees &lt;code&gt;aws_instance.web_server&lt;/code&gt; as a new resource and &lt;code&gt;aws_instance.web&lt;/code&gt; as no longer needed. First Terraform destroys the existing one and then creates a new resource with identifier &lt;code&gt;web_server&lt;/code&gt;. During this process your web server will be in a downtime. Thats not what you wanted.&lt;/p&gt;&lt;p&gt;The proper way of renaming a resource in the example above will be by using a &lt;code&gt;terraform state mv&lt;/code&gt; command:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-plaintext&quot;&gt;terraform state mv aws_instance.web aws_instance.web_server&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: Staring from Terraform v1.1 and above you can use explicit refactoring declarations with &lt;code&gt;moved&lt;/code&gt; blocks instead of &lt;code&gt;terraform state mv&lt;/code&gt; command.&lt;/p&gt;&lt;div data-node-type=&quot;callout&quot;&gt;&lt;div data-node-type=&quot;callout-emoji&quot;&gt;💡&lt;/div&gt;&lt;div data-node-type=&quot;callout-text&quot;&gt;Keep in mind that Terraform is not like a general-purpose programming language and the core nature of it is operating with the &lt;a target=&quot;_blank&quot; href=&quot;https://developer.hashicorp.com/terraform/language/state&quot;&gt;state of the infrastructure&lt;/a&gt;. The default behavior of Terraform is: &lt;em&gt;destroy old then create new&lt;/em&gt;&lt;strong&gt;&lt;em&gt;.&lt;/em&gt;&lt;/strong&gt;&lt;/div&gt;&lt;/div&gt;&lt;h3 id=&quot;heading-safeguards&quot;&gt;Safeguards:&lt;/h3&gt;&lt;p&gt;So, how to keep yourself safeguarded? The main rule is to use &lt;code&gt;terraform plan&lt;/code&gt; and inspect it thoroughly. Verify that your changes are not destroying or creating something new.&lt;/p&gt;&lt;p&gt;The general list of rules are:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Plan Before Applying:&lt;/strong&gt; Always run &lt;code&gt;terraform plan&lt;/code&gt; to see the implications of your changes before applying them.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Update All References:&lt;/strong&gt; Ensure that all usages of renamed variables or resources are updated.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Manage State Carefully:&lt;/strong&gt; Use Terraform state commands to reflect changes in resource names.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use Version Control:&lt;/strong&gt; Keep your Terraform code in a version control system to track changes and facilitate rollbacks if necessary.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Test Changes:&lt;/strong&gt; Apply refactoring changes in a non-production environment first to observe any unintended effects.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;By following these rules you can avoid the pitfalls associated with refactoring and maintain a stable infrastructure with Terraform.&lt;/p&gt;&lt;h3 id=&quot;heading-references&quot;&gt;References:&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://developer.hashicorp.com/terraform/language/modules/develop/refactoring&quot;&gt;Terraform Docs: Refactoring&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://medium.com/driven-by-code/the-terrors-and-joys-of-terraform-88bbd1aa4359&quot;&gt;The Terrors and Joys of Terraform&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;]]&gt;</hashnode:content><hashnode:coverImage>https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/a9X7rBh-A5Y/upload/f66c36dcb0d01ea99a197d877c81a792.jpeg</hashnode:coverImage></item><item><title><![CDATA[How 'copy' built-in function works in Go]]></title><description><![CDATA[How 'copy' built-in function works in Go]]></description><link>https://maxat-akbanov.com/how-copy-built-in-function-works-in-go</link><guid isPermaLink="true">https://maxat-akbanov.com/how-copy-built-in-function-works-in-go</guid><category><![CDATA[Go Language]]></category><category><![CDATA[golang]]></category><category><![CDATA[Devops]]></category><dc:creator><![CDATA[Maxat Akbanov]]></dc:creator><pubDate>Tue, 17 Sep 2024 20:02:59 GMT</pubDate><content:encoded>&lt;![CDATA[&lt;p&gt;The &lt;a target=&quot;_blank&quot; href=&quot;https://go.dev/ref/spec#Appending_and_copying_slices&quot;&gt;&lt;code&gt;copy&lt;/code&gt;&lt;/a&gt; built-in function in Go is used to copy elements from one slice to another. It is particularly useful when you need to duplicate or copy portions of a slice into another slice.&lt;/p&gt;&lt;h3 id=&quot;heading-syntax&quot;&gt;Syntax&lt;/h3&gt;&lt;pre&gt;&lt;code class=&quot;lang-go&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;copy&lt;/span&gt;(dst, src []T) &lt;span class=&quot;hljs-keyword&quot;&gt;int&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;dst&lt;/code&gt;: The destination slice where elements are copied to.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;src&lt;/code&gt;: The source slice from which elements are copied.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;T&lt;/code&gt;: The type of elements in the slices.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Return value&lt;/strong&gt;: The function returns the number of elements that were copied, which is the minimum of the lengths of &lt;code&gt;src&lt;/code&gt; and &lt;code&gt;dst&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;As a &lt;strong&gt;special case&lt;/strong&gt;, its legal to copy bytes from a string to a slice of bytes.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-plaintext&quot;&gt;copy(dst []byte, src string) int&lt;/code&gt;&lt;/pre&gt;&lt;div data-node-type=&quot;callout&quot;&gt;&lt;div data-node-type=&quot;callout-emoji&quot;&gt;💡&lt;/div&gt;&lt;div data-node-type=&quot;callout-text&quot;&gt;Remember! You can use copy function to create independent slices. This allows to avoid the problem of sharing the same underlying array when using the slice of slices operations.&lt;/div&gt;&lt;/div&gt;&lt;h3 id=&quot;heading-rules&quot;&gt;Rules:&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Only the number of elements that both slices can accommodate will be copied (i.e., the minimum length of &lt;code&gt;dst&lt;/code&gt; and &lt;code&gt;src&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The &lt;code&gt;copy&lt;/code&gt; function works with any slice type, as long as both slices have elements of the same type.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-example&quot;&gt;Example:&lt;/h3&gt;&lt;pre&gt;&lt;code class=&quot;lang-go&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;package&lt;/span&gt; main&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;fmt&quot;&lt;/span&gt;&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;()&lt;/span&gt;&lt;/span&gt; {    &lt;span class=&quot;hljs-comment&quot;&gt;// Source slice&lt;/span&gt;    src := []&lt;span class=&quot;hljs-keyword&quot;&gt;int&lt;/span&gt;{&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;}    &lt;span class=&quot;hljs-comment&quot;&gt;// Destination slice with enough capacity&lt;/span&gt;    dst := &lt;span class=&quot;hljs-built_in&quot;&gt;make&lt;/span&gt;([]&lt;span class=&quot;hljs-keyword&quot;&gt;int&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;)    &lt;span class=&quot;hljs-comment&quot;&gt;// Copying elements from src to dst&lt;/span&gt;    numCopied := &lt;span class=&quot;hljs-built_in&quot;&gt;copy&lt;/span&gt;(dst, src)    fmt.Println(&lt;span class=&quot;hljs-string&quot;&gt;&quot;Source slice:&quot;&lt;/span&gt;, src)                    &lt;span class=&quot;hljs-comment&quot;&gt;// [1, 2, 3, 4, 5]&lt;/span&gt;    fmt.Println(&lt;span class=&quot;hljs-string&quot;&gt;&quot;Destination slice after copy:&quot;&lt;/span&gt;, dst)    &lt;span class=&quot;hljs-comment&quot;&gt;// [1, 2, 3, 4, 5] --&amp;gt; [0, 0, 0] --&amp;gt; [1, 2, 3]&lt;/span&gt;    fmt.Println(&lt;span class=&quot;hljs-string&quot;&gt;&quot;Number of elements copied:&quot;&lt;/span&gt;, numCopied) &lt;span class=&quot;hljs-comment&quot;&gt;// 3&lt;/span&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&quot;heading-output&quot;&gt;Output:&lt;/h4&gt;&lt;pre&gt;&lt;code class=&quot;lang-plaintext&quot;&gt;Source slice: [1 2 3 4 5]Destination slice after copy: [1 2 3]Number of elements copied: 3&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-explanation&quot;&gt;Explanation:&lt;/h3&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1726571237074/655c9881-548e-4358-8eaf-d4abd03eca2c.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;The &lt;code&gt;src&lt;/code&gt; slice has 5 elements: &lt;code&gt;[1, 2, 3, 4, 5]&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The &lt;code&gt;dst&lt;/code&gt; slice has a capacity of 3, so only the first 3 elements from &lt;code&gt;src&lt;/code&gt; are copied.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The &lt;code&gt;copy&lt;/code&gt; function returns the number of elements copied, which is &lt;code&gt;3&lt;/code&gt; in this case.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-edge-cases&quot;&gt;Edge Cases:&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Destination shorter than source&lt;/strong&gt;: Only as many elements as the destination can hold are copied.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Source shorter than destination&lt;/strong&gt;: The copy will stop when all elements of the source have been copied.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;pre&gt;&lt;code class=&quot;lang-go&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;package&lt;/span&gt; main&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;fmt&quot;&lt;/span&gt;&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;()&lt;/span&gt;&lt;/span&gt; {    src := []&lt;span class=&quot;hljs-keyword&quot;&gt;int&lt;/span&gt;{&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;}          &lt;span class=&quot;hljs-comment&quot;&gt;// [1, 2]&lt;/span&gt;    dst := &lt;span class=&quot;hljs-built_in&quot;&gt;make&lt;/span&gt;([]&lt;span class=&quot;hljs-keyword&quot;&gt;int&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;)       &lt;span class=&quot;hljs-comment&quot;&gt;// [0, 0, 0, 0, 0]&lt;/span&gt;    numCopied := &lt;span class=&quot;hljs-built_in&quot;&gt;copy&lt;/span&gt;(dst, src) &lt;span class=&quot;hljs-comment&quot;&gt;// 2&lt;/span&gt;    fmt.Println(&lt;span class=&quot;hljs-string&quot;&gt;&quot;Dst:&quot;&lt;/span&gt;, dst)    &lt;span class=&quot;hljs-comment&quot;&gt;// [1, 2, 0, 0, 0]&lt;/span&gt;    fmt.Println(&lt;span class=&quot;hljs-string&quot;&gt;&quot;Number of copied elements&quot;&lt;/span&gt;, numCopied)}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In this case, only 2 elements from &lt;code&gt;src&lt;/code&gt; are copied into the first two positions of &lt;code&gt;dst&lt;/code&gt;.&lt;/p&gt;&lt;h3 id=&quot;heading-benefits&quot;&gt;Benefits:&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Efficient copying without needing a loop.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Works with slices of any type (integers, strings, structs, etc.).&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Thats the basic idea of the &lt;code&gt;copy&lt;/code&gt; function in Go!&lt;/p&gt;&lt;h3 id=&quot;heading-references&quot;&gt;References:&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://yourbasic.org/golang/copy-explained/&quot;&gt;How to use the copy function&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://go.dev/blog/slices-intro&quot;&gt;Go Blog: Slices Intro&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;]]&gt;</content:encoded><hashnode:content>&lt;![CDATA[&lt;p&gt;The &lt;a target=&quot;_blank&quot; href=&quot;https://go.dev/ref/spec#Appending_and_copying_slices&quot;&gt;&lt;code&gt;copy&lt;/code&gt;&lt;/a&gt; built-in function in Go is used to copy elements from one slice to another. It is particularly useful when you need to duplicate or copy portions of a slice into another slice.&lt;/p&gt;&lt;h3 id=&quot;heading-syntax&quot;&gt;Syntax&lt;/h3&gt;&lt;pre&gt;&lt;code class=&quot;lang-go&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;copy&lt;/span&gt;(dst, src []T) &lt;span class=&quot;hljs-keyword&quot;&gt;int&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;dst&lt;/code&gt;: The destination slice where elements are copied to.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;src&lt;/code&gt;: The source slice from which elements are copied.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;T&lt;/code&gt;: The type of elements in the slices.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Return value&lt;/strong&gt;: The function returns the number of elements that were copied, which is the minimum of the lengths of &lt;code&gt;src&lt;/code&gt; and &lt;code&gt;dst&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;As a &lt;strong&gt;special case&lt;/strong&gt;, its legal to copy bytes from a string to a slice of bytes.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-plaintext&quot;&gt;copy(dst []byte, src string) int&lt;/code&gt;&lt;/pre&gt;&lt;div data-node-type=&quot;callout&quot;&gt;&lt;div data-node-type=&quot;callout-emoji&quot;&gt;💡&lt;/div&gt;&lt;div data-node-type=&quot;callout-text&quot;&gt;Remember! You can use copy function to create independent slices. This allows to avoid the problem of sharing the same underlying array when using the slice of slices operations.&lt;/div&gt;&lt;/div&gt;&lt;h3 id=&quot;heading-rules&quot;&gt;Rules:&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Only the number of elements that both slices can accommodate will be copied (i.e., the minimum length of &lt;code&gt;dst&lt;/code&gt; and &lt;code&gt;src&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The &lt;code&gt;copy&lt;/code&gt; function works with any slice type, as long as both slices have elements of the same type.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-example&quot;&gt;Example:&lt;/h3&gt;&lt;pre&gt;&lt;code class=&quot;lang-go&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;package&lt;/span&gt; main&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;fmt&quot;&lt;/span&gt;&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;()&lt;/span&gt;&lt;/span&gt; {    &lt;span class=&quot;hljs-comment&quot;&gt;// Source slice&lt;/span&gt;    src := []&lt;span class=&quot;hljs-keyword&quot;&gt;int&lt;/span&gt;{&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;4&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;}    &lt;span class=&quot;hljs-comment&quot;&gt;// Destination slice with enough capacity&lt;/span&gt;    dst := &lt;span class=&quot;hljs-built_in&quot;&gt;make&lt;/span&gt;([]&lt;span class=&quot;hljs-keyword&quot;&gt;int&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;)    &lt;span class=&quot;hljs-comment&quot;&gt;// Copying elements from src to dst&lt;/span&gt;    numCopied := &lt;span class=&quot;hljs-built_in&quot;&gt;copy&lt;/span&gt;(dst, src)    fmt.Println(&lt;span class=&quot;hljs-string&quot;&gt;&quot;Source slice:&quot;&lt;/span&gt;, src)                    &lt;span class=&quot;hljs-comment&quot;&gt;// [1, 2, 3, 4, 5]&lt;/span&gt;    fmt.Println(&lt;span class=&quot;hljs-string&quot;&gt;&quot;Destination slice after copy:&quot;&lt;/span&gt;, dst)    &lt;span class=&quot;hljs-comment&quot;&gt;// [1, 2, 3, 4, 5] --&amp;gt; [0, 0, 0] --&amp;gt; [1, 2, 3]&lt;/span&gt;    fmt.Println(&lt;span class=&quot;hljs-string&quot;&gt;&quot;Number of elements copied:&quot;&lt;/span&gt;, numCopied) &lt;span class=&quot;hljs-comment&quot;&gt;// 3&lt;/span&gt;}&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&quot;heading-output&quot;&gt;Output:&lt;/h4&gt;&lt;pre&gt;&lt;code class=&quot;lang-plaintext&quot;&gt;Source slice: [1 2 3 4 5]Destination slice after copy: [1 2 3]Number of elements copied: 3&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-explanation&quot;&gt;Explanation:&lt;/h3&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1726571237074/655c9881-548e-4358-8eaf-d4abd03eca2c.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;The &lt;code&gt;src&lt;/code&gt; slice has 5 elements: &lt;code&gt;[1, 2, 3, 4, 5]&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The &lt;code&gt;dst&lt;/code&gt; slice has a capacity of 3, so only the first 3 elements from &lt;code&gt;src&lt;/code&gt; are copied.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The &lt;code&gt;copy&lt;/code&gt; function returns the number of elements copied, which is &lt;code&gt;3&lt;/code&gt; in this case.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-edge-cases&quot;&gt;Edge Cases:&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Destination shorter than source&lt;/strong&gt;: Only as many elements as the destination can hold are copied.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Source shorter than destination&lt;/strong&gt;: The copy will stop when all elements of the source have been copied.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;pre&gt;&lt;code class=&quot;lang-go&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;package&lt;/span&gt; main&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;fmt&quot;&lt;/span&gt;&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;hljs-params&quot;&gt;()&lt;/span&gt;&lt;/span&gt; {    src := []&lt;span class=&quot;hljs-keyword&quot;&gt;int&lt;/span&gt;{&lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt;}          &lt;span class=&quot;hljs-comment&quot;&gt;// [1, 2]&lt;/span&gt;    dst := &lt;span class=&quot;hljs-built_in&quot;&gt;make&lt;/span&gt;([]&lt;span class=&quot;hljs-keyword&quot;&gt;int&lt;/span&gt;, &lt;span class=&quot;hljs-number&quot;&gt;5&lt;/span&gt;)       &lt;span class=&quot;hljs-comment&quot;&gt;// [0, 0, 0, 0, 0]&lt;/span&gt;    numCopied := &lt;span class=&quot;hljs-built_in&quot;&gt;copy&lt;/span&gt;(dst, src) &lt;span class=&quot;hljs-comment&quot;&gt;// 2&lt;/span&gt;    fmt.Println(&lt;span class=&quot;hljs-string&quot;&gt;&quot;Dst:&quot;&lt;/span&gt;, dst)    &lt;span class=&quot;hljs-comment&quot;&gt;// [1, 2, 0, 0, 0]&lt;/span&gt;    fmt.Println(&lt;span class=&quot;hljs-string&quot;&gt;&quot;Number of copied elements&quot;&lt;/span&gt;, numCopied)}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In this case, only 2 elements from &lt;code&gt;src&lt;/code&gt; are copied into the first two positions of &lt;code&gt;dst&lt;/code&gt;.&lt;/p&gt;&lt;h3 id=&quot;heading-benefits&quot;&gt;Benefits:&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Efficient copying without needing a loop.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Works with slices of any type (integers, strings, structs, etc.).&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Thats the basic idea of the &lt;code&gt;copy&lt;/code&gt; function in Go!&lt;/p&gt;&lt;h3 id=&quot;heading-references&quot;&gt;References:&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://yourbasic.org/golang/copy-explained/&quot;&gt;How to use the copy function&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://go.dev/blog/slices-intro&quot;&gt;Go Blog: Slices Intro&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;]]&gt;</hashnode:content><hashnode:coverImage>https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/fd9mIBluHkA/upload/66091d342dc823c43a6987d0d9dbca2f.jpeg</hashnode:coverImage></item><item><title><![CDATA[Get started with Kubernetes Annotations]]></title><description><![CDATA[Get started with Kubernetes Annotations]]></description><link>https://maxat-akbanov.com/get-started-with-kubernetes-annotations</link><guid isPermaLink="true">https://maxat-akbanov.com/get-started-with-kubernetes-annotations</guid><category><![CDATA[Devops]]></category><category><![CDATA[sysops]]></category><category><![CDATA[annotations]]></category><category><![CDATA[Kubernetes]]></category><category><![CDATA[k8s]]></category><dc:creator><![CDATA[Maxat Akbanov]]></dc:creator><pubDate>Mon, 08 Jul 2024 18:31:16 GMT</pubDate><content:encoded>&lt;![CDATA[&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/&quot;&gt;Annotations&lt;/a&gt; in Kubernetes are a way to attach arbitrary non-identifying metadata to objects. They are key-value pairs, and unlike labels, they are not used to identify and select objects. Instead, annotations can be used to store additional information that can be useful for various purposes without affecting the behavior of Kubernetes itself.&lt;/p&gt;&lt;p&gt;The metadata in an annotation can be small or large, structured or unstructured, and can include characters not permitted by labels. It is possible to use labels as well as annotations in the metadata of the same object.&lt;/p&gt;&lt;p&gt;Annotations, like labels, are key/value maps:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;&quot;metadata&quot;:&lt;/span&gt; {  &lt;span class=&quot;hljs-attr&quot;&gt;&quot;annotations&quot;:&lt;/span&gt; {    &lt;span class=&quot;hljs-string&quot;&gt;&quot;key1&quot;&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;value1&quot;&lt;/span&gt;,    &lt;span class=&quot;hljs-string&quot;&gt;&quot;key2&quot;&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;value2&quot;&lt;/span&gt;  }}&lt;/code&gt;&lt;/pre&gt;&lt;div data-node-type=&quot;callout&quot;&gt;&lt;div data-node-type=&quot;callout-emoji&quot;&gt;&lt;/div&gt;&lt;div data-node-type=&quot;callout-text&quot;&gt;&lt;strong&gt;The keys and the values in the map must be strings.&lt;/strong&gt; In other words, you cannot use numeric, boolean, list or other types for either the keys or the values.&lt;/div&gt;&lt;/div&gt;&lt;h2 id=&quot;heading-key-characteristics-of-annotations&quot;&gt;Key Characteristics of Annotations:&lt;/h2&gt;&lt;p&gt;Valid annotation keys have two segments: an optional prefix and name, separated by a slash (&lt;code&gt;/&lt;/code&gt;). The name segment is required and must be 63 characters or less, beginning and ending with an alphanumeric character (&lt;code&gt;[a-z0-9A-Z]&lt;/code&gt;) with dashes (&lt;code&gt;-&lt;/code&gt;), underscores (&lt;code&gt;_&lt;/code&gt;), dots (&lt;code&gt;.&lt;/code&gt;), and alphanumerics between. The prefix is optional. If specified, the prefix must be a DNS subdomain: a series of DNS labels separated by dots (&lt;code&gt;.&lt;/code&gt;), not longer than 253 characters in total, followed by a slash (&lt;code&gt;/&lt;/code&gt;).&lt;/p&gt;&lt;p&gt;The &lt;code&gt;kubernetes.io/&lt;/code&gt; and &lt;code&gt;k8s.io/&lt;/code&gt; prefixes are reserved for Kubernetes core components.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Arbitrary Key-Value Pairs&lt;/strong&gt;: Annotations are free-form key-value pairs that can be used to attach any type of metadata to Kubernetes objects.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Not Used for Selection&lt;/strong&gt;: Unlike labels, annotations are not used in selectors (e.g., for service selection, replication controller selection).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;No Constraints on Values&lt;/strong&gt;: The values of annotations can be any string, including structured data formats like JSON or XML.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Can Be Large&lt;/strong&gt;: Annotations can store larger amounts of data compared to labels, which are typically limited to a few kilobytes.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Example of Pod manifest with annotation:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;annotations-demo&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;annotations:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;imageregistry:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;https://hub.docker.com/&quot;&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;containers:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx:1.14.2&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;ports:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;containerPort:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;80&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;heading-common-use-cases-for-annotations&quot;&gt;Common Use Cases for Annotations:&lt;/h2&gt;&lt;h3 id=&quot;heading-metadata-for-external-tools&quot;&gt;&lt;strong&gt;Metadata for External Tools&lt;/strong&gt;:&lt;/h3&gt;&lt;p&gt;Annotations can be used to attach information that is used by external tools or systems. For example, a monitoring system might use annotations to store configuration details for collecting metrics from a pod.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;mypod&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;annotations:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;monitoring.tool/config:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&apos;{&quot;scrape_interval&quot;: &quot;30s&quot;, &quot;path&quot;: &quot;/metrics&quot;}&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-build-and-deployment-information&quot;&gt;&lt;strong&gt;Build and Deployment Information&lt;/strong&gt;:&lt;/h3&gt;&lt;p&gt;Annotations can be used to store build and deployment details such as the version of the application, build date, or git commit hash.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;mypod&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;annotations:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;build.version:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;1.0.0&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;build.date:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;2024-07-08T12:34:56Z&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;build.commit:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;abc123def&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-debugging-and-auditing&quot;&gt;&lt;strong&gt;Debugging and Auditing&lt;/strong&gt;:&lt;/h3&gt;&lt;p&gt;Annotations can be used to track the source of changes, reasons for deployments, or other debugging and auditing information.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;mypod&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;annotations:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;lastUpdatedBy:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;DevOps Team&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;updateReason:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Security patch&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-configuration-and-policy-management&quot;&gt;&lt;strong&gt;Configuration and Policy Management&lt;/strong&gt;:&lt;/h3&gt;&lt;p&gt;Annotations can be used to pass configuration data to controllers or &lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#what-are-admission-webhooks&quot;&gt;admission webhooks&lt;/a&gt; that enforce policies or modify the behavior of resources.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;mypod&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;annotations:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;policy.enforcer/ignore:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;true&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-operational-information&quot;&gt;&lt;strong&gt;Operational Information&lt;/strong&gt;:&lt;/h3&gt;&lt;p&gt;Annotations can store operational information such as priority data or custom handling instructions for specific environments.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;high-priority-pod&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;annotations:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;environment:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;production&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;custom.scheduler/priority:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;high&quot;&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;containers:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx:1.17.4&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;ports:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;containerPort:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;80&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;heading-dynamic-annotation-values&quot;&gt;Dynamic annotation values&lt;/h2&gt;&lt;p&gt;Keep in mind, that annotation values can be populated dynamically in CI/CD tools. In the following examples, you will see the hardcoded values. However, on practice we can generate the annotation value dynamically by using scripts, environment variables and CI/CD toolset.&lt;/p&gt;&lt;p&gt;For example here&apos;s &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; for GitLab CI/CD that annotates the deployment parameters by using environment variables:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;stages:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;build&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;docker&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;deploy&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;variables:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;APP_VERSION:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;1.2.3&quot;&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;build:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;stage:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;build&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;script:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Building application version $APP_VERSION&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-comment&quot;&gt;# Add your build commands here&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;docker-build:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;stage:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;docker&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;script:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;docker&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;-t&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;myapp:$APP_VERSION&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;.&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;docker&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;tag&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;myapp:$APP_VERSION&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;myregistry/myapp:$APP_VERSION&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;docker&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;push&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;myregistry/myapp:$APP_VERSION&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;deploy:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;stage:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;deploy&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;script:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;BUILD_DATE=$(date&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;-u&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;+&quot;%Y-%m-%dT%H:%M:%SZ&quot;)&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;GIT_COMMIT=$(git&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;rev-parse&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;HEAD)&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;|      cat &amp;lt;&amp;lt;EOF &amp;gt; deployment.yaml      apiVersion: apps/v1      kind: Deployment      metadata:        name: myapp-deployment        annotations:          build.version: &quot;$APP_VERSION&quot;          build.date: &quot;$BUILD_DATE&quot;          build.commit: &quot;$GIT_COMMIT&quot;          deployment.team: &quot;devops&quot;          deployment.reason: &quot;feature release&quot;      spec:        replicas: 3        selector:          matchLabels:            app: myapp        template:          metadata:            labels:              app: myapp            annotations:              monitoring.tool/config: &apos;{&quot;scrape_interval&quot;: &quot;30s&quot;, &quot;path&quot;: &quot;/metrics&quot;}&apos;          spec:            containers:            - name: myapp-container              image: myregistry/myapp:$APP_VERSION              ports:              - containerPort: 80      EOF&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;kubectl&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;apply&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;deployment.yaml&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;heading-managing-annotations&quot;&gt;Managing Annotations:&lt;/h2&gt;&lt;p&gt;Annotations can be managed using kubectl commands. For example:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Add an annotation&lt;/strong&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-sh&quot;&gt;  kubectl annotate pod example-pod example.com/owner=&lt;span class=&quot;hljs-string&quot;&gt;&quot;team-a&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Remove an annotation&lt;/strong&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-sh&quot;&gt;  kubectl annotate pod example-pod example.com/owner-&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&quot;heading-references&quot;&gt;References:&lt;/h2&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://medium.com/@sangjinn/kubernetes-annotations-e61b19effdf9&quot;&gt;Medium Blog: What are Kubernetes Annotations?&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/&quot;&gt;Kubernetes Docs: Annotations&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;]]&gt;</content:encoded><hashnode:content>&lt;![CDATA[&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/&quot;&gt;Annotations&lt;/a&gt; in Kubernetes are a way to attach arbitrary non-identifying metadata to objects. They are key-value pairs, and unlike labels, they are not used to identify and select objects. Instead, annotations can be used to store additional information that can be useful for various purposes without affecting the behavior of Kubernetes itself.&lt;/p&gt;&lt;p&gt;The metadata in an annotation can be small or large, structured or unstructured, and can include characters not permitted by labels. It is possible to use labels as well as annotations in the metadata of the same object.&lt;/p&gt;&lt;p&gt;Annotations, like labels, are key/value maps:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;&quot;metadata&quot;:&lt;/span&gt; {  &lt;span class=&quot;hljs-attr&quot;&gt;&quot;annotations&quot;:&lt;/span&gt; {    &lt;span class=&quot;hljs-string&quot;&gt;&quot;key1&quot;&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;value1&quot;&lt;/span&gt;,    &lt;span class=&quot;hljs-string&quot;&gt;&quot;key2&quot;&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;value2&quot;&lt;/span&gt;  }}&lt;/code&gt;&lt;/pre&gt;&lt;div data-node-type=&quot;callout&quot;&gt;&lt;div data-node-type=&quot;callout-emoji&quot;&gt;&lt;/div&gt;&lt;div data-node-type=&quot;callout-text&quot;&gt;&lt;strong&gt;The keys and the values in the map must be strings.&lt;/strong&gt; In other words, you cannot use numeric, boolean, list or other types for either the keys or the values.&lt;/div&gt;&lt;/div&gt;&lt;h2 id=&quot;heading-key-characteristics-of-annotations&quot;&gt;Key Characteristics of Annotations:&lt;/h2&gt;&lt;p&gt;Valid annotation keys have two segments: an optional prefix and name, separated by a slash (&lt;code&gt;/&lt;/code&gt;). The name segment is required and must be 63 characters or less, beginning and ending with an alphanumeric character (&lt;code&gt;[a-z0-9A-Z]&lt;/code&gt;) with dashes (&lt;code&gt;-&lt;/code&gt;), underscores (&lt;code&gt;_&lt;/code&gt;), dots (&lt;code&gt;.&lt;/code&gt;), and alphanumerics between. The prefix is optional. If specified, the prefix must be a DNS subdomain: a series of DNS labels separated by dots (&lt;code&gt;.&lt;/code&gt;), not longer than 253 characters in total, followed by a slash (&lt;code&gt;/&lt;/code&gt;).&lt;/p&gt;&lt;p&gt;The &lt;code&gt;kubernetes.io/&lt;/code&gt; and &lt;code&gt;k8s.io/&lt;/code&gt; prefixes are reserved for Kubernetes core components.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Arbitrary Key-Value Pairs&lt;/strong&gt;: Annotations are free-form key-value pairs that can be used to attach any type of metadata to Kubernetes objects.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Not Used for Selection&lt;/strong&gt;: Unlike labels, annotations are not used in selectors (e.g., for service selection, replication controller selection).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;No Constraints on Values&lt;/strong&gt;: The values of annotations can be any string, including structured data formats like JSON or XML.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Can Be Large&lt;/strong&gt;: Annotations can store larger amounts of data compared to labels, which are typically limited to a few kilobytes.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Example of Pod manifest with annotation:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;annotations-demo&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;annotations:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;imageregistry:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;https://hub.docker.com/&quot;&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;containers:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx:1.14.2&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;ports:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;containerPort:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;80&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;heading-common-use-cases-for-annotations&quot;&gt;Common Use Cases for Annotations:&lt;/h2&gt;&lt;h3 id=&quot;heading-metadata-for-external-tools&quot;&gt;&lt;strong&gt;Metadata for External Tools&lt;/strong&gt;:&lt;/h3&gt;&lt;p&gt;Annotations can be used to attach information that is used by external tools or systems. For example, a monitoring system might use annotations to store configuration details for collecting metrics from a pod.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;mypod&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;annotations:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;monitoring.tool/config:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&apos;{&quot;scrape_interval&quot;: &quot;30s&quot;, &quot;path&quot;: &quot;/metrics&quot;}&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-build-and-deployment-information&quot;&gt;&lt;strong&gt;Build and Deployment Information&lt;/strong&gt;:&lt;/h3&gt;&lt;p&gt;Annotations can be used to store build and deployment details such as the version of the application, build date, or git commit hash.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;mypod&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;annotations:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;build.version:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;1.0.0&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;build.date:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;2024-07-08T12:34:56Z&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;build.commit:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;abc123def&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-debugging-and-auditing&quot;&gt;&lt;strong&gt;Debugging and Auditing&lt;/strong&gt;:&lt;/h3&gt;&lt;p&gt;Annotations can be used to track the source of changes, reasons for deployments, or other debugging and auditing information.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;mypod&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;annotations:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;lastUpdatedBy:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;DevOps Team&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;updateReason:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Security patch&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-configuration-and-policy-management&quot;&gt;&lt;strong&gt;Configuration and Policy Management&lt;/strong&gt;:&lt;/h3&gt;&lt;p&gt;Annotations can be used to pass configuration data to controllers or &lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#what-are-admission-webhooks&quot;&gt;admission webhooks&lt;/a&gt; that enforce policies or modify the behavior of resources.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;mypod&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;annotations:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;policy.enforcer/ignore:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;true&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-operational-information&quot;&gt;&lt;strong&gt;Operational Information&lt;/strong&gt;:&lt;/h3&gt;&lt;p&gt;Annotations can store operational information such as priority data or custom handling instructions for specific environments.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;high-priority-pod&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;annotations:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;environment:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;production&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;custom.scheduler/priority:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;high&quot;&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;containers:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx:1.17.4&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;ports:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;containerPort:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;80&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;heading-dynamic-annotation-values&quot;&gt;Dynamic annotation values&lt;/h2&gt;&lt;p&gt;Keep in mind, that annotation values can be populated dynamically in CI/CD tools. In the following examples, you will see the hardcoded values. However, on practice we can generate the annotation value dynamically by using scripts, environment variables and CI/CD toolset.&lt;/p&gt;&lt;p&gt;For example here&apos;s &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; for GitLab CI/CD that annotates the deployment parameters by using environment variables:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;stages:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;build&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;docker&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;deploy&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;variables:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;APP_VERSION:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;1.2.3&quot;&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;build:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;stage:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;build&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;script:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Building application version $APP_VERSION&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-comment&quot;&gt;# Add your build commands here&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;docker-build:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;stage:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;docker&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;script:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;docker&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;build&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;-t&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;myapp:$APP_VERSION&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;.&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;docker&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;tag&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;myapp:$APP_VERSION&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;myregistry/myapp:$APP_VERSION&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;docker&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;push&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;myregistry/myapp:$APP_VERSION&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;deploy:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;stage:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;deploy&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;script:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;BUILD_DATE=$(date&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;-u&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;+&quot;%Y-%m-%dT%H:%M:%SZ&quot;)&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;GIT_COMMIT=$(git&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;rev-parse&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;HEAD)&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;|      cat &amp;lt;&amp;lt;EOF &amp;gt; deployment.yaml      apiVersion: apps/v1      kind: Deployment      metadata:        name: myapp-deployment        annotations:          build.version: &quot;$APP_VERSION&quot;          build.date: &quot;$BUILD_DATE&quot;          build.commit: &quot;$GIT_COMMIT&quot;          deployment.team: &quot;devops&quot;          deployment.reason: &quot;feature release&quot;      spec:        replicas: 3        selector:          matchLabels:            app: myapp        template:          metadata:            labels:              app: myapp            annotations:              monitoring.tool/config: &apos;{&quot;scrape_interval&quot;: &quot;30s&quot;, &quot;path&quot;: &quot;/metrics&quot;}&apos;          spec:            containers:            - name: myapp-container              image: myregistry/myapp:$APP_VERSION              ports:              - containerPort: 80      EOF&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;kubectl&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;apply&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;deployment.yaml&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;heading-managing-annotations&quot;&gt;Managing Annotations:&lt;/h2&gt;&lt;p&gt;Annotations can be managed using kubectl commands. For example:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Add an annotation&lt;/strong&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-sh&quot;&gt;  kubectl annotate pod example-pod example.com/owner=&lt;span class=&quot;hljs-string&quot;&gt;&quot;team-a&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Remove an annotation&lt;/strong&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-sh&quot;&gt;  kubectl annotate pod example-pod example.com/owner-&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&quot;heading-references&quot;&gt;References:&lt;/h2&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://medium.com/@sangjinn/kubernetes-annotations-e61b19effdf9&quot;&gt;Medium Blog: What are Kubernetes Annotations?&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/&quot;&gt;Kubernetes Docs: Annotations&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;]]&gt;</hashnode:content><hashnode:coverImage>https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/eeSdJfLfx1A/upload/8d8ec9f8ccdd7b41539ec31f2e39320b.jpeg</hashnode:coverImage></item><item><title><![CDATA[Kubernetes Logging Basics: Tracking at Container and Pod Levels]]></title><description><![CDATA[Kubernetes Logging Basics: Tracking at Container and Pod Levels]]></description><link>https://maxat-akbanov.com/kubernetes-logging-basics-tracking-at-container-and-pod-levels</link><guid isPermaLink="true">https://maxat-akbanov.com/kubernetes-logging-basics-tracking-at-container-and-pod-levels</guid><category><![CDATA[Devops]]></category><category><![CDATA[sysops]]></category><category><![CDATA[Kubernetes]]></category><category><![CDATA[k8s]]></category><category><![CDATA[#Pods ]]></category><category><![CDATA[containers]]></category><category><![CDATA[logging]]></category><dc:creator><![CDATA[Maxat Akbanov]]></dc:creator><pubDate>Sun, 07 Jul 2024 10:10:23 GMT</pubDate><content:encoded>&lt;![CDATA[&lt;p&gt;In Kubernetes, &lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/cluster-administration/logging/#basic-logging-in-kubernetes&quot;&gt;logging at the container and pod levels&lt;/a&gt; is essential for monitoring and debugging applications. Kubernetes captures logs from each container in a running Pod.&lt;/p&gt;&lt;h2 id=&quot;heading-container-level-logging&quot;&gt;Container-Level Logging&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Container logs&lt;/strong&gt; are generated by individual containers running within pods. These logs typically include application-specific logs, such as error messages, access logs, and other runtime information.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://kubernetes.io/images/docs/user-guide/logging/logging-node-level.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;Image credits: &lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/&quot;&gt;Kubernetes&lt;/a&gt;&lt;/p&gt;&lt;p&gt;In general Kubernetes handles container logs in the following way:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Containers write their logs to standard output (&lt;code&gt;stdout&lt;/code&gt;) and standard error (&lt;code&gt;stderr&lt;/code&gt;) streams.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The container runtime, like &lt;a target=&quot;_blank&quot; href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt; or &lt;a target=&quot;_blank&quot; href=&quot;https://containerd.io/&quot;&gt;containerd&lt;/a&gt;, intercepts these streams.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Kubernetes uses a standardized format (CRI logging) to interact with the container runtime and access the logs.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;By default, logs are saved in files on the node, typically under &lt;code&gt;/var/log/pods&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;You can view container logs using the &lt;code&gt;kubectl logs &amp;lt;pod_name&amp;gt; [container_name]&lt;/code&gt; command.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;The &lt;code&gt;container_name&lt;/code&gt; is optional if the pod only has one container.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;You can use the &lt;code&gt;-f&lt;/code&gt; flag to follow the logs in real-time.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-standard-output-and-error-streams&quot;&gt;&lt;strong&gt;Standard Output and Error Streams&lt;/strong&gt;:&lt;/h3&gt;&lt;p&gt;Containers in Kubernetes are designed to log information to the standard output (&lt;code&gt;stdout&lt;/code&gt;) and standard error (&lt;code&gt;stderr&lt;/code&gt;) streams. Container runtimes captures these streams and stores the logs for later access. Different container runtimes implement this in different ways; however, the integration with the kubelet is standardized as the &lt;em&gt;Container Runtime Interface&lt;/em&gt; (&lt;em&gt;CRI) logging format&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;Kubernetes CRI defines a standard for container runtimes to follow, which also affects log format. A typical CRI log entry includes a timestamp, the output stream type, and the log message itself.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-plaintext&quot;&gt;2023-10-06T00:17:09.669794202Z stdout F Your log message here2023-10-06T00:17:09.669794202Z stdout P Another log pt 12023-10-06T00:17:09.669794202Z stdout P Another log pt 22023-10-06T00:17:10.113242941Z stderr F Another log final&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-log-storage&quot;&gt;&lt;strong&gt;Log Storage&lt;/strong&gt;:&lt;/h3&gt;&lt;p&gt;The way that the kubelet and container runtime write logs depends on the operating system that the node uses (Linux, Windows).&lt;/p&gt;&lt;p&gt;On Linux nodes that use systemd, the kubelet and container runtime write to journald by default. You use &lt;code&gt;journalctl&lt;/code&gt; to read the systemd journal; for example: &lt;code&gt;journalctl -u kubelet&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;If systemd is not present, the kubelet and container runtime write to &lt;code&gt;.log&lt;/code&gt; files in the &lt;code&gt;/var/log&lt;/code&gt; directory. If you want to have logs written elsewhere, you can indirectly run the kubelet via a helper tool, &lt;code&gt;kube-log-runner&lt;/code&gt;, and use that tool to redirect kubelet logs to a directory that you choose.&lt;/p&gt;&lt;p&gt;By default, kubelet directs your container runtime to write logs into directories within &lt;code&gt;/var/log/pods&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;For more information on &lt;code&gt;kube-log-runner&lt;/code&gt;, read &lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/cluster-administration/system-logs/#klog&quot;&gt;System Logs.&lt;/a&gt;&lt;/p&gt;&lt;h3 id=&quot;heading-accessing-logs&quot;&gt;&lt;strong&gt;Accessing Logs&lt;/strong&gt;:&lt;/h3&gt;&lt;p&gt;You can access container logs using the &lt;code&gt;kubectl logs&lt;/code&gt; command:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;kubectl logs &amp;lt;pod-name&amp;gt; -c &amp;lt;container-name&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If a pod has only one container, you can omit the &lt;code&gt;-c &amp;lt;container-name&amp;gt;&lt;/code&gt; option.&lt;/p&gt;&lt;p&gt;You can use &lt;code&gt;kubectl logs --previous&lt;/code&gt; to retrieve logs from a previous instantiation of a container.&lt;/p&gt;&lt;h3 id=&quot;heading-log-aggregation&quot;&gt;&lt;strong&gt;Log Aggregation&lt;/strong&gt;:&lt;/h3&gt;&lt;p&gt;While accessing logs directly is useful for quick debugging, for large-scale applications, aggregating logs from all containers and storing them in a centralized location is more efficient. This is usually done using logging agents like &lt;a target=&quot;_blank&quot; href=&quot;https://www.fluentd.org/&quot;&gt;Fluentd&lt;/a&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/cluster-administration/system-logs/#klog&quot;&gt;,&lt;/a&gt; &lt;a target=&quot;_blank&quot; href=&quot;https://www.elastic.co/logstash&quot;&gt;Logstash&lt;/a&gt;, &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/grafana/loki&quot;&gt;Loki&lt;/a&gt; or others, which collect logs from containers and forward them to a logging backend.&lt;/p&gt;&lt;h2 id=&quot;heading-pod-level-logging&quot;&gt;Pod-Level Logging&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Pod logs&lt;/strong&gt; encompass the logs of all containers within a pod. A pod is the smallest deployable unit in Kubernetes and can consist of one or more containers that share the same network namespace and storage volumes.&lt;/p&gt;&lt;h3 id=&quot;heading-multi-container-pods&quot;&gt;&lt;strong&gt;Multi-Container Pods&lt;/strong&gt;:&lt;/h3&gt;&lt;p&gt;When a pod contains multiple containers, each container logs independently. These logs need to be aggregated to get a complete picture of the pods activities.&lt;/p&gt;&lt;p&gt;In general Kubernetes manages pod level logging in the following way:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;A pod might have multiple containers.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Kubernetes captures logs from each container within the pod.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;By default, &lt;code&gt;kubectl logs &amp;lt;pod_name&amp;gt;&lt;/code&gt; retrieves logs only from the first container.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;To view logs from a specific container within a pod, use &lt;code&gt;kubectl logs &amp;lt;pod_name&amp;gt; -c &amp;lt;container_name&amp;gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-sidecar-containers&quot;&gt;&lt;strong&gt;Sidecar Containers&lt;/strong&gt;:&lt;/h3&gt;&lt;p&gt;Often, &lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/cluster-administration/logging/#sidecar-container-with-logging-agent&quot;&gt;a sidecar container&lt;/a&gt; is used within the same pod to handle logging. The sidecar can read logs from shared volumes or directly from other containers and forward them to a centralized logging system.&lt;/p&gt;&lt;p&gt;You can use a sidecar container in one of the following ways:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;The sidecar container streams application logs to its own &lt;code&gt;stdout&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/cluster-administration/logging/#sidecar-container-with-a-logging-agent&quot;&gt;The sidecar container runs a logging agent&lt;/a&gt;, which is configured to pick up logs from an application container.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img src=&quot;https://kubernetes.io/images/docs/user-guide/logging/logging-with-streaming-sidecar.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;Image credits: &lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/&quot;&gt;Kubernetes&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The sidecar containers read logs from a file, a socket, or journald. Each sidecar container prints a log to its own &lt;code&gt;stdout&lt;/code&gt; or &lt;code&gt;stderr&lt;/code&gt; stream.&lt;/p&gt;&lt;p&gt;This approach allows you to separate several log streams from different parts of your application, some of which can lack support for writing to &lt;code&gt;stdout&lt;/code&gt; or &lt;code&gt;stderr&lt;/code&gt;. The logic behind redirecting logs is minimal, so it&apos;s not a significant overhead. Additionally, because &lt;code&gt;stdout&lt;/code&gt; and &lt;code&gt;stderr&lt;/code&gt; are handled by the kubelet, you can use built-in tools like &lt;code&gt;kubectl logs&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;For example, a pod runs a single container, and the container writes to two different log files using two different formats. Here&apos;s a manifest for the Pod:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;counter&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;containers:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;count&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;busybox:1.28&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;args:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/bin/sh&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;-c&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;gt;      i=0;      while true;      do        echo &quot;$i: $(date)&quot; &amp;gt;&amp;gt; /var/log/1.log;        echo &quot;$(date) INFO $i&quot; &amp;gt;&amp;gt; /var/log/2.log;        i=$((i+1));        sleep 1;      done      &lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;volumeMounts:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;varlog&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;mountPath:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/var/log&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;volumes:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;varlog&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;emptyDir:&lt;/span&gt; {}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It is not recommended to write log entries with different formats to the same log stream, even if you managed to redirect both components to the &lt;code&gt;stdout&lt;/code&gt; stream of the container. Instead, you can create two sidecar containers. Each sidecar container could tail a particular log file from a shared volume and then redirect the logs to its own &lt;code&gt;stdout&lt;/code&gt; stream.&lt;/p&gt;&lt;p&gt;Here&apos;s a manifest for a pod that has two sidecar containers:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;counter&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;containers:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;count&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;busybox:1.28&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;args:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/bin/sh&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;-c&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;gt;      i=0;      while true;      do        echo &quot;$i: $(date)&quot; &amp;gt;&amp;gt; /var/log/1.log;        echo &quot;$(date) INFO $i&quot; &amp;gt;&amp;gt; /var/log/2.log;        i=$((i+1));        sleep 1;      done      &lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;volumeMounts:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;varlog&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;mountPath:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/var/log&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;count-log-1&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;busybox:1.28&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;args:&lt;/span&gt; [&lt;span class=&quot;hljs-string&quot;&gt;/bin/sh&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;-c&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&apos;tail -n+1 -F /var/log/1.log&apos;&lt;/span&gt;]    &lt;span class=&quot;hljs-attr&quot;&gt;volumeMounts:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;varlog&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;mountPath:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/var/log&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;count-log-2&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;busybox:1.28&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;args:&lt;/span&gt; [&lt;span class=&quot;hljs-string&quot;&gt;/bin/sh&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;-c&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&apos;tail -n+1 -F /var/log/2.log&apos;&lt;/span&gt;]    &lt;span class=&quot;hljs-attr&quot;&gt;volumeMounts:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;varlog&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;mountPath:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/var/log&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;volumes:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;varlog&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;emptyDir:&lt;/span&gt; {}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now when you run this pod, you can access each log stream separately by running the following commands:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;kubectl logs counter count-log-1kubectl logs counter count-log-2&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Sidecar containers can also be used to rotate log files that cannot be rotated by the application itself. An example of this approach is a small container running &lt;code&gt;logrotate&lt;/code&gt; periodically. However, it&apos;s more straightforward to use &lt;code&gt;stdout&lt;/code&gt; and &lt;code&gt;stderr&lt;/code&gt; directly, and leave rotation and retention policies to the kubelet.&lt;/p&gt;&lt;h2 id=&quot;heading-log-management-tools&quot;&gt;&lt;strong&gt;Log Management Tools&lt;/strong&gt;:&lt;/h2&gt;&lt;p&gt;Using tools like &lt;a target=&quot;_blank&quot; href=&quot;https://www.fluentd.org/&quot;&gt;Fluentd&lt;/a&gt;, &lt;a target=&quot;_blank&quot; href=&quot;https://fluentbit.io/&quot;&gt;Fluent Bit&lt;/a&gt;, or &lt;a target=&quot;_blank&quot; href=&quot;https://grafana.com/docs/loki/latest/send-data/promtail/&quot;&gt;Promtail&lt;/a&gt; (from Loki), you can deploy them as DaemonSets or sidecars to collect logs from all pods across the cluster.&lt;/p&gt;&lt;p&gt;Example &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/fluent/fluentd-kubernetes-daemonset&quot;&gt;Fluentd DaemonSet configuration&lt;/a&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;apps/v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;DaemonSet&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;fluentd&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;namespace:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;kube-system&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;labels:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;k8s-app:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;fluentd-logging&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;selector:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;matchLabels:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;fluentd&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;template:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;labels:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;fluentd&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;containers:&lt;/span&gt;      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;fluentd&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;fluent/fluentd:v1.17&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;env:&lt;/span&gt;        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;FLUENTD_ARGS&lt;/span&gt;          &lt;span class=&quot;hljs-attr&quot;&gt;value:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;--no-supervisor -q&quot;&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;resources:&lt;/span&gt;          &lt;span class=&quot;hljs-attr&quot;&gt;limits:&lt;/span&gt;            &lt;span class=&quot;hljs-attr&quot;&gt;memory:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;200Mi&lt;/span&gt;            &lt;span class=&quot;hljs-attr&quot;&gt;cpu:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;100m&lt;/span&gt;          &lt;span class=&quot;hljs-attr&quot;&gt;requests:&lt;/span&gt;            &lt;span class=&quot;hljs-attr&quot;&gt;memory:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;200Mi&lt;/span&gt;            &lt;span class=&quot;hljs-attr&quot;&gt;cpu:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;100m&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;volumeMounts:&lt;/span&gt;        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;varlog&lt;/span&gt;          &lt;span class=&quot;hljs-attr&quot;&gt;mountPath:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/var/log&lt;/span&gt;        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;varlibdockercontainers&lt;/span&gt;          &lt;span class=&quot;hljs-attr&quot;&gt;mountPath:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/var/lib/docker/containers&lt;/span&gt;          &lt;span class=&quot;hljs-attr&quot;&gt;readOnly:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;terminationGracePeriodSeconds:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;30&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;volumes:&lt;/span&gt;      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;varlog&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;hostPath:&lt;/span&gt;          &lt;span class=&quot;hljs-attr&quot;&gt;path:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/var/log&lt;/span&gt;      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;varlibdockercontainers&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;hostPath:&lt;/span&gt;          &lt;span class=&quot;hljs-attr&quot;&gt;path:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/var/lib/docker/containers&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-centralized-logging&quot;&gt;Centralized Logging&lt;/h3&gt;&lt;p&gt;For large Kubernetes clusters, centralized logging is crucial. It involves collecting logs from all nodes, containers, and pods and storing them in a centralized logging system for easy access, search, and analysis. Common centralized logging solutions include:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;EFK Stack&lt;/strong&gt;: Elasticsearch, Fluentd, and Kibana.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;ELK Stack&lt;/strong&gt;: Elasticsearch, Logstash, and Kibana.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Loki and Grafana&lt;/strong&gt;: Promtail for log collection, Loki for storage, and Grafana for visualization.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Third-Party Paid Services&lt;/strong&gt;: Such as &lt;a target=&quot;_blank&quot; href=&quot;https://www.datadoghq.com/&quot;&gt;Datadog&lt;/a&gt; or &lt;a target=&quot;_blank&quot; href=&quot;https://www.splunk.com/&quot;&gt;Splunk&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;]]&gt;</content:encoded><hashnode:content>&lt;![CDATA[&lt;p&gt;In Kubernetes, &lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/cluster-administration/logging/#basic-logging-in-kubernetes&quot;&gt;logging at the container and pod levels&lt;/a&gt; is essential for monitoring and debugging applications. Kubernetes captures logs from each container in a running Pod.&lt;/p&gt;&lt;h2 id=&quot;heading-container-level-logging&quot;&gt;Container-Level Logging&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Container logs&lt;/strong&gt; are generated by individual containers running within pods. These logs typically include application-specific logs, such as error messages, access logs, and other runtime information.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://kubernetes.io/images/docs/user-guide/logging/logging-node-level.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;Image credits: &lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/&quot;&gt;Kubernetes&lt;/a&gt;&lt;/p&gt;&lt;p&gt;In general Kubernetes handles container logs in the following way:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Containers write their logs to standard output (&lt;code&gt;stdout&lt;/code&gt;) and standard error (&lt;code&gt;stderr&lt;/code&gt;) streams.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The container runtime, like &lt;a target=&quot;_blank&quot; href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt; or &lt;a target=&quot;_blank&quot; href=&quot;https://containerd.io/&quot;&gt;containerd&lt;/a&gt;, intercepts these streams.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Kubernetes uses a standardized format (CRI logging) to interact with the container runtime and access the logs.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;By default, logs are saved in files on the node, typically under &lt;code&gt;/var/log/pods&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;You can view container logs using the &lt;code&gt;kubectl logs &amp;lt;pod_name&amp;gt; [container_name]&lt;/code&gt; command.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;The &lt;code&gt;container_name&lt;/code&gt; is optional if the pod only has one container.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;You can use the &lt;code&gt;-f&lt;/code&gt; flag to follow the logs in real-time.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-standard-output-and-error-streams&quot;&gt;&lt;strong&gt;Standard Output and Error Streams&lt;/strong&gt;:&lt;/h3&gt;&lt;p&gt;Containers in Kubernetes are designed to log information to the standard output (&lt;code&gt;stdout&lt;/code&gt;) and standard error (&lt;code&gt;stderr&lt;/code&gt;) streams. Container runtimes captures these streams and stores the logs for later access. Different container runtimes implement this in different ways; however, the integration with the kubelet is standardized as the &lt;em&gt;Container Runtime Interface&lt;/em&gt; (&lt;em&gt;CRI) logging format&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;Kubernetes CRI defines a standard for container runtimes to follow, which also affects log format. A typical CRI log entry includes a timestamp, the output stream type, and the log message itself.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-plaintext&quot;&gt;2023-10-06T00:17:09.669794202Z stdout F Your log message here2023-10-06T00:17:09.669794202Z stdout P Another log pt 12023-10-06T00:17:09.669794202Z stdout P Another log pt 22023-10-06T00:17:10.113242941Z stderr F Another log final&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-log-storage&quot;&gt;&lt;strong&gt;Log Storage&lt;/strong&gt;:&lt;/h3&gt;&lt;p&gt;The way that the kubelet and container runtime write logs depends on the operating system that the node uses (Linux, Windows).&lt;/p&gt;&lt;p&gt;On Linux nodes that use systemd, the kubelet and container runtime write to journald by default. You use &lt;code&gt;journalctl&lt;/code&gt; to read the systemd journal; for example: &lt;code&gt;journalctl -u kubelet&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;If systemd is not present, the kubelet and container runtime write to &lt;code&gt;.log&lt;/code&gt; files in the &lt;code&gt;/var/log&lt;/code&gt; directory. If you want to have logs written elsewhere, you can indirectly run the kubelet via a helper tool, &lt;code&gt;kube-log-runner&lt;/code&gt;, and use that tool to redirect kubelet logs to a directory that you choose.&lt;/p&gt;&lt;p&gt;By default, kubelet directs your container runtime to write logs into directories within &lt;code&gt;/var/log/pods&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;For more information on &lt;code&gt;kube-log-runner&lt;/code&gt;, read &lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/cluster-administration/system-logs/#klog&quot;&gt;System Logs.&lt;/a&gt;&lt;/p&gt;&lt;h3 id=&quot;heading-accessing-logs&quot;&gt;&lt;strong&gt;Accessing Logs&lt;/strong&gt;:&lt;/h3&gt;&lt;p&gt;You can access container logs using the &lt;code&gt;kubectl logs&lt;/code&gt; command:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;kubectl logs &amp;lt;pod-name&amp;gt; -c &amp;lt;container-name&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If a pod has only one container, you can omit the &lt;code&gt;-c &amp;lt;container-name&amp;gt;&lt;/code&gt; option.&lt;/p&gt;&lt;p&gt;You can use &lt;code&gt;kubectl logs --previous&lt;/code&gt; to retrieve logs from a previous instantiation of a container.&lt;/p&gt;&lt;h3 id=&quot;heading-log-aggregation&quot;&gt;&lt;strong&gt;Log Aggregation&lt;/strong&gt;:&lt;/h3&gt;&lt;p&gt;While accessing logs directly is useful for quick debugging, for large-scale applications, aggregating logs from all containers and storing them in a centralized location is more efficient. This is usually done using logging agents like &lt;a target=&quot;_blank&quot; href=&quot;https://www.fluentd.org/&quot;&gt;Fluentd&lt;/a&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/cluster-administration/system-logs/#klog&quot;&gt;,&lt;/a&gt; &lt;a target=&quot;_blank&quot; href=&quot;https://www.elastic.co/logstash&quot;&gt;Logstash&lt;/a&gt;, &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/grafana/loki&quot;&gt;Loki&lt;/a&gt; or others, which collect logs from containers and forward them to a logging backend.&lt;/p&gt;&lt;h2 id=&quot;heading-pod-level-logging&quot;&gt;Pod-Level Logging&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Pod logs&lt;/strong&gt; encompass the logs of all containers within a pod. A pod is the smallest deployable unit in Kubernetes and can consist of one or more containers that share the same network namespace and storage volumes.&lt;/p&gt;&lt;h3 id=&quot;heading-multi-container-pods&quot;&gt;&lt;strong&gt;Multi-Container Pods&lt;/strong&gt;:&lt;/h3&gt;&lt;p&gt;When a pod contains multiple containers, each container logs independently. These logs need to be aggregated to get a complete picture of the pods activities.&lt;/p&gt;&lt;p&gt;In general Kubernetes manages pod level logging in the following way:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;A pod might have multiple containers.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Kubernetes captures logs from each container within the pod.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;By default, &lt;code&gt;kubectl logs &amp;lt;pod_name&amp;gt;&lt;/code&gt; retrieves logs only from the first container.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;To view logs from a specific container within a pod, use &lt;code&gt;kubectl logs &amp;lt;pod_name&amp;gt; -c &amp;lt;container_name&amp;gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-sidecar-containers&quot;&gt;&lt;strong&gt;Sidecar Containers&lt;/strong&gt;:&lt;/h3&gt;&lt;p&gt;Often, &lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/cluster-administration/logging/#sidecar-container-with-logging-agent&quot;&gt;a sidecar container&lt;/a&gt; is used within the same pod to handle logging. The sidecar can read logs from shared volumes or directly from other containers and forward them to a centralized logging system.&lt;/p&gt;&lt;p&gt;You can use a sidecar container in one of the following ways:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;The sidecar container streams application logs to its own &lt;code&gt;stdout&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/cluster-administration/logging/#sidecar-container-with-a-logging-agent&quot;&gt;The sidecar container runs a logging agent&lt;/a&gt;, which is configured to pick up logs from an application container.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img src=&quot;https://kubernetes.io/images/docs/user-guide/logging/logging-with-streaming-sidecar.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;Image credits: &lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/&quot;&gt;Kubernetes&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The sidecar containers read logs from a file, a socket, or journald. Each sidecar container prints a log to its own &lt;code&gt;stdout&lt;/code&gt; or &lt;code&gt;stderr&lt;/code&gt; stream.&lt;/p&gt;&lt;p&gt;This approach allows you to separate several log streams from different parts of your application, some of which can lack support for writing to &lt;code&gt;stdout&lt;/code&gt; or &lt;code&gt;stderr&lt;/code&gt;. The logic behind redirecting logs is minimal, so it&apos;s not a significant overhead. Additionally, because &lt;code&gt;stdout&lt;/code&gt; and &lt;code&gt;stderr&lt;/code&gt; are handled by the kubelet, you can use built-in tools like &lt;code&gt;kubectl logs&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;For example, a pod runs a single container, and the container writes to two different log files using two different formats. Here&apos;s a manifest for the Pod:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;counter&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;containers:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;count&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;busybox:1.28&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;args:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/bin/sh&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;-c&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;gt;      i=0;      while true;      do        echo &quot;$i: $(date)&quot; &amp;gt;&amp;gt; /var/log/1.log;        echo &quot;$(date) INFO $i&quot; &amp;gt;&amp;gt; /var/log/2.log;        i=$((i+1));        sleep 1;      done      &lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;volumeMounts:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;varlog&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;mountPath:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/var/log&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;volumes:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;varlog&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;emptyDir:&lt;/span&gt; {}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It is not recommended to write log entries with different formats to the same log stream, even if you managed to redirect both components to the &lt;code&gt;stdout&lt;/code&gt; stream of the container. Instead, you can create two sidecar containers. Each sidecar container could tail a particular log file from a shared volume and then redirect the logs to its own &lt;code&gt;stdout&lt;/code&gt; stream.&lt;/p&gt;&lt;p&gt;Here&apos;s a manifest for a pod that has two sidecar containers:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;counter&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;containers:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;count&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;busybox:1.28&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;args:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/bin/sh&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;-c&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&amp;gt;      i=0;      while true;      do        echo &quot;$i: $(date)&quot; &amp;gt;&amp;gt; /var/log/1.log;        echo &quot;$(date) INFO $i&quot; &amp;gt;&amp;gt; /var/log/2.log;        i=$((i+1));        sleep 1;      done      &lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;volumeMounts:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;varlog&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;mountPath:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/var/log&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;count-log-1&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;busybox:1.28&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;args:&lt;/span&gt; [&lt;span class=&quot;hljs-string&quot;&gt;/bin/sh&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;-c&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&apos;tail -n+1 -F /var/log/1.log&apos;&lt;/span&gt;]    &lt;span class=&quot;hljs-attr&quot;&gt;volumeMounts:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;varlog&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;mountPath:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/var/log&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;count-log-2&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;busybox:1.28&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;args:&lt;/span&gt; [&lt;span class=&quot;hljs-string&quot;&gt;/bin/sh&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;-c&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&apos;tail -n+1 -F /var/log/2.log&apos;&lt;/span&gt;]    &lt;span class=&quot;hljs-attr&quot;&gt;volumeMounts:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;varlog&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;mountPath:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/var/log&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;volumes:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;varlog&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;emptyDir:&lt;/span&gt; {}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now when you run this pod, you can access each log stream separately by running the following commands:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;kubectl logs counter count-log-1kubectl logs counter count-log-2&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Sidecar containers can also be used to rotate log files that cannot be rotated by the application itself. An example of this approach is a small container running &lt;code&gt;logrotate&lt;/code&gt; periodically. However, it&apos;s more straightforward to use &lt;code&gt;stdout&lt;/code&gt; and &lt;code&gt;stderr&lt;/code&gt; directly, and leave rotation and retention policies to the kubelet.&lt;/p&gt;&lt;h2 id=&quot;heading-log-management-tools&quot;&gt;&lt;strong&gt;Log Management Tools&lt;/strong&gt;:&lt;/h2&gt;&lt;p&gt;Using tools like &lt;a target=&quot;_blank&quot; href=&quot;https://www.fluentd.org/&quot;&gt;Fluentd&lt;/a&gt;, &lt;a target=&quot;_blank&quot; href=&quot;https://fluentbit.io/&quot;&gt;Fluent Bit&lt;/a&gt;, or &lt;a target=&quot;_blank&quot; href=&quot;https://grafana.com/docs/loki/latest/send-data/promtail/&quot;&gt;Promtail&lt;/a&gt; (from Loki), you can deploy them as DaemonSets or sidecars to collect logs from all pods across the cluster.&lt;/p&gt;&lt;p&gt;Example &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/fluent/fluentd-kubernetes-daemonset&quot;&gt;Fluentd DaemonSet configuration&lt;/a&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;apps/v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;DaemonSet&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;fluentd&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;namespace:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;kube-system&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;labels:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;k8s-app:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;fluentd-logging&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;selector:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;matchLabels:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;fluentd&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;template:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;labels:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;fluentd&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;containers:&lt;/span&gt;      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;fluentd&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;fluent/fluentd:v1.17&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;env:&lt;/span&gt;        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;FLUENTD_ARGS&lt;/span&gt;          &lt;span class=&quot;hljs-attr&quot;&gt;value:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;--no-supervisor -q&quot;&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;resources:&lt;/span&gt;          &lt;span class=&quot;hljs-attr&quot;&gt;limits:&lt;/span&gt;            &lt;span class=&quot;hljs-attr&quot;&gt;memory:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;200Mi&lt;/span&gt;            &lt;span class=&quot;hljs-attr&quot;&gt;cpu:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;100m&lt;/span&gt;          &lt;span class=&quot;hljs-attr&quot;&gt;requests:&lt;/span&gt;            &lt;span class=&quot;hljs-attr&quot;&gt;memory:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;200Mi&lt;/span&gt;            &lt;span class=&quot;hljs-attr&quot;&gt;cpu:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;100m&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;volumeMounts:&lt;/span&gt;        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;varlog&lt;/span&gt;          &lt;span class=&quot;hljs-attr&quot;&gt;mountPath:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/var/log&lt;/span&gt;        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;varlibdockercontainers&lt;/span&gt;          &lt;span class=&quot;hljs-attr&quot;&gt;mountPath:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/var/lib/docker/containers&lt;/span&gt;          &lt;span class=&quot;hljs-attr&quot;&gt;readOnly:&lt;/span&gt; &lt;span class=&quot;hljs-literal&quot;&gt;true&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;terminationGracePeriodSeconds:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;30&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;volumes:&lt;/span&gt;      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;varlog&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;hostPath:&lt;/span&gt;          &lt;span class=&quot;hljs-attr&quot;&gt;path:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/var/log&lt;/span&gt;      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;varlibdockercontainers&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;hostPath:&lt;/span&gt;          &lt;span class=&quot;hljs-attr&quot;&gt;path:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/var/lib/docker/containers&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-centralized-logging&quot;&gt;Centralized Logging&lt;/h3&gt;&lt;p&gt;For large Kubernetes clusters, centralized logging is crucial. It involves collecting logs from all nodes, containers, and pods and storing them in a centralized logging system for easy access, search, and analysis. Common centralized logging solutions include:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;EFK Stack&lt;/strong&gt;: Elasticsearch, Fluentd, and Kibana.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;ELK Stack&lt;/strong&gt;: Elasticsearch, Logstash, and Kibana.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Loki and Grafana&lt;/strong&gt;: Promtail for log collection, Loki for storage, and Grafana for visualization.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Third-Party Paid Services&lt;/strong&gt;: Such as &lt;a target=&quot;_blank&quot; href=&quot;https://www.datadoghq.com/&quot;&gt;Datadog&lt;/a&gt; or &lt;a target=&quot;_blank&quot; href=&quot;https://www.splunk.com/&quot;&gt;Splunk&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;]]&gt;</hashnode:content><hashnode:coverImage>https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/1bNQVGzuy0U/upload/26c39b80657be275e7f1b3587bc388ac.jpeg</hashnode:coverImage></item><item><title><![CDATA[Kubernetes Pod Anti-Affinity: A Beginner's Guide]]></title><description><![CDATA[Kubernetes Pod Anti-Affinity: A Beginner's Guide]]></description><link>https://maxat-akbanov.com/kubernetes-pod-anti-affinity-a-beginners-guide</link><guid isPermaLink="true">https://maxat-akbanov.com/kubernetes-pod-anti-affinity-a-beginners-guide</guid><category><![CDATA[Devops]]></category><category><![CDATA[sysops]]></category><category><![CDATA[k8s]]></category><category><![CDATA[Kubernetes]]></category><category><![CDATA[Affinity]]></category><category><![CDATA[#Pods ]]></category><dc:creator><![CDATA[Maxat Akbanov]]></dc:creator><pubDate>Thu, 04 Jul 2024 14:04:56 GMT</pubDate><content:encoded>&lt;![CDATA[&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity&quot;&gt;&lt;strong&gt;Pod anti-affinity&lt;/strong&gt;&lt;/a&gt; is a Kubernetes feature that allows you to specify that certain pods should not be scheduled on the same nodes as other specified pods. This is useful for ensuring high availability and resilience by spreading out workloads across different nodes.&lt;/p&gt;&lt;div data-node-type=&quot;callout&quot;&gt;&lt;div data-node-type=&quot;callout-emoji&quot;&gt;💡&lt;/div&gt;&lt;div data-node-type=&quot;callout-text&quot;&gt;Pod anti-affinity is not only applied for nodes, but in case of using of cloud provider it can be applied for different &lt;em&gt;availability zones&lt;/em&gt; and &lt;em&gt;regions. &lt;/em&gt;This achieved by specifying the &lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/reference/labels-annotations-taints/&quot;&gt;&lt;code&gt;topologyKey&lt;/code&gt;&lt;/a&gt; value in the affinity specification.&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Let&apos;s imagine a scenario where you have multiple applications running on your cluster in a microservice architecture, and your cluster consists of several nodes hosting your application pods. While the scheduler ensures that all your pods are placed on healthy nodes with adequate resources, it doesn&apos;t consider which specific applications are running in each pod when deciding on placement. This could lead to a situation where all the pods from a particular deployment are placed on the same node. The major drawback of this situation is that it exposes that application to the risk of failure if that node goes down. The Pod Anti-Affinity helps us to spread the pods evenly across the nodes in the cluster.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1720034669524/6ec14458-1fd0-4bb0-87bd-9306527545b0.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;h2 id=&quot;heading-difference-between-node-affinity-and-pod-affinityanti-affinity&quot;&gt;Difference between Node Affinity and Pod Affinity/Anti-Affinity&lt;/h2&gt;&lt;p&gt;Node Affinity and Inter-Pod Affinity/Anti-Affinity are Kubernetes features that help control the placement of pods within a cluster. However, they serve different purposes and operate based on different criteria.&lt;/p&gt;&lt;h3 id=&quot;heading-node-affinity&quot;&gt;Node Affinity&lt;/h3&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity&quot;&gt;&lt;strong&gt;Node Affinity&lt;/strong&gt;&lt;/a&gt; is used to control which nodes a pod can be scheduled on based on node labels. It allows you to specify rules that must be satisfied for a pod to be scheduled onto a node.&lt;/p&gt;&lt;h4 id=&quot;heading-key-points&quot;&gt;Key Points:&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Based on Node Labels&lt;/strong&gt;: Node Affinity uses the labels assigned to nodes to determine where pods can be scheduled.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Types of Affinity&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;requiredDuringSchedulingIgnoredDuringExecution&lt;/strong&gt;: The scheduler can&apos;t schedule the Pod unless the rule is met. This is a hard requirement.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;preferredDuringSchedulingIgnoredDuringExecution&lt;/strong&gt;: The scheduler tries to find a node that meets the rule. If a matching node is not available, the scheduler still schedules the Pod.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div data-node-type=&quot;callout&quot;&gt;&lt;div data-node-type=&quot;callout-emoji&quot;&gt;💡&lt;/div&gt;&lt;div data-node-type=&quot;callout-text&quot;&gt;&lt;code&gt;IgnoredDuringExecution&lt;/code&gt;&lt;strong&gt; &lt;/strong&gt;means that if the node labels change after Kubernetes schedules the Pod, the Pod continues to run.&lt;/div&gt;&lt;/div&gt;&lt;h4 id=&quot;heading-example&quot;&gt;Example:&lt;/h4&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;with-node-affinity&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;affinity:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;nodeAffinity:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;requiredDuringSchedulingIgnoredDuringExecution:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;nodeSelectorTerms:&lt;/span&gt;        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;matchExpressions:&lt;/span&gt;          &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;key:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;topology.kubernetes.io/zone&lt;/span&gt;            &lt;span class=&quot;hljs-attr&quot;&gt;operator:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;In&lt;/span&gt;            &lt;span class=&quot;hljs-attr&quot;&gt;values:&lt;/span&gt;            &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;antarctica-east1&lt;/span&gt;            &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;antarctica-west1&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;preferredDuringSchedulingIgnoredDuringExecution:&lt;/span&gt;      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;weight:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;preference:&lt;/span&gt;          &lt;span class=&quot;hljs-attr&quot;&gt;matchExpressions:&lt;/span&gt;          &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;key:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;another-node-label-key&lt;/span&gt;            &lt;span class=&quot;hljs-attr&quot;&gt;operator:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;In&lt;/span&gt;            &lt;span class=&quot;hljs-attr&quot;&gt;values:&lt;/span&gt;            &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;another-node-label-value&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;containers:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;with-node-affinity&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;registry.k8s.io/pause:2.0&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-inter-pod-affinityanti-affinity&quot;&gt;Inter-Pod Affinity/Anti-Affinity&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Inter-Pod Affinity&lt;/strong&gt; and &lt;strong&gt;Pod Anti-Affinity&lt;/strong&gt; control the placement of pods relative to other pods based on their labels. These features allow you to specify rules for placing pods in relation to other pods.&lt;/p&gt;&lt;div data-node-type=&quot;callout&quot;&gt;&lt;div data-node-type=&quot;callout-emoji&quot;&gt;&lt;/div&gt;&lt;div data-node-type=&quot;callout-text&quot;&gt;Inter-pod affinity and anti-affinity require substantial amounts of processing which can slow down scheduling in large clusters significantly. It is not recommended using them in clusters larger than several hundred nodes.&lt;/div&gt;&lt;/div&gt;&lt;h4 id=&quot;heading-key-points-1&quot;&gt;Key Points:&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Based on Pod Labels&lt;/strong&gt;: Pod Affinity/Anti-Affinity uses labels assigned to pods to determine placement.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Types of Affinity&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Inter-Pod Affinity&lt;/strong&gt;: Ensures that pods are scheduled on the same node or close to other specified pods.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pod Anti-Affinity&lt;/strong&gt;: Ensures that pods are not scheduled on the same node or close to other specified pods.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Topology Key&lt;/strong&gt;: Specifies the &lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Failure_domain&quot;&gt;failure domain&lt;/a&gt; within which the affinity or anti-affinity rule applies (e.g., &lt;a target=&quot;_blank&quot; href=&quot;http://kubernetes.io/hostname&quot;&gt;&lt;code&gt;kubernetes.io/hostname&lt;/code&gt;&lt;/a&gt; for nodes, &lt;a target=&quot;_blank&quot; href=&quot;http://topology.kubernetes.io/zone&quot;&gt;&lt;code&gt;topology.kubernetes.io/zone&lt;/code&gt;&lt;/a&gt; for zones in the cloud).&lt;/p&gt;  &lt;div data-node-type=&quot;callout&quot;&gt;  &lt;div data-node-type=&quot;callout-emoji&quot;&gt;&lt;/div&gt;  &lt;div data-node-type=&quot;callout-text&quot;&gt;Pod anti-affinity requires nodes to be consistently labeled, in other words, every node in the cluster must have an appropriate label matching &lt;code&gt;topologyKey&lt;/code&gt;. If some or all nodes are missing the specified &lt;code&gt;topologyKey&lt;/code&gt; label, it can lead to unintended behavior.&lt;/div&gt;  &lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h4 id=&quot;heading-examples&quot;&gt;Examples:&lt;/h4&gt;&lt;p&gt;&lt;strong&gt;Inter-Pod Affinity&lt;/strong&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;example-pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;affinity:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;podAffinity:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;requiredDuringSchedulingIgnoredDuringExecution:&lt;/span&gt;        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;labelSelector:&lt;/span&gt;            &lt;span class=&quot;hljs-attr&quot;&gt;matchExpressions:&lt;/span&gt;              &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;key:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;app&lt;/span&gt;                &lt;span class=&quot;hljs-attr&quot;&gt;operator:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;In&lt;/span&gt;                &lt;span class=&quot;hljs-attr&quot;&gt;values:&lt;/span&gt;                  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;my-app&lt;/span&gt;          &lt;span class=&quot;hljs-attr&quot;&gt;topologyKey:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;kubernetes.io/hostname&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In this example, the pod will be scheduled on the same node as other pods with the label &lt;code&gt;app=my-app&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Pod Anti-Affinity&lt;/strong&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;example-pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;affinity:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;podAntiAffinity:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;requiredDuringSchedulingIgnoredDuringExecution:&lt;/span&gt;        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;labelSelector:&lt;/span&gt;            &lt;span class=&quot;hljs-attr&quot;&gt;matchExpressions:&lt;/span&gt;              &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;key:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;app&lt;/span&gt;                &lt;span class=&quot;hljs-attr&quot;&gt;operator:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;In&lt;/span&gt;                &lt;span class=&quot;hljs-attr&quot;&gt;values:&lt;/span&gt;                  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;my-app&lt;/span&gt;          &lt;span class=&quot;hljs-attr&quot;&gt;topologyKey:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;kubernetes.io/hostname&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In this example, the pod will be scheduled on different nodes from pods with the label &lt;code&gt;app=my-app&lt;/code&gt;.&lt;/p&gt;&lt;h3 id=&quot;heading-summary-of-differences&quot;&gt;Summary of Differences&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Node Affinity&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Focuses on the relationship between pods and nodes.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Uses node labels.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Controls which nodes a pod can be scheduled on.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pod Affinity/Anti-Affinity&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Focuses on the relationship between pods.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Uses pod labels.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Controls placement of pods relative to other pods.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Can specify inter-affinity (co-location) or anti-affinity (separation).&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Both Node Affinity and Pod Affinity/Anti-Affinity are powerful tools for managing pod placement and ensuring high availability, performance, and compliance with deployment policies in a Kubernetes cluster.&lt;/p&gt;&lt;h2 id=&quot;heading-use-cases-for-pod-anti-affinity&quot;&gt;Use Cases for Pod Anti-Affinity&lt;/h2&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;High Availability&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Ensure that replicas of a critical application are not placed on the same node to prevent a single point of failure.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Example: Deploying replicas of a web server across different nodes to ensure availability if one node goes down.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resource Contention&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Prevent pods from competing for the same resources by spreading them across different nodes.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Example: Avoiding multiple CPU-intensive workloads on the same node to ensure they do not affect each other&apos;s performance.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Failure Isolation&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Reduce the risk of correlated failures by ensuring that similar pods are not scheduled on the same node.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Example: Distributing pods of a stateful application across different nodes to prevent losing data in case of a node failure.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compliance and Security&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Enforce organizational policies that require certain types of workloads to be isolated from each other.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Example: Ensuring that test and production environments do not share the same nodes.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-example-scenario&quot;&gt;Example Scenario&lt;/h3&gt;&lt;p&gt;Imagine you have a web application with multiple replicas (pods) and a database. You want to ensure that:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;No two replicas of the web application are on the same node.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The database pod is not on the same node as any web application pod.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;You would use pod anti-affinity rules to achieve this separation, thereby enhancing the resilience and performance of your application.&lt;/p&gt;&lt;h2 id=&quot;heading-workshop-exercise-pod-anti-affinity-with-minikube&quot;&gt;Workshop Exercise: Pod Anti-Affinity with Minikube&lt;/h2&gt;&lt;p&gt;This exercise demonstrates how to set up and observe pod anti-affinity rules in a Kubernetes cluster using Minikube. By following these steps, you can see how Kubernetes schedules pods across different nodes to ensure high availability and fault tolerance.&lt;/p&gt;&lt;h4 id=&quot;heading-prerequisites&quot;&gt;Prerequisites:&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://minikube.sigs.k8s.io/docs/start/?arch=%2Flinux%2Fx86-64%2Fstable%2Fbinary+download&quot;&gt;Minikube&lt;/a&gt; installed on your local machine.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/&quot;&gt;kubectl&lt;/a&gt; installed and configured to interact with Minikube.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h4 id=&quot;heading-step-1-start-minikube&quot;&gt;Step 1: Start Minikube&lt;/h4&gt;&lt;p&gt;Start a Minikube cluster with multiple nodes to see the anti-affinity rules in action.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-sh&quot;&gt;minikube start --nodes 6&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Verify that the nodes are up and running:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-sh&quot;&gt;kubectl get nodes&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&quot;heading-step-2-create-a-namespace&quot;&gt;Step 2: Create a Namespace&lt;/h4&gt;&lt;p&gt;Create a new namespace for the exercise:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-sh&quot;&gt;kubectl create namespace anti-affinity-demo&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&quot;heading-step-3-define-a-deployment-with-anti-affinity&quot;&gt;Step 3: Define a Deployment with Anti-Affinity&lt;/h4&gt;&lt;p&gt;Create a deployment configuration file with pod anti-affinity rules. Save the following YAML content to a file named &lt;code&gt;deployment.yaml&lt;/code&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;apps/v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Deployment&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;my-app&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;namespace:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;anti-affinity-demo&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;replicas:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;selector:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;matchLabels:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;app:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;my-app&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;template:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;labels:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;app:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;my-app&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;affinity:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;podAntiAffinity:&lt;/span&gt;          &lt;span class=&quot;hljs-attr&quot;&gt;requiredDuringSchedulingIgnoredDuringExecution:&lt;/span&gt;            &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;labelSelector:&lt;/span&gt;                &lt;span class=&quot;hljs-attr&quot;&gt;matchExpressions:&lt;/span&gt;                  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;key:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;app&lt;/span&gt;                    &lt;span class=&quot;hljs-attr&quot;&gt;operator:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;In&lt;/span&gt;                    &lt;span class=&quot;hljs-attr&quot;&gt;values:&lt;/span&gt;                      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;my-app&lt;/span&gt;              &lt;span class=&quot;hljs-attr&quot;&gt;topologyKey:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;kubernetes.io/hostname&quot;&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;containers:&lt;/span&gt;      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;my-app-container&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;ports:&lt;/span&gt;        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;containerPort:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;80&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&quot;heading-step-4-apply-the-deployment&quot;&gt;Step 4: Apply the Deployment&lt;/h4&gt;&lt;p&gt;Apply the deployment to your Minikube cluster:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-sh&quot;&gt;kubectl apply -f deployment.yaml&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&quot;heading-step-5-verify-pod-distribution&quot;&gt;Step 5: Verify Pod Distribution&lt;/h4&gt;&lt;p&gt;Check the status of the pods and verify their node placement:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-sh&quot;&gt;kubectl get pods -o wide -n anti-affinity-demo&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You should see that the pods are distributed across different nodes, adhering to the anti-affinity rule specified.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1720101623439/799302f6-8433-4c7f-93e2-9b0b30d94d8b.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;h4 id=&quot;heading-step-6-inspect-node-and-pod-details&quot;&gt;Step 6: Inspect Node and Pod Details&lt;/h4&gt;&lt;p&gt;Inspect the pods to verify the labels and affinity rules:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-sh&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Describe a pod&lt;/span&gt;kubectl describe pod &amp;lt;pod-name&amp;gt; -n anti-affinity-demo&lt;span class=&quot;hljs-comment&quot;&gt;# Get the yaml output&lt;/span&gt;kubectl get pod &amp;lt;pod-name&amp;gt; -n anti-affinity-demo -o yaml&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Replace &lt;code&gt;&amp;lt;pod-name&amp;gt;&lt;/code&gt; with the name of one of your pods.&lt;/p&gt;&lt;h4 id=&quot;heading-step-7-observe-anti-affinity-in-action&quot;&gt;Step 7: Observe Anti-Affinity in Action&lt;/h4&gt;&lt;p&gt;To observe the anti-affinity rules in action, try scaling the deployment up or down and see how Kubernetes schedules the pods.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-sh&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Scale up the deployment&lt;/span&gt;kubectl scale deployment my-app --replicas=6 -n anti-affinity-demo&lt;span class=&quot;hljs-comment&quot;&gt;# Verify pod distribution again&lt;/span&gt;kubectl get pods -o wide -n anti-affinity-demo&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Scaling up should distribute the new pods across different nodes as much as possible, adhering to the anti-affinity rules.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1720101699256/82ffce6d-12ce-48c1-94ed-24bfe87b51a9.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;h3 id=&quot;heading-cleanup&quot;&gt;Cleanup&lt;/h3&gt;&lt;p&gt;After completing the exercise, clean up the resources:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-sh&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Delete the deployment&lt;/span&gt;kubectl delete deployment my-app -n anti-affinity-demo&lt;span class=&quot;hljs-comment&quot;&gt;# Delete the namespace&lt;/span&gt;kubectl delete namespace anti-affinity-demo&lt;span class=&quot;hljs-comment&quot;&gt;# Stop Minikube&lt;/span&gt;minikube stop&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;heading-references&quot;&gt;References&lt;/h2&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/&quot;&gt;Kubernetes Docs: Assigning Pods to Nodes&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/reference/labels-annotations-taints/#kubernetesiohostname&quot;&gt;Kubernetes Hostname Label&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://medium.com/@danielaaronw/k8s-pod-anti-affinity-dd2667a20c5f&quot;&gt;Medium blog: K8s Pod Anti-affinity&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;]]&gt;</content:encoded><hashnode:content>&lt;![CDATA[&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity&quot;&gt;&lt;strong&gt;Pod anti-affinity&lt;/strong&gt;&lt;/a&gt; is a Kubernetes feature that allows you to specify that certain pods should not be scheduled on the same nodes as other specified pods. This is useful for ensuring high availability and resilience by spreading out workloads across different nodes.&lt;/p&gt;&lt;div data-node-type=&quot;callout&quot;&gt;&lt;div data-node-type=&quot;callout-emoji&quot;&gt;💡&lt;/div&gt;&lt;div data-node-type=&quot;callout-text&quot;&gt;Pod anti-affinity is not only applied for nodes, but in case of using of cloud provider it can be applied for different &lt;em&gt;availability zones&lt;/em&gt; and &lt;em&gt;regions. &lt;/em&gt;This achieved by specifying the &lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/reference/labels-annotations-taints/&quot;&gt;&lt;code&gt;topologyKey&lt;/code&gt;&lt;/a&gt; value in the affinity specification.&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Let&apos;s imagine a scenario where you have multiple applications running on your cluster in a microservice architecture, and your cluster consists of several nodes hosting your application pods. While the scheduler ensures that all your pods are placed on healthy nodes with adequate resources, it doesn&apos;t consider which specific applications are running in each pod when deciding on placement. This could lead to a situation where all the pods from a particular deployment are placed on the same node. The major drawback of this situation is that it exposes that application to the risk of failure if that node goes down. The Pod Anti-Affinity helps us to spread the pods evenly across the nodes in the cluster.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1720034669524/6ec14458-1fd0-4bb0-87bd-9306527545b0.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;h2 id=&quot;heading-difference-between-node-affinity-and-pod-affinityanti-affinity&quot;&gt;Difference between Node Affinity and Pod Affinity/Anti-Affinity&lt;/h2&gt;&lt;p&gt;Node Affinity and Inter-Pod Affinity/Anti-Affinity are Kubernetes features that help control the placement of pods within a cluster. However, they serve different purposes and operate based on different criteria.&lt;/p&gt;&lt;h3 id=&quot;heading-node-affinity&quot;&gt;Node Affinity&lt;/h3&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity&quot;&gt;&lt;strong&gt;Node Affinity&lt;/strong&gt;&lt;/a&gt; is used to control which nodes a pod can be scheduled on based on node labels. It allows you to specify rules that must be satisfied for a pod to be scheduled onto a node.&lt;/p&gt;&lt;h4 id=&quot;heading-key-points&quot;&gt;Key Points:&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Based on Node Labels&lt;/strong&gt;: Node Affinity uses the labels assigned to nodes to determine where pods can be scheduled.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Types of Affinity&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;requiredDuringSchedulingIgnoredDuringExecution&lt;/strong&gt;: The scheduler can&apos;t schedule the Pod unless the rule is met. This is a hard requirement.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;preferredDuringSchedulingIgnoredDuringExecution&lt;/strong&gt;: The scheduler tries to find a node that meets the rule. If a matching node is not available, the scheduler still schedules the Pod.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div data-node-type=&quot;callout&quot;&gt;&lt;div data-node-type=&quot;callout-emoji&quot;&gt;💡&lt;/div&gt;&lt;div data-node-type=&quot;callout-text&quot;&gt;&lt;code&gt;IgnoredDuringExecution&lt;/code&gt;&lt;strong&gt; &lt;/strong&gt;means that if the node labels change after Kubernetes schedules the Pod, the Pod continues to run.&lt;/div&gt;&lt;/div&gt;&lt;h4 id=&quot;heading-example&quot;&gt;Example:&lt;/h4&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;with-node-affinity&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;affinity:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;nodeAffinity:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;requiredDuringSchedulingIgnoredDuringExecution:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;nodeSelectorTerms:&lt;/span&gt;        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;matchExpressions:&lt;/span&gt;          &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;key:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;topology.kubernetes.io/zone&lt;/span&gt;            &lt;span class=&quot;hljs-attr&quot;&gt;operator:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;In&lt;/span&gt;            &lt;span class=&quot;hljs-attr&quot;&gt;values:&lt;/span&gt;            &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;antarctica-east1&lt;/span&gt;            &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;antarctica-west1&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;preferredDuringSchedulingIgnoredDuringExecution:&lt;/span&gt;      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;weight:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;preference:&lt;/span&gt;          &lt;span class=&quot;hljs-attr&quot;&gt;matchExpressions:&lt;/span&gt;          &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;key:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;another-node-label-key&lt;/span&gt;            &lt;span class=&quot;hljs-attr&quot;&gt;operator:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;In&lt;/span&gt;            &lt;span class=&quot;hljs-attr&quot;&gt;values:&lt;/span&gt;            &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;another-node-label-value&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;containers:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;with-node-affinity&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;registry.k8s.io/pause:2.0&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-inter-pod-affinityanti-affinity&quot;&gt;Inter-Pod Affinity/Anti-Affinity&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Inter-Pod Affinity&lt;/strong&gt; and &lt;strong&gt;Pod Anti-Affinity&lt;/strong&gt; control the placement of pods relative to other pods based on their labels. These features allow you to specify rules for placing pods in relation to other pods.&lt;/p&gt;&lt;div data-node-type=&quot;callout&quot;&gt;&lt;div data-node-type=&quot;callout-emoji&quot;&gt;&lt;/div&gt;&lt;div data-node-type=&quot;callout-text&quot;&gt;Inter-pod affinity and anti-affinity require substantial amounts of processing which can slow down scheduling in large clusters significantly. It is not recommended using them in clusters larger than several hundred nodes.&lt;/div&gt;&lt;/div&gt;&lt;h4 id=&quot;heading-key-points-1&quot;&gt;Key Points:&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Based on Pod Labels&lt;/strong&gt;: Pod Affinity/Anti-Affinity uses labels assigned to pods to determine placement.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Types of Affinity&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Inter-Pod Affinity&lt;/strong&gt;: Ensures that pods are scheduled on the same node or close to other specified pods.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pod Anti-Affinity&lt;/strong&gt;: Ensures that pods are not scheduled on the same node or close to other specified pods.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Topology Key&lt;/strong&gt;: Specifies the &lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Failure_domain&quot;&gt;failure domain&lt;/a&gt; within which the affinity or anti-affinity rule applies (e.g., &lt;a target=&quot;_blank&quot; href=&quot;http://kubernetes.io/hostname&quot;&gt;&lt;code&gt;kubernetes.io/hostname&lt;/code&gt;&lt;/a&gt; for nodes, &lt;a target=&quot;_blank&quot; href=&quot;http://topology.kubernetes.io/zone&quot;&gt;&lt;code&gt;topology.kubernetes.io/zone&lt;/code&gt;&lt;/a&gt; for zones in the cloud).&lt;/p&gt;  &lt;div data-node-type=&quot;callout&quot;&gt;  &lt;div data-node-type=&quot;callout-emoji&quot;&gt;&lt;/div&gt;  &lt;div data-node-type=&quot;callout-text&quot;&gt;Pod anti-affinity requires nodes to be consistently labeled, in other words, every node in the cluster must have an appropriate label matching &lt;code&gt;topologyKey&lt;/code&gt;. If some or all nodes are missing the specified &lt;code&gt;topologyKey&lt;/code&gt; label, it can lead to unintended behavior.&lt;/div&gt;  &lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h4 id=&quot;heading-examples&quot;&gt;Examples:&lt;/h4&gt;&lt;p&gt;&lt;strong&gt;Inter-Pod Affinity&lt;/strong&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;example-pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;affinity:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;podAffinity:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;requiredDuringSchedulingIgnoredDuringExecution:&lt;/span&gt;        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;labelSelector:&lt;/span&gt;            &lt;span class=&quot;hljs-attr&quot;&gt;matchExpressions:&lt;/span&gt;              &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;key:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;app&lt;/span&gt;                &lt;span class=&quot;hljs-attr&quot;&gt;operator:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;In&lt;/span&gt;                &lt;span class=&quot;hljs-attr&quot;&gt;values:&lt;/span&gt;                  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;my-app&lt;/span&gt;          &lt;span class=&quot;hljs-attr&quot;&gt;topologyKey:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;kubernetes.io/hostname&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In this example, the pod will be scheduled on the same node as other pods with the label &lt;code&gt;app=my-app&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Pod Anti-Affinity&lt;/strong&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;example-pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;affinity:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;podAntiAffinity:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;requiredDuringSchedulingIgnoredDuringExecution:&lt;/span&gt;        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;labelSelector:&lt;/span&gt;            &lt;span class=&quot;hljs-attr&quot;&gt;matchExpressions:&lt;/span&gt;              &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;key:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;app&lt;/span&gt;                &lt;span class=&quot;hljs-attr&quot;&gt;operator:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;In&lt;/span&gt;                &lt;span class=&quot;hljs-attr&quot;&gt;values:&lt;/span&gt;                  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;my-app&lt;/span&gt;          &lt;span class=&quot;hljs-attr&quot;&gt;topologyKey:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;kubernetes.io/hostname&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In this example, the pod will be scheduled on different nodes from pods with the label &lt;code&gt;app=my-app&lt;/code&gt;.&lt;/p&gt;&lt;h3 id=&quot;heading-summary-of-differences&quot;&gt;Summary of Differences&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Node Affinity&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Focuses on the relationship between pods and nodes.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Uses node labels.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Controls which nodes a pod can be scheduled on.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pod Affinity/Anti-Affinity&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Focuses on the relationship between pods.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Uses pod labels.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Controls placement of pods relative to other pods.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Can specify inter-affinity (co-location) or anti-affinity (separation).&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Both Node Affinity and Pod Affinity/Anti-Affinity are powerful tools for managing pod placement and ensuring high availability, performance, and compliance with deployment policies in a Kubernetes cluster.&lt;/p&gt;&lt;h2 id=&quot;heading-use-cases-for-pod-anti-affinity&quot;&gt;Use Cases for Pod Anti-Affinity&lt;/h2&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;High Availability&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Ensure that replicas of a critical application are not placed on the same node to prevent a single point of failure.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Example: Deploying replicas of a web server across different nodes to ensure availability if one node goes down.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resource Contention&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Prevent pods from competing for the same resources by spreading them across different nodes.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Example: Avoiding multiple CPU-intensive workloads on the same node to ensure they do not affect each other&apos;s performance.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Failure Isolation&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Reduce the risk of correlated failures by ensuring that similar pods are not scheduled on the same node.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Example: Distributing pods of a stateful application across different nodes to prevent losing data in case of a node failure.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compliance and Security&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Enforce organizational policies that require certain types of workloads to be isolated from each other.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Example: Ensuring that test and production environments do not share the same nodes.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-example-scenario&quot;&gt;Example Scenario&lt;/h3&gt;&lt;p&gt;Imagine you have a web application with multiple replicas (pods) and a database. You want to ensure that:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;No two replicas of the web application are on the same node.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The database pod is not on the same node as any web application pod.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;You would use pod anti-affinity rules to achieve this separation, thereby enhancing the resilience and performance of your application.&lt;/p&gt;&lt;h2 id=&quot;heading-workshop-exercise-pod-anti-affinity-with-minikube&quot;&gt;Workshop Exercise: Pod Anti-Affinity with Minikube&lt;/h2&gt;&lt;p&gt;This exercise demonstrates how to set up and observe pod anti-affinity rules in a Kubernetes cluster using Minikube. By following these steps, you can see how Kubernetes schedules pods across different nodes to ensure high availability and fault tolerance.&lt;/p&gt;&lt;h4 id=&quot;heading-prerequisites&quot;&gt;Prerequisites:&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://minikube.sigs.k8s.io/docs/start/?arch=%2Flinux%2Fx86-64%2Fstable%2Fbinary+download&quot;&gt;Minikube&lt;/a&gt; installed on your local machine.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/&quot;&gt;kubectl&lt;/a&gt; installed and configured to interact with Minikube.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h4 id=&quot;heading-step-1-start-minikube&quot;&gt;Step 1: Start Minikube&lt;/h4&gt;&lt;p&gt;Start a Minikube cluster with multiple nodes to see the anti-affinity rules in action.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-sh&quot;&gt;minikube start --nodes 6&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Verify that the nodes are up and running:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-sh&quot;&gt;kubectl get nodes&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&quot;heading-step-2-create-a-namespace&quot;&gt;Step 2: Create a Namespace&lt;/h4&gt;&lt;p&gt;Create a new namespace for the exercise:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-sh&quot;&gt;kubectl create namespace anti-affinity-demo&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&quot;heading-step-3-define-a-deployment-with-anti-affinity&quot;&gt;Step 3: Define a Deployment with Anti-Affinity&lt;/h4&gt;&lt;p&gt;Create a deployment configuration file with pod anti-affinity rules. Save the following YAML content to a file named &lt;code&gt;deployment.yaml&lt;/code&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;apps/v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Deployment&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;my-app&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;namespace:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;anti-affinity-demo&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;replicas:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;3&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;selector:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;matchLabels:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;app:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;my-app&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;template:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;labels:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;app:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;my-app&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;affinity:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;podAntiAffinity:&lt;/span&gt;          &lt;span class=&quot;hljs-attr&quot;&gt;requiredDuringSchedulingIgnoredDuringExecution:&lt;/span&gt;            &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;labelSelector:&lt;/span&gt;                &lt;span class=&quot;hljs-attr&quot;&gt;matchExpressions:&lt;/span&gt;                  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;key:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;app&lt;/span&gt;                    &lt;span class=&quot;hljs-attr&quot;&gt;operator:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;In&lt;/span&gt;                    &lt;span class=&quot;hljs-attr&quot;&gt;values:&lt;/span&gt;                      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;my-app&lt;/span&gt;              &lt;span class=&quot;hljs-attr&quot;&gt;topologyKey:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;kubernetes.io/hostname&quot;&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;containers:&lt;/span&gt;      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;my-app-container&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;ports:&lt;/span&gt;        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;containerPort:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;80&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&quot;heading-step-4-apply-the-deployment&quot;&gt;Step 4: Apply the Deployment&lt;/h4&gt;&lt;p&gt;Apply the deployment to your Minikube cluster:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-sh&quot;&gt;kubectl apply -f deployment.yaml&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&quot;heading-step-5-verify-pod-distribution&quot;&gt;Step 5: Verify Pod Distribution&lt;/h4&gt;&lt;p&gt;Check the status of the pods and verify their node placement:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-sh&quot;&gt;kubectl get pods -o wide -n anti-affinity-demo&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You should see that the pods are distributed across different nodes, adhering to the anti-affinity rule specified.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1720101623439/799302f6-8433-4c7f-93e2-9b0b30d94d8b.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;h4 id=&quot;heading-step-6-inspect-node-and-pod-details&quot;&gt;Step 6: Inspect Node and Pod Details&lt;/h4&gt;&lt;p&gt;Inspect the pods to verify the labels and affinity rules:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-sh&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Describe a pod&lt;/span&gt;kubectl describe pod &amp;lt;pod-name&amp;gt; -n anti-affinity-demo&lt;span class=&quot;hljs-comment&quot;&gt;# Get the yaml output&lt;/span&gt;kubectl get pod &amp;lt;pod-name&amp;gt; -n anti-affinity-demo -o yaml&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Replace &lt;code&gt;&amp;lt;pod-name&amp;gt;&lt;/code&gt; with the name of one of your pods.&lt;/p&gt;&lt;h4 id=&quot;heading-step-7-observe-anti-affinity-in-action&quot;&gt;Step 7: Observe Anti-Affinity in Action&lt;/h4&gt;&lt;p&gt;To observe the anti-affinity rules in action, try scaling the deployment up or down and see how Kubernetes schedules the pods.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-sh&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Scale up the deployment&lt;/span&gt;kubectl scale deployment my-app --replicas=6 -n anti-affinity-demo&lt;span class=&quot;hljs-comment&quot;&gt;# Verify pod distribution again&lt;/span&gt;kubectl get pods -o wide -n anti-affinity-demo&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Scaling up should distribute the new pods across different nodes as much as possible, adhering to the anti-affinity rules.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1720101699256/82ffce6d-12ce-48c1-94ed-24bfe87b51a9.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;h3 id=&quot;heading-cleanup&quot;&gt;Cleanup&lt;/h3&gt;&lt;p&gt;After completing the exercise, clean up the resources:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-sh&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Delete the deployment&lt;/span&gt;kubectl delete deployment my-app -n anti-affinity-demo&lt;span class=&quot;hljs-comment&quot;&gt;# Delete the namespace&lt;/span&gt;kubectl delete namespace anti-affinity-demo&lt;span class=&quot;hljs-comment&quot;&gt;# Stop Minikube&lt;/span&gt;minikube stop&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;heading-references&quot;&gt;References&lt;/h2&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/&quot;&gt;Kubernetes Docs: Assigning Pods to Nodes&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/reference/labels-annotations-taints/#kubernetesiohostname&quot;&gt;Kubernetes Hostname Label&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://medium.com/@danielaaronw/k8s-pod-anti-affinity-dd2667a20c5f&quot;&gt;Medium blog: K8s Pod Anti-affinity&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;]]&gt;</hashnode:content><hashnode:coverImage>https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/Q-ioK6NPFos/upload/6ca4ddc80792a4bae4b343c25f27be59.jpeg</hashnode:coverImage></item><item><title><![CDATA[Understanding Ephemeral Storage in Kubernetes]]></title><description><![CDATA[Understanding Ephemeral Storage in Kubernetes]]></description><link>https://maxat-akbanov.com/understanding-ephemeral-storage-in-kubernetes</link><guid isPermaLink="true">https://maxat-akbanov.com/understanding-ephemeral-storage-in-kubernetes</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[Devops]]></category><category><![CDATA[sysops]]></category><category><![CDATA[storage]]></category><category><![CDATA[ephemeral]]></category><dc:creator><![CDATA[Maxat Akbanov]]></dc:creator><pubDate>Wed, 03 Jul 2024 09:18:39 GMT</pubDate><content:encoded>&lt;![CDATA[&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/storage/ephemeral-volumes/&quot;&gt;&lt;strong&gt;Ephemeral storage&lt;/strong&gt;&lt;/a&gt; in Kubernetes refers to the storage associated with a pod that exists only for the lifetime of that pod. It is typically used for temporary data that does not need to persist beyond the pod&apos;s lifecycle. Ephemeral storage is usually backed by the nodes local storage and is not designed for long-term data retention. It gets wiped clean once the pod is deleted or restarted.&lt;/p&gt;&lt;h2 id=&quot;heading-usage-of-ephemeral-storage&quot;&gt;Usage of Ephemeral Storage&lt;/h2&gt;&lt;p&gt;Ephemeral storage in Kubernetes can be used in various scenarios, such as:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scratch space&lt;/strong&gt; for applications:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Applications that require temporary space for intermediate data processing.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Caching&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Temporary storage for cached data that can be regenerated if lost.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Logs&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Storing log data that can be offloaded to persistent storage or log aggregation systems.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Temporary storage for build artifacts&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;During CI/CD processes, ephemeral storage can be used to store build artifacts that are needed only temporarily.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h2 id=&quot;heading-types-of-ephemeral-storage-in-kubernetes&quot;&gt;Types of Ephemeral Storage in Kubernetes&lt;/h2&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/storage/volumes/#emptydir&quot;&gt;&lt;strong&gt;EmptyDir&lt;/strong&gt;&lt;/a&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;A volume that is created when a pod is assigned to a node and exists as long as the pod is running. Empty at Pod startup, with storage coming locally from the kubelet base directory (usually the root disk &lt;code&gt;/var/lib/kubelet&lt;/code&gt;) or RAM&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/storage/volumes/#configmap&quot;&gt;&lt;strong&gt;ConfigMap&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;and&lt;/strong&gt; &lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/storage/volumes/#secret&quot;&gt;&lt;strong&gt;Secret&lt;/strong&gt;&lt;/a&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Used for storing configuration data and sensitive information that can be consumed by pods.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/storage/volumes/#downwardapi&quot;&gt;&lt;strong&gt;DownwardAPI&lt;/strong&gt;&lt;/a&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Allows pods to consume metadata about themselves or their environment.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/storage/ephemeral-volumes/#csi-ephemeral-volumes&quot;&gt;&lt;strong&gt;CSI ephemeral volumes:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Similar to the previous volume kinds, but provided by special CSI drivers which specifically &lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes-csi.github.io/docs/ephemeral-local-volumes.html&quot;&gt;support this feature.&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/storage/ephemeral-volumes/#generic-ephemeral-volumes&quot;&gt;&lt;strong&gt;Generic ephemeral volumes&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Can be provided by all storage drivers that also support persistent volumes&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;code&gt;emptyDir&lt;/code&gt;, &lt;code&gt;configMap&lt;/code&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/storage/ephemeral-volumes/#generic-ephemeral-volumes&quot;&gt;,&lt;/a&gt;&lt;code&gt;downwardAPI&lt;/code&gt;, &lt;code&gt;secret&lt;/code&gt; are provided as &lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#local-ephemeral-storage&quot;&gt;local ephemeral storage.&lt;/a&gt; They are managed by kubelet on each node.&lt;/p&gt;&lt;h2 id=&quot;heading-default-ephemeral-storage-type&quot;&gt;Default Ephemeral Storage Type&lt;/h2&gt;&lt;p&gt;When a Pod is started in Kubernetes, the default type of ephemeral storage used is the nodes local storage associated with the pod&apos;s lifecycle. Specifically, the primary forms of ephemeral storage that are used by default without any explicit configuration are:&lt;/p&gt;&lt;h3 id=&quot;heading-container-writable-layer&quot;&gt;Container Writable Layer&lt;/h3&gt;&lt;p&gt;Each container in a pod has a writable layer provided by the container runtime (e.g., Docker, containerd). This writable layer is ephemeral and used by default for any file operations within the container that are not mapped to other volumes.&lt;/p&gt;&lt;h3 id=&quot;heading-automatic-ephemeral-storage-features&quot;&gt;Automatic Ephemeral Storage Features&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Container Writable Layer&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Each container has its own writable layer where it can write files. This writable layer is ephemeral and lasts only for the duration of the container. Once the container is terminated or restarted, the data in this writable layer is lost.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;EmptyDir (if specified)&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;If an &lt;code&gt;emptyDir&lt;/code&gt; volume is explicitly specified in the pod&apos;s configuration, it provides a dedicated ephemeral storage that is shared among all containers in the pod. This storage is tied to the pod&apos;s lifecycle and is created when the pod is scheduled and deleted when the pod is terminated.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;    &lt;div data-node-type=&quot;callout&quot;&gt;    &lt;div data-node-type=&quot;callout-emoji&quot;&gt;💡&lt;/div&gt;    &lt;div data-node-type=&quot;callout-text&quot;&gt;To get the list of all pods or deployments that are using emptyDir, use the following command: &lt;a target=&quot;_blank&quot; href=&quot;https://gist.github.com/Brain2life/173dbad51c112a2ff1b3f3add9312fb1&quot;&gt;https://gist.github.com/Brain2life/173dbad51c112a2ff1b3f3add9312fb1&lt;/a&gt;&lt;/div&gt;    &lt;/div&gt;&lt;p&gt;    Here&apos;s an example of pod definition with &lt;code&gt;emptyDir&lt;/code&gt; volume specified:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;example-pod&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;containers:&lt;/span&gt;      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;example-container&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;busybox&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;command:&lt;/span&gt; [&lt;span class=&quot;hljs-string&quot;&gt;&quot;sh&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;-c&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;echo Hello Kubernetes! &amp;gt; /data/hello.txt &amp;amp;&amp;amp; sleep 3600&quot;&lt;/span&gt;]        &lt;span class=&quot;hljs-attr&quot;&gt;volumeMounts:&lt;/span&gt;        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;mountPath:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/data&lt;/span&gt;          &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;temp-storage&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;volumes:&lt;/span&gt;      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;temp-storage&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;emptyDir:&lt;/span&gt; {}&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-example&quot;&gt;Example&lt;/h3&gt;&lt;p&gt;If you start a pod without specifying any volumes, the writable layer of each container acts as the ephemeral storage by default. Here is an example of a simple pod configuration without any explicit ephemeral storage:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;example-pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;containers:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;example-container&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;busybox&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;command:&lt;/span&gt; [&lt;span class=&quot;hljs-string&quot;&gt;&quot;sh&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;-c&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;echo Hello Kubernetes! &amp;gt; /tmp/hello.txt &amp;amp;&amp;amp; sleep 3600&quot;&lt;/span&gt;]&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In this example:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;The container uses its writable layer to write the file &lt;code&gt;/tmp/hello.txt&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;This storage is ephemeral and will be lost if the container is terminated or restarted.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;To see the writable layer of a container in Kubernetes, you typically need to access the container&apos;s filesystem. The writable layer is where all changes made to the filesystem of the container (such as creating or modifying files) are stored. Here&apos;s how you can inspect the writable layer:&lt;/p&gt;&lt;p&gt;Exec into the container:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;kubectl &lt;span class=&quot;hljs-built_in&quot;&gt;exec&lt;/span&gt; -it example-pod -c example-container -- /bin/sh&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Inspect filesystem. You should see &lt;code&gt;hello.txt&lt;/code&gt; file:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;cd&lt;/span&gt; /tmpls -l&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;By default, when a pod is started in Kubernetes, the containers writable layer is used as the ephemeral storage. If you need shared ephemeral storage among containers in the same pod, you can explicitly define an &lt;code&gt;emptyDir&lt;/code&gt; volume. The writable layer is tied to the container lifecycle, while &lt;code&gt;emptyDir&lt;/code&gt; (if used) is tied to the pod lifecycle.&lt;/p&gt;&lt;h2 id=&quot;heading-best-practices&quot;&gt;Best Practices&lt;/h2&gt;&lt;h3 id=&quot;heading-resource-requests-and-limits&quot;&gt;&lt;strong&gt;Resource Requests and Limits&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#setting-requests-and-limits-for-local-ephemeral-storage&quot;&gt;Set requests and limits for ephemeral storage&lt;/a&gt; to ensure that no single pod can consume all the node&apos;s storage. This helps in managing resource allocation and preventing resource exhaustion.&lt;/p&gt;&lt;p&gt;In the following example, the Pod has two containers. Each container has a request of 2GiB of local ephemeral storage. Each container has a limit of 4GiB of local ephemeral storage. Therefore, the Pod has a request of 4GiB of local ephemeral storage, and a limit of 8GiB of local ephemeral storage. 500Mi of that limit could be consumed by the &lt;code&gt;emptyDir&lt;/code&gt; volume.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;frontend&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;containers:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;app&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;images.my-company.example/app:v4&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;resources:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;requests:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;ephemeral-storage:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;2Gi&quot;&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;limits:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;ephemeral-storage:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;4Gi&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;volumeMounts:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;ephemeral&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;mountPath:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;/tmp&quot;&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;log-aggregator&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;images.my-company.example/log-aggregator:v6&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;resources:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;requests:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;ephemeral-storage:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;2Gi&quot;&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;limits:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;ephemeral-storage:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;4Gi&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;volumeMounts:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;ephemeral&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;mountPath:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;/tmp&quot;&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;volumes:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;ephemeral&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;emptyDir:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;sizeLimit:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;500Mi&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;sizeLimit&lt;/code&gt; field under &lt;code&gt;emptyDir&lt;/code&gt; specifies the maximum size for the entire emptyDir volume. An &lt;code&gt;emptyDir&lt;/code&gt; volume is a temporary directory that initially starts empty and is deleted when the Pod is removed.&lt;/p&gt;&lt;p&gt;In given example, the &lt;code&gt;sizeLimit&lt;/code&gt; of 500Mi restricts the total size of the &lt;code&gt;ephemeral&lt;/code&gt; volume that is mounted to &lt;code&gt;/tmp&lt;/code&gt; in both containers.&lt;/p&gt;&lt;p&gt;Each container (&lt;code&gt;app&lt;/code&gt; and &lt;code&gt;log-aggregator&lt;/code&gt;) is allowed to request 2Gi and use up to 4Gi of ephemeral storage individually.&lt;/p&gt;&lt;p&gt;However, the shared &lt;code&gt;ephemeral&lt;/code&gt; volume (&lt;code&gt;emptyDir&lt;/code&gt;) has a &lt;code&gt;sizeLimit&lt;/code&gt; of 500Mi, meaning the combined storage usage of both containers in &lt;code&gt;/tmp&lt;/code&gt; cannot exceed 500Mi.&lt;/p&gt;&lt;h3 id=&quot;heading-log-management&quot;&gt;Log Management&lt;/h3&gt;&lt;p&gt;Use log aggregation solutions (e.g., &lt;a target=&quot;_blank&quot; href=&quot;https://www.elastic.co/elastic-stack&quot;&gt;ELK Stack&lt;/a&gt;, &lt;a target=&quot;_blank&quot; href=&quot;https://www.fluentd.org/&quot;&gt;Fluentd&lt;/a&gt;) to collect and store logs from pods to avoid losing critical log data when pods are deleted.&lt;/p&gt;&lt;h3 id=&quot;heading-monitoring-and-alerts&quot;&gt;&lt;strong&gt;Monitoring and Alerts&lt;/strong&gt;:&lt;/h3&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#resource-emphemeralstorage-consumption&quot;&gt;Implement monitoring for ephemeral storage usage&lt;/a&gt;. Tools like &lt;a target=&quot;_blank&quot; href=&quot;https://prometheus.io/&quot;&gt;Prometheus&lt;/a&gt; and &lt;a target=&quot;_blank&quot; href=&quot;https://grafana.com/&quot;&gt;Grafana&lt;/a&gt; can be used to set up alerts for storage thresholds.&lt;/p&gt;&lt;p&gt;If the kubelet is managing local ephemeral storage as a resource, then the kubelet measures storage use in:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;emptyDir&lt;/code&gt; volumes, except &lt;em&gt;tmpfs&lt;/em&gt; &lt;code&gt;emptyDir&lt;/code&gt; volumes&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;directories holding node-level logs&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;writeable container layers&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;If a Pod is using more ephemeral storage than you allow it to, the kubelet sets an eviction signal that triggers Pod eviction.&lt;/p&gt;&lt;p&gt;For container-level isolation, if a container&apos;s writable layer and log usage exceeds its storage limit, the kubelet marks the Pod for eviction.&lt;/p&gt;&lt;p&gt;For pod-level isolation the kubelet works out an overall Pod storage limit by summing the limits for the containers in that Pod. In this case, if the sum of the local ephemeral storage usage from all containers and also the Pod&apos;s &lt;code&gt;emptyDir&lt;/code&gt; volumes exceeds the overall Pod storage limit, then the kubelet also marks the Pod for eviction.&lt;/p&gt;&lt;p&gt;By default ephemeral container data is located at:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;/var/lib/kubelet&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;/var/lib/containers&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;on the Kubernetes Node.&lt;/p&gt;&lt;p&gt;To show the ephemeral storage usage on the node use:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;df -h /var/lib&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To show the ephemeral storage usage inside the container:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;du -h .du -h [directory]&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-data-backup&quot;&gt;&lt;strong&gt;Data Backup&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;For critical temporary data, implement mechanisms to periodically back up data to persistent storage solutions.&lt;/p&gt;&lt;h3 id=&quot;heading-clean-up&quot;&gt;&lt;strong&gt;Clean Up&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;Ensure that ephemeral storage is properly cleaned up when pods are terminated to avoid orphaned data and wasted storage space. Even terminated and failed pods take up the space. Therefore, it is important to clean up the cluster from hanging pods.&lt;/p&gt;&lt;p&gt;You can use the following Bash script in your CI/CD pipelines or clean your cluster manually by starting the script from your local machine: &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/Brain2life/bash-cookbook/tree/k8s-cleanup-pods&quot;&gt;https://github.com/Brain2life/bash-cookbook/tree/k8s-cleanup-pods&lt;/a&gt;&lt;/p&gt;&lt;h2 id=&quot;heading-type-of-issues-with-ephemeral-storage&quot;&gt;Type of Issues with Ephemeral Storage&lt;/h2&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data Loss&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Since ephemeral storage is tied to the pod lifecycle, any data stored there will be lost if the pod is deleted or crashes.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resource Contention&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Without proper resource limits, pods might consume more storage than expected, leading to node resource contention and potential disruptions.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Node Disk Pressure&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;High usage of ephemeral storage can cause disk pressure on nodes, triggering eviction of pods or other resource management actions by the kubelet.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Limited Capacity&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Nodes have finite storage capacity, and excessive usage of ephemeral storage can exhaust available space, affecting the overall cluster performance.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;No Persistence&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Ephemeral storage is not suitable for storing data that needs to be preserved across pod restarts or crashes. Applications requiring persistent storage should use &lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/storage/persistent-volumes/&quot;&gt;Persistent Volumes (PVs)&lt;/a&gt; and Persistent Volume Claims (PVCs).&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Understanding and effectively managing ephemeral storage in Kubernetes is crucial for ensuring the stability and performance of applications running in the cluster.&lt;/p&gt;]]&gt;</content:encoded><hashnode:content>&lt;![CDATA[&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/storage/ephemeral-volumes/&quot;&gt;&lt;strong&gt;Ephemeral storage&lt;/strong&gt;&lt;/a&gt; in Kubernetes refers to the storage associated with a pod that exists only for the lifetime of that pod. It is typically used for temporary data that does not need to persist beyond the pod&apos;s lifecycle. Ephemeral storage is usually backed by the nodes local storage and is not designed for long-term data retention. It gets wiped clean once the pod is deleted or restarted.&lt;/p&gt;&lt;h2 id=&quot;heading-usage-of-ephemeral-storage&quot;&gt;Usage of Ephemeral Storage&lt;/h2&gt;&lt;p&gt;Ephemeral storage in Kubernetes can be used in various scenarios, such as:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scratch space&lt;/strong&gt; for applications:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Applications that require temporary space for intermediate data processing.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Caching&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Temporary storage for cached data that can be regenerated if lost.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Logs&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Storing log data that can be offloaded to persistent storage or log aggregation systems.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Temporary storage for build artifacts&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;During CI/CD processes, ephemeral storage can be used to store build artifacts that are needed only temporarily.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h2 id=&quot;heading-types-of-ephemeral-storage-in-kubernetes&quot;&gt;Types of Ephemeral Storage in Kubernetes&lt;/h2&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/storage/volumes/#emptydir&quot;&gt;&lt;strong&gt;EmptyDir&lt;/strong&gt;&lt;/a&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;A volume that is created when a pod is assigned to a node and exists as long as the pod is running. Empty at Pod startup, with storage coming locally from the kubelet base directory (usually the root disk &lt;code&gt;/var/lib/kubelet&lt;/code&gt;) or RAM&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/storage/volumes/#configmap&quot;&gt;&lt;strong&gt;ConfigMap&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;and&lt;/strong&gt; &lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/storage/volumes/#secret&quot;&gt;&lt;strong&gt;Secret&lt;/strong&gt;&lt;/a&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Used for storing configuration data and sensitive information that can be consumed by pods.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/storage/volumes/#downwardapi&quot;&gt;&lt;strong&gt;DownwardAPI&lt;/strong&gt;&lt;/a&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Allows pods to consume metadata about themselves or their environment.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/storage/ephemeral-volumes/#csi-ephemeral-volumes&quot;&gt;&lt;strong&gt;CSI ephemeral volumes:&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Similar to the previous volume kinds, but provided by special CSI drivers which specifically &lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes-csi.github.io/docs/ephemeral-local-volumes.html&quot;&gt;support this feature.&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/storage/ephemeral-volumes/#generic-ephemeral-volumes&quot;&gt;&lt;strong&gt;Generic ephemeral volumes&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Can be provided by all storage drivers that also support persistent volumes&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;code&gt;emptyDir&lt;/code&gt;, &lt;code&gt;configMap&lt;/code&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/storage/ephemeral-volumes/#generic-ephemeral-volumes&quot;&gt;,&lt;/a&gt;&lt;code&gt;downwardAPI&lt;/code&gt;, &lt;code&gt;secret&lt;/code&gt; are provided as &lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#local-ephemeral-storage&quot;&gt;local ephemeral storage.&lt;/a&gt; They are managed by kubelet on each node.&lt;/p&gt;&lt;h2 id=&quot;heading-default-ephemeral-storage-type&quot;&gt;Default Ephemeral Storage Type&lt;/h2&gt;&lt;p&gt;When a Pod is started in Kubernetes, the default type of ephemeral storage used is the nodes local storage associated with the pod&apos;s lifecycle. Specifically, the primary forms of ephemeral storage that are used by default without any explicit configuration are:&lt;/p&gt;&lt;h3 id=&quot;heading-container-writable-layer&quot;&gt;Container Writable Layer&lt;/h3&gt;&lt;p&gt;Each container in a pod has a writable layer provided by the container runtime (e.g., Docker, containerd). This writable layer is ephemeral and used by default for any file operations within the container that are not mapped to other volumes.&lt;/p&gt;&lt;h3 id=&quot;heading-automatic-ephemeral-storage-features&quot;&gt;Automatic Ephemeral Storage Features&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Container Writable Layer&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Each container has its own writable layer where it can write files. This writable layer is ephemeral and lasts only for the duration of the container. Once the container is terminated or restarted, the data in this writable layer is lost.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;EmptyDir (if specified)&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;If an &lt;code&gt;emptyDir&lt;/code&gt; volume is explicitly specified in the pod&apos;s configuration, it provides a dedicated ephemeral storage that is shared among all containers in the pod. This storage is tied to the pod&apos;s lifecycle and is created when the pod is scheduled and deleted when the pod is terminated.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;    &lt;div data-node-type=&quot;callout&quot;&gt;    &lt;div data-node-type=&quot;callout-emoji&quot;&gt;💡&lt;/div&gt;    &lt;div data-node-type=&quot;callout-text&quot;&gt;To get the list of all pods or deployments that are using emptyDir, use the following command: &lt;a target=&quot;_blank&quot; href=&quot;https://gist.github.com/Brain2life/173dbad51c112a2ff1b3f3add9312fb1&quot;&gt;https://gist.github.com/Brain2life/173dbad51c112a2ff1b3f3add9312fb1&lt;/a&gt;&lt;/div&gt;    &lt;/div&gt;&lt;p&gt;    Here&apos;s an example of pod definition with &lt;code&gt;emptyDir&lt;/code&gt; volume specified:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;example-pod&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;containers:&lt;/span&gt;      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;example-container&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;busybox&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;command:&lt;/span&gt; [&lt;span class=&quot;hljs-string&quot;&gt;&quot;sh&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;-c&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;echo Hello Kubernetes! &amp;gt; /data/hello.txt &amp;amp;&amp;amp; sleep 3600&quot;&lt;/span&gt;]        &lt;span class=&quot;hljs-attr&quot;&gt;volumeMounts:&lt;/span&gt;        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;mountPath:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/data&lt;/span&gt;          &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;temp-storage&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;volumes:&lt;/span&gt;      &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;temp-storage&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;emptyDir:&lt;/span&gt; {}&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-example&quot;&gt;Example&lt;/h3&gt;&lt;p&gt;If you start a pod without specifying any volumes, the writable layer of each container acts as the ephemeral storage by default. Here is an example of a simple pod configuration without any explicit ephemeral storage:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;example-pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;containers:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;example-container&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;busybox&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;command:&lt;/span&gt; [&lt;span class=&quot;hljs-string&quot;&gt;&quot;sh&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;-c&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;echo Hello Kubernetes! &amp;gt; /tmp/hello.txt &amp;amp;&amp;amp; sleep 3600&quot;&lt;/span&gt;]&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In this example:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;The container uses its writable layer to write the file &lt;code&gt;/tmp/hello.txt&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;This storage is ephemeral and will be lost if the container is terminated or restarted.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;To see the writable layer of a container in Kubernetes, you typically need to access the container&apos;s filesystem. The writable layer is where all changes made to the filesystem of the container (such as creating or modifying files) are stored. Here&apos;s how you can inspect the writable layer:&lt;/p&gt;&lt;p&gt;Exec into the container:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;kubectl &lt;span class=&quot;hljs-built_in&quot;&gt;exec&lt;/span&gt; -it example-pod -c example-container -- /bin/sh&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Inspect filesystem. You should see &lt;code&gt;hello.txt&lt;/code&gt; file:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;cd&lt;/span&gt; /tmpls -l&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;By default, when a pod is started in Kubernetes, the containers writable layer is used as the ephemeral storage. If you need shared ephemeral storage among containers in the same pod, you can explicitly define an &lt;code&gt;emptyDir&lt;/code&gt; volume. The writable layer is tied to the container lifecycle, while &lt;code&gt;emptyDir&lt;/code&gt; (if used) is tied to the pod lifecycle.&lt;/p&gt;&lt;h2 id=&quot;heading-best-practices&quot;&gt;Best Practices&lt;/h2&gt;&lt;h3 id=&quot;heading-resource-requests-and-limits&quot;&gt;&lt;strong&gt;Resource Requests and Limits&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#setting-requests-and-limits-for-local-ephemeral-storage&quot;&gt;Set requests and limits for ephemeral storage&lt;/a&gt; to ensure that no single pod can consume all the node&apos;s storage. This helps in managing resource allocation and preventing resource exhaustion.&lt;/p&gt;&lt;p&gt;In the following example, the Pod has two containers. Each container has a request of 2GiB of local ephemeral storage. Each container has a limit of 4GiB of local ephemeral storage. Therefore, the Pod has a request of 4GiB of local ephemeral storage, and a limit of 8GiB of local ephemeral storage. 500Mi of that limit could be consumed by the &lt;code&gt;emptyDir&lt;/code&gt; volume.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;frontend&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;containers:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;app&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;images.my-company.example/app:v4&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;resources:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;requests:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;ephemeral-storage:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;2Gi&quot;&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;limits:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;ephemeral-storage:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;4Gi&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;volumeMounts:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;ephemeral&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;mountPath:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;/tmp&quot;&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;log-aggregator&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;images.my-company.example/log-aggregator:v6&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;resources:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;requests:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;ephemeral-storage:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;2Gi&quot;&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;limits:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;ephemeral-storage:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;4Gi&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;volumeMounts:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;ephemeral&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;mountPath:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;/tmp&quot;&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;volumes:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;ephemeral&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;emptyDir:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;sizeLimit:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;500Mi&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;sizeLimit&lt;/code&gt; field under &lt;code&gt;emptyDir&lt;/code&gt; specifies the maximum size for the entire emptyDir volume. An &lt;code&gt;emptyDir&lt;/code&gt; volume is a temporary directory that initially starts empty and is deleted when the Pod is removed.&lt;/p&gt;&lt;p&gt;In given example, the &lt;code&gt;sizeLimit&lt;/code&gt; of 500Mi restricts the total size of the &lt;code&gt;ephemeral&lt;/code&gt; volume that is mounted to &lt;code&gt;/tmp&lt;/code&gt; in both containers.&lt;/p&gt;&lt;p&gt;Each container (&lt;code&gt;app&lt;/code&gt; and &lt;code&gt;log-aggregator&lt;/code&gt;) is allowed to request 2Gi and use up to 4Gi of ephemeral storage individually.&lt;/p&gt;&lt;p&gt;However, the shared &lt;code&gt;ephemeral&lt;/code&gt; volume (&lt;code&gt;emptyDir&lt;/code&gt;) has a &lt;code&gt;sizeLimit&lt;/code&gt; of 500Mi, meaning the combined storage usage of both containers in &lt;code&gt;/tmp&lt;/code&gt; cannot exceed 500Mi.&lt;/p&gt;&lt;h3 id=&quot;heading-log-management&quot;&gt;Log Management&lt;/h3&gt;&lt;p&gt;Use log aggregation solutions (e.g., &lt;a target=&quot;_blank&quot; href=&quot;https://www.elastic.co/elastic-stack&quot;&gt;ELK Stack&lt;/a&gt;, &lt;a target=&quot;_blank&quot; href=&quot;https://www.fluentd.org/&quot;&gt;Fluentd&lt;/a&gt;) to collect and store logs from pods to avoid losing critical log data when pods are deleted.&lt;/p&gt;&lt;h3 id=&quot;heading-monitoring-and-alerts&quot;&gt;&lt;strong&gt;Monitoring and Alerts&lt;/strong&gt;:&lt;/h3&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#resource-emphemeralstorage-consumption&quot;&gt;Implement monitoring for ephemeral storage usage&lt;/a&gt;. Tools like &lt;a target=&quot;_blank&quot; href=&quot;https://prometheus.io/&quot;&gt;Prometheus&lt;/a&gt; and &lt;a target=&quot;_blank&quot; href=&quot;https://grafana.com/&quot;&gt;Grafana&lt;/a&gt; can be used to set up alerts for storage thresholds.&lt;/p&gt;&lt;p&gt;If the kubelet is managing local ephemeral storage as a resource, then the kubelet measures storage use in:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;emptyDir&lt;/code&gt; volumes, except &lt;em&gt;tmpfs&lt;/em&gt; &lt;code&gt;emptyDir&lt;/code&gt; volumes&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;directories holding node-level logs&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;writeable container layers&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;If a Pod is using more ephemeral storage than you allow it to, the kubelet sets an eviction signal that triggers Pod eviction.&lt;/p&gt;&lt;p&gt;For container-level isolation, if a container&apos;s writable layer and log usage exceeds its storage limit, the kubelet marks the Pod for eviction.&lt;/p&gt;&lt;p&gt;For pod-level isolation the kubelet works out an overall Pod storage limit by summing the limits for the containers in that Pod. In this case, if the sum of the local ephemeral storage usage from all containers and also the Pod&apos;s &lt;code&gt;emptyDir&lt;/code&gt; volumes exceeds the overall Pod storage limit, then the kubelet also marks the Pod for eviction.&lt;/p&gt;&lt;p&gt;By default ephemeral container data is located at:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;/var/lib/kubelet&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;/var/lib/containers&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;on the Kubernetes Node.&lt;/p&gt;&lt;p&gt;To show the ephemeral storage usage on the node use:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;df -h /var/lib&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To show the ephemeral storage usage inside the container:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;du -h .du -h [directory]&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-data-backup&quot;&gt;&lt;strong&gt;Data Backup&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;For critical temporary data, implement mechanisms to periodically back up data to persistent storage solutions.&lt;/p&gt;&lt;h3 id=&quot;heading-clean-up&quot;&gt;&lt;strong&gt;Clean Up&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;Ensure that ephemeral storage is properly cleaned up when pods are terminated to avoid orphaned data and wasted storage space. Even terminated and failed pods take up the space. Therefore, it is important to clean up the cluster from hanging pods.&lt;/p&gt;&lt;p&gt;You can use the following Bash script in your CI/CD pipelines or clean your cluster manually by starting the script from your local machine: &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/Brain2life/bash-cookbook/tree/k8s-cleanup-pods&quot;&gt;https://github.com/Brain2life/bash-cookbook/tree/k8s-cleanup-pods&lt;/a&gt;&lt;/p&gt;&lt;h2 id=&quot;heading-type-of-issues-with-ephemeral-storage&quot;&gt;Type of Issues with Ephemeral Storage&lt;/h2&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data Loss&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Since ephemeral storage is tied to the pod lifecycle, any data stored there will be lost if the pod is deleted or crashes.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resource Contention&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Without proper resource limits, pods might consume more storage than expected, leading to node resource contention and potential disruptions.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Node Disk Pressure&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;High usage of ephemeral storage can cause disk pressure on nodes, triggering eviction of pods or other resource management actions by the kubelet.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Limited Capacity&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Nodes have finite storage capacity, and excessive usage of ephemeral storage can exhaust available space, affecting the overall cluster performance.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;No Persistence&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Ephemeral storage is not suitable for storing data that needs to be preserved across pod restarts or crashes. Applications requiring persistent storage should use &lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/storage/persistent-volumes/&quot;&gt;Persistent Volumes (PVs)&lt;/a&gt; and Persistent Volume Claims (PVCs).&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Understanding and effectively managing ephemeral storage in Kubernetes is crucial for ensuring the stability and performance of applications running in the cluster.&lt;/p&gt;]]&gt;</hashnode:content><hashnode:coverImage>https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/jXd2FSvcRr8/upload/18be438fc595b73d839ce431313d410a.jpeg</hashnode:coverImage></item><item><title><![CDATA[Get started with Gitleaks tool]]></title><description><![CDATA[Get started with Gitleaks tool]]></description><link>https://maxat-akbanov.com/get-started-with-gitleaks-tool</link><guid isPermaLink="true">https://maxat-akbanov.com/get-started-with-gitleaks-tool</guid><category><![CDATA[Devops]]></category><category><![CDATA[Security]]></category><category><![CDATA[sysops]]></category><category><![CDATA[Git]]></category><category><![CDATA[SAST]]></category><dc:creator><![CDATA[Maxat Akbanov]]></dc:creator><pubDate>Thu, 06 Jun 2024 13:49:34 GMT</pubDate><content:encoded>&lt;![CDATA[&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://github.com/gitleaks/gitleaks&quot;&gt;Gitleaks&lt;/a&gt; is an open-source &lt;a target=&quot;_blank&quot; href=&quot;https://owasp.org/www-community/Source_Code_Analysis_Tools&quot;&gt;SAST tool&lt;/a&gt; designed to detect and prevent secrets (such as API keys, passwords, and other sensitive information) from being committed to version control repositories. It scans the entire repository history, including directories and files, to identify potential secrets. By configuring it properly and integrating it into your development workflow, you can significantly reduce the risk of exposing sensitive information.&lt;/p&gt;&lt;h2 id=&quot;heading-key-features&quot;&gt;Key Features&lt;/h2&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Detection&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Patterns and Rules&lt;/strong&gt;: Gitleaks uses &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/gitleaks/gitleaks/blob/master/config/gitleaks.toml&quot;&gt;predefined patterns and rules&lt;/a&gt; to identify secrets. These patterns can include regular expressions for common types of secrets like AWS keys, Slack tokens, and more:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-ini&quot;&gt;  &lt;span class=&quot;hljs-section&quot;&gt;[[rules]]&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;id&lt;/span&gt; = &lt;span class=&quot;hljs-string&quot;&gt;&quot;aws-access-token&quot;&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;description&lt;/span&gt; = &lt;span class=&quot;hljs-string&quot;&gt;&quot;Identified a pattern that may indicate AWS credentials, risking unauthorized cloud resource access and data breaches on AWS platforms.&quot;&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;regex&lt;/span&gt; = &lt;span class=&quot;hljs-string&quot;&gt;&apos;&apos;&apos;(?:A3T[A-Z0-9]|AKIA|ASIA|ABIA|ACCA)[A-Z0-9]{16}&apos;&apos;&apos;&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;keywords&lt;/span&gt; = [      &lt;span class=&quot;hljs-string&quot;&gt;&quot;akia&quot;&lt;/span&gt;,&lt;span class=&quot;hljs-string&quot;&gt;&quot;asia&quot;&lt;/span&gt;,&lt;span class=&quot;hljs-string&quot;&gt;&quot;abia&quot;&lt;/span&gt;,&lt;span class=&quot;hljs-string&quot;&gt;&quot;acca&quot;&lt;/span&gt;,  ]&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Custom Rules&lt;/strong&gt;: Users can &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/gitleaks/gitleaks?tab=readme-ov-file#configuration&quot;&gt;define custom rules&lt;/a&gt; to detect specific types of secrets relevant to their projects.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scanning&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Repository Scanning&lt;/strong&gt;: Gitleaks can &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/gitleaks/gitleaks?tab=readme-ov-file#detect&quot;&gt;scan entire Git repositories&lt;/a&gt;, including commit history, directories and files.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pre-commit Hook&lt;/strong&gt;: It can be integrated as a &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/gitleaks/gitleaks?tab=readme-ov-file#pre-commit&quot;&gt;pre-commit hook&lt;/a&gt; to scan changes before they are committed, preventing secrets from entering the repository.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Configuration&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Config Files&lt;/strong&gt;: Users can configure Gitleaks using a configuration file (&lt;a target=&quot;_blank&quot; href=&quot;https://github.com/gitleaks/gitleaks/blob/master/config/gitleaks.toml&quot;&gt;&lt;code&gt;gitleaks.toml&lt;/code&gt;&lt;/a&gt;) to customize the rules and behavior of the tool.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ignore Files&lt;/strong&gt;: Gitleaks can be configured to ignore specific files or directories using an ignore file (&lt;a target=&quot;_blank&quot; href=&quot;https://github.com/gitleaks/gitleaks?tab=readme-ov-file#gitleaksignore&quot;&gt;&lt;code&gt;.gitleaksignore&lt;/code&gt;&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reports&lt;/strong&gt;: Gitleaks generates detailed reports of identified secrets, including the location in the repository and the specific rule that triggered the detection.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;  ~/code(master) gitleaks detect --&lt;span class=&quot;hljs-built_in&quot;&gt;source&lt;/span&gt; . -v  Finding:     &lt;span class=&quot;hljs-string&quot;&gt;&quot;export BUNDLE_ENTERPRISE__CONTRIBSYS__COM=cafebabe:deadbeef&quot;&lt;/span&gt;,  Secret:      cafebabe:deadbeef  RuleID:      sidekiq-secret  Entropy:     2.609850  File:        cmd/generate/config/rules/sidekiq.go  Line:        23  Commit:      cd5226711335c68be1e720b318b7bc3135a30eb2  Author:      John  Email:       john@users.noreply.github.com  Date:        2022-08-03T12:31:40Z  Fingerprint: cd5226711335c68be1e720b318b7bc3135a30eb2:cmd/generate/config/rules/sidekiq.go:sidekiq-secret:23&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Formats&lt;/strong&gt;: Reports can be output in &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/gitleaks/gitleaks?tab=readme-ov-file#creating-a-baseline&quot;&gt;various formats&lt;/a&gt; such as &lt;a target=&quot;_blank&quot; href=&quot;https://json-schema.org/&quot;&gt;JSON&lt;/a&gt; (default), &lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Comma-separated_values&quot;&gt;CSV&lt;/a&gt;, &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/testmoapp/junitxml&quot;&gt;junit&lt;/a&gt;, &lt;a target=&quot;_blank&quot; href=&quot;https://sarifweb.azurewebsites.net/&quot;&gt;sarif&lt;/a&gt; or directly to the console.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h2 id=&quot;heading-installation-on-linux&quot;&gt;&lt;strong&gt;Installation on Linux&lt;/strong&gt;&lt;/h2&gt;&lt;p&gt;Gitleaks can be &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/gitleaks/gitleaks?tab=readme-ov-file#installing&quot;&gt;installed&lt;/a&gt; as a binary from the &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/gitleaks/gitleaks/releases&quot;&gt;GitHub releases page&lt;/a&gt;.&lt;/p&gt;&lt;div data-node-type=&quot;callout&quot;&gt;&lt;div data-node-type=&quot;callout-emoji&quot;&gt;💡&lt;/div&gt;&lt;div data-node-type=&quot;callout-text&quot;&gt;Ensure that you have the &lt;a target=&quot;_blank&quot; href=&quot;https://maxat-akbanov.com/how-to-install-the-stable-version-of-go-on-kali-linux&quot;&gt;Go installed properly&lt;/a&gt; on your system as a prerequisite.&lt;/div&gt;&lt;/div&gt;&lt;p&gt;For Go installation you can use the following settings in &lt;code&gt;~/.bashrc&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Golang &lt;/span&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;export&lt;/span&gt; GOPATH=&lt;span class=&quot;hljs-variable&quot;&gt;$HOME&lt;/span&gt;/go &lt;span class=&quot;hljs-built_in&quot;&gt;export&lt;/span&gt; GOROOT=/usr/&lt;span class=&quot;hljs-built_in&quot;&gt;local&lt;/span&gt;/go PATH=&lt;span class=&quot;hljs-variable&quot;&gt;$PATH&lt;/span&gt;:&lt;span class=&quot;hljs-variable&quot;&gt;$GOROOT&lt;/span&gt;/bin/:&lt;span class=&quot;hljs-variable&quot;&gt;$GOPATH&lt;/span&gt;/bin&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To install &lt;strong&gt;the latest version&lt;/strong&gt; of the gitleaks:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;Compile the source code:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# From Source&lt;/span&gt; git &lt;span class=&quot;hljs-built_in&quot;&gt;clone&lt;/span&gt; https://github.com/gitleaks/gitleaks.git &lt;span class=&quot;hljs-built_in&quot;&gt;cd&lt;/span&gt; gitleaks make build&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; After compiling the source code, you&apos;ll find the executable:&lt;/p&gt;&lt;p&gt; &lt;img src=&quot;https://i.imgur.com/rRpvTKB.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Now move the &lt;code&gt;gitleaks&lt;/code&gt; executable into your &lt;code&gt;/usr/local/bin/&lt;/code&gt; :&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; sudo mv gitleaks /usr/&lt;span class=&quot;hljs-built_in&quot;&gt;local&lt;/span&gt;/bin/&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;To verify the installation run:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; gitleaks version&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h2 id=&quot;heading-basic-usage&quot;&gt;Basic Usage&lt;/h2&gt;&lt;ol&gt;&lt;li&gt;To scan a repository&apos;s &lt;code&gt;git log&lt;/code&gt; history, navigate to the repository directory and run:&lt;/li&gt;&lt;/ol&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;gitleaks detect .&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;detect&lt;/code&gt; command is used to scan repos, directories, and files.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/cpUG8MN.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;ol start=&quot;2&quot;&gt;&lt;li&gt;&lt;p&gt;To scan files and directories while ignoring &lt;code&gt;git log&lt;/code&gt; history use the &lt;code&gt;--no-git&lt;/code&gt; option.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; gitleaks detect . --no-git&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;To save finding into report JSON (default) file:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; gitleaks detect --report-path gitleaks-report.json&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;To output current repository scan while ignoring the &lt;code&gt;git log&lt;/code&gt; history:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; gitleaks detect . --no-git --report-format=json --report-path=gitleaks-report.json&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;If you need to process JSON report file for all found files with sensitive information (&lt;code&gt;File&lt;/code&gt; field) use the following command:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;jq -r &lt;span class=&quot;hljs-string&quot;&gt;&apos;.[].File&apos;&lt;/span&gt; gitleaks-report.json | sort | uniq &amp;gt; sensitive_files.txt&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;heading-gitleaks-pre-commit&quot;&gt;Gitleaks pre-commit&lt;/h2&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;To use &lt;code&gt;gitleaks&lt;/code&gt; as pre-commit hook, first install &lt;a target=&quot;_blank&quot; href=&quot;https://pre-commit.com/#install&quot;&gt;pre-commit&lt;/a&gt; tool:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; pip install pre-commit&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Create &lt;code&gt;.pre-commit-config.yaml&lt;/code&gt; file at the root of the project. Specify the configuration and the version of the &lt;code&gt;gitleaks&lt;/code&gt; to use:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# .pre-commit-config.yaml&lt;/span&gt; - repo: https://github.com/zricethezav/gitleaks   rev: v8.18.3   hooks:     - id: gitleaks&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;To install the hook run:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; pre-commit install&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Optional. To update the &lt;code&gt;gitleaks&lt;/code&gt; version used in the hook configuration to the latest:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; pre-commit autoupdate&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Optional. To disable the gitleaks pre-commit hook you can prepend &lt;code&gt;SKIP=gitleaks&lt;/code&gt; to the commit command and it will skip running gitleaks:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; SKIP=gitleaks git commit -m &lt;span class=&quot;hljs-string&quot;&gt;&quot;skip gitleaks check&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h2 id=&quot;heading-create-custom-configuration-of-rules&quot;&gt;Create custom configuration of rules&lt;/h2&gt;&lt;p&gt;Gitleaks offers a configuration format you can follow to write your own secret detection rules. Create a &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/gitleaks/gitleaks/blob/master/config/gitleaks.toml&quot;&gt;&lt;code&gt;gitleaks.toml&lt;/code&gt;&lt;/a&gt; file to define custom rules and settings:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-ini&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;title&lt;/span&gt; = &lt;span class=&quot;hljs-string&quot;&gt;&quot;Gitleaks Configuration&quot;&lt;/span&gt;&lt;span class=&quot;hljs-section&quot;&gt;[[rules]]&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;description&lt;/span&gt; = &lt;span class=&quot;hljs-string&quot;&gt;&quot;Generic API Key&quot;&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;regex&lt;/span&gt; = &lt;span class=&quot;hljs-string&quot;&gt;&apos;&apos;&apos;[a-zA-Z0-9]{32}&apos;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;tags&lt;/span&gt; = [&lt;span class=&quot;hljs-string&quot;&gt;&quot;key&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;api&quot;&lt;/span&gt;]&lt;span class=&quot;hljs-comment&quot;&gt;# Ignoring paths&lt;/span&gt;&lt;span class=&quot;hljs-section&quot;&gt;[[allowlist]]&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;paths&lt;/span&gt; = [&lt;span class=&quot;hljs-string&quot;&gt;&quot;path/to/ignore&quot;&lt;/span&gt;]&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For more information, see also &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/gitleaks/gitleaks?tab=readme-ov-file#configuration&quot;&gt;Configuration section of gitleaks&lt;/a&gt;&lt;/p&gt;]]&gt;</content:encoded><hashnode:content>&lt;![CDATA[&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://github.com/gitleaks/gitleaks&quot;&gt;Gitleaks&lt;/a&gt; is an open-source &lt;a target=&quot;_blank&quot; href=&quot;https://owasp.org/www-community/Source_Code_Analysis_Tools&quot;&gt;SAST tool&lt;/a&gt; designed to detect and prevent secrets (such as API keys, passwords, and other sensitive information) from being committed to version control repositories. It scans the entire repository history, including directories and files, to identify potential secrets. By configuring it properly and integrating it into your development workflow, you can significantly reduce the risk of exposing sensitive information.&lt;/p&gt;&lt;h2 id=&quot;heading-key-features&quot;&gt;Key Features&lt;/h2&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Detection&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Patterns and Rules&lt;/strong&gt;: Gitleaks uses &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/gitleaks/gitleaks/blob/master/config/gitleaks.toml&quot;&gt;predefined patterns and rules&lt;/a&gt; to identify secrets. These patterns can include regular expressions for common types of secrets like AWS keys, Slack tokens, and more:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-ini&quot;&gt;  &lt;span class=&quot;hljs-section&quot;&gt;[[rules]]&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;id&lt;/span&gt; = &lt;span class=&quot;hljs-string&quot;&gt;&quot;aws-access-token&quot;&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;description&lt;/span&gt; = &lt;span class=&quot;hljs-string&quot;&gt;&quot;Identified a pattern that may indicate AWS credentials, risking unauthorized cloud resource access and data breaches on AWS platforms.&quot;&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;regex&lt;/span&gt; = &lt;span class=&quot;hljs-string&quot;&gt;&apos;&apos;&apos;(?:A3T[A-Z0-9]|AKIA|ASIA|ABIA|ACCA)[A-Z0-9]{16}&apos;&apos;&apos;&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;keywords&lt;/span&gt; = [      &lt;span class=&quot;hljs-string&quot;&gt;&quot;akia&quot;&lt;/span&gt;,&lt;span class=&quot;hljs-string&quot;&gt;&quot;asia&quot;&lt;/span&gt;,&lt;span class=&quot;hljs-string&quot;&gt;&quot;abia&quot;&lt;/span&gt;,&lt;span class=&quot;hljs-string&quot;&gt;&quot;acca&quot;&lt;/span&gt;,  ]&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Custom Rules&lt;/strong&gt;: Users can &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/gitleaks/gitleaks?tab=readme-ov-file#configuration&quot;&gt;define custom rules&lt;/a&gt; to detect specific types of secrets relevant to their projects.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scanning&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Repository Scanning&lt;/strong&gt;: Gitleaks can &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/gitleaks/gitleaks?tab=readme-ov-file#detect&quot;&gt;scan entire Git repositories&lt;/a&gt;, including commit history, directories and files.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pre-commit Hook&lt;/strong&gt;: It can be integrated as a &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/gitleaks/gitleaks?tab=readme-ov-file#pre-commit&quot;&gt;pre-commit hook&lt;/a&gt; to scan changes before they are committed, preventing secrets from entering the repository.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Configuration&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Config Files&lt;/strong&gt;: Users can configure Gitleaks using a configuration file (&lt;a target=&quot;_blank&quot; href=&quot;https://github.com/gitleaks/gitleaks/blob/master/config/gitleaks.toml&quot;&gt;&lt;code&gt;gitleaks.toml&lt;/code&gt;&lt;/a&gt;) to customize the rules and behavior of the tool.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ignore Files&lt;/strong&gt;: Gitleaks can be configured to ignore specific files or directories using an ignore file (&lt;a target=&quot;_blank&quot; href=&quot;https://github.com/gitleaks/gitleaks?tab=readme-ov-file#gitleaksignore&quot;&gt;&lt;code&gt;.gitleaksignore&lt;/code&gt;&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reports&lt;/strong&gt;: Gitleaks generates detailed reports of identified secrets, including the location in the repository and the specific rule that triggered the detection.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;  ~/code(master) gitleaks detect --&lt;span class=&quot;hljs-built_in&quot;&gt;source&lt;/span&gt; . -v  Finding:     &lt;span class=&quot;hljs-string&quot;&gt;&quot;export BUNDLE_ENTERPRISE__CONTRIBSYS__COM=cafebabe:deadbeef&quot;&lt;/span&gt;,  Secret:      cafebabe:deadbeef  RuleID:      sidekiq-secret  Entropy:     2.609850  File:        cmd/generate/config/rules/sidekiq.go  Line:        23  Commit:      cd5226711335c68be1e720b318b7bc3135a30eb2  Author:      John  Email:       john@users.noreply.github.com  Date:        2022-08-03T12:31:40Z  Fingerprint: cd5226711335c68be1e720b318b7bc3135a30eb2:cmd/generate/config/rules/sidekiq.go:sidekiq-secret:23&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Formats&lt;/strong&gt;: Reports can be output in &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/gitleaks/gitleaks?tab=readme-ov-file#creating-a-baseline&quot;&gt;various formats&lt;/a&gt; such as &lt;a target=&quot;_blank&quot; href=&quot;https://json-schema.org/&quot;&gt;JSON&lt;/a&gt; (default), &lt;a target=&quot;_blank&quot; href=&quot;https://en.wikipedia.org/wiki/Comma-separated_values&quot;&gt;CSV&lt;/a&gt;, &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/testmoapp/junitxml&quot;&gt;junit&lt;/a&gt;, &lt;a target=&quot;_blank&quot; href=&quot;https://sarifweb.azurewebsites.net/&quot;&gt;sarif&lt;/a&gt; or directly to the console.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h2 id=&quot;heading-installation-on-linux&quot;&gt;&lt;strong&gt;Installation on Linux&lt;/strong&gt;&lt;/h2&gt;&lt;p&gt;Gitleaks can be &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/gitleaks/gitleaks?tab=readme-ov-file#installing&quot;&gt;installed&lt;/a&gt; as a binary from the &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/gitleaks/gitleaks/releases&quot;&gt;GitHub releases page&lt;/a&gt;.&lt;/p&gt;&lt;div data-node-type=&quot;callout&quot;&gt;&lt;div data-node-type=&quot;callout-emoji&quot;&gt;💡&lt;/div&gt;&lt;div data-node-type=&quot;callout-text&quot;&gt;Ensure that you have the &lt;a target=&quot;_blank&quot; href=&quot;https://maxat-akbanov.com/how-to-install-the-stable-version-of-go-on-kali-linux&quot;&gt;Go installed properly&lt;/a&gt; on your system as a prerequisite.&lt;/div&gt;&lt;/div&gt;&lt;p&gt;For Go installation you can use the following settings in &lt;code&gt;~/.bashrc&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Golang &lt;/span&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;export&lt;/span&gt; GOPATH=&lt;span class=&quot;hljs-variable&quot;&gt;$HOME&lt;/span&gt;/go &lt;span class=&quot;hljs-built_in&quot;&gt;export&lt;/span&gt; GOROOT=/usr/&lt;span class=&quot;hljs-built_in&quot;&gt;local&lt;/span&gt;/go PATH=&lt;span class=&quot;hljs-variable&quot;&gt;$PATH&lt;/span&gt;:&lt;span class=&quot;hljs-variable&quot;&gt;$GOROOT&lt;/span&gt;/bin/:&lt;span class=&quot;hljs-variable&quot;&gt;$GOPATH&lt;/span&gt;/bin&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To install &lt;strong&gt;the latest version&lt;/strong&gt; of the gitleaks:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;Compile the source code:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# From Source&lt;/span&gt; git &lt;span class=&quot;hljs-built_in&quot;&gt;clone&lt;/span&gt; https://github.com/gitleaks/gitleaks.git &lt;span class=&quot;hljs-built_in&quot;&gt;cd&lt;/span&gt; gitleaks make build&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; After compiling the source code, you&apos;ll find the executable:&lt;/p&gt;&lt;p&gt; &lt;img src=&quot;https://i.imgur.com/rRpvTKB.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Now move the &lt;code&gt;gitleaks&lt;/code&gt; executable into your &lt;code&gt;/usr/local/bin/&lt;/code&gt; :&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; sudo mv gitleaks /usr/&lt;span class=&quot;hljs-built_in&quot;&gt;local&lt;/span&gt;/bin/&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;To verify the installation run:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; gitleaks version&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h2 id=&quot;heading-basic-usage&quot;&gt;Basic Usage&lt;/h2&gt;&lt;ol&gt;&lt;li&gt;To scan a repository&apos;s &lt;code&gt;git log&lt;/code&gt; history, navigate to the repository directory and run:&lt;/li&gt;&lt;/ol&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;gitleaks detect .&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;detect&lt;/code&gt; command is used to scan repos, directories, and files.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/cpUG8MN.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;ol start=&quot;2&quot;&gt;&lt;li&gt;&lt;p&gt;To scan files and directories while ignoring &lt;code&gt;git log&lt;/code&gt; history use the &lt;code&gt;--no-git&lt;/code&gt; option.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; gitleaks detect . --no-git&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;To save finding into report JSON (default) file:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; gitleaks detect --report-path gitleaks-report.json&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;To output current repository scan while ignoring the &lt;code&gt;git log&lt;/code&gt; history:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; gitleaks detect . --no-git --report-format=json --report-path=gitleaks-report.json&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;If you need to process JSON report file for all found files with sensitive information (&lt;code&gt;File&lt;/code&gt; field) use the following command:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;jq -r &lt;span class=&quot;hljs-string&quot;&gt;&apos;.[].File&apos;&lt;/span&gt; gitleaks-report.json | sort | uniq &amp;gt; sensitive_files.txt&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;heading-gitleaks-pre-commit&quot;&gt;Gitleaks pre-commit&lt;/h2&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;To use &lt;code&gt;gitleaks&lt;/code&gt; as pre-commit hook, first install &lt;a target=&quot;_blank&quot; href=&quot;https://pre-commit.com/#install&quot;&gt;pre-commit&lt;/a&gt; tool:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; pip install pre-commit&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Create &lt;code&gt;.pre-commit-config.yaml&lt;/code&gt; file at the root of the project. Specify the configuration and the version of the &lt;code&gt;gitleaks&lt;/code&gt; to use:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# .pre-commit-config.yaml&lt;/span&gt; - repo: https://github.com/zricethezav/gitleaks   rev: v8.18.3   hooks:     - id: gitleaks&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;To install the hook run:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; pre-commit install&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Optional. To update the &lt;code&gt;gitleaks&lt;/code&gt; version used in the hook configuration to the latest:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; pre-commit autoupdate&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Optional. To disable the gitleaks pre-commit hook you can prepend &lt;code&gt;SKIP=gitleaks&lt;/code&gt; to the commit command and it will skip running gitleaks:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; SKIP=gitleaks git commit -m &lt;span class=&quot;hljs-string&quot;&gt;&quot;skip gitleaks check&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h2 id=&quot;heading-create-custom-configuration-of-rules&quot;&gt;Create custom configuration of rules&lt;/h2&gt;&lt;p&gt;Gitleaks offers a configuration format you can follow to write your own secret detection rules. Create a &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/gitleaks/gitleaks/blob/master/config/gitleaks.toml&quot;&gt;&lt;code&gt;gitleaks.toml&lt;/code&gt;&lt;/a&gt; file to define custom rules and settings:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-ini&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;title&lt;/span&gt; = &lt;span class=&quot;hljs-string&quot;&gt;&quot;Gitleaks Configuration&quot;&lt;/span&gt;&lt;span class=&quot;hljs-section&quot;&gt;[[rules]]&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;description&lt;/span&gt; = &lt;span class=&quot;hljs-string&quot;&gt;&quot;Generic API Key&quot;&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;regex&lt;/span&gt; = &lt;span class=&quot;hljs-string&quot;&gt;&apos;&apos;&apos;[a-zA-Z0-9]{32}&apos;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;tags&lt;/span&gt; = [&lt;span class=&quot;hljs-string&quot;&gt;&quot;key&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;api&quot;&lt;/span&gt;]&lt;span class=&quot;hljs-comment&quot;&gt;# Ignoring paths&lt;/span&gt;&lt;span class=&quot;hljs-section&quot;&gt;[[allowlist]]&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;paths&lt;/span&gt; = [&lt;span class=&quot;hljs-string&quot;&gt;&quot;path/to/ignore&quot;&lt;/span&gt;]&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For more information, see also &lt;a target=&quot;_blank&quot; href=&quot;https://github.com/gitleaks/gitleaks?tab=readme-ov-file#configuration&quot;&gt;Configuration section of gitleaks&lt;/a&gt;&lt;/p&gt;]]&gt;</hashnode:content><hashnode:coverImage>https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/MPKQiDpMyqU/upload/d25fa2d3aca7b490f7714532d35c14db.jpeg</hashnode:coverImage></item><item><title><![CDATA[Iterate over matching files: `with_fileglob` module in Ansible]]></title><description><![CDATA[Iterate over matching files: `with_fileglob` module in Ansible]]></description><link>https://maxat-akbanov.com/iterate-over-matching-files-withfileglob-module-in-ansible</link><guid isPermaLink="true">https://maxat-akbanov.com/iterate-over-matching-files-withfileglob-module-in-ansible</guid><category><![CDATA[ansible]]></category><category><![CDATA[Devops]]></category><category><![CDATA[sysops]]></category><category><![CDATA[configuration management]]></category><dc:creator><![CDATA[Maxat Akbanov]]></dc:creator><pubDate>Mon, 27 May 2024 08:19:15 GMT</pubDate><content:encoded>&lt;![CDATA[&lt;p&gt;The &lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/collections/ansible/builtin/fileglob_lookup.html&quot;&gt;&lt;code&gt;with_fileglob&lt;/code&gt;&lt;/a&gt; module in Ansible is used to iterate over files in a directory that match a specified pattern on the &lt;strong&gt;Ansible controller machine&lt;/strong&gt;. This is useful when you need to perform tasks on multiple files without explicitly listing each one. The &lt;code&gt;with_fileglob&lt;/code&gt; loop allows you to apply actions to all files that match a given globbing pattern, making your playbooks more dynamic and easier to maintain.&lt;/p&gt;&lt;p&gt;&lt;code&gt;with_fileglob&lt;/code&gt; module use Pythons &lt;a target=&quot;_blank&quot; href=&quot;https://docs.python.org/3/library/glob.html&quot;&gt;glob&lt;/a&gt; library to find all pathnames.&lt;/p&gt;&lt;h3 id=&quot;heading-use-cases&quot;&gt;Use Cases&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deploying Configuration Files&lt;/strong&gt;: You can use &lt;code&gt;with_fileglob&lt;/code&gt; to copy multiple configuration files from a directory to a target host.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Template Rendering&lt;/strong&gt;: Render multiple template files from a directory.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;File Permissions&lt;/strong&gt;: Change the permissions of multiple files in a directory.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Backup&lt;/strong&gt;: Back up multiple files from a directory to another location.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-code-examples&quot;&gt;Code Examples&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Copying Configuration Files&lt;/strong&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt; &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Copy&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;all&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;files&lt;/span&gt;   &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;webservers&lt;/span&gt;   &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;     &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Copy&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;configuration&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;files&lt;/span&gt;       &lt;span class=&quot;hljs-attr&quot;&gt;copy:&lt;/span&gt;         &lt;span class=&quot;hljs-attr&quot;&gt;src:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ item }}&lt;/span&gt;&quot;&lt;/span&gt;         &lt;span class=&quot;hljs-attr&quot;&gt;dest:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/etc/myapp/config/&lt;/span&gt;       &lt;span class=&quot;hljs-attr&quot;&gt;with_fileglob:&lt;/span&gt;         &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/path/to/local/configs/*.conf&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Rendering Templates&lt;/strong&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt; &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Render&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;multiple&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;template&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;files&lt;/span&gt;   &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;appservers&lt;/span&gt;   &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;     &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Template&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;files&lt;/span&gt;       &lt;span class=&quot;hljs-attr&quot;&gt;template:&lt;/span&gt;         &lt;span class=&quot;hljs-attr&quot;&gt;src:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ item }}&lt;/span&gt;&quot;&lt;/span&gt;         &lt;span class=&quot;hljs-attr&quot;&gt;dest:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;/etc/myapp/templates/&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ item | basename }}&lt;/span&gt;&quot;&lt;/span&gt;       &lt;span class=&quot;hljs-attr&quot;&gt;with_fileglob:&lt;/span&gt;         &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/path/to/templates/*.j2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Changing File Permissions&lt;/strong&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt; &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Change&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;permissions&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;files&lt;/span&gt;   &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;servers&lt;/span&gt;   &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;     &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;permissions&lt;/span&gt;       &lt;span class=&quot;hljs-attr&quot;&gt;file:&lt;/span&gt;         &lt;span class=&quot;hljs-attr&quot;&gt;path:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ item }}&lt;/span&gt;&quot;&lt;/span&gt;         &lt;span class=&quot;hljs-attr&quot;&gt;mode:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&apos;0644&apos;&lt;/span&gt;       &lt;span class=&quot;hljs-attr&quot;&gt;with_fileglob:&lt;/span&gt;         &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/var/log/myapp/*.log&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Backing Up Files&lt;/strong&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt; &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Backup&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;important&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;files&lt;/span&gt;   &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;all&lt;/span&gt;   &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;     &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Copy&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;files&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;backup&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;directory&lt;/span&gt;       &lt;span class=&quot;hljs-attr&quot;&gt;copy:&lt;/span&gt;         &lt;span class=&quot;hljs-attr&quot;&gt;src:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ item }}&lt;/span&gt;&quot;&lt;/span&gt;         &lt;span class=&quot;hljs-attr&quot;&gt;dest:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/backup/&lt;/span&gt;       &lt;span class=&quot;hljs-attr&quot;&gt;with_fileglob:&lt;/span&gt;         &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/etc/myapp/important_files/*&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-explanation&quot;&gt;Explanation&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;with_fileglob&lt;/code&gt;: This is the loop directive that tells Ansible to iterate over files matching the given pattern.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;src&lt;/code&gt;: Specifies the source file or directory.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;dest&lt;/code&gt;: Specifies the destination file or directory.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;item&lt;/code&gt;: The current item in the loop, representing each file that matches the pattern.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;By using &lt;code&gt;with_fileglob&lt;/code&gt;, you can simplify tasks that need to be performed on multiple files without hardcoding each file path, making your Ansible playbooks more efficient and easier to manage.&lt;/p&gt;&lt;h3 id=&quot;heading-how-withfileglob-works&quot;&gt;How with_fileglob works&lt;/h3&gt;&lt;p&gt;The &lt;code&gt;with_fileglob&lt;/code&gt; module in Ansible is used to &lt;strong&gt;match files on the Ansible control machine&lt;/strong&gt;, not on the remote hosts. This is an important distinction because the file matching is performed locally on the machine where the playbook is being run, and then the actions specified in the tasks are applied to the matched files.&lt;/p&gt;&lt;h3 id=&quot;heading-key-points&quot;&gt;Key Points&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Local to Control Machine&lt;/strong&gt;: The file globbing operation (&lt;code&gt;with_fileglob&lt;/code&gt;) is executed on the control machine where Ansible is running.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Remote Tasks&lt;/strong&gt;: Once the files are matched, the specified tasks (such as copying files, changing permissions, etc.) are executed on the remote hosts.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-example-clarification&quot;&gt;Example Clarification&lt;/h3&gt;&lt;p&gt;Let&apos;s clarify with an example:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Control Machine Setup&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Assume you have a directory &lt;code&gt;/path/to/local/configs/&lt;/code&gt; on your control machine with several &lt;code&gt;.conf&lt;/code&gt; files.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Playbook&lt;/strong&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Copy&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;all&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;files&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;webservers&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Copy&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;configuration&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;files&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;copy:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;src:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ item }}&lt;/span&gt;&quot;&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;dest:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/etc/myapp/config/&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;with_fileglob:&lt;/span&gt;        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/path/to/local/configs/*.conf&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-execution-flow&quot;&gt;Execution Flow&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Globbing on Control Machine&lt;/strong&gt;: Ansible matches all files ending with &lt;code&gt;.conf&lt;/code&gt; in the &lt;code&gt;/path/to/local/configs/&lt;/code&gt; directory on the control machine.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Copy Task&lt;/strong&gt;: The &lt;code&gt;copy&lt;/code&gt; module is then used to copy each matched file from the control machine to the specified destination (&lt;code&gt;/etc/myapp/config/&lt;/code&gt;) on the remote hosts (e.g., &lt;code&gt;webservers&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-workshop-copy-config-files-from-one-local-directory-to-another&quot;&gt;Workshop: Copy config files from one local directory to another&lt;/h3&gt;&lt;p&gt;This example will demonstrate using &lt;code&gt;with_fileglob&lt;/code&gt; to copy multiple configuration files from a local directory to another directory on the same machine.&lt;/p&gt;&lt;h3 id=&quot;heading-step-1-prepare-the-environment&quot;&gt;Step 1: Prepare the Environment&lt;/h3&gt;&lt;p&gt;Open a terminal and run the following commands:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;mkdir -p ~/ansible_test/configsmkdir -p ~/ansible_test/target&lt;span class=&quot;hljs-comment&quot;&gt;# Create some sample config files&lt;/span&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;config1&quot;&lt;/span&gt; &amp;gt; ~/ansible_test/configs/sample1.conf&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;config2&quot;&lt;/span&gt; &amp;gt; ~/ansible_test/configs/sample2.conf&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;config3&quot;&lt;/span&gt; &amp;gt; ~/ansible_test/configs/sample3.conf&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-step-2-create-the-ansible-playbook&quot;&gt;Step 2: Create the Ansible Playbook&lt;/h3&gt;&lt;p&gt;Create a file named &lt;code&gt;copy_configs.yml&lt;/code&gt; and add the following content:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Copy&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;configuration&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;files&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;with_fileglob&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;localhost&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;connection:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;local&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Copy&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;configuration&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;files&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;target&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;directory&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;copy:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;src:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ item }}&lt;/span&gt;&quot;&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;dest:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;~/ansible_test/target/&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;with_fileglob:&lt;/span&gt;        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;~/ansible_test/configs/*.conf&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-step-3-run-the-playbook&quot;&gt;Step 3: Run the Playbook&lt;/h3&gt;&lt;p&gt;Ensure you have Ansible installed. If not, you can install it using:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;sudo apt updatesudo apt install ansible -y&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Run the playbook with the following command:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;ansible-playbook copy_configs.yml&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-step-4-verify-the-result&quot;&gt;Step 4: Verify the Result&lt;/h3&gt;&lt;p&gt;Check the contents of the target directory to ensure the files were copied correctly:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;ls ~/ansible_test/target&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You should see &lt;code&gt;sample1.conf&lt;/code&gt;, &lt;code&gt;sample2.conf&lt;/code&gt;, and &lt;code&gt;sample3.conf&lt;/code&gt; in the &lt;code&gt;~/ansible_test/target&lt;/code&gt; directory.&lt;/p&gt;&lt;h3 id=&quot;heading-explanation-1&quot;&gt;Explanation&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;hosts: localhost&lt;/code&gt;: Specifies that the playbook will run on the local machine.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;connection: local&lt;/code&gt;: Ensures Ansible runs the tasks locally.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;with_fileglob&lt;/code&gt;: Matches all &lt;code&gt;.conf&lt;/code&gt; files in the specified directory.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;copy&lt;/code&gt; module: Copies each matched file from the source directory to the target directory.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-references&quot;&gt;References:&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/collections/ansible/builtin/fileglob_lookup.html#ansible-builtin-fileglob-lookup-list-files-matching-a-pattern&quot;&gt;Ansible docs: ansible.builtin.fileglob lookup  list files matching a pattern&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;]]&gt;</content:encoded><hashnode:content>&lt;![CDATA[&lt;p&gt;The &lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/collections/ansible/builtin/fileglob_lookup.html&quot;&gt;&lt;code&gt;with_fileglob&lt;/code&gt;&lt;/a&gt; module in Ansible is used to iterate over files in a directory that match a specified pattern on the &lt;strong&gt;Ansible controller machine&lt;/strong&gt;. This is useful when you need to perform tasks on multiple files without explicitly listing each one. The &lt;code&gt;with_fileglob&lt;/code&gt; loop allows you to apply actions to all files that match a given globbing pattern, making your playbooks more dynamic and easier to maintain.&lt;/p&gt;&lt;p&gt;&lt;code&gt;with_fileglob&lt;/code&gt; module use Pythons &lt;a target=&quot;_blank&quot; href=&quot;https://docs.python.org/3/library/glob.html&quot;&gt;glob&lt;/a&gt; library to find all pathnames.&lt;/p&gt;&lt;h3 id=&quot;heading-use-cases&quot;&gt;Use Cases&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deploying Configuration Files&lt;/strong&gt;: You can use &lt;code&gt;with_fileglob&lt;/code&gt; to copy multiple configuration files from a directory to a target host.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Template Rendering&lt;/strong&gt;: Render multiple template files from a directory.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;File Permissions&lt;/strong&gt;: Change the permissions of multiple files in a directory.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Backup&lt;/strong&gt;: Back up multiple files from a directory to another location.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-code-examples&quot;&gt;Code Examples&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Copying Configuration Files&lt;/strong&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt; &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Copy&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;all&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;files&lt;/span&gt;   &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;webservers&lt;/span&gt;   &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;     &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Copy&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;configuration&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;files&lt;/span&gt;       &lt;span class=&quot;hljs-attr&quot;&gt;copy:&lt;/span&gt;         &lt;span class=&quot;hljs-attr&quot;&gt;src:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ item }}&lt;/span&gt;&quot;&lt;/span&gt;         &lt;span class=&quot;hljs-attr&quot;&gt;dest:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/etc/myapp/config/&lt;/span&gt;       &lt;span class=&quot;hljs-attr&quot;&gt;with_fileglob:&lt;/span&gt;         &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/path/to/local/configs/*.conf&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Rendering Templates&lt;/strong&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt; &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Render&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;multiple&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;template&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;files&lt;/span&gt;   &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;appservers&lt;/span&gt;   &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;     &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Template&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;files&lt;/span&gt;       &lt;span class=&quot;hljs-attr&quot;&gt;template:&lt;/span&gt;         &lt;span class=&quot;hljs-attr&quot;&gt;src:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ item }}&lt;/span&gt;&quot;&lt;/span&gt;         &lt;span class=&quot;hljs-attr&quot;&gt;dest:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;/etc/myapp/templates/&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ item | basename }}&lt;/span&gt;&quot;&lt;/span&gt;       &lt;span class=&quot;hljs-attr&quot;&gt;with_fileglob:&lt;/span&gt;         &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/path/to/templates/*.j2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Changing File Permissions&lt;/strong&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt; &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Change&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;permissions&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;log&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;files&lt;/span&gt;   &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;servers&lt;/span&gt;   &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;     &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;permissions&lt;/span&gt;       &lt;span class=&quot;hljs-attr&quot;&gt;file:&lt;/span&gt;         &lt;span class=&quot;hljs-attr&quot;&gt;path:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ item }}&lt;/span&gt;&quot;&lt;/span&gt;         &lt;span class=&quot;hljs-attr&quot;&gt;mode:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&apos;0644&apos;&lt;/span&gt;       &lt;span class=&quot;hljs-attr&quot;&gt;with_fileglob:&lt;/span&gt;         &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/var/log/myapp/*.log&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Backing Up Files&lt;/strong&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt; &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Backup&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;important&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;files&lt;/span&gt;   &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;all&lt;/span&gt;   &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;     &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Copy&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;files&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;backup&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;directory&lt;/span&gt;       &lt;span class=&quot;hljs-attr&quot;&gt;copy:&lt;/span&gt;         &lt;span class=&quot;hljs-attr&quot;&gt;src:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ item }}&lt;/span&gt;&quot;&lt;/span&gt;         &lt;span class=&quot;hljs-attr&quot;&gt;dest:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/backup/&lt;/span&gt;       &lt;span class=&quot;hljs-attr&quot;&gt;with_fileglob:&lt;/span&gt;         &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/etc/myapp/important_files/*&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-explanation&quot;&gt;Explanation&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;with_fileglob&lt;/code&gt;: This is the loop directive that tells Ansible to iterate over files matching the given pattern.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;src&lt;/code&gt;: Specifies the source file or directory.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;dest&lt;/code&gt;: Specifies the destination file or directory.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;item&lt;/code&gt;: The current item in the loop, representing each file that matches the pattern.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;By using &lt;code&gt;with_fileglob&lt;/code&gt;, you can simplify tasks that need to be performed on multiple files without hardcoding each file path, making your Ansible playbooks more efficient and easier to manage.&lt;/p&gt;&lt;h3 id=&quot;heading-how-withfileglob-works&quot;&gt;How with_fileglob works&lt;/h3&gt;&lt;p&gt;The &lt;code&gt;with_fileglob&lt;/code&gt; module in Ansible is used to &lt;strong&gt;match files on the Ansible control machine&lt;/strong&gt;, not on the remote hosts. This is an important distinction because the file matching is performed locally on the machine where the playbook is being run, and then the actions specified in the tasks are applied to the matched files.&lt;/p&gt;&lt;h3 id=&quot;heading-key-points&quot;&gt;Key Points&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Local to Control Machine&lt;/strong&gt;: The file globbing operation (&lt;code&gt;with_fileglob&lt;/code&gt;) is executed on the control machine where Ansible is running.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Remote Tasks&lt;/strong&gt;: Once the files are matched, the specified tasks (such as copying files, changing permissions, etc.) are executed on the remote hosts.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-example-clarification&quot;&gt;Example Clarification&lt;/h3&gt;&lt;p&gt;Let&apos;s clarify with an example:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Control Machine Setup&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Assume you have a directory &lt;code&gt;/path/to/local/configs/&lt;/code&gt; on your control machine with several &lt;code&gt;.conf&lt;/code&gt; files.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Playbook&lt;/strong&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Copy&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;all&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;files&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;webservers&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Copy&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;configuration&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;files&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;copy:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;src:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ item }}&lt;/span&gt;&quot;&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;dest:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/etc/myapp/config/&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;with_fileglob:&lt;/span&gt;        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/path/to/local/configs/*.conf&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-execution-flow&quot;&gt;Execution Flow&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Globbing on Control Machine&lt;/strong&gt;: Ansible matches all files ending with &lt;code&gt;.conf&lt;/code&gt; in the &lt;code&gt;/path/to/local/configs/&lt;/code&gt; directory on the control machine.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Copy Task&lt;/strong&gt;: The &lt;code&gt;copy&lt;/code&gt; module is then used to copy each matched file from the control machine to the specified destination (&lt;code&gt;/etc/myapp/config/&lt;/code&gt;) on the remote hosts (e.g., &lt;code&gt;webservers&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-workshop-copy-config-files-from-one-local-directory-to-another&quot;&gt;Workshop: Copy config files from one local directory to another&lt;/h3&gt;&lt;p&gt;This example will demonstrate using &lt;code&gt;with_fileglob&lt;/code&gt; to copy multiple configuration files from a local directory to another directory on the same machine.&lt;/p&gt;&lt;h3 id=&quot;heading-step-1-prepare-the-environment&quot;&gt;Step 1: Prepare the Environment&lt;/h3&gt;&lt;p&gt;Open a terminal and run the following commands:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;mkdir -p ~/ansible_test/configsmkdir -p ~/ansible_test/target&lt;span class=&quot;hljs-comment&quot;&gt;# Create some sample config files&lt;/span&gt;&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;config1&quot;&lt;/span&gt; &amp;gt; ~/ansible_test/configs/sample1.conf&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;config2&quot;&lt;/span&gt; &amp;gt; ~/ansible_test/configs/sample2.conf&lt;span class=&quot;hljs-built_in&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;config3&quot;&lt;/span&gt; &amp;gt; ~/ansible_test/configs/sample3.conf&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-step-2-create-the-ansible-playbook&quot;&gt;Step 2: Create the Ansible Playbook&lt;/h3&gt;&lt;p&gt;Create a file named &lt;code&gt;copy_configs.yml&lt;/code&gt; and add the following content:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Copy&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;configuration&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;files&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;with_fileglob&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;localhost&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;connection:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;local&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Copy&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;configuration&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;files&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;target&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;directory&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;copy:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;src:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ item }}&lt;/span&gt;&quot;&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;dest:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;~/ansible_test/target/&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;with_fileglob:&lt;/span&gt;        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;~/ansible_test/configs/*.conf&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-step-3-run-the-playbook&quot;&gt;Step 3: Run the Playbook&lt;/h3&gt;&lt;p&gt;Ensure you have Ansible installed. If not, you can install it using:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;sudo apt updatesudo apt install ansible -y&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Run the playbook with the following command:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;ansible-playbook copy_configs.yml&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-step-4-verify-the-result&quot;&gt;Step 4: Verify the Result&lt;/h3&gt;&lt;p&gt;Check the contents of the target directory to ensure the files were copied correctly:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;ls ~/ansible_test/target&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You should see &lt;code&gt;sample1.conf&lt;/code&gt;, &lt;code&gt;sample2.conf&lt;/code&gt;, and &lt;code&gt;sample3.conf&lt;/code&gt; in the &lt;code&gt;~/ansible_test/target&lt;/code&gt; directory.&lt;/p&gt;&lt;h3 id=&quot;heading-explanation-1&quot;&gt;Explanation&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;hosts: localhost&lt;/code&gt;: Specifies that the playbook will run on the local machine.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;connection: local&lt;/code&gt;: Ensures Ansible runs the tasks locally.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;with_fileglob&lt;/code&gt;: Matches all &lt;code&gt;.conf&lt;/code&gt; files in the specified directory.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;copy&lt;/code&gt; module: Copies each matched file from the source directory to the target directory.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-references&quot;&gt;References:&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/collections/ansible/builtin/fileglob_lookup.html#ansible-builtin-fileglob-lookup-list-files-matching-a-pattern&quot;&gt;Ansible docs: ansible.builtin.fileglob lookup  list files matching a pattern&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;]]&gt;</hashnode:content><hashnode:coverImage>https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/cPccYbPrF-A/upload/d9722e1acfe31dd7b3c974b2aa968e87.jpeg</hashnode:coverImage></item><item><title><![CDATA[Quick Startup with Ansible]]></title><description><![CDATA[Quick Startup with Ansible]]></description><link>https://maxat-akbanov.com/quick-startup-with-ansible</link><guid isPermaLink="true">https://maxat-akbanov.com/quick-startup-with-ansible</guid><category><![CDATA[ansible]]></category><category><![CDATA[Devops]]></category><category><![CDATA[sysops]]></category><category><![CDATA[configuration management]]></category><dc:creator><![CDATA[Maxat Akbanov]]></dc:creator><pubDate>Sun, 26 May 2024 14:38:44 GMT</pubDate><content:encoded>&lt;![CDATA[&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://github.com/ansible/ansible&quot;&gt;Ansible&lt;/a&gt; is a powerful automation tool used for configuration management, application deployment, and task automation. It operates by connecting to your nodes and pushing out small programs, called &lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/2.9/user_guide/modules.html&quot;&gt;Ansible modules&lt;/a&gt;, to perform tasks.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/GimrSd7.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;Image credits: &lt;a target=&quot;_blank&quot; href=&quot;https://www.ansible.com/how-ansible-works/&quot;&gt;Ansible.com&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The main components of Ansible are:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/inventory_guide/intro_inventory.html&quot;&gt;&lt;strong&gt;Inventory&lt;/strong&gt;&lt;/a&gt;: A list of hosts or nodes that Ansible manages.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/2.9/modules/list_of_all_modules.html&quot;&gt;&lt;strong&gt;Modules&lt;/strong&gt;&lt;/a&gt;: Units of work that Ansible executes. Examples include tasks for installing packages, copying files, or restarting services.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/playbook_guide/playbooks.html&quot;&gt;&lt;strong&gt;Playbooks&lt;/strong&gt;&lt;/a&gt;: YAML files that define a series of tasks to be executed on a set of hosts.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_reuse_roles.html&quot;&gt;&lt;strong&gt;Roles&lt;/strong&gt;&lt;/a&gt;: A way to group multiple tasks and configurations to be reusable.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html&quot;&gt;&lt;strong&gt;Variables&lt;/strong&gt;&lt;/a&gt;: Used to store values that can be reused in playbooks and templates.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_templating.html&quot;&gt;&lt;strong&gt;Templates&lt;/strong&gt;&lt;/a&gt;: Files that have placeholders for variables and can be dynamically populated during execution.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_handlers.html&quot;&gt;&lt;strong&gt;Handlers&lt;/strong&gt;&lt;/a&gt;: Used to trigger actions at the end of a playbook run when certain conditions are met.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h2 id=&quot;heading-ansible-components-overview&quot;&gt;Ansible Components Overview&lt;/h2&gt;&lt;h3 id=&quot;heading-1-inventory&quot;&gt;1. Inventory&lt;/h3&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/inventory_guide/intro_inventory.html&quot;&gt;&lt;strong&gt;Inventory File&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;The default inventory file is usually named &lt;code&gt;hosts&lt;/code&gt; or &lt;code&gt;inventory&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;By default, it is located at &lt;code&gt;/etc/ansible/hosts&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;It can be a simple INI-style file or YAML file, listing the managed nodes.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;INI File:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;An &lt;code&gt;.ini&lt;/code&gt; file is a simple text file used for configuration, with sections, properties, and values.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;In the context of Ansible, it defines groups of hosts and their variables.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example (INI-style):&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-ini&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Default inventory file location: /etc/ansible/hosts&lt;/span&gt;&lt;span class=&quot;hljs-section&quot;&gt;[webservers]&lt;/span&gt;web1.example.comweb2.example.com&lt;span class=&quot;hljs-section&quot;&gt;[databases]&lt;/span&gt;db1.example.com&lt;span class=&quot;hljs-comment&quot;&gt;# Defining variables for groups&lt;/span&gt;&lt;span class=&quot;hljs-section&quot;&gt;[webservers:vars]&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;ansible_user&lt;/span&gt;=admin&lt;span class=&quot;hljs-attr&quot;&gt;ansible_ssh_private_key_file&lt;/span&gt;=/path/to/key&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Example (YAML-style):&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;all:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;children:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;webservers:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;web1.example.com:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;web2.example.com:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;vars:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;ansible_user:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;admin&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;ansible_ssh_private_key_file:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/path/to/key&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;databases:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;db1.example.com:&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-2-modules&quot;&gt;2. Modules&lt;/h3&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/2.9/modules/list_of_all_modules.html&quot;&gt;&lt;strong&gt;Modules&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Small programs that Ansible pushes out to nodes to perform tasks. After programs finish the execution, Ansible removes them.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Examples include modules for package management (&lt;code&gt;apt&lt;/code&gt;, &lt;code&gt;yum&lt;/code&gt;), file operations (&lt;code&gt;copy&lt;/code&gt;, &lt;code&gt;template&lt;/code&gt;), and service management (&lt;code&gt;service&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Install&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Nginx&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;apt:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;state:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;present&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Command to list available modules:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-shell&quot;&gt;ansible-doc -l&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-3-playbooks&quot;&gt;3. Playbooks&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Playbooks:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;YAML files that define a series of tasks to be executed on hosts.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;They contain plays, each mapping a group of hosts to roles and tasks.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Important Parts:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;hosts&lt;/code&gt;: Specifies which hosts the playbook should run against.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;tasks&lt;/code&gt;: Defines a list of tasks to be executed.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;vars&lt;/code&gt;: Defines variables to be used within the playbook.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;handlers&lt;/code&gt;: Defines handlers that can be notified by tasks.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Configure&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;web&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;servers&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;webservers&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;vars:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;nginx_version:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1.18&lt;/span&gt;&lt;span class=&quot;hljs-number&quot;&gt;.0&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Install&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Nginx&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;apt:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx={{&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx_version&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;}}&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;state:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;present&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Copy&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Nginx&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;config&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;template:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;src:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;templates/nginx.conf.j2&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;dest:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/etc/nginx/nginx.conf&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;notify:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Restart&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Nginx&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;handlers:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Restart&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Nginx&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;service:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;state:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;restarted&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-4-roles&quot;&gt;4. Roles&lt;/h3&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_reuse_roles.html&quot;&gt;&lt;strong&gt;Roles&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Provide a structured way to group tasks, handlers, files, templates, and variables.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Allow for reuse and sharing of Ansible content.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Role Directory Structure:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-plaintext&quot;&gt;roles/  webserver/    tasks/      main.yml    templates/      nginx.conf.j2    handlers/      main.yml    vars/      main.yml    defaults/      main.yml    files/    meta/      main.yml&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Example Task File (roles/webserver/tasks/main.yml):&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Install&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Nginx&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;apt:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;state:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;present&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The beauty of roles lies in their reusability. You can include the same role in multiple playbooks to automate the same configuration on different sets of servers. For example, like installing and configuring a web server (Apache or Nginx) or setting up a database (MySQL or PostgreSQL).&lt;/p&gt;&lt;p&gt;To include a role inside an Ansible playbook you can use &lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/collections/ansible/builtin/include_role_module.html&quot;&gt;&lt;code&gt;include_role&lt;/code&gt;&lt;/a&gt; module.&lt;/p&gt;&lt;p&gt;This is the recommended approach for Ansible versions 2.4 and later. It offers more control and clarity.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;ansible.builtin.include_role:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;myrole&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Run&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;tasks/other.yaml&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;instead&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&apos;main&apos;&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;ansible.builtin.include_role:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;myrole&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;tasks_from:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pass&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;variables&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;role&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;ansible.builtin.include_role:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;myrole&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;vars:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;rolevar1:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Use&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;role&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;loop&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;ansible.builtin.include_role:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&apos;&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ roleinputvar }}&lt;/span&gt;&apos;&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;loop:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&apos;&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ roleinput1 }}&lt;/span&gt;&apos;&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&apos;&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ roleinput2 }}&lt;/span&gt;&apos;&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;loop_control:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;loop_var:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;roleinputvar&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Conditional&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;role&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;ansible.builtin.include_role:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;myrole&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;when:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;idontwanttorun&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Apply&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;tags&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;tasks&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;within&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;included&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;file&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;ansible.builtin.include_role:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;install&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;apply:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;tags:&lt;/span&gt;        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;install&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tags:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;always&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-5-variables&quot;&gt;5. Variables&lt;/h3&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html&quot;&gt;&lt;strong&gt;Variables&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Used to store values that can be reused in playbooks, roles, and templates.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Can be defined in playbooks, inventories, roles, or passed via command line.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Variable Precedence (highest to lowest):&lt;/strong&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;Extra vars (command line &lt;code&gt;-e&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Task vars (only in scope for the task)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Block vars (only in scope for the block)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Role and include vars&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Play vars (for the entire play)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Inventory vars&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Facts (gathered or set via &lt;code&gt;set_fact&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Playbook group_vars&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Playbook host_vars&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Ansible configuration settings&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;To learn more about variables check out this article: &lt;a target=&quot;_blank&quot; href=&quot;https://spacelift.io/blog/ansible-variables&quot;&gt;How to Use Different Types of Ansible Variables (Examples)&lt;/a&gt;&lt;/p&gt;&lt;h3 id=&quot;heading-1-extra-vars-command-line-e&quot;&gt;1. Extra vars (command line &lt;code&gt;-e&lt;/code&gt;)&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Extra variables passed directly on the command line have the highest precedence.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-shell&quot;&gt;ansible-playbook playbook.yml -e &quot;var1=value1 var2=value2&quot;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Playbook (playbook.yml):&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;all&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;debug:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;msg:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;var1=&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ var1 }}&lt;/span&gt;, var2=&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ var2 }}&lt;/span&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-2-task-vars-only-in-scope-for-the-task&quot;&gt;2. Task vars (only in scope for the task)&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Variables defined within a specific task have a very high precedence.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;all&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;variable&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;debug:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;msg:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Task variable var1=&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ var1 }}&lt;/span&gt;&quot;&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;vars:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;var1:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;task_value&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-3-block-vars-only-in-scope-for-the-block&quot;&gt;3. Block vars (only in scope for the block)&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Variables defined within a block are in scope only for tasks within that block.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;all&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;block:&lt;/span&gt;        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;block&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;variable&lt;/span&gt;          &lt;span class=&quot;hljs-attr&quot;&gt;debug:&lt;/span&gt;            &lt;span class=&quot;hljs-attr&quot;&gt;msg:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Block variable var1=&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ var1 }}&lt;/span&gt;&quot;&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;vars:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;var1:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;block_value&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To learn more, check out &quot;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_blocks.html#blocks&quot;&gt;Blocks&lt;/a&gt;&quot;&lt;/p&gt;&lt;h3 id=&quot;heading-4-role-and-include-vars&quot;&gt;4. Role and include vars&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Variables defined within roles or included files.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# roles/webserver/vars/main.yml&lt;/span&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;var1:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;role_value&quot;&lt;/span&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# playbook.yml&lt;/span&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;all&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;roles:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;role:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;webserver&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;debug:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;msg:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Role variable var1=&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ var1 }}&lt;/span&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-5-play-vars-for-the-entire-play&quot;&gt;5. Play vars (for the entire play)&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Variables defined within a play are in scope for the entire play.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;all&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;vars:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;var1:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;play_value&quot;&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;play&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;variable&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;debug:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;msg:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Play variable var1=&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ var1 }}&lt;/span&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-6-inventory-vars&quot;&gt;6. Inventory vars&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Variables defined in the inventory file.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example (INI-style inventory):&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-ini&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# inventory&lt;/span&gt;&lt;span class=&quot;hljs-section&quot;&gt;[all:vars]&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;var1&lt;/span&gt;=inventory_value&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Playbook:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;all&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;inventory&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;variable&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;debug:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;msg:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Inventory variable var1=&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ var1 }}&lt;/span&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-7-facts-gathered-or-set-via-setfact&quot;&gt;7. Facts (gathered or set via &lt;code&gt;set_fact&lt;/code&gt;)&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Facts are gathered by Ansible or set during playbook execution using &lt;code&gt;set_fact&lt;/code&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;all&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;fact&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;variable&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;set_fact:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;var1:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;fact_value&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;fact&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;variable&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;debug:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;msg:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Fact variable var1=&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ var1 }}&lt;/span&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-8-playbook-groupvars&quot;&gt;8. Playbook group_vars&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Variables defined for groups in the &lt;code&gt;group_vars&lt;/code&gt; directory within the playbook directory.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example (group_vars/all.yml):&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# group_vars/all.yml&lt;/span&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;var1:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;group_vars_value&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Playbook:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;all&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;group_vars&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;variable&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;debug:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;msg:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Group_vars variable var1=&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ var1 }}&lt;/span&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-9-playbook-hostvars&quot;&gt;9. Playbook host_vars&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Variables defined for individual hosts in the &lt;code&gt;host_vars&lt;/code&gt; directory within the playbook directory.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example (host_vars/hostname.yml):&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# host_vars/hostname.yml&lt;/span&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;var1:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;host_vars_value&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Playbook:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;hostname&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;host_vars&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;variable&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;debug:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;msg:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Host_vars variable var1=&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ var1 }}&lt;/span&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-10-ansible-configuration-settings&quot;&gt;10. Ansible configuration settings&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Variables set in the Ansible configuration files (e.g., &lt;code&gt;ansible.cfg&lt;/code&gt;).&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example (&lt;/strong&gt;&lt;code&gt;ansible.cfg&lt;/code&gt;):&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-ini&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# ansible.cfg&lt;/span&gt;&lt;span class=&quot;hljs-section&quot;&gt;[defaults]&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;var1&lt;/span&gt; = config_value&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Playbook:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;all&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;variable&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;debug:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;msg:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Config variable var1=&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ var1 }}&lt;/span&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-6-templates&quot;&gt;6. Templates&lt;/h3&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_templating.html&quot;&gt;&lt;strong&gt;Templates&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Jinja2 templates are used to create dynamic configuration files.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Variables can be embedded and will be replaced during execution.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example Template (templates/nginx.conf.j2):&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-plaintext&quot;&gt;server {    listen 80;    server_name {{ server_name }};    location / {        proxy_pass http://{{ backend }};    }}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Example Task Using Template:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Copy&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Nginx&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;config&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;template:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;src:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;templates/nginx.conf.j2&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;dest:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/etc/nginx/nginx.conf&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-7-handlers&quot;&gt;7. Handlers&lt;/h3&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_handlers.html&quot;&gt;&lt;strong&gt;Handlers&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Special tasks that are triggered by other tasks using the &lt;code&gt;notify&lt;/code&gt; directive.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Run once at the end of the playbook execution if notified.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Install&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Nginx&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;apt:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;state:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;present&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;notify:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Restart&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Nginx&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;handlers:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Restart&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Nginx&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;service:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;state:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;restarted&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Understanding these components allows for efficient and effective use of Ansible for automation tasks. Each component plays a crucial role in defining the structure and functionality of your automation scripts.&lt;/p&gt;&lt;h3 id=&quot;heading-references&quot;&gt;References:&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/&quot;&gt;Ansible Community Documentation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://www.ansible.com/how-ansible-works/&quot;&gt;Ansible Docs: How Ansible Works&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;]]&gt;</content:encoded><hashnode:content>&lt;![CDATA[&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://github.com/ansible/ansible&quot;&gt;Ansible&lt;/a&gt; is a powerful automation tool used for configuration management, application deployment, and task automation. It operates by connecting to your nodes and pushing out small programs, called &lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/2.9/user_guide/modules.html&quot;&gt;Ansible modules&lt;/a&gt;, to perform tasks.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://i.imgur.com/GimrSd7.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;Image credits: &lt;a target=&quot;_blank&quot; href=&quot;https://www.ansible.com/how-ansible-works/&quot;&gt;Ansible.com&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The main components of Ansible are:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/inventory_guide/intro_inventory.html&quot;&gt;&lt;strong&gt;Inventory&lt;/strong&gt;&lt;/a&gt;: A list of hosts or nodes that Ansible manages.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/2.9/modules/list_of_all_modules.html&quot;&gt;&lt;strong&gt;Modules&lt;/strong&gt;&lt;/a&gt;: Units of work that Ansible executes. Examples include tasks for installing packages, copying files, or restarting services.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/playbook_guide/playbooks.html&quot;&gt;&lt;strong&gt;Playbooks&lt;/strong&gt;&lt;/a&gt;: YAML files that define a series of tasks to be executed on a set of hosts.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_reuse_roles.html&quot;&gt;&lt;strong&gt;Roles&lt;/strong&gt;&lt;/a&gt;: A way to group multiple tasks and configurations to be reusable.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html&quot;&gt;&lt;strong&gt;Variables&lt;/strong&gt;&lt;/a&gt;: Used to store values that can be reused in playbooks and templates.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_templating.html&quot;&gt;&lt;strong&gt;Templates&lt;/strong&gt;&lt;/a&gt;: Files that have placeholders for variables and can be dynamically populated during execution.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_handlers.html&quot;&gt;&lt;strong&gt;Handlers&lt;/strong&gt;&lt;/a&gt;: Used to trigger actions at the end of a playbook run when certain conditions are met.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h2 id=&quot;heading-ansible-components-overview&quot;&gt;Ansible Components Overview&lt;/h2&gt;&lt;h3 id=&quot;heading-1-inventory&quot;&gt;1. Inventory&lt;/h3&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/inventory_guide/intro_inventory.html&quot;&gt;&lt;strong&gt;Inventory File&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;The default inventory file is usually named &lt;code&gt;hosts&lt;/code&gt; or &lt;code&gt;inventory&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;By default, it is located at &lt;code&gt;/etc/ansible/hosts&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;It can be a simple INI-style file or YAML file, listing the managed nodes.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;INI File:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;An &lt;code&gt;.ini&lt;/code&gt; file is a simple text file used for configuration, with sections, properties, and values.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;In the context of Ansible, it defines groups of hosts and their variables.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example (INI-style):&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-ini&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# Default inventory file location: /etc/ansible/hosts&lt;/span&gt;&lt;span class=&quot;hljs-section&quot;&gt;[webservers]&lt;/span&gt;web1.example.comweb2.example.com&lt;span class=&quot;hljs-section&quot;&gt;[databases]&lt;/span&gt;db1.example.com&lt;span class=&quot;hljs-comment&quot;&gt;# Defining variables for groups&lt;/span&gt;&lt;span class=&quot;hljs-section&quot;&gt;[webservers:vars]&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;ansible_user&lt;/span&gt;=admin&lt;span class=&quot;hljs-attr&quot;&gt;ansible_ssh_private_key_file&lt;/span&gt;=/path/to/key&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Example (YAML-style):&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;all:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;children:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;webservers:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;web1.example.com:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;web2.example.com:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;vars:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;ansible_user:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;admin&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;ansible_ssh_private_key_file:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/path/to/key&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;databases:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;db1.example.com:&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-2-modules&quot;&gt;2. Modules&lt;/h3&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/2.9/modules/list_of_all_modules.html&quot;&gt;&lt;strong&gt;Modules&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Small programs that Ansible pushes out to nodes to perform tasks. After programs finish the execution, Ansible removes them.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Examples include modules for package management (&lt;code&gt;apt&lt;/code&gt;, &lt;code&gt;yum&lt;/code&gt;), file operations (&lt;code&gt;copy&lt;/code&gt;, &lt;code&gt;template&lt;/code&gt;), and service management (&lt;code&gt;service&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Install&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Nginx&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;apt:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;state:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;present&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Command to list available modules:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-shell&quot;&gt;ansible-doc -l&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-3-playbooks&quot;&gt;3. Playbooks&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Playbooks:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;YAML files that define a series of tasks to be executed on hosts.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;They contain plays, each mapping a group of hosts to roles and tasks.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Important Parts:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;hosts&lt;/code&gt;: Specifies which hosts the playbook should run against.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;tasks&lt;/code&gt;: Defines a list of tasks to be executed.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;vars&lt;/code&gt;: Defines variables to be used within the playbook.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;handlers&lt;/code&gt;: Defines handlers that can be notified by tasks.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Configure&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;web&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;servers&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;webservers&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;vars:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;nginx_version:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;1.18&lt;/span&gt;&lt;span class=&quot;hljs-number&quot;&gt;.0&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Install&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Nginx&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;apt:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx={{&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx_version&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;}}&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;state:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;present&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Copy&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Nginx&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;config&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;template:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;src:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;templates/nginx.conf.j2&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;dest:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/etc/nginx/nginx.conf&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;notify:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Restart&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Nginx&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;handlers:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Restart&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Nginx&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;service:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;state:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;restarted&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-4-roles&quot;&gt;4. Roles&lt;/h3&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_reuse_roles.html&quot;&gt;&lt;strong&gt;Roles&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Provide a structured way to group tasks, handlers, files, templates, and variables.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Allow for reuse and sharing of Ansible content.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Role Directory Structure:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-plaintext&quot;&gt;roles/  webserver/    tasks/      main.yml    templates/      nginx.conf.j2    handlers/      main.yml    vars/      main.yml    defaults/      main.yml    files/    meta/      main.yml&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Example Task File (roles/webserver/tasks/main.yml):&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Install&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Nginx&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;apt:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;state:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;present&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The beauty of roles lies in their reusability. You can include the same role in multiple playbooks to automate the same configuration on different sets of servers. For example, like installing and configuring a web server (Apache or Nginx) or setting up a database (MySQL or PostgreSQL).&lt;/p&gt;&lt;p&gt;To include a role inside an Ansible playbook you can use &lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/collections/ansible/builtin/include_role_module.html&quot;&gt;&lt;code&gt;include_role&lt;/code&gt;&lt;/a&gt; module.&lt;/p&gt;&lt;p&gt;This is the recommended approach for Ansible versions 2.4 and later. It offers more control and clarity.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;ansible.builtin.include_role:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;myrole&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Run&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;tasks/other.yaml&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;instead&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&apos;main&apos;&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;ansible.builtin.include_role:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;myrole&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;tasks_from:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pass&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;variables&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;role&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;ansible.builtin.include_role:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;myrole&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;vars:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;rolevar1:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Use&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;role&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;loop&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;ansible.builtin.include_role:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&apos;&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ roleinputvar }}&lt;/span&gt;&apos;&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;loop:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&apos;&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ roleinput1 }}&lt;/span&gt;&apos;&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&apos;&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ roleinput2 }}&lt;/span&gt;&apos;&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;loop_control:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;loop_var:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;roleinputvar&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Conditional&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;role&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;ansible.builtin.include_role:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;myrole&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;when:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;idontwanttorun&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Apply&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;tags&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;tasks&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;within&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;included&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;file&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;ansible.builtin.include_role:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;install&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;apply:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;tags:&lt;/span&gt;        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;install&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tags:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;always&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-5-variables&quot;&gt;5. Variables&lt;/h3&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html&quot;&gt;&lt;strong&gt;Variables&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Used to store values that can be reused in playbooks, roles, and templates.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Can be defined in playbooks, inventories, roles, or passed via command line.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Variable Precedence (highest to lowest):&lt;/strong&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;Extra vars (command line &lt;code&gt;-e&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Task vars (only in scope for the task)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Block vars (only in scope for the block)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Role and include vars&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Play vars (for the entire play)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Inventory vars&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Facts (gathered or set via &lt;code&gt;set_fact&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Playbook group_vars&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Playbook host_vars&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Ansible configuration settings&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;To learn more about variables check out this article: &lt;a target=&quot;_blank&quot; href=&quot;https://spacelift.io/blog/ansible-variables&quot;&gt;How to Use Different Types of Ansible Variables (Examples)&lt;/a&gt;&lt;/p&gt;&lt;h3 id=&quot;heading-1-extra-vars-command-line-e&quot;&gt;1. Extra vars (command line &lt;code&gt;-e&lt;/code&gt;)&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Extra variables passed directly on the command line have the highest precedence.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-shell&quot;&gt;ansible-playbook playbook.yml -e &quot;var1=value1 var2=value2&quot;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Playbook (playbook.yml):&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;all&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;debug:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;msg:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;var1=&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ var1 }}&lt;/span&gt;, var2=&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ var2 }}&lt;/span&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-2-task-vars-only-in-scope-for-the-task&quot;&gt;2. Task vars (only in scope for the task)&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Variables defined within a specific task have a very high precedence.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;all&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;variable&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;debug:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;msg:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Task variable var1=&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ var1 }}&lt;/span&gt;&quot;&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;vars:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;var1:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;task_value&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-3-block-vars-only-in-scope-for-the-block&quot;&gt;3. Block vars (only in scope for the block)&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Variables defined within a block are in scope only for tasks within that block.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;all&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;block:&lt;/span&gt;        &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;block&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;variable&lt;/span&gt;          &lt;span class=&quot;hljs-attr&quot;&gt;debug:&lt;/span&gt;            &lt;span class=&quot;hljs-attr&quot;&gt;msg:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Block variable var1=&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ var1 }}&lt;/span&gt;&quot;&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;vars:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;var1:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;block_value&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To learn more, check out &quot;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_blocks.html#blocks&quot;&gt;Blocks&lt;/a&gt;&quot;&lt;/p&gt;&lt;h3 id=&quot;heading-4-role-and-include-vars&quot;&gt;4. Role and include vars&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Variables defined within roles or included files.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# roles/webserver/vars/main.yml&lt;/span&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;var1:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;role_value&quot;&lt;/span&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# playbook.yml&lt;/span&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;all&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;roles:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;role:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;webserver&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;debug:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;msg:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Role variable var1=&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ var1 }}&lt;/span&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-5-play-vars-for-the-entire-play&quot;&gt;5. Play vars (for the entire play)&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Variables defined within a play are in scope for the entire play.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;all&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;vars:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;var1:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;play_value&quot;&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;play&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;variable&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;debug:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;msg:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Play variable var1=&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ var1 }}&lt;/span&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-6-inventory-vars&quot;&gt;6. Inventory vars&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Variables defined in the inventory file.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example (INI-style inventory):&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-ini&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# inventory&lt;/span&gt;&lt;span class=&quot;hljs-section&quot;&gt;[all:vars]&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;var1&lt;/span&gt;=inventory_value&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Playbook:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;all&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;inventory&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;variable&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;debug:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;msg:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Inventory variable var1=&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ var1 }}&lt;/span&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-7-facts-gathered-or-set-via-setfact&quot;&gt;7. Facts (gathered or set via &lt;code&gt;set_fact&lt;/code&gt;)&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Facts are gathered by Ansible or set during playbook execution using &lt;code&gt;set_fact&lt;/code&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;all&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Set&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;fact&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;variable&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;set_fact:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;var1:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;fact_value&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;fact&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;variable&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;debug:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;msg:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Fact variable var1=&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ var1 }}&lt;/span&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-8-playbook-groupvars&quot;&gt;8. Playbook group_vars&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Variables defined for groups in the &lt;code&gt;group_vars&lt;/code&gt; directory within the playbook directory.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example (group_vars/all.yml):&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# group_vars/all.yml&lt;/span&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;var1:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;group_vars_value&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Playbook:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;all&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;group_vars&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;variable&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;debug:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;msg:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Group_vars variable var1=&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ var1 }}&lt;/span&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-9-playbook-hostvars&quot;&gt;9. Playbook host_vars&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Variables defined for individual hosts in the &lt;code&gt;host_vars&lt;/code&gt; directory within the playbook directory.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example (host_vars/hostname.yml):&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# host_vars/hostname.yml&lt;/span&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;var1:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;host_vars_value&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Playbook:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;hostname&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;host_vars&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;variable&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;debug:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;msg:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Host_vars variable var1=&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ var1 }}&lt;/span&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-10-ansible-configuration-settings&quot;&gt;10. Ansible configuration settings&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Variables set in the Ansible configuration files (e.g., &lt;code&gt;ansible.cfg&lt;/code&gt;).&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example (&lt;/strong&gt;&lt;code&gt;ansible.cfg&lt;/code&gt;):&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-ini&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# ansible.cfg&lt;/span&gt;&lt;span class=&quot;hljs-section&quot;&gt;[defaults]&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;var1&lt;/span&gt; = config_value&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Playbook:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-meta&quot;&gt;---&lt;/span&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;hosts:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;all&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tasks:&lt;/span&gt;    &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Show&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;variable&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;debug:&lt;/span&gt;        &lt;span class=&quot;hljs-attr&quot;&gt;msg:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Config variable var1=&lt;span class=&quot;hljs-template-variable&quot;&gt;{{ var1 }}&lt;/span&gt;&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-6-templates&quot;&gt;6. Templates&lt;/h3&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_templating.html&quot;&gt;&lt;strong&gt;Templates&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Jinja2 templates are used to create dynamic configuration files.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Variables can be embedded and will be replaced during execution.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example Template (templates/nginx.conf.j2):&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-plaintext&quot;&gt;server {    listen 80;    server_name {{ server_name }};    location / {        proxy_pass http://{{ backend }};    }}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Example Task Using Template:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Copy&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Nginx&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;config&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;template:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;src:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;templates/nginx.conf.j2&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;dest:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;/etc/nginx/nginx.conf&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;heading-7-handlers&quot;&gt;7. Handlers&lt;/h3&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_handlers.html&quot;&gt;&lt;strong&gt;Handlers&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Special tasks that are triggered by other tasks using the &lt;code&gt;notify&lt;/code&gt; directive.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Run once at the end of the playbook execution if notified.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Install&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Nginx&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;apt:&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;state:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;present&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;notify:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Restart&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Nginx&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;handlers:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Restart&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Nginx&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;service:&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx&lt;/span&gt;      &lt;span class=&quot;hljs-attr&quot;&gt;state:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;restarted&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Understanding these components allows for efficient and effective use of Ansible for automation tasks. Each component plays a crucial role in defining the structure and functionality of your automation scripts.&lt;/p&gt;&lt;h3 id=&quot;heading-references&quot;&gt;References:&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://docs.ansible.com/&quot;&gt;Ansible Community Documentation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://www.ansible.com/how-ansible-works/&quot;&gt;Ansible Docs: How Ansible Works&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;]]&gt;</hashnode:content><hashnode:coverImage>https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/NLSXFjl_nhc/upload/fa111dad5ce47518af4c3c5e47ac4473.jpeg</hashnode:coverImage></item><item><title><![CDATA[Kubernetes Troubleshooting: Disk Pressure Taint]]></title><description><![CDATA[Kubernetes Troubleshooting: Disk Pressure Taint]]></description><link>https://maxat-akbanov.com/kubernetes-troubleshooting-disk-pressure-taint</link><guid isPermaLink="true">https://maxat-akbanov.com/kubernetes-troubleshooting-disk-pressure-taint</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[disk]]></category><category><![CDATA[Devops]]></category><category><![CDATA[sysops]]></category><dc:creator><![CDATA[Maxat Akbanov]]></dc:creator><pubDate>Mon, 20 May 2024 05:30:44 GMT</pubDate><content:encoded>&lt;![CDATA[&lt;p&gt;In Kubernetes, a &quot;&lt;a target=&quot;_blank&quot; href=&quot;https://maxat-akbanov.com/get-started-with-taints-and-tolerations-in-kubernetes&quot;&gt;taint&lt;/a&gt;&quot; is a way to mark a node with a specific attribute that repels pods from being scheduled on it, unless those pods have a matching &quot;toleration&quot; for the taint. The term &quot;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/scheduling-eviction/node-pressure-eviction/#node-conditions&quot;&gt;disk pressure taint&lt;/a&gt;&quot; refers to a specific condition where a node is experiencing low disk space. This taint is automatically added by Kubernetes to nodes that are nearing their storage capacity limits to prevent new pods from being scheduled on them, which helps in maintaining the node&apos;s performance and stability by avoiding additional strain on its disk resources.&lt;/p&gt;&lt;p&gt;This mechanism ensures that pods are scheduled on nodes with sufficient disk space, maintaining overall cluster health and performance. When disk space is freed or increased, the disk pressure condition may be resolved, and the taint can be removed, allowing pods to be scheduled on the node again.&lt;/p&gt;&lt;h3 id=&quot;heading-reasons&quot;&gt;Reasons&lt;/h3&gt;&lt;p&gt;The disk pressure warning in Kubernetes signals that a node is running low on disk space or inode capacity. This condition can arise due to various factors, often related to resource usage and management within the cluster. Here are some common reasons for a disk pressure warning:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;High Container Log Volume&lt;/strong&gt;: Containers can generate substantial log output, especially if verbose logging is enabled. If not managed properly, these logs can fill up the nodes disk space.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Unused or Dangling Docker Images&lt;/strong&gt;: Over time, Docker images and containers that are no longer in use can accumulate, especially if images are frequently updated. These unused images take up significant disk space.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Persistent Volume Claims (PVCs)&lt;/strong&gt;: Persistent volumes associated with PVCs can consume a large amount of disk space, particularly if many stateful applications are running within the cluster.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Evicted Pods&lt;/strong&gt;: When pods are evicted due to resource constraints, their data might still reside on the node, consuming space. This is especially relevant if the pods were using ephemeral volumes or if the logs of these evicted pods are not cleaned up.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Node-Level Application Data&lt;/strong&gt;: Applications might write data directly to the nodes filesystem, outside of what Kubernetes manages, which can accumulate over time.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Temporary Files&lt;/strong&gt;: Applications or systems processes may create temporary files that arent cleaned up properly, leading to gradual space consumption.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;System Logs and Backups&lt;/strong&gt;: System operations, diagnostics, backups, and logs can take up significant space. These often grow over time unless log rotation and cleanup policies are in place.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Improper Resource Quotas&lt;/strong&gt;: If resource quotas and limits arent set properly, a single namespace or application can end up using an undue portion of disk resources, leading to disk pressure.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;To manage and mitigate these issues, administrators should implement monitoring and alerting for disk usage, enforce appropriate resource quotas, manage log lifecycles, and periodically clean up unused images and volumes. This proactive management helps maintain node health and prevents disruptions due to disk pressure.&lt;/p&gt;&lt;h3 id=&quot;heading-collecting-information-about-disk-pressure&quot;&gt;Collecting Information About Disk Pressure&lt;/h3&gt;&lt;p&gt;Kubernetes monitors and manages the state of nodes through a component called the &lt;strong&gt;kubelet&lt;/strong&gt;, which runs on each node in the cluster. The kubelet is responsible for a variety of node management tasks, including monitoring the health and resource status of the node it runs on.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1716172249058/20afb0ae-e6b0-4592-aa4a-9b4379c307a5.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;Image credits: &lt;a target=&quot;_blank&quot; href=&quot;https://blog.kubesimplify.com/understanding-the-architecture-of-kubernetes-a-beginners-guide&quot;&gt;kubesimplify&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Heres how kubelet specifically handles disk space and detects disk pressure:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resource Metrics&lt;/strong&gt;: The kubelet collects metrics about the node&apos;s resources, including CPU, memory, and disk utilization. For disk resources, it monitors the filesystem that houses the node&apos;s Docker images and container writable layers, as well as the filesystem used for the nodes main processes.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Thresholds and Conditions&lt;/strong&gt;: Administrators can set thresholds for what constitutes disk pressure in terms of available disk space and inode counts. These thresholds are part of the kubelet&apos;s configuration. When the disk usage exceeds these thresholds, the kubelet identifies this as a disk pressure condition.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Node Status&lt;/strong&gt;: If the kubelet detects that disk usage exceeds the configured thresholds, it updates the node&apos;s status to reflect that it is under disk pressure. This status update includes adding a taint to the node that prevents new pods from being scheduled unless they tolerate this taint.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reporting&lt;/strong&gt;: The kubelet regularly reports the node status, including any resource pressure conditions, back to the Kubernetes API server. This information is then used by the scheduler and other control plane components to make decisions about pod placement and cluster management.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automatic Eviction&lt;/strong&gt;: In some cases, if the disk pressure persists, the kubelet may start to evict pods to free up disk space, prioritizing the eviction based on factors such as the quality of service (QoS) class of the pods.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;This proactive monitoring and management help maintain the stability and performance of the Kubernetes cluster by ensuring nodes operate within their resource limits.&lt;/p&gt;&lt;h3 id=&quot;heading-get-information-about-disk-pressure&quot;&gt;Get Information about Disk Pressure&lt;/h3&gt;&lt;p&gt;To find out which node in a Kubernetes cluster is affected by disk pressure, you can use the &lt;code&gt;kubectl&lt;/code&gt; command-line tool to inspect the nodes&apos; status. Here&apos;s how you can identify nodes with disk pressure:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;List Node Conditions&lt;/strong&gt;: You can list all nodes along with their conditions by running:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; kubectl get nodes -o wide&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; However, for more detailed information about the conditions affecting each node, including disk pressure, you can use:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; kubectl get nodes -o jsonpath=&lt;span class=&quot;hljs-string&quot;&gt;&quot;{.items[*].status.conditions}&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; This command displays all conditions for each node. Look for conditions where the &lt;code&gt;type&lt;/code&gt; is &lt;code&gt;DiskPressure&lt;/code&gt; and the &lt;code&gt;status&lt;/code&gt; is &lt;code&gt;True&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Specifically Check for Disk Pressure&lt;/strong&gt;: To filter and show only nodes under disk pressure, you can use a more refined command:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; kubectl get nodes -o jsonpath=&lt;span class=&quot;hljs-string&quot;&gt;&quot;{.items[?(@.status.conditions[?(@.type==&apos;DiskPressure&apos; &amp;amp;&amp;amp; @.status==&apos;True&apos;)])].metadata.name}&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; This command will output the names of nodes where the disk pressure condition is currently &lt;code&gt;True&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Describe Nodes&lt;/strong&gt;: For a more verbose and comprehensive look at a particular nodes status, including events and conditions like disk pressure, you can use the describe command:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; kubectl describe node &amp;lt;node-name&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; Replace &lt;code&gt;&amp;lt;node-name&amp;gt;&lt;/code&gt; with the name of the node you want to inspect. The output will include all conditions, events, and other details specific to that node, helping you understand why disk pressure is being reported.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;These commands help you identify and diagnose nodes experiencing disk pressure, allowing you to take appropriate actions such as cleaning up disk space or adjusting resource allocations.&lt;/p&gt;&lt;h3 id=&quot;heading-clean-up-disk-space-on-the-node&quot;&gt;Clean-up Disk Space on the Node&lt;/h3&gt;&lt;p&gt;Cleaning up disk space on a Kubernetes node involves several strategies, depending on what&apos;s consuming the space. Here are some common approaches:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Prune Unused Docker Images and Containers&lt;/strong&gt;: Over time, Docker can accumulate unused images and containers, which can consume considerable disk space. Use the following Docker commands to clean them up:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; docker system prune -a&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; This command removes all unused containers, networks, images (both dangling and unreferenced), and optionally, volumes.&lt;/p&gt; &lt;div data-node-type=&quot;callout&quot;&gt; &lt;div data-node-type=&quot;callout-emoji&quot;&gt;&lt;/div&gt; &lt;div data-node-type=&quot;callout-text&quot;&gt;&lt;strong&gt;It&apos;s a good practice to ensure that you do not need the data in these containers or images before running this command.&lt;/strong&gt;&lt;/div&gt; &lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clear Kubernetes Evicted Pods&lt;/strong&gt;: Sometimes, when a node is under resource pressure, Kubernetes may evict pods but their metadata might still remain. You can clear evicted pods with:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; kubectl get pods --all-namespaces -o json | jq &lt;span class=&quot;hljs-string&quot;&gt;&apos;.items[] | select(.status.phase == &quot;Failed&quot;) | &quot;kubectl delete pods \(.metadata.name) --namespace \(.metadata.namespace)&quot;&apos;&lt;/span&gt; | xargs -n 1 bash -c&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clean Up Node Filesystem&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Logs&lt;/strong&gt;: System and application logs can consume significant disk space. You might want to clean or rotate logs managed under &lt;code&gt;/var/log/&lt;/code&gt;, or set up a log rotation policy if not already in place.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Temporary Files&lt;/strong&gt;: The &lt;code&gt;/tmp&lt;/code&gt; directory often contains temporary files which might not be necessary. Consider deleting older or unnecessary files.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Orphaned Volumes&lt;/strong&gt;: Check for any orphaned volumes in &lt;code&gt;/var/lib/kubelet/pods/&lt;/code&gt; and remove them if they are no longer linked to existing pods.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Manage Persistent Volume Claims (PVCs)&lt;/strong&gt;: Review persistent volume claims and their associated volumes. Sometimes, unused or old PVCs can be deleted to free up space. Use:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; kubectl get pvc --all-namespaces&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; to list all PVCs. Review and delete any that are unnecessary.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use a Resource Quota&lt;/strong&gt;: To avoid future disk space issues, consider setting resource quotas and limits for namespaces to better manage the space used by each project or team.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Node Monitoring and Alerts&lt;/strong&gt;: Implement monitoring and alerting for disk usage to proactively manage disk space and prevent nodes from hitting disk pressure.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div data-node-type=&quot;callout&quot;&gt;&lt;div data-node-type=&quot;callout-emoji&quot;&gt;&lt;/div&gt;&lt;div data-node-type=&quot;callout-text&quot;&gt;Before performing these cleanup tasks, especially in a production environment, ensure you have backups as needed and that the deletions will not affect running applications. It&apos;s also wise to test these actions in a staging environment before executing them in production.&lt;/div&gt;&lt;/div&gt;&lt;h3 id=&quot;heading-how-to-check-the-log-file-sizes-for-docker-and-podman-on-nodes&quot;&gt;How to Check the Log File Sizes for Docker and Podman on Nodes&lt;/h3&gt;&lt;p&gt;When investigating disk pressure in a Kubernetes cluster and you suspect that logs from container runtimes like Docker and Podman are consuming a significant amount of disk space, you can check the log sizes directly on the nodes. Heres how to do it for both Docker and Podman:&lt;/p&gt;&lt;h3 id=&quot;heading-for-docker&quot;&gt;For Docker&lt;/h3&gt;&lt;p&gt;Docker typically stores its logs in the container&apos;s directory under &lt;code&gt;/var/lib/docker/containers/&lt;/code&gt;. Each container has its own directory here, containing log files. To find out the size of these logs:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;SSH into the Node&lt;/strong&gt;: Log into the node where Docker is running.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Run a Command to Summarize Log Sizes&lt;/strong&gt;: Use the following command to find the total size of all log files:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; sudo du -sh /var/lib/docker/containers/*/*-json.log&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; This command sums up the sizes of all Docker log files. It can be helpful to run this on each node to determine where the largest log files are.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-for-podman&quot;&gt;For Podman&lt;/h3&gt;&lt;p&gt;Podman stores its logs under &lt;code&gt;/var/lib/containers/storage/overlay-containers/&lt;/code&gt; in each container&apos;s directory. Similar to Docker, you can inspect the sizes of these logs:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;SSH into the Node&lt;/strong&gt;: Access the node where Podman containers are running.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Run a Command to Summarize Log Sizes&lt;/strong&gt;: Execute the following to find out how much space the log files are using:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; sudo du -sh /var/lib/containers/storage/overlay-containers/*/userdata/ctr.log&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; This will display the sizes of all Podman container log files.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-references&quot;&gt;References:&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/scheduling-eviction/node-pressure-eviction/&quot;&gt;Kubernetes Documentation: Node-pressure Eviction&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://neilcameronwhite.medium.com/under-disk-pressure-34b5ba4284b6&quot;&gt;Medium Blog: Under Disk Pressure&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;]]&gt;</content:encoded><hashnode:content>&lt;![CDATA[&lt;p&gt;In Kubernetes, a &quot;&lt;a target=&quot;_blank&quot; href=&quot;https://maxat-akbanov.com/get-started-with-taints-and-tolerations-in-kubernetes&quot;&gt;taint&lt;/a&gt;&quot; is a way to mark a node with a specific attribute that repels pods from being scheduled on it, unless those pods have a matching &quot;toleration&quot; for the taint. The term &quot;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/scheduling-eviction/node-pressure-eviction/#node-conditions&quot;&gt;disk pressure taint&lt;/a&gt;&quot; refers to a specific condition where a node is experiencing low disk space. This taint is automatically added by Kubernetes to nodes that are nearing their storage capacity limits to prevent new pods from being scheduled on them, which helps in maintaining the node&apos;s performance and stability by avoiding additional strain on its disk resources.&lt;/p&gt;&lt;p&gt;This mechanism ensures that pods are scheduled on nodes with sufficient disk space, maintaining overall cluster health and performance. When disk space is freed or increased, the disk pressure condition may be resolved, and the taint can be removed, allowing pods to be scheduled on the node again.&lt;/p&gt;&lt;h3 id=&quot;heading-reasons&quot;&gt;Reasons&lt;/h3&gt;&lt;p&gt;The disk pressure warning in Kubernetes signals that a node is running low on disk space or inode capacity. This condition can arise due to various factors, often related to resource usage and management within the cluster. Here are some common reasons for a disk pressure warning:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;High Container Log Volume&lt;/strong&gt;: Containers can generate substantial log output, especially if verbose logging is enabled. If not managed properly, these logs can fill up the nodes disk space.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Unused or Dangling Docker Images&lt;/strong&gt;: Over time, Docker images and containers that are no longer in use can accumulate, especially if images are frequently updated. These unused images take up significant disk space.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Persistent Volume Claims (PVCs)&lt;/strong&gt;: Persistent volumes associated with PVCs can consume a large amount of disk space, particularly if many stateful applications are running within the cluster.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Evicted Pods&lt;/strong&gt;: When pods are evicted due to resource constraints, their data might still reside on the node, consuming space. This is especially relevant if the pods were using ephemeral volumes or if the logs of these evicted pods are not cleaned up.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Node-Level Application Data&lt;/strong&gt;: Applications might write data directly to the nodes filesystem, outside of what Kubernetes manages, which can accumulate over time.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Temporary Files&lt;/strong&gt;: Applications or systems processes may create temporary files that arent cleaned up properly, leading to gradual space consumption.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;System Logs and Backups&lt;/strong&gt;: System operations, diagnostics, backups, and logs can take up significant space. These often grow over time unless log rotation and cleanup policies are in place.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Improper Resource Quotas&lt;/strong&gt;: If resource quotas and limits arent set properly, a single namespace or application can end up using an undue portion of disk resources, leading to disk pressure.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;To manage and mitigate these issues, administrators should implement monitoring and alerting for disk usage, enforce appropriate resource quotas, manage log lifecycles, and periodically clean up unused images and volumes. This proactive management helps maintain node health and prevents disruptions due to disk pressure.&lt;/p&gt;&lt;h3 id=&quot;heading-collecting-information-about-disk-pressure&quot;&gt;Collecting Information About Disk Pressure&lt;/h3&gt;&lt;p&gt;Kubernetes monitors and manages the state of nodes through a component called the &lt;strong&gt;kubelet&lt;/strong&gt;, which runs on each node in the cluster. The kubelet is responsible for a variety of node management tasks, including monitoring the health and resource status of the node it runs on.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1716172249058/20afb0ae-e6b0-4592-aa4a-9b4379c307a5.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;Image credits: &lt;a target=&quot;_blank&quot; href=&quot;https://blog.kubesimplify.com/understanding-the-architecture-of-kubernetes-a-beginners-guide&quot;&gt;kubesimplify&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Heres how kubelet specifically handles disk space and detects disk pressure:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resource Metrics&lt;/strong&gt;: The kubelet collects metrics about the node&apos;s resources, including CPU, memory, and disk utilization. For disk resources, it monitors the filesystem that houses the node&apos;s Docker images and container writable layers, as well as the filesystem used for the nodes main processes.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Thresholds and Conditions&lt;/strong&gt;: Administrators can set thresholds for what constitutes disk pressure in terms of available disk space and inode counts. These thresholds are part of the kubelet&apos;s configuration. When the disk usage exceeds these thresholds, the kubelet identifies this as a disk pressure condition.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Node Status&lt;/strong&gt;: If the kubelet detects that disk usage exceeds the configured thresholds, it updates the node&apos;s status to reflect that it is under disk pressure. This status update includes adding a taint to the node that prevents new pods from being scheduled unless they tolerate this taint.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reporting&lt;/strong&gt;: The kubelet regularly reports the node status, including any resource pressure conditions, back to the Kubernetes API server. This information is then used by the scheduler and other control plane components to make decisions about pod placement and cluster management.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automatic Eviction&lt;/strong&gt;: In some cases, if the disk pressure persists, the kubelet may start to evict pods to free up disk space, prioritizing the eviction based on factors such as the quality of service (QoS) class of the pods.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;This proactive monitoring and management help maintain the stability and performance of the Kubernetes cluster by ensuring nodes operate within their resource limits.&lt;/p&gt;&lt;h3 id=&quot;heading-get-information-about-disk-pressure&quot;&gt;Get Information about Disk Pressure&lt;/h3&gt;&lt;p&gt;To find out which node in a Kubernetes cluster is affected by disk pressure, you can use the &lt;code&gt;kubectl&lt;/code&gt; command-line tool to inspect the nodes&apos; status. Here&apos;s how you can identify nodes with disk pressure:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;List Node Conditions&lt;/strong&gt;: You can list all nodes along with their conditions by running:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; kubectl get nodes -o wide&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; However, for more detailed information about the conditions affecting each node, including disk pressure, you can use:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; kubectl get nodes -o jsonpath=&lt;span class=&quot;hljs-string&quot;&gt;&quot;{.items[*].status.conditions}&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; This command displays all conditions for each node. Look for conditions where the &lt;code&gt;type&lt;/code&gt; is &lt;code&gt;DiskPressure&lt;/code&gt; and the &lt;code&gt;status&lt;/code&gt; is &lt;code&gt;True&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Specifically Check for Disk Pressure&lt;/strong&gt;: To filter and show only nodes under disk pressure, you can use a more refined command:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; kubectl get nodes -o jsonpath=&lt;span class=&quot;hljs-string&quot;&gt;&quot;{.items[?(@.status.conditions[?(@.type==&apos;DiskPressure&apos; &amp;amp;&amp;amp; @.status==&apos;True&apos;)])].metadata.name}&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; This command will output the names of nodes where the disk pressure condition is currently &lt;code&gt;True&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Describe Nodes&lt;/strong&gt;: For a more verbose and comprehensive look at a particular nodes status, including events and conditions like disk pressure, you can use the describe command:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; kubectl describe node &amp;lt;node-name&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; Replace &lt;code&gt;&amp;lt;node-name&amp;gt;&lt;/code&gt; with the name of the node you want to inspect. The output will include all conditions, events, and other details specific to that node, helping you understand why disk pressure is being reported.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;These commands help you identify and diagnose nodes experiencing disk pressure, allowing you to take appropriate actions such as cleaning up disk space or adjusting resource allocations.&lt;/p&gt;&lt;h3 id=&quot;heading-clean-up-disk-space-on-the-node&quot;&gt;Clean-up Disk Space on the Node&lt;/h3&gt;&lt;p&gt;Cleaning up disk space on a Kubernetes node involves several strategies, depending on what&apos;s consuming the space. Here are some common approaches:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Prune Unused Docker Images and Containers&lt;/strong&gt;: Over time, Docker can accumulate unused images and containers, which can consume considerable disk space. Use the following Docker commands to clean them up:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; docker system prune -a&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; This command removes all unused containers, networks, images (both dangling and unreferenced), and optionally, volumes.&lt;/p&gt; &lt;div data-node-type=&quot;callout&quot;&gt; &lt;div data-node-type=&quot;callout-emoji&quot;&gt;&lt;/div&gt; &lt;div data-node-type=&quot;callout-text&quot;&gt;&lt;strong&gt;It&apos;s a good practice to ensure that you do not need the data in these containers or images before running this command.&lt;/strong&gt;&lt;/div&gt; &lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clear Kubernetes Evicted Pods&lt;/strong&gt;: Sometimes, when a node is under resource pressure, Kubernetes may evict pods but their metadata might still remain. You can clear evicted pods with:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; kubectl get pods --all-namespaces -o json | jq &lt;span class=&quot;hljs-string&quot;&gt;&apos;.items[] | select(.status.phase == &quot;Failed&quot;) | &quot;kubectl delete pods \(.metadata.name) --namespace \(.metadata.namespace)&quot;&apos;&lt;/span&gt; | xargs -n 1 bash -c&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clean Up Node Filesystem&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Logs&lt;/strong&gt;: System and application logs can consume significant disk space. You might want to clean or rotate logs managed under &lt;code&gt;/var/log/&lt;/code&gt;, or set up a log rotation policy if not already in place.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Temporary Files&lt;/strong&gt;: The &lt;code&gt;/tmp&lt;/code&gt; directory often contains temporary files which might not be necessary. Consider deleting older or unnecessary files.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Orphaned Volumes&lt;/strong&gt;: Check for any orphaned volumes in &lt;code&gt;/var/lib/kubelet/pods/&lt;/code&gt; and remove them if they are no longer linked to existing pods.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Manage Persistent Volume Claims (PVCs)&lt;/strong&gt;: Review persistent volume claims and their associated volumes. Sometimes, unused or old PVCs can be deleted to free up space. Use:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; kubectl get pvc --all-namespaces&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; to list all PVCs. Review and delete any that are unnecessary.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use a Resource Quota&lt;/strong&gt;: To avoid future disk space issues, consider setting resource quotas and limits for namespaces to better manage the space used by each project or team.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Node Monitoring and Alerts&lt;/strong&gt;: Implement monitoring and alerting for disk usage to proactively manage disk space and prevent nodes from hitting disk pressure.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div data-node-type=&quot;callout&quot;&gt;&lt;div data-node-type=&quot;callout-emoji&quot;&gt;&lt;/div&gt;&lt;div data-node-type=&quot;callout-text&quot;&gt;Before performing these cleanup tasks, especially in a production environment, ensure you have backups as needed and that the deletions will not affect running applications. It&apos;s also wise to test these actions in a staging environment before executing them in production.&lt;/div&gt;&lt;/div&gt;&lt;h3 id=&quot;heading-how-to-check-the-log-file-sizes-for-docker-and-podman-on-nodes&quot;&gt;How to Check the Log File Sizes for Docker and Podman on Nodes&lt;/h3&gt;&lt;p&gt;When investigating disk pressure in a Kubernetes cluster and you suspect that logs from container runtimes like Docker and Podman are consuming a significant amount of disk space, you can check the log sizes directly on the nodes. Heres how to do it for both Docker and Podman:&lt;/p&gt;&lt;h3 id=&quot;heading-for-docker&quot;&gt;For Docker&lt;/h3&gt;&lt;p&gt;Docker typically stores its logs in the container&apos;s directory under &lt;code&gt;/var/lib/docker/containers/&lt;/code&gt;. Each container has its own directory here, containing log files. To find out the size of these logs:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;SSH into the Node&lt;/strong&gt;: Log into the node where Docker is running.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Run a Command to Summarize Log Sizes&lt;/strong&gt;: Use the following command to find the total size of all log files:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; sudo du -sh /var/lib/docker/containers/*/*-json.log&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; This command sums up the sizes of all Docker log files. It can be helpful to run this on each node to determine where the largest log files are.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-for-podman&quot;&gt;For Podman&lt;/h3&gt;&lt;p&gt;Podman stores its logs under &lt;code&gt;/var/lib/containers/storage/overlay-containers/&lt;/code&gt; in each container&apos;s directory. Similar to Docker, you can inspect the sizes of these logs:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;SSH into the Node&lt;/strong&gt;: Access the node where Podman containers are running.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Run a Command to Summarize Log Sizes&lt;/strong&gt;: Execute the following to find out how much space the log files are using:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt; sudo du -sh /var/lib/containers/storage/overlay-containers/*/userdata/ctr.log&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; This will display the sizes of all Podman container log files.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;heading-references&quot;&gt;References:&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/scheduling-eviction/node-pressure-eviction/&quot;&gt;Kubernetes Documentation: Node-pressure Eviction&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://neilcameronwhite.medium.com/under-disk-pressure-34b5ba4284b6&quot;&gt;Medium Blog: Under Disk Pressure&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;]]&gt;</hashnode:content><hashnode:coverImage>https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/4u6TUbreFc0/upload/33a1b7fdd8484d9ed7942ba9dd677b66.jpeg</hashnode:coverImage></item><item><title><![CDATA[Get started with Taints and Tolerations in Kubernetes]]></title><description><![CDATA[Get started with Taints and Tolerations in Kubernetes]]></description><link>https://maxat-akbanov.com/get-started-with-taints-and-tolerations-in-kubernetes</link><guid isPermaLink="true">https://maxat-akbanov.com/get-started-with-taints-and-tolerations-in-kubernetes</guid><category><![CDATA[Devops]]></category><category><![CDATA[sysops]]></category><category><![CDATA[Taints and Toleration]]></category><category><![CDATA[Kubernetes]]></category><dc:creator><![CDATA[Maxat Akbanov]]></dc:creator><pubDate>Mon, 20 May 2024 02:10:18 GMT</pubDate><content:encoded>&lt;![CDATA[&lt;p&gt;In Kubernetes, &lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/&quot;&gt;&lt;strong&gt;taints&lt;/strong&gt;&lt;/a&gt; and &lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/&quot;&gt;&lt;strong&gt;tolerations&lt;/strong&gt;&lt;/a&gt; are two distinct concepts used together to control how pods are scheduled on nodes. They help ensure that pods are only scheduled on appropriate nodes.&lt;/p&gt;&lt;h3 id=&quot;heading-taints-marking-nodes&quot;&gt;Taints (Marking Nodes)&lt;/h3&gt;&lt;p&gt;A &lt;strong&gt;taint&lt;/strong&gt; is applied to a node to mark it as repelling pods, unless those pods explicitly tolerate the taint. Taints have three properties:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Key&lt;/strong&gt;: The name of the taint.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Value&lt;/strong&gt;: The value associated with the taint, providing additional specificity.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Effect&lt;/strong&gt;: Describes what happens to pods that do not tolerate the taint. The effects can be:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;NoSchedule&lt;/code&gt;: Pods that do not tolerate this taint are not scheduled on the node. Pods currently running on the node are &lt;strong&gt;not&lt;/strong&gt; evicted.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;PreferNoSchedule&lt;/code&gt;: Kubernetes will try to avoid placing a pod on the node but it&apos;s not guaranteed.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;NoExecute&lt;/code&gt;: Pods that do not tolerate this taint are evicted if they are already running on the node, and new pods will not be scheduled on the node.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-tolerations-specifying-pod-compatibility&quot;&gt;Tolerations (Specifying Pod Compatibility)&lt;/h3&gt;&lt;p&gt;A &lt;strong&gt;toleration&lt;/strong&gt; is applied to a pod and allows (but does not require) the pod to be scheduled on a node with matching taints. Tolerations specify which taints they can accept. They consist of:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Key&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Value&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Effect&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Operator&lt;/strong&gt;: Determines how to match the taint&apos;s key and value. Commonly used operators include &lt;code&gt;Equal&lt;/code&gt; (default) and &lt;code&gt;Exists&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;TolerationSeconds&lt;/strong&gt;: Only relevant with the &lt;code&gt;NoExecute&lt;/code&gt; effect, this specifies how long a pod should stay on the node after the taint appears.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;A toleration &quot;matches&quot; a taint if the keys are the same and the effects are the same, and:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;the &lt;code&gt;operator&lt;/code&gt; is &lt;code&gt;Exists&lt;/code&gt; (in which case no &lt;code&gt;value&lt;/code&gt; should be specified), or&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;the &lt;code&gt;operator&lt;/code&gt; is &lt;code&gt;Equal&lt;/code&gt; and the values should be equal.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The default value for &lt;code&gt;operator&lt;/code&gt; is &lt;code&gt;Equal&lt;/code&gt;.&lt;/p&gt;&lt;h3 id=&quot;heading-differences&quot;&gt;Differences&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Where they apply&lt;/strong&gt;: Taints are applied to nodes, while tolerations are applied to pods.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Purpose&lt;/strong&gt;: Taints make a node repulsive to certain pods, while tolerations make a pod capable of resisting certain taints, thereby allowing it to be scheduled on or remain on a node with those taints.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-how-they-are-used-together&quot;&gt;How They Are Used Together&lt;/h3&gt;&lt;p&gt;The combination of taints and tolerations works as a mechanism to ensure that pods are scheduled on suitable nodes. For example, you might have a set of nodes with special hardware like GPUs. You can taint these nodes to repel ordinary workloads and add tolerations to GPU-enabled pods so they can still be scheduled there.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1716169271477/b72c7d3f-abbf-4f4d-8f59-144b1e0fe6f1.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;Image credits: &lt;a target=&quot;_blank&quot; href=&quot;https://blog.kubecost.com/blog/kubernetes-taints/&quot;&gt;kubecost&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Another example would be to use taints and tolerations to utilize &lt;a target=&quot;_blank&quot; href=&quot;https://aws.amazon.com/ec2/spot/&quot;&gt;spot nodes in AWS.&lt;/a&gt; If a workload is qualified to run on a spot node, the ideal way to &lt;a target=&quot;_blank&quot; href=&quot;https://blog.kubecost.com/blog/spot-node-recommendations/#adopting-the-recommended-configuration&quot;&gt;configure Kubernetes to utilize these spot nodes&lt;/a&gt; is to add taints and tolerations so these work&lt;a target=&quot;_blank&quot; href=&quot;https://blog.kubecost.com/blog/spot-node-recommendations/#adopting-the-recommended-configuration&quot;&gt;l&lt;/a&gt;oads will tolerate the tainted spot instances.&lt;/p&gt;&lt;p&gt;These mechanisms can be particularly useful in multi-tenant environments, where certain nodes may be reserved for specific teams or types of workloads, helping in maintaining the desired level of security and performance isolation.&lt;/p&gt;&lt;h3 id=&quot;heading-example-of-tainting-a-node&quot;&gt;Example of Tainting a Node&lt;/h3&gt;&lt;p&gt;First, you can taint a node using the &lt;code&gt;kubectl&lt;/code&gt; command line tool. This command taints a node to prevent any pods from being scheduled on it unless they explicitly tolerate the taint:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;kubectl taint nodes node1 key1=value1:NoSchedule&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This command applies a taint with:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;key&lt;/strong&gt; = &lt;code&gt;key1&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;value&lt;/strong&gt; = &lt;code&gt;value1&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;effect&lt;/strong&gt; = &lt;code&gt;NoSchedule&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-example-pod-specification-with-tolerations&quot;&gt;Example Pod Specification with Tolerations&lt;/h3&gt;&lt;p&gt;Below is a YAML example of a pod specification that includes a toleration. This pod will tolerate the taint we added to &lt;code&gt;node1&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;mypod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;containers:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;mycontainer&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tolerations:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;key:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;key1&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;operator:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Equal&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;value:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;value1&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;effect:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;NoSchedule&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This configuration means the pod &lt;code&gt;mypod&lt;/code&gt; can be scheduled on the node &lt;code&gt;node1&lt;/code&gt; despite its taint.&lt;/p&gt;&lt;h3 id=&quot;heading-more-complex-taint-and-toleration-scenario&quot;&gt;More Complex Taint and Toleration Scenario&lt;/h3&gt;&lt;p&gt;If a node has a taint that should evict existing pods and prevent new ones from being scheduled unless they tolerate the taint, you can do the following:&lt;/p&gt;&lt;h4 id=&quot;heading-tainting-the-node&quot;&gt;Tainting the Node&lt;/h4&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;kubectl taint nodes node2 key2=value2:NoExecute&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This applies a taint that has the &lt;code&gt;NoExecute&lt;/code&gt; effect, which will evict pods that do not tolerate this taint.&lt;/p&gt;&lt;h4 id=&quot;heading-pod-with-a-toleration-including-tolerationseconds&quot;&gt;Pod with a Toleration Including &lt;code&gt;TolerationSeconds&lt;/code&gt;&lt;/h4&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;mypod2&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;containers:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;mycontainer2&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tolerations:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;key:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;key2&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;operator:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Equal&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;value:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;value2&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;effect:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;NoExecute&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;tolerationSeconds:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;3600&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This pod tolerates the &lt;code&gt;NoExecute&lt;/code&gt; taint on &lt;code&gt;node2&lt;/code&gt; and will not be evicted for at least 3600 seconds (1 hour) if the taint is applied after the pod is already running on the node. This gives time to handle the pod appropriately, such as gracefully shutting down or relocating its workload.&lt;/p&gt;&lt;h3 id=&quot;heading-best-practices&quot;&gt;Best practices&lt;/h3&gt;&lt;p&gt;When using taints and tolerations in Kubernetes, its important to follow best practices to ensure efficient, secure, and reliable cluster operations. Here are some key best practices:&lt;/p&gt;&lt;h3 id=&quot;heading-1-use-specific-taints-for-specialized-hardware&quot;&gt;1. &lt;strong&gt;Use Specific Taints for Specialized Hardware&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;Taints are highly effective for nodes with specialized hardware such as GPUs or high-performance SSDs. Use taints to ensure that only workloads requiring such resources are scheduled on those nodes. This optimizes resource utilization and prevents general workloads from consuming resources that are expensive or scarce.&lt;/p&gt;&lt;h3 id=&quot;heading-2-minimize-use-of-noexecute-for-stability&quot;&gt;2. &lt;strong&gt;Minimize Use of&lt;/strong&gt; &lt;code&gt;NoExecute&lt;/code&gt; for Stability&lt;/h3&gt;&lt;p&gt;The &lt;code&gt;NoExecute&lt;/code&gt; taint effect can cause pods to be evicted from a node, which might lead to service disruption. Use this effect sparingly and mainly when its crucial to remove pods from a node due to compliance, security, or hardware decommissioning reasons. Always define &lt;code&gt;tolerationSeconds&lt;/code&gt; to manage the eviction timing gracefully.&lt;/p&gt;&lt;h3 id=&quot;heading-3-balance-tolerance-and-restriction&quot;&gt;3. &lt;strong&gt;Balance Tolerance and Restriction&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;While taints can restrict pods from scheduling on certain nodes, excessive use of taints can lead to inefficient scheduling and resource fragmentation. Use taints judiciously and ensure there are enough tolerations in place to maintain a balanced and efficient workload distribution.&lt;/p&gt;&lt;h3 id=&quot;heading-4-integrate-with-affinityanti-affinity&quot;&gt;4. &lt;strong&gt;Integrate with Affinity/Anti-affinity&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;Taints and tolerations should be used in conjunction with pod affinity and anti-affinity specifications to fine-tune pod placement. For instance, while taints can prevent certain pods from running on a node, affinity rules can be used to co-locate pods that benefit from running in proximity to each other (e.g., for performance reasons).&lt;/p&gt;&lt;h3 id=&quot;heading-5-document-and-manage-taints-and-tolerations&quot;&gt;5. &lt;strong&gt;Document and Manage Taints and Tolerations&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;As the number of taints and tolerations grows, its crucial to document why and where they are used. This avoids configuration errors and helps new team members understand the setup. Consider using infrastructure as code (IaC) tools to manage and version control taint and toleration configurations.&lt;/p&gt;&lt;h3 id=&quot;heading-6-security-and-multi-tenancy&quot;&gt;6. &lt;strong&gt;Security and Multi-tenancy&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;In multi-tenant clusters, use taints to isolate nodes dedicated to different tenants, ensuring that workloads from one tenant cannot be accidentally or maliciously scheduled on anothers nodes. This is particularly useful for enhancing security and compliance in shared environments.&lt;/p&gt;&lt;h3 id=&quot;heading-7-testing-and-validation&quot;&gt;7. &lt;strong&gt;Testing and Validation&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;Regularly test your taints and tolerations setup in a staging environment to ensure that they behave as expected, especially after modifications or updates to your cluster configuration. This can help avoid unexpected scheduling behavior in production.&lt;/p&gt;&lt;h3 id=&quot;heading-8-monitoring-and-alerts&quot;&gt;8. &lt;strong&gt;Monitoring and Alerts&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;Set up monitoring and alerts for the scheduling process. If pods are unschedulable due to taints or if certain nodes are underutilized, you should have visibility into these events to make timely adjustments.&lt;/p&gt;&lt;h3 id=&quot;heading-references&quot;&gt;References:&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/&quot;&gt;Kubernetes Documentation: Taints and Tolerations&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://blog.kubecost.com/blog/kubernetes-taints/&quot;&gt;Kubecost blog: Kubernetes Taints &amp;amp; Tolerations: Tutorial With Examples&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;]]&gt;</content:encoded><hashnode:content>&lt;![CDATA[&lt;p&gt;In Kubernetes, &lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/&quot;&gt;&lt;strong&gt;taints&lt;/strong&gt;&lt;/a&gt; and &lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/&quot;&gt;&lt;strong&gt;tolerations&lt;/strong&gt;&lt;/a&gt; are two distinct concepts used together to control how pods are scheduled on nodes. They help ensure that pods are only scheduled on appropriate nodes.&lt;/p&gt;&lt;h3 id=&quot;heading-taints-marking-nodes&quot;&gt;Taints (Marking Nodes)&lt;/h3&gt;&lt;p&gt;A &lt;strong&gt;taint&lt;/strong&gt; is applied to a node to mark it as repelling pods, unless those pods explicitly tolerate the taint. Taints have three properties:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Key&lt;/strong&gt;: The name of the taint.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Value&lt;/strong&gt;: The value associated with the taint, providing additional specificity.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Effect&lt;/strong&gt;: Describes what happens to pods that do not tolerate the taint. The effects can be:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;NoSchedule&lt;/code&gt;: Pods that do not tolerate this taint are not scheduled on the node. Pods currently running on the node are &lt;strong&gt;not&lt;/strong&gt; evicted.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;PreferNoSchedule&lt;/code&gt;: Kubernetes will try to avoid placing a pod on the node but it&apos;s not guaranteed.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;NoExecute&lt;/code&gt;: Pods that do not tolerate this taint are evicted if they are already running on the node, and new pods will not be scheduled on the node.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-tolerations-specifying-pod-compatibility&quot;&gt;Tolerations (Specifying Pod Compatibility)&lt;/h3&gt;&lt;p&gt;A &lt;strong&gt;toleration&lt;/strong&gt; is applied to a pod and allows (but does not require) the pod to be scheduled on a node with matching taints. Tolerations specify which taints they can accept. They consist of:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Key&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Value&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Effect&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Operator&lt;/strong&gt;: Determines how to match the taint&apos;s key and value. Commonly used operators include &lt;code&gt;Equal&lt;/code&gt; (default) and &lt;code&gt;Exists&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;TolerationSeconds&lt;/strong&gt;: Only relevant with the &lt;code&gt;NoExecute&lt;/code&gt; effect, this specifies how long a pod should stay on the node after the taint appears.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;A toleration &quot;matches&quot; a taint if the keys are the same and the effects are the same, and:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;the &lt;code&gt;operator&lt;/code&gt; is &lt;code&gt;Exists&lt;/code&gt; (in which case no &lt;code&gt;value&lt;/code&gt; should be specified), or&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;the &lt;code&gt;operator&lt;/code&gt; is &lt;code&gt;Equal&lt;/code&gt; and the values should be equal.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The default value for &lt;code&gt;operator&lt;/code&gt; is &lt;code&gt;Equal&lt;/code&gt;.&lt;/p&gt;&lt;h3 id=&quot;heading-differences&quot;&gt;Differences&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Where they apply&lt;/strong&gt;: Taints are applied to nodes, while tolerations are applied to pods.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Purpose&lt;/strong&gt;: Taints make a node repulsive to certain pods, while tolerations make a pod capable of resisting certain taints, thereby allowing it to be scheduled on or remain on a node with those taints.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-how-they-are-used-together&quot;&gt;How They Are Used Together&lt;/h3&gt;&lt;p&gt;The combination of taints and tolerations works as a mechanism to ensure that pods are scheduled on suitable nodes. For example, you might have a set of nodes with special hardware like GPUs. You can taint these nodes to repel ordinary workloads and add tolerations to GPU-enabled pods so they can still be scheduled there.&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1716169271477/b72c7d3f-abbf-4f4d-8f59-144b1e0fe6f1.png&quot; alt class=&quot;image--center mx-auto&quot; /&gt;&lt;/p&gt;&lt;p&gt;Image credits: &lt;a target=&quot;_blank&quot; href=&quot;https://blog.kubecost.com/blog/kubernetes-taints/&quot;&gt;kubecost&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Another example would be to use taints and tolerations to utilize &lt;a target=&quot;_blank&quot; href=&quot;https://aws.amazon.com/ec2/spot/&quot;&gt;spot nodes in AWS.&lt;/a&gt; If a workload is qualified to run on a spot node, the ideal way to &lt;a target=&quot;_blank&quot; href=&quot;https://blog.kubecost.com/blog/spot-node-recommendations/#adopting-the-recommended-configuration&quot;&gt;configure Kubernetes to utilize these spot nodes&lt;/a&gt; is to add taints and tolerations so these work&lt;a target=&quot;_blank&quot; href=&quot;https://blog.kubecost.com/blog/spot-node-recommendations/#adopting-the-recommended-configuration&quot;&gt;l&lt;/a&gt;oads will tolerate the tainted spot instances.&lt;/p&gt;&lt;p&gt;These mechanisms can be particularly useful in multi-tenant environments, where certain nodes may be reserved for specific teams or types of workloads, helping in maintaining the desired level of security and performance isolation.&lt;/p&gt;&lt;h3 id=&quot;heading-example-of-tainting-a-node&quot;&gt;Example of Tainting a Node&lt;/h3&gt;&lt;p&gt;First, you can taint a node using the &lt;code&gt;kubectl&lt;/code&gt; command line tool. This command taints a node to prevent any pods from being scheduled on it unless they explicitly tolerate the taint:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;kubectl taint nodes node1 key1=value1:NoSchedule&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This command applies a taint with:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;key&lt;/strong&gt; = &lt;code&gt;key1&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;value&lt;/strong&gt; = &lt;code&gt;value1&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;effect&lt;/strong&gt; = &lt;code&gt;NoSchedule&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;heading-example-pod-specification-with-tolerations&quot;&gt;Example Pod Specification with Tolerations&lt;/h3&gt;&lt;p&gt;Below is a YAML example of a pod specification that includes a toleration. This pod will tolerate the taint we added to &lt;code&gt;node1&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;mypod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;containers:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;mycontainer&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tolerations:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;key:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;key1&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;operator:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Equal&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;value:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;value1&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;effect:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;NoSchedule&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This configuration means the pod &lt;code&gt;mypod&lt;/code&gt; can be scheduled on the node &lt;code&gt;node1&lt;/code&gt; despite its taint.&lt;/p&gt;&lt;h3 id=&quot;heading-more-complex-taint-and-toleration-scenario&quot;&gt;More Complex Taint and Toleration Scenario&lt;/h3&gt;&lt;p&gt;If a node has a taint that should evict existing pods and prevent new ones from being scheduled unless they tolerate the taint, you can do the following:&lt;/p&gt;&lt;h4 id=&quot;heading-tainting-the-node&quot;&gt;Tainting the Node&lt;/h4&gt;&lt;pre&gt;&lt;code class=&quot;lang-bash&quot;&gt;kubectl taint nodes node2 key2=value2:NoExecute&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This applies a taint that has the &lt;code&gt;NoExecute&lt;/code&gt; effect, which will evict pods that do not tolerate this taint.&lt;/p&gt;&lt;h4 id=&quot;heading-pod-with-a-toleration-including-tolerationseconds&quot;&gt;Pod with a Toleration Including &lt;code&gt;TolerationSeconds&lt;/code&gt;&lt;/h4&gt;&lt;pre&gt;&lt;code class=&quot;lang-yaml&quot;&gt;&lt;span class=&quot;hljs-attr&quot;&gt;apiVersion:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;kind:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;Pod&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;metadata:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;mypod2&lt;/span&gt;&lt;span class=&quot;hljs-attr&quot;&gt;spec:&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;containers:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;name:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;mycontainer2&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;image:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;nginx&lt;/span&gt;  &lt;span class=&quot;hljs-attr&quot;&gt;tolerations:&lt;/span&gt;  &lt;span class=&quot;hljs-bullet&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;hljs-attr&quot;&gt;key:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;key2&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;operator:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;Equal&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;value:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;value2&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;effect:&lt;/span&gt; &lt;span class=&quot;hljs-string&quot;&gt;&quot;NoExecute&quot;&lt;/span&gt;    &lt;span class=&quot;hljs-attr&quot;&gt;tolerationSeconds:&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;3600&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This pod tolerates the &lt;code&gt;NoExecute&lt;/code&gt; taint on &lt;code&gt;node2&lt;/code&gt; and will not be evicted for at least 3600 seconds (1 hour) if the taint is applied after the pod is already running on the node. This gives time to handle the pod appropriately, such as gracefully shutting down or relocating its workload.&lt;/p&gt;&lt;h3 id=&quot;heading-best-practices&quot;&gt;Best practices&lt;/h3&gt;&lt;p&gt;When using taints and tolerations in Kubernetes, its important to follow best practices to ensure efficient, secure, and reliable cluster operations. Here are some key best practices:&lt;/p&gt;&lt;h3 id=&quot;heading-1-use-specific-taints-for-specialized-hardware&quot;&gt;1. &lt;strong&gt;Use Specific Taints for Specialized Hardware&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;Taints are highly effective for nodes with specialized hardware such as GPUs or high-performance SSDs. Use taints to ensure that only workloads requiring such resources are scheduled on those nodes. This optimizes resource utilization and prevents general workloads from consuming resources that are expensive or scarce.&lt;/p&gt;&lt;h3 id=&quot;heading-2-minimize-use-of-noexecute-for-stability&quot;&gt;2. &lt;strong&gt;Minimize Use of&lt;/strong&gt; &lt;code&gt;NoExecute&lt;/code&gt; for Stability&lt;/h3&gt;&lt;p&gt;The &lt;code&gt;NoExecute&lt;/code&gt; taint effect can cause pods to be evicted from a node, which might lead to service disruption. Use this effect sparingly and mainly when its crucial to remove pods from a node due to compliance, security, or hardware decommissioning reasons. Always define &lt;code&gt;tolerationSeconds&lt;/code&gt; to manage the eviction timing gracefully.&lt;/p&gt;&lt;h3 id=&quot;heading-3-balance-tolerance-and-restriction&quot;&gt;3. &lt;strong&gt;Balance Tolerance and Restriction&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;While taints can restrict pods from scheduling on certain nodes, excessive use of taints can lead to inefficient scheduling and resource fragmentation. Use taints judiciously and ensure there are enough tolerations in place to maintain a balanced and efficient workload distribution.&lt;/p&gt;&lt;h3 id=&quot;heading-4-integrate-with-affinityanti-affinity&quot;&gt;4. &lt;strong&gt;Integrate with Affinity/Anti-affinity&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;Taints and tolerations should be used in conjunction with pod affinity and anti-affinity specifications to fine-tune pod placement. For instance, while taints can prevent certain pods from running on a node, affinity rules can be used to co-locate pods that benefit from running in proximity to each other (e.g., for performance reasons).&lt;/p&gt;&lt;h3 id=&quot;heading-5-document-and-manage-taints-and-tolerations&quot;&gt;5. &lt;strong&gt;Document and Manage Taints and Tolerations&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;As the number of taints and tolerations grows, its crucial to document why and where they are used. This avoids configuration errors and helps new team members understand the setup. Consider using infrastructure as code (IaC) tools to manage and version control taint and toleration configurations.&lt;/p&gt;&lt;h3 id=&quot;heading-6-security-and-multi-tenancy&quot;&gt;6. &lt;strong&gt;Security and Multi-tenancy&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;In multi-tenant clusters, use taints to isolate nodes dedicated to different tenants, ensuring that workloads from one tenant cannot be accidentally or maliciously scheduled on anothers nodes. This is particularly useful for enhancing security and compliance in shared environments.&lt;/p&gt;&lt;h3 id=&quot;heading-7-testing-and-validation&quot;&gt;7. &lt;strong&gt;Testing and Validation&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;Regularly test your taints and tolerations setup in a staging environment to ensure that they behave as expected, especially after modifications or updates to your cluster configuration. This can help avoid unexpected scheduling behavior in production.&lt;/p&gt;&lt;h3 id=&quot;heading-8-monitoring-and-alerts&quot;&gt;8. &lt;strong&gt;Monitoring and Alerts&lt;/strong&gt;&lt;/h3&gt;&lt;p&gt;Set up monitoring and alerts for the scheduling process. If pods are unschedulable due to taints or if certain nodes are underutilized, you should have visibility into these events to make timely adjustments.&lt;/p&gt;&lt;h3 id=&quot;heading-references&quot;&gt;References:&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/&quot;&gt;Kubernetes Documentation: Taints and Tolerations&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://blog.kubecost.com/blog/kubernetes-taints/&quot;&gt;Kubecost blog: Kubernetes Taints &amp;amp; Tolerations: Tutorial With Examples&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;]]&gt;</hashnode:content><hashnode:coverImage>https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/9cXMJHaViTM/upload/0569fbf7556298427bc3d8e5f35dfc73.jpeg</hashnode:coverImage></item><item><title><![CDATA[Python 101: Special variables]]></title><description><![CDATA[Python 101: Special variables]]></description><link>https://maxat-akbanov.com/python-101-special-variables</link><guid isPermaLink="true">https://maxat-akbanov.com/python-101-special-variables</guid><category><![CDATA[Python]]></category><category><![CDATA[Devops]]></category><category><![CDATA[programming languages]]></category><category><![CDATA[variables]]></category><category><![CDATA[dunder]]></category><dc:creator><![CDATA[Maxat Akbanov]]></dc:creator><pubDate>Tue, 16 Apr 2024 12:07:08 GMT</pubDate><content:encoded>&lt;![CDATA[&lt;p&gt;Python uses several special variables, often referred to as &quot;&lt;strong&gt;dunder&lt;/strong&gt;&quot; (&lt;strong&gt;double underscore&lt;/strong&gt;) variables or &quot;&lt;strong&gt;magic methods&lt;/strong&gt;&quot; in the context of &lt;a target=&quot;_blank&quot; href=&quot;https://maxat-akbanov.com/basics-of-object-oriented-programming-oop-in-python&quot;&gt;OOP&lt;/a&gt;, that have specific meanings and are used by the Python interpreter for particular purposes. This double underscore naming distinguishes them from regular variables and avoid naming conflicts with your custom variables.  &lt;/p&gt;&lt;p&gt;These variables are integral to Python&apos;s internal operations and often relate to object-oriented features and module management.&lt;/p&gt;&lt;p&gt;Here are some of the key special variables in Python:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;__name__&lt;/code&gt;: This variable is perhaps the most well-known. It holds the name of the module in which it is used. If the module is the entry point to the program (i.e., the script that is run), &lt;code&gt;__name__&lt;/code&gt; is set to &lt;code&gt;&quot;__main__&quot;&lt;/code&gt;. This helps determine whether the module is being run directly or being imported.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-python&quot;&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# example.py&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; __name__ == &lt;span class=&quot;hljs-string&quot;&gt;&quot;__main__&quot;&lt;/span&gt;:     print(&lt;span class=&quot;hljs-string&quot;&gt;&quot;This script is running directly&quot;&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:     print(&lt;span class=&quot;hljs-string&quot;&gt;&quot;This script has been imported&quot;&lt;/span&gt;)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; Run this file directly or import it in another Python script to see the difference.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;__doc__&lt;/code&gt;: This variable contains the module&apos;s (script&apos;s) or function&apos;s documentation string (docstring), which is the first string after the definition. It&apos;s used to provide documentation about the module, class, method, or function.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-python&quot;&gt; &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;example_function&lt;/span&gt;():&lt;/span&gt;     &lt;span class=&quot;hljs-string&quot;&gt;&quot;&quot;&quot;     This is a docstring for example_function.     &quot;&quot;&quot;&lt;/span&gt;     &lt;span class=&quot;hljs-keyword&quot;&gt;pass&lt;/span&gt; print(example_function.__doc__)&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;__file__&lt;/code&gt;: This variable contains the pathname of the file from which the module was loaded, if it was loaded from a file. This can be useful for modules that want to load data files located in the same directory as the module file.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-python&quot;&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Prints the pathname of the file from which the module was loaded&lt;/span&gt; print(__file__)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; This will output the full path of the current script file.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;__dict__&lt;/code&gt;: This dictionary contains the namespace supported by most objects in Python, including modules, classes, and instances. It maps attribute names to their values and can be used for introspection or dynamically manipulating objects.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-python&quot;&gt; &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Example&lt;/span&gt;:&lt;/span&gt;     &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;__init__&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;self&lt;/span&gt;):&lt;/span&gt;         self.attribute = &lt;span class=&quot;hljs-string&quot;&gt;&quot;value&quot;&lt;/span&gt; instance = Example() print(instance.__dict__)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; This will print the dictionary containing the namespace of the &lt;code&gt;instance&lt;/code&gt; of &lt;code&gt;Example&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;__package__&lt;/code&gt;: This variable is used to support relative imports. It holds the name of the package that the current module is a part of. If the module is not part of a package, &lt;code&gt;__package__&lt;/code&gt; is set to &lt;code&gt;None&lt;/code&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-python&quot;&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# example_module.py&lt;/span&gt; print(__package__)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; When part of a package, this prints the package name. If not part of a package, it prints &lt;code&gt;None&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;__path__&lt;/code&gt;: This variable only exists on packages. It is used to define the list of paths where Python searches for sub-modules and sub-packages under the package. This is how Python determines what can be imported within a package.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;__class__&lt;/code&gt;: Within a class method, this variable refers to the class object that the method is defined on. This can be useful for accessing class-level attributes and methods from instance methods.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-python&quot;&gt; &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;MyClass&lt;/span&gt;:&lt;/span&gt;     &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;show_class&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;self&lt;/span&gt;):&lt;/span&gt;         print(self.__class__) obj = MyClass() obj.show_class()&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; This code will print the class &lt;code&gt;MyClass&lt;/code&gt; of the object &lt;code&gt;obj&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;__bases__&lt;/code&gt;: Available only on class objects, this tuple contains the base classes, in the order of their occurrence in the base class list, of the class object.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-python&quot;&gt; &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;BaseClass&lt;/span&gt;:&lt;/span&gt;     &lt;span class=&quot;hljs-keyword&quot;&gt;pass&lt;/span&gt; &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;DerivedClass&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;BaseClass&lt;/span&gt;):&lt;/span&gt;     &lt;span class=&quot;hljs-keyword&quot;&gt;pass&lt;/span&gt; print(DerivedClass.__bases__)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; This will print the tuple of base classes of &lt;code&gt;DerivedClass&lt;/code&gt;, here (&lt;code&gt;BaseClass&lt;/code&gt;,).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;__annotations__&lt;/code&gt;: This dictionary contains type hints for the module, class, or function. It maps parameter names to their type hints, and is available from Python 3.6 onwards.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-python&quot;&gt; &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;func&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;a: int, b: str&lt;/span&gt;) -&amp;gt; float:&lt;/span&gt;     &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;3.14&lt;/span&gt; print(func.__annotations__)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; This will print the type hints of the parameters and the return type of &lt;code&gt;func&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;__all__&lt;/code&gt;: This list controls what is exported when the module is imported using &lt;code&gt;from module import *&lt;/code&gt;. Only names included in &lt;code&gt;__all__&lt;/code&gt; will be imported.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-python&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# mymodule.py&lt;/span&gt;__all__ = [&lt;span class=&quot;hljs-string&quot;&gt;&apos;public_function&apos;&lt;/span&gt;]&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;public_function&lt;/span&gt;():&lt;/span&gt;    print(&lt;span class=&quot;hljs-string&quot;&gt;&quot;Accessible function&quot;&lt;/span&gt;)&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;_private_function&lt;/span&gt;():&lt;/span&gt;    print(&lt;span class=&quot;hljs-string&quot;&gt;&quot;Hidden function&quot;&lt;/span&gt;)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;When you use &lt;code&gt;from mymodule import *&lt;/code&gt;, only &lt;code&gt;public_function&lt;/code&gt; will be imported due to &lt;code&gt;__all__&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;]]&gt;</content:encoded><hashnode:content>&lt;![CDATA[&lt;p&gt;Python uses several special variables, often referred to as &quot;&lt;strong&gt;dunder&lt;/strong&gt;&quot; (&lt;strong&gt;double underscore&lt;/strong&gt;) variables or &quot;&lt;strong&gt;magic methods&lt;/strong&gt;&quot; in the context of &lt;a target=&quot;_blank&quot; href=&quot;https://maxat-akbanov.com/basics-of-object-oriented-programming-oop-in-python&quot;&gt;OOP&lt;/a&gt;, that have specific meanings and are used by the Python interpreter for particular purposes. This double underscore naming distinguishes them from regular variables and avoid naming conflicts with your custom variables.  &lt;/p&gt;&lt;p&gt;These variables are integral to Python&apos;s internal operations and often relate to object-oriented features and module management.&lt;/p&gt;&lt;p&gt;Here are some of the key special variables in Python:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;__name__&lt;/code&gt;: This variable is perhaps the most well-known. It holds the name of the module in which it is used. If the module is the entry point to the program (i.e., the script that is run), &lt;code&gt;__name__&lt;/code&gt; is set to &lt;code&gt;&quot;__main__&quot;&lt;/code&gt;. This helps determine whether the module is being run directly or being imported.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-python&quot;&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# example.py&lt;/span&gt; &lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; __name__ == &lt;span class=&quot;hljs-string&quot;&gt;&quot;__main__&quot;&lt;/span&gt;:     print(&lt;span class=&quot;hljs-string&quot;&gt;&quot;This script is running directly&quot;&lt;/span&gt;) &lt;span class=&quot;hljs-keyword&quot;&gt;else&lt;/span&gt;:     print(&lt;span class=&quot;hljs-string&quot;&gt;&quot;This script has been imported&quot;&lt;/span&gt;)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; Run this file directly or import it in another Python script to see the difference.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;__doc__&lt;/code&gt;: This variable contains the module&apos;s (script&apos;s) or function&apos;s documentation string (docstring), which is the first string after the definition. It&apos;s used to provide documentation about the module, class, method, or function.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-python&quot;&gt; &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;example_function&lt;/span&gt;():&lt;/span&gt;     &lt;span class=&quot;hljs-string&quot;&gt;&quot;&quot;&quot;     This is a docstring for example_function.     &quot;&quot;&quot;&lt;/span&gt;     &lt;span class=&quot;hljs-keyword&quot;&gt;pass&lt;/span&gt; print(example_function.__doc__)&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;__file__&lt;/code&gt;: This variable contains the pathname of the file from which the module was loaded, if it was loaded from a file. This can be useful for modules that want to load data files located in the same directory as the module file.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-python&quot;&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# Prints the pathname of the file from which the module was loaded&lt;/span&gt; print(__file__)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; This will output the full path of the current script file.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;__dict__&lt;/code&gt;: This dictionary contains the namespace supported by most objects in Python, including modules, classes, and instances. It maps attribute names to their values and can be used for introspection or dynamically manipulating objects.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-python&quot;&gt; &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;Example&lt;/span&gt;:&lt;/span&gt;     &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;__init__&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;self&lt;/span&gt;):&lt;/span&gt;         self.attribute = &lt;span class=&quot;hljs-string&quot;&gt;&quot;value&quot;&lt;/span&gt; instance = Example() print(instance.__dict__)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; This will print the dictionary containing the namespace of the &lt;code&gt;instance&lt;/code&gt; of &lt;code&gt;Example&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;__package__&lt;/code&gt;: This variable is used to support relative imports. It holds the name of the package that the current module is a part of. If the module is not part of a package, &lt;code&gt;__package__&lt;/code&gt; is set to &lt;code&gt;None&lt;/code&gt;.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-python&quot;&gt; &lt;span class=&quot;hljs-comment&quot;&gt;# example_module.py&lt;/span&gt; print(__package__)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; When part of a package, this prints the package name. If not part of a package, it prints &lt;code&gt;None&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;__path__&lt;/code&gt;: This variable only exists on packages. It is used to define the list of paths where Python searches for sub-modules and sub-packages under the package. This is how Python determines what can be imported within a package.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;__class__&lt;/code&gt;: Within a class method, this variable refers to the class object that the method is defined on. This can be useful for accessing class-level attributes and methods from instance methods.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-python&quot;&gt; &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;MyClass&lt;/span&gt;:&lt;/span&gt;     &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;show_class&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;self&lt;/span&gt;):&lt;/span&gt;         print(self.__class__) obj = MyClass() obj.show_class()&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; This code will print the class &lt;code&gt;MyClass&lt;/code&gt; of the object &lt;code&gt;obj&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;__bases__&lt;/code&gt;: Available only on class objects, this tuple contains the base classes, in the order of their occurrence in the base class list, of the class object.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-python&quot;&gt; &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;BaseClass&lt;/span&gt;:&lt;/span&gt;     &lt;span class=&quot;hljs-keyword&quot;&gt;pass&lt;/span&gt; &lt;span class=&quot;hljs-class&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;DerivedClass&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;BaseClass&lt;/span&gt;):&lt;/span&gt;     &lt;span class=&quot;hljs-keyword&quot;&gt;pass&lt;/span&gt; print(DerivedClass.__bases__)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; This will print the tuple of base classes of &lt;code&gt;DerivedClass&lt;/code&gt;, here (&lt;code&gt;BaseClass&lt;/code&gt;,).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;__annotations__&lt;/code&gt;: This dictionary contains type hints for the module, class, or function. It maps parameter names to their type hints, and is available from Python 3.6 onwards.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-python&quot;&gt; &lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;func&lt;/span&gt;(&lt;span class=&quot;hljs-params&quot;&gt;a: int, b: str&lt;/span&gt;) -&amp;gt; float:&lt;/span&gt;     &lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;hljs-number&quot;&gt;3.14&lt;/span&gt; print(func.__annotations__)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; This will print the type hints of the parameters and the return type of &lt;code&gt;func&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;__all__&lt;/code&gt;: This list controls what is exported when the module is imported using &lt;code&gt;from module import *&lt;/code&gt;. Only names included in &lt;code&gt;__all__&lt;/code&gt; will be imported.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;lang-python&quot;&gt;&lt;span class=&quot;hljs-comment&quot;&gt;# mymodule.py&lt;/span&gt;__all__ = [&lt;span class=&quot;hljs-string&quot;&gt;&apos;public_function&apos;&lt;/span&gt;]&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;public_function&lt;/span&gt;():&lt;/span&gt;    print(&lt;span class=&quot;hljs-string&quot;&gt;&quot;Accessible function&quot;&lt;/span&gt;)&lt;span class=&quot;hljs-function&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;hljs-title&quot;&gt;_private_function&lt;/span&gt;():&lt;/span&gt;    print(&lt;span class=&quot;hljs-string&quot;&gt;&quot;Hidden function&quot;&lt;/span&gt;)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;When you use &lt;code&gt;from mymodule import *&lt;/code&gt;, only &lt;code&gt;public_function&lt;/code&gt; will be imported due to &lt;code&gt;__all__&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;]]&gt;</hashnode:content><hashnode:coverImage>https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/oJlt2XBWuWs/upload/6c2a6ed5220486fc934276cd0e3d0f30.jpeg</hashnode:coverImage></item></channel></rss>