본문 바로가기

회고

AI와 함께 구축한 K8s가 6개월 뒤 보낸 청구서

제가 현재 인프라 엔지니어로 근무하는 '블루키'에서는 프랜차이즈 운영의 A부터 Z까지, 매출 수집부터 품질 점검까지 통합 관리하는 플랫폼 'fc-system'을 통해 본사와 가맹점을 잇는 비즈니스 가교 역할을 하고 있습니다.

 

하지만 제가 처음 이 팀에 합류했을 당시, 그 가교의 실상은 금방이라도 무너질 듯 위태로운 상태였습니다.

 

외부 개발사의 중도 포기로 급히 결성된 인하우스 팀 내에서, 저는 기존 시스템의 유지보수와 신규 납품을 위한 인프라 구축이라는 무거운 과제를 동시에 떠안게 되었습니다. 당시 제가 마주한 현실은 그야말로 ‘사면초가’였습니다.

  • 기술적 파편화: 프레임워크 없이 짜인 코드는 고객사별로 포크(Fork)되어 제각각의 버그를 품고 있었고, 유지보수는 불가능에 가까웠습니다.

  • 인프라의 비효율: 베어메탈 기반의 이중화 구조였으나, 애플리케이션과의 부조화로 인해 비싼 HA 솔루션 라이선스 비용만 낭비될 뿐 정작 효율적인 배포와 운영은 원천 봉쇄되어 있었습니다.

  • 물리적 제약: 이미 계약 조건에 묶여 추가 장비 구매조차 불가능한, 손발이 다 묶인 상황이었습니다.

이 절망적인 상황을 타개하기 위해 제가 선택한 파트너는 AI였습니다. AI와 밤낮으로 논의하며 설계한 ‘K8s(Kubernetes) 전환’이라는 청사진은 저에게 유일한 구명줄처럼 보였습니다.

 

01. 물리적 제약과 인프라의 한계

이전 개발사로부터 인계받은 시스템은 표준 프레임워크 없이 PHP와 Node.js(NestJS)가 혼재된 구조로, 운영 및 유지보수의 효율성이 한계에 다다른 상태였습니다.

 

이를 해결하기 위해 Next.js와 NestJS 기반의 전면 신규 개발을 추진하였으나, 이미 고객사에 납품 비용이 확정된 상황에서 클라우드 전환이나 추가 스토리지 구매를 위한 예산 확보가 불가능한 제약에 직면했습니다.

 

기존 인프라는 Active-Standby 기반의 HA 환경이었으나, 다음과 같은 구조적 결함과 추가 비용 부담으로 인해 안정적인 운영을 기대하기 어려웠습니다.

  • 장애 판별의 모순: 기존 시스템은 Apache(PHP)와 독립 API(NestJS)가 혼재된 구조였으나, HA 로직은 오직 Apache의 생존만을 체크했습니다. 이로 인해 핵심인 NestJS가 다운되어도 시스템은 이를 '정상'으로 오판하여 페일오버를 수행하지 못했습니다. 결과적으로 장애 상황에서 고가의 이중화 솔루션이 무용지물이 되는 구조적 맹점을 안고 있었습니다.

  • 환경 및 솔루션 제약: 물리적으로는 RAID 1 구성과 단일 애플리케이션 기반의 장애 판별 구조를 가졌으며, 특히 양 서버 간의 커널 버전이 동일해야만 하는 환경적 제약이 존재했습니다.

  • 라이선스 비용 부담: 위와 같은 비효율적인 구조에도 불구하고, HA 솔루션 유지를 위한 라이선스 사용 비용이 지속적으로 발생하고 있었습니다. 성능 개선을 위한 인프라 투자 예산은 부족한 상황에서, 비효율적인 시스템 유지에 고정 비용이 지출되는 악순환이 지속되었습니다.

기존 시스템 구성도

 

02. AI가 제시한 장밋빛 설계와 전략적 인프라 구축

기존 시스템의 고질적인 가용성 문제를 해결하기 위해 AI와 협업하여 설계한 Kubernetes(K8s) 환경은 운영 효율성과 구조적 안정성을 동시에 확보한 이상적인 모델이었습니다. 단일 장애 지점(SPOF)을 제거하기 위해 다음과 같은 고도화된 설계를 반영했습니다.

  • Control-plane 고가용성(HA) 구현: 기존 1대 구성의 위험성을 탈피하여 3대의 Control-plane 클러스터를 제안받았으며, 이를 통해 특정 노드 장애 시에도 클러스터 전체의 연속성을 보장하는 복구 환경을 마련했습니다.

  • 분산 스토리지 체계 구축: 3대의 노드에 각각 고성능 SSD를 장착하고 Rook-Ceph를 도입하여, 별도의 외부 스토리지 없이도 데이터 안정성과 확장성을 확보하는 분산 스토리지 클러스터를 설계했습니다.

  • 네트워크 가용성 최적화: Ingress Controller 연결을 위한 가상 로드밸런서로 MetalLB를 선택, 서비스 전용 VIP를 통해 외부 트래픽이 안정적으로 웹 서비스에 도달할 수 있는 구조를 완성했습니다.

이러한 설계의 실현을 위해 약 350만 원의 추가 예산이 소요되었으나, 이는 장기적인 관점에서 매우 경제적이고 합리적인 선택이었습니다.

  • 압도적인 가성비 확보: 신규 서버 장비를 대량 구매하거나 고가의 상용 HA 솔루션 라이선스 유지비를 지불하는 것에 비해, 기존 자원을 활용한 RAM 증설과 SSD 추가만으로 고도화된 인프라를 구축함으로써 압도적인 비용 절감 효과를 거두었습니다.

  • MSA 환경으로의 전환: 확보된 리소스를 통해 팀의 최종 목표인 MSA(Microservices Architecture) 구조에 최적화된 개발 및 배포 환경을 실질적으로 구현할 수 있게 되었습니다.

비용적 한계를 딛고 구축된 K8s 클러스터는 서비스 단위의 정밀한 장애 판별이 가능하며, 단일 장애 지점이 없는 견고한 인프라를 지향 하였습니다. 이는 'fc-system'이 어떠한 환경에서도 중단 없이 본사와 가맹점을 잇는 핵심 교두보 역할을 수행할 수 있는 강력한 기술적 기반이 되었습니다.

 

AI와 함께 구축한 K8s 구성도

 

 

03. AI가 제시한 장밋빛 설계의 이면, '6개월 뒤의 청구서'

사례 1: K8s의 인내심이 불러온 5분의 침묵  (https://1ocate.tistory.com/8)

혼잡한 출근길, '시스템 접근 불가' 알림이 휴대폰을 가득 채웠습니다. 장애의 원인은 L2 스위치의 일시적 결함으로 인한 노드 네트워크 단절이었습니다. 하지만 기대를 모았던 K8s의 '자동 복구(Self-healing)'는 즉각 작동하지 않았고, 서비스는 5분이라는 긴 시간 동안 멈춰 있었습니다.

  • 뼈아픈 깨달음: K8s의 기본 설정은 노드 응답이 없을 때 약 300초(5분)를 기다린 후 Pod를 재배치(Eviction)합니다.

  • 실무의 간극: AI는 복구 메커니즘이라는 '논리'는 알려주었지만, 서비스 현장에서 5분이 엔지니어에게 '영겁의 시간'과 같다는 실무적 튜닝(Timeout Tuning)의 중요성은 조언해주지 않았습니다.

사례 2: 물리 법칙은 AI의 계산을 따르지 않는다

데이터가 쌓이고 서비스가 확장되자 예상치 못한 '스토리지 성능 저하'라는 청구서가 날아왔습니다. 쓰기 속도가 30MB/s에 불과한 상황에서 원인을 분석해 보니, 소프트웨어와 물리 환경의 불일치가 문제였습니다.

  • 설계의 맹점: AI와 구축한 분산 스토리지(Ceph)의 권장 사양은 10Gbps 네트워크였으나, 실제 인프라는 이에 미치지 못했습니다.
  • 물리의 한계: 네트워크 분리 등 다양한 최적화를 시도했으나, 하드웨어라는 기초 체력이 결여된 소프트웨어 설계는 결국 물리적 병목 현상에 부딪혔습니다. AI가 그린 화려한 설계도도 물리 법칙을 거스를 수는 없었습니다.

 

결론: 지름길을 걷는 엔지니어의 자세

이번 경험을 통해 AI와 협업하는 엔지니어에게 필요한 태도를 배웠습니다. AI는 제가 요청한 '기능적 요구사항'을 완벽히 만족시켰지만, 실제 운영 환경의 가혹한 변수와 물리적 한계까지 대신 고민해주지는 않았습니다.

 

만약 저에게 더 깊은 경험이 있었다면 AI의 답변 속에서 '기본값의 함정'과 '리소스의 제약'을 미리 읽어냈을 것입니다. 설계의 미숙함을 AI의 탓으로 돌리는 것은 엔지니어로서 변명이 될 수 없음을 깨달았습니다.

"AI는 목적지까지의 지름길을 제안합니다. 하지만 그 길 위의 돌덩이를 치우고, 현장에 맞는 지도를 그려나가는 것은 결국 엔지니어의 몫입니다."