Kubernetes分配内存资源

2023-12-21 77

Kubernetes中,内存资源的分配对于容器和Pod的正常运行至关重要。为了确保容器能够获得所需的内存资源并避免过度使用,Kubernetes提供了内存请求(request)和内存限制(limit)的概念。通过合理地设置这两个参数,我们可以为容器分配适当的内存资源,从而保证其性能和稳定性。

一、准备

1、必须拥有一个 Kubernetes 的集群,同时必须配置 kubectl 命令行工具与集群通信。 建议在至少有两个不作为控制平面主机的节点的集群上运行本教程。 如果还没有集群,可以通过 Minikube 构建一个自己的集群,或者可以使用下面的 Kubernetes 练习环境之一:

  • Killercoda
  • 玩转 Kubernetes

2、要获知版本信息,请输入 kubectl version.

3、集群中的每个节点必须拥有至少 300 MiB 的内存。

4、该页面上的一些步骤要求在集群中运行 metrics-server 服务。 如果已经有在运行中的 metrics-server,则可以跳过这些步骤。

如果运行的是 Minikube,可以运行下面的命令启用 metrics-server:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
minikube addons enable metrics-server
minikube addons enable metrics-server
minikube addons enable metrics-server

要查看 metrics-server 或资源指标 API (metrics.k8s.io) 是否已经运行,请运行以下命令:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
kubectl get apiservices
kubectl get apiservices
kubectl get apiservices

如果资源指标 API 可用,则输出结果将包含对 metrics.k8s.io 的引用信息。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
NAME
v1beta1.metrics.k8s.io
NAME v1beta1.metrics.k8s.io
NAME
v1beta1.metrics.k8s.io

二、创建命名空间

创建一个命名空间,以便将本练习中创建的资源与集群的其余部分隔离。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
kubectl create namespace mem-example
kubectl create namespace mem-example
kubectl create namespace mem-example

三、指定内存请求和限制

要为容器指定内存请求,请在容器资源清单中包含 resources: requests 字段。 同理,要指定内存限制,请包含 resources: limits。

在本练习中,将创建一个拥有一个容器的 Pod。 容器将会请求 100 MiB 内存,并且内存会被限制在 200 MiB 以内。 这是 Pod 的配置文件:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
apiVersion: v1
kind: Pod
metadata:
name: memory-demo
namespace: mem-example
spec:
containers:
- name: memory-demo-ctr
image: polinux/stress
resources:
requests:
memory: "100Mi"
limits:
memory: "200Mi"
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]
apiVersion: v1 kind: Pod metadata: name: memory-demo namespace: mem-example spec: containers: - name: memory-demo-ctr image: polinux/stress resources: requests: memory: "100Mi" limits: memory: "200Mi" command: ["stress"] args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]
apiVersion: v1
kind: Pod
metadata:
name: memory-demo
namespace: mem-example
spec:
containers:
- name: memory-demo-ctr
image: polinux/stress
resources:
requests:
memory: "100Mi"
limits:
memory: "200Mi"
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]

配置文件的 args 部分提供了容器启动时的参数。 “–vm-bytes”, “150M” 参数告知容器尝试分配 150 MiB 内存。

开始创建 Pod:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit.yaml --namespace=mem-example
kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit.yaml --namespace=mem-example
kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit.yaml --namespace=mem-example

验证 Pod 中的容器是否已运行:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
kubectl get pod memory-demo --namespace=mem-example
kubectl get pod memory-demo --namespace=mem-example
kubectl get pod memory-demo --namespace=mem-example

查看 Pod 相关的详细信息:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
kubectl get pod memory-demo --output=yaml --namespace=mem-example
kubectl get pod memory-demo --output=yaml --namespace=mem-example
kubectl get pod memory-demo --output=yaml --namespace=mem-example

输出结果显示:该 Pod 中容器的内存请求为 100 MiB,内存限制为 200 MiB。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
...
resources:
requests:
memory: 100Mi
limits:
memory: 200Mi
...
... resources: requests: memory: 100Mi limits: memory: 200Mi ...
...
resources:
requests:
memory: 100Mi
limits:
memory: 200Mi
...

运行 kubectl top 命令,获取该 Pod 的指标数据:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
kubectl top pod memory-demo --namespace=mem-example
kubectl top pod memory-demo --namespace=mem-example
kubectl top pod memory-demo --namespace=mem-example

输出结果显示:Pod 正在使用的内存大约为 162,900,000 字节,约为 150 MiB。 这大于 Pod 请求的 100 MiB,但在 Pod 限制的 200 MiB之内。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
NAME CPU(cores) MEMORY(bytes)
memory-demo <something> 162856960
NAME CPU(cores) MEMORY(bytes) memory-demo <something> 162856960
NAME CPU(cores) MEMORY(bytes)
memory-demo <something> 162856960

删除 Pod:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
kubectl delete pod memory-demo --namespace=mem-example
kubectl delete pod memory-demo --namespace=mem-example
kubectl delete pod memory-demo --namespace=mem-example

四、超过容器限制的内存

当节点拥有足够的可用内存时,容器可以使用其请求的内存。 但是,容器不允许使用超过其限制的内存。 如果容器分配的内存超过其限制,该容器会成为被终止的候选容器。 如果容器继续消耗超出其限制的内存,则终止容器。 如果终止的容器可以被重启,则 kubelet 会重新启动它,就像其他任何类型的运行时失败一样。

在本练习中,将创建一个 Pod,尝试分配超出其限制的内存。 这是一个 Pod 的配置文件,其拥有一个容器,该容器的内存请求为 50 MiB,内存限制为 100 MiB:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
apiVersion: v1
kind: Pod
metadata:
name: memory-demo-2
namespace: mem-example
spec:
containers:
- name: memory-demo-2-ctr
image: polinux/stress
resources:
requests:
memory: "50Mi"
limits:
memory: "100Mi"
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "250M", "--vm-hang", "1"]
apiVersion: v1 kind: Pod metadata: name: memory-demo-2 namespace: mem-example spec: containers: - name: memory-demo-2-ctr image: polinux/stress resources: requests: memory: "50Mi" limits: memory: "100Mi" command: ["stress"] args: ["--vm", "1", "--vm-bytes", "250M", "--vm-hang", "1"]
apiVersion: v1
kind: Pod
metadata:
name: memory-demo-2
namespace: mem-example
spec:
containers:
- name: memory-demo-2-ctr
image: polinux/stress
resources:
requests:
memory: "50Mi"
limits:
memory: "100Mi"
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "250M", "--vm-hang", "1"]

在配置文件的 args 部分中,可以看到容器会尝试分配 250 MiB 内存,这远高于 100 MiB 的限制。

创建 Pod:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit-2.yaml --namespace=mem-example
kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit-2.yaml --namespace=mem-example
kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit-2.yaml --namespace=mem-example

查看 Pod 相关的详细信息:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
kubectl get pod memory-demo-2 --namespace=mem-example
kubectl get pod memory-demo-2 --namespace=mem-example
kubectl get pod memory-demo-2 --namespace=mem-example

此时,容器可能正在运行或被杀。重复前面的命令,直到容器被杀:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
NAME READY STATUS RESTARTS AGE
memory-demo-2 0/1 OOMKilled 1 24s
NAME READY STATUS RESTARTS AGE memory-demo-2 0/1 OOMKilled 1 24s
NAME READY STATUS RESTARTS AGE
memory-demo-2 0/1 OOMKilled 1 24s

获取容器更详细的状态信息:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
kubectl get pod memory-demo-2 --output=yaml --namespace=mem-example
kubectl get pod memory-demo-2 --output=yaml --namespace=mem-example
kubectl get pod memory-demo-2 --output=yaml --namespace=mem-example

输出结果显示:由于内存溢出(OOM),容器已被杀掉:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
lastState:
terminated:
containerID: 65183c1877aaec2e8427bc95609cc52677a454b56fcb24340dbd22917c23b10f
exitCode: 137
finishedAt: 2017-06-20T20:52:19Z
reason: OOMKilled
startedAt: null
lastState: terminated: containerID: 65183c1877aaec2e8427bc95609cc52677a454b56fcb24340dbd22917c23b10f exitCode: 137 finishedAt: 2017-06-20T20:52:19Z reason: OOMKilled startedAt: null
lastState:
terminated:
containerID: 65183c1877aaec2e8427bc95609cc52677a454b56fcb24340dbd22917c23b10f
exitCode: 137
finishedAt: 2017-06-20T20:52:19Z
reason: OOMKilled
startedAt: null

本练习中的容器可以被重启,所以 kubelet 会重启它。 多次运行下面的命令,可以看到容器在反复的被杀死和重启:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
kubectl get pod memory-demo-2 --namespace=mem-example
kubectl get pod memory-demo-2 --namespace=mem-example
kubectl get pod memory-demo-2 --namespace=mem-example

输出结果显示:容器被杀掉、重启、再杀掉、再重启……:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
kubectl get pod memory-demo-2 --namespace=mem-example
NAME READY STATUS RESTARTS AGE
memory-demo-2 0/1 OOMKilled 1 37s
kubectl get pod memory-demo-2 --namespace=mem-example NAME READY STATUS RESTARTS AGE memory-demo-2 0/1 OOMKilled 1 37s
kubectl get pod memory-demo-2 --namespace=mem-example
NAME READY STATUS RESTARTS AGE
memory-demo-2 0/1 OOMKilled 1 37s
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
kubectl get pod memory-demo-2 --namespace=mem-example
NAME READY STATUS RESTARTS AGE
memory-demo-2 1/1 Running 2 40s
kubectl get pod memory-demo-2 --namespace=mem-example NAME READY STATUS RESTARTS AGE memory-demo-2 1/1 Running 2 40s
kubectl get pod memory-demo-2 --namespace=mem-example
NAME READY STATUS RESTARTS AGE
memory-demo-2 1/1 Running 2 40s

查看关于该 Pod 历史的详细信息:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
kubectl describe pod memory-demo-2 --namespace=mem-example
kubectl describe pod memory-demo-2 --namespace=mem-example
kubectl describe pod memory-demo-2 --namespace=mem-example

输出结果显示:该容器反复的在启动和失败:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
... Normal Created Created container with id 66a3a20aa7980e61be4922780bf9d24d1a1d8b7395c09861225b0eba1b1f8511
... Warning BackOff Back-off restarting failed container
... Normal Created Created container with id 66a3a20aa7980e61be4922780bf9d24d1a1d8b7395c09861225b0eba1b1f8511 ... Warning BackOff Back-off restarting failed container
... Normal Created Created container with id 66a3a20aa7980e61be4922780bf9d24d1a1d8b7395c09861225b0eba1b1f8511
... Warning BackOff Back-off restarting failed container

查看关于集群节点的详细信息:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
kubectl describe nodes
kubectl describe nodes
kubectl describe nodes

输出结果包含了一条练习中的容器由于内存溢出而被杀掉的记录:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Warning OOMKilling Memory cgroup out of memory: Kill process 4481 (stress) score 1994 or sacrifice child
Warning OOMKilling Memory cgroup out of memory: Kill process 4481 (stress) score 1994 or sacrifice child
Warning OOMKilling Memory cgroup out of memory: Kill process 4481 (stress) score 1994 or sacrifice child

删除 Pod:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
kubectl delete pod memory-demo-2 --namespace=mem-example
kubectl delete pod memory-demo-2 --namespace=mem-example
kubectl delete pod memory-demo-2 --namespace=mem-example

五、超过整个节点容量的内存

内存请求和限制是与容器关联的,但将 Pod 视为具有内存请求和限制,也是很有用的。 Pod 的内存请求是 Pod 中所有容器的内存请求之和。 同理,Pod 的内存限制是 Pod 中所有容器的内存限制之和。

Pod 的调度基于请求。只有当节点拥有足够满足 Pod 内存请求的内存时,才会将 Pod 调度至节点上运行。

在本练习中,将创建一个 Pod,其内存请求超过了集群中的任意一个节点所拥有的内存。 这是该 Pod 的配置文件,其拥有一个请求 1000 GiB 内存的容器,这应该超过了集群中任何节点的容量。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
apiVersion: v1
kind: Pod
metadata:
name: memory-demo-3
namespace: mem-example
spec:
containers:
- name: memory-demo-3-ctr
image: polinux/stress
resources:
requests:
memory: "1000Gi"
limits:
memory: "1000Gi"
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]
apiVersion: v1 kind: Pod metadata: name: memory-demo-3 namespace: mem-example spec: containers: - name: memory-demo-3-ctr image: polinux/stress resources: requests: memory: "1000Gi" limits: memory: "1000Gi" command: ["stress"] args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]
apiVersion: v1
kind: Pod
metadata:
name: memory-demo-3
namespace: mem-example
spec:
containers:
- name: memory-demo-3-ctr
image: polinux/stress
resources:
requests:
memory: "1000Gi"
limits:
memory: "1000Gi"
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]

创建 Pod:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit-3.yaml --namespace=mem-example
kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit-3.yaml --namespace=mem-example
kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit-3.yaml --namespace=mem-example

查看 Pod 状态:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
kubectl get pod memory-demo-3 --namespace=mem-example
kubectl get pod memory-demo-3 --namespace=mem-example
kubectl get pod memory-demo-3 --namespace=mem-example

输出结果显示:Pod 处于 PENDING 状态。 这意味着,该 Pod 没有被调度至任何节点上运行,并且它会无限期的保持该状态:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
kubectl get pod memory-demo-3 --namespace=mem-example
NAME READY STATUS RESTARTS AGE
memory-demo-3 0/1 Pending 0 25s
kubectl get pod memory-demo-3 --namespace=mem-example NAME READY STATUS RESTARTS AGE memory-demo-3 0/1 Pending 0 25s
kubectl get pod memory-demo-3 --namespace=mem-example
NAME READY STATUS RESTARTS AGE
memory-demo-3 0/1 Pending 0 25s

查看关于 Pod 的详细信息,包括事件:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
kubectl describe pod memory-demo-3 --namespace=mem-example
kubectl describe pod memory-demo-3 --namespace=mem-example
kubectl describe pod memory-demo-3 --namespace=mem-example

输出结果显示:由于节点内存不足,该容器无法被调度:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
Events:
... Reason Message
------ -------
... FailedScheduling No nodes are available that match all of the following predicates:: Insufficient memory (3).
Events: ... Reason Message ------ ------- ... FailedScheduling No nodes are available that match all of the following predicates:: Insufficient memory (3).
Events:
... Reason Message
------ -------
... FailedScheduling No nodes are available that match all of the following predicates:: Insufficient memory (3).

六、内存单位

内存资源的基本单位是字节(byte)。可以使用这些后缀之一,将内存表示为 纯整数或定点整数:E、P、T、G、M、K、Ei、Pi、Ti、Gi、Mi、Ki。 例如,下面是一些近似相同的值:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
128974848, 129e6, 129M, 123Mi
128974848, 129e6, 129M, 123Mi
128974848, 129e6, 129M, 123Mi

删除 Pod:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
kubectl delete pod memory-demo-3 --namespace=mem-example
kubectl delete pod memory-demo-3 --namespace=mem-example
kubectl delete pod memory-demo-3 --namespace=mem-example

七、如果没有指定内存限制

如果没有为一个容器指定内存限制,则自动遵循以下情况之一:

  • 容器可无限制地使用内存。容器可以使用其所在节点所有的可用内存, 进而可能导致该节点调用 OOM Killer。 此外,如果发生 OOM Kill,没有资源限制的容器将被杀掉的可行性更大;
  • 运行的容器所在命名空间有默认的内存限制,那么该容器会被自动分配默认限制。 集群管理员可用使用 LimitRange 来指定默认的内存限制。

八、内存请求和限制目的

通过为集群中运行的容器配置内存请求和限制,可以有效利用集群节点上可用的内存资源。 通过将 Pod 的内存请求保持在较低水平,可以更好地安排 Pod 调度。 通过让内存限制大于内存请求,可以完成两件事:

  • Pod 可以进行一些突发活动,从而更好的利用可用内存;
  • Pod 在突发活动期间,可使用的内存被限制为合理的数量。

九、清理

删除命名空间。下面的命令会删除根据这个任务创建的所有 Pod:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
kubectl delete namespace mem-example
kubectl delete namespace mem-example
kubectl delete namespace mem-example
  • 广告合作

  • QQ群号:4114653

温馨提示:
1、本网站发布的内容(图片、视频和文字)以原创、转载和分享网络内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。邮箱:2942802716#qq.com(#改为@)。 2、本站原创内容未经允许不得转裁,转载请注明出处“站长百科”和原文地址。