The resource limit of Pod has been set as:
resource
limit
cpu: 500m
memory: 5Gi
and there's 10G mem left on the node.
I've created 5 pods in a short time successfully, and the node maybe still have some mem left, e.g. 8G.
The mem usage is growing as the time goes on, and reach the limit (5G x 5 = 25G > 10G), then the node will be out of response.
In order to ensure the usability, is there a way to set the resource limit on the node?
Update
The core problem is that pod memory usage does not always equal to the limit, especially in the time when it just starts. So there can be unlimited pods created as soon as possible, then make all nodes full load. That's not good. There might be something to allocate resources rather than setting the limit.
Update 2
I've tested again for the limits and resources:
resources:
limits:
cpu: 500m
memory: 5Gi
requests:
cpu: 500m
memory: 5Gi
The total mem is 15G and left 14G, but 3 pods are scheduled and running successfully:
> free -mh
total used free shared buff/cache available
Mem: 15G 1.1G 8.3G 3.4M 6.2G 14G
Swap: 0B 0B 0B
> docker stats
CONTAINER CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O
44eaa3e2d68c 0.63% 1.939 GB / 5.369 GB 36.11% 0 B / 0 B 47.84 MB / 0 B
87099000037c 0.58% 2.187 GB / 5.369 GB 40.74% 0 B / 0 B 48.01 MB / 0 B
d5954ab37642 0.58% 1.936 GB / 5.369 GB 36.07% 0 B / 0 B 47.81 MB / 0 B
It seems that the node will be crushed soon XD
Update 3
Now I change the resources limits, request 5G and limit 8G:
resources:
limits:
cpu: 500m
memory: 5Gi
requests:
cpu: 500m
memory: 8Gi
The results are:
According to the k8s source code about the resource check:
The total memory is only 15G, and all the pods needs 24G, so all the pods may be killed. (my single one container will cost more than 16G usually if not limited.)
It means that you'd better keep the requests exactly equals to the limits in order to avoid pod killed or node crush. As if the requests value is not specified, it will be set to the limit as default, so what exactly requests used for? I think only limits is totally enough, or IMO, on the contrary of what K8s claimed, I rather like to set the resource request greater than the limit, in order to ensure the usability of nodes.
Update 4
Kubernetes 1.1 schedule the pods mem requests via the formula:
(capacity - memoryRequested) >= podRequest.memory
It seems that kubernetes is not caring about memory usage as Vishnu Kannan said. So the node will be crushed if the mem used much by other apps.
Fortunately, from the commit e64fe822, the formula has been changed as:
(allocatable - memoryRequested) >= podRequest.memory
waiting for the k8s v1.2!
Kubernetes resource specifications have two fields, request and limit.
limits place a cap on how much of a resource a container can use. For memory, if a container goes above its limits, it will be OOM killed. For CPU, its usage may be throttled.
requests are different in that they ensure the node that the pod is put on has at least that much capacity available for it. If you want to make sure that your pods will be able to grow to a particular size without the node running out of resources, specify a request of that size. This will limit how many pods you can schedule, though -- a 10G node will only be able to fit 2 pods with a 5G memory request.
Kubernetes supports Quality of Service. If your Pods have limits set, they belong to the Guaranteed class and the likelihood of them getting killed due to system memory pressure is extremely low. If the docker daemon or some other daemon you run on the node consumes a lot of memory, that's when there is a possibility for Guaranteed Pods to get killed.
The Kube scheduler does take into account memory capacity and memory allocated while scheduling. For instance, you cannot schedule more than two pods each requesting 5 GB on a 10GB node.
Memory usage is not consumed by Kubernetes as of now for the purposes of scheduling.
Related
I have below resource limits in kubernates pod. where as my image starts with jvm args .
we have added resource limit less than min/max heap . java process started to run for some time and pod got killed abruptly with OutOfmemory.
How can pod start if memory specified in resource limit is 3 times less value ? Could some one help on this ?
cmd:
java -Xmx1512m -Xms1512m $LOGARGS -jar test-ms.jar
pod resourcelimits:
resources:
limits:
cpu: 300m
memory: 500Mi
requests:
cpu: 150m
memory: 300Mi
/start.sh: line 19: 7 Killed java -Xmx1512m -Xms1512m $LOGARGS -jar test-ms.jar
At 500Mi your but is evicted. If Java requires 1500, this cant work. Raise the memory value in the limit section, play with the value. Your container does not only need memory for Java.
Update to your comment:
Means that when the container reach 500Mi (500 MiB = 524.288 MB) the pod is restarted. To avoid that the pod use to much memory (ex. 10GB) because something inaspect happens. Memoryleaks for example. You limit the memory so that also other pods can run on the node. You must get what is a normal scenario for memory inside your container. As you are setting memory requirements for java, you can check if you really need them. If your cluster has metrics installed like prometheus.
https://github.com/kubernetes-sigs/metrics-server
You can install:
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/high-availability-1.21+.yaml
Then to analyse Cpu and memory:
kubectl top node // shows values for the nodes
kubectl top pod // shows values for the pods
Refere to the documentation if you want to use it.
While your container is running, you can also get inside and execute the normal top linux command.
I am deploying some pods in Azure Kubernetes Service. When I deploy the pods with CPU requests for 100m I can see the 5 pods are running. Now with this state I run some performance tests and benchmark my result.
Now I redeploy the pods with CPU requests of 1 CPU and run same tests again. I can see that the pods are created successfully in both the cases and are in running state.
Shouldnt I see better performance results? Can someone please explain. Below is deployment file. CPU request for first test is 100m and for second is 1. If no performance difference is expected how to improve performance?
resources:
limits:
cpu: 3096m
memory: 2Gi
requests:
cpu: 100m
memory: 1Gi
CPU requests are mostly more important for the kube-scheduler to identify the best node suitable to place a pod. If you set CPU requests = 1 for every workload there will be no more capacity soon to schedule new pods.
Furthermore assigning more CPU requests to a pod does not automatically mean that the container/application will consume this.
CPU limits on the other hand can be responsible for CPU throttling in Kubernetes bcs they limit the time pods can consume the CPU.
Here is a great article about it.
Basically there are a lot of articles about about to no limit the CPU to avoid kernel throttling but from my experience throttling of a pod is less harmless than a pod going crazy and consume the whole CPU of a node. So i would recommend to not overcommit resources and set requests=limits.
You can also check the capacity and allocated resources of your nodes:
kubectl describe node <node>:
Capacity:
cpu: 4
ephemeral-storage: 203070420Ki
memory: 16393308Ki
Allocatable:
cpu: 3860m
ephemeral-storage: 187149698763
memory: 12899420Ki
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.)
Resource Requests Limits
-------- -------- ------
cpu 1080m (27%) 5200m (134%)
memory 1452Mi (11%) 6796Mi (53%)
I have a Kubernetes cluster of around 18 nodes where few are with 4 cores and 16G RAM, and few are with 16 core and 64G RAM, and there are around 25-30 applications running on
the cluster.
Each of the applications are configured with requests and limit parameter, around 2-3cores & 4-8G ram and allocated to each of the application.
Now how do I get the current utilization report saying how many cores/ram I am left within the current cluster? before deploying any new application.
I tried using the below commands:
kubectl top no; kubectl describe no [node-name]
These are not giving me the exact no. of cores or ram I am left with.
Any leads to this will help a lot.
Note: I am using version 1.19 of Kubernetes.
You can use a kubectl plugin to view the resourses capacity, usage etc.
Here, are few related plugins.
etopeter/kubectl-view-utilization
davidB/kubectl-view-allocations
robscott/kube-capacity
You can use krew to install those plugins.
kubectl describe node <insert-node-name-here>
You should see something like this:
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.)
Resource Requests Limits
-------- -------- ------
cpu 1130m (59%) 3750m (197%)
memory 4836Mi (90%) 7988Mi (148%)
ephemeral-storage 0 (0%) 0 (0%)
hugepages-1Gi 0 (0%) 0 (0%)
hugepages-2Mi 0 (0%) 0 (0%)
attachable-volumes-azure-disk 0 0
I am running postgres timescaledb on my docker swarm node. I set limit of CPU to 4 and Mem limit to 32G. When I check docker stats, I can see this output:
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
c6ce29c7d1a4 pg-timescale.1.6c1hql1xui8ikrrcsuwbsoow5 341.33% 20.45GiB / 32GiB 63.92% 6.84GB / 5.7GB 582GB / 172GB 133
CPU% is oscilating around 400%. Node has 6CPUs and average load has been 1 - 2 (1minute load average), So according to me, with my limit of CPUs - 4, the maximum load should be oscilating around 6. My current load is 20 (1minute load average), and output of top command from inside of postgres show 50-60%.
My service configuration limit:
deploy:
resources:
limits:
cpus: '4'
memory: 32G
I am confused, all values are different so what is real CPU usage of postgres and how to limit it ? My server load is pushed to maximum even limit of postgres is set to 4. Inside postgres I can see from htop that there is 6 cores and 64G MEM so its looks like it has all resources of the hosts. From docker stats maximum cpu is 400% - corelate with limit of 4 cpus.
Load average from commands like top in Linux refer to the number of processes running or waiting to run on average over some time period. CPU limits used by docker specify the number of CPU cycles over some timeframe permitted for processes inside of a cgroup. These aren't really measuring the same thing, especially when you factor in things like I/O waiting. You can have a process waiting for a read from disk, that wants to run but is blocked on that I/O call, increasing your load measurements on the host, but not using any CPU cycles.
When calculating how much CPU to allocate to a cgroup, no only do you need to factor in the I/O and other system needs of the process, but consider queuing theory when you approach saturation on the CPU. The closer you get to 100% utilization of the CPU, the longer the queue of processes ready to run will likely be, resulting in significant jumps in load measurements.
Setting these limits correctly will likely require trial and error because not all processes are the same, and not all workload on the host is the same. A batch processing job that kicks off at irregular intervals and saturates the drives and network will have a very different impact on the host from a scientific computation that is heavily CPU and memory bound.
So I have a simple Go web app I deployed as a Docker container. I am running a t2.small instance on AWS with CoreOS AMI.
The container is very small, only using about 10MB of memory according to docker stat:
CONTAINER CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O
8e230506e99a 0.00% 11.11 MB / 2.101 GB 0.53% 49.01 MB / 16.39 MB 1.622 MB / 0 B
However the CoreOS instance seems to be using a lot of memory:
$ free
total used free shared buffers cached
Mem: 2051772 1686012 365760 25388 253096 1031836
-/+ buffers/cache: 401080 1650692
Swap: 0 0 0
As you can see it's using almost 1.7GB of memory of its 2GB total memory with only about 300MB left. And this seems to be slowly getting worse.
I've had the instance running for about 3 days now and the free memory started at around 400MB after fresh launch and starting a single Docker container.
Is this something I should worry about? Or is CoreOS supposed to use so so much memory when my little Go app in a container only uses tiny 10MB.
Because a lot of that memory usage is buffers and cache. The better indicator is your application from Docker (which is likely close if it is a small Go app) and the OS total usage minux buffers and cache on the second line (which is closer to 400 MB used).
See https://unix.stackexchange.com/a/152301/6515 for a decent explanation.