Ssoon
[5주차] EKS Autoscaling - KARPENTER - MULTI-ARCHITECTURE DEPLOYMENTS 본문
[5주차] EKS Autoscaling - KARPENTER - MULTI-ARCHITECTURE DEPLOYMENTS
구구달스 2023. 5. 25. 16:23CloudNet@ 팀의 AWS EKS Workshop Study 5주차 정리입니다.
# Karpenter Workshop 의 내용입니다.
[ DEPLOYING MULTIPLE PROVISIONERS ]
Setting up the Provisioners CRD
- 프로비저너 CRD(Custom Resource Definition)를 설정합니다.
- 기본값으로 하나를 설정하고 이전에 생성한 것을 재정의하고 team1이라는 새 프로비저너를 설정합니다.
- 기본 제공자의 구성을 변경합니다.
cat <<EOF | kubectl apply -f -
apiVersion: karpenter.sh/v1alpha5
kind: Provisioner
metadata:
name: default
spec:
consolidation:
enabled: true
weight: 100
labels:
intent: apps
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand","spot"]
- key: kubernetes.io/arch
operator: In
values: ["amd64","arm64"]
limits:
resources:
cpu: 1000
memory: 1000Gi
ttlSecondsUntilExpired: 2592000
providerRef:
name: default
---
apiVersion: karpenter.k8s.aws/v1alpha1
kind: AWSNodeTemplate
metadata:
name: default
spec:
subnetSelector:
alpha.eksctl.io/cluster-name: ${CLUSTER_NAME}
securityGroupSelector:
alpha.eksctl.io/cluster-name: ${CLUSTER_NAME}
tags:
KarpenerProvisionerName: "default"
NodeType: "karpenter-workshop"
IntentLabel: "apps"
EOF
- team1이라는 보조 프로비저너를 배포합니다.
cat <<EOF | kubectl apply -f -
apiVersion: karpenter.sh/v1alpha5
kind: Provisioner
metadata:
name: team1
spec:
labels:
intent: apps
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand"]
- key: kubernetes.io/arch
operator: In
values: ["amd64","arm64"]
limits:
resources:
cpu: 1000
memory: 1000Gi
ttlSecondsAfterEmpty: 30
ttlSecondsUntilExpired: 2592000
taints:
- effect: NoSchedule
key: team1
providerRef:
name: team1
---
apiVersion: karpenter.k8s.aws/v1alpha1
kind: AWSNodeTemplate
metadata:
name: team1
spec:
amiFamily: Bottlerocket
subnetSelector:
alpha.eksctl.io/cluster-name: ${CLUSTER_NAME}
securityGroupSelector:
alpha.eksctl.io/cluster-name: ${CLUSTER_NAME}
tags:
KarpenerProvisionerName: "team1"
NodeType: "karpenter-workshop"
IntentLabel: "apps"
userData: |
[settings.kubernetes]
kube-api-qps = 30
[settings.kubernetes.eviction-hard]
"memory.available" = "20%"
EOF
- 두 프로비저너 모두 레이블 intent: apps 을 설정합니다. 이것은 intent: control-apps 를 가진 관리 노드 그룹에 설정된 것과 용량을 구별합니다.
- 둘 다 아키텍처 amd64(x86_64와 동일) 및 arm64를 허용합니다.
- 기본 프로비저너는 이제 spot 및 on-demand 용량 유형을 모두 지원합니다. 그러나 team1 프로비저너는 on-demand 만 지원합니다.
- team1 프로비저너는 key team1에 대한 Toleration을 제공하는 Pods 또는 Jobs 만 지원합니다. 이 제공자가 조달한 노드는 key team1 및 효과 NoSchedule 과 함께 Taint를 사용하여 tainted 됩니다.
- team1 프로비저너는 다른 AWSNodeTemplate 을 정의하고 AMI를 기본 EKS 최적화 AMI에서 bottlerocket으로 변경합니다. 또한 이 특정 공급자에 대한 UserData 부트스트래핑을 조정합니다.
- 기본 프로비저너는 가중치 100을 설정합니다. 프로비저너 평가는 가중치를 사용할 수 있습니다. 가중치가 높을수록 평가의 우선 순위가 높아집니다. 워크로드와 일치하는 첫 번째 프로비저너가 사용됩니다.
Karpenter가 Pod 에서 허용되지 않는 프로비저너에서 taint 을 발견하면 Karpenter는 해당 프로비저너를 사용하여 포드를 프로비저닝하지 않습니다. 상호 배타적인 프로비저너를 생성하는 것이 좋습니다. 따라서 포드가 여러 프로비저너와 일치해서는 안 됩니다. 여러 프로비저너가 일치하는 경우 Karpenter는 사용할 항목을 무작위로 선택합니다.
- 현재 프로비저너 구성정보를 확인합니다.
- 프로비저너 내의 provider 섹션을 확인할 수 있습니다.
[ MULTI-ARCHITECTURE DEPLOYMENTS ]
두 개의 프로비저닝을 정의했는데, 두 프로비저닝 모두 amd64(x86_64) 및 arm64 아키텍처를 지원합니다.
특정 아키텍처가 필요한 애플리케이션을 배포합니다.
Creating Multi-Architecture Deployments
각 아키텍처에 대해 하나씩 두 개의 새 deployments를 생성합니다. 0개의 복제본으로 deployments 를 시작하겠습니다.
- amd64 deployment 를 생성합니다.
cat <<EOF > inflate-amd64.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: inflate-amd64
spec:
replicas: 0
selector:
matchLabels:
app: inflate-amd64
template:
metadata:
labels:
app: inflate-amd64
spec:
nodeSelector:
intent: apps
kubernetes.io/arch: amd64
karpenter.sh/capacity-type: on-demand
containers:
- image: public.ecr.aws/eks-distro/kubernetes/pause:3.2
name: inflate-amd64
resources:
requests:
cpu: "1"
memory: 256M
EOF
kubectl apply -f inflate-amd64.yaml
- arm64 deployment 를 생성합니다.
cat <<EOF > inflate-arm64.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: inflate-arm64
spec:
replicas: 0
selector:
matchLabels:
app: inflate-arm64
template:
metadata:
labels:
app: inflate-arm64
spec:
nodeSelector:
intent: apps
kubernetes.io/arch: arm64
node.kubernetes.io/instance-type: c6g.xlarge
containers:
- image: public.ecr.aws/eks-distro/kubernetes/pause:3.2
name: inflate-arm64
resources:
requests:
cpu: "1"
memory: 256M
EOF
kubectl apply -f inflate-arm64.yaml
inflate-amd64 deployment 를 2개의 replicas 로 확장합니다. 카펜터는 어떤 노드를 선택했나요?
kubectl scale deployment inflate-amd64 --replicas 2
- Node selector 는 사용자가 pod 를 스케줄링할 수 있는 노드를 지정할 수 있는 opt-in 메커니즘이다.
- Karpenter 는 unschedulable pod 에서 well-known Node selector 를 인식하고 이를 사용하여 프로비저닝하는 노드를 제한한다.
- kubernetes.io/arch는 카펜터에서 well-known Node selector 중 하나이다. 카펜터가 kubernetes.io/arch가 amd64로 설정된 것을 발견하면 프로비저닝된 노드가 amd64 인스턴스에 따라 제약되도록 보장한다.
controller.provisioner launching machine with 2 pods requesting {"cpu":"2125m","memory":"512M","pods":"4"} from types m5a.16xlarge, r5ad.8xlarge, m5ad.8xlarge, r5.24xlarge, m5.metal and 159 other(s) {"commit": "982c35f", "provisioner": "default"}
첫 번째는 인스턴스 선택에 사용된 프로비저너와 관련된 것입니다. 로그는 controller.allocation.provisioner/default 가 선택한 것을 가리킵니다.
로그에는 선택된 인스턴스가 c5a.xlarge 유형의 on-demand 인스턴스이며, 인스턴스 diversified selection (from types m5a.16xlarge, r5ad.8xlarge, m5ad.8xlarge, r5.24xlarge, m5.metal and 159 other(s) 에서 고려되었음을 보여 줍니다.
목록에 있는 모든 인스턴스는 유형이 amd64 또는 x86_64이며, 모두 최소한 2개의 복제본 배포에 적합한 크기입니다.
spec:
nodeSelector:
intent: apps
kubernetes.io/arch: amd64
karpenter.sh/capacity-type: on-demand
Node selector 는 사용자가 파드를 스케줄링할 수 있는 노드를 지정할 수 있는 옵트인 메커니즘입니다.
Karpenter는 pending pods 에 정의된 Node selector 를 사용하고 그에 따라 용량을 프로비저닝합니다.
kubernetes.sh/capacity-type 에 대한 Node selector 에 on-demand 로 명시되어 있습니다.
내부적으로 Karpenter는 온디맨드 인스턴스에 대해 최저 가격 할당 전략을 사용합니다.
CloudTrail을 사용하여 CreateFleet에 대한 최신 호출(EC2 Fleet instant mode call)을 추출해 보겠습니다.
aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=CreateFleet --max-items=1
그러면 이 계정에서 수행된 CreateFleet에 대한 마지막 호출이 표시됩니다. CloudTrailEvent의 출력에는 이스케이프된 JSON 문서가 표시됩니다. Cloud9 콘솔에서 "Control-F" 를 입력하고 lowest-price 를 검색할 수 있습니다.
"OnDemandOptions\":{\"AllocationStrategy\":\"lowest-price\"
또한 intent:apps 및 kubernetes.io/arch:amd64 를 필터링하는 다음 명령을 실행하여 선택한 인스턴스에 대한 자세한 정보를 얻을 수 있습니다.
kubectl get node --selector=intent=apps -L kubernetes.io/arch -L node.kubernetes.io/instance-type -L karpenter.sh/provisioner-name -L topology.kubernetes.io/zone -L karpenter.sh/capacity-type
inflate-arm64 deployment 를 2개의 replicas 로 확장합니다. 카펜터는 어떤 노드를 선택했나요?
kubectl scale deployment inflate-arm64 --replicas 2
- node.kubernetes.io/instance-type: c6g.xlarge
spec:
nodeSelector:
intent: apps
kubernetes.io/arch: arm64
node.kubernetes.io/instance-type: c6g.xlarge
- Karpenter 로그를 실행하여 확인할 수 있습니다
- intent:apps 및 kubernetes.io/arch:arm64를 필터링하여 선택한 인스턴스에 대한 자세한 정보를 얻을 수 있습니다.
kubectl get node --selector=intent=apps,kubernetes.io/arch=arm64 -L kubernetes.io/arch -L node.kubernetes.io/instance-type -L karpenter.sh/provisioner-name -L topology.kubernetes.io/zone -L karpenter.sh/capacity-type
두 deployment 를 replicas 를 0으로 변경합니다.
kubectl scale deployment inflate-amd64 --replicas 0
kubectl scale deployment inflate-arm64 --replicas 0
[ 정리 ]
- Karpenter 는 NodeSelector pods 에서 well-known labels 을 사용하여 선택한 타입 인스턴스를 오버라이드합니다. 실습에서는 NodeSelector kubernetes.io/arch를 사용하여 amd64 x86_64 및 arm64 타입의 인스턴스를 선택했습니다. 또한 well-known labels 인 node.kubernetes.io/instance-type(예: c6g.xlarge)을 사용하여 특정 인스턴스 유형을 선택할 수 있습니다.
- NodeSelector 가 지정되지 않은 경우, Karpenter 는 해당 레이블에 대한 default 구성 설정으로 되돌아간다. 이 경우, arm64 디플로이먼트의 경우 kubernetes.sh/capacity-type 속성이 설정되지 않았기 때문에 기본 프로비저너가 spot 과 on-demand 모두를 지원하더라도 spot 인스턴스가 선택되었다는 의미이다.
- Karpenter는 다양한 선택을 통해 on-demand 인스턴스도 확장합니다. spot 과 마찬가지로, 인스턴스는 pending pods 를 bin-pack well 하는 능력에 따라 선택됩니다. Karpenter는 on-demand 할당 전략인 lowest-price 을 사용하여 사용 가능한 용량이 있는 인스턴스 중에서 어떤 인스턴스를 선택할지 선택합니다.
'AWS EKS Workshop Study' 카테고리의 다른 글
[5주차] EKS Autoscaling - Scaling App and Cluster - BUILD THE MICROSERVICE (0) | 2023.05.25 |
---|---|
[5주차] EKS Autoscaling - KARPENTER - USING ALTERNATIVE PROVISIONERS (0) | 2023.05.25 |
[5주차] EKS Autoscaling - KARPENTER - EC2 SPOT DEPLOYMENTS (0) | 2023.05.25 |
[5주차] EKS Autoscaling - KARPENTER - CONSOLIDATION (0) | 2023.05.25 |
[5주차] EKS Autoscaling - KARPENTER - AUTOMATIC NODE PROVISIONING (0) | 2023.05.25 |