1주차 - 2. EKS 배포

bocopile·2025년 2월 8일

AEWS 3기 스터디 

목록 보기
2/18
post-thumbnail

지난 포스팅에서는 EKS가 무엇인지, EKS 아키텍처는 어떻게 구성되어 있는지 정리하였습니다.

이번 포스팅에서는 EKS를 직접 배포해보고, 제대로 배포하였는지 검사, 마지막으론 Deployment, Service를 통한 배포를 진행하도록 하겠습니다.

EKS 배포 방식

EKS를 배포하는 방식은 크게 3가지 방법이 있습니다.
1. AWS Console, CLI 배포 방법
2. eksctl 배포
3. Iac 배포 방식

1. AWS Console 배포

가장 기본적인 배포 방법으로 AWS Console은 말 그대로 웹 관리 콘솔을 접근해서 배포하는 방식입니다.

2. eksctl 배포

eksctl는 EKS 클러스터 구축 및 관리를 하기 위해 명령줄 도구로 오픈소스 입니다.
eksctl 명령어

3. IaC 도구

코드형 인프라 (Infreastructure as Code, IaC)는 코드를 통해 인프라를 관리하고 프로비저닝을 하는것을 의미합니다.
대표적으로 Ansible, Terraform, CloudFormation 등이 있습니다.!

기본 인프라 구성

1. 사전 준비

본격적으로 EKS 세팅을 하기전에 사전에 준비할 것이 있습니다.

Resource 생성할수 있도록 Key Pairs, Access Key 생성, AWS cli 설치가 필요합니다..

1) Key Pairs 생성

  1. EC2 > Network & Security > Key Pairs 클릭
  2. name, Key pair type, file format 선택 후 ‘Create key Pair’ 클릭
  • name : key pairs 명칭
  • key pair type : RSA
  • Private key file format : pem

2) Access Key 생성

aws cli 명령어를 이용하기 위해선 Access key 생성이 필요합니다.
1. IAM > User > ‘해당 아이디’ 접근

2. 하단 Access Keys 탭에서 ‘Create Access Key’ 버튼 클릭

3. Command Line Interface (CLI) 선택 > 'next' 버튼 클릭

4. 태그명 입력후 'create access key' 버튼 클릭

5.‘Download .csv file’ 클릭하여 csv 파일 다운로드

  • 이때 Secret access key는 다른 사람에게 노출 하지 않도록 주의 하여 관리 필요

3) AWS CLI 설치

AWS 관련 명령어를 사용하기 위해선 AWS CLI 설치가 필요합니다.

  • 링크 : AWS CLI 설치
  • 자신이 사용하는 OS를 클릭한 후 가이드대로 설치 진행

4) IAM User 자격 증명 설정 설정

  • Stack, EKS 생성을 위해 인증이 필요합니다.
  • 다운로드 받았던 Access Key 파일을 열어 Access Key ID, Secret Access Key 확인 후 입력
aws configure

# 해당 명령어를 입력하면 다음과 같이 뜬다.
## 다운로드 받았던 access key 파일을 열어 Access Key, Secret Acess Key를 입력한다.
AWS Access Key ID:
AWS Secret Access Key :
# region : ap-northeast-2 입력(서울)
Default region name: ap-northeast-2
# output Type : json을 입력
Default output format : json

2. 인프라 배포

1) 기본 구성

2) Stack 배포

EKS 배포 전 우선 Stack 생성이 필요합니다.
Stack 은 CloudFormation을 통해 리소스를 효율적으로 관리하는 단위로, 자동화와 일관성을 제공하여 인프라 관리의 복잡성을 줄여줍니다.

  • Stack 생성
# 클라우드넷팀에서 미리 만든 yaml 파일
# 테스트 목적으로 생성 된 것이므로 주의 필요
curl -O https://s3.ap-northeast-2.amazonaws.com/cloudformation.cloudneta.net/K8S/myeks-1week.yaml

# 배포
# aws cloudformation deploy --template-file ~/Downloads/myeks-1week.yaml --stack-name mykops --parameter-overrides KeyName=<My SSH Keyname> SgIngressSshCidr=<My Home Public IP Address>/32 --region <리전>
## KeyName : 생성 했던 Key Pair Name
## sSshCidr : eksctl 작업을 수행할 EC2 인스턴스를 접속할 수 있는 IP 주소 ( 집 공인 IP/32)
aws cloudformation deploy --template-file ~/aeks/myeks-1week.yaml \
     --stack-name myeks --paramete![](https://velog.velcdn.com/images/gjrjr4545/post/23ca4c84-98e3-4aa9-9723-3b779f63c7e0/image.png)
r-overrides KeyName=bocopile-eks sSshCidr=$(curl -s ipinfo.io/ip)/32 --region ap-northeast-2

해당 명령어를 이용하면 다음과 같이 생성 됩니다.

또한 AWS Console에서도 myeks가 생성된것을 확인할수 있습니다.

Stacks 가 생성 되었다면 EC2 IP를 확인하여 접속해봅시다.

# CloudFormation 스택 배포 완료 후 EC2 IP 출력
aws cloudformation describe-stacks --stack-name myeks --query 'Stacks[*].Outputs[*].OutputValue' --output text
43.201.47.222

# ec2 에 SSH 접속 : root / qwe123
ssh root@43.201.47.222

접속이 되었다면 여러가지를 확인해야 합니다.

3) 기본 정보 확인

# 사용자 확인
whoami

# 기본 툴 및 SSH 키 설치 등 확인
kubectl version --client=true -o yaml
eksctl version
aws --version
ls /root/.ssh/id_rsa*

# 도커 엔진 설치 확인
docker info
  • 기본 툴 및 SSH 키 확인
  • 도커 엔진 설치 확인

4) IAM User 자격 증명 설정 및 VPC 확인 / 변수 지정

기본 정보가 확인이 완료되었다면 IAM 자격증명 설정 및 VPC 확인 및 변수 지정이 필요합니다.

# User 자격 구성 설정 여부 확인
aws ec2 describe-instances

해당 명령어를 입력하면 IAM 자격증명이 안되어서 아래 화면처럼 인증이 필요하단 메세지가 발생합니다.

aws configure 명령어를 이용하여 IAM User 자격 구성이 필요합니다.

해당 정보를 입력한 후에 IAM 자격 구성 설정 여부를 확인하면 아래 첨부된 이미지 처럼 나오면 설정이 완료된것입니다.

5) VPC 확인 및 변수 지정

EKS를 배포하기 위해선 VPC를 변수로 지정해줘야 합니다.

  • VPC 정보 확인
# EKS 배포할 VPC 정보 확인
aws ec2 describe-vpcs --filters "Name=tag:Name,Values=$CLUSTER_NAME-VPC" | jq

위와 같이 조회가 가능하다면 변수로 지정해준 뒤에 변수가 조회 되는지 확인을 합니다.


export VPCID=$(aws ec2 describe-vpcs --filters "Name=tag:Name,Values=$CLUSTER_NAME-VPC" | jq -r .Vpcs[].VpcId)
echo "export VPCID=$VPCID" >> /etc/profile
echo $VPCID

6) Public Subnet ID 변수 지정

VPC 변수 지정이 완료되었다면 Public Subnet ID를 변수로 지정해야 합니다.

우선 VPC에 속한 Subnet 정보부터 확인해봅니다.

# EKS 배포할 VPC에 속한 Subnet 정보 확인
aws ec2 describe-subnets --filters "Name=vpc-id,Values=$VPCID" --output json | jq
aws ec2 describe-subnets --filters "Name=vpc-id,Values=$VPCID" --output yaml

Subnet 조회가 된다면 public Subnet ID #1,#2를 변수로 지정해야 합니다.

## 퍼블릭 서브넷 ID 확인
aws ec2 describe-subnets --filters Name=tag:Name,Values="$CLUSTER_NAME-PublicSubnet1" | jq
aws ec2 describe-subnets --filters Name=tag:Name,Values="$CLUSTER_NAME-PublicSubnet1" --query "Subnets[0].[SubnetId]" --output text
export PubSubnet1=$(aws ec2 describe-subnets --filters Name=tag:Name,Values="$CLUSTER_NAME-PublicSubnet1" --query "Subnets[0].[SubnetId]" --output text)
export PubSubnet2=$(aws ec2 describe-subnets --filters Name=tag:Name,Values="$CLUSTER_NAME-PublicSubnet2" --query "Subnets[0].[SubnetId]" --output text)
echo "export PubSubnet1=$PubSubnet1" >> /etc/profile
echo "export PubSubnet2=$PubSubnet2" >> /etc/profile
echo $PubSubnet1
echo $PubSubnet2

7) EKS Add-on 정보 확인

마지막으로 EKS Add-on이 kubernetes 버전 별로 조회가 되는지 확인합니다.

# EKS Addon 정보 확인
aws eks describe-addon-versions --kubernetes-version 1.32  --query 'addons[].{MarketplaceProductUrl: marketplaceInformation.productUrl, Name: addonName, Owner: owner Publisher: publisher, Type: type}' --output table
aws eks describe-addon-versions --kubernetes-version 1.31  --query 'addons[].{MarketplaceProductUrl: marketplaceInformation.productUrl, Name: addonName, Owner: owner Publisher: publisher, Type: type}' --output table


## wc -l 로 갯수 비교
aws eks describe-addon-versions --kubernetes-version 1.32  --query 'addons[].{MarketplaceProductUrl: marketplaceInformation.productUrl, Name: addonName, Owner: owner Publisher: publisher, Type: type}' --output text | wc -l
aws eks describe-addon-versions --kubernetes-version 1.31  --query 'addons[].{MarketplaceProductUrl: marketplaceInformation.productUrl, Name: addonName, Owner: owner Publisher: publisher, Type: type}' --output text | wc -l


조회가 가능하다면 다음 절차를 진행하면 됩니다.
단 최신버전인 경우 설치할수 있는 Add-on 갯수가 적으므로 이전버전을 설치할 것을 권장한다.

# EKS Add-on 별 전체 버전 정보 확인
ADDON=<add-on 이름>
ADDON=vpc-cni

# 아래는 vpc-cni 전체 버전 정보와 기본 설치 버전(True) 정보 확인
aws eks describe-addon-versions \
    --addon-name $ADDON \
    --kubernetes-version 1.31 \
    --query "addons[].addonVersions[].[addonVersion, compatibilities[].defaultVersion]" \
    --output text

# EKS 애드온의 버전별로 호환되는 EKS 버전을 확인하는 스크립트 https://malwareanalysis.tistory.com/760
ADDON_NAME=aws-ebs-csi-driver
aws eks describe-addon-versions --addon-name $ADDON_NAME | jq -r '
  .addons[] |
  .addonVersions[] |
  select(.architecture[] | index("amd64")) |
  [.addonVersion, (.compatibilities[] | .clusterVersion), (.compatibilities[] | .defaultVersion)] |
  @tsv'

8) EKS 배포

이제 본격적으로 EKS를 배포하려고 합니다.

변수 확인

먼저 아래 명령어를 이용하여 변수가 조회 되는지 확인합니다.

echo $AWS_DEFAULT_REGION
echo $CLUSTER_NAME
echo $VPCID
echo $PubSubnet1,$PubSubnet2

다음 EKS 클러스터 및 관리형 노드그룹 배포 정보를 미리 확인 합니다.

# eks 클러스터 & 관리형노드그룹 배포 전 정보 확인
eksctl create cluster --name $CLUSTER_NAME --region=$AWS_DEFAULT_REGION --nodegroup-name=$CLUSTER_NAME-nodegroup --node-type=t3.medium \
--node-volume-size=30 --vpc-public-subnets "$PubSubnet1,$PubSubnet2" --version 1.31 --ssh-access --external-dns-access --dry-run | yh

다음 EKS 클러스터와 관리형 노드그룹을 배포합시다.
배포 시간은 약 15분 정도 소요 됩니다.

# eks 클러스터 & 관리형노드그룹 배포
eksctl create cluster --name $CLUSTER_NAME --region=$AWS_DEFAULT_REGION --nodegroup-name=$CLUSTER_NAME-nodegroup --node-type=t3.medium \
--node-volume-size=30 --vpc-public-subnets "$PubSubnet1,$PubSubnet2" --version 1.31 --ssh-access --external-dns-access --verbose 4

배포가 완료되면 다음과 같은 콘솔이 나옵니다..

또한 AWS Console에서 확인 가능합니다.

  • EKS > Cluster > myeks

이러면 배포가 완료되었습니다.

배포 확인

배포가 완료되었다면 제대로 배포가 되었는지 확인이 필요합니다.

1. Control Plane 확인

1) krew 플러그인 확인

kubectl krew list

2) ctx 확인

kubectl ctx

3) namespace 확인

kubectl ns

4) cluster 정보 확인

kubectl cluster-info

**eksctl get cluster**

aws eks describe-cluster --name $CLUSTER_NAME | jq
aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint

5) eks API 조회

  • 메인 조회
    • 권한 이슈로 인한 403 Result Code return
      curl -k -s $(**aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint**)
  • version 조회
    curl -k -s $(**aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint**)/version | jq
  • 해당 정보는 외부에서도 접근이 가능합니다.

6) EKS 노드 그룹 정보 확인

aws eks describe-nodegroup --cluster-name $CLUSTER_NAME --nodegroup-name $CLUSTER_NAME-nodegroup | jq

7) 노드 정보 확인

# 노드 정보 확인 : OS와 컨테이너런타임 확인
kubectl get node --label-columns=node.kubernetes.io/instance-type,eks.amazonaws.com/capacityType,topology.kubernetes.io/zone
kubectl get node --label-columns=node.kubernetes.io/instance-type**
kubectl get node -o wide

8) CapacityType 확인

  • 해당 리소스가 라우드 서비스의 인스턴스, 컨테이너, 또는 기타 컴퓨팅 자원)가 필요할 때만 할당되고, 사용한 만큼만 비용을 지불하는 방식을 나타낸다.
  • CapacityType가 CapacityType이면?
    - 사전 예약 없이 필요할 때 즉시 리소스를 생성하고 사용할 수 있음.
    - 사용한 시간(또는 분, 초) 단위로 비용을 지불함.
    # 노드의 capacityType 확인
    kubectl get node --label-columns=eks.amazonaws.com/capacityType

9) 인증 정보 확인

kubectl get node -v=6

aws eks get-token --cluster-name $CLUSTER_NAME --region $AWS_DEFAULT_REGION

10) 파드 정보 확인

kubectl get pod -n kube-system -o wide

11) 컨테이너 이미지 확인

클러스터에 존재하는 모든 파드에 대해서 어떤 이미지를 사용하고 있는지를 확인합니다.

kubectl get pods --all-namespaces -o jsonpath="{.items[*].spec.containers[*].image}" | tr -s '[[:space:]]' '\n' | sort | uniq -c

2. Data Plane 확인

Control Plane 제대로 배포 되었는지 확인이 완료되었습니다.
이제 Data Plane를 확인할 차례입니다.

1) 노드 접속 확인

  • 노드 별 IP 확인

    aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,PrivateIPAdd:PrivateIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output table

  • Private IP 변수 지정
    Node별 Private IP 확인이 완료되었다면 변수 선언을 진행 합니다.

    N1=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2a -o jsonpath={.items[0].status.addresses[0].address})
    N2=$(kubectl get node --label-columns=topology.kubernetes.io/zone --selector=topology.kubernetes.io/zone=ap-northeast-2c -o jsonpath={.items[0].status.addresses[0].address})
    echo $N1, $N2
    echo "export N1=$N1" >> /etc/profile
    echo "export N2=$N2" >> /etc/profile

  • ping 테스트
    eksctl-host 에서 Node IP나, coreDNS 파드 IP로 통신이 가능한지 확인을 합니다.

    ping -c 1 $N1
    ping -c 1 $N2

    확인한 결과 Data Plane 전부 통신이 안됩니다.
    그렇다면 노드 보안 그룹 추가가 필요합니다.

  • 보안 그룹 ID 확인
aws ec2 describe-security-groups --filters Name=group-name,Values=*nodegroup* --query "SecurityGroups[*].[GroupId]" --output text
NGSGID=$(aws ec2 describe-security-groups --filters Name=group-name,Values=*nodegroup* --query "SecurityGroups[*].[GroupId]" --output text)
echo $NGSGID
echo "export NGSGID=$NGSGID" >> /etc/profile

  • 보안 그룹 ID 등록
aws ec2 authorize-security-group-ingress --group-id $NGSGID --protocol '-1' --cidr 192.168.1.100/32

  • 보안 그룹 등록후 ping 테스트
    다시 eksctl-host 에서 Node IP나, coreDNS 파드 IP로 통신이 가능한지 확인을 합니다.
    ping -c 1 $N1
     ping -c 1 $N2

    확인한 결과 통신이 되는것이 확인하였습니다.
  • Data Plane 접속 확인
    마지막으로 각 워커 노드에 접속이 가능한지 확인을 합니다.
    ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no ec2-user@$N1 hostname
    ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no ec2-user@$N2 hostname
    ssh ec2-user@$N1
    ssh ec2-user@$N2

2) 노드 네트워크 확인

다음 노드간의 네트워크가 연결이 제대로 되었는지 확인을 합니다.

  • AWS VPC CNI 사용 확인
kubectl -n kube-system get ds aws-node
kubectl describe daemonset aws-node --namespace kube-system | grep Image | cut -d "/" -f 2
kubecolor describe pod -n kube-system -l k8s-app=aws-node

  • 파드 IP 확인
  kubectl get pod -n kube-system -o wide
  kubectl get pod -n kube-system -l k8s-app=kube-dns -o wide

  • 노드 정보 확인
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i **hostname**; echo; done
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i **sudo ip -c addr**; echo; done
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i **sudo ip -c route**; echo; done
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i **sudo iptables -t nat -S**; echo; done

3) 노드 스토리지 정보 확인

다음은 노드 스토리지 정보를 확인해야 한다.

for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i **lsblk**; echo; done
for i in $N1 $N2; do echo ">> node $i <<"; ssh ec2-user@$i **df -hT /**; echo; done

테스트 서비스 배포

Control Plane, Data Plane 까지 확인이 완료되었습니다.
마지막으로 샘플 서비스를 띄워 배포를 진행 하도록 하겠습니다.
오늘 서비스로 배포 할것은 슈퍼마리오 입니다.

# mario.yaml
cat <<EOT > mario.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mario
  labels:
    app: mario
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mario
  template:
    metadata:
      labels:
        app: mario
    spec:
      containers:
      - name: mario
        image: pengbai/docker-supermario
---
apiVersion: v1
kind: Service
metadata:
   name: mario
spec:
  selector:
    app: mario
  ports:
  - port: 80
    protocol: TCP
    targetPort: 8080
  type: LoadBalancer
EOT

#  mario deployment, service 배포
kubectl apply -f mario.yaml

마리오 배포가 완료되었으면 deployment, service가 제대로 배포 되었는지 확인이 필요합니다.

# 배포 확인 : CLB 배포 확인
kubectl get deploy,svc,ep mario

배포가 완료되었다면 사이트를 접근하여 제대로 동작하는지 확인이 필요합니다.

# 마리오 게임 접속 : CLB 주소로 웹 접속
kubectl get svc mario -o jsonpath={.status.loadBalancer.ingress[0].hostname} | awk '{ print "Maria URL = http://"$1 }'

Resource 삭제

AWS는 리소스가 사용됨에 따라서 과금이 발생합니다.
테스트가 완료되었다면 삭제하여 불필요한 과금이 발생하지 않도록 주의 합니다.

# Amazon EKS 클러스터 삭제 
eksctl delete cluster --name $CLUSTER_NAME
# AWS CloudFormation 스택 삭제
aws cloudformation delete-stack --stack-name myeks

참조

  • 인프라 기본 구성 : AEWS 3기 스터디
profile
DevOps Engineer

0개의 댓글