참여 소감
현재 자바, 파이썬 애플리케이션을 SCP(Samsung Cloud Platform)의 Kubernetes 환경으로 마이그레이션 업무를 하면서 Kubernetes를 다룰 수 있다는 것에 대체로 만족하고 있지만, 마이그레이션 업무 특성상 생각보다 Kubernetes를 깊게 다뤄보기는 어려웠습니다.(이미 구축된 클러스터/네임스페이스에 워크로드만 구성하기 때문에...) CKA 자격증을 준비할 때 VirtualBox에 개인적으로 K8S Cluster를 구축해보긴 했지만.. AWS와 같은 클라우드 환경에서 K8S를 제대로 다뤄보고 싶다는 마음이 항상 있었고 이번 스터디를 통해 차근차근 배워나가고자 합니다.
아쉽게도 개인 일정이 있어 1주차 스터디는 실시간으로 참여할 수는 없었습니다. 영상을 녹화해서 올려주신 가시다님과 스터디를 도와주시는 분들께 감사드리면서 블로깅 시작해보겠습니다.
EKS 구성도
EKS와 일반적인 Kubernetes 와의 차이점
- EKS는 AWS에서 관리해주는 AWS Managed VPC 내에 Controlplane이 존재하고 EKS 사용자(고객)의 VPC에 DataPlane(워커노드) 가 존재합니다.
- EKS는 Kubernetes의 ControlPlane 리소스인 API 서버, Controller, Scheduler, etcd 등을 관리해줍니다.
- EKS onwned ENI 존재
- 사용자의 VPC 내에 자체적으로 관리되는 Elastic Network Interface(ENI)를 가지고 있습니다.
- DataPlane와 VPC 사이의 네트워크 트래픽을 처리하며, EKS 클러스터의 ControlPlane과 DataPlane 간의 통신에 사용
- DataPlane에 사용자(고객)의 파드가 배포됩니다.
EKS DataPlane 구성 타입
- Managed node groups(관리형 노드 그룹)
- AWS에서 관리하는 EC2 인스턴스 그룹으로, 최신 EKS Optimized AMI를 사용하며, AWS에서 AMI 관리와 Capacity(On-Demand, Spot)를 자동으로 처리
- 이 방법을 사용하면 EC2 인스턴스 관리를 간편하게 할 수 있으며, 높은 확장성과 안정성을 제공
- Self-managed nodes(자체 관리 노드)
- Custom AMI를 사용하며, Auto Scaling Group(ASG)을 직접 관리하여 DataPlane을 구성
- OS 기본 구성과 패치 역시 고객이 직접 관리 -> 더 많은 제어권, 유연성을 가질 수 있지만, 관리적인 부담 증가
- AWS Fargate(서버리스)
- AWS Fargate 환경에서 제공하는 Micro VM을 이용하여 Pod 단위로 VM을 할당
- EC2 인스턴스를 직접 관리할 필요 없이, 컨테이너 실행 환경만 구성하면 되므로 높은 간편성을 제공
- firecracker/design.md at main · firecracker-microvm/firecracker · GitHub
EKS Cluster Endpoint
1) Public
실제 통신이 되는 과정
- API 서버 → (EKS owned ENI) → 워커노드의 Kubelet
- 워커노드의 kube-proxy→ (퍼블릭 도메인) → API Server
- 사용자(Local PC)의 kubectl → (퍼블릭 도메인) → API Server
2) Public, Private
실제 통신이 되는 과정
- API 서버 → (EKS owned ENI) → 워커노드의 Kubelet
- 워커노드의 kube-proxy→ (ENI의 Private hosted domain) → API Server
- 사용자(Local PC)의 kubectl → (퍼블릭 도메인) → API Server
3) Private -> 실제 현업에서 사용하는 방식
실제 통신이 되는 과정
- API 서버 → (EKS owned ENI) → 워커노드의 Kubelet
- 워커노드의 kube-proxy→ (ENI의 Private hosted domain) → API Server
- 사용자(Local PC)의 kubectl → (ENI의 Private hosted domain) → API Server
실습 구성도
실습
1. CloudFormation 배포
2. Bastion Host(작업용 EC2) SSH 접속 및 배포 확인
3. AWS IAM 자격 증명
- 작업용 EC2(Bastion Host)가 eksctl로 EKS Control Plane을 설치하고 워커노드를 배포해야하기 때문에 권한이 필요합니다. 이번 실습에서는 Administrator 권한을 가진 IAM user를 통해 자격증명을 진행하였습니다.
4. 환경 변수 설정
EKS 클러스터를 콘솔에서 배포하는 것 보다는 aws cli를 사용하기 위해 사전에 변수부터 설정해줍니다.
# EKS 배포할 VPC 정보를 변수로 설정
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
## 퍼블릭 서브넷 ID를 변수로 설정
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
5. EKS 클러스터 생성
# eks 클러스터 & 관리형노드그룹 배포 전 정보 확인(실제 배포 X)
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-04a877b4ab4b9ed72
manageSharedNodeSecurityGroupRules: true
nat:
gateway: Disable
subnets:
public:
ap-northeast-2a:
az: ap-northeast-2a
cidr: 192.168.1.0/24
id: subnet-0e8f88439746d30a8
ap-northeast-2c:
az: ap-northeast-2c
cidr: 192.168.2.0/24
id: subnet-0387669667f0cc26f
우선 배포전 dry run을 통해 테스트로 명령어를 수행하고 파이프라인으로 yh를 사용하면 보기 좋게 yaml 형식으로 출력하여 배포가 어떻게 이루어질 것인지 확인 가능합니다.
# 실제 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 --verbose 4
# 배포 모니터링 명령어
$ watch -n 1 "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"
6. 워커노드 SSH 접속
Bastion Host -> 워커노드를 접근하기 위해서는 반드시 Security Group 설정을 해줘야합니다.
# Security Group ID값을 변수로 설정
$ NGSGID=$(aws ec2 describe-security-groups --filters Name=group-name,Values=*nodegroup* --query "SecurityGroups[*].[GroupId]" --output text)
$ echo $NGSGID
# 노드 보안그룹에 bastion-host 에서 워커노드(파드)에 접속 가능하게 룰(Rule) 추가 설정(워커노드의 inbound 정책 추가)
$ aws ec2 authorize-security-group-ingress --group-id $NGSGID --protocol '-1' --cidr 192.168.1.100/32
# 워커 노드 SSH 접속 확인
$ ssh -i ~/.ssh/id_rsa ec2-user@$N1 hostname
$ ssh -i ~/.ssh/id_rsa ec2-user@$N2 hostname
7. Kubectl exec 명령어 수행했을 때 네트워크 통신 과정 이해하기
$ ssh -i ~/.ssh/id_rsa ec2-user@$N2 sudo ss -tnp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
ESTAB 0 0 192.168.2.142:59450 13.124.250.129:443 users:(("kubelet",pid=2842,fd=39))
ESTAB 0 0 192.168.2.142:52026 13.124.128.132:443 users:(("kube-proxy",pid=3092,fd=11))
# kube-proxy와 kubelet이 API 서버의 퍼블릭 엔드포인트 IP로 통신하는 것 확인
$ nslookup CDF8079FECDC2D94BC67B74994915637.gr7.ap-northeast-2.eks.amazonaws.com
Server: 192.168.0.2
Address: 192.168.0.2#53
Non-authoritative answer:
Name: CDF8079FECDC2D94BC67B74994915637.gr7.ap-northeast-2.eks.amazonaws.com
Address: 13.124.250.129
Name: CDF8079FECDC2D94BC67B74994915637.gr7.ap-northeast-2.eks.amazonaws.com
Address: 13.124.128.132
8. Deployment , Service 배포
# YAML 파일 다운로드
$ curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/1/mario.yaml
# 워크로드 배포
$ kubectl apply -f mario.yaml -n default
9. 관리형 노드 Scale out
# 옵션 [터미널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
# eks 노드 그룹 정보 확인
eksctl get nodegroup --cluster $CLUSTER_NAME --name $CLUSTER_NAME-nodegroup
# 노드 2개 → 3개 증가
eksctl scale nodegroup --cluster $CLUSTER_NAME --name $CLUSTER_NAME-nodegroup --nodes 3 --nodes-min 3 --nodes-max 6
# 노드 확인
kubectl get nodes -o wide
kubectl get nodes -l eks.amazonaws.com/nodegroup=$CLUSTER_NAME-nodegroup
# 노드 3개 → 2개 감소 : 적용까지 시간이 소요됨
aws eks update-nodegroup-config --cluster-name $CLUSTER_NAME --nodegroup-name $CLUSTER_NAME-nodegroup --scaling-config minSize=2,maxSize=2,desiredSize=2
10. 클러스터 및 리소스 제거
# EKS 클러스터 제거
$ eksctl delete cluster --name $CLUSTER_NAME
# AWS CloudFormation Stack 제거
$ aws cloudformation delete-stack --stack-name myeks
마지막으로 AWS에 돈을 계속 갖다 바칠 수는 없기 때문에 반드시 생성했던 리소스를 정리해줘야합니다. CloudFormation Stack을 제거하기 전에 우선 EKS 클러스터를 제거해야 합니다. 이번 실습을 마치고 EKS Cluster가 완전히 제거된 것을 확인하고 AWS CLI를 통해 CloudFormation Stack을 제거해주었습니다.
1주차 후기
1주차를 통해 EKS를 처음 접해보면서 EKS 클러스터가 어떻게 구성되는지, kubectl 명령어 수행 시 네트워크상으로 어떻게 통신이 이루어지는지 알 수 있어 매우 유익했던 시간이었습니다. 이번에 알게된 내용을 바탕으로 업무에 사용하는 SCP 의 Kubernetes 클러스터는 어떻게 구성되어있는지 다시 한 번 살펴봐야겠다고 느껴집니다. 스터디를 준비해주신 모든 분께 감사드립니다. 😊
'AWES[1기](Amzaon EKS Study)' 카테고리의 다른 글
[AWES] 6주차 - EKS Security (0) | 2023.06.01 |
---|---|
[AWES] 5주차 - EKS Autoscaling (0) | 2023.05.25 |
[AWES] 4주차 - EKS Observability (0) | 2023.05.18 |
[AWES] 3주차 - EKS Storage & Node 관리 (0) | 2023.05.10 |
[AWES] 2주차 - EKS Networking (0) | 2023.05.03 |