Infra & DevOps/k8s(EKS)

[EKS] 설치 및 기본 사용

용감한 개복치 2024. 3. 10. 02:45

Amazon Eks Workshop Study 2기

가시다님께서 운영하시는 스터디를 시작하게 되었습니다.

8주 코스이며, 매주 일요일 20:00 - 22:00 ( + 30min ) 진행되는 수업에 대해 정리하여 업로드합니다.

 

1주차

EKS 설치 및 기본 사용

 

개념

- EKS 란?

EKS는 Amazon Web Services (AWS)에서 제공하는 Kubernetes 서비스로, "Elastic Kubernetes Service"의 약자

사용자가 Kubernetes 클러스터를 손쉽게 배포, 관리 및 확장할 수 있도록 도와주는 관리형 서비스

 

일반적인 Kubernetes 환경에서는 사용자가 직접 Control Plane과 Data Plane을 관리

즉, 사용자는 클러스터를 배포하고 유지 관리하고 확장하기 위해 모든 인프라 관련 작업을 직접 처리

 

출처 :  AWS

 

- EKS 의 control plane

EKS의 Control Plane은 Kubernetes의 마스터 노드 역할

Control Plane은 AWS가 관리

Control Plane은 클러스터의 상태를 관리하고, 사용자가 클러스터와 상호 작용할 때 요청을 처리하고 관리

이는 마스터 노드에 해당하며, 주요 기능으로 API 서버, 스케줄러, 컨트롤러 매니저 등이 포함

 

+)

etcd 란?

etcd 데이터베이스

이는 클러스터의 모든 상태 정보를 저장하고 관리하는 데 사용되는 분산형 키-값 저장소

 

어째서 NLB?

ALB와 NLB 둘다 가능하지만,

NLB가 선호되는데는 다음과 같은 이유가 있음

 

TCP 레벨 부하 분산: EKS Control Plane은 TCP 기반의 API를 사용하므로 NLB의 TCP 레벨 부하 분산이 더 적합. NLB는 OSI 모델의 네트워크 레이어에서 동작

고가용성 및 성능: NLB는 높은 성능과 고가용성을 제공하는데, 이는 EKS Control Plane의 API 서버에 필요한 요구 사항을 충족시키는데 유리

Network Load Balancer의 특징: NLB는 IP 주소를 고정할 수 있고, 클라이언트 IP 주소를 유지할 수 있으며, 정적 IP 주소를 할당받을 수 있음

 

- EKS 의 data plane

Data Plane은 실제로 애플리케이션 컨테이너가 실행되는 노드들로 구성

이는 워커 노드에 해당하며, EKS 클러스터 내에서 사용자가 정의한 파드들이 실행

data plane은 사용자가 정의한 EC2 인스턴스 또는 AWS Fargate와 같은 컨테이너 실행 환경에 의해 구성

즉, 사용자가 관리하는 부분

 

- 노드 구성품

pod :

여러개의 컨테이너의 묶음 -> 최소 실행 단위

여러개 있을 수 있음

ec2 인스턴스에서 도커 compose 한 것과 비슷한 느낌으로 이해

kubelet :

kubernetes 클러스터의 각 노드에서 실행되는 Kubernetes 에이전트

마스터 노드와 통신하여 노드의 상태를 보고하고, 마스터의 명령에 따라 컨테이너를 시작, 정지 또는 재시작

kube-proxy :

각 노드에서 실행되는 네트워크 프록시 서버로, Kubernetes 서비스의 로드 밸런싱 및 네트워크 프록싱

서비스 디스커버리 및 로드 밸런싱을 제공하여 서비스 간 통신을 관리

 

+)

ENI 란?

ENI는 Amazon Web Services의 가상 네트워크 인터페이스

ENI는 Amazon EC2(탄력적 컴퓨팅 클라우드) 인스턴스에 연결되어 네트워크 통신을 가능하게 함

모든 인스턴스는 기본 네트워크 인터페이스(기본 ENI)가 있어야 하며, 이 인터페이스는 하나의 서브넷에만 연결

인스턴스를 시작할 때 서브넷을 지정하도록 하는 이유

기본 ENI는 인스턴스에서 제거 X, 서브넷 또한 변경 X

 

왜 EKS owned ENI ?

ENI 는 아키텍처 상에 사용자가 관리하는 곳에 있긴 하지만 ( = 사용자 관리 하에 있는 VPC 내의 서브넷에 붙어 있음) EKS 로 AWS 에서 관리하기 때문

 

관리형 노드그룹 ?

EKS 클러스터에 인스턴스들을 관리형 노드 / 사용자 정의 노드 두 가지 버전으로 사용가능

사용자 정의로 하면 직접 인스턴스를 생성 -> 쿠버네티스 클러스터 노드로 등록 하는 과정 필요

ec2 인스턴스를 관리하려면 묶는게 필요하고 그게 오토스케일링 그룹으로 나타남

 

실습

- cloudformation 으로 기본 인프라 배포 : 제공된 yaml 파일 활용하여 cloud formation 배포

목표 아키텍처

 

- cloudformation 으로 기본 인프라 만들기

미리 제공받은 yaml 파일

테라폼만 사용해봐서 클라우드 포메이션용 yaml은 이런식으로 작성하는구나했다.

미리 정의된 부분들이 있으므로 기본 설정 그대로

key name 은 ec2의 ssh 접속을 위한 pem키

 

+) pem 키 생성ec2 > 네트워크 보안 > 키페어 > 생성 ( 확장자 .pem으로 ) > 다운로드다운로드시 경로 주의특히 윈도우에서 wsl 사용하는 경우 mnt 에서 root 쪽으로 이사해야함

 

iam 권한 주의cloud formation 에서 eks 사용을 위한 admin 별도 정의필요

 

- 배포 업데이트 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=peach SgIngressSshCidr=$222.112.255.3/32 --region ap-northeast-2

 

 

VPC, Subnet4개, EC2 1대 + 보안그룹(자신의 IP만 허용) 생성 된 것 확인

 

- 만들어진 ec2 접속

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

# ec2 에 SSH 접속
ssh root@$(aws cloudformation describe-stacks --stack-name myeks --query 'Stacks[*].Outputs[0].OutputValue' --output text)

# 접속 후 aws configure 적용
aws configure

# 적용된 자격증명 확인
aws configure list

 

 

접속한 인스턴스는 노란 줄 처진 것

일종의 bastion host 로 사용

 

- 환경변수 적용하기

# 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

#결과
#vpc-0c4760b337732a3be

# subnet 설정
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

#결과
#echo $PubSubnet1
#subnet-0b16ede59b2f1e128
#echo $PubSubnet2
#subnet-00b22e6787389a5d4

 

 

- EKS 배포

# 변수 확인
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.28 --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 클러스터 & 관리형노드그룹 배포: 총 15분 소요
# verbose 옵션 : 로깅 레벨 4는 자세함. 작을수록 간단
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.28 --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"
...

 

- 콘솔에서 확인하기

 

+)

오토스케일링 그룹을 확인 하는 이유

ec2 인스턴스가 하나가 노드

여러개 있는게 노드 그룹, 이 개념을 aws 의 오토스케일링 그룹 서비스로 제공하는 것

 

- eks-host 에서 정보 확인하기

# krew 플러그인 확인
kubectl krew list
kubectl ctx
kubectl ns
kubectl ns default
kubectl get-all    # 모든 네임스페이스에서 모든 리소스 확인

# eks 클러스터 정보 확인
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

## dig 조회 : 해당 IP 소유 리소스는 어떤것일까요?
APIDNS=$(aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint | cut -d '/' -f 3)
dig +short $APIDNS

# eks API 접속 시도 : 도메인 or 출력되는 ip 주소로 https://<IP>/version 외부에서도 접속 가능!
curl -k -s $(aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint)
curl -k -s $(aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint)/version | jq

# eks 노드 그룹 정보 확인
eksctl get nodegroup --cluster $CLUSTER_NAME --name $CLUSTER_NAME-nodegroup
aws eks describe-nodegroup --cluster-name $CLUSTER_NAME --nodegroup-name $CLUSTER_NAME-nodegroup | jq

# 노드 정보 확인 : 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
kubectl get node -owide
kubectl get node -v=6

# 노드의 capacityType 확인
kubectl get node --label-columns=eks.amazonaws.com/capacityType

# 인증 정보 확인 : 자세한 정보는 6주차(보안)에서 다룸
cat /root/.kube/config
kubectl config view
kubectl ctx
aws eks get-token --cluster-name $CLUSTER_NAME --region $AWS_DEFAULT_REGION

# 파드 정보 확인
kuectl get pod -n kube-system
kubectl get pod -n kube-system -o wide
kubectl get pod -A

# kube-system 네임스페이스에 모든 리소스 확인
kubectl get-all -n kube-system

# 모든 네임스페이스에서 모든 리소스 확인
kubectl get-all

# 모든 파드의 컨테이너 이미지 정보 확인
kubectl get pods --all-namespaces -o jsonpath="{.items[*].spec.containers[*].image}" | tr -s '[[:space:]]' '\n' | sort | uniq -c

# AWS ECR에서 컨테이너 이미지 가져오기 시도
docker pull 602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/eks/coredns:v1.10.1-eksbuild.4

 

+)

왜 명령어가 eksctl / kubetctl 로 두 가지일까?

 

- eks-host에서 노드 정보 확인 > 노드 인스턴스 ssh 접속 > 각 노드에서 각 pod 정보 확인

# 노드 IP 확인 및 PrivateIP 변수 지정
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 "export N1=$N1" >> /etc/profile
echo "export N2=$N2" >> /etc/profile

# 노드 보안그룹에 eksctl-host 에서 노드(파드)에 접속 가능하게 룰(Rule) 추가 설정
NGSGID=$(aws ec2 describe-security-groups --filters Name=group-name,Values=*nodegroup* --query "SecurityGroups[*].[GroupId]" --output text)
echo "export NGSGID=$NGSGID" >> /etc/profile
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

# 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

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

# 노드 정보 확인
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

# 노드 스토리지 (EBS 볼륨) 정보 확인
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

 

 

참고 문서

https://kimjingo.tistory.com/197 [김징어의 Devlog:티스토리]

'Infra & DevOps > k8s(EKS)' 카테고리의 다른 글

[EKS] Observability  (0) 2024.03.31
[EKS] Storage  (0) 2024.03.22
[EKS] network  (0) 2024.03.17
[EKS] VPC CNI  (1) 2024.03.16
[Kubernetes] http 에러 검증, 파드, pv  (0) 2022.04.26