Karpenter 会自动将节点标注为Drifted,并添加注释 controller.nodeclaim.disruption:"marking drifted"
,如果节点使用的 AMI 与 EC2NodeClass
上设置的 AMI ID 不匹配。一旦节点被标记为Drifted,Karpenter 将自动隔离、排空和终止节点,同时满足任何托管具有 Pod 中断预算 (PDB) 或 karpenter.sh/do-not-disrupt: "true"
注释的 Pod 的节点。
我们将首先创建一个使用 Kubernetes 版本 1.29 AMI 的 EC2NodeClass,更新一个basic NodePool 以引用该新创建的 EC2NodeClass,并部署一个 Pod 来启动一个新节点。之后,我们将把 EC2NodeClass 中的 AMI 更改为 Kubernetes 版本 1.30,这最终会使先前的节点Drift,并用 1.30 版本的 AMI 替换它。
确保在继续之前已经创建了默认的 Nodepool
和 EC2NodeClass
。
kubectl get nodepool default && kubectl get ec2nodeclass default 2>/dev/null || echo "Not found"
我们应该看到类似的输出:
NAME NODECLASS
default default
NAME AGE
default 113m
首先为 AMI 设置一个环境变量。我们将设置一个 Kubernetes 版本 1.29 的 AMI 作为 AMI_OLD。
export AMI_OLD=$(aws ssm get-parameter --name /aws/service/eks/optimized-ami/1.29/amazon-linux-2/recommended/image_id --region $AWS_REGION --query "Parameter.Value" --output text)
echo 1.29=$AMI_OLD
例如,如果我们的区域是 us-west-2,这里是预期的输出:
1.29=ami-0a3a90a465f626a03
现在,让我们首先创建一个新的 EC2NodeClass。我们可以在以下 node-class 部分了解更多信息。
cd ~/environment/karpenter
cat << EoF > oldnode_class.yaml
apiVersion: karpenter.k8s.aws/v1beta1
kind: EC2NodeClass
metadata:
name: oldnode
spec:
amiFamily: AL2
amiSelectorTerms:
- id: $AMI_OLD
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 -f oldnode_class.yaml create
我们应该看到以下消息。
ec2nodeclass.karpenter.k8s.aws/oldnode created
让我们编辑默认的 nodepool 以使用这个新创建的 EC2NodeClass。
kubectl edit nodepool default
在 spec 下搜索 nodeClassRef
,并将 name 值从 default
更改为 oldnode
....
spec:
nodeClassRef:
name: oldnode <<<< 将 `default` 更改为 `oldnode`
requirements:
- key: karpenter.k8s.aws/instance-category
operator: In
我们将看到默认的 nodepool 已被编辑
nodepool.karpenter.sh/default edited
现在,让我们部署一个 Pod 来通过 Karpenter 启动一个节点。
cd ~/environment/karpenter
cat <<EoF> drift-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: inflate
spec:
replicas: 5
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 drift-deploy.yaml
deployment.apps/inflate created
让我们检查新部署节点的版本。
kubectl get nodes -l eks-immersion-team=my-team
我们将在几秒钟内看到一个版本为 1.29 (v1.29.xx-eks-xxxxxxx) 的节点就绪。
现在,让我们将 AMI 版本更改为v1.30。
首先,我们将设置一个 Kubernetes 版本 1.30 AMI 的环境变量。
export AMI_NEW=$(aws ssm get-parameter --name /aws/service/eks/optimized-ami/1.30/amazon-linux-2/recommended/image_id --region $AWS_REGION --query "Parameter.Value" --output text)
echo 1.30=$AMI_NEW
如果我们的区域是 us-west-2,这里是预期的输出:
1.30=ami-08946d4d49fc3f27b
现在,让我们创建一个新的 EC2NodeClass。
cd ~/environment/karpenter
cat << EoF > newnode_class.yaml
apiVersion: karpenter.k8s.aws/v1beta1
kind: EC2NodeClass
metadata:
name: newnode
spec:
amiFamily: AL2
amiSelectorTerms:
- id: $AMI_NEW
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 -f newnode_class.yaml create
我们应该看到以下消息。
ec2nodeclass.karpenter.k8s.aws/newnode created
现在,让我们使用新的 EC2NodeClass newnode
, 编辑默认的 nodepool:
kubectl edit nodepool default
在 spec 下搜索 providerRef
,并将 name 值从 oldnode
更改为 newnode
。
....
spec:
nodeClassRef:
name: newnode <<<< 将 `oldnode` 更改为 `newnode`
requirements:
- key: karpenter.k8s.aws/instance-category
operator: In
我们将看到默认的 nodepool 已被编辑
nodepool.karpenter.sh/default edited
让我们检查节点状态。
kubectl get nodes -l eks-immersion-team=my-team
我们将看到 v1.29 节点状态已更改为 Ready,SchedulingDisabled
,而新部署的 v1.30 节点仍处于 NotReady
状态。
ip-192-168-63-204.us-west-2.compute.internal NotReady <none> 23s v1.30.13-eks-0a21954
ip-192-168-66-103.us-west-2.compute.internal Ready,SchedulingDisabled <none> 6h8m v1.29.17-eks-0a21954
再次运行以下命令几秒钟后。最终,我们将看到 v1.29 节点已被终止,新创建的 v1.30 节点现已就绪。
kubectl get nodes -l eks-immersion-team=my-team
ip-192-168-63-204.us-west-2.compute.internal Ready <none> 76s v1.30.13-eks-0a21954
我们还可以检查漂移相关的日志消息。
kubectl -n karpenter logs --tail=100 -l app.kubernetes.io/name=karpenter | grep -i drift
删除deployment:
kubectl delete -f drift-deploy.yaml