본문 바로가기
프로젝트&&스터디/AWES 3기 (2025.01~)

[AEWS 3기] eksctl을 활용해 yaml로 EKS Cluster 생성하기

by james_janghun 2025. 2. 9.
이 포스팅은 가시다(gasida)님이 진행하는 AEWS(Amazon EKS Workshop Study) 3기에서 학습한 내용을 정리하고 제가 스스로 공부한 내용을 기록하고자 하는 포스팅입니다.

 

이번 1주차 주차는 EKS 클러스터 생성 및 구성 방법에 대한 내용입니다.

EKS는 AWS에서 제공하는 쿠버네티스 서비스입니다. 따라서 기본적인 쿠버네티스 구성과 동일합니다.

쿠버네티스 구조

쿠버네티스의 아키텍처는 다음과 같습니다.

https://kubernetes.io/docs/concepts/architecture/

 

기본적으로 Control Plane에서 쿠버네티스의 모든 중요 api들이 동작합니다. 여기에 Worker Node가 실제로 Pod 컨테이너들이 운영되는 공간이됩니다.

그리고 이 쿠버네티스 구조가 Cloud Provider로 넘어오게 되면서 각 클라우드 벤더사 별로 Cloud Provider API를 통해서 소통할 수 있도록 구성되어 있습니다.

 

EKS의 구조

EKS또한 위의 쿠버네티스 구조 그림과 완전히 동일한 구성을 가지고 있으나, 딱 한가지 염두할 것은 EKS는 Control plane이 AWS Managed service로 동작하게 됩니다. 따라서 api server / etcd 등 모든 control plane이 AWS Managed VPC에 존속하고, EKS public endpoint를 통해서 해당 control plane에 api 요청을 보낼 수 있다는게 큰 차이점입니다.

 

아래 그림에서 보면 사용자는 kubectl을 통해서 EKS public endpoint로 통신을 보내면 해당 요청이 AWS Managed VPC 내에 있는 api server로 들어가게 됩니다. 이 요청을 받은 api server는 EKS worker node가 가지고 있는 EKS owned ENI를 통해서 worker node의 kubelet으로 명령을 날리게 됩니다. 따라서 이러한 통신구조를 알고 있어야 네트워킹 설정에 문제가 없을 겁니다.

https://aws.github.io/aws-eks-best-practices/reliability/docs/controlplane/

 

EKS 클러스터 생성

클러스터를 생성하는 방법은 다양하게있습니다.

기본적으로 온프레미스를 사용할 경우 kubeadm, kubespray 이 2가지가 가장 유명합니다.

 

이는 우리가 온프레미스에서 만들때 다루기로 하고, 오늘은 EKS에서 주로 클러스터를 만드는 방법을 알아보겠습니다.

콘솔에서는 EKS 서비스로 들어가서 클러스터 생성 버튼을 누르고 콘솔에 맞게 여러가지 옵션을 주어 설정을 마무리하면됩니다.

 

따라서 오늘은 CLI를 통해서 만들어보도록 하겠습니다.

CLI를 통해서 클러스터를 생성하는 방법은 결국 CloudFormation 서비스에 yaml파일을 통한 생성을 하거나, eksctl을 통해서 클러스터를 생성하는 방법이 있습니다. 결국 eksctl도 cloudformation으로 생성되는 것은 동일합니다.

 

Managed node groups (관리형 노드 그룹)

사용자는 Managed node Groups 이라는 관리형 노드 그룹을 worker node로 활용합니다. 이 노드에서 활용되는 실제 인스턴스는 EC2 기반으로 운영되기 때문에 EC2 인스턴스 유형을 그대로 따라갑니다. 또한 노드 그룹이 생성되면 자동으로 EC2에서 확인할 수 있게됩니다.

 

관리형 노드 그룹으로 제공되는 옵션은 5가지 정도로 분류됩니다.

- Self-managed nodes : Custom AMI를 활용하고, OS 기본 구성이나 패치등을 모두 사용자가 관리하여 말 그대로 self 관리입니다.

- Karpenter : 클러스터, 노드 Auto Scaling 도구로 최근 정말 많이 쓰이고 있습니다. 적절한 크기 컴퓨팅 리소스를 자동으로 조절하여 워크로드의 요구사항을 적절하게 맞춰줍니다.

- EKS Auto Mode : AWS 에서 관리를 확장하는 모델로 기존 control plane을 넘어서 컴퓨팅 오토 스케일링, 네트워킹, 로드배런싱, DNS 등 모든 쿠버네티스 기능 요소를 EKS Auto Mode로 통합해 관리할 수 있습니다.

- EKS Hybrid Nodes : 온프레미스와 AWS EKS를 하나로 합쳐 클라우드와 온프레미스가 혼합된 하이브리드 형태입니다.

- AWS Fargate : 서버리스 컨테이너를 통해서 pod를 할당할 수 있습니다.

 

 

eksctl이란?

eksctl은 Kubernetes 클러스터의 자동화된 네트워크 설정, 노드 그룹 생성, IAM 역할 구성 등의 작업을 간단한 명령으로 수행할 수 있습니다. https://eksctl.io/

 

eksctl - The official CLI for Amazon EKS

The official CLI for Amazon EKS

eksctl.io

 

스터디에서 같이 실제 코드를 확인해 보았는데 해당 코드를 확인하니 더 명확하게 이해가 되었습니다.

https://github.com/eksctl-io/eksctl/blob/8064a501bd4c9c0fa2199ba358fcbd1db63e3356/pkg/cfn/manager/api.go#L93

 

eksctl/pkg/cfn/manager/api.go at 8064a501bd4c9c0fa2199ba358fcbd1db63e3356 · eksctl-io/eksctl

The official CLI for Amazon EKS. Contribute to eksctl-io/eksctl development by creating an account on GitHub.

github.com

 

잘보면 아래 NewStackCollection을 확인해보면, cloudformation을 호출하고, ec2(노드그룹을 위해), eks, iam, asg, role 등 eks를 호출하는 작업을 기본적으로 해주는 것을 볼 수 있습니다.

// NewStackCollection creates a stack manager for a single cluster
func NewStackCollection(provider api.ClusterProvider, spec *api.ClusterConfig) StackManager {
	tags := []types.Tag{
		newTag(api.ClusterNameTag, spec.Metadata.Name),
		newTag(api.OldClusterNameTag, spec.Metadata.Name),
		newTag(api.EksctlVersionTag, version.GetVersion()),
	}
	for key, value := range spec.Metadata.Tags {
		tags = append(tags, newTag(key, value))
	}
	return &StackCollection{
		spec:              spec,
		sharedTags:        tags,
		cloudformationAPI: provider.CloudFormation(),
		ec2API:            provider.EC2(),
		eksAPI:            provider.EKS(),
		iamAPI:            provider.IAM(),
		cloudTrailAPI:     provider.CloudTrail(),
		asgAPI:            provider.ASG(),
		disableRollback:   provider.CloudFormationDisableRollback(),
		roleARN:           provider.CloudFormationRoleARN(),
		region:            provider.Region(),
		waitTimeout:       provider.WaitTimeout(),
	}
}

 

이제 실제 eksctl을 통해서 클러스터를 생성해 보겠습니다.

 

eksctl 설치

mac에서는 brew로 설치할 수 있습니다.

brew install eksctl

 

나머지 리눅스에서는 아래의 명령어로 설치합니다.

https://eksctl.io/installation/에서 각 운영체제에 맞게 찾으면 됩니다.

# for ARM systems, set ARCH to: `arm64`, `armv6` or `armv7`
ARCH=amd64
PLATFORM=$(uname -s)_$ARCH

curl -sLO "https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_$PLATFORM.tar.gz"

# (Optional) Verify checksum
curl -sL "https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_checksums.txt" | grep $PLATFORM | sha256sum --check

tar -xzf eksctl_$PLATFORM.tar.gz -C /tmp && rm eksctl_$PLATFORM.tar.gz

sudo mv /tmp/eksctl /usr/local/bin

 

 

eksctl - yaml을 통한 클러스터 생성하기  (기본)

다음과 같이 yaml 하나면 eksctl로 바로 쿠버네티스 클러스터를 생성할 수 있습니다. 생성에는 약 15분정도 소요됩니다.

cat << EOF > cluster.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: test-cluster # eks 이름
  region: ap-northeast-2
  version: "1.31" # 쿠버네티스 버전

vpc:
  cidr: "10.0.0.0/16" # eks클러스터에서 사용할 VPC의 CIDR

managedNodeGroups:
  - name: node-group-a
    instanceType: t3.medium
    desiredCapacity: 2
    volumeSize: 20
    privateNetworking: true
EOF

 

클러스터 생성은 다음과같이 진행합니다.

eksctl create cluster -f cluster.yaml

vpc:
  cidr: "10.0.0.0/16" # eks클러스터에서 사용할 VPC의 CIDR

 

managedNodeGroups:
  - name: node-group-a
    instanceType: t3.medium
    desiredCapacity: 2
    volumeSize: 20
    privateNetworking: true

 

 

클러스터 삭제

클러스터 삭제시에는 다음과 같이 명령어 한줄이면 됩니다.

eksctl delete cluster -f cluster.yaml

 

eksctl - yaml로 생성하기 (기존에 있는 네트워크에 운영하기)

이제는 조금 더 심화된 내용으로 들어가봅시다.

 

아래 yaml은 보다 구체적인 설정을 지정하였습니다. 만들면서 하나씩 설명해보겠습니다.

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: test-ekscluster
  region: ap-northeast-2
  version: "1.31"
  tags:
    Environment: dev
   
vpc:
  nat:
    gateway: Single  # Options: HighlyAvailable, Disable, Single (default)
  autoAllocateIPv6: false
  clusterEndpoints:
    publicAccess: true
    privateAccess: true
  subnets:
    public:
      ap-northeast-2a:
        id: subnet-a5b812ce
      ap-northeast-2c:
        id: subnet-db081697
    private:
      ap-northeast-2b:
        id: subnet-586a0d23
      ap-northeast-2d:
        id: subnet-6443ab3b

nodeGroups:
  - name: al2
    instanceType: t3.small
    minSize: 2
    maxSize: 2
    desiredCapacity: 2
    labels:
      role: worker
    amiFamily: AmazonLinux2
    volumeSize: 25
    volumeType: gp3
    volumeEncrypted: true
    privateNetworking: true
    availabilityZones:
      - ap-northeast-2a
      - ap-northeast-2c
    ssh:
      publicKeyName: james

addons:
  - name: vpc-cni
  - name: coredns
  - name: kube-proxy

iam:
  withOIDC: true

cloudWatch:
  clusterLogging:
    enableTypes:
      - audit
      - authenticator
      - controllerManager
    logRetentionInDays: 7

 

역시 동일하게 잘 생성되었습니다.

 

사실 이는 Cloudformation에서도 자세한 내용을 확인할 수 있습니다.

특히 이 리소스와 출력정보에서 생성된 리소스와 상태를 바로 체크할 수 있어 좋습니다.

이제 각각의 내용을 살펴보겠습니다.

metadata에서는 클러스터의 기본정보를 기록합니다.

metadata:
  name: test-ekscluster
  region: ap-northeast-2
  version: "1.31"
  tags:
    Environment: dev

 

이번에는 제가 태그도 지정했는데요. 잘들어간 것을 확인할 수 있습니다.

 

vpc에서는 네트워크 설정을 하게되는데, 해당 대역을 지정하게되면 자동으로 해당 대역의 네트워크를 임의적으로 생성합니다.

vpc:
  nat:
    gateway: Single  # Options: HighlyAvailable, Disable, Single (default)
  autoAllocateIPv6: false
  clusterEndpoints:
    publicAccess: true
    privateAccess: true
  subnets:
    public:
      ap-northeast-2a:
        id: subnet-a5b812ce
      ap-northeast-2c:
        id: subnet-db081697
    private:
      ap-northeast-2b:
        id: subnet-586a0d23
      ap-northeast-2d:
        id: subnet-6443ab3b


저는 현재 네트워크 구성상 서브넷을 이렇게 가지고 있습니다. 서브넷은 최소 2개 이상을 요구했습니다.

- 퍼블릭서브넷  ap-northeast-2a (subnet-a5b812ce), ap-northeast-2c (subnet-db081697)

- 프라이빗 서브넷 ap-northeast-2b (subnet-586a0d23), ap-northeast-2d(subnet-6443ab3b)

 

뿐 만아니라 nat gateway 유형을 지정할 수 있습니다.

single이 기본으로 1개가 생성되며, HighlyAvailable(고가용성)을 선택할 경우 2개의 가용영역에 다중으로 생성합니다.

또한 disable은 당연히 nat gateway를 생성하지 않는 것입니다.

autoAllocateIPv6는 IPv6를 할당할 건지 확인합니다.

clusterEndpoints는 public, private 접근 중 어떤 것을 허용할지 정하는 옵션입니다.

실제로 생성된 내용을 확인해보면 잘 반영된걸 확인할 수 있습니다.

 

managedNodeGroups에서는 managed 되는 노드 그룹을 생성합니다. 이 노드 인스턴스에 대한 다양한 정보를 작성하게 됩니다.

nodeGroups:
  - name: al2
    instanceType: t3.small
    minSize: 2
    maxSize: 2
    desiredCapacity: 2
    labels:
      role: worker
    amiFamily: AmazonLinux2
    volumeSize: 25
    volumeType: gp3
    volumeEncrypted: true
    privateNetworking: true
    availabilityZones:
      - ap-northeast-2a
      - ap-northeast-2c
    ssh:
      publicKeyName: james

 

노드그룹은 stack을 별도로 생성하는 것을 볼 수 있습니다.

 

addon

addon도 cli로 간편하게 추가할 수 있었습니다. coredns와 kube-proxy, vpc-cni는 반드시 필요한 것으로 addon을 사용하는게 좋습니다. addon을 사용하지 않고 한다면 별도의 CNI, DNS, proxy를 가지고 있어야 합니다.

addons:
  - name: vpc-cni
  - name: coredns
  - name: kube-proxy

 

cloudwatch 로그

로그도 yaml로 지정하면 정말 쉽고 빠르게 지정할 수 있습니다. 기간도 7일(1주) 정확하네요.

cloudWatch:
  clusterLogging:
    enableTypes:
      - audit
      - authenticator
      - controllerManager
    logRetentionInDays: 7

 

EKS에서 Security Group(보안그룹)의 용도

EKS에서는 정말 많은 보안그룹을 사용합니다.

일단 가장 눈에 띄는게 네트워킹에서 존재하는 보안그룹입니다. 이는 EKS 클러스터 자체의 보안그룹입니다.

 

1. 클러스터 보안그룹

설명에도 보면 Control Plane에서 작동하는 ENI로 클러스터 전반에 대한 접근 통제 하는데 사용됩니다.

Control Plane 과 Node ENI에서 활용될 수 있으며, 처음에는 클러스터 보안그룹의 경우 ENI에 붙은 보안그룹입니다.

 

2. 추가 보안 그룹

추가 보안그룹은 설명에도 있듯 control plane과 워커 노드 그룹 사이의 통신을 위해서 존재합니다.

control plane ENI에 적용되는 보안그룹으로 초기에는 아무것도 없고 별도의 통신 허용 작업 외에는 잘 쓰이지 않습니다.

 

3. node 보안 그룹 (EKS 워커 노드 EC2에서 사용하는 보안그룹)

이는 NodeGroup 별로 생성되며, 각 노드그룹마다 가지고 있는 ENI에서 적용됩니다.  보안그룹은 벌써 자동으로 달고나오는 보안그룹이 많습니다. remote access 옵션을 켰다면 vpc 대역에서 ssh 접속 허용에 대한 규칙이 자동으로 추가됩니다. 이처럼 주로 워커노드에 직접 사용자가 접속하기 위해서 사용하는 포트로 주로 SSH 접속과 관련이 있습니다.

하지만 사용자가 직접 워커노드를 들어가는 행위는 사실 좋지 않습니다.