在Kubernetes中,命名空间是一种隔离不同应用程序资源的方式。除了CPU和存储资源之外,内存也是容器运行所需的重要资源之一。为了确保应用程序的稳定运行,我们可以为每个命名空间配置最小和最大内存约束。本教程介绍如何设置在名字空间中运行的容器所使用的内存的最小值和最大值。
可以在 LimitRange 对象中指定最小和最大内存值。如果 Pod 不满足 LimitRange 施加的约束, 则无法在名字空间中创建它。
一、准备开始
必须拥有一个 Kubernetes 的集群,同时必须配置 kubectl 命令行工具与集群通信。 建议在至少有两个不作为控制平面主机的节点的集群上运行本教程。 如果还没有集群,可以通过 Minikube 构建一个自己的集群,或者可以使用下面的 Kubernetes 练习环境之一:
- Killercoda
- 玩转 Kubernetes
在集群里必须要有创建命名空间的权限。集群中的每个节点都必须至少有 1 GiB 的内存可供 Pod 使用。
二、创建命名空间
创建一个命名空间,以便在此练习中创建的资源与集群的其余资源隔离。
kubectl create namespace constraints-mem-example
三、创建LimitRange和Pod
下面是 LimitRange 的示例清单:
apiVersion: v1 kind: LimitRange metadata: name: mem-min-max-demo-lr spec: limits: - max: memory: 1Gi min: memory: 500Mi type: Container
创建 LimitRange:
kubectl apply -f https://k8s.io/examples/admin/resource/memory-constraints.yaml --namespace=constraints-mem-example
查看 LimitRange 的详情:
kubectl get limitrange mem-min-max-demo-lr --namespace=constraints-mem-example --output=yaml
输出显示预期的最小和最大内存约束。 但请注意,即使没有在 LimitRange 的配置文件中指定默认值,默认值也会自动生成。
limits: - default: memory: 1Gi defaultRequest: memory: 1Gi max: memory: 1Gi min: memory: 500Mi type: Container
现在,每当在 constraints-mem-example 命名空间中创建 Pod 时,Kubernetes 就会执行下面的步骤:
- 如果 Pod 中的任何容器未声明自己的内存请求和限制,控制面将为该容器设置默认的内存请求和限制。
确保该 Pod 中的每个容器的内存请求至少 500 MiB; - 确保该 Pod 中每个容器内存请求不大于 1 GiB;
- 以下为包含一个容器的 Pod 清单。该容器声明了 600 MiB 的内存请求和 800 MiB 的内存限制, 这些满足了 LimitRange 施加的最小和最大内存约束。
apiVersion: v1 kind: Pod metadata: name: constraints-mem-demo spec: containers: - name: constraints-mem-demo-ctr image: nginx resources: limits: memory: "800Mi" requests: memory: "600Mi"
创建 Pod:
kubectl apply -f https://k8s.io/examples/admin/resource/memory-constraints-pod.yaml --namespace=constraints-mem-example
确认 Pod 正在运行,并且其容器处于健康状态:
kubectl get pod constraints-mem-demo --namespace=constraints-mem-example
查看 Pod 详情:
kubectl get pod constraints-mem-demo --output=yaml --namespace=constraints-mem-example
输出结果显示该 Pod 的容器的内存请求为 600 MiB,内存限制为 800 MiB。 这些满足这个命名空间中 LimitRange 设定的限制范围。
resources: limits: memory: 800Mi requests: memory: 600Mi
删除创建的 Pod:
kubectl delete pod constraints-mem-demo --namespace=constraints-mem-example
四、超过最大限制的Pod
以下为包含一个容器的 Pod 的清单。这个容器声明了 800 MiB 的内存请求和 1.5 GiB 的内存限制。
apiVersion: v1 kind: Pod metadata: name: constraints-mem-demo-2 spec: containers: - name: constraints-mem-demo-2-ctr image: nginx resources: limits: memory: "1.5Gi" requests: memory: "800Mi"
尝试创建 Pod:
kubectl apply -f https://k8s.io/examples/admin/resource/memory-constraints-pod-2.yaml --namespace=constraints-mem-example
输出结果显示 Pod 没有创建成功,因为它定义了一个容器的内存请求超过了允许的值。
Error from server (Forbidden): error when creating "examples/admin/resource/memory-constraints-pod-2.yaml": pods "constraints-mem-demo-2" is forbidden: maximum memory usage per Container is 1Gi, but limit is 1536Mi.
五、不满足最小请求的Pod
以下为只有一个容器的 Pod 的清单。这个容器声明了 100 MiB 的内存请求和 800 MiB 的内存限制。
apiVersion: v1 kind: Pod metadata: name: constraints-mem-demo-3 spec: containers: - name: constraints-mem-demo-3-ctr image: nginx resources: limits: memory: "800Mi" requests: memory: "100Mi"
尝试创建 Pod:
kubectl apply -f https://k8s.io/examples/admin/resource/memory-constraints-pod-3.yaml --namespace=constraints-mem-example
输出结果显示 Pod 没有创建成功,因为它定义了一个容器的内存请求小于强制要求的最小值:
Error from server (Forbidden): error when creating "examples/admin/resource/memory-constraints-pod-3.yaml": pods "constraints-mem-demo-3" is forbidden: minimum memory usage per Container is 500Mi, but request is 100Mi.
六、没有声明请求/限制的Pod
创建一个没有声明内存请求和限制的 Pod。以下为只有一个容器的 Pod 清单。该容器没有声明内存请求,也没有声明内存限制。
apiVersion: v1 kind: Pod metadata: name: constraints-mem-demo-4 spec: containers: - name: constraints-mem-demo-4-ctr image: nginx
创建 Pod:
kubectl apply -f https://k8s.io/examples/admin/resource/memory-constraints-pod-4.yaml --namespace=constraints-mem-example
查看 Pod 详情:
kubectl get pod constraints-mem-demo-4 --namespace=constraints-mem-example --output=yaml
输出结果显示 Pod 的唯一容器内存请求为 1 GiB,内存限制为 1 GiB。容器怎样获得那些数值呢?
resources: limits: memory: 1Gi requests: memory: 1Gi
因为 Pod 没有为容器声明任何内存请求和限制,集群会从 LimitRange 获取默认的内存请求和限制。 应用于容器。
这意味着 Pod 的定义会显示这些值。可以通过 kubectl describe 查看:
# 查看输出结果中的 "Requests:" 的值 kubectl describe pod constraints-mem-demo-4 --namespace=constraints-mem-example
此时, Pod 可能已经运行起来也可能没有运行起来。 回想一下我们本次任务的先决条件是每个节点都至少有 1 GiB 的内存。 如果每个节点都只有 1 GiB 的内存,那将没有一个节点拥有足够的可分配内存来满足 1 GiB 的内存请求。
删除 Pod:
kubectl delete pod constraints-mem-demo-4 --namespace=constraints-mem-example
七、强制执行最小/最大限制
LimitRange 为命名空间设定的最小和最大内存限制只有在 Pod 创建和更新时才会强制执行。 如果更新 LimitRange,它不会影响此前创建的 Pod。
八、设置内存最小/最大限制动因
作为集群管理员,可能想规定 Pod 可以使用的内存总量限制。例如:
1、集群的每个节点有 2 GiB 内存。不想接受任何请求超过 2 GiB 的 Pod,因为集群中没有节点可以满足。
2、集群由生产部门和开发部门共享。希望允许产品部门的负载最多耗用 8 GiB 内存, 但是开发部门的负载最多可使用 512 MiB。 这时,可以为产品部门和开发部门分别创建名字空间,并为各个名字空间设置内存约束。
九、清理
删除命名空间:
kubectl delete namespace constraints-mem-example