概要介紹
Karpenter是一款現代Kubernetes自動擴縮器,旨在與云提供商緊密集成,為 Kubernetes 集群提供更智能的節點自動擴縮。
它旨在克服 Cluster Autoscaler 等傳統工具的局限性,并提供靈活而強大的解決方案來配置工作節點,同時確保適當的資源分配。
Karpenter是亞馬遜捐獻的CNCF項目,最初于 2021 年 11 月推出,剛發布1.0版本。
官方文檔:karpenter.sh/docs
使用示例
該示例將演示如何為不同的團隊設置多個 NodePools 并隔離每個workload
需要提前準備好aws的EKS集群
部署 Karpenter
使用下面的 Helm 命令開始安裝。還有其他標志可用于自定義安裝配置:
helm upgrade --install karpenter oci://public.ecr.aws/karpenter/karpenter --version "${KARPENTER_VERSION}" --namespace "${KARPENTER_NAMESPACE}" --create-namespace \
--set "settings.clusterName=${CLUSTER_NAME}" \
--set "settings.interruptionQueue=${CLUSTER_NAME}" \
--set controller.resources.requests.cpu=1 \
--set controller.resources.requests.memory=1Gi \
--set serviceAccount.create=false \
--set serviceAccount.name=karpenter \
--wait
我們需要設置一些 NodePools 和 NodeClass 資源來定義所需的工作節點配置。運行以下命令將創建兩個 NodePools 和一個 NodeClass 對象,每個 NodePool 包含一個基于團隊的污點。
與 EC2 實例關聯的子網和安全組是根據現有標簽自動選擇的,這些標簽都是由 eksctl 在前面的步驟中創建的。
cat <<EOF | envsubst | kubectl apply -f -
apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
name: team-1
spec:
template:
spec:
taints:
- key: team-1-nodes
effect: NoSchedule
requirements:
- key: kubernetes.io/arch
operator: In
values: ["amd64"]
nodeClassRef:
name: default
---
apiVersion: karpenter.sh/v1beta1
kind: NodePool metadata:
name: team-2
spec:
template:
spec:
taints:
- key: team-2-nodes
effect: NoSchedule
requirements:
- key: kubernetes.io/arch
operator: In
values: ["amd64"]
nodeClassRef:
name: default
---
apiVersion: karpenter.k8s.aws/v1beta1
kind: EC2NodeClass
metadata:
name: default
spec:
amiFamily: AL2 # Amazon Linux 2
role: "KarpenterNodeRole-${CLUSTER_NAME}"
subnetSelectorTerms:
- tags:
karpenter.sh/discovery: "${CLUSTER_NAME}"
securityGroupSelectorTerms:
- tags:
karpenter.sh/discovery: "${CLUSTER_NAME}"
EOF
完成上述步驟后,集群即可開始調度新 Pod。讓我們部署一些 Pod 來驗證 Karpenter 是否正常工作。
部署workload
我們將使用以下 YAML 部署兩個 Pod。每個 Pod 將具有單獨的容忍度,允許 Pod 僅調度到我們上面定義的 NodePool 之一。部署這兩個 Pod 后,我們預計會看到“team-1-nginx”Pod 調度到“team-1”NodePool,而“team-2-nginx”Pod 調度到“team-2”NodePool。該示例演示了如何配置多個 NodePool 以根據污點和容忍度隔離不同類型的workload,并依靠 Karpenter 啟動適當的節點來調度所需的 Pod:
kubectl apply -f -
<<EOF apiVersion: v1
kind: Pod
metadata:
name: team-1-nginx
spec:
containers:
- name: nginx
image: nginx
resources:
requests:
cpu: "0.5"
memory: 300Mi
tolerations:
- key: "team-1-nodes"
operator: "Exists"
effect: "NoSchedule"
---
apiVersion: v1
kind: Pod
metadata:
name: team-2-nginx
spec:
containers:
- name: nginx
image: nginx
resources:
requests:
cpu: "0.5"
memory: 300Mi
tolerations:
- key: "team-2-nodes"
operator: "Exists"
effect: "NoSchedule"
EOF
Karpenter 將看到上面的 Pod 卡在“不可調度”狀態,因為沒有 EC2 實例來托管它們。它將通過配置兩個新節點來適應我們的新 Pod,如下所示:
kubectl logs deploy/karpenter --namespace "${KARPENTER_NAMESPACE}"
# "message":"found provisionable pod(s)"
kubectl get nodes
# ip-192-168-4-xx.us-west-2.compute.internal Ready v1.29.0
# ip-192-168-8-xx.us-west-2.compute.internal Ready v1.29.0
kubectl get pods
# team-1-nginx Running
# team-2-nginx Running
上述測試表明,Karpenter 成功配置了新的工作節點來托管我們的 Pod,同時遵守了污點和容忍度配置。
同理,可以通過使用更精細的設置擴展 NodePools 和 NodeClass,并部署具有不同約束(如 Pod 親和性)的新workload,以觀察 Karpenter 的配置行為。
刪除 Pod 將導致 Karpenter 自動終止多余的節點。