<?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:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Directeam - Medium]]></title>
        <description><![CDATA[We help you own the cloud - Medium]]></description>
        <link>https://medium.com/directeam?source=rss----eb217c281961---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Directeam - Medium</title>
            <link>https://medium.com/directeam?source=rss----eb217c281961---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Mon, 11 May 2026 16:51:25 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/directeam" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[AWS RDS Storage types — Which one should I choose?]]></title>
            <link>https://medium.com/directeam/aws-rds-storage-types-which-one-should-i-choose-943bc89c4f2f?source=rss----eb217c281961---4</link>
            <guid isPermaLink="false">https://medium.com/p/943bc89c4f2f</guid>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[finops]]></category>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[cloud-cost-optimization]]></category>
            <category><![CDATA[rds]]></category>
            <dc:creator><![CDATA[Shir Monether]]></dc:creator>
            <pubDate>Mon, 22 May 2023 12:11:21 GMT</pubDate>
            <atom:updated>2023-06-08T12:28:35.649Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*TvQzKOkk-KhhRrHahU5tCQ.png" /></figure><h3>AWS RDS Storage types — Which one should I choose?</h3><p>Amazon RDS (Relational Database Service) is a cloud-based web service that makes it easier to set up, operate, and scale a relational database. RDS is designed to provide an efficient and cost-effective solution for managing databases. One of the crucial components of RDS, is storage. Amazon RDS provides three recommended storage options for database instances: GP2, GP3 &amp; IO1 (Magnetic is for backwards compatibility).</p><p>In this blog post, we will explore the differences between storage types and when to use each type. But before we dive in, you’ll need to understand the main differences between GP2 and GP3 volumes.</p><p><a href="https://aws.amazon.com/blogs/storage/migrate-your-amazon-ebs-volumes-from-gp2-to-gp3-and-save-up-to-20-on-costs/">Here</a> is an AWS blog regarding migrating EBS with a great comparison table.</p><p>TLDR; GP2 IOPS and throughput get larger with volume size, while GP3 requires you to configure the amount of IOPS and throughput required.</p><h3>Traditional EBS vs RDS storage</h3><p>RDS storage is backed by AWS EBS but it has a few tricks that do not come out of the box with traditional EBS, for example an EBS volume can be up to 16TiB while RDS storage can max out at 64TiB.</p><p>This also makes different performance metrics maximums:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zhUlDP6U0LklGD-ayffJOw.png" /></figure><p><em>Disclaimer: These maximums are for all database engines other than SQL Server as it doesn’t support disk striping</em></p><p>This is mainly due to AWS performing some magic behind the scenes that makes use of multiple EBS volumes &amp; volume striping.</p><p>Another big consideration is price. With traditional EBS, GP3 is generally 20% cheaper than GP2. However, how does this compare with RDS storage?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/844/1*guD3y2y4HdNiDiID1hBAEA.png" /></figure><p>They are the same price!</p><p>What’s more, as GP3 is GP3, you will need to pay more for each additional Throughput/IOPS over baseline.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/900/0*zt9ffT9cd4oFoJl3.jpg" /></figure><h3>Then when should I use GP3?</h3><p>The obvious answer would be when I require a small amount of storage but a large amount of IOPS/Throughput. But we’re not here for the obvious answers, let’s geek out with some graphs!</p><p>Here are a few graphs depicting the difference between GP2 &amp; GP3 regarding the amount of IOPS, Throughput &amp; price (When equalizing GP3 IOPS &amp; Throughput configuration to what is provided with GP2).</p><p><em>These charts are up to 25TB storage since after 21 it flat lines (or in the case of price continues in parallel with each other).</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-lCUYRj5a72JCck4go4cgA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*a3py_HigEN5R7MqOnm5Fyw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Vegjh-DSw8ZkZmrzxCrV9w.png" /></figure><p><em>Disclaimer; Notice the gray areas on the IOPs and Throughput graphs? these are in a bit of a gray area (see what I did there?), These areas indicate where GP2 is burstable. For the IOPS graph, the burst can be up to 3000, and for the Throughput graph, between 170–334GB storage, the burst can be up to 250MiB/s however between 1,000GB and 1,336GB, it’s burstable up to 1,000MiB/s.</em></p><p>So in the IOPS and Throughput graphs, whenever GP2 is higher than GP3, we have to pay more to get the same performance! And the delta between the price gets higher the larger the storage!</p><p>Hold on, with all these technicalities between GP2 and GP3 storage I’ve forgotten the third (and most mind-blowing) storage type; IO1.</p><p>IO1 is a storage type for workloads that require huge amounts of IOPS, allowing you to go up to 256,000 IOPS! But how does its pricing compare with GP2 &amp; GP3?</p><figure><img alt="us-east-1 pricing" src="https://cdn-images-1.medium.com/max/946/1*hDx1Q0WGoS2vvl1Z7TJKpg.png" /><figcaption>us-east-1 pricing</figcaption></figure><p>Well some bad news for you if you’ve been using IO1 at under 64,000 IOPS. It looks like you’re wasting money!</p><p>Comparing the pricing with GP3 you can see that you will be getting the same performance for a lot lower price! (Even without taking into consideration the free baseline IOPS you get from GP3). The main use-case that makes sense to use IO1 over GP3 is when you’re restricted by GP3s IOPS limit (64,000).</p><p><em>Disclaimer: There is another metric that slightly differs between GP2/3 and IO1, which is latency. While all provide single digit latency, for GP2/3 it’s for 99% of the time, while for IO1 it’s 99.9% of the time. This may be relevant if you have tight SLO/SLA requirements, but keep in mind the trade-off of potentially thousands of dollars a month. If you want to deep dive into more granular resolution, Percona wrote </em><a href="https://www.percona.com/blog/performance-of-various-ebs-storage-types-in-aws/"><em>this</em></a><em> great article benchmarking the performance of each storage type.</em></p><h3>So how do I decide which storage type fits my needs?</h3><p>So the answer to this question is the good old; It’s complicated.</p><p>There are a few rules of thumb we can go by;</p><ul><li>If you require more IOPS than what GP2 offers at the storage size you require, better go with GP3.</li><li>If you don’t know your IOPS and Throughput requirements, use GP3 when your storage is lower than 4TB, and when your storage is over 4TB use GP2 (This makes sure you get larger baselines).</li><li>If you know how much Storage, IOPS and Throughput you require, you can calculate which one would be either cheaper, or (in the case of smaller storage sizes) provides larger IOPS &amp; Throughput headroom at the same price (GP3 baselines).</li><li>If you don’t need over 64,000 IOPS don’t use IO1.</li></ul><h3>Awesome, so I’m all set?</h3><p>Well it would be great if this was the end of the story right?</p><p>But I’m afraid there is another parameter we have to take into consideration when configuring these metrics, which can very well be a bottleneck; the instance type.</p><p>In AWS each instance type has it’s own IOPS and Throughput limits for the instance itself (You can view the whole table <a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-optimized.html">here</a>). This means that we can hit an IOPS or Throughput bottleneck if we aren’t using a large enough instance.</p><p>For example let’s take the m6g.large instance which has a baseline Throughput of 78.75 MB/s and baseline IOPS of 3600 (Yes, these are also burstable but only for 30 minutes in a 24 hour period so I wouldn’t count on it). If I use m6g.large for my RDS instance I wouldn’t be able to take advantage of any storage configuration that provides more than the instance constraints.</p><p>This is quite rare as usually you’ll be required to have a larger instance to answer to CPU and memory requirements at this scale before you hit the IOPS and Throughput limits. But if you are experiencing inability to utilize the storage configuration you may want to keep this in mind.</p><p><strong>If you want to learn more about cost optimization strategies and configurations, please do not hesitate to get in touch with us to discover how we can help you, own the cloud </strong>— <a href="https://directeam.io/contact/">https://directeam.io/contact/</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=943bc89c4f2f" width="1" height="1" alt=""><hr><p><a href="https://medium.com/directeam/aws-rds-storage-types-which-one-should-i-choose-943bc89c4f2f">AWS RDS Storage types — Which one should I choose?</a> was originally published in <a href="https://medium.com/directeam">Directeam</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Kubernetes resources under the hood — Part 3]]></title>
            <link>https://medium.com/directeam/kubernetes-resources-under-the-hood-part-3-6ee7d6015965?source=rss----eb217c281961---4</link>
            <guid isPermaLink="false">https://medium.com/p/6ee7d6015965</guid>
            <category><![CDATA[containers]]></category>
            <category><![CDATA[kubernetes]]></category>
            <category><![CDATA[cloud-computing]]></category>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[docker]]></category>
            <dc:creator><![CDATA[Shon Lev-Ran]]></dc:creator>
            <pubDate>Wed, 07 Sep 2022 08:58:02 GMT</pubDate>
            <atom:updated>2022-09-07T08:58:02.518Z</atom:updated>
            <content:encoded><![CDATA[<h3>Kubernetes resources under the hood — Part 3</h3><h4>Kubernetes resources, breaking the limits! Understand the biggest Kubernetes misunderstanding and why you should remove your CPU limits and unleash your cluster&#39;s full potential</h4><p>Co-Authored by@<a href="https://medium.com/@shirmon">shirmon</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7-WhDU0x_Z6IK39JLzc2Tw.png" /></figure><h4>What have we learned so far?</h4><p>So far I’ve mostly explained things you probably know in one way or another, I’ve explained concepts like allocatable resources &amp; Quality of Service (QoS) in the <a href="https://medium.com/@shonlevran/kubernetes-resources-under-the-hood-part-1-4f2400b6bb96">first part</a>, and CPU requests and shares in the <a href="https://shonlevran.medium.com/kubernetes-resources-under-the-hood-part-2-6eeb50197c44">second part</a>.</p><p>In this part, I will focus on what is happening when you set CPU limits.</p><blockquote>TLDR; don’t set CPU limits!</blockquote><p>I highly recommend you read the previous parts of this blog to get a solid understanding of what I’m about to explain. Once you’re done, if you did the math correctly, you should start to understand that CPU limits are not the way to achieve a fair division of CPU time between containers.</p><p>CPU time is divided among the containers by their <a href="https://medium.com/@shonlevran/kubernetes-resources-under-the-hood-part-2-6eeb50197c44#:~:text=to%20CPU%20requests%3F-,CPU%20Shares,-When%20you%20configure">CPU shares</a> (or requests).</p><h3>The CPU Limits myth</h3><p>As I’ve said, when getting into Kubernetes we are advised to set CPU limits to make sure we aren’t being ‘noisy neighbors’, meaning that if our workloads start to be CPU hungry it won’t eat up all of the CPU that our other workloads need. But I’m afraid this is a complete myth since, as I’ve explained in part 2 — CPU requests <a href="https://shonlevran.medium.com/kubernetes-resources-under-the-hood-part-2-6eeb50197c44#:~:text=Don%E2%80%99t%20worry%20when%20setting%20high%20CPU%20requests%2C%20the%20node%E2%80%99s%20components%20are%20higher%20priority%20out%20of%20the%20box.">guarantee your workload to receive at least this amount of CPU from the CFS</a>.</p><p>What about overloading the node?</p><p>CPU is a <a href="https://medium.com/@shonlevran/kubernetes-resources-under-the-hood-part-1-4f2400b6bb96#:~:text=There%20is%20no%20eviction%20for%20compressible%20resources!">compressible</a> resource, and this is why <strong>there is </strong><a href="https://medium.com/p/6eeb50197c44#:~:text=Eviction%20is%20a%20process%20running%20on%20the%20node%20that%20chooses%20and%20kills%20pods%20when%20the%20node%20is%20low%20on%20resources.%20Eviction%20only%20happens%20for%20in%2Dcompressible%20resources%20like%20memory%2C%20disk%20space%2C%20etc.%20more%20on%20that%20in%20the%20fourth%20part."><strong>no eviction</strong></a><strong> for CPU stress</strong>, only throttling (delay).</p><h3>What do CPU limits actually do?</h3><p>As I’ve explained in the first part, Kubernetes will <a href="https://medium.com/@shonlevran/kubernetes-resources-under-the-hood-part-1-4f2400b6bb96#:~:text=A%20compressible%20resource%20means%20that%20if%20the%20usage%20of%20this%20resource%20reaches%20its%20maximum%2C%20the%20processes%20that%20require%20this%20resource%20will%20have%20to%20wait%20until%20the%20resource%20becomes%20free.%20In%20other%20words%2C%20throttling%20the%20processes.">throttle</a><strong> </strong>the CPU usage of containers that reach their CPU limit.</p><p>This is done by configuring the following CGroup parameters:</p><ul><li>“<strong>cpu.cfs_period_us</strong>” — This configures what a “CPU period” is in microseconds, or if we are using the <a href="https://medium.com/@shonlevran/kubernetes-resources-under-the-hood-part-2-6eeb50197c44#:~:text=Let%E2%80%99s%20think%20of,the%20oven.%20Yummy!%20%F0%9F%8D%95">same example</a> as in part 2, the time interval for every new CPU pizza. Currently, Kubernetes configures this to be 100,000µs [100ms] by default, this can be configured via the <a href="https://kubernetes.io/docs/reference/config-api/kubelet-config.v1beta1/#:~:text=limits.%20Default%3A%20true-,cpuCFSQuotaPeriod,-meta/v1.Duration">kubelet configuration</a></li><li>“<strong>cpu.cfs_quota_us”</strong> — The CPU time in µs that the container (CGroup) can consume every period. Every 1 vCore you define as CPU limits will configure 100,000µs (100 ms) quota — equal to the period</li></ul><p><em>You can learn more about the above CGroups configurations </em><a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/resource_management_guide/sec-cpu#sect-cfs"><em>here</em></a><em>.</em></p><p>So for example, if you have configured 0.5 vCore as the CPU limit (500 milli-cores), 50,000 µs (50ms) will be configured as the quota giving the CGroup a maximum usage of 50ms per the 100ms period. If the process in the container (CGroup) asks for more, it will have to wait for the next CPU period, meaning waiting for the remanding 50ms of the period, this is CPU throttling. This is only true if my container runs a single process that runs on one core (one thread can only use one core).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/731/0*20FW6dz52zoO2VN8" /><figcaption>Single-threaded CPU limit and throttling</figcaption></figure><p>Sounds simple? Let’s make it a little more complicated with multi-process containers / multi-threaded processes!</p><blockquote>Every core you use consumes time out of the quota simultaneously.</blockquote><p>For multi-threaded (I’m looking at you Java thread-pool) or multi-process tasks, if you run on 4 cores simultaneously, you will consume your quota in 12.5 ms (4 milliseconds of the quota for every actually millisecond) and will be throttled for the rest of the period — 87.5ms!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/731/0*WVYOn-E0b8yedLPU" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/731/0*NcpU14w0WBK6qn_Y" /><figcaption>Multi-threaded CPU limit and throttling over and over again</figcaption></figure><p>The more cores your node has &amp; your container utilizes, the worse the throttling will get, so if we take the same example and run it on a node with 8 cores it will consume its quota in only 6.25 milliseconds!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/731/0*8zgEtjsl-sxlrZyF" /><figcaption>Multi-threaded CPU limit and worth throttling with more cores</figcaption></figure><p>I would show an example on a node with 88 cores, but I’m sure you get the point. Throttling hurts your container&#39;s response times drastically!</p><h3>CPU Limits in real life</h3><p>Here I can see the CPU usage of a CPU stress test that is single threaded (therefore can only use up to 1 core) with 3 cores as CPU limit.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*k7RVbgfQDE090qz1" /><figcaption>Single-threaded stress test with 3 CPU limit</figcaption></figure><p>As expected we aren’t getting throttled by the CPU limit and the process is getting all of the CPU it needs (or in our stress test case, all the CPU it can get!).</p><p><strong>Bonus myth:</strong> Another best practice misunderstanding is to set your CPU request or limit at 1 vCore or below. This is only true for containers that are single-threaded, and yes, it’s better to use multiple containers or pods for parallel jobs than to replicate processes for the same task in the same container, but languages such as Java and GoLang are highly concurrent by design, so when utilizing multiple threads with concurrency, you absolutely need to set more than 1 vCore as your CPU request if your app requires it.</p><p>Here is an example of a multi-threaded CPU stress that also has 3 vCPU limits and as you can see, it uses all of its available CPU and is suffering from a huge amount of throttling.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*gvhbWbAo6lUXj1eJ" /><figcaption>Multi-threaded stress test with 3 CPU limit</figcaption></figure><blockquote>The measurement of CPU throttling is a very interesting topic, maybe it will get its own blogpost in the future.</blockquote><p>Note that I didn’t show you the total CPU usage of the node, and in our stress pod example, there isn’t any other CPU-intensive activity on the node. But the stress pod is throttled regardless of this fact due to the CPU limit, causing idle CPU to be wasted.</p><p>I have already explained why the node’s CPU stress is not really a problem, the stressed pod has X CPU shares, and in case other pods will require CPU (that are in their requests), they will get it, and the stressed pod will just gain less idle CPU, being throttled down to its requests.</p><h3>The CPU Limit anti-pattern</h3><p>Let’s see it in action! I have a cluster with one worker node that has 2 vCPUs.</p><p>First, I started 2 pods running a full CPU stress. Both of them have no CPU request or limit, falling into the Best effort QoS class.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*I6kbDdSSEruhhd-G" /><figcaption>Start 2 CPU stressed pods — BestEffort</figcaption></figure><blockquote><em>Containers with no CPU Requests will receive 2 CPU shares by default.</em></blockquote><p>Since there are 2 containers running on the node with the same amount of CPU shares, that want as much CPU as possible, the CFS will split the CPU time between them.</p><p>Now, Let’s start another 2 pods, this time guaranteed QoS class pods with 0.1 CPU request and limit.</p><p>0.1 CPU requests is 100m CPU, which equals to 102 CPU shares. Do you think a “higher” QoS pod with 50 times the CPU shares will get more CPU than the BestEffort pods? Hopefully, by now you understand that the CPU limit in fact prevents this from happening.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*utkuQPEvjSMXtNkM" /><figcaption>Start 2 CPU stressed pods — Guaranteed</figcaption></figure><p>And voilà! The Guaranteed pods get up to the CPU Limits and never more, no matter if there is idle CPU on the node or not.</p><p>Here is a closer look at the CPU allocation for those pods.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*I0pEz0wRkBtIe_cj" /><figcaption>Only the BestEffort pods enjoying the spare CPU on this node</figcaption></figure><p>Notice the small drop in CPU usage? This is from the deployment of the Guaranteed pods, but not because of their QoS class, <strong>only due to the fact that they have more CPU shares</strong>!</p><p>The final step in this experiment is to start another set of 2 pods, this time with the same 0.1 CPU Requests but with <strong>no limit</strong>. Burstable QoS.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*6LIJUoGw6DWasknc" /></figure><p>Notice what happened to the BestEffort pods? No, I didn’t delete them, they just got run down almost completely, to the point you can’t even see them in the graph! This is because the new Burstable pods have much more CPU shares. The Guaranteed pods are ‘guaranteed’ (See what I did there) to get the same amount of CPU no matter what, they are not guaranteed to be top priority pods on the cluster.</p><p>Note that during this time, the node stays consistently on 100% CPU and didn’t crash, not only did it not crash, all of the components on the node like Kubelet, container runtime, SystemD, and the others kept working just fine. The hungry pods fought only for the CPU leftovers.</p><p>❗ The bottom line. CPU limits are only for preventing the use of CPU leftovers, not to prevent noisy neighbors or to protect your nodes from overallocation. Mic dropped.</p><blockquote>🔥 So go ahead and <strong>remove your CPU limits</strong>!</blockquote><h3>When to use CPU limits?</h3><p>But wait, why do CPU limits exist in the first place?</p><p>You may have heard that Google uses CPU limits in their workloads, and assumed that It must be the best practice. Well, it depends on what you’re trying to achieve, <a href="https://youtu.be/nWGkvrIPqJ4?t=1229">Google prefers consistent workloads over performant workloads</a>. It makes much more sense for organizations with many groups that consume resources from one central cluster (or cluster operators). They must have reproducible performance every single time at the group level, before thinking about performance at the organization (or cluster) level.</p><p>Are you Google? Probably not. Most of us are trying to achieve the best possible performance on the cheapest infrastructure while minimizing downtime. <strong>Production workloads should be able to utilize idle CPU</strong>. Containers won’t “steal” CPU from other containers if you set your CPU requests right, if you didn’t set CPU requests or set them badly, I’m afraid that the CPU limit wouldn’t save you.</p><p>Similar to Google’s use case, <a href="https://cloud.google.com/kubernetes-engine/docs/concepts/autopilot-overview">GKE AutoPilot</a> is another great example.</p><p>GKE AutoPilot in a nutshell is a managed Kubernetes cluster, that not only manages the control plane for you but also the nodes, you just need to apply your pods.</p><p>AutoPilot will always <a href="https://cloud.google.com/kubernetes-engine/docs/concepts/autopilot-resource-requests">set CPU requests and limits</a> for you (unlike AWS Fargate), even if you didn’t define it in your pod spec. That will guarantee consistent performance over and over again. You can’t enjoy idle resources but you can be sure that you will always get the same performance no matter what node you’re running on.</p><h3>Real-life use-cases</h3><p>In our day-to-day, we may want to set CPU limits on staging environments to simulate “the worst case scenario (no idle resources to consume)” and to be able to run stress tests without using the idle CPU that can’t and shouldn’t be counted on.</p><p>In production, there is not a good usage for CPU limit, even for low-priority containers. If your goal is to reserve the idle CPU capacity for your important workloads, just adjust the CPU Requests accordingly.</p><h3>CPU resources best practice</h3><p>After months of diving into the Kubernetes resources rabbit hole, the conclusions I’ve come to are:</p><ul><li>Set your CPU Requests as the relative weight you want the container to have. No less than the expected CPU usage.</li><li>Concurrency matters, you can’t run on more cores than your task knows how to utilize, so don’t set CPU requests higher than 1*(number of concurrent threads / processes) you have.</li><li><a href="https://learnk8s.io/production-best-practices#:~:text=Disable%20CPU%20limits%20%E2%80%94%20unless%20you%20have%20a%20good%20use%20case">Never set CPU limits</a> if performance is what you desire.</li></ul><p>This is what Tim Hockin, one of the first <a href="https://www.youtube.com/watch?v=BE77h7dmoQU">creators &amp; maintainers of Kubernetes</a> at Google advised in a tweet a few years back;</p><h3>Tim Hockin (thockin.yaml) on Twitter: &quot;This is why I always advise:1) Always set memory limit == request2) Never set CPU limit(for locally adjusted values of &quot;always&quot; and &quot;never&quot;) / Twitter&quot;</h3><p>This is why I always advise:1) Always set memory limit == request2) Never set CPU limit(for locally adjusted values of &quot;always&quot; and &quot;never&quot;)</p><p>Wait, memory request should be equal to the memory limit? We’ll dive into this in the fourth &amp; final part of this blog. stay tuned!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6ee7d6015965" width="1" height="1" alt=""><hr><p><a href="https://medium.com/directeam/kubernetes-resources-under-the-hood-part-3-6ee7d6015965">Kubernetes resources under the hood — Part 3</a> was originally published in <a href="https://medium.com/directeam">Directeam</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Kubernetes resources under the hood — Part 2]]></title>
            <link>https://medium.com/directeam/kubernetes-resources-under-the-hood-part-2-6eeb50197c44?source=rss----eb217c281961---4</link>
            <guid isPermaLink="false">https://medium.com/p/6eeb50197c44</guid>
            <category><![CDATA[cloud-computing]]></category>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[kubernetes]]></category>
            <category><![CDATA[containers]]></category>
            <category><![CDATA[docker]]></category>
            <dc:creator><![CDATA[Shon Lev-Ran]]></dc:creator>
            <pubDate>Sun, 04 Sep 2022 14:20:37 GMT</pubDate>
            <atom:updated>2022-09-15T07:05:37.370Z</atom:updated>
            <content:encoded><![CDATA[<h3>Kubernetes resources under the hood — Part 2</h3><h4>Do you think that CPU requests are just used for scheduling? Think again. Introducing CPU Shares, and laying the grounds for removing your limits!</h4><p>Co-Authored by@<a href="https://medium.com/@shirmon">shirmon</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*xG65UgQP2Y1hf-Dt.jpg" /></figure><h3>Understanding CPU Requests</h3><p>In the <a href="https://medium.com/@shonlevran/kubernetes-resources-under-the-hood-part-1-4f2400b6bb96">previous post</a>, I talked about the foundation of Kubernetes resource management. In this post, we will dive deeper into what is going on behind the scenes when we configure CPU requests to a pod’s containers.</p><pre>apiVersion: v1<br>kind: Pod<br>metadata:<br>  name: frontend<br>spec:<br>  containers:<br>  - name: app<br>    image: images.my-company.example/app:v4<br>    resources:<br>      requests:<br>        memory: &quot;64Mi&quot;<br>        <strong>cpu: &quot;250m&quot;</strong><br>      limits:<br>        memory: &quot;128Mi&quot;<br>        cpu: &quot;500m&quot; # For the last time!</pre><p>Resource <a href="https://medium.com/@shonlevran/kubernetes-resources-under-the-hood-part-1-4f2400b6bb96#:~:text=for%20scheduling%20decisions.-,Requests,-When%20scheduling%20pods">requests</a> are first and foremost used for scheduling decisions, but is there anything more to CPU requests?</p><h3>CPU Shares</h3><p>When you configure an X amount of vCPUs as a container CPU request in your pod’s manifest, Kubernetes configures (1024 * X) CPU shares for your container.</p><blockquote><em>For example, if I configure 250m for my CPU requests Kubernetes will set 1024 * 250m = 256 CPU shares.</em></blockquote><p>So what are CPU shares and what do they do?</p><p>To understand CPU shares, let’s talk first about the Kernel mechanism called CFS (<a href="https://en.wikipedia.org/wiki/Completely_Fair_Scheduler">Completely Fair Scheduler</a>).</p><h3>CFS — Completely Fair Scheduler</h3><p>CFS is the default Linux CPU scheduler and is in charge of allocating CPU time between processes fairly.</p><p>The “completely fair” part is not as simple as it sounds, it uses a few parameters to decide what is the relative weight (priority) of each process. Many of you may be familiar with the “nice” setting that can be set for processes to change their relative weight. But currently, Kubernetes doesn’t use nice to affect the processes’ weight, instead, it configures CPU shares for a CGroup.</p><p>So, CPU shares are a Linux CGroup feature that is designed to prioritize CGroup processes for the CFS to allocate more CPU time <strong>at times of congestion</strong> to the higher priority processes.</p><h4>Let me explain;</h4><p>Let’s think of a single CPU timeframe (1 second for example) as a pizza. Every second a new pizza comes out of the oven, processes eat what they need from it, and then it’s gone. If all of my processes are not hungry enough to eat all the pizza in 1 second, they will eat their fill until the time is over and a new CPU-second-pizza will come out of the oven. Yummy! 🍕</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/400/0*nKKa1e-qRmq-gBG1.png" /><figcaption>CPU feeding Homer</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*w-sW65hCWqc-91Fs.png" /><figcaption>Sufficient CPU per second</figcaption></figure><p>The complications start when our processes are hungry and 1 pizza every second is not enough to feed them.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*oKrkwin8mgEUBscZ.png" /><figcaption>Insufficient CPU per second</figcaption></figure><p>When there is not enough CPU time (or pizza) for all of my processes, CFS will look at the shares every CGroup has, will cut the pizza into the sum of all shares, and will split it accordingly.</p><blockquote><strong>In the case that many of the processes in the CGroup want more CPU than available, the slice that each CGroup receives will be evenly distributed between the processes in that CGroup.</strong></blockquote><p>So for example, if processes in 5 CGroups are requesting the maximum amount of CPU possible, and each of the CGroups has an equal amount of CPU shares, then the CPU time will be distributed evenly between the CGroups.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*mtKOELiW9WrAv3sL.png" /><figcaption>CPU shared between CGroups with the same amount of shares</figcaption></figure><p>Another example is (Staying in the state that all processes are requesting as much CPU as possible); if I have 3 CGroups with 1024 CPU shares each, and one other CGroup with 3072 shares the first 3 CGroups will get 1/6 of the CPU, and the last CGroup will get half (3/6)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*h4mj8B_C66tahmdy.png" /><figcaption>CPU shared between CGroups with different amounts of shares</figcaption></figure><p>Remember, all of this only matters if I’m lacking CPU, if I have 3 CGroups with X CPU shares that need a lot of CPU and the fourth CGroup with 1000X CPU shares that is idle, the first 3 will split the CPU equally.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*NLM3YVAZBRzvwS0F.png" /><figcaption>CPU shared only between hungry CGroups</figcaption></figure><p><em>Can my container </em>even<em> have 1,048,576 CPU shares on Kubernetes? Only if my node has more than 1024 CPU cores such as the </em><a href="https://parallella.org/2016/10/05/epiphany-v-a-1024-core-64-bit-risc-processor/"><em>Epiphany-V</em></a><em>, but I’m sure most of us don’t have those kinds of nodes.</em></p><h4>How Kubernetes uses these features</h4><p>So as I’ve said, Kubernetes CPU requests configure CPU shares for our containers CGroups,</p><p>Shares “over-commitment” is prevented by Kubernetes magic; On one hand, the scheduler only schedules on each node the total amount of CPU requests to be lower or equal to the amount of CPU on the node (allocatable — see <a href="https://medium.com/@shonlevran/kubernetes-resources-under-the-hood-part-1-4f2400b6bb96#:~:text=Then%2C%20it%20calculates,and%20ephemeral%20storage.">previous part</a>). On the other hand, the CPU shares you provision can be up to 1024 times the number of cores. That sets a cap on the maximum number of shares that can be used by the pods, and the ratio remains.</p><blockquote>The sum of CPU shares your containers can have on Kubernetes is 1024 times the number of allocatable CPUs you have in your cluster.</blockquote><h3>Real-life examples</h3><p>I tried to make the previous examples as simple as possible so I removed some important parameters such as:</p><ul><li>Threads and processes count in each CGroup</li><li>The CPU consumed by the node (other than your running pods)</li></ul><p>There are some other parameters that don’t take effect although you might think so. Such as:</p><ul><li>Quality of Service (QoS)</li><li>Pod priority</li><li>Evictions</li></ul><p>Let’s have a shallow dive into them;</p><h4>Thread Count</h4><p>When we run just a single process in our container, if that process only creates a single thread, it can not consume more than one core anyway. When you set CPU requests to your containers, <a href="https://shonlevran.medium.com/kubernetes-resources-under-the-hood-part-3-6ee7d6015965#:~:text=Bonus%20myth%3A,app%20requires%20it.">always bear in mind the number of threads they will run</a>.</p><p>A side note — <strong>threads are not free</strong>, try not to use too many treads as each thread brings its own overhead, and increase the number of replicas instead.</p><h4>Node Load</h4><p>The bar charts from earlier are for isolated processes, but not all processes are isolated. Not to worry! The CGroups for your containers are pretty low on the CGroups hierarchy.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ia_GVVf1qispoJoqLRIiAw.png" /><figcaption>Simple Kubernetes CGroups map</figcaption></figure><p>Maybe while reading you already went to check how many CPU shares your Kubelet has to make sure it’s not deprived. Don’t worry, Your pods and containers are just sharing the CPU time “kubepods” CGroup is eligible for. If the Kubelet, the container runtime, or other services on the node need CPU time, they will get it.</p><blockquote>Don’t worry when setting high CPU requests, the node’s components are higher priority out of the box.</blockquote><h4><a href="https://medium.com/@shonlevran/kubernetes-resources-under-the-hood-part-1-4f2400b6bb96#:~:text=We%20can%20specify%20resource%20requests%20and%20limits%20for%20the%20containers%20in%20our%20pod%3B%20based%20on%20those%20parameters%20Kubernetes%20also%20assigns%20a%20QoS%20class%20(Quality%20of%20Service)%20to%20our%20pods.">Quality of Service</a></h4><p>Kubernetes is configuring CGroups per QoS, currently, they have no real function and they exist for future use.</p><blockquote>In terms of CPU time and priority, the CPU Request is the only thing that matters.</blockquote><p>So what will happen if you don’t set CPU Requests? The container will get 2 CPU shares by default and will have a very low priority compared to pods that have CPU requests configured.</p><p>CPU time allocation will be the same both for burstable and best-effort pods. Guaranteed will have another parameter impacting the CPU time. More on that in the <a href="http://CPU time allocation will be the same both for burstable and best-effort pods. Guaranteed will have another parameter impacting the CPU time. More on that in the next part.">next part</a>.<br>Bottom line is that the QoS doesn’t directly affect the CPU time a pod&#39;s containers will receive. The only thing matter is CPU shares (and limits if you still use them).</p><h4>Pod Priority</h4><p>“It’s OK, I set pod priority.” — Sorry but not exactly…</p><p>Pod priority is only used to determine the termination order on node evection, and as we’ve mentioned; There is <a href="https://medium.com/@shonlevran/kubernetes-resources-under-the-hood-part-1-4f2400b6bb96#:~:text=There%20is%20no%20eviction%20for%20incompressible%20resources!">no eviction caused by CPU pressure</a>.</p><h4>Evictions</h4><p>Eviction is a process running on the node that chooses and kills pods when the node is low on resources. Eviction only happens for in-compressible resources like memory, disk space, etc. more on that in the fourth part.</p><h3>Not just for scheduling</h3><p>We learned that CPU requests are used not only for scheduling purposes but also for the lifetime of the container. Memory requests also have their deep layers, more on that in part four.</p><p>Also, we talked only about normal Kubernetes behavior, there are many other options like <a href="https://kubernetes.io/docs/tasks/administer-cluster/cpu-management-policies/#static-policy">CPU pinning</a> that sets exclusive CPU cores per container. That’s outside of the scope of this article, but we may get into it in the future 😄</p><h3>To summarize;</h3><p>We learned that CPU requests are not used just for scheduling, but also take a huge part in the whole container lifecycle! We learned the importance of setting the correct requests to configure the right amount of CPU shares for each container and why configurations such as QoS don’t really affect our workloads.</p><blockquote>Remember! CPU requests configure how much CPU will be Guaranteed to your container throughout its lifecycle!</blockquote><p><a href="https://shonlevran.medium.com/kubernetes-resources-under-the-hood-part-3-6ee7d6015965"><strong>Part 3</strong></a><strong> is out! Explains all about why you should remove your CPU limits.</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6eeb50197c44" width="1" height="1" alt=""><hr><p><a href="https://medium.com/directeam/kubernetes-resources-under-the-hood-part-2-6eeb50197c44">Kubernetes resources under the hood — Part 2</a> was originally published in <a href="https://medium.com/directeam">Directeam</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Kubernetes resources under the hood — Part 1]]></title>
            <link>https://medium.com/directeam/kubernetes-resources-under-the-hood-part-1-4f2400b6bb96?source=rss----eb217c281961---4</link>
            <guid isPermaLink="false">https://medium.com/p/4f2400b6bb96</guid>
            <category><![CDATA[docker]]></category>
            <category><![CDATA[kubernetes]]></category>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[cloud-computing]]></category>
            <category><![CDATA[containers]]></category>
            <dc:creator><![CDATA[Shon Lev-Ran]]></dc:creator>
            <pubDate>Sun, 04 Sep 2022 14:17:37 GMT</pubDate>
            <atom:updated>2022-09-04T14:17:36.973Z</atom:updated>
            <content:encoded><![CDATA[<h3>Kubernetes resources under the hood — Part 1</h3><h4>I’m sure we’re all familiar with the ‘resources’ block of containers in a pod. But do we really know what Kubernetes uses them for under the hood?</h4><p>Co-Authored by@<a href="https://medium.com/@shirmon">shirmon</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*KcDfk50gtiskFFLP.jpg" /></figure><p>One of the very first things that we are taught by the community when starting to use Kubernetes is always to set requests and limits for CPU and memory on every container in our pods.</p><blockquote><em>When you specify a </em><a href="https://kubernetes.io/docs/concepts/workloads/pods/"><em>Pod</em></a><em>, you can optionally specify how much of each resource a </em><a href="https://kubernetes.io/docs/concepts/containers/"><em>container</em></a><em> needs. The most common resources you’ll specify are CPU and memory (RAM); there are others. </em><a href="https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#:~:text=When%20you%20specify,there%20are%20others."><em>source</em></a></blockquote><pre>apiVersion: v1<br>kind: Pod<br>metadata:<br>  name: frontend<br>spec:<br>  containers:<br>  - name: app<br>    image: images.my-company.example/app:v4<br>    resources:<br>      requests:<br>        memory: &quot;64Mi&quot;<br>        cpu: &quot;250m&quot;<br>      limits:<br>        memory: &quot;128Mi&quot;<br>        cpu: &quot;500m&quot;</pre><blockquote><em>If a container specifies its own resource limit but does not specify a resource request, then Kubernetes automatically assigns a resource request that matches the specified limit. </em><a href="https://kubernetes.io/docs/tasks/configure-pod-container/quality-service-pod/#:~:text=If%20a%20Container%20specifies%20its%20own,CPU%20request%20that%20matches%20the%20limit."><em>source</em></a></blockquote><p>However, after years of experience with many use cases and having to investigate many resources-related issues, I have discovered that Kubernetes resource management is a lot more complex than it seems.</p><h3>Let’s start from the beginning</h3><p>Kubernetes is a container orchestrator that deploys workloads (pods) over a pool of resources (nodes). Of course, this is a huge simplification since Kubernetes is a lot more complex and schedules pods using many different parameters, but what I want to dig into in this article (if it’s not already obvious) is how Kubernetes manages container resources.</p><p>So which resources can Kubernetes manage? Containers consume many kinds of resources. The obvious ones are resources like CPU and Memory, but they can also consume other resources such as disk space, disk time (I/O), network bandwidth, process IDs, host ports, IP addresses, GPU, power, and more!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*Jgg_F47WP6NocEzY.png" /><figcaption>Pods requests and nodes resources</figcaption></figure><h3>First, let’s take a deep dive into containers</h3><h4>So, what are containers really?</h4><blockquote><em>In a nutshell, containers are a set of Linux namespaces.</em></blockquote><p>So, what are <a href="https://en.wikipedia.org/wiki/Linux_namespaces">Linux namespaces</a>?</p><p>Linux namespaces are a Linux kernel functionality that partitions kernel resources such that a process or set of processes in the same Linux namespace can see a set of kernel resources and are isolated from processes in other namespaces. Some examples of these namespaces are PID, UID, Cgroups &amp; IPC (see the complete list in the <a href="https://en.wikipedia.org/wiki/Linux_namespaces">wiki</a>).</p><p>Another thing to know about namespaces is that they are nested, meaning namespaces can be inside other namespaces. Child namespaces are isolated from their parent namespaces, but the parent namespaces can see everything within the child namespaces.</p><p>Technically speaking, when running a Linux machine, you are already inside a container (since you are in the first set of namespaces). We utilize the isolation advantages of containers when creating another set of namespaces in the same system.</p><p>So, when spinning up a container, it creates a set of these namespaces and runs your application inside them. This is also why inside of a container, you will see the PID of your application usually set as 1 (or a low number depending on what you’re running), while outside of the container (in the main PID namespace), the PID of your application will be a far larger number. This is the same process, but the PID in the container is mapped to the higher PID in the main namespace and isolated from it and any other sets of namespaces (other containers).</p><p>Namespaces give us the ability to isolate processes from each other, but what about resource consumption? If all of our containers think they are operating in isolation, couldn’t they consume too much of the resources and impact the others? This phenomenon is known as <em>noisy neighbors</em>.</p><p>So how can we deal with noisy neighbors? One approach is to limit the resources each process can consume, and (surprise, surprise) the Linux kernel has another feature up its sleeve that can do just this, called Control groups (Cgroups). These are configured for each process to limit, account for, and isolate the resources they each consume. Using this functionality, Kubernetes can limit the resource usage of containers.</p><p>Currently, Kubernetes uses Cgroups v1, but another player has entered the arena (for the last five years), <a href="https://medium.com/some-tldrs/tldr-understanding-the-new-control-groups-api-by-rami-rosen-980df476f633#:~:text=In%20cgroups%20v1%2C%20a%20process,only%20to%20a%20single%20subgroup">Cgroups v2</a>! Their current use would be for Memory Quality of Service (QoS), which, since 1.22 is in alpha, has opened a whole new world of possibilities. You can read all about it <a href="https://kubernetes.io/blog/2021/11/26/qos-memory-resources/">here</a>.</p><h4>What resources are currently managed by Kubernetes?</h4><p>Kubernetes by itself currently only manage a fraction of the resources present. First of all, it lists the capacity for each resource on its nodes.</p><pre># You can see it using kubectl.<br>kubectl get node -ojson | jq &#39;.items[].status.capacity&#39; <br>{<br>  &quot;cpu&quot;: &quot;2&quot;,<br>  &quot;ephemeral-storage&quot;: &quot;52416492Ki&quot;,<br>  &quot;hugepages-1Gi&quot;: &quot;0&quot;,<br>  &quot;hugepages-2Mi&quot;: &quot;0&quot;,<br>  &quot;memory&quot;: &quot;8003232Ki&quot;,<br>  &quot;pods&quot;: &quot;110&quot;<br>}</pre><p>Then, it calculates the <a href="https://kubernetes.io/docs/tasks/administer-cluster/reserve-compute-resources/#node-allocatable">allocatable amount</a> used for pods scheduling. The allocatable resources of a node are calculated by subtracting a buffer of reserved resources for the <a href="https://kubernetes.io/docs/tasks/administer-cluster/reserve-compute-resources/#system-reserved">Linux system</a>, <a href="https://kubernetes.io/docs/tasks/administer-cluster/reserve-compute-resources/#kube-reserved">kubelet</a>, and the <a href="https://kubernetes.io/docs/tasks/administer-cluster/reserve-compute-resources/#eviction-thresholds">eviction threshold</a> from the node’s total resources. As of 1.21, the kubelet only calculates the allocatable resources for CPU, memory, huge pages, and ephemeral storage.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/580/0*MDJ8AI_Pg0hhG_CW.png" /><figcaption>Nodes capacity components</figcaption></figure><pre>kubectl get node -ojson | jq &#39;.items[].status.allocatable&#39; <br>{<br>  &quot;cpu&quot;: &quot;1930m&quot;,<br>  &quot;ephemeral-storage&quot;: &quot;47233297124&quot;,<br>  &quot;hugepages-1Gi&quot;: &quot;0&quot;,<br>  &quot;hugepages-2Mi&quot;: &quot;0&quot;,<br>  &quot;memory&quot;: &quot;7313056Ki&quot;,<br>  &quot;pods&quot;: &quot;110&quot;<br>}</pre><p>Each allocatable resource is a vector that the Kubernetes scheduler uses for scheduling decisions.</p><h3>Requests</h3><p>When scheduling pods, <strong>the scheduler only considers the pod’s container requests against the allocatable resources</strong> (which naturally lowers the amount of allocatable resources, so the next pods requests will have fewer allocatable resources it can request to be scheduled). <strong>It does not consider the actual resource usage</strong> on the node (i.e. containers that use resources over or below their requests).</p><p>If the containers in my pod have no requests assigned, Kubernetes can schedule them to any nodes (if, of course, there are no other scheduling restrictions).<br>By default, Kubernetes can schedule up to 110 pods per node.</p><p>Since Kubernetes 1.21, the <a href="https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#resource-types">main resources you can request from Kubernetes </a>are CPU, Memory, Ephemeral storage, and HugePages. In addition, you can accomplish scheduling by requesting custom resources using <a href="https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#extended-resources">extended resources</a> (which can also be applied with controllers such as the <a href="https://github.com/NVIDIA/k8s-device-plugin">Nvidia controller</a> for GPU).</p><p>Note that you can also limit <a href="https://kubernetes.io/docs/concepts/policy/pid-limiting/">PIDs</a> consumption per pod at the node level.</p><p>So we’ve learned that resource requests are important for scheduling (Not just for scheduling, see <a href="https://medium.com/@shonlevran/kubernetes-resources-under-the-hood-part-2-6eeb50197c44">next part</a> for more information), where all of the requested resources must be available in the node, including extended resources.<br>We’ll dive deeper into the other effects of CPU requests in the <a href="https://medium.com/@shonlevran/kubernetes-resources-under-the-hood-part-2-6eeb50197c44">second part of this blog post</a>.</p><h3>Limits</h3><p>Resources are considered both for scheduling and runtime. To limit our containers from overloading and consuming too many resources, Kubernetes utilizes Cgroups. Kubernetes uses container limits to define the Cgroups and limit their resource consumption.</p><h3>Compressible vs. incompressible resources</h3><p>I want to take a step back for a moment to talk about the two different types of resources, <a href="https://en.wikipedia.org/wiki/System_resource#:~:text=One%20can%20also,will%20slow%20significantly">compressible and incompressible</a>.</p><p>A compressible resource means that if the usage of this resource reaches its maximum, the processes that require this resource will have to <strong>wait</strong> until the resource becomes free. In other words, <strong>throttling</strong> the processes.</p><p>Think of it as a water dam; when the outlet pipes of the dam are full, and the flowing water arriving at the dam exceeds these pipes’ capacity, the water inside the dam will fill up. Usually, we measure compressible resources by time.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*IiT83jkJnejMkeFd" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/400/0*EdYk8Q8GDUfwHkX_" /><figcaption>Dam of compressible CPU throttling</figcaption></figure><p>CPU is a compressible resource, meaning if the CPU usage is at 100%, a process that requires CPU will need to wait until they receive CPU time.</p><blockquote>There is no eviction for compressible resources!</blockquote><p>On the other hand, a resource being incompressible means processes cannot wait for it; either they cannot run, or something else has to stop and release resources for the new process.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*1pN4mCRNfkxMQiD3" /><figcaption>Incompressible box shelves</figcaption></figure><p>Think of it like putting boxes on shelves, once the shelves are filled with boxes you cannot put another box on the shelf. You either have to make room by removing boxes from the shelf or not placing the box on the shelf at all. Memory is an incompressible resource, meaning if you are out of memory and want to allocate memory for a new or existing process you have to either kill a process that is taking up memory space or the process will crash.</p><p>For Kubernetes, the only compressible resource that it manages is the CPU. The other resources Kubernetes manages (memory, HugePages, Ephemeral storage, and PIDs) are all incompressible.</p><p>When you specify limits for compressible resources like CPU, Kubernetes makes sure to throttle them when they try to consume more than their allowable levels. On the other hand, Kubernetes has to deal with limits for incompressible resources using eviction. We will dig into this in the upcoming blog posts.</p><h3>Requests vs. Limits</h3><p>So we know we use resource requests as our “manual” guide for the Kubernetes scheduler to make scheduling decisions based on the minimum amount that we need to ensure our workload.</p><p>We can also use resource limits as instructions to Kubernetes for which Cgroups it should configure for our containers and their thresholds.</p><p>When using extended resources, Kubernetes will use requests for scheduling but will not use the limits to set any Cgroups and limit those special resources usage.</p><h3>Quality of Service — Not really the bottom line</h3><p>We can specify resource requests and limits for the containers in our pod; based on those parameters Kubernetes also assigns a <a href="https://kubernetes.io/docs/tasks/configure-pod-container/quality-service-pod/#qos-classes">QoS</a> class (Quality of Service) to our pods.</p><pre># Try this command to view your current QoS.<br>kubectl get pods -A -o=jsonpath=&#39;{range .items[*]}{.metadata.namespace}{&quot; : &quot;}{.metadata.name}{&quot; --QoS--&gt; &quot;}{.status.qosClass}{&quot;\n&quot;}{end}&#39;</pre><p>As good as it sounds, quality of service is not the last word in terms of pods’ priorities. This parameter is visible to us, as Kubernetes users, to estimate the probable priority of our pod in case of high resource stresses and eviction events. There is a lot more to it, such that so-called lower QoS pods might survive eviction events while higher QoS class pods may be terminated.</p><p>By the end of this blog series, you will know everything you need to know about the implication of QoS.</p><p>First of all, there are three classes of QoS:</p><ul><li>Guaranteed</li><li>Burstable</li><li>BestEffort</li></ul><p>For a Pod to have a QoS class of Guaranteed, every container in the Pod must have both memory and CPU with limits and requests that are equal.</p><p>A Pod has a QoS class of Burstable if the Pod has at least one Container with a memory or CPU request.</p><p>For a Pod to have a QoS class of BestEffort, the Containers in the Pod must not have any memory or CPU limits or requests.</p><p>Note that this only uses CPU and memory for calculating the QoS class of the pod.</p><p>Regarding the usage of QoS, you should be aware:</p><ul><li>It’s used to set the OOM_Score_adj parameter — more on that in part 4.</li><li>It’s used to set <a href="https://medium.com/@shonlevran/kubernetes-resources-under-the-hood-part-2-6eeb50197c44#:~:text=The%20bar%20charts%20from%20earlier%20are%20for%20isolated%20processes%2C%20but%20not%20all%20processes%20are%20isolated.%20Not%20to%20worry!%20The%20CGroups%20for%20your%20containers%20are%20pretty%20low%20on%20the%20CGroups%20hierarchy.">QoS Cgroups</a> — which so far have no effect and is a future QoS feature.</li></ul><h3>To summarize;</h3><p>So that was a lot of information to go through, and this first part was just getting the basics out of the way.</p><p><strong>The </strong><a href="https://medium.com/@shonlevran/kubernetes-resources-under-the-hood-part-2-6eeb50197c44"><strong>second part</strong></a><strong> of this blog is out</strong>, we will start digging into the whys and whats of these features to understand exactly how Kubernetes uses them and what you should be putting in your resource requests and limits!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4f2400b6bb96" width="1" height="1" alt=""><hr><p><a href="https://medium.com/directeam/kubernetes-resources-under-the-hood-part-1-4f2400b6bb96">Kubernetes resources under the hood — Part 1</a> was originally published in <a href="https://medium.com/directeam">Directeam</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>