From e7f6f596ff593852305eec5d2b1bf9d34a10e523 Mon Sep 17 00:00:00 2001 From: Yoni Date: Sun, 14 Jun 2020 13:04:42 +0300 Subject: [PATCH 1/5] Memory limit - 1st draft --- README.md | 6 +-- sections/docker/memory-limit.md | 76 +++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 sections/docker/memory-limit.md diff --git a/README.md b/README.md index 2d87bcd6..431435c9 100644 --- a/README.md +++ b/README.md @@ -1131,11 +1131,11 @@ Bear in mind that with the introduction of the new V8 engine alongside the new E


-## ![βœ”] 8.6. Set Docker memory limits which are in-par with v8 memory limit +## ![βœ”] 8.6. Set memory limits using Docker only -**TL;DR:** +**TL;DR:** Configure a memory limit using Docker, not using V8. Use Docker command flag 'run --memory' or set the right values within the platform that runs Docker. By doing this, the runtime will be capable of making better decisions on when to scale, prevent one citizen from starving others, drive thoughtful crash decisions (e.g., Docker can allow slight burst deviations) and in-overall it's always better to move HW decisions to the OPS court -**Otherwise:** +**Otherwise:** When setting limits using V8 --max-old-space-size the Docker runtime won't be aware of its capacity limits and will have to blindly place it in an instance that might not have the right size πŸ”— [**Read More: Set Docker memory limits which are in-par with v8 memory limit**](/sections/docker/file.md) diff --git a/sections/docker/memory-limit.md b/sections/docker/memory-limit.md new file mode 100644 index 00000000..58389151 --- /dev/null +++ b/sections/docker/memory-limit.md @@ -0,0 +1,76 @@ +# Set memory limits using Docker only + +

+ +### One Paragraph Explainer + +A memory limit tells the process/container the maximum allowed memory usage - a request or usage beyond this number will kill the process (OOMKill). Applying this is a great practice to ensure one citizen doesn't drink alone all the juice and leave other components to starve. Memory limits also allow the runtime to place a container in the right instance - placing a container that consumes 500MB in an instance with 300MB memory available will lead to failures. Two different options allow configuring this limit: V8 flags (--max-old-space-size) and the Docker runtime. There is confusion around which of those to set, some configure both. The better option would be to set the limit on the Docker command or the Docker runtime (e.g. Kubernetes) as is has a much wider perspective for making the right decisions. First, given this limit, the runtime knows how to scale and create more resources. It can also make a thoughtful decision on when to crash - if a container has a short burst in memory request and the hosting instance is capable of supporting this, Docker will let the container stay alive. Docker also measures the actually used memory and not the allocated part so it can get Killed only when really needed. Last, With Docker the Ops experts can set various production memory configurations that can be taken into account like memory swap. On the contrary, when setting the limit on V8 - each of the described scenarios will not be supported. + +

+ +### Code Example – Memory limit with Docker + +
+Bash + +``` +docker run --memory 512m my-node-app +``` + +
+ +

+ +### Code Example – Memory limit with Kubernetes + +
+Kubernetes deployment yaml + +``` +apiVersion: v1 +kind: Pod +metadata: + name: my-node-app +spec: + containers: + - name: my-node-app + image: my-node-app + resources: + requests: + memory: "400Mi" + limits: + memory: "500Mi" + command: ["node index.js"] +``` + +
+ +

+ +### Code Example Anti-Pattern – Setting memory limit using V8 flags + +
+ +Kubernetes deployment yaml + +``` +apiVersion: v1 +kind: Pod +metadata: + name: my-node-app +spec: + containers: + - name: my-node-app + image: my-node-app + command: ["node index.js --max-old-space-size=400"] +``` + +
+ +

+ +### Kubernetes documentation: "If you do not specify a memory limit" + +From [K8S documentation](https://kubernetes.io/docs/tasks/configure-pod-container/assign-memory-resource/?fbclid=IwAR2gfRL-3UB2WIbxJNSl3jNdlEJF3rAU5WG049yNorLOVSVngmRY1xhrbqg#if-you-do-not-specify-a-memory-limit) + +> The Container has no upper bound on the amount of memory it uses. The Container could use all of the memory available on the Node where it is running which in turn could invoke the OOM Killer. Further, in case of an OOM Kill, a container with no resource limits will have a greater chance of being killed. From e7c8e06a8f6d351bd6ca8cf4b97cbd1eaa41043d Mon Sep 17 00:00:00 2001 From: Yoni Date: Sun, 14 Jun 2020 13:06:27 +0300 Subject: [PATCH 2/5] Memory limit - 1st draft --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 431435c9..e65e6621 100644 --- a/README.md +++ b/README.md @@ -1137,7 +1137,7 @@ Bear in mind that with the introduction of the new V8 engine alongside the new E **Otherwise:** When setting limits using V8 --max-old-space-size the Docker runtime won't be aware of its capacity limits and will have to blindly place it in an instance that might not have the right size -πŸ”— [**Read More: Set Docker memory limits which are in-par with v8 memory limit**](/sections/docker/file.md) +πŸ”— [**Read More: Set Docker memory limits which are in-par with v8 memory limit**](/sections/docker/memory-limit.md)


@@ -1320,9 +1320,9 @@ Thank you to all our collaborators! πŸ™ Our collaborators are members who are contributing to the repository on a regular basis, through suggesting new best practices, triaging issues, reviewing pull requests and more. If you are interested in helping us guide thousands of people to craft better Node.js applications, please read our [contributor guidelines](/.operations/CONTRIBUTING.md) πŸŽ‰ -| | | | -| :---------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------: |:--------------------------------------------------------------------------------------------------------------------------------: | -| [Ido Richter (Founder)](https://github.com/idori) | [Keith Holliday](https://github.com/TheHollidayInn) | [Kevyn Bruyere](https://github.com/kevynb) | +| | | | +| :---------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------: | +| [Ido Richter (Founder)](https://github.com/idori) | [Keith Holliday](https://github.com/TheHollidayInn) | [Kevyn Bruyere](https://github.com/kevynb) | ### Past collaborators From 0e1e15c7945251642c8105800bb746ec31635bc4 Mon Sep 17 00:00:00 2001 From: Yoni Date: Sun, 14 Jun 2020 13:06:58 +0300 Subject: [PATCH 3/5] Memory limit - 1st draft --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e65e6621..1dfd8ea5 100644 --- a/README.md +++ b/README.md @@ -1137,7 +1137,7 @@ Bear in mind that with the introduction of the new V8 engine alongside the new E **Otherwise:** When setting limits using V8 --max-old-space-size the Docker runtime won't be aware of its capacity limits and will have to blindly place it in an instance that might not have the right size -πŸ”— [**Read More: Set Docker memory limits which are in-par with v8 memory limit**](/sections/docker/memory-limit.md) +πŸ”— [**Read More: Set memory limits using Docker only**](/sections/docker/memory-limit.md)


From 3890a679edc142c963068e70fe808b09fd89c088 Mon Sep 17 00:00:00 2001 From: Yoni Date: Sun, 26 Jul 2020 17:07:26 +0300 Subject: [PATCH 4/5] Fixed per the PR comments --- sections/docker/memory-limit.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/sections/docker/memory-limit.md b/sections/docker/memory-limit.md index 58389151..c38256f5 100644 --- a/sections/docker/memory-limit.md +++ b/sections/docker/memory-limit.md @@ -71,6 +71,14 @@ spec: ### Kubernetes documentation: "If you do not specify a memory limit" -From [K8S documentation](https://kubernetes.io/docs/tasks/configure-pod-container/assign-memory-resource/?fbclid=IwAR2gfRL-3UB2WIbxJNSl3jNdlEJF3rAU5WG049yNorLOVSVngmRY1xhrbqg#if-you-do-not-specify-a-memory-limit) +From [K8S documentation](https://kubernetes.io/docs/tasks/configure-pod-container/assign-memory-resource/) > The Container has no upper bound on the amount of memory it uses. The Container could use all of the memory available on the Node where it is running which in turn could invoke the OOM Killer. Further, in case of an OOM Kill, a container with no resource limits will have a greater chance of being killed. + +

+ +### Docker documentation: "it throws an OOME and starts killing processes " + +From [Docker official docs](https://docs.docker.com/config/containers/resource_constraints/) + +> It is important not to allow a running container to consume too much of the host machine’s memory. On Linux hosts, if the kernel detects that there is not enough memory to perform important system functions, it throws an OOME, or Out Of Memory Exception, and starts killing processes to free up memory. From 17b3e7497eeaab6c1c5bd3d29e005fd3d27cfa5f Mon Sep 17 00:00:00 2001 From: Yoni Date: Sun, 26 Jul 2020 17:14:57 +0300 Subject: [PATCH 5/5] Fixed per the PR comments --- README.md | 4 ++-- sections/docker/memory-limit.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1dfd8ea5..36c61fef 100644 --- a/README.md +++ b/README.md @@ -1131,9 +1131,9 @@ Bear in mind that with the introduction of the new V8 engine alongside the new E


-## ![βœ”] 8.6. Set memory limits using Docker only +## ![βœ”] 8.6. Set memory limits using Docker -**TL;DR:** Configure a memory limit using Docker, not using V8. Use Docker command flag 'run --memory' or set the right values within the platform that runs Docker. By doing this, the runtime will be capable of making better decisions on when to scale, prevent one citizen from starving others, drive thoughtful crash decisions (e.g., Docker can allow slight burst deviations) and in-overall it's always better to move HW decisions to the OPS court +**TL;DR:** Always configure a memory limit using Docker, optionally set also the v8 limits. Practically, use the Docker flag 'run --memory' or set the right values within the platform that runs Docker. By doing this, the runtime will be capable of making better decisions on when to scale, prevent one citizen from starving others, drive thoughtful crash decisions (e.g., Docker can allow slight burst deviations) and in-overall it's always better to move HW decisions to the OPS court **Otherwise:** When setting limits using V8 --max-old-space-size the Docker runtime won't be aware of its capacity limits and will have to blindly place it in an instance that might not have the right size diff --git a/sections/docker/memory-limit.md b/sections/docker/memory-limit.md index c38256f5..264dc89b 100644 --- a/sections/docker/memory-limit.md +++ b/sections/docker/memory-limit.md @@ -4,7 +4,7 @@ ### One Paragraph Explainer -A memory limit tells the process/container the maximum allowed memory usage - a request or usage beyond this number will kill the process (OOMKill). Applying this is a great practice to ensure one citizen doesn't drink alone all the juice and leave other components to starve. Memory limits also allow the runtime to place a container in the right instance - placing a container that consumes 500MB in an instance with 300MB memory available will lead to failures. Two different options allow configuring this limit: V8 flags (--max-old-space-size) and the Docker runtime. There is confusion around which of those to set, some configure both. The better option would be to set the limit on the Docker command or the Docker runtime (e.g. Kubernetes) as is has a much wider perspective for making the right decisions. First, given this limit, the runtime knows how to scale and create more resources. It can also make a thoughtful decision on when to crash - if a container has a short burst in memory request and the hosting instance is capable of supporting this, Docker will let the container stay alive. Docker also measures the actually used memory and not the allocated part so it can get Killed only when really needed. Last, With Docker the Ops experts can set various production memory configurations that can be taken into account like memory swap. On the contrary, when setting the limit on V8 - each of the described scenarios will not be supported. +A memory limit tells the process/container the maximum allowed memory usage - a request or usage beyond this number will kill the process (OOMKill). Applying this is a great practice to ensure one citizen doesn't drink alone all the juice and leave other components to starve. Memory limits also allow the runtime to place a container in the right instance - placing a container that consumes 500MB in an instance with 300MB memory available will lead to failures. Two different options allow configuring this limit: V8 flags (--max-old-space-size) and the Docker runtime. There is confusion around which of those to set: Ensure to always configure the Docker runtime limits as is has a much wider perspective for making the right decisions. First, given this limit, the runtime knows how to scale and create more resources. It can also make a thoughtful decision on when to crash - if a container has a short burst in memory request and the hosting instance is capable of supporting this, Docker will let the container stay alive. Docker also measures the actually used memory and not the allocated part (unlike v8 --max-old-space-size) so it can get Killed only when really needed. Last, With Docker the Ops experts can set various production memory configurations that can be taken into account like memory swap.