Skip to main content Link Menu Expand (external link) Document Search Copy Copied

created at 2023-12-10

Table of contents

  1. 쿠버네티스 클러스터 초기 구성
  2. 이슈 발생!
    1. [문제점-1] 컨테이너 몰림 현상 issue #250
    2. [해결방법-1] 토폴로지 설정
    3. [문제점-2] 적절한 토폴로지 설정을 위한 노드의 리소스 상황 파악 문제
    4. [해결방법-2] Grafana 대시보드를 통한 Pod 별 리소스 소모량 확인
    5. [문제점-3] External IP 노출과 수동 NLB 설정에 소요되는 시간문제
    6. [해결방법-3] EKS 사용
    7. [사소한 문제점-4] NLB 설정 시 노출되는 dns 가 너무 김
    8. [해결방법-4] 짧은 DNS 를 통한 NLB 와 통신
  3. [결론]
  4. Reference

1.CI/CD 자동화 성공 그리고 실패

기존에 CI/CD 플로우는 하나의 머신에 자동으로 업로드하는 플로우를 가지고 있습니다(기존의 CI/CD 방법). 그리고 이런 머신에 초기 deploy 하였을 때 아래와 같이 컴퓨팅 리소스가 부족했습니다(특히 CPU 리소스).

1

2.부족한 cpu 리소스를 채우기 위한 수직확장 시 비용문제

vCPU 코어 수를 늘리기 위해 수직확장은 하나의 방법이 될 수 있었지만, AWS 요금이 급격하게 늘어납니다. img 기존 금액인 33.408 USD/month 에서 4배인 133.632 USD/month 로 급격하게 증가합니다. 단순히 vCPU 코어를 2개 더 늘렸을 뿐인데 말이죠.

  • t2.medium : 0.0464 USD/hour * 720 hours = 33.408 USD/month
  • t2.xlarge : 0.1856 USD/hour * 720 hours = 133.632 USD/month

3.수평확장 시 비용문제 완화

하지만 만약 t2.medium 두 곳에 균등하게 배포한다면(수평확장), 66.816 USD/month 로 2배 정도만 증가합니다. 즉, 2배의 비용으로 CPU 리소스를 2배 더 늘릴 수 있습니다. 굳이 같은 vCPU 증가량을 가지지만 4배 비싼 t2.xlarge 로 수직확장을 할 필요가 없죠. 그래서 매우 현실적으로 생각해보았을 때, 수평확장이 필요하다고 생각했습니다. 그리고 이를 위해 쿠버네티스를 도입하였습니다.


쿠버네티스 클러스터 초기 구성

저는 (마스터노드 t3.medium 1대), (워커노드 t3.medium 2대), (config-저장소버스 겸 nfs 서버 t3.medium 1대)를 사용하여 쿠버네티스 클러스터를 구성하였습니다. t3.medium 의 경우 2 vCPU, 4GB 메모리를 가지고 있습니다. 그리고 ENI 3개를 사용할 수 있습니다. 사용가능 pods 계산 계산식에 따르면 1개 노드 당 3 * (6 - 1) + 2 = 17개를 사용할 수 있으며, 운용가능한 pods 개수는 34개입니다.

img

이렇게 구성되어 돌아가고있는 파드들은 link 에서 확인하실 수 있습니다.

이슈 발생!

[문제점-1] 컨테이너 몰림 현상 issue #250

파드가 한쪽 워커노드로 치우쳐져있는 현상을 발견했습니다.

img

워커노드-2 에 대부분의 파드가 몰려있는 것을 확인할 수 있었으며, 리소스 사용량이 vCPU 2개에 거의 근접함을 확인할 수 있었어요.

[해결방법-1] 토폴로지 설정

각 Pod 들의 토폴로지를 설정함으로써 전체 컨테이너들이 균등하게 분포될 수 있습니다. 토폴로지란 클러스터 내 물리적/논리적인 노드들의 연결관계를 의미하며, 쿠버네티스에서는 이를 통해 파드들이 노드들에 균등하게 분포되도록 만들 수 있어요. 제가 사용한 토폴로지는 아래의 두 가지입니다.

  • Affinity와 Anti-Affinity 사용: Affinity 설정을 사용하여 파드가 특정 노드 또는 노드 그룹에 배치되도록 유도할 수 있으며, Anti-Affinity 설정을 사용하여 파드가 서로 다른 노드에 분산되도록 할 수 있습니다.
  • 리소스 요구사항과 제한 설정: 각 파드의 CPU와 메모리 요구사항(requests)과 제한(limits)을 적절히 설정하여, 노드의 리소스가 과도하게 사용되지 않도록 합니다. 이는 스케줄러가 노드의 리소스 상황을 고려하여 파드를 적절히 배치하는 데 도움이 됩니다.

[문제점-2] 적절한 토폴로지 설정을 위한 노드의 리소스 상황 파악 문제

어떤 Pod 가 얼마정도의 CPU 리소스가 필요한지 사전에 정의되어있지 않은 문제가 발생했습니다. 따라서 직접 실행하가며 필요한 리소스를 파악해야했는데요. 이를 위해선 노드들의 리소스 상황을 실시간으로 확인할 수 있어야했습니다.

[해결방법-2] Grafana 대시보드를 통한 Pod 별 리소스 소모량 확인

그래서 Grafana 대시보드를 추가로 구성하였습니다. 이를 통해 각 Pod 별 리소스 사용량을 실시간으로 확인할 수 있었어요. img

그래프에서 보이듯 user-server Pod 가 꽤 많은 cpu 리소스를 사용하는 것을 확인할 수 있었어요. 중간에 새로운 파란색 user-server 가 실행되는 이유는 제가 설정한 메모리 리소스 할당량를 초과했기 때문에 OOMKilled 되었기 때문입니다(100MB 만 줬거든요). 이를 통해 적절한 리소스 요구사항과 제한을 설정할 수 있었어요. 제 경우에는 유저서버와 Kafka에 부족한 메모리와 vCPU 를 추가로 할당해주었습니다.

[문제점-3] External IP 노출과 수동 NLB 설정에 소요되는 시간문제

이후 모든 클러스터를 구동시킬 수 있었지만 문제는 Ingress 설정을 위해 노드들의 NLB를 설정하는 것에 있었어요. 직접 모든 설정을 수동으로 설정해줘야하기 때문에 매 설정마다 시간이 소요됩니다. 또한 단순 EC2 로 쿠버네티스를 직접 설정하게 되면 쿠버네티스에 노드들의 외부 IP 를 등록시키기 위한 방법이 부족합니다. 이유는 EC2 로 구성된 쿠버네티스 클러스터 내부 노드들의 IP 는 유동적이기 때문인데요. 이를 해결하기 위해선 Elastic IP를 사용해야합니다. Elastic IP는 사용자가 할당 및 해제할 수 있는 AWS의 고정 IPv4 주소입니다. 한 번 할당하면, 사용자가 명시적으로 해제하기 전까지 그 주소가 유지됩니다.

베어메탈에서는 MetalLB를 통해 자동으로 NLB를 설정해줄 수 있지만 EC2 에 대한 지원을 하지 못한다고 합니다. img

그냥 EC2 로 직접 클러스터 설정할 바에 EKS 써라! 라고 하네요 :)

[해결방법-3] EKS 사용

AWS EC2 노드의 1) 유동IP 노출 문제2) 노드 오토 스케일링과 같은 다른 문제들을 편하게 해결하기 위해 EKS 를 사용하기로 결정했습니다. 일단 각 노드들의 1) External-IP 가 정상적으로 노출됩니다. 그리고 AWS 가 제공하는 Nginx Ingress Controller 를 사용할 수 있습니다. 이를 사용하면 2) 자동으로 NLB 를 생성해줍니다. 즉, Ingress 를 통해 외부에서 접근가능한 리버스 프록시를 만들 수 있으며 각 노드들에게 요청을 분산시켜주죠. 또한 직접 쿠버네티스 설정할 땐 AWS-ECR 토큰을 cronjob으로 갱신해주어야했지만, EKS 를 사용하면서 3) ECR 토큰을 갱신하지않아도 되어 매우 편했습니다. 4) 노드 스케일 그룹을 통해 노드들이 자동으로 스케일링되어 리소스가 부족한 경우에도 자동으로 리소스를 늘려주었습니다.

[사소한 문제점-4] NLB 설정 시 노출되는 dns 가 너무 김

이제 자동으로 NLB 를 생성할 수 있게 되었으며(쿠버네티스에 LoadBalancer 설정하면 자동으로 NLB 등록가능), 노드 또한 자동으로 scale-out 됩니다. 하지만 이 길고 긴 NLB external dns 로 쿠버네티스와 통신하기란 너무 귀찮은 문제가 있습니다.

img

a5a72… 이 긴 dns 로 쿠버네티스와 통신해야하는 문제가 있습니다.

[해결방법-4] 짧은 DNS 를 통한 NLB 와 통신

그래서 AWS-Route-53 을 사용하여 A 서브도메인으로 NLB 와 연결하였습니다. 이를 통해 www.litcodev.com 와 같이 짧은 dns 로 쿠버네티스와 통신할 수 있었어요.
img

[결론]

  1. 단일 인스턴스로 수행하다가 CPU 리소스가 부족했습니다.
  2. 수직확장을 하려고 했지만 비용이 너무 많이 들어서 수평확장을 하기로 결정했습니다.
  3. 수평확장을 하기 위해선 쿠버네티스를 사용해야했습니다.
  4. 쿠버네티스를 사용하기 위해선 EC2 로 직접 구성하기엔 노드들의 NLB 수동설정문제와 외부IP 노출제한 문제가 있었습니다.
  5. 이를 해결하기 위해 EKS 를 사용하기로 결정했습니다.

Reference

본 포스팅은 제가 아래의 이슈에서 이야기한 내용을 정리한 글이에요.