규턴의 개발블로그
article thumbnail

이번글은 제가 클론코딩하면서 실습한 EKS에서 대해 전체적인 flow를 정리하고자 합니다.

그렇기에 해당 실습을 해보지 않은 분들은 글을 읽기 어려울수도 있습니다.

https://catalog.us-east-1.prod.workshops.aws/workshops/9c0aa9ab-90a9-44a6-abe1-8dff360ae428/ko-KR/10-intro

 

Workshop Studio

 

catalog.us-east-1.prod.workshops.aws

해당 링크를 통해 참고

 

워크샵 진행순서

  • AWS Cloud9을 통한 실습 환경 구축
  • 도커를 이용하여 컨테이너 이미지 생성
  • 컨테이너 이미지를 ECR에 업로드
  • Amazon EKS 클러스터 구축 및 서비스 배포
  • Container Insights 사용해보기
  • 파드 및 클러스터 오토 스케일링
  • AWS Fargate로 서비스 올리기
  • CI/CD 파이프라인 구축

Kubernets

 

현재의 쿠버네티스 클러스터 구성도는 다음과 같습니다.

ControlPlane: 워커노드 + 노드 내의 파드들을 관리합니다.

 

EKS

EKS는 AWS에서 제공하는 Kubernetes기반 Saas입니다.

 

EKS를 사용함으로서 AWS에서 제공하는 기능들을 확장하여 사용할 수 잇습니다.

  • ECR
  • ELB
  • IAM
  • VPC...

EKS 클러스터 구축

cat << EOF > eks-demo-cluster.yaml
---
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: eks-demo # 생성할 EKS 클러스터명
  region: ${AWS_REGION} # 클러스터를 생성할 리전
  version: "1.21"

vpc:
  cidr: "192.168.0.0/16" # 클러스터에서 사용할 VPC의 CIDR

managedNodeGroups:
  - name: node-group # 클러스터의 노드 그룹명
    instanceType: m5.large # 클러스터 워커 노드의 인스턴스 타입
    desiredCapacity: 3 # 클러스터 워커 노드의 갯수
    volumeSize: 10  # 클러스터 워커 노드의 EBS 용량 (단위: GiB)
    iam:
      withAddonPolicies:
        imageBuilder: true # Amazon ECR에 대한 권한 추가
        # albIngress: true  # albIngress에 대한 권한 추가
        cloudWatch: true # cloudWatch에 대한 권한 추가
        autoScaler: true # auto scaling에 대한 권한 추가

cloudWatch:
  clusterLogging:
    enableTypes: ["*"]
EOF

 

AWS 콘솔에서도 만들 수 있지만 해당 실습에서 제공하는 yaml파일을 사용합니다.

만약 EC2나 Cloud9에서 사용한다면 EKS 관련 IAM권한을 가지고 있어야합니다.

 

해당 실습에서는 3개의 노드그룹을 생성합니다.( 워커노드)

또한 ECR, CloudWatch, autoScaler 기능을 추가적으로 사용합니다.

 

현재의 아키텍쳐

 

 

ALB (Application Load Balancer)

 

 


해당 기능을 알기전에 Ingress와 Ingress 컨트롤러에 대한 차이가 헷갈려 정리하고자합니다.

(https://blog.naver.com/alice_k106/221502890249 참고)

 

Ingress: 주로 yaml파일로 정의되는 쿠버네티스 상의 리소스 오브젝트, Ingress 리소스를 통해 클라이언트에서 보내는 요청이 어떠한 deployment or Service에 접근할지 정의한다.

 

Ingress Controller: Ingress리소스를 기반으로 실제로 요청이 들어오면 ingress내용을 기반으로 트래픽을 처리한다.

즉 Ingress가 kubernetes상에 존재하여 Ingress Controller가 없으면 작동하지 않는다.

Ingress Controller는 Kong, nginx 등등 있다.

 


그렇다면 ALB는?
AWS에서 제공하는 LoadBalancer

클러스터내에 ingress 리소스가 생성될때 ALB는 해당 자원들을 구성하여 HTTP, HTTPS 트래픽을 라우팅하는 Ingress Controller입니다.

 

 

 

서비스 배포하기

 

 

실제로 서비스를 배포하는것은 다음그림과 같습니다.

  1. 소스코드 다운
  2. ECR에서 이미지 Pull
  3. Deployment, Service, Ingress 메니페스트 파일 EKS에 리소스로 등록

실제 clinet입장에서 서비스에 접속할때 다음과 같은 과정을 거칩니다.

1. Ingress를 통한 트래픽 라우팅

2. 해당 라우팅된 트래픽을 service 객체를 통해 서비스 통신

 

* 3개의 어플리케이션 메니페스트 파일은 https://catalog.us-east-1.prod.workshops.aws/workshops/9c0aa9ab-90a9-44a6-abe1-8dff360ae428/ko-KR/70-deploy-service/100-flask-backend링크에서 확인할 수 있습니다.

 

저는 그중 하나의 어플리케이션 deployment, service, ingress 메니페스트 파일을 분석하겠습니다.

 

 

1. Deployment

cat <<EOF> flask-deployment.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-flask-backend
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: demo-flask-backend
  template:
    metadata:
      labels:
        app: demo-flask-backend
    spec:
      containers:
        - name: demo-flask-backend
          image: $ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/demo-flask-backend:latest
          imagePullPolicy: Always
          ports:
            - containerPort: 8080
EOF
  • replicas: 3개의 파드를 생성
  • selector.matchLabels.app: sepc.template.spect.containers의 name과 같은 label의 것을 실행시키겠다.
  • spec.tempalte.spec.containers: 해당 컨테이너를 쿠버네티스 상에서 "demo-flask-backend"라고 labeling하고 해당 이미지를 들고오겠다. k8s 클러스터 내에서는 8080포트를 사용하겠다.

해당 deployment만으로는 pod가 생성되긴 하지만 클라이언트가 실제로 접근할 수 없습니다.

또한 내부 pod들 끼리 접근하기 위해서는 고정된 ip를 가지고 접근을 해야하는데 deployment만을 사용할경우 pod가 재 생성될때마다 ip가 변동되기에 service 오브젝트를 생성해줘여합니다.

 

* Service 오브젝트 기능

  • 고유한 도메인 이름을 부여함
  • 로드 밸런서 기능 수행
  • 포드를 외부로 노출

Service

 

cat <<EOF> flask-service.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: demo-flask-backend
  annotations:
    alb.ingress.kubernetes.io/healthcheck-path: "/contents/aws"
spec:
  selector:
    app: demo-flask-backend
  type: NodePort
  ports:
    - port: 8080 # 서비스가 생성할 포트  
      targetPort: 8080 # 서비스가 접근할 pod의 포트
      protocol: TCP
EOF
  • spec.selector.app: deployment에서 설정한 metedata.name이 매핑됩니다.
  • spec.type:
    • ClusterIP: 쿠버네티스 내부에서만 포드에 접근할 때 (관리자가 주로 사용) 
    • NodePort: 서비스에 외부 트래픽을 직접 보내는 원시적인 방법
      모든 워커노드에 port가 할당되는 방식
    • LoadBalancer: 로드 밸런스를 동적으로 프로비저닝하여 포드에 연결+ 트래픽 분산
      로드밸런서라는것이 생격 각노드에 트래픽을 분산
  • https://nearhome.tistory.com/87참고


Ingress

cat <<EOF> flask-ingress.yaml
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
    name: "flask-backend-ingress"
    namespace: default
    annotations:
      kubernetes.io/ingress.class: alb
      alb.ingress.kubernetes.io/scheme: internet-facing
      alb.ingress.kubernetes.io/target-type: ip
      alb.ingress.kubernetes.io/group.name: eks-demo-group
      alb.ingress.kubernetes.io/group.order: '1'
spec:
    rules:
    - http:
        paths:
          - path: /contents
            pathType: Prefix
            backend:
              service:
                name: "demo-flask-backend"
                port:
                  number: 8080
EOF

/contentents url로 들어오는것은 "demo-flask-backend" service로 트래픽을 보내겠다라는 의미입니다.

 

CI/CD 파이프라인 구축

 

저희가 진행할 ci/cd파이프라인은 다음과 같습니다.

해당 실습은 프론트 소스코드만을 다룹니다.

 

1. front 소스코드를 github에 push합니다.

2. git action을 통해 ecr repo에 업데이트 합니다.

3. kubernetes+kustomize관련 repo를 생성하고 push합니다.

4. argocd를 설치하고 3번의 repo를 연결합니다.

5. kustomize를 통해 kubernetes 메니페스트파일내 리소스가 kustomize.yml파일에 맞게 변경됩니다.
-> github action을 통해 commit/push 까지 설정

6. argocd는 3번 repo를 바라보고 있다가 sync가 맞지 않으면 out of sync를 나타냅니다.

7. sync를 맞추는것을 클릭하면 해당 pod를 재시작하여 sync를 맞춥니다.

 

CI/CD과정은 클론코딩하면서도 이해가 잘되지 않아 추가적인 공부가 필요할것 같습니다..

 

profile

규턴의 개발블로그

@규턴이

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!