본문 바로가기
Engineering

eksctl로 eks 구축해보기 with 스팟 인스턴스

by weq155 2024. 1. 25.
반응형
반응형

eksctl을 활용한 테스트용 eks를 구축

 

비용 효율적인 스팟인스턴스를 사용한 EKS를 구축해봄으로써 테스트 환경의 비용절감과 Unmanaged nodegroup을 사용해

스팟 인스턴스의 단점인 불안정성을 보완하는 환경을 구축해보는 테스트를 진행했다.

 

EKS Spot Instance

  • 목적 : 테스트나 개발 단계에서 EKS를 활용할 때 Spot Instance를 사용해 비용 절감
  • 상황 : Spot Instance는 저렴한 가격으로 이용할 수 있지만 Instance가 가격 변동이 생기면 자동으로 Terminate 됨
  • 목표 : Spot Instance를 사용해 비용을 절감하면서 기존 단점인 안정성을 확보할 수 있는 방안
Spot Request 프로세스

 

Spot Instance는 On-Demand Instance 보다 40~80% 정도 저렴합니다.

Instance Type, Availability Zones에 따라 다름

Spot Instance는 가격이 실시간으로 변동된다. → 가격 변동, Zone에 가용 용량이 부족한 경우 2분 내에 회수 됨

Spot Instance 가격은 AWS Console → EC2 → SpotRequest → Pricing history에서 확인 할 수 있습니다.

보통 1/3 정도 가격으로 Spot Instance를 사용 할 수 있다.

AWS Console에서는 Type과 하나의 Instance만 선택 할 수 있기 때문에 가격변동에 취약해 지게 됩니다.

그래서 eksctl을 활용해서 Eks 클러스터와 노드 그룹을 구성하게 되었습니다.

 


Spot NodeGroup 구성

  • 목표 : eksctl을 활용한 Cluster, NodeGroup 구성
  • 사전 준비 :
    • aws cli, eksctl 설치된 환경
    • AWS AccessKey, IAM Role : ssm(System Manager), Cloud Formation 권한 등 필요

eksctl을 사용하면 다양한 옵션을 포함한 Nodegroup을 생성할 수 있습니다.

하지만 명령어 보단 수정과 관리가 편한 Config 파일로 진행하였습니다.

 

명령어 사용 예시

eksctl create nodegroup \
  --cluster=eksworkshop-eksctl --region=${AWS_REGION} \
  --managed --spot --name=ng-spot \
  --instance-types=m5.large,m4.large,m5d.large,m5a.large,m5ad.large,m5n.large,m5dn.large

 

Config 파일 예시

다양한 파라미터가 있지만 제가 사용한 예시입니다.

다른 파라미터는https://eksctl.io/usage/schema/#nodeGroups-instancesDistribution 참고해 주세요

Cluster와 NodeGroup을 한번에 생성

eksctl에는 NodeGroup과 ManagedNodeGroup 두가지 방법으로 클러스터에 노드를 배포 할 수 있는데,

제가 테스트 해보았을 때는 ManagedNodeGroup은 기존 웹 콘솔 만큼만 설정이 가능한 것 같았습니다.

eksctl create cluster -f config.yaml

# 노드그룹만 배포를 하는 경우 
eksctl create nodegroup -f config.yaml
apiVersion: eksctl.io/v1alpha5 
kind: ClusterConfig
metadata:
  name: ${Cluster_Name}
  region: ${AWS_REGION}
  version: ${Kubernetes_Version}
# 클러스터 설정
vpc: 
  id: "${VPC_ID}"
  autoAllocateIPv6: false
  clusterEndpoints:
    privateAccess: true
    publicAccess: true
  #sharedNodeSecurityGroup: "${SG_ID}" 
  subnets:
    public:
      ap-northeast-2a:
        id: "PUBILC_SUBNET_ID"
      ap-northeast-2b:
        id: "PUBILC_SUBNET_ID"
      ap-northeast-2c:
        id: "PUBILC_SUBNET_ID"
    private:
      ap-northeast-2a:
        id: "PRIVEATE_SUBNET_ID"
      ap-northeast-2b:
        id: "PRIVEATE_SUBNET_ID"
      ap-northeast-2c:
        id: "PRIVEATE_SUBNET_ID"

nodeGroups: # 노드 그룹 생성
  - name: ${NG_NAME}
    iam: # iam 옵션을 지정해주지 않으면 노드에 아무 권한이 없음
      withAddonPolicies:
        imageBuilder: true
        autoScaler: true
        externalDNS: true
        certManager: true
        appMesh: true
        appMeshPreview: true
        ebs: true
        awsLoadBalancerController: true
        xRay: true
        cloudWatch: true
    amiFamily: AmazonLinux2
    availabilityZones: [ # 가용가능한 Zone 설정 Cluster의 AZ와 같게 설정
      "ap-northeast-2a",
      "ap-northeast-2b",
      "ap-northeast-2c"
    ]
    privateNetworking: false
    minSize: 3
    maxSize: 5
    desiredCapacity: 3
    volumeSize: 30 
    volumeType: gp2
    instancesDistribution: 
      maxPrice: 0.10
      instanceTypes:
      	- c5.xlarge
        - m6g.xlarge
        - m6gd.xlarge
      onDemandBaseCapacity: 0
      onDemandPercentageAboveBaseCapacity: 20 # all the instances will be Spot Instances = 0
      spotAllocationStrategy: capacity-optimized

조금 자세하게 다룰 부분은 아래 부분이라고 생각합니다.

    instancesDistribution: 
      maxPrice: 0.10
      instanceTypes:
      	- c5.xlarge
        - m6g.xlarge
        - m6gd.xlarge
      onDemandBaseCapacity: 0
      onDemandPercentageAboveBaseCapacity: 20 # all the instances will be Spot Instances = 0
      spotAllocationStrategy: capacity-optimized

maxPrice : 인스턴스의 최대 가격

옵션을 사용해서 스팟 인스턴스 타입의 최근 3개월 가격(0.64~0.7) 보다 높은가격으로 설정해서

가격변동으로 종료될 변수를 줄였습니다. → 안정성 확보

instanceTypes : 인스턴스 타입 설정

기존 웹 콘솔에서와는 동일한 스펙의 여러 인스턴스를 리스트로 선언해서 가용가능한 인스턴스가 부족할 경우

2순위, 3순위 인스턴스를 찾게 됩니다.

onDemandBaseCapacity : 온디멘드 인스턴스의 갯수

onDemandPercentageAboveBaseCapacity : 온디멘드 인스턴스 비율

옵션으로 on-demand 인스턴스를 섞어서 사용할 수도 있습니다. * (전부 Spot으로 사용할 시 둘다 0으로 설정)

spotAllocationStrategy : Spot 정책

클러스터에서 Spot 중단 수를 줄이기 위해 가장 많은 가용 용량으로 Spot Instance Pool에서 Instance를 시작하는 spotAllocationStrategy로 capacity-optimized를 지정했습니다. → 가장 안정성 높은 정책

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-fleet-allocation-strategy.html


IaC 활용법

추가적으로 Spot Blueprints라는 기능을 활용해 Cloud Formation이나 Terraform 코드로 템플릿을 쉽게 생성 할 수 있습니다. (추후 테스트 예정)

 
 

IAM Role이나 VPC 등을 설정 할 수 있고 템플릿 받은 후에 추가적인 수정을 하면 좀더 손쉽게 IaC를 이용한

Spot Instance 활용 가능할 것 같습니다.


addons 설정

eksctl을 좀더 테라폼 처럼 활용해보고 싶어 addon을 추가해보았습니다.

결과부터 말씀드리면 생각보다 엄청 단순하게 생성할 수 있었다.

eksctl을 사용해서 만들면 iam, policy 등을 생성할 필요가 없고 얘네가 자동으로 생성하고 attach도 시켜줘서 간편합니다.

( 노드그룹에 권한이 있어서 인지? )

iam:
  withOIDC: true

addons:
  - name: vpc-cni
    # all below properties are optional
    version: v1.15.1-eksbuild.1

  - name: coredns
    version: v1.10.1-eksbuild.4
  - name: kube-proxy
    version: v1.28.2-eksbuild.2
  - name: aws-ebs-csi-driver
    version: v1.26.1-eksbuild.1

 

위의 코드만 추가해주어도 addon이 생성되면서 aws-ebs-csi-driver 같은 경우에는 Role도 자동으로 생성해주고 addon에

attach도 자동으로 해줘서 간편합니다.

기타 유의사항

추가적으로 테스트 과정에서 생겼던 몇가지 이슈에 대해 말씀드리겠습니다.

  • 스팟 인스턴스를 처음에 검색할 당시 사용 가능 리전에 대한 정보만으로 인스턴스 리스트를 작성했는데 AZ 별로 구분 됨
    • Cluster가 설정된 AZ에 가용 인스턴스가 없으면 노드그룹 생성 안됨
# 가용 가능 AZ 확인 방법
❯ aws ec2 describe-instance-type-offerings --location-type availability-zone \
 --filters Name=instance-type,Values=c5.xlarge --region ap-northeast-2 --output table
------------------------------------------------------------
|               DescribeInstanceTypeOfferings              |
+----------------------------------------------------------+
||                  InstanceTypeOfferings                 ||
|+--------------+-------------------+---------------------+|
|| InstanceType |     Location      |    LocationType     ||
|+--------------+-------------------+---------------------+|
||  c5.xlarge   |  ap-northeast-2a  |  availability-zone  ||
||  c5.xlarge   |  ap-northeast-2c  |  availability-zone  ||
||  c5.xlarge   |  ap-northeast-2b  |  availability-zone  ||
||  c5.xlarge   |  ap-northeast-2d  |  availability-zone  ||
|+--------------+-------------------+---------------------+|
(END)

❯ aws ec2 describe-instance-type-offerings --location-type availability-zone \
 --filters Name=instance-type,Values=c4.8xlarge --region ap-northeast-2 --output table
 ------------------------------------------------------------
|               DescribeInstanceTypeOfferings              |
+----------------------------------------------------------+
||                  InstanceTypeOfferings                 ||
|+--------------+-------------------+---------------------+|
|| InstanceType |     Location      |    LocationType     ||
|+--------------+-------------------+---------------------+|
||  c4.8xlarge  |  ap-northeast-2a  |  availability-zone  || # a,c 만 가능
||  c4.8xlarge  |  ap-northeast-2c  |  availability-zone  || 
|+--------------+-------------------+---------------------+|
(END)

  • eksctl로 클러스터를 생성할 때 생성 실패시 stack이 남아서 같은 이름으로 생성 불가
    • 버그로 판명됐는데 아직 고쳐지지 않았다고 합니다.
    • 그나마 대처 가능한 방법으로 스택 삭제하는 코드입니다.
    • aws --region ap-northeast-2 cloudformation delete-stack --stack-name eksctl-${CLUSTER_NAME}-cluster

- 추가로 스택에 의한 문제는 콘솔에서 스택을 삭제하거나 실행 시작했던 eks의 cluster name을 delete해주면 스택이 삭제되며 정상작동됩니다. 

- 생성 시 eksctl create cluster --dry-run 명령어로 확인해보는 것을 권장.


요약

  • Eks를 사용할 때 1/3 가격정도로 테스트 가능
  • eksctl nodegroup을 활용해서 웹 콘솔보다 조금 안정적으로 Spot 인스턴스를 활용 가능합니다.
  • 인스턴스 가격과 리스트를 넓게 조정해서 안정성을 확보.
  • 하지만 AZ에 인스턴스가 부족하면 인스턴스가 변경되는 경우가 있기 때문에 테스트나 개발 환경으로만 사용하는 것이 바람직해 보입니다.
반응형