AEWS STUDY - 1주차

Eljoe·2023년 4월 25일
0

AEWS STUDY

목록 보기
1/7
post-thumbnail

1주차

본 페이지는 AWS EKS Workshop 실습 스터디의 일환으로 매주 실습 결과와 생각을 기록하는 장으로써 작성하였습니다.

작성 방향

  • 앞으로의 워크샵 기록을 어떤 방향으로 작성할 것인지에 대해 고민을 해본 결과, 가시다님의 강의에서 뇌리에 강하게 남아있거나 내 입장에서 이해가 되는 내용을 토대로 작성하기로 하였다.
  • 얼마 전부터 김익한 교수님의 ‘거인의 노트’를 탐독 중이었고 그 중 인상적인 구절들이 있었다.
    • 강의와 같은 학습을 눈과 귀로만 쫓는 수동적 배움 행위를 통해 얻은 지식은 자기화할 수 없다.
    • 자기의 입장에서 충분히 이해가 되는 내용을 파악하고 핵심 키워드를 뽑고 그 내용을 토대로 자기 방식으로 재구성하고 자기 생각을 덧붙이는 행위를 통해 지식을 자기화할 수 있다.
    • 내가 온전히 이해하고 교감할 수 있는 단어 위주로 핵심 키워드와 중심 내용을 뽑고 서사를 정리하고 기록한다.
  • 위 구절과 같이 앞으로의 워크샵 과정에서 오롯이 내가 이해한 내용을 토대로 키워드를 뽑아 최대한 간결한 문구로 작성토록 하겠다.

💡과정 수행 中, 이해되지 않는 내용은 페이지 마지막에 학습 후 의문점으로 작성하겠습니다.

내가 EKS를 학습하려는 이유

  • 일단, 본 내용을 작성하기에 앞서 내가 왜 EKS를 학습하려는지에 대해 간략하게 설명할 필요가 있겠다.
  • 얼마 전까지 나는 이직 활동을 열심히 하고 있었는데 지원한 회사 모두 공통적으로 기술 면접에서 쿠버네티스 관련 지식을 여쭤보았다. 알고 있는 한도 내에서 열심히 의견을 피력하였으나 얕은 지식의 한계 때문이었는지 만족스럽지 않은 결과를 통보 받았다.
  • 이전에는 고객사의 Onprem. & Public Cloud-based Application을 K8S 기반 Containerization하는 업무를 수행하였으나, 그 당시 나는 각각의 요소들-예컨데 Deployment, Replicaset과 같은-을 어림짐작(이라 말하고 대충이라 읽는다)으로 학습한 상태에서 배포 작업 후엔 언제나 Pod의 상태가 초록색이길 간절히 기도하고 각종 테스트를 진행 후 운영 서버로 이관이 완료되면 회고는 커녕 손을 완전히 떼는 행위를 반복하고 있었다.
  • 그러니 기술 면접에서의 나의 답변은 한없이 얕디 얕을 수 밖에 없는 건 당연지사였고, 이는 어제보다 더 나은 사람이 되길 바라는 나의 가치관-솔직히 말하자면 나의 시장 가치를 상승시키고자 하는 욕구-에서 용납할 수 없는 행동이었다.
  • 내 안의 부족함을 한없이 느끼던 중 가시다님의 EKS 스터디 모집 공고를 직장 동료로부터 소개 받았고 당일 신청하여 합류하게 되었다.
  • 이 글을 빌려 소개해준 동료분들께 감사하다는 말씀을 드리고 싶다!😊

Keyword

  • 첫 번째 강의를 듣고 기억에 남거나 의문이 들었던 키워드를 마인드 맵 형태로 작성해보자면 다음과 같다.

웹 페이지 확대가 아닌 이미지 자체를 확대할 수 있는 방법을 알고 계신다면 공유 부탁드립니다.🥲

What does mean…?

Amazon Elastic Kubernetes Service

  • Kubernetes를 쉽게 실행할 수 있는 관리형 서비스
  • 관리형 서비스이기 때문에 컨트롤/데이터 플레인을 직접 설치, 운영 및 유지할 필요가 없으므로 비즈니스/애플리케이션에 더욱 집중할 수 있다.
  • 컨트롤 플레인은 여러 개의 마스터 노드 인스턴스로 구성되어 있고, 여러 가용 영역에 배포되어 고가용성을 보장한다.
  • 또한, 비정상 마스터 노드 인스턴스를 Auto Scaling Group을 사용하여 자동으로 감지하고 교체하며 버전 업데이트와 패치를 자동으로 제공한다.
  • ECR, ELB, IAM 등과 같이 다양한 AWS 서비스들과 연동이 가능하며 Kubernetes 커뮤니티의 모든 플러그인과 도구를 사용할 수 있다.

워크샵 설명을 읽어보면서 왜인지 모르게 ‘네가 필요한 건 여기 다 있으니까 너는 애플리케이션만 들고오면 돼!’ 같은 느낌을 받았다.

vs ECS…?

  • 현재 프로젝트에서 ECS를 운영 중에 있으므로 자연스레 EKS와의 비교가 떠올랐는데 구조적인 이론을 설명하기엔 나의 지식이 부족한 탓으로 사용성에 초점을 맞춰 설명하자면 다음과 같다.
    • Elastic Container Service

      • 심플하다. Kubernetes Based EKS보다 덜 복잡한 대신 비어있는 부분은 전부 AWS 서비스가 채워주는 느낌이 든다.

      • 상기 What does mean 내용에서 언급한 ‘네가 필요한 건 여기 다 있으니까 너는 애플리케이션만 들고오면 돼!’에서 하기와 같이 첨언한 느낌이다.

        • 네가 필요한 서비스는 전부 AWS에서 제공할테니까 너는 애플리케이션만 들고오면 돼!
      • 비교적 간단한(비교적이라는 단어를 추가했음에 유의하자) MSA 서비스가 필요할 때 유용한 서비스라는 생각이 든다.

    • Elastic Kubernetes Service

      • 유연하다. Kubernetes 기반 서비스라 그런지 여러가지 오픈소스, 써드파티 라이브러리, 개발자 도구를 조합할 수 있다.

      • 예를 들자면 CNCF에서 제공하는 오픈소스 프로젝트나 기타 써드파티 라이브러리를 조합하여 본인만의 Custom EKS를 구축할 수 있다.

        • 마치 레고 같은 느낌이다.

💡사용성에 중점을 둔 나의 설명으로는 ECS vs EKS 대결 구도보다는 상황 또는 규모에 따라 적절한 서비스를 택하면 되지 않을까라는 결론을 내리고 싶다.

Version

  • EKS 지원 버전의 경우 보통 4개의 마이너 버전을 제공하고, 평균 3개월마다 새로운 마이너 버전을 업데이트하고 각 버전은 약 12개월정도 지원한다.
  • 버전을 읽는 방법은 다음과 같다.

    1.24.2
    Major.Minor.Patch

    • Major : Breaking Change(이전 버전과의 호환성이 없는 완전 새로운 버전)
    • Minor : New Features(기존 버전에서 새로운 기능이 추가된 버전)
    • Patch : Bug Fixes(기존 버전에서 발생한 버그를 수정한 버전)

Architecture

  • Cluster 배포 시, 다음과 같은 구조가 생성된다.
    • Control Plane
      • AWS측에서 관리하는 VPC
      • 3개의 가용영역에 배포된 각 마스터 노드 인스턴스와 이를 포함하는 ASG
      • 워커 노드로부터 API 서버 접근을 위한 Network Load Balancer
      • 3개의 가용영역에 배포된 각 etcd 인스턴스와 이를 포함하는 ASG
      • etcd로의 접근을 위한 Elastic Load Balancer

        💡etcd : 클러스터의 구성 및 상태 정보를 저장하는 분산형 Key-Value 저장소

    • Data Plane
      • 고객이 관리하는 VPC
      • EKS owned Elastic Network Interface

        💡EKS owned Elastic Network Interface
        컨트롤 플레인과 워커노드 사이 연결 통로 역할을 하는 ENI

      • 여러가지 타입별 Nodes
        • Managed node groups : AWS측에서 최신 EKS Optimized AMI 관리 및 제공
        • Self-managed nodes : 고객측에서 AMI와 ASG, OS 관리
        • Fargate : 별도의 AMI 기반 인스턴스를 관리할 필요 없이 MicroVM을 이용해 Pod별 VM 할당

          MicroVM
          VM을 가동하는데 최소한의 기능과 장치를 구현한 경량화 가상머신
          가상머신의 장점인 보안성과 컨테이너의 빠른 속도를 취합한 기술이며 보통 MicroVM을 먼저 실행시키고 해당 VM 내부에 컨테이너를 생성하는 구조로 사용한다.

Network

  • EKS Cluster Endpoint - Private : API 서버가 외부로 노출이 되지 않는 방식 → 프로덕션에서 주로 쓰는 구조
    • 사용자가 kubectl 명령어를 수행하는 경우
      • kubectl > Private hosted zone > EKS owned ENI > API 서버
    • 워커노드(kubelet, kubeproxy)에서 컨트롤 플레인(API 서버)으로 요청하는 경우
      • 워커노드(kubelet, kubeproxy) > EKS owned ENI > API 서버
    • 컨트롤 플레인(API 서버)에서 워커노드로 명령을 수행하는 경우
      • API 서버 > EKS owned ENI > 워커노드(kubelet)

Deploy

  • 1주차 실습 아키텍처는 다음과 같다.
  • 기본 인프라는 Cloudformation Telmplate를 제공해주셨으므로, 스택 그대로 배포를 진행한다.
  • 생성한 Bastion으로 Putty를 통해 접속하고 클러스터 생성에 필요한 환경변수를 선언한다.
    $sudo su -
    
    # 자격 구성 등록
    # AdministratorAccess 정책을 부여한 IAM User의 자격 증명을 입력한다.
    $aws configure
    AWS Access Key ID [None]: <생성한 액세스 키 아이디>
    AWS Secret Access Key [None]: <생성한 시크릿 액세스 키>
    Default region name [None]: ap-northeast-2
    Default output format [None]: json
    
    # VPC ID 환경변수 등록
    $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-01...
    
    # Subnet 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
    subnet-096...
    $echo $PubSubnet2
    subnet-058...
  • 클러스터를 생성하기 전 dry-run 옵션을 통해서 생성될 구조를 먼저 확인한다.
    $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-01b6...
      manageSharedNodeSecurityGroupRules: true
      nat:
        gateway: Disable
      subnets:
        public:
          ap-northeast-2a:
            az: ap-northeast-2a
            cidr: 192.168.1.0/24
            id: subnet-096...
          ap-northeast-2c:
            az: ap-northeast-2c
            cidr: 192.168.2.0/24
            id: subnet-058...
  • 생성될 구조에 문제가 없는 경우 배포를 진행한다.
    # Deploy EKS Cluster & Managed node grops
    # ssh-access : 노드로 ssh 접속 허용
    # external-dns-access : ExternalDNS 허용
    # verbose : 로그 레벨 설정(0 ~ 5)
    $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
    ...
    2023-04-25 11:06:06 []  setting current-context to eljoe@myeks.ap-northeast-2.eksctl.io
    2023-04-25 11:06:06 []  saved kubeconfig as "/root/.kube/config"
    • eksctl create cluster 명령어를 입력하면 CloudFormation을 통해 스택 배포가 진행되므로 해당 콘솔에서 진행 상황을 확인할 수 있다.
    • 스택이 정상적으로 배포된 경우 EKS 콘솔로 접속하여 아래와 같이 생성된 클러스터를 확인할 수 있다.
    • EC2 > ASG 콘솔에서 아래와 같이 관리형 노드그룹 인스턴스를 포함하는 ASG가 생성된 것을 확인할 수 있다.
  • bastion 인스턴스로 돌아가서 아래와 같이 EKS 관련 정보를 확인하는 명령어를 수행한다.
    $kubectl krew list
    PLUGIN   VERSION
    ctx      v0.9.4
    get-all  v1.3.8
    krew     v0.4.3
    ns       v0.9.4
    
    $kubectl ctx
    eljoe@myeks.ap-northeast-2.eksctl.io
    
    $kubectl ns
    default
    kube-node-lease
    kube-public
    kube-system
    
    # 네임스페이스 활성화
    (eljoe@myeks:N/A) [root@myeks-host ~]# kubectl ns default
    Context "eljoe@myeks.ap-northeast-2.eksctl.io" modified.
    Active namespace is "default".
    
    # default로 변경된 것을 확인한다.
    (eljoe@myeks:default) [root@myeks-host ~]#
    
    # 클러스터 정보 확인
    $kubectl cluster-info
    Kubernetes control plane is running at https://24F9A0BCA38046CD70B1F02A211771D8.yl4.ap-northeast-2.eks.amazonaws.com
    
    # EKS 클러스터 정보 확인
    $eksctl get cluster
    
    # API 서버 퍼블릭 엔드포인트 확인
    $aws eks describe-cluster --name $CLUSTER_NAME | jq -r .cluster.endpoint
    https://24F9A0BCA38046CD70B1F02A211771D8.yl4.ap-northeast-2.eks.amazonaws.com
  • 배포한 노드에 ssh-access 옵션을 통해 ssh 접속을 허용하였으므로 접속을 위한 설정을 진행한다.
    # 노드 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
    myeks-myeks-nodegroup-Node |  192.168.2.193 |  3.34.134.155   |  running
    myeks-myeks-nodegroup-Node |  192.168.1.80  |  3.36.94.216    |  running
    
    # 노드 Private IP 환경변수 등록
    $N1=192.168.1.80
    $N2=192.168.2.193
    
    # 노드 보안그룹 환경변수 등록
    $NGSGID=$(aws ec2 describe-security-groups --filters Name=group-name,Values=*nodegroup* --query "SecurityGroups[*].[GroupId]" --output text)
    $echo $NGSGID
    sg-09759...
    
    # 노드 보안그룹에 bastion에서 접속 가능하게 인바운드 규칙 추가
    $aws ec2 authorize-security-group-ingress --group-id $NGSGID --protocol '-1' --cidr 192.168.1.100/32
    
    # bastion에서 ping 테스트
    $ping -c 2 $N1
    $ping -c 2 $N2
    
    # 워커 노드 SSH 접속
    $ssh -i ~/.ssh/id_rsa ec2-user@$N1
    $ssh -i ~/.ssh/id_rsa ec2-user@$N2
  • EKS owned ENI 확인하는 명령어를 수행하여 네트워크 흐름을 확인한다.
    $ssh -i ~/.ssh/id_rsa ec2-user@$N2 sudo ss -tnp
    ESTAB 0      0       192.168.1.80:60786    3.34.155.17:443   users:(("kube-proxy",pid=3088,fd=11))
    ESTAB 0      0       192.168.1.80:59072 43.200.114.234:443   users:(("kubelet",pid=2841,fd=40))
    
    # 노드 내 kubeproxy와 kubelet이 클러스터의 API 서버 퍼블릭 엔드포인트 IP와 통신하는 것을 확인할 수 있다.
    $nslookup 24F9A0BCA38046CD70B1F02A211771D8.yl4.ap-northeast-2.eks.amazonaws.com
    Server:         192.168.0.2
    Address:        192.168.0.2#53
    
    Non-authoritative answer:
    Name:   24F9A0BCA38046CD70B1F02A211771D8.yl4.ap-northeast-2.eks.amazonaws.com
    Address: 3.34.155.17
    Name:   24F9A0BCA38046CD70B1F02A211771D8.yl4.ap-northeast-2.eks.amazonaws.com
    Address: 43.200.114.234
    
    # Bastion 터미널을 하나 더 열어서 아래와 같이 데몬셋 파드 하나에 bash를 실행한다
    $kubectl exec daemonsets/aws-node -it -n kube-system -c aws-node -- bash
    bash-4.2#
    
    # 마지막 줄에 kubelet이 통신하는 IP를 ENI 콘솔에서 검색해보면 소유자와 요청자 ID가 다른 것을 확인할 수 있다.
    # 해당 ENI가 EKS 컨트롤 플레인과 데이터 플레인 사이 연결 통로 역할을 하는 EKS owned ENI이다.
    $ssh -i ~/.ssh/id_rsa ec2-user@$N2 sudo ss -tnp
    ESTAB 0      0      [::ffff:192.168.2.193]:10250 [::ffff:192.168.2.134]:41606 users:(("kubelet",pid=2842,fd=7))

학습 이후 의문점

  • etcd
    • 왜 사용하는걸까?
      • K:V 저장소의 특징 - 최소한의 데이터로 주고 받는 것이 빠른 구조라서?
      • 뭔가 다른 이유가 있을까?
    • 클러스터의 정보를 저장하는 스토리지니까 만약 내가 kubectl get과 같은 명령어를 수행하면 그 흐름은 NLB > API Server > ELB > etcd순일까?
  • Network
    • 프로덕션 환경에서 Private 구성을 주로 사용한다는데, Public 또는 Public/Private 구성은 어떤 상황에서 사용하는 걸까?
profile
DevOps Engineer

0개의 댓글