Pod 密度是每个节点的 Pod 数量,Karpenter 还提供 pod density control
(Pod 密度控制),允许设置在节点上调度的 Pod 数量。 Kubernetes 默认限制每个节点 110 个 pod,在EKS上Pod 数量还受实例类型的限制。
Static Pod Density
- 在Provisioner配置 .spec.kubeletConfiguration
,指定 maxPods 。 此Provisioner生成的所有节点都将在其 kubelet 上设置此 maxPods 值,并将在调度期间考虑此值。Dynamic Pod Densisty
- 设置应在节点的每个 CPU 核心上调度的 pod 数量。 这是通过使用 podsPerCore
参数来完成的,该参数指定每个 CPU 核心的 pod 目标数量。默认情况下,EKS根据实例大小决定了节点能创建的最大pod数量。如果想调整这个值,可以调整spec.kubeletConfiguration
的maxPods
值,这个参数会由Karpenter传给kubelet,在kubelet上设置--max-pods
参数。通过提高小机型的pod密度,可以达到成本优化的效果,每个节点上能跑更多的pod。
在下面的例子中,我们将为c5.2xlarge
设置Pod密度,让它最多跑六个Pod(它有8个CPU,如果pod需要1个cpu的话能跑8个)
注意设置Static Pod Density的时候很容易遇到一个坑——忽略Daemenset的数量。比如我们node上有六个DaemonSet在跑,那么应用直接启动不起来,因为一启动就会超出maxPods的值
我们将这样设置:
kubeletConfiguration:
maxPods: 6
先删除之前创建的资源:
kubectl delete deployment inflate
kubectl delete provisioners.karpenter.sh default
kubectl delete awsnodetemplates.karpenter.k8s.aws default
部署Provisioner和Node Template,注意在spec.kubeletConfiguration
部分指定了最大Pod数量:
mkdir ~/environment/karpenter
cd ~/environment/karpenter
cat <<EoF> static.yaml
apiVersion: karpenter.sh/v1alpha5
kind: Provisioner
metadata:
name: default
spec:
providerRef:
name: default
ttlSecondsAfterEmpty: 30
labels:
eks-immersion-team: my-team
requirements:
- key: "node.kubernetes.io/instance-type"
operator: In
values: ["c5.2xlarge"]
- key: "kubernetes.io/arch"
operator: In
values: ["amd64"]
- key: "karpenter.sh/capacity-type" # If not included, the webhook for the AWS cloud provider will default to on-demand
operator: In
values: ["on-demand"]
kubeletConfiguration:
maxPods: 6
---
apiVersion: karpenter.k8s.aws/v1alpha1
kind: AWSNodeTemplate
metadata:
name: default
spec:
subnetSelector:
alpha.eksctl.io/cluster-name: ${CLUSTER_NAME}
securityGroupSelector:
aws:eks:cluster-name: ${CLUSTER_NAME}
tags:
managed-by: "karpenter"
intent: "apps"
EoF
kubectl apply -f static.yaml
创建应用:
cd ~/environment/karpenter
cat <<EoF> static-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: inflate
spec:
replicas: 3 # 这里是因为我们Pod上跑了4个DaemonSet,可以继续将这个值调大
selector:
matchLabels:
app: inflate
template:
metadata:
labels:
app: inflate
spec:
terminationGracePeriodSeconds: 0
containers:
- name: inflate
image: public.ecr.aws/eks-distro/kubernetes/pause:3.7
resources:
requests:
cpu: 1
nodeSelector:
eks-immersion-team: my-team
EoF
kubectl apply -f static-deploy.yaml
由于我们每个节点上要跑4个DaemonSet,maxPods设置的为6,所以此时即使要创建三个replica也需要两台机器,一台上跑2个replica,另一台跑1个:
可以设置每个CPU核上运行Pod的数量,从而更好的利用CPU资源。Karpenter把这个值传给kubelet的--pods-per-core
参数来完成设置。例如如果将其设置为5,Karpenter会尝试每个CPU核上运行5个pod,所以如果你有8核CPU,Karpenter将在上面部署40个Pod:
kubeletConfiguration:
podsPerCore: 5
首先清理之前创建的资源:
kubectl delete deployment inflate
kubectl delete provisioners.karpenter.sh default
kubectl delete awsnodetemplates.karpenter.k8s.aws default
部署Provisioner和Node template,为了设置每个CPU核上最大Pod数量,在spec.kubeletConfiguration
中指定了podsPerCore
:
mkdir -p ~/environment/karpenter
cd ~/environment/karpenter
cat <<EoF> dynamic.yaml
apiVersion: karpenter.sh/v1alpha5
kind: Provisioner
metadata:
name: default
spec:
providerRef:
name: default
ttlSecondsAfterEmpty: 30
labels:
eks-immersion-team: my-team
requirements:
- key: "node.kubernetes.io/instance-type"
operator: In
values: ["c6a.2xlarge"]
- key: "kubernetes.io/arch"
operator: In
values: ["amd64"]
- key: "karpenter.sh/capacity-type" # If not included, the webhook for the AWS cloud provider will default to on-demand
operator: In
values: ["on-demand"]
kubeletConfiguration:
podsPerCore: 5
---
apiVersion: karpenter.k8s.aws/v1alpha1
kind: AWSNodeTemplate
metadata:
name: default
spec:
subnetSelector:
alpha.eksctl.io/cluster-name: ${CLUSTER_NAME}
securityGroupSelector:
aws:eks:cluster-name: ${CLUSTER_NAME}
tags:
managed-by: "karpenter"
intent: "apps"
EoF
kubectl apply -f dynamic.yaml
我们创建inflate应用,并让它有45个replica:
cd ~/environment/karpenter
cat <<EoF> dynamic-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: inflate
spec:
replicas: 45
selector:
matchLabels:
app: inflate
template:
metadata:
labels:
app: inflate
spec:
terminationGracePeriodSeconds: 0
containers:
- name: inflate
image: public.ecr.aws/eks-distro/kubernetes/pause:3.7
resources:
requests:
cpu: 0.1
nodeSelector:
eks-immersion-team: my-team
EoF
kubectl apply -f dynamic-deploy.yaml
c6a.2xlarge
具有8个CPU,我们将cpu request设置为0.1,理想情况它上面应该能跑80个pod。但是因为设置了podsPerCore = 5
,所以它实际最多只能跑40个pod: