본문 바로가기
  • lakescript
스터디 이야기/AWS EKS

[AEWS] 3-2. Amazon EKS - NodeGroup (ARM Instance, Spot Instance)

by lakescript 2024. 3. 21.

사전 준비

더보기

 

위와 같이 사전 준비가 필요합니다.

저번 글에서 설명했듯이, EKS를 배포하기 위한 VPC를 생성하고, Public Subnet, Private Subnet을 생성합니다. 그 후 EKS Cluster에 접근하기 위한 bastion EC2를 미리 생성합니다.

 

Amazon EKS NodeGroup

ChatGPT가 알려주는 Amazon EKS의 NodeGroup
Amazon EKS의 Node Group은 EKS 클러스터 내에서 애플리케이션을 실행하는 데 사용되는 워커 노드(또는 서버)의 집합입니다. EKS를 사용하면 Kubernetes 애플리케이션을 AWS 클라우드 인프라상에서 쉽게 실행, 관리 및 확장할 수 있습니다. 

 

즉, Worker Node로 사용할 EC2 Instance의 묶음이라고 보실 수 있습니다.

 

ARM 기반 EC2 NodeGroup

 

보통 Cluster를 생성하고 실제 운영을 하실 때에는 한 개의 NodeGroup만 생성하여 애플리케이션을 띄우고 운영을 하시는 경우가 많습니다. 하지만 요즘은 LLM이나 AI 등 ARM을 요구하는 애플리케이션이 많은데요. 현재 호스팅 하고 있는 Worker Node를 모두 ARM 형식으로 바꾸게 되면 운영되고 있는 애플리케이션에 호환성 관련 문제가 생길 수 있습니다. 그렇기에 최적의 방안은 ARM 기반의 EC2를 배포하는 NodeGroup을 생성하고, 해당 node에 Taint를 주어 일반 Pod는 스케줄링 할 수 없게 만들고, ARM을 요구하는 애플리케이션의 Pod는 Toleration을 주어 해당 Nodegroup의 EC2에 연결하는 것입니다.

 

현재 Cluster에 연결되어 있는 NodeGroup 확인

 

AWS Manages Console에 접근하시어 EKS 메뉴에서 컴퓨팅 탭에 접근하시면 위의 사진과 같이 현재 Cluster에 연결되어있는 NodeGroup을 확인하실 수 있습니다.

 

또한 aws cli를 통해 확인가능합니다.

aws eks list-nodegroups --cluster-name $CLUSTER_NAME

 

 

현재 연결되어 있는 EC2 Node들의 arch를 확인해보겠습니다.

kubectl get nodes -L kubernetes.io/arch

 

amd64 기반의 EC2들이 연결되어 있는 것을 확인하실 수 있습니다.

 

 

신규 노드 그룹 생성

eksctl create nodegroup -c $CLUSTER_NAME -r $AWS_DEFAULT_REGION --subnet-ids "$PubSubnet1","$PubSubnet2","$PubSubnet3" --ssh-access   -n nq-arm -t t4g.medium -N 1 -m 1 -M 1 --node-volume-size=30 --node-labels family=graviton

 

--dry-run 옵션을 주어 nodegroup을 배포하기 전에 한번 더 확인해 보겠습니다.

 

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
managedNodeGroups:
- amiFamily: AmazonLinux2
  desiredCapacity: 1
  disableIMDSv1: true
  disablePodIMDS: false
  iam:
    withAddonPolicies:
      albIngress: false
      appMesh: false
      appMeshPreview: false
      autoScaler: false
      awsLoadBalancerController: false
      certManager: false
      cloudWatch: false
      ebs: false
      efs: false
      externalDNS: false
      fsx: false
      imageBuilder: false
      xRay: false
  instanceSelector: {}
  instanceType: t4g.medium
  labels:
    alpha.eksctl.io/cluster-name: myeks
    alpha.eksctl.io/nodegroup-name: ng3
    family: graviton
  maxSize: 1
  minSize: 1
  name: ng-arm
  privateNetworking: false
  releaseVersion: ""
  securityGroups:
    withLocal: null
    withShared: null
  ssh:
    allow: true
    publicKeyPath: ~/.ssh/id_rsa.pub
  subnets:
  - subnet-01dec1caccaade360
  - subnet-062d303f6e13f1c83
  - subnet-0b9ade2e30b1b002e
  tags:
    alpha.eksctl.io/nodegroup-name: ng3
    alpha.eksctl.io/nodegroup-type: managed
  volumeIOPS: 3000
  volumeSize: 30
  volumeThroughput: 125
  volumeType: gp3
metadata:
  name: myeks
  region: ap-northeast-2
  version: "1.28"

 

주로 보실 건, InstanceType입니다. 위의 명세 파일에서는 t4g.medium를 사용했는데요. 

 

Graviton 기반 인스턴스는 인스턴스 유형 규칙에서 문자 g로 식별할 수 있습니다. 즉, t4g에서 g로 인해 이 EC2가 Graviton 기반 인스턴스 (ARM)이라는 것을 알 수 있습니다. 

 

생성된 노드 그룹 확인

다시 AWS Managed Console에 들어가서 확인해 보시면 아래와 같이 ng-arm Nodegroup이 생성된 것을 확인하실 수 있습니다.

 

마찬가지로 awc cli를 통해서도 확인가능합니다.

 

aws eks list-nodegroups --cluster-name $CLUSTER_NAME

 

NodeGroup이 활성화될 때까지 잠시 기다리기

aws eks wait nodegroup-active --cluster-name $CLUSTER_NAME --nodegroup-name $NODEGROUP_NAME

 

이 명령어는 노드 그룹의 생성, 업데이트 또는 스케일링 작업이 완료되고 노드 그룹이 완전히 활성화될 때까지 CLI가 응답을 보류하도록 합니다.

 

 

생성된 Node 확인

 

이제 현재 Cluster에 연결되어 있는 Worker Node의 type을 한번 보겠습니다.

kubectl get nodes --label-columns eks.amazonaws.com/nodegroup,kubernetes.io/arch

 

 

위의 사진처럼 arm64 기반의 node가 생성되어 있는 것을 확인하실 수 있습니다.

 

taints 설정

aws eks update-nodegroup-config --cluster-name $CLUSTER_NAME --nodegroup-name ng-arm --taints "addOrUpdateTaints=[{key=frontend, value=true, effect=NO_EXECUTE}]"

 

위의 명령어를 통해 key:frontend, value: ture, effect: NO_EXCUTE를 taint로 설정하였습니다.

aws eks describe-nodegroup --cluster-name $CLUSTER_NAME --nodegroup-name ng-arm | jq .nodegroup.taints

 

2~3분 정도의 설정시간이 필요하니 그 후에 위의 명령어로 taint를 확인해 보겠습니다.

 

Pod 띄우기

 

이제 ARM 기반의 Node를 생성하였고, taint를 걸어 아무 Pod나 배포할 수 없게 설정하였습니다. 그러면 이제 이 Node에 배포할 수 있는 Pod를 tolerations 설정을 통해 생성해 보겠습니다.

apiVersion: v1
kind: Pod
metadata:
  name: busybox
spec:
  terminationGracePeriodSeconds: 3
  containers:
  - name: busybox
    image: busybox
    command:
    - "/bin/sh"
    - "-c"
    - "while true; do date >> /home/pod-out.txt; cd /home; sync; sync; sleep 10; done"
  tolerations:
    - effect: NoExecute
      key: frontend
      operator: Exists

 

위의 명세를 보시면 tolerations에 key: frontend를 주어 frontend라는 key로 taint 설정된 Node에 스케줄링 가능하도록 생성하였습니다.

 

ARM 기반의 Node에 배포되었는지 확인

 

 

위의 사진을 보시면 tolerations을 가진 busybox를 생성하였고, 그에 맞게 taint가 설정된 node에 정상적으로 배포된 것을 확인하실 수 있습니다.

 

 

Spot Instance NodeGroup

ChatGPT가 알려주는 Spot Instance
Spot Instance는 Amazon Web Services(AWS)에서 제공하는, 사용 가능한 컴퓨팅 용량을 시장 가격에 따라 구매할 수 있는 인스턴스 유형입니다. 이들은 온디맨드 인스턴스에 비해 훨씬 낮은 비용으로 제공되며, 비용을 최소화하면서 유연성이 높은 작업을 실행할 수 있는 효과적인 방법을 제공합니다.
Spot Instance를 사용할 때는 인스턴스가 예고 없이 종료될 수 있다는 점을 고려해야 합니다. AWS는 시장 가격이 사용자의 최대 가격을 초과하거나 AWS가 해당 용량이 필요할 경우 인스턴스를 회수할 수 있으며, 이 경우 사용자에게 종료 2분 전에 알림을 보냅니다. 따라서, Spot Instance는 중요한 실시간 애플리케이션보다는 중단이 허용되는 작업에 더 적합합니다.

 

즉, Spot Instance는 AWS에서 현재 사용하지 않는 컴퓨팅 자원을 저렴한 가격에 제공함으로써 서버를 임시로 사용할 수 있는 방법입니다. 하지만, AWS가 해당 서버 자원이 필요하게 되면 미리 알림을 보내주고 사용자는 서버를 반납해야 합니다.

 

현재 Cluster의 연결되어 있는 node들의 capacityType 확인

kubectl get nodes -L eks.amazonaws.com/capacityType

 

현재 사용하고 있는 NodeGroup의 Node들은 ON_DEMAND Type의 EC2 Instance입니다.

 

Spot type의 NodeGroup 생성

aws eks create-nodegroup \
  --cluster-name $CLUSTER_NAME \
  --nodegroup-name managed-spot \
  --subnets $PubSubnet1 $PubSubnet2 $PubSubnet3 \
  --node-role ${각자 자신의 노드롤 ARN을 입력하자} \
  --instance-types c5.large c5d.large c5a.large \
  --capacity-type SPOT \
  --scaling-config minSize=2,maxSize=3,desiredSize=2 \
  --disk-size 20

 

여기서 주의해야 할 점은 node-role 부분을 worker node로 사용하고 있는 EC2들의 IAM Role을 입력하셔야 합니다.

 

 

 

그 후 AWS Manages Console의 EKS에 접근하셔서 컴퓨팅 탭에서 NodeGroup을 확인해 보시면 managed-spot이라는 NodeGroup이 생성된 것을 확인하실 수 있습니다. (이것 또한 aws cli로도 확인가능합니다.)

 

 

 

NodeGroup이 활성화될 때까지 잠시 기다리기

aws eks wait nodegroup-active --cluster-name $CLUSTER_NAME --nodegroup-name $NODEGROUP_NAME

 

이 명령어는 노드 그룹의 생성, 업데이트 또는 스케일링 작업이 완료되고 노드 그룹이 완전히 활성화될 때까지 CLI가 응답을 보류하도록 합니다.

 

 

스팟 요청 확인

 

 

Amazon Managed Console에 접근하셔서 EC2 메뉴에서 스팟 요청 탭을 보시면 정상적으로 2개의 Spot Instance를 확인하실 수 있습니다!

 

Pod 띄우기

apiVersion: v1
kind: Pod
metadata:
  name: busybox
spec:
  terminationGracePeriodSeconds: 3
  containers:
  - name: busybox
    image: busybox
    command:
    - "/bin/sh"
    - "-c"
    - "while true; do date >> /home/pod-out.txt; cd /home; sync; sync; sleep 10; done"
  nodeSelector:
    eks.amazonaws.com/capacityType: SPOT

 

Pod 명세파일을 보면 nodeSelector에 capacityType: SPOT을 주어 SPOT Instance에 스케줄링 되게 설정합니다.

 

SPOT Instance Node에 배포되었는지 확인

 

 

 


Reference

- https://www.eksworkshop.com/docs/fundamentals/managed-node-groups/graviton/