在 Kubernetes 中部署应用程序时如何定义资源限制和计算消耗?
How to define resource limits and calculate consumption when deploying applications in Kubernetes?
我正尝试按照 official Kubernetes website 中的教程部署一个简单的 zookeeper 整体。教程说我需要
a cluster with at least four nodes and each node requires at least 2
CPUs and 4 GiB of memory.
我忽略了这个事实并创建了一个包含 3 个 n1-standard-1 节点的集群(1 个 vCPU,3.73 GB 内存)
当我尝试应用 .yaml 文件时
apiVersion: v1
kind: Service
metadata:
name: zk-hs
labels:
app: zk
spec:
ports:
- port: 2888
name: server
- port: 3888
name: leader-election
clusterIP: None
selector:
app: zk
---
apiVersion: v1
kind: Service
metadata:
name: zk-cs
labels:
app: zk
spec:
ports:
- port: 2181
name: client
selector:
app: zk
---
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
name: zk-pdb
spec:
selector:
matchLabels:
app: zk
maxUnavailable: 1
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: zk
spec:
selector:
matchLabels:
app: zk
serviceName: zk-hs
replicas: 3
updateStrategy:
type: RollingUpdate
podManagementPolicy: OrderedReady
template:
metadata:
labels:
app: zk
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: "app"
operator: In
values:
- zk
topologyKey: "kubernetes.io/hostname"
containers:
- name: kubernetes-zookeeper
imagePullPolicy: Always
image: "k8s.gcr.io/kubernetes-zookeeper:1.0-3.4.10"
resources:
requests:
memory: "1Gi"
cpu: "0.5"
ports:
- containerPort: 2181
name: client
- containerPort: 2888
name: server
- containerPort: 3888
name: leader-election
command:
- sh
- -c
- "start-zookeeper \
--servers=3 \
--data_dir=/var/lib/zookeeper/data \
--data_log_dir=/var/lib/zookeeper/data/log \
--conf_dir=/opt/zookeeper/conf \
--client_port=2181 \
--election_port=3888 \
--server_port=2888 \
--tick_time=2000 \
--init_limit=10 \
--sync_limit=5 \
--heap=512M \
--max_client_cnxns=60 \
--snap_retain_count=3 \
--purge_interval=12 \
--max_session_timeout=40000 \
--min_session_timeout=4000 \
--log_level=INFO"
readinessProbe:
exec:
command:
- sh
- -c
- "zookeeper-ready 2181"
initialDelaySeconds: 10
timeoutSeconds: 5
livenessProbe:
exec:
command:
- sh
- -c
- "zookeeper-ready 2181"
initialDelaySeconds: 10
timeoutSeconds: 5
volumeMounts:
- name: datadir
mountPath: /var/lib/zookeeper
securityContext:
runAsUser: 1000
fsGroup: 1000
volumeClaimTemplates:
- metadata:
name: datadir
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 10Gi
当然,我得到了错误 PodUnschedulable
在这个文件中,我找不到任何说明我需要 4 个节点和 2 个 CPU 和 4G Ram 的集群的内容。
所以:
- 什么定义了我的部署需要多少资源?
- 如何understand/calculate预先获取应用程序所需的资源及其各自的部署?
- Zookeeper 根据要求在 2GB RAM 上运行,但这只是推荐配置。
部署 yaml 中的 resources
部分定义了 pod 中容器的资源要求。
resources:
requests:
memory: "1Gi"
cpu: "0.5"
requests
意味着一个节点需要有超过 1GB 的内存和 0.5 CPU 可用于在该节点上调度的副本 pod 之一。
还有另一个概念 limits
,它定义了 pod 在被逐出节点之前允许消耗的最大资源。
resources:
requests:
memory: "1Gi"
cpu: "0.5"
limits:
memory: "2Gi"
cpu: "2"
虽然您有 3 个节点,但默认情况下主节点未调度。
您可以通过kubectl describe nodename
并检查Capacity
和Allocatable
部分来了解节点的资源可用性。
Capacity:
cpu: 4
ephemeral-storage: 8065444Ki
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 16424256Ki
pods: 110
Allocatable:
cpu: 4
ephemeral-storage: 7433113179
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 16321856Ki
pods: 110
关于计算 pod 的资源需求(requests
和 limits
),没有灵丹妙药。它取决于应用程序,应该通过对其进行分析来确定和调整。但推荐的最佳做法是在部署 pod 时定义 requests
和 limits
。
默认情况下,kubernetes 节点 不会为空。 相反,它甚至在 运行 您的应用程序工作负载之前就有 运行 个进程:
- kubelet 是 运行(在每个节点中)
- kube-proxy 运行 作为守护进程(在每个节点中)
- container-runtime (Docker) 在每个节点运行
- 其他 daemonset 可以是 运行(如 EKS 中的 aws-node DS..)。
We are here discussing Worker Nodes not Masters.
所以想象一下,您最终会为每个节点选择尊重的资源。
并非所有节点都必须具有相同的大小。但是,您可以根据应用程序的类型来决定所需的尺寸:
如果您的应用占用内存超过 CPUs(如 Java 应用),您需要选择 [2[=111 的节点=], 8GB] 优于 [4CPUs, 8GB].
如果您的应用消耗的内存多于 CPUs(如 ML 工作负载),则需要选择相反的选项;计算优化实例。
黄金法则是计算整体容量优于查看每个节点的单独容量。
这意味着 3 个大型 节点在成本方面可能优于 4 个中等 节点,但在最佳使用方面也是如此容量。
总之,节点资源必须是:
- 不少于2CPU秒
- 不少于4GB内存
否则,您应该会遇到容量问题。
现在,我们完成了一半的答案:确定集群的容量。
下半部分是关于回答如何为每个应用程序 (pod) 分配资源。
这又陷入另一个问题了;您的应用消耗了多少?
要回答这个问题,您需要使用 Prometheus + Grafana 等 APM 工具监控您的应用程序。
一旦您了解平均消费情况,就可以为您的应用(它的 pods)设置资源限制。
限制 可能会限制应用程序,这就是为什么您需要与其他设置一起设置水平自动缩放:
- 运行 Pods 在 Deployment 中管理副本和部署。
- HPA 或 Horizontal Pod autoscaler:监控部署的 pods,然后根据阈值(CPU、内存)
扩展 out/in
作为这部分的结论,我们可以说:
- 测量: 开始测量以识别 resources.limits
和 resources.requests
。
- 测量: 在应用 运行 之后测量以再次识别所需的资源。
- 测量: 保持测量
我正尝试按照 official Kubernetes website 中的教程部署一个简单的 zookeeper 整体。教程说我需要
a cluster with at least four nodes and each node requires at least 2 CPUs and 4 GiB of memory.
我忽略了这个事实并创建了一个包含 3 个 n1-standard-1 节点的集群(1 个 vCPU,3.73 GB 内存) 当我尝试应用 .yaml 文件时
apiVersion: v1
kind: Service
metadata:
name: zk-hs
labels:
app: zk
spec:
ports:
- port: 2888
name: server
- port: 3888
name: leader-election
clusterIP: None
selector:
app: zk
---
apiVersion: v1
kind: Service
metadata:
name: zk-cs
labels:
app: zk
spec:
ports:
- port: 2181
name: client
selector:
app: zk
---
apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
name: zk-pdb
spec:
selector:
matchLabels:
app: zk
maxUnavailable: 1
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: zk
spec:
selector:
matchLabels:
app: zk
serviceName: zk-hs
replicas: 3
updateStrategy:
type: RollingUpdate
podManagementPolicy: OrderedReady
template:
metadata:
labels:
app: zk
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: "app"
operator: In
values:
- zk
topologyKey: "kubernetes.io/hostname"
containers:
- name: kubernetes-zookeeper
imagePullPolicy: Always
image: "k8s.gcr.io/kubernetes-zookeeper:1.0-3.4.10"
resources:
requests:
memory: "1Gi"
cpu: "0.5"
ports:
- containerPort: 2181
name: client
- containerPort: 2888
name: server
- containerPort: 3888
name: leader-election
command:
- sh
- -c
- "start-zookeeper \
--servers=3 \
--data_dir=/var/lib/zookeeper/data \
--data_log_dir=/var/lib/zookeeper/data/log \
--conf_dir=/opt/zookeeper/conf \
--client_port=2181 \
--election_port=3888 \
--server_port=2888 \
--tick_time=2000 \
--init_limit=10 \
--sync_limit=5 \
--heap=512M \
--max_client_cnxns=60 \
--snap_retain_count=3 \
--purge_interval=12 \
--max_session_timeout=40000 \
--min_session_timeout=4000 \
--log_level=INFO"
readinessProbe:
exec:
command:
- sh
- -c
- "zookeeper-ready 2181"
initialDelaySeconds: 10
timeoutSeconds: 5
livenessProbe:
exec:
command:
- sh
- -c
- "zookeeper-ready 2181"
initialDelaySeconds: 10
timeoutSeconds: 5
volumeMounts:
- name: datadir
mountPath: /var/lib/zookeeper
securityContext:
runAsUser: 1000
fsGroup: 1000
volumeClaimTemplates:
- metadata:
name: datadir
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 10Gi
当然,我得到了错误 PodUnschedulable
在这个文件中,我找不到任何说明我需要 4 个节点和 2 个 CPU 和 4G Ram 的集群的内容。 所以:
- 什么定义了我的部署需要多少资源?
- 如何understand/calculate预先获取应用程序所需的资源及其各自的部署?
- Zookeeper 根据要求在 2GB RAM 上运行,但这只是推荐配置。
resources
部分定义了 pod 中容器的资源要求。
resources:
requests:
memory: "1Gi"
cpu: "0.5"
requests
意味着一个节点需要有超过 1GB 的内存和 0.5 CPU 可用于在该节点上调度的副本 pod 之一。
还有另一个概念 limits
,它定义了 pod 在被逐出节点之前允许消耗的最大资源。
resources:
requests:
memory: "1Gi"
cpu: "0.5"
limits:
memory: "2Gi"
cpu: "2"
虽然您有 3 个节点,但默认情况下主节点未调度。
您可以通过kubectl describe nodename
并检查Capacity
和Allocatable
部分来了解节点的资源可用性。
Capacity:
cpu: 4
ephemeral-storage: 8065444Ki
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 16424256Ki
pods: 110
Allocatable:
cpu: 4
ephemeral-storage: 7433113179
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 16321856Ki
pods: 110
关于计算 pod 的资源需求(requests
和 limits
),没有灵丹妙药。它取决于应用程序,应该通过对其进行分析来确定和调整。但推荐的最佳做法是在部署 pod 时定义 requests
和 limits
。
默认情况下,kubernetes 节点 不会为空。 相反,它甚至在 运行 您的应用程序工作负载之前就有 运行 个进程:
- kubelet 是 运行(在每个节点中)
- kube-proxy 运行 作为守护进程(在每个节点中)
- container-runtime (Docker) 在每个节点运行
- 其他 daemonset 可以是 运行(如 EKS 中的 aws-node DS..)。
We are here discussing Worker Nodes not Masters.
所以想象一下,您最终会为每个节点选择尊重的资源。
并非所有节点都必须具有相同的大小。但是,您可以根据应用程序的类型来决定所需的尺寸:
如果您的应用占用内存超过 CPUs(如 Java 应用),您需要选择 [2[=111 的节点=], 8GB] 优于 [4CPUs, 8GB].
如果您的应用消耗的内存多于 CPUs(如 ML 工作负载),则需要选择相反的选项;计算优化实例。
黄金法则是计算整体容量优于查看每个节点的单独容量。
这意味着 3 个大型 节点在成本方面可能优于 4 个中等 节点,但在最佳使用方面也是如此容量。
总之,节点资源必须是:
- 不少于2CPU秒
- 不少于4GB内存
否则,您应该会遇到容量问题。
现在,我们完成了一半的答案:确定集群的容量。
下半部分是关于回答如何为每个应用程序 (pod) 分配资源。
这又陷入另一个问题了;您的应用消耗了多少?
要回答这个问题,您需要使用 Prometheus + Grafana 等 APM 工具监控您的应用程序。
一旦您了解平均消费情况,就可以为您的应用(它的 pods)设置资源限制。
限制 可能会限制应用程序,这就是为什么您需要与其他设置一起设置水平自动缩放:
- 运行 Pods 在 Deployment 中管理副本和部署。
- HPA 或 Horizontal Pod autoscaler:监控部署的 pods,然后根据阈值(CPU、内存) 扩展 out/in
作为这部分的结论,我们可以说:
- 测量: 开始测量以识别 resources.limits
和 resources.requests
。
- 测量: 在应用 运行 之后测量以再次识别所需的资源。
- 测量: 保持测量