Spot到Spot的Consolidation

Karpenter 可以将 pod 从一个 Spot 节点合并到另一个 Spot 节点,终止未使用的 Spot 实例,从而进一步优化成本。

首先,让我们在开始新的deploy之前清理现有的 NodePool 和deployment,否则结果可能会有所不同:

kubectl delete deployment  inflate
kubectl delete nodepool.karpenter.sh default
kubectl delete ec2nodeclass.karpenter.k8s.aws default

部署 NodePool

让我们部署 Spot 实例的 Nodepool:

mkdir -p ~/environment/karpenter
cd ~/environment/karpenter
cat <<EoF> spottospot.yaml
apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
  name: default
spec:
  disruption:
    consolidationPolicy: WhenUnderutilized
    expireAfter: Never
  limits:
    cpu: 10
  template:
    metadata:
      labels:
        eks-immersion-team: my-team
    spec:
      nodeClassRef:
        name: default
      requirements:
      - key: karpenter.k8s.aws/instance-category
        operator: In
        values:
        - c
        - m
        - r
      - key: kubernetes.io/arch
        operator: In
        values:
        - amd64
      - key: karpenter.sh/capacity-type
        operator: In
        values:
        - spot

---
apiVersion: karpenter.k8s.aws/v1beta1
kind: EC2NodeClass
metadata:
  name: default
spec:
  amiFamily: AL2
  role: "KarpenterNodeRole-${CLUSTER_NAME}"
  securityGroupSelectorTerms:
  - tags:
      alpha.eksctl.io/cluster-name: $CLUSTER_NAME
  subnetSelectorTerms:
  - tags:
      alpha.eksctl.io/cluster-name: $CLUSTER_NAME
  tags:
    intent: apps
    managed-by: karpenter
    eks-immersion-team: my-team
EoF

kubectl apply -f spottospot.yaml

部署应用

让我们部署应用:

  1. 容器资源请求为"1” CPU 和"1Gi” 内存。
  2. 我们还将副本数更改为 8
cd ~/environment/karpenter
cat <<EoF> spot-consolidation.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: inflate
spec:
  replicas: 8
  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:
              memory: 1Gi
              cpu: 1
      nodeSelector:
        eks-immersion-team: my-team
EoF

kubectl apply -f spot-consolidation.yaml

我们看到 Karpenter 在两个节点上调度了 8 个应用程pod,这两个节点,一个是2xlarge,一个是large:

image-20240803213234978

现在,让我们将deploy缩到 4 个副本。

kubectl scale deployment inflate --replicas 4
deployment.apps/inflate scaled

eks先将2xlarge节点上的4个pod下掉,分布成3:1

image-20240803213424512

karpenter检查到可以将large节点上的1个pod移动到2xlarge上,再把large节点下掉。最终如下:

image-20240803213441484

检查 Karpenter 的日志:

kubectl -n karpenter logs -l app.kubernetes.io/name=karpenter

我们应该在日志中看到 disrupting via consolidation deleteterminating 1 nodes 的消息

image-20240803213511990

假如我们再将replica缩小到3个:

kubectl scale deployment inflate --replicas 3

image-20240803213803984

Karpenter也不会再将2xlarge consolidation成xlarge,这是因为它是spot节点。对于spot节点,只有删除机制,Karpenter不会使用节点替换

清理

删除示例应用、NodePool 和 EC2NodeClass 资源。

cd ~/environment/karpenter
kubectl delete -f spottospot.yaml
kubectl delete -f spot-consolidation.yaml