概要介绍
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 自动终止多余的节点。