[aews] EKS Basics

xgro·2023년 4월 24일
1

AEWS

목록 보기
1/7

📌 Review

23년 1~2월에 진행했었던 PKOS 시리즈의 뒤를 이어 [AEWS] AWS EKS 스터디를 시작하였습니다.

EKS 도입을 위해 지속적으로 쿠버네티스와 AWS에 대해서 공부하고 있는 와중에 정말 소중한 기회를 제공해 주신 가시다님께 다시한번 감사드립니다.

이번 스터디는 워낙 대단한 분들이 많이 참여하신 것 같습니다. 특히 카카오톡 오픈채팅 방에서 자주 뵌 분들이라 혼자서 내적 친밀감이 상승하기도...

2시간의 짧은 스터디 시간이었지만 PKOS 때와는 또 다른 느낌으로 워낙 내공이 깊은 분들이 수업 중간중간 필요한 자료를 공유해주셔서 지루할 틈 없이 유익한 시간이었습니다.

이번 7주간의 여정도 열심히 참여하겠습니다.

text 쿠버네티스 고인물의 세계가 이 중간 어디쯤 있지 않을까...

🎤 Speech

1주차는 이정훈님과 김세웅님 두분께서 사용사례 발표를 진행하였습니다.

이정훈님은 현재 근무중인 회사에서 EKS를 이용하여 어떻게 인프라를 구축하고 있는지, 최근 EKS를 업그레이드 하면서 겪은 내용 등 정말 친절하고 자세하게 공유해주셨습니다.

김세웅님은 EKS 내부에 대한 자세한 설명과 배포 등 트리거 발생시 EKS 내부에서 일어나는 이벤트에 대해서 설명해주셨습니다.

인사이트를 확장하는데 큰 도움이 된 시간이었습니다. 두분 모두에게 다시 한번 감사드립니다.



📌 Summary

  • EKS를 직접 배포하고 사용해보며 동작원리 및 구성요소를 이해합니다.
  • EKS 클러스터를 Public, Private에 배치함에 따라 어떤 Flow를 통해 요청이 전달되는지 확인할 수 있습니다.



📌 Architecture

1주차 배포하고자 하는 아키텍처입니다.

kubectl을 위한 ec2를 배포하고 이어서 EKS 클러스터를 배포합니다.



📌 Study

1주차는 EKS에 대한 소개 및 배포에 중점을 두고 스터디 하였습니다.

AWS EKS Workshop에서 배포에 사용하는 테라폼 코드를 사용하지 않는 이유?
⇒ 모든 기능이 전부 활성화되서 배포되어 비용과 시간이 필요하고 오히려 복잡해서 이해에 어려움

AWS EKS Workshop에서 사용하는 Cloud9 IDE를 사용하지 않는 이유?
⇒ 최대한의 비용 절감과 SSH로 접속 후 사용해도 실습에 문제 없음

EKS 배치 시 보통 PrivateSubnet에 NAT GW를 사용하는데, 스터디 실습에서 사용하지 않는 이유?
⇒ 역시 최대한의 비용 절감을 위함

EKS 배치 시 보통 3개의 Subnet을 사용하는데, 스터디 실습에서는 2개의 Subnet을 사용하는 이유?
⇒ 복잡하지 않게 최대한 간결한 환경에서 실습 진행을 위해

EKS 버전을 v1.24 선정한 이유?
⇒ EKS 지원 add-on 및 호환되고 검증된 애플리케이션이 가장 많은 버전

👉 Step 01. Amazon EKS 소개


✅ AWS EKS 란?

Amazon EKS 는 Kubernetes를 쉽게 실행할 수 있는 관리형 서비스입니다. Amazon EKS를 사용하시면 AWS 환경에서 Kubernetes 컨트롤 플레인 또는 노드를 직접 설치, 운영 및 유지할 필요가 없습니다.

Amazon EKS는 여러 가용 영역에서 Kubernetes 컨트롤 플레인 인스턴스를 실행하여 고가용성을 보장합니다. 또한, 비정상 컨트롤 플레인 인스턴스를 자동으로 감지하고 교체하며 자동화된 버전 업그레이드 및 패치를 제공합니다.


✅ EKS Control plane

EKS 컨트롤 플레인의 아키텍처 입니다.

AWS EKS는 각각의 클러스터에 대해서 K8s 컨트롤 플레인을 실행합니다.

  • Control plane 인프라는 AWS 계정간 공유되지 않습니다.
  • 최소 2개의 API 서버 인스턴스와 3개의 ectd 인스턴스로 구성됩니다. 각각의 인스턴스는 다른 3개의 가용영역(AZ)에 배포됩니다.

  • etcd란 무엇일까요?
    • etcd는 Key-Value 형태로 데이터를 저장하는 스토리지입니다.
    • 쿠버네티스에서 ectd를 컨트롤 플레인의 컴포넌트로 채택하여 널리 사용하고 있습니다.

✅ EKS Data plane

쿠버네티스 노드입니다.

각 노드에는 다음 구성요소가 포함됩니다.

  • 컨테이너 런타임 – 컨테이너 실행을 담당하는 소프트웨어.
  • kubelet – 컨테이너가 관련 포드 내에서 정상이고 실행 중인지 확인합니다.
  • kube-proxy – 팟(Pod)과의 통신을 허용하는 네트워크 규칙을 유지합니다.

EKS의 노드는 세가지 유형으로 분류하여 사용할 수 있습니다.

  • EKS 매니지드 노드 그룹
    • EKS 클러스터용 노드의 프로비저닝 및 수명 주기 관리를 자동화합니다.
    • AWS에서 수명주기를 관리하지만, Amazon EKS 관리형 노드 그룹을 사용하는 데 드는 추가 비용은 없으며 프로비저닝한 AWS 리소스에 대해서만 비용을 지불하면 됩니다.
  • 자체 관리형 노드
  • AWS FARGATE
    • 고객은 별도의 EC2관리할 필요 없이, AWS Fargate 환경에서 제공하는 Micro VM을 이용하여 Pod 별 VM 할당하여 사용할 수 있습니다.
      • 기본 커널, CPU 리소스, 메모리 리소스 또는 탄력적 네트워크 인터페이스를 다른 포드와 공유하지 않으므로 컨테이너의 보안을 준수할 수 있습니다.
    • Fargate를 사용하면 컨테이너를 실행하기 위해 가상 머신 그룹을 직접 프로비저닝, 구성 또는 확장할 필요가 없습니다.
    • 서버 유형을 선택하거나 노드 그룹을 확장할 시기를 결정하거나 클러스터 패킹을 최적화할 필요가 없습니다.

👉 Step 02. EKS Cluster Endpoint

  • Public : 제어부 → (EKS owned ENI) 워커노드 kubelet, 워커노드 → (퍼블릭 도메인) 제어부, 사용자 kubectl → (퍼블릭 도메인) 제어부

  • EKS Cluster Endpoint - Public Private : 제어부 → (EKS owned ENI) 워커노드 kubelet, 워커노드 → (프라이빗 도메인, EKS owned ENI) 제어부, 사용자 kubectl → (퍼블릭 도메인) 제어부

  • EKS Cluster Endpoint - Private : 제어부 → (EKS owned ENI) 워커노드 kubelet, 워커노드,사용자 kubectl → (프라이빗 도메인, EKS owned ENI) 제어부


👉 Step 03. Deploy EKS

📌 파라미터 : 아래 빨간색 부분은 설정해주는어야 할 것, 그외 부분은 기본값 사용을 권장

  1. <<<<< EKSCTL MY EC2 >>>>>
    1. ClusterBaseName: EKS 클러스터의 기본 이름 (생성되는 리소스들의 주석에 접두어로 활용), EKS 클러스터 이름에 '_(밑줄)' 사용 불가!
    2. KeyName: EC2 접속에 사용하는 SSH 키페어 지정
    3. SgIngressSshCidr: eksctl 작업을 수행할 EC2 인스턴스를 접속할 수 있는 IP 주소 입력 (집 공인IP/32 입력)
    4. MyInstanceType: eksctl 작업을 수행할 EC2 인스턴스의 타입 (기본 t3.medium)
  2. <<<<< Region AZ >>>>> : 리전과 가용영역을 지정
  3. <<<<< VPC Subnet >>>>> : VPC, 서브넷 정보 지정

EC2를 굳이 배포한 이유는 모든 실습환경을 통일하기 위해 kubectl을 실행할 호스트를 AWS Cloud의 EC2에 배포하였습니다.

두가지 방법 중 하나를 선택하여 실습에 필요한 인프라를 배포합니다.

기본 인프라 배포
링크 ← AWS CloudFormation 페이지로 연결되며, 파라미터 입력 후 스택 실행

CLI를 이용하여 배포

# 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 <리전>
예시) aws cloudformation deploy --template-file ~/Downloads/myeks-1week.yaml \
     --stack-name myeks --parameter-overrides KeyName=aews SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32 --region ap-northeast-2

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

# ec2 에 SSH 접속
예시) ssh -i <My SSH Keyfile> ec2-user@3.35.137.31
ssh -i "~/.ssh/aews.pem" ec2-user@$(aws cloudformation describe-stacks --stack-name myeks --query 'Stacks[*].Outputs[0].OutputValue' --output text)

IAM User 자격 증명 설정 및 VPC 확인 및 변수를 지정합니다.

# 자격 구성 설정 없이 확인
aws ec2 describe-instances

# IAM User 자격 구성 : 실습 편리를 위해 administrator 권한을 가진 IAM User 의 자격 증명 입력
aws configure
AWS Access Key ID [None]: AKIA5...
AWS Secret Access Key [None]: CVNa2...
Default region name [None]: ap-northeast-2
Default output format [None]: json

# 자격 구성 적용 확인 : 노드 IP 확인
aws ec2 describe-instances

# EKS 배포할 VPC 정보 확인
aws ec2 describe-vpcs --filters "Name=tag:Name,Values=$CLUSTER_NAME-VPC" | jq
aws ec2 describe-vpcs --filters "Name=tag:Name,Values=$CLUSTER_NAME-VPC" | jq Vpcs[]
aws ec2 describe-vpcs --filters "Name=tag:Name,Values=$CLUSTER_NAME-VPC" | jq Vpcs[].VpcId
aws ec2 describe-vpcs --filters "Name=tag:Name,Values=$CLUSTER_NAME-VPC" | jq -r .Vpcs[].VpcId
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

# 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 | yh

# 퍼블릭 서브넷 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

kubectl을 위한 EC2가 정상적으로 배포되었고, 실습을 위한 VPC, Subnet, 보안그룹등이 준비가 되었다면 eksctl을 이용하여 배포를 수행합니다.

# 변수 확인
echo $AWS_DEFAULT_REGION
echo $CLUSTER_NAME
echo $VPCID
echo $PubSubnet1,$PubSubnet2

# 옵션 [터미널1] EC2 생성 모니터링
#while true; do 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 text ; echo "------------------------------" ; sleep 1; done
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

# 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.24 --ssh-access --external-dns-access --dry-run | yh
...
vpc:
  autoAllocateIPv6: false
  cidr: 192.168.0.0/16
  clusterEndpoints:
    privateAccess: false
    publicAccess: true
  id: vpc-0505d154771a3dfdf
  manageSharedNodeSecurityGroupRules: true
  nat:
    gateway: Disable
  subnets:
    public:
      ap-northeast-2a:
        az: ap-northeast-2a
        cidr: 192.168.1.0/24
        id: subnet-0d98bee5a7c0dfcc6
      ap-northeast-2c:
        az: ap-northeast-2c
        cidr: 192.168.2.0/24
        id: subnet-09dc49de8d899aeb7

# eks 클러스터 & 관리형노드그룹 배포: 총 16분(13분+3분) 소요 
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.24 --ssh-access --external-dns-access --verbose 4
...
023-04-23 01:32:22 []  setting current-context to admin@myeks.ap-northeast-2.eksctl.io
2023-04-23 01:32:22 []  saved kubeconfig as "/root/.kube/config"
...

✅ Assignment

EKS owned ENI 확인

아키텍처를 유심히 보면 EKS owned ENI 라고 표기된 것을 확인할 수 있습니다.

고객의 VPC에 설치되어 있는 ENI이지만 왜 이렇게 표현 하고 있을까요?

실제 구성을 한번 확인해 보겠습니다.

Step 01. 노드 정보 확인

아래 명령어를 사용하면 현재 사용중인 노드의 정보를 확인할 수 있습니다.

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


Step 02. 보안그룹 설정 및 ENI 확인을 위한 데몬셋 파드 실행

위 과정에서 N1, N2의 주소를 사용하여 데몬셋 파드를 하나 실행합니다. 실행된 데몬셋 파드를 통해 현재 파드가 통신하는 ENI의 주소를 확인할 수 있습니다.

# Node 변수 설정
N1=<PrivateIPAdd.myeks-myeks-nodegroup-Node1>
N2=<PrivateIPAdd.myeks-myeks-nodegroup-Node2>

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

# 노드 보안그룹에 eksctl-host 에서 노드(파드)에 접속 가능하게 룰(Rule) 추가 설정
aws ec2 authorize-security-group-ingress --group-id $NGSGID --protocol '-1' --cidr 192.168.1.100/32

# eksctl-host 에서 노드의IP나 coredns 파드IP로 ping 테스트
ping -c 2 $N1
ping -c 2 $N2

# kubelet, kube-proxy 통신 Peer Address는 어딘인가요?
ssh -i ~/.ssh/id_rsa ec2-user@$N1 sudo ss -tnp
ssh -i ~/.ssh/id_rsa ec2-user@$N2 sudo ss -tnp

# [터미널] aws-node 데몬셋 파드 1곳에 bash 실행해두기 
kubectl exec daemonsets/aws-node -it -n kube-system -c aws-node -- bash

# exec 실행으로 추가된 연결 정보의 Peer Address는 어딘인가요? >> AWS 네트워크 인터페이스 ENI에서 해당 IP 정보 확인
ssh -i ~/.ssh/id_rsa ec2-user@$N1 sudo ss -tnp
ssh -i ~/.ssh/id_rsa ec2-user@$N2 sudo ss -tnp


Step 03. ENI AWS CONSOLE 확인

eksctl-myeks-cluster-ControlPlane의 ENI의 상세정보를 확인하면 소유자와 요청자, 인스턴스 소유자가 다른것을 확인할 수 있습니다.



📌 Reference

  • AWS Docs - link
  • Kubernetes 운영을 위한 etcd 기본 동작 원리의 이해 - link
profile
안녕하세요! DevOps 엔지니어 이재찬입니다. 블로그에 대한 피드백은 언제나 환영합니다! 기술, 개발, 운영에 관한 다양한 주제로 함께 나누며, 더 나은 협업과 효율적인 개발 환경을 만드는 과정에 대해 인사이트를 나누고 싶습니다. 함께 여행하는 기분으로, 즐겁게 읽어주시면 감사하겠습니다! 🚀

0개의 댓글