让我们先从基本配置开始,看看 Karpenter 在幕后是如何工作的。
创建NodePool是必要的,Karpenter 在至少配置了一个NodePool之前,将保持非活动状态
spec.template.spec.nodeClassRef
引用一个 EC2NodeClass。让我们创建一个NodePool和NodeClass,我们在下面的NodePool中指定的一些详细信息如下:
pod.spec.affinity.nodeAffinity
规则结合使用。
nodelSelector
,以确保我们的应用程序只能在具有此标签的节点上部署。如果我们使用自己的方式创建 EKS 集群,请确保相应地更改下面节点类规范中的 “subnetSelector” 和 “securityGroupSelector” 的值。
mkdir ~/environment/karpenter
cd ~/environment/karpenter
cat <<EoF> basic.yaml
apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
name: default
spec:
disruption:
consolidateAfter: 30s
consolidationPolicy: WhenEmpty
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 # If not included, the webhook for the AWS cloud provider will default to on-demand
operator: In
values: ["on-demand"]
- key: kubernetes.io/os
operator: In
values: ["linux"]
---
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
EoF
kubectl apply -f basic.yaml
部署后,看到:
Karpenter 提供了一种自动扩展机制,可以根据未调度的 pod 来扩展节点。当在 Kubernetes 中创建一个 pod 时,Kubernetes 调度器负责将该 pod 调度到集群中的一个节点上。如果没有可用的节点可以容纳该 pod,它将保持在 Pending 状态,直到有节点可用。Karpenter 可以监控集群中的pending pod,并通过创建新节点来扩展集群以满足 pod 的需求。在本示例中,我们将看到当我们扩展应用程序 pod 并且它们处于pending状态时,Karpenter 如何创建新节点。
让我们部署我们的第一个应用程序,副本数为零。
nodeSelector
可确保pending的 pod 始终落在 Karpenter NodePool 创建的实例上。cd ~/environment/karpenter
cat <<EoF> basic-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: inflate
spec:
replicas: 0
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 basic-deploy.yaml
deployment.apps/inflate created
让我们先看看当前 EKS 集群中有多少个节点。打开kube ops view, 我们可以看到有两个节点,这些节点是在 EKS 集群创建设置过程中创建的:
现在,让我们将replica从 0 扩展到 5 个
kubectl scale deployment inflate --replicas 5
deployment.apps/inflate scaled
检查 Karpenter 的日志(我们应该在 karpenter 控制器 pod 的日志中看到此日志)。
kubectl -n karpenter logs -l app.kubernetes.io/name=karpenter
我们应该在日志中看到 launched nodeclaim
消息
在 kube ops view中,我们将看到 Karpenter 创建了一个 c6a.2xlarge (具有 8 个 vCPU) 的节点。
检查NodePool 管理的节点:
kubectl get nodes -l eks-immersion-team=my-team
可以看到有七个 pod 落在这个新节点上。 还可以检查 Karpenter 创建的节点的元数据:
kubectl get node -l eks-immersion-team=my-team -o json | jq -r '.items[0].metadata.labels'