How Kubernetes measures memory
A memory request or limit is a quantity: a number followed by at most one suffix. Memory is measured in bytes, so a number with no suffix is bytes.
The suffixes k, M, G, T, P and E are powers of 1000, and Ki, Mi, Gi, Ti, Pi and Ei are powers of 1024. They are case-sensitive: 1K is not valid, and 1m is a thousandth of a byte.
| Powers of 1024 | Powers of 1000 |
|---|---|
| 1Ki = 1,024 bytes | 1k = 1,000 bytes |
| 1Mi = 1,048,576 bytes | 1M = 1,000,000 bytes |
| 1Gi = 1,073,741,824 bytes | 1G = 1,000,000,000 bytes |
The format is the same on every provider, because it comes from the Kubernetes API: 512Mi is 536,870,912 bytes on EKS, GKE and AKS. What differs is how much of each node is left for pods, which the Kubernetes allocatable calculator compares.
Worked example: 129M and 123Mi
The Kubernetes docs list 128974848, 129e6, 129M, 128974848000m and 123Mi as roughly the same value. Only roughly: try them above and two different figures come out.
123Miis 123 × 1,048,576 = 128,974,848 bytes.128974848and128974848000mare that same number.129Mand129e6are 129 × 1,000,000 = 129,000,000 bytes.
The gap here is only 25,152 bytes, because 129 and 123 happen to land close together. Keep the number and change the suffix, and the gap is far larger: the default 512Mi is 536,870,912 bytes and 512M is 512,000,000 bytes, a difference of almost 25 MB. A team that sizes a memory limit in one unit and reads usage in the other can be off by that much.
Pitfall: valid but wrong suffixes
The costly mistakes are the ones the API server accepts, because you get no error when you apply them:
400mis a request for 0.4 bytes. The author probably meant400Mi, but the API server only warns about a fractional byte value. The habit comes from CPU, where400mis normal.128is 128 bytes, since a number with no suffix is bytes.
The calculator warns about both. Other typos do fail at once: 512MB and 1K are not valid quantities, and neither is 1e3Ki, because a quantity takes an exponent or a suffix, not both.
Canonical form and noisy diffs
Kubernetes accepts many spellings of one value. The reference says it writes each one back in canonical form: no fractional digits, and the largest suffix that keeps the value exact. 1.5Gi comes back as 1536Mi, and 1024Mi as 1Gi. A decimal suffix stays decimal and a binary one stays binary, but a binary value that isn't a multiple of 1Ki has no binary form: 0.5Ki comes back as 512. An exponent usually stays an exponent: 129e6 stays, while 1e2 comes back as 100. A few unusual spellings come back as typed, such as +1, 1E3 and 1.500.
The reference sums it up as "always use canonical form, or don't diff". If a tool that compares your manifest with the live object keeps flagging a memory value that nobody changed, copy the canonical form above into the manifest. For CPU values, use the Kubernetes CPU units converter. To see how requests add up on a node, use the Kubernetes pod capacity calculator.
FAQ
What is the difference between M and Mi in Kubernetes?
M is a power of 1000 and Mi is a power of 1024. 1M is 1,000,000 bytes and 1Mi is 1,048,576 bytes, so Mi is 4.86% larger. The gap grows with the suffix: 1Gi is 7.37% larger than 1G.
How many bytes are in 1Gi?
1,073,741,824 bytes, which is 1024 to the power of 3. 1G is 1,000,000,000 bytes. So 1Gi is the same as 1024Mi, and Kubernetes writes 1024Mi back as 1Gi.
What does a lowercase m mean on memory?
Thousandths of a byte. The Kubernetes docs warn that 400m of memory is a request for 0.4 bytes, when the author probably meant 400Mi or 400M. Suffixes are case-sensitive, and m is a valid suffix, so the API server accepts it, with at most a warning about a fractional byte value.
What does a memory value with no suffix mean?
Bytes. A memory request of 128 is 128 bytes, not 128 mebibytes. It is a valid quantity, so the API server accepts it. Write 128Mi for mebibytes, or 128M for megabytes.
Are Kubernetes memory units different on EKS, GKE and AKS?
No. The format comes from the Kubernetes API, so 512Mi is 536,870,912 bytes on all three. What differs is how much memory each provider reserves on a node, so the same machine leaves a different amount for pods. EKS Fargate also adds 256 MB to a pod and rounds up to its supported sizes, and GKE Autopilot can raise requests to fit its rules.
Why does kubectl show a different memory value from the one I applied?
Kubernetes normally rewrites a quantity in canonical form when it serializes it: no fractional digits, and the largest suffix that keeps the value exact. So 1.5Gi comes back as 1536Mi, and 1024Mi comes back as 1Gi. The amount is the same, but tools that compare text will report a difference. Writing the canonical form in your manifests avoids that.