AWS EKS를 활용한 CI/CD 구축 - 3 팁 모음

#eks#k8s

2023-08-29 10:14

대표 이미지

두 편에 걸친 시리즈물을 통해, AWS EKS를 활용하여 Jenkins, ArgoCD 등 CI/CD 파이프라인을 구축하고, 실제 애플리케이션을 배포하는 과정을 공유하였습니다. 시리즈 마지막 장인 3번째 게시물에서는 앞선 글에서 미처 담지 못한 각종 팁들을 공유합니다.

개요


앞서 두 개의 글을 통해, AWS EKS에 Jenkins와 ArgoCD, ECR 레포지토리를 이용해 CI/CD 파이프라인을 구축하고 실제 애플리케이션을 배포하였다. 마지막 세 번째 장에서는, 앞선 두 글에서 미처 담지 못한 모니터링, 비용, Pod 제한 등에 대한 EKS 관련 팁을 모아서 소개해보고자 한다.

Monitoring


쿠버네티스 환경을 유지/관리하는데 있어 모니터링의 유무는 필수적이다. 정말 다양한 방법이 있고, 다들 장단점이 있으니 몇 가지 방법을 소개하려고 한다.

Open Lens

기존에 많은 사람들이 사용하던 쿠버네티스 환경 GUI Client인 'Lens'는, 2023년 1월 2일부로 기업 사용자는 유료화로 전환하였다. 그 가격은 1년에 199$. 그러나 다행히도 MIT 라이선스인 오픈소스 버전 'Open Lens'는 아직 무료로 사용 가능하다.

설치

  • 맥북 기준으로, 다음과 같이 brew를 이용해 간편히 설치 가능하다.
    • brew install --cask openlens
  • 설치 후, pod shell, pod log 기능을 추가하기 위해 확장 설치가 필요하다.
    • 상단 메뉴 OpenLens → Extensions → @alebcay/openlens-node-pod-menu Install

활용

  • 클러스터 전체 조망: 클러스터의 전체적인 리소스 현황 등의 상태 확인lens_1.png
  • 노드그룹 & 노드 상태 및 리소스 현황lens_2.png
  • 특정 Pod의 로그 보기image.png
  • 그 외에도 ConfigMap 직접 수정이나 Deployment, DaemonSet, StatefulSet, ReplicaSet 관리 등 수많은 기능이 있다.

Prometheus

프로메테우스는 오픈소스로 개발된 모니터링 및 알림 툴킷이며, 주로 클라우드 환경과 같은 대규모 분산 시스템에서 시스템 및 서비스의 상태를 모니터링하는 데 사용된다. 자세한 내용은 공식 Document를 참조하자.

설치

Helm chart를 이용해 배포해 보자.

  1. 레포지토리 추가
    1. helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
  2. 배포
    1. helm upgrade -i prometheus prometheus-community/prometheus \ --namespace monitoring \ --set alertmanager.persistentVolume.storageClass="gp2",server.persistentVolume.storageClass="gp2" --kubeconfig="./kubeconfig.yaml"
  3. 설치 시 다음 리소스들이 배포된다.
    1. Prometheus Server
    2. Prometheus Alert Manager
    3. Prometheus Kube State Metrics
    4. Prometheus Push Gateway
    5. Prometheus Node Exporter x 노드의 갯수

Grafana

그라파나는 유명한 오픈소스 대시보드 및 시각화 플랫폼이다. 시계열 데이터베이스에서 데이터를 가져와 사용자 정의된 다양한 대시보드를 만들 수 있고, 그래프 및 패널을 통해 데이터를 시각화하는 데 사용된다. 자세한 내용은 역시 Grafana 공식 문서를 참조하도록 하자.

설치

Helm chart를 이용해 배포해 보자.

  1. 레포지토리 추가

    1. helm repo add grafana https://grafana.github.io/helm-charts
  2. 필자의 경우 도메인 연결 및 하위 subpath 설정이 필요했고, 디폴트 설정으로 설치할 경우 ClusterIP 형태로 서비스가 설치되기 때문에 AWS Application LoadBalancer Ingress와 연동하기 위해(해당 Ingress는 서비스 타입이 NodePort 또는 LoadBalancer 타입일 경우만 연결된다.) grafana-values.yaml을 만들어 설정하였다. NodePort의 범위는 30000 ~ 32767 범위 내에 있어야 한다.

    service:
      type: NodePort
      port: 80
      targetPort: 3000
      nodePort: 32166
    grafana.ini:
      server:
        domain: grafana.mydomain.co.kr
        root_url: https://grafana.mydomain.co.kr/
        serve_from_sub_path: true
    
  3. 배포

    1. helm install grafana grafana/grafana --kubeconfig="./kubeconfig.yaml" -f grafana-values.yaml --namespace=monitoring
  4. 최초 접속 시 admin 패스워드

    1. kubectl get secret --namespace monitoring grafana -o jsonpath="{.data.admin-password}" --kubeconfig="./kubeconfig.yaml" | base64 --decode ; echo

데이터소스

Grafana에서 대시보드를 구성하려면 데이터를 가져올 데이터소스 설정이 필요하다. 위에서 설치한 프로메테우스를 데이터소스로 사용할 것이다.

  • Administration -> Data Sources -> Add new data source
  • 정말 다양한 데이터소스가 보일 텐데 프로메테우스를 선택한다.
  • Prometheus server URL을 지정한다. 동일한 'monitoring' 네임스페이스에 있으므로 서비스명만으로 접근이 가능하다. 다음과 같이 적자.
    • http://prometheus-server

대시보드

사용자 정의 대시보드를 입맛대로 구성할 수 있는 Grafana지만, Grafana Labs에는 다른 사용자들이 만들어 놓은 대시보드의 공유가 이루어진다. 다음 URL에서 Kubernetes + Prometheus용 대시보드를 설정해 보자. https://grafana.com/grafana/dashboards/17119-kubernetes-eks-cluster-prometheus/

  • 페이지에 접속해서 Revision 탭을 보면, Revision 별로 대시보드의 json을 다운로드 할 수 있다. 맨 위의 Revision을 다운로드 한다.
  • Grafana로 돌아와서, 우측 상단의 '+' 모양 버튼을 클릭하고 Import Dashboard 메뉴로 진입한다.
  • json을 업로드하고, 위에서 추가한 prometheus 데이터소스를 선택해 주자. image.png
  • 다음과 같은 대시보드가 추가될 것이다. image.png

Kubecost

Kubecost는 K8s 클러스터의 리소스 사용과 관련된 비용을 시각화하고 분석하는 데 도움을 주는 오픈소스 도구이다. 클러스터 운영 비용, 네트워크 비용, 사용된 리소스 비용 등의 관점에서 비용을 추적하고 최적화 솔루션도 제공해 준다. 자세한 내용은 kubecost 공식 문서를 참조하도록 하자.

설치

Kubecost 역시 Helm chart를 이용해 배포할 것이다.

  1. 레포지토리 추가
    1. helm repo add kubecost https://kubecost.github.io/cost-analyzer/
  2. 배포
    1. helm install kubecost kubecost/cost-analyzer \ --namespace monitoring \ -f https://raw.githubusercontent.com/kubecost/cost-analyzer-helm-chart/develop/cost-analyzer/values-eks-cost-monitoring.yaml \ --kubeconfig="./kubeconfig.yaml"
  3. 설치 시 다음 리소스들이 배포된다.
    1. Kubecost Prometheus Server
    2. Kubecost Kube State Metrics
    3. Kubecost Cost Analyzer
  4. Cost Analyzer에 대한 Ingress를 설정해도 되고, Open Lens의 기능인 Pod 포트포워딩 기능을 통해 Web UI로 접근할 수도 있다. 대략 다음과 같은 화면을 가진다. image.png
    1. Overview 대시보드, 클러스터 모니터, 보고서를 제공하며 비용 절감 플랜과 이유, 방법을 알려주는 Savings 메뉴가 있다.

Grafana와 합체

Kubecost를 설치하면 Kubecost용 프로메테우스 서버가 생성되는데, 이를 데이터소스로 Grafana 대시보드를 통해 Kubecost의 정보를 한번 확인해보자. 다음 대시보드를 교보재로 사용한다. https://grafana.com/grafana/dashboards/15714-kubecost-cluster-costs-overview/

  • kubecost prometheus 데이터소스를 추가해야 한다. 위에서 설명한 것과 동일하게 진행하며, 서버 URL은 다음과 같다.
  • 대시보드를 import하여, 위에서 추가한 kubecost prometheus를 데이터소스로 지정한다.
  • 다음과 같은 대시보드가 추가될 것이다.image.png

노드 인스턴스 Pod 제한


AWS EC2 인스턴스에는 CPU나 Memory의 리소스와 별개로, 인스턴스 하나당 생성할 수 있는 Pod의 갯수에 제한이 있다. 이유는 AWS에서 인스턴스에 붙일 수 있는 Elastic Network Interface(ENI)에 의한 IP의 갯수에 제한이 있기 때문이다. AWS는 Amazon VPC CNI 플러그인을 통해 각 노드에 대한 IP 할당을 관리한다. 각 인스턴스 별로 가지고 있는 ENI와 그 수를 바탕으로 계산을 하면 Pod의 최대치가 나오지만, 모든 인스턴스 타입에 대해 이미 계산해놓은 문서가 있다.

각 환경별로 천차만별이겠지만 CPU 또는 Memory는 여유로운데, 인스턴스당 Pod 제한 때문에 추가 노드를 사용하거나 노드의 인스턴스 타입을 스케일업 해야되는 경우가 생길 수도 있다. 이를 해결하고자 인스턴스당 Pod의 제한을 늘릴 수 있는 방법 중 하나를 소개한다.

Nitro 기반 인스턴스

Nitro System 기반 인스턴스로, 공식 문서를 참조하자: https://aws.amazon.com/ko/ec2/nitro/

m5, r5 패밀리 타입의 인스턴스는, Amazon VPC CNI 플러그인의 ENABLE_PREFIX_DELEGATION기능을 켤 수 있다.

  • kubectl set env daemonset aws-node -n kube-system ENABLE_PREFIX_DELEGATION=true

이 기능을 쓰면 각 ENI별로 IP Prefix(/28 블록)를 할당할 수 있다. 예를 들어, m5.large 인스턴스는 기본 설정으로는 30개의 Pod 제한이 있으나, ENABLE_PREFIX_DELEGATION 기능을 사용 시 최소 110개의 IP를 사용 가능하다.

eksctl을 통해 관리형 노드 그룹을 생성할 경우, 노드당 최대 Pod의 갯수를 지정할 수 있다. eksctl을 통해 노드 그룹을 생성할 경우 CloudFormation 스택을 통해 생성하는데, 반드시 설정해줘야 할 두가지 포인트가 있다.

  1. EKS Cluster API 엔드포인트를 퍼블릭 및 프라이빗으로 설정
    1. AWS EKS 콘솔 -> 클러스터 -> 네트워킹 -> 네트워킹 관리 image.png
  2. Cluster 생성 시 보안 그룹을 지정하지 않았다면 자동 생성되는데, 이 보안그룹의 아웃바운드 트래픽을 추가해야 함

설정이 완료됐으면, 클러스터 정보 및 생성할 노드그룹의 정보를 담은 eksctl-nodegroup.yaml 파일을 만든다.

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: {클러스터명}
  region: {리전}

vpc:
  id: "{VPC ID}"
  securityGroup: "{Security Group ID}"
  subnets:
    public:
      {가용 영역}: { id: {서브넷 ID} }
      {가용 영역}: { id: {서브넷 ID} }
      {가용 영역}: { id: {서브넷 ID} }

managedNodeGroups:
  - name: {노드그룹 이름}
    instanceType: {인스턴스 타입}
    desiredCapacity: 2
    minSize: 2
    maxSize: 4
    maxPodsPerNode: 60
    iam:
      instanceRoleARN: {노드그룹에서 사용할 IAM 역할의 ARN}

다음 명령어를 통해 관리형 노드 그룹을 생성한다. eksctl create nodegroup -f eksctl-nodegroup.yaml

위의 yaml로 생성한 노드 그룹의 노드는 노드당 Pod 제한이 60이 된다. 인스턴스의 제한을 넘어서는 Pod이 배포될 경우 Nitro계열 인스턴스가 아니라면 max pod 설정이 되어 있어도 IP 할당이 불가능하므로 배포가 되지 않을 것이지만 ENABLE_PREFIX_DELEGATION기능이 켜져 있고 노드가 Nitro계열 인스턴스라면 Prefix를 통한 IP 할당으로 인스턴스 자체의 제한을 넘어서는 Pod이 배포될 것이다.

맺음말


Amazon EKS와 ECR, Git, Jenkins, ArgoCD를 이용하여 CI/CD 파이프라인을 함께 생성해 보며 달렸던 EKS 활용 시리즈가 마지막 모니터링 및 비용 관리와 Pod 제한 해제에 이르기까지 남은 팁들을 모두 공유하며 끝이 났다.

쿠버네티스와 Amazon EKS를 구축하는데 있어 이 시리즈가 도움이 되었으면 한다.

Ref