13년차의 서버실

서버, 인프라, 홈랩 기술 블로그

[태그:] 인프라 운영

  • [보안] 방화벽 설정, 이것만은 꼭! 10가지 필수 점검 항목

    [보안] 방화벽 설정, 이것만은 꼭! 10가지 필수 점검 항목

    [보안] 방화벽 설정, 이것만은 꼭! 10가지 필수 점검 항목

    서버를 올리고 포트만 열어둔 뒤 불안했던 경험, 아마 한 번쯤 있으실 겁니다. 저도 홈랩에서 테스트 서버를 굴리다가 방화벽 설정을 대충 해두고 넘어갔다가 나중에 로그를 보고 식은땀을 흘린 적이 있거든요. 방화벽 설정은 단순히 포트를 열고 닫는 작업이 아니라, 네트워크 보안의 기본선(baseline, 최소 보안 기준)을 만드는 일입니다. 이번 글에서는 실무와 홈랩에서 반복해서 확인하는 방화벽 보안 체크리스트 중심으로, 꼭 봐야 할 필수 점검 항목 10가지를 정리해보겠습니다.

    특히 이 글은 “방화벽 설정 후 뭘 먼저 확인해야 하지?” 하고 막막하신 분들을 위해 썼습니다. Linux 서버 기준 예시를 넣겠지만, 원칙 자체는 온프레미스(on-premise, 사내 구축 환경), 클라우드, 가상화 환경 모두에 그대로 적용됩니다.

    방화벽 설정이 적용된 홈랩 네트워크 아키텍처 이미지

    방화벽 설정 점검 항목이 DMZ, 내부망, 관리망으로 나뉘어 보이는 전체 개요 이미지입니다.

    1. 왜 방화벽 설정 점검은 항상 사고 전에 해야 할까요

    방화벽(Firewall, 트래픽을 제어하는 보안 장치)은 평소엔 조용합니다. 그래서 더 무섭습니다. 문제가 생기기 전까지는 존재감이 없거든요. 그런데 실제 장애나 침해사고 대응에서는 거의 항상 “이 포트 왜 열려 있었지?”, “관리 포트가 왜 외부에 노출됐지?” 같은 질문이 나옵니다.

    제가 직접 경험해보니 방화벽 설정 검토는 잘한 티는 안 나는데, 한 번 놓치면 문제가 됩니다. 특히 다음 상황에서 실수가 많이 나옵니다.

    • 테스트 서버를 운영 서버처럼 오래 끌고 갔을 때
    • 임시 오픈한 포트를 닫지 않았을 때
    • 소스 IP 제한 없이 관리 포트를 공개했을 때
    • 클라우드 보안 그룹(Security Group, 가상 방화벽)과 OS 방화벽 정책이 따로 놀 때

    여기서 중요한 포인트는 이것입니다: 방화벽은 “설정해뒀다”보다 “지금도 맞는 상태인지 확인하는 것”이 더 중요합니다.

    2. 좋은 방화벽 설정의 기본 원칙

    좋은 방화벽 설정은 결국 한 문장으로 정리됩니다: 필요한 통신만 허용하고, 나머지는 기본 차단(Default Deny, 기본 거부)하는 상태입니다. 이 원칙 하나만 제대로 잡아도 절반은 갑니다.

    방화벽 설정 점검 기준은 세 가지로 보면 편합니다.

    1. 누가 들어오나: 소스 IP, 네트워크 대역
    2. 어디로 들어오나: 목적지 포트, 서비스
    3. 왜 열어두나: 실제 업무 필요성, 운영 근거

    결국 방화벽 설정은 ACL(Access Control List, 접근 제어 목록)을 얼마나 명확하게 관리하느냐의 문제더라고요. “웹 서비스라서 80/443 허용”, “운영자만 SSH 22 접근”, “DB 3306은 앱 서버만 허용” 이런 식으로요.

    3. 방화벽 설정 점검 체크리스트: 필수 10가지 항목

    아래 10가지는 제가 서버 오픈 전에 거의 습관처럼 확인하는 필수 점검 항목입니다. 이 순서로 보면 빠르고, 빠뜨릴 것도 줄어듭니다.

    항목 무엇을 확인하나 핵심 이유
    1 기본 정책(Default Policy) 미정의 트래픽 차단
    2 허용 포트 최소화 공격 표면 축소
    3 관리 포트 접근 제한 SSH, RDP 등 보호
    4 소스 IP 대역 제한 불필요한 외부 접근 차단
    5 인바운드/아웃바운드 구분 양방향 정책 명확화
    6 불필요한 Any 허용 제거 과도한 허용 방지
    7 로그 활성화 추적과 감사 가능
    8 규칙 우선순위 확인 예상과 다른 매칭 방지
    9 예외 정책 문서화 운영 지속성 확보
    10 검증 명령과 정기 점검 설정 드리프트 방지

    보안 체크리스트는 화려할 필요 없습니다. 대신 반복 가능해야 합니다. 그리고 누가 봐도 같은 결론이 나와야 합니다.

    10가지 필수 항목을 짧게 풀어보면

    • 기본 정책은 deny: 허용보다 차단을 기본값으로 둡니다.
    • 포트는 최소한만: 서비스와 무관한 포트는 닫습니다.
    • 관리 포트는 외부 전체 공개 금지: Bastion(배스천, 중계 관리 서버)이나 VPN 뒤로 넣는 게 좋습니다.
    • 소스 제한: 가능하면 특정 사무실 IP나 관리망만 허용합니다.
    • 아웃바운드도 본다: 내부 서버가 외부로 아무 데나 나가는 것도 위험할 수 있습니다.
    • Any-Any 규칙 제거: 편하지만 위험합니다. 저도 급할 때 열었다가 나중에 후회했었습니다.
    • 로그는 꼭 남긴다: 침해 대응의 시작점입니다.
    • 우선순위 확인: 먼저 걸리는 규칙 때문에 뒤 규칙이 무의미해질 수 있습니다.
    • 예외는 기록: 왜 열었는지 안 적어두면 몇 달 뒤 아무도 모릅니다.
    • 정기 검증: 월 1회만 해도 효과가 큽니다.

    4. 실전 구현: Linux 서버의 방화벽 설정 기본

    여기서는 Ubuntu 계열에서 많이 쓰는 UFW(Uncomplicated Firewall, 간단 방화벽 관리 도구) 기준으로 보여드리겠습니다. 환경에 따라 nftables(리눅스 패킷 필터 프레임워크)나 iptables(전통적 패킷 필터)를 쓰실 수도 있는데, 원칙은 같습니다.

    1. 현재 열려 있는 서비스와 포트를 먼저 확인합니다.
    2. 기본 정책을 설정합니다.
    3. 서비스별 허용 규칙을 최소 권한으로 추가합니다.
    4. 로그와 검증을 수행합니다.
    ss -tulpn
    sudo ufw status verbose
    sudo ufw default deny incoming
    sudo ufw default allow outgoing
    sudo ufw allow 80/tcp
    sudo ufw allow 443/tcp
    sudo ufw allow from 203.0.113.10 to any port 22 proto tcp
    sudo ufw logging on
    sudo ufw enable
    sudo ufw status numbered

    위 예시는 정말 기본형입니다. 웹 서버라면 80/443만, SSH는 관리 IP에서만 허용하는 식이죠. 실제로 써보니까 처음부터 이렇게 보수적으로 잡는 게 나중에 훨씬 편하더라고요.

    서비스별 방화벽 설정 기준

    서비스 권장 접근 방식 비고
    SSH 특정 관리 IP만 허용 가능하면 VPN 뒤에서 접근
    HTTP/HTTPS 외부 공개 허용 리버스 프록시 뒤 구성 가능
    DB 포트 앱 서버 IP만 허용 인터넷 직접 공개 지양
    모니터링 포트 관리망만 허용 Prometheus 등 내부 수집 권장
    방화벽 설정에서 허용 포트를 구분한 서버 구성 이미지

    웹 포트와 관리 포트가 구분되어 보이는 실전 방화벽 설정 예시 이미지입니다.

    5. 더 실무적으로: 인바운드와 아웃바운드를 함께 점검하세요

    많이 놓치는 부분이 아웃바운드(Outbound, 서버에서 외부로 나가는 트래픽)입니다. 인바운드만 막아두면 끝이라고 생각하기 쉬운데, 실제 운영에서는 그렇지 않거든요. 만약 서버가 침해당했다면 외부 C2(Command and Control, 원격 제어 서버)와 통신을 시도할 수도 있습니다.

    그래서 저는 최소한 아래는 꼭 봅니다.

    • 패키지 저장소, 시간 동기화, 외부 API 등이 꼭 필요한 목적지인지
    • 내부 서버가 임의 포트로 외부에 나가고 있지 않은지
    • 백업, 모니터링, 알림 전송 경로가 정책과 충돌하지 않는지

    예를 들어 DB 서버는 인터넷으로 직접 나갈 이유가 거의 없습니다. 그런 서버는 아웃바운드 정책도 보수적으로 잡는 편이 낫습니다.

    sudo ufw default deny outgoing
    sudo ufw allow out 53
    sudo ufw allow out 123/udp
    sudo ufw allow out 443/tcp
    sudo ufw status verbose

    물론 이렇게 하면 처음엔 업데이트나 에이전트 통신이 막혀서 좀 삽질했습니다. ㅎㅎ 그래서 운영 서버에 바로 적용하기보다는, 먼저 필요한 통신 목록부터 뽑아보시는 걸 추천드립니다.

    6. 규칙 우선순위, 로그, 문서화: 운영 품질을 갈라놓는 세 가지

    방화벽 설정이 당장은 맞아 보여도, 시간이 지나면 예외 규칙이 늘어나면서 복잡해집니다. 그때 진짜 차이가 나는 게 규칙 우선순위(rule order), 로그(logging), 문서화(documentation)입니다.

    규칙 우선순위 확인하기

    특히 iptables나 클라우드 ACL에서는 먼저 매칭된 규칙이 적용되는 경우가 많습니다. 그래서 아래처럼 번호나 순서를 보고 정리해야 합니다.

    sudo ufw status numbered

    분명 차단 규칙을 넣었는데 접속이 되는 경험 있으신가요? 나중에 보면 위쪽에 더 넓은 허용 규칙이 먼저 있더라고요. 저도 처음엔 꽤 헷갈렸습니다.

    로그는 최소한 이 정도는 남기세요

    • 거부된 접속 시도
    • 관리 포트 접근 시도
    • 비정상적으로 반복되는 스캔 패턴

    로그가 있어야 Fail2ban 같은 자동 방어 도구를 붙이기도 쉽고, 나중에 보안 체크리스트 점검 결과를 설명하기도 편합니다.

    예외 정책은 꼭 기록하세요

    예를 들어 “협력사 고정 IP에서만 임시 허용, 만료일은 2026-08-03” 같은 걸 남겨야 합니다. 안 그러면 임시가 영구가 됩니다. 이거 진짜 자주 봅니다.

    방화벽 설정 결과를 모니터링하는 네트워크 보안 대시보드 이미지

    차단 로그와 관리 포트 접근 시도가 보이는 결과 검증용 모니터링 이미지입니다.

    7. ⚠️ 실제로 겪었던 문제들: 방화벽 트러블슈팅 포인트

    실무든 홈랩이든 방화벽 설정에서 가장 무서운 건 “서비스를 보호하려다가 내가 못 들어가는 상황”입니다. 저도 원격지 장비에서 SSH를 제 손으로 막아본 적 있습니다. “드디어 됐다!” 하고 나갔는데 다시 접속이 안 되더라고요.

    자주 겪는 문제 1: SSH를 너무 빨리 막음

    해결 방법은 간단합니다: 현재 접속 중인 세션을 유지한 상태에서 새 세션으로 재접속 테스트를 먼저 하세요.

    sudo ufw allow from 203.0.113.10 to any port 22 proto tcp
    ssh user@server-ip

    새 세션 접속이 확인되기 전에는 기존 세션을 끊지 않는 게 안전합니다.

    자주 겪는 문제 2: 클라우드 방화벽과 OS 방화벽이 충돌

    AWS Security Group, GCP VPC Firewall, Azure NSG 같은 상위 정책과 OS 내부 정책이 둘 다 있으면, 어디서 막히는지 헷갈립니다. 이런 경우는 아래 순서로 확인하면 됩니다.

    1. 클라우드 보안 그룹에서 허용 여부 확인
    2. OS 방화벽에서 동일 포트 허용 여부 확인
    3. 서비스 데몬이 실제로 Listen(포트 대기) 중인지 확인
    4. 라우팅과 NAT(Network Address Translation, 주소 변환) 경로 확인
    ss -tulpn
    sudo ufw status verbose
    ip addr
    ip route

    자주 겪는 문제 3: IPv4만 보고 끝냄

    이 부분도 은근히 놓칩니다. IPv6이 활성화된 환경이라면 IPv4 규칙만 보고 안심하면 안 됩니다. 방화벽 설정 점검 시 IPv6 정책도 같이 봐야 합니다.

    8. 검증 방법: 설정했으면 반드시 확인하세요

    보안은 추측으로 끝내면 안 됩니다. 설정 후에는 꼭 검증해야 합니다. 저는 보통 서버 내부 확인과 외부 확인을 나눠서 봅니다.

    서버 내부에서 확인

    sudo ufw status verbose
    sudo ufw status numbered
    ss -tulpn
    • 열려 있어야 하는 포트만 열려 있는지
    • 허용 대상 IP가 의도와 맞는지
    • 기본 정책이 incoming deny인지

    외부에서 확인

    nc -vz server-ip 22
    nc -vz server-ip 80
    nc -vz server-ip 443

    관리 PC에서는 열려야 하고, 허용되지 않은 위치에서는 막혀야 정상입니다. 이 차이를 직접 확인해보면 훨씬 마음이 놓입니다.

    방화벽 설정 검증 체크리스트

    1. 기본 정책이 차단 중심인지 확인
    2. 불필요한 포트가 남아 있지 않은지 확인
    3. 관리 포트가 특정 IP로 제한됐는지 확인
    4. 로그가 남고 있는지 확인
    5. 예외 정책이 문서화됐는지 확인

    이 정도만 해도 네트워크 보안 수준이 꽤 안정됩니다. 화려한 장비보다 이런 기본기가 훨씬 오래 갑니다.

    방화벽 설정 필수 점검 항목을 요약한 네트워크 보안 이미지

    점검 전후 차이와 필수 점검 항목 10가지를 한눈에 보여주는 요약 이미지입니다.

    9. 정리: 방화벽 설정은 결국 운영 습관입니다

    정리하면 방화벽 설정의 핵심은 세 가지입니다: 기본 차단, 최소 허용, 지속 검증. 사실 특별한 비법은 없습니다. 대신 귀찮아도 반복해야 합니다. 저도 처음엔 규칙 몇 개 넣고 끝내려 했었는데, 시간이 지나 보니 결국 방화벽 보안 체크리스트를 얼마나 성실하게 돌리느냐가 차이를 만들더라고요.

    다음 글에서는 홈랩 기준으로 리버스 프록시(역방향 프록시)와 방화벽을 함께 구성하는 방법도 다뤄볼 예정입니다. 이전 글에서 다뤘던 로그 모니터링 내용과 연결해서 보시면 더 이해가 쉬우실 겁니다.

    자주 묻는 질문

    Q. 방화벽 설정은 서버마다 다르게 해야 하나요?
    네, 서비스 역할이 다르면 달라져야 합니다. 웹 서버, DB 서버, 모니터링 서버는 필요한 포트와 접근 주체가 다르거든요.

    Q. 클라우드 보안 그룹만 있으면 OS 방화벽은 안 써도 되나요?
    환경에 따라 다르지만, 저는 이중으로 두는 편입니다. 방어 계층(다층 방어)이 생기기 때문입니다.

    Q. 제일 먼저 바꿔야 할 한 가지는 뭔가요?
    기본 정책을 정리하고, SSH 같은 관리 포트의 소스 IP 제한부터 거세요. 체감 효과가 가장 큽니다.

    마지막으로 한 줄만 드리면, 방화벽 설정은 한 번 잘해두는 작업이 아니라 계속 점검하는 운영 루�ine입니다. 오늘 서버 한 대라도 체크리스트대로 다시 보시면 분명 놓친 게 하나쯤은 보일 겁니다.

  • [Linux] rsyslog Loki 마이그레이션: 레거시 로그 시스템 현대화 경험

    [Linux] rsyslog Loki 마이그레이션: 레거시 로그 시스템 현대화 경험

    rsyslog Loki 마이그레이션 경험: 레거시 로그 시스템 현대화

    운영 서버가 늘어나면 로그가 제일 먼저 말을 걸어옵니다. 처음엔 rsyslog 하나로도 잘 굴러가거든요. 파일로 남기고, 필요한 서버로 포워딩하고, 급하면 grep으로 뒤지면 되니까요. 그런데 장애가 길어지고 서버 수가 늘어나면 이야기가 달라집니다. 이번 글은 제가 실제로 진행했던 rsyslog Loki 마이그레이션 경험을 바탕으로, 레거시 로그 시스템을 어떻게 현대화했는지 정리한 내용입니다.

    먼저 현재 시점 기준으로 짚고 갈 점이 하나 있습니다. Promtail은 2026년 3월 2일부로 EOL(지원 종료) 상태라서, 신규 구축이라면 Grafana Alloy도 함께 검토하는 게 맞습니다. 다만 이미 rsyslog와 Promtail을 쓰고 있거나, 단계적으로 Loki로 옮겨야 하는 환경이라면 이 글의 접근은 여전히 꽤 현실적이더라고요. 특히 리눅스 로그 관리, 중앙 집중식 로그, 그리고 조회 동선 단축이 고민이라면 더 그렇습니다.

    저도 처음엔 "rsyslog 잘 돌아가는데 굳이 바꿔야 하나?" 싶었습니다. 막상 옮겨보니 검색성, 라벨(label, 분류용 메타데이터), 대시보드 연동이 확실히 다르더라고요. 반대로 아무 생각 없이 옮기면 기존 syslog 습관 때문에 삽질도 꽤 합니다. 여기서 중요한 포인트는 한 번에 뒤엎지 말고, 수집 계층과 조회 계층을 분리해서 천천히 옮기는 것입니다.

    rsyslog Loki 마이그레이션 전체 아키텍처 다이어그램

    기존 rsyslog 기반 수집과 Promtail, Loki, Grafana가 어떻게 연결되는지 한눈에 보여주는 아키텍처 이미지입니다.

    왜 rsyslog만으로는 점점 버거워졌을까

    rsyslog는 여전히 아주 좋은 도구입니다. 특히 Syslog 생태계에서는 검증이 끝난 축에 가깝습니다. 문제는 "수집은 잘하는데, 분석과 검색은 별도 고민이 필요하다"는 점입니다. 서버 수가 늘고 장애가 복합적으로 얽히기 시작하면, 그 차이가 생각보다 크게 느껴집니다.

    • 서버별 로그 파일 위치가 제각각이면 장애 때 동선이 길어집니다.
    • 포워딩만 해두고 검색 체계가 약하면 결국 SSH 접속 후 grep에 의존하게 됩니다.
    • 애플리케이션 로그와 시스템 로그를 함께 보려면 포맷 통일이 필요합니다.
    • 운영자가 바뀌거나 시간이 지나면 "어디에 뭐가 쌓이는지" 문서보다 실서버가 더 진실이 됩니다.

    제가 겪었던 가장 큰 문제는 장애 시점 상관관계(correlation, 연관 분석)가 너무 느렸다는 점이었습니다. 예를 들어 웹 서버에서 502가 튀고, 뒤에서 인증 서비스가 지연되고, 같은 시간대에 커널 메시지까지 흔들리면 이걸 시간축으로 모아봐야 하거든요. rsyslog만으로 불가능한 건 아니지만, 편하게 하기는 어렵습니다. 그래서 결론은 명확했습니다. 수집은 rsyslog의 장점을 활용하고, 조회와 분석은 Loki 쪽으로 넘기자. 이게 제가 정리한 rsyslog Loki 마이그레이션의 핵심 방향이었습니다.

    rsyslog Loki 마이그레이션에서 Loki와 Promtail을 어떻게 볼까

    쉽게 말해 Loki는 로그 저장소이자 검색 엔진 역할을 하고, Promtail은 로그를 모아서 Loki로 보내는 에이전트입니다. Prometheus가 메트릭을 다루듯이, Loki는 로그를 라벨 기반으로 다루는 느낌이라고 보시면 됩니다. 다만 2026년 기준으로는 Promtail보다 Grafana Alloy가 앞으로의 기본 경로라는 점은 꼭 같이 기억하셔야 합니다.

    구성요소 역할 마이그레이션에서의 포인트
    rsyslog 로그 수집, 필터링, 포워딩 기존 서버 설정을 최대한 유지하면서 다음 수집 계층으로 전달
    Promtail 로그 수신 또는 파일 테일링 기존 환경에서 syslog 수신 지점 또는 파일 수집 지점으로 활용 가능
    Loki 로그 저장 및 질의 라벨 설계가 성패를 좌우
    Grafana 조회, 대시보드, 탐색 운영자가 가장 체감하는 개선 지점
    Grafana Alloy 차세대 수집 에이전트 신규 구축이나 장기 운영 기준으로 우선 검토

    많이 헷갈리는 부분이 하나 있습니다. "Promtail이 파일만 읽는 거 아니었나?" 저도 처음엔 그렇게 생각했었습니다. 그런데 Promtail은 Syslog Receiver 설정도 지원합니다. 그래서 기존 rsyslog가 잘 깔려 있다면, rsyslog가 TCP로 Promtail에 넘기고 Promtail이 Loki로 적재하는 구조가 꽤 현실적입니다. 이 방식이 좋은 이유는 레거시 환경을 한 번에 뜯어고치지 않아도 되기 때문입니다.

    마이그레이션 설계: 한 번에 바꾸지 말고 두 단계로

    제가 추천드리는 방식은 아래 순서입니다. 이 흐름이 rsyslog Loki 마이그레이션에서 제일 덜 아프더라고요.

    1. 1단계: 기존 rsyslog는 유지하고, Promtail 또는 Alloy를 syslog 수신기로 세웁니다.
    2. 2단계: Grafana에서 검색과 대시보드를 검증한 뒤, 필요한 서버부터 파일 수집이나 구조화 로그로 확장합니다.

    이렇게 하면 롤백도 쉽습니다. 장애가 나도 rsyslog는 원래 하던 일을 계속하니까요. 운영에서는 이 안정감이 정말 큽니다.

    rsyslog Loki 마이그레이션 2단계 전환 구성도

    기존 rsyslog를 유지한 채 Promtail을 앞단 수신기로 추가하고, 이후 Loki 조회 환경을 점진적으로 확장하는 전환 방식입니다.

    권장 아키텍처

    • 애플리케이션/시스템 로그 발생
    • 로컬 rsyslog가 표준 syslog 포맷으로 정리
    • rsyslog가 TCP로 Promtail에 전달
    • Promtail이 라벨을 붙여 Loki로 전송
    • Grafana에서 검색, 필터링, 시각화

    중요한 포인트! 라벨은 많이 붙인다고 좋은 게 아닙니다. host, job, facility 정도처럼 조회에 꼭 필요한 축만 먼저 가져가세요. 처음부터 프로그램명, PID, path, 환경명, 팀명, 서비스명까지 다 라벨로 올리면 쿼리보다 라벨 관리가 더 힘들어집니다.

    실전 구현: rsyslog에서 Loki로 넘기는 기본 구성

    이제 실제 설정입니다. 아래 예시는 "Promtail이 syslog를 받고 Loki에 넣는 구성"입니다. 이미 Loki, Grafana, Promtail 서비스가 준비되어 있다는 전제로 적겠습니다. 설치 방식은 배포판 패키지, 바이너리, 컨테이너 등 환경마다 다르니 여기서는 마이그레이션 구성 자체에 집중하겠습니다.

    1. Promtail 설정 준비

    Promtail 설정에는 positions 파일이 자주 등장합니다. 파일 테일링이나 journal 수집에서는 어디까지 읽었는지 기억하는 데 중요하거든요. 다만 이 글처럼 syslog receiver만 쓰는 경로라면 중복 수집 방지의 핵심은 positions 파일보다 수집 경로 분리와 송신 설계에 있습니다. 이 부분은 저도 초반에 헷갈렸습니다.

    sudo mkdir -p /etc/promtail
    sudo mkdir -p /var/lib/promtail
    sudo chown -R promtail:promtail /var/lib/promtail

    다음은 Promtail 설정 예시입니다.

    server:
      http_listen_port: 9080
      grpc_listen_port: 0
    
    positions:
      filename: /var/lib/promtail/positions.yaml
    
    clients:
      - url: http://loki.example.internal:3100/loki/api/v1/push
    
    scrape_configs:
      - job_name: syslog
        syslog:
          listen_address: 0.0.0.0:1514
          listen_protocol: tcp
          idle_timeout: 60s
          label_structured_data: true
          labels:
            job: syslog
        relabel_configs:
          - source_labels: ['__syslog_message_hostname']
            target_label: host
          - source_labels: ['__syslog_message_app_name']
            target_label: app
          - source_labels: ['__syslog_message_severity']
            target_label: severity

    여기서 제가 실제로 많이 썼던 건 relabel_configs입니다. syslog 헤더에서 넘어온 값을 바로 host, app 같은 라벨로 바꿔주면 Grafana 탐색이 훨씬 편해집니다. 처음엔 라벨 이름을 제 멋대로 만들다가 쿼리 통일이 안 돼서 다시 정리했었는데, 운영팀 여러 명이 같이 볼 거면 naming rule부터 맞춰두는 게 좋습니다.

    2. rsyslog에서 Promtail로 포워딩

    rsyslog는 omfwd 모듈로 Promtail 쪽으로 보낼 수 있습니다. TCP를 권장하는 이유는 운영에서 안정성이 더 좋기 때문입니다. UDP는 편하지만 장애 상황에서 조용히 놓치는 메시지가 생기면 답답하더라고요. 특히 Promtail 쪽은 RFC5424 계열 syslog 포맷과 octet-counted framing 조합이 가장 무난했습니다.

    # /etc/rsyslog.d/90-promtail.conf
    *.* action(
      type="omfwd"
      protocol="tcp"
      target="promtail.example.internal"
      port="1514"
      Template="RSYSLOG_SyslogProtocol23Format"
      TCP_Framing="octet-counted"
      KeepAlive="on"
      queue.type="linkedList"
    )

    queue.type="linkedList"를 넣은 이유도 꼭 짚고 넘어가야 합니다. 원격 수신기가 잠깐 죽거나 네트워크가 흔들릴 때, 큐가 없으면 송신 쪽이 막히거나 손실을 체감하기 쉬워집니다. 다만 운영 환경에 따라 디스크 큐나 재시도 옵션까지 더 챙겨야 할 수 있으니, 중요한 서비스라면 여기서 한 번 더 보수적으로 잡는 걸 권합니다.

    3. 설정 검증과 서비스 재시작

    설정 파일을 넣었다고 바로 끝은 아닙니다. 문법 검사를 먼저 하고, 서비스 상태를 짧게라도 확인해야 뒤탈이 적습니다. 이 단계에서 1분만 더 써도 나중에 1시간 덜 헤매더라고요.

    sudo rsyslogd -N1
    sudo systemctl restart rsyslog
    sudo systemctl restart promtail
    sudo systemctl status rsyslog --no-pager
    sudo systemctl status promtail --no-pager

    rsyslog는 재시작 전에 rsyslogd -N1로 문법 검사를 꼭 하세요. 이거 안 하고 바로 재시작했다가 로그 수집 전체가 멈추면 진짜 식은땀 납니다.

    4. 테스트 로그 보내기

    테스트는 꼭 단순해야 합니다. logger 한 줄로 시작하세요. 괜히 복잡한 애플리케이션 로그부터 확인하면 어디서 막혔는지 추적이 어렵습니다.

    logger -t migration-test "rsyslog to promtail to loki test message"
    curl -s http://127.0.0.1:9080/ready
    curl -s http://loki.example.internal:3100/ready

    여기서 ready 응답이 나온다고 끝난 건 아닙니다. 실제로 Grafana Explore에서 라벨이 원하는 대로 붙는지까지 봐야 합니다. 운영에서는 이 마지막 한 단계가 제일 중요하더라고요.

    Promtail 활용과 rsyslog 전달 설정 구성 이미지

    Promtail의 syslog 수신 설정과 rsyslog의 omfwd 전달 관계를 시각적으로 정리한 구성 이미지입니다.

    ⚠️ 실제로 많이 겪는 문제와 해결 방법

    여기부터가 진짜 운영 이야기입니다. 문서만 보면 금방 끝날 것 같았는데, 저는 여기서 시간을 꽤 썼습니다. rsyslog Loki 마이그레이션은 개념보다 디테일에서 더 많이 막히더라고요.

    1. 메시지는 들어오는데 라벨이 예상과 다를 때

    Promtail이 syslog 헤더를 내부 라벨로 들고 오는데, relabel_configs에서 이름을 잘못 참조하면 Grafana에서 host가 비어 보일 수 있습니다. 이 경우는 대부분 입력값 이름을 잘못 쓴 겁니다. 예를 들어 hostname, app-name 같은 식으로 감으로 쓰면 안 되고, Promtail이 제공하는 내부 라벨 이름을 기준으로 맞춰야 합니다.

    • host가 비면 __syslog_message_hostname 확인
    • 앱 이름이 비면 __syslog_message_app_name 확인
    • 심각도가 안 잡히면 __syslog_message_severity 확인

    2. rsyslog는 보냈다고 하는데 Promtail에서 안 받을 때

    이건 네트워크와 포맷 두 가지를 같이 보셔야 합니다. TCP 포트가 열려 있는지 먼저 확인하고, 그다음 syslog 포맷을 맞춰야 합니다. 저도 한 번은 포트는 맞게 열어두고 템플릿을 기본값으로 둬서 Promtail 파싱이 애매하게 꼬인 적이 있었습니다. 그 뒤로는 RSYSLOG_SyslogProtocol23Format을 먼저 의심합니다.

    ss -lntp | grep 1514
    sudo journalctl -u promtail -n 50 --no-pager
    sudo journalctl -u rsyslog -n 50 --no-pager

    3. 중복 수집이 생길 때

    이 부분도 자주 나옵니다. 기존에 파일 테일링과 syslog 포워딩을 동시에 물려두면 같은 로그가 두 번 들어갈 수 있습니다. 특히 /var/log/messages를 Promtail이 읽고 있는데, 같은 메시지를 rsyslog가 또 syslog receiver로 보내면 조회 화면에서 두 줄로 보여요. 처음엔 "Loki가 복제했나?" 싶었는데 아니더라고요. 수집 경로를 한 로그 소스당 하나로 정리해야 합니다.

    4. 라벨을 너무 많이 붙여서 쿼리가 무거워질 때

    라벨은 검색에 좋지만, 남발하면 관리 포인트가 폭증합니다. 저는 초기에 프로그램명, 파일경로, 환경명, 인스턴스명, 팀명까지 다 넣었다가 나중에 정리하느라 더 힘들었습니다. 운영에서 오래 가는 구성은 의외로 단순합니다.

    항목 처음 욕심낸 구성 지금 추천하는 구성
    host 사용 사용
    job 사용 사용
    app 사용 선택적 사용
    path 라벨로 사용 가급적 지양
    pid 라벨로 사용 지양
    team/env 모두 라벨화 정말 필요한 것만

    검증: rsyslog Loki 마이그레이션이 제대로 끝났는지 확인하는 방법

    설정이 끝났다고 바로 성공은 아닙니다. 운영에서는 "수집된다"보다 "원하는 방식으로 검색된다"가 더 중요합니다. 저는 아래 체크리스트로 마이그레이션 완료 여부를 봤습니다.

    1. 테스트 메시지가 Loki에 들어오는지 확인
    2. host 라벨로 서버별 필터링이 되는지 확인
    3. 같은 시간대 다른 서버 로그를 한 화면에서 비교 가능한지 확인
    4. 기존 rsyslog 경로와 신규 Loki 경로 결과가 크게 어긋나지 않는지 샘플 비교
    5. 장애 상황에서 운영자가 SSH보다 Grafana를 먼저 열게 되는지 확인

    Grafana Explore에서는 보통 이런 식으로 보기 시작했습니다.

    {job="syslog",host="web-01"}
    {job="syslog",app="nginx"}
    {job="syslog",severity="err"}

    드디어 원하는 대로 host 기준으로 잘 걸리고, 애플리케이션별로도 묶이기 시작하면 그때부터 체감이 옵니다. "아, 이제 장애 볼 때 여기부터 보면 되겠구나" 하는 느낌이요. 이거 진짜 편하더라고요.

    Grafana Loki에서 중앙 집중식 로그를 검색하는 결과 화면

    Grafana Explore에서 host, app, severity 라벨로 로그를 필터링하고 시간축으로 비교하는 결과 화면 이미지입니다.

    마이그레이션 이후 운영 방식이 어떻게 바뀌었나

    가장 큰 변화는 로그 확인 동선이 짧아졌다는 점입니다. 예전에는 "어느 서버지? 어떤 파일이지? 압축됐나? rotate됐나?"부터 시작했는데, 지금은 일단 Grafana에서 시간대와 호스트를 좁혀보고 필요할 때만 서버에 들어갑니다. 중앙 집중식 로그 체계의 장점이 여기서 확실히 보입니다.

    • 장애 초동 대응 속도가 빨라집니다.
    • 서버별 로그 위치를 전부 외우지 않아도 됩니다.
    • 운영 인수인계가 쉬워집니다.
    • 애플리케이션 로그와 시스템 로그를 함께 보기 편해집니다.

    물론 단점도 있습니다. Loki 쪽 저장 정책, 라벨 설계, 대시보드 표준화는 결국 운영팀이 책임져야 합니다. 그래서 저는 마이그레이션을 "도구 교체"보다 운영 습관 교정에 가깝게 봅니다. 혹시 지금도 grep과 SSH에 너무 의존하고 계신가요? 그렇다면 rsyslog를 버리라는 뜻이 아니라, 조회 계층만이라도 현대화해보시라고 말씀드리고 싶네요.

    정리와 다음 단계

    rsyslog Loki 마이그레이션은 생각보다 거창한 프로젝트가 아닐 수도 있습니다. 핵심은 rsyslog를 적으로 보지 않는 겁니다. 기존 수집 안정성은 살리고, Promtail 활용 또는 Alloy 전환을 통해 Loki에 연결해서 검색 경험을 개선하면 됩니다. 제가 직접 해보니 한 번에 완벽하게 옮기려는 순간부터 어려워지더라고요. 반대로 syslog receiver 하나 붙이고, 라벨 몇 개만 정리해도 금방 효과가 납니다.

    정리하면 이렇습니다.

    • 수집은 보수적으로: 기존 rsyslog를 유지합니다.
    • 조회는 현대적으로: Loki와 Grafana로 검색 동선을 줄입니다.
    • 라벨은 절제해서: host, job 같은 핵심부터 시작합니다.
    • 중복 수집은 반드시 제거: 파일 테일링과 syslog 전달 경로를 겹치지 않게 합니다.

    다음 글에서는 Loki 쿼리 정리와 라벨 설계 실전, 그리고 systemd-journald와 함께 가져갈 때 어떤 점을 조심해야 하는지 다뤄볼 예정입니다. 블로그의 이전 글에서 다뤘던 로그 로테이션 설계 내용과 연결해서 보시면 흐름이 더 잘 잡히실 거예요.

    rsyslog와 Loki 기반 로그 시스템 현대화 비교 인포그래픽

    레거시 rsyslog 중심 운영과 Loki 기반 현대화 운영의 차이를 요약 비교한 인포그래픽 이미지입니다.

    자주 묻는 질문

    Q1. rsyslog를 완전히 없애야 하나요?

    아닙니다. 많은 환경에서 rsyslog는 여전히 좋은 전처리와 전달 계층입니다. 저도 처음엔 완전 교체를 고민했는데, 실제로는 공존 전략이 훨씬 안정적이었습니다.

    Q2. Promtail은 파일만 읽는 도구인가요?

    아닙니다. syslog 수신 구성도 가능합니다. 다만 현재는 Promtail이 EOL이라서, 새로 시작하는 환경이라면 Grafana Alloy를 먼저 검토하는 편이 맞습니다.

    Q3. 처음부터 구조화 로그(JSON)를 강제해야 하나요?

    꼭 그렇지는 않습니다. 저는 먼저 중앙 수집과 조회 체계를 만들고, 그다음 서비스별로 구조화 로그를 넓혀갔습니다. 순서를 잘 잡는 게 중요합니다.

    Q4. 가장 먼저 챙길 검증 포인트는 뭔가요?

    중복 수집 여부와 라벨 품질입니다. 로그가 들어오는 것만 보면 반쪽 성공입니다. 검색이 잘 되어야 진짜 성공이거든요.

  • [Linux] CentOS 7에서 AlmaLinux 9로: 성공적인 서버 마이그레이션 전략과 실제 경험

    [Linux] CentOS 7에서 AlmaLinux 9로: 성공적인 서버 마이그레이션 전략과 실제 경험

    [Linux] CentOS 7에서 AlmaLinux 9로: 성공적인 서버 마이그레이션 전략과 실제 경험

    CentOS 7 AlmaLinux 9 마이그레이션 이야기가 요즘 정말 많이 나옵니다. 이유는 단순합니다. CentOS 7 EOL(End of Life, 기술지원 종료)이 이미 현실이 됐기 때문이거든요. 기존에 잘 돌아가던 서버라도 보안 업데이트가 끊기면 운영 입장에서는 그냥 두기 어렵습니다. 저도 홈랩과 업무 환경에서 비슷한 상황을 여러 번 겪었는데, 처음엔 “OS만 바꾸면 끝 아닌가?” 싶었다가 생각보다 체크할 게 많아서 삽질 좀 했습니다 ㅎㅎ

    특히 이번 글은 CentOS 7에서 AlmaLinux 9로 바로 점프하는 상황을 기준으로 정리했습니다. 결론부터 말씀드리면, 저는 이런 경우 인플레이스 업그레이드(in-place upgrade, 현재 서버를 그대로 올리는 방식)보다 병행 구축 후 이전(side-by-side migration, 새 서버를 만들고 데이터와 서비스를 옮기는 방식)을 훨씬 더 추천합니다. 실제로 써보니까 이 방식이 훨씬 덜 위험하더라고요.

    CentOS 7 AlmaLinux 9 마이그레이션 전체 아키텍처 다이어그램

    기존 CentOS 7 서버, 신규 AlmaLinux 9 서버, 데이터 동기화, 검증, DNS 또는 로드밸런서 전환 흐름을 한눈에 보여주는 개요 이미지입니다.

    1. 왜 CentOS 7 AlmaLinux 9 마이그레이션이 중요한가

    쉽게 말해 운영체제는 서버의 바닥입니다. 애플리케이션이 아무리 멀쩡해도 바닥이 낡으면 문제가 생깁니다. CentOS EOL 이후에는 보안 패치, 버그 수정, 생태계 호환성 측면에서 점점 불리해집니다. 지금 당장은 돌아가도, 어느 날 패키지 설치 하나 때문에 막히는 경우가 생겨요. 저도 예전에 오래된 저장소(repository, 패키지 보관소) 의존성 때문에 야간 작업에서 발목 잡힌 적이 있었습니다.

    AlmaLinux는 RHEL(Red Hat Enterprise Linux, 레드햇 엔터프라이즈 리눅스) 계열과의 호환성을 바탕으로 운영하기 좋은 선택지입니다. 실무 관점에서는 “얼마나 화려한가”보다 얼마나 예측 가능하게 굴러가느냐가 중요하잖아요. 그런 면에서 AlmaLinux 전환은 꽤 현실적인 선택입니다.

    • 보안 측면: 지원 종료 OS를 계속 쓰는 리스크를 줄일 수 있습니다.
    • 운영 측면: 최신 패키지와 관리 체계를 받아들이기 쉬워집니다.
    • 표준화 측면: 앞으로의 리눅스 서버 이전 작업도 훨씬 수월해집니다.

    2. 개념부터 정리: 업그레이드와 마이그레이션은 다릅니다

    여기서 중요한 포인트가 하나 있습니다. 많은 분들이 업그레이드와 마이그레이션을 비슷하게 보시는데, 실제 운영에서는 완전히 다르게 접근해야 합니다.

    구분 의미 장점 주의점
    인플레이스 업그레이드 기존 서버 OS를 바로 올림 서버 수가 적고 빠르게 시도 가능 실패 시 롤백이 까다롭고 서비스 영향이 큼
    사이드 바이 사이드 마이그레이션 신규 서버를 만들고 서비스/데이터를 이전 검증과 롤백이 쉽고 운영 안정성이 높음 초기 준비 작업이 더 필요함

    제가 직접 해보니 CentOS 7에서 AlmaLinux 9로는 새 서버를 만들고 옮기는 전략이 가장 안정적이었습니다. 이유는 간단합니다. 메이저 버전 차이가 크면 패키지 체계, 기본 설정, 런타임(runtime, 실행 환경), 보안 정책이 한꺼번에 바뀌거든요. 특히 다음 항목은 꼭 체크해야 합니다.

    • yum에서 dnf: 명령 습관은 비슷하지만 운영 방식이 미묘하게 달라집니다.
    • Python 2에서 Python 3: 운영 스크립트가 있다면 거의 필수 점검입니다.
    • 방화벽 정책: firewalld, nftables 계열 변화에 따라 기존 iptables 습관이 그대로 안 먹히는 경우가 있습니다.
    • OpenSSL/OpenSSH/PHP/MariaDB 같은 런타임 차이: 애플리케이션 호환성 검증이 필요합니다.

    3. 제가 실제로 잡았던 AlmaLinux 9 마이그레이션 전략

    처음엔 저도 “야간 점검 시간에 한 번에 올리면 되지 않을까?” 생각했었습니다. 근데 서비스가 조금이라도 복잡하면 그 접근이 위험하더라고요. 그래서 최종적으로는 아래 순서로 갔습니다.

    1. 기존 CentOS 7 서버의 서비스 목록과 의존성 파악
    2. 신규 AlmaLinux 9 서버 구축
    3. 패키지, 계정, 서비스 설정 재현
    4. 데이터 사전 동기화
    5. 테스트 도메인 또는 hosts 기반 검증
    6. 짧은 점검 시간에 최종 동기화 후 전환
    7. 문제 없으면 기존 서버는 일정 기간 읽기 전용 또는 대기 상태로 유지

    이 방식의 장점은 명확합니다. 언제든 이전 상태로 돌아갈 수 있다는 거예요. 드디어 됐다 싶어도 사람 일은 모르거든요. 실제 운영은 “성공”보다 “실패했을 때 얼마나 빨리 회복하느냐”가 더 중요합니다.

    4. 실전 구현: CentOS 7 AlmaLinux 9 마이그레이션 준비

    4-1. 기존 서버 인벤토리 정리

    먼저 해야 할 일은 감으로 움직이지 않는 겁니다. 서비스 포트, 패키지, 크론(cron, 주기 실행 작업), 사용자 계정, 마운트 정보를 뽑아두세요. 저는 아래처럼 기본 자료부터 수집했습니다.

    hostnamectl
    cat /etc/centos-release
    ip addr
    ss -tulpn
    rpm -qa | sort > /root/pkglist-centos7.txt
    systemctl list-unit-files --type=service > /root/services-centos7.txt
    crontab -l
    ls -al /etc/cron.d/
    getent passwd > /root/passwd.snapshot
    getent group > /root/group.snapshot
    df -h
    mount

    이 단계에서 중요한 건 “무엇이 설치돼 있는가”보다 실제로 무엇이 쓰이고 있는가입니다. 설치만 돼 있고 안 쓰는 패키지는 꽤 많습니다. 이걸 정리해두면 AlmaLinux 전환 후 서버가 훨씬 깔끔해집니다.

    4-2. 신규 AlmaLinux 9 서버 기본 세팅

    새 서버는 기존 서버를 그대로 복제하려 하지 말고, 필요한 것만 다시 만든다는 느낌으로 가는 게 좋습니다. 저도 처음엔 예전 설정을 몽땅 복붙했다가 SELinux(Security-Enhanced Linux, 보안 강제 정책)와 서비스 경로 차이 때문에 다시 정리했었네요.

    dnf update -y
    hostnamectl set-hostname new-app01.example.local
    timedatectl set-timezone Asia/Seoul
    dnf install -y rsync vim tar curl wget firewalld policycoreutils-python-utils
    systemctl enable --now firewalld
    systemctl enable --now sshd

    계정과 SSH 키도 이 시점에 맞춰둡니다.

    useradd -m deploy
    mkdir -p /home/deploy/.ssh
    chmod 700 /home/deploy/.ssh
    chown -R deploy:deploy /home/deploy/.ssh
    CentOS 7 AlmaLinux 9 마이그레이션을 위한 AlmaLinux 9 신규 서버 구성 이미지

    AlmaLinux 9 신규 서버에서 기본 패키지 설치, firewalld 활성화, 호스트명 설정이 끝난 초기 구성 단계를 보여주는 이미지입니다.

    4-3. 애플리케이션 설정과 데이터 이전

    데이터 이전은 보통 rsync(알싱크, 파일 동기화 도구)를 많이 씁니다. 증분 복사(incremental copy, 바뀐 부분만 다시 전송)가 가능해서 정말 편하더라고요. 서비스 종류에 따라 디렉터리만 옮길지, DB를 별도로 덤프(dump, 내보내기)할지는 달라집니다.

    rsync -avzH --numeric-ids /etc/nginx/ root@new-app01:/etc/nginx/
    rsync -avzH --numeric-ids /var/www/ root@new-app01:/var/www/
    rsync -avzH --numeric-ids /data/ root@new-app01:/data/

    DB는 파일 복사보다 논리 백업(logical backup, SQL 기반 백업) 쪽이 더 안전한 경우가 많습니다.

    mysqldump --all-databases --single-transaction --routines --triggers > all.sql
    scp all.sql root@new-app01:/root/
    mysql < /root/all.sql

    웹 서비스라면 설정 파일을 옮긴 뒤 문법 검사를 먼저 합니다.

    nginx -t
    apachectl configtest
    systemctl daemon-reload
    systemctl enable --now nginx

    여기서 제가 많이 하는 방식은 운영 DNS를 바로 바꾸지 않고 hosts 파일이나 임시 도메인으로 먼저 붙어보는 것입니다. 이 단계에서 80% 문제를 잡아요.

    5. ⚠️ 실제로 자주 막히는 문제와 해결법

    이 섹션은 진짜 중요합니다. 문서만 보면 다 쉬워 보이는데, 실전에서는 작은 차이 때문에 시간이 녹습니다.

    5-1. SELinux 때문에 서비스는 뜨는데 동작이 이상한 경우

    처음엔 이게 뭔가 싶었는데, 프로세스는 살아 있는데 파일 접근이 막혀서 웹이 비정상 동작하는 경우가 있더라고요. 저는 로그부터 확인했습니다.

    getenforce
    ausearch -m avc -ts recent
    journalctl -xe

    무작정 비활성화하기보다 컨텍스트(context, 보안 레이블)를 먼저 맞춰보는 게 훨씬 낫더라고요.

    restorecon -Rv /var/www
    semanage fcontext -a -t httpd_sys_content_t "/data/web(/.*)?" 
    restorecon -Rv /data/web

    5-2. 예전 스크립트가 Python 2 기준인 경우

    CentOS 7 시절에 만든 운영 스크립트가 꽤 오래 살아남는 경우가 많죠. 근데 AlmaLinux 9로 오면서 Python 3 기준으로 정리해야 할 때가 많습니다. 저도 백업 스크립트 하나가 print 문법 때문에 바로 죽어서 순간 멈칫했습니다.

    • 쉘 스크립트로 대체 가능한지 먼저 검토
    • Python 스크립트라면 shebang과 모듈 의존성 점검
    • 가상환경(virtual environment, 독립 실행 환경) 필요 여부 확인

    5-3. 방화벽 규칙이 예전과 다르게 느껴지는 경우

    서비스는 정상인데 외부에서 접속이 안 되는 상황, 생각보다 흔합니다. 이럴 때는 애플리케이션만 보지 말고 포트 리슨(listen, 대기 상태) 여부, firewalld 규칙, 보안 그룹 또는 상위 네트워크 정책까지 같이 봐야 합니다.

    ss -tulpn
    firewall-cmd --get-active-zones
    firewall-cmd --list-all
    firewall-cmd --permanent --add-service=http
    firewall-cmd --permanent --add-service=https
    firewall-cmd --reload

    5-4. 패키지 이름은 비슷한데 설정 경로가 미묘하게 다른 경우

    이거 꽤 귀찮습니다. 특히 예전 블로그 글만 보고 따라 하면 안 맞는 경우가 있어요. 그래서 저는 항상 패키지 설치 후 기본 설정 파일 위치와 systemd(unit, 서비스 정의) 이름부터 확인합니다.

    rpm -qc nginx
    systemctl status nginx
    systemctl cat nginx
    CentOS 7 AlmaLinux 9 마이그레이션 트러블슈팅과 SELinux 점검 이미지

    마이그레이션 중 흔히 만나는 SELinux, 방화벽, 파일 동기화 문제를 점검하는 실제 운영자 시점의 트러블슈팅 이미지입니다.

    6. 검증: 전환 전에 꼭 확인한 체크리스트

    제가 실제로 써보니까 AlmaLinux 마이그레이션 성공 여부는 전환 직전보다 전환 전에 얼마나 검증했는가에서 갈리더라고요. 아래 체크리스트는 꼭 추천드립니다.

    1. 서비스 프로세스가 정상 기동하는가
    2. 기존 포트와 동일하게 리슨 중인가
    3. 웹, API, 배치, DB 연결이 모두 정상인가
    4. 로그 경로와 로그 로테이션(log rotation, 로그 순환)이 정상인가
    5. 백업 스크립트와 크론 작업이 정상 동작하는가
    6. 모니터링 대상과 알림 규칙이 새 서버에 반영됐는가
    7. TLS/인증서, 권한, SELinux, 방화벽 정책이 검증됐는가

    저는 간단한 검증 스크립트도 만들어서 썼습니다.

    #!/bin/bash
    set -e
    curl -I http://127.0.0.1
    systemctl is-active nginx
    systemctl is-active mariadb
    ss -tulpn | grep -E ":80|:443|:3306"
    test -f /var/log/messages

    그리고 전환 직전에는 한 번 더 최종 동기화를 했습니다.

    systemctl stop nginx
    rsync -avzH --delete /var/www/ root@new-app01:/var/www/
    rsync -avzH --delete /etc/nginx/ root@new-app01:/etc/nginx/

    이후 DNS를 바꾸거나, 로드밸런서(load balancer, 트래픽 분산 장비) 백엔드를 교체하는 식으로 컷오버(cutover, 실제 전환)를 진행했습니다.

    CentOS 7 AlmaLinux 9 마이그레이션 완료 후 검증 대시보드 이미지

    마이그레이션 완료 후 시스템 서비스 상태, 포트 오픈 현황, 웹 응답, 기본 모니터링 지표가 정상임을 보여주는 검증 이미지입니다.

    7. 결과: AlmaLinux 전환 후 체감했던 변화

    결과적으로는 꽤 만족스러웠습니다. 물론 마이그레이션 자체가 즐거운 작업은 아니죠. 근데 막상 끝나고 나면 얻는 게 분명합니다.

    • 지원 종료에 대한 불안감이 줄어듭니다.
    • 새로운 패키지와 운영 표준으로 정리하기 쉬워집니다.
    • 불필요한 설정과 레거시(legacy, 오래된 자산)를 털어낼 기회가 됩니다.
    • 향후 자동화(Ansible 같은 구성관리 포함) 기반 정리가 쉬워집니다.

    특히 CentOS 7 AlmaLinux 9 마이그레이션은 단순히 OS 이름만 바꾸는 일이 아니라, 운영 환경을 한 번 건강하게 정리하는 계기였습니다. 저도 처음엔 귀찮아서 미루고 싶었는데, 정리하고 나니 다음 서버도 훨씬 자신 있게 이전하게 되더라고요.

    8. 정리와 FAQ: 리눅스 서버 이전 전에 꼭 기억할 것

    CentOS 7 AlmaLinux 9 마이그레이션에서 제가 가장 강조하고 싶은 건 딱 세 가지입니다. 첫째, 무리해서 한 번에 올리지 말 것. 둘째, 새 서버를 만들고 검증한 뒤 전환할 것. 셋째, 롤백 경로를 미리 확보할 것. 이 세 가지만 지켜도 실패 확률이 크게 줄어듭니다.

    혹시 이런 경험 있으신가요? 설정은 맞는 것 같은데 전환 후에만 이상하게 꼬이는 상황이요. 대부분은 서비스 자체보다 권한, 경로, 방화벽, 이름 해석 같은 주변 요소에서 터집니다. 그래서 저는 항상 체크리스트와 검증 스크립트를 같이 둡니다. 이거 진짜 편하더라고요.

    자주 묻는 질문

    • Q. 인플레이스 업그레이드보다 신규 구축이 왜 더 낫나요?
      A. 메이저 버전 차이가 큰 경우 변수도 많아집니다. 신규 구축은 검증과 롤백이 쉬워서 운영 리스크가 낮습니다.
    • Q. 모든 설정 파일을 그대로 복사하면 되나요?
      A. 권장하지 않습니다. 필요한 설정만 검토해서 옮기는 편이 안전합니다.
    • Q. AlmaLinux 전환 전에 가장 먼저 볼 것은 뭔가요?
      A. 서비스 의존성, 런타임 버전, 백업/복구 절차입니다.

    다음 글에서는 AlmaLinux 전환 이후 체크해야 할 보안 하드닝(hardening, 보안 강화) 항목이나 Ansible 기반 자동화 이전 방법도 다뤄볼 예정입니다. 이전 글에서 다뤘던 백업 검증 루틴과 함께 보시면 더 도움이 될 겁니다.

    CentOS 7 AlmaLinux 9 마이그레이션 요약 인포그래픽

    CentOS 7과 AlmaLinux 9의 운영 차이, 추천 마이그레이션 방식, 전환 전후 체크포인트를 요약한 인포그래픽 이미지입니다.

  • [인프라] OpenStack 멀티노드 클러스터 1년 운영 회고

    [인프라] OpenStack 멀티노드 클러스터 1년 운영 회고

    [인프라] OpenStack 멀티노드 클러스터 1년 운영 회고

    OpenStack 멀티노드 운영을 1년 정도 굴려보면, 설치가 끝이라고 생각했던 시점부터 진짜 일이 시작되더라고요. 저도 처음엔 “컨트롤 플레인(control plane, 제어 영역)만 안정적이면 되겠지”라고 가볍게 봤었는데, 실제로 써보니까 네트워크, 스토리지, 메시지 큐(message queue, 비동기 작업 전달), 그리고 운영 절차가 전부 엮여 있어서 한 군데만 흔들려도 전체가 불안해졌습니다. 혹시 랩 환경(home lab, 개인 실험실)에서 잘 되던 구성이 운영 구간에서 갑자기 말을 안 들어서 당황하신 적 있으신가요? 오늘은 제가 직접 겪은 OpenStack 클러스터 후기, 그리고 OpenStack 배포 실패 사례까지 솔직하게 묶어서 정리해보겠습니다.

    이 글은 특정 배포판 홍보가 아니라, OpenStack 멀티노드 운영에서 실제로 부딪히는 포인트를 중심으로 썼습니다. 다음 글에서는 Ceph(세프, 분산 스토리지) 연동 쪽도 따로 다룰 예정이고, 이전 글에서 다뤘던 가상화 호스트 설계 내용이 있다면 함께 보시면 흐름이 더 잘 잡히실 겁니다.

    컨트롤 노드, 컴퓨트 노드, 네트워크 경로가 한눈에 보이는 OpenStack 멀티노드 운영 아키텍처 예시입니다.

    왜 OpenStack 멀티노드 운영은 설치보다 운영이 더 어렵나

    쉽게 말해 OpenStack은 하나의 프로그램이 아니라 여러 서비스의 연합체더라고요. Keystone(키스톤, 인증), Nova(노바, 컴퓨트), Neutron(뉴트론, 네트워크), Glance(글랜스, 이미지), Cinder(신더, 블록 스토리지) 같은 서비스가 각자 잘 떠 있어야 하고, 서로 API 호출도 정상이어야 합니다. 설치 문서는 대부분 “어떻게 올릴까”에 집중하는데, 운영은 “문제가 났을 때 어디부터 볼까”가 핵심이거든요.

    제가 1년 운영하면서 느낀 건 딱 세 가지였습니다.

    • 장애는 단일 원인처럼 보이지만 실제론 연쇄 장애인 경우가 많습니다.
    • 성능 문제보다 상태 일관성(state consistency, 서비스 간 상태 맞춤) 문제가 더 까다롭습니다.
    • 사람이 반복하는 운영 작업은 결국 사고로 이어집니다.

    예를 들어 인스턴스(instance, 가상 머신) 생성 실패가 떴다고 해서 꼭 Nova 문제는 아니었습니다. 메시지 브로커(broker, 중간 전달자) 지연, Neutron 포트 생성 실패, 데이터베이스 연결 수 부족 같은 식으로 옆 서비스 이슈가 튀어나오는 경우가 꽤 많았거든요. 처음엔 이게 뭔가 싶었는데, 로그를 몇 번 따라가다 보면 OpenStack은 결국 관계도 싸움이라는 걸 알게 됩니다.

    운영 전에 잡아야 했던 기본 원칙

    여기서 중요한 포인트! OpenStack 멀티노드 운영은 기술 스택보다 운영 원칙을 먼저 정하는 게 훨씬 중요합니다. 저는 초반에 이걸 대충 잡았다가 삽질 좀 했습니다 ㅎㅎ

    영역 초기 생각 1년 뒤 결론
    네트워크 가능하면 단순하게 관리망, 스토리지망, 테넌트망 분리가 운영 피로를 줄임
    스토리지 일단 붙으면 된다 장애 복구 절차와 성능 특성까지 같이 봐야 함
    로그 문제 생기면 그때 확인 중앙 수집 없으면 원인 추적 시간이 급격히 늘어남
    배포 처음 한 번만 성공하면 됨 재현 가능한 자동화가 없으면 다음 장애 때 무너짐
    모니터링 CPU, 메모리만 보면 됨 API 지연, 큐 적체, DB 연결 상태까지 봐야 함

    특히 네트워크는 정말 중요했습니다. Neutron이 들어가는 순간 브리지(bridge, 가상 스위치), VLAN(가상 랜), 오버레이 네트워크(overlay network, 가상 터널 네트워크) 이해도가 부족하면 “핑은 되는데 VM 통신은 안 됨” 같은 상황이 자주 생깁니다. 이거 진짜 사람 멘탈 흔듭니다.

    제가 실제로 사용한 운영 구조와 체크 포인트

    구성 자체는 전형적인 멀티노드 방식이었습니다. 컨트롤 노드에 API와 스케줄러 계열을 두고, 컴퓨트 노드에서 하이퍼바이저(hypervisor, 가상화 실행 계층)를 돌리고, 네트워크는 별도 역할을 분리하거나 최소한 경로를 명확히 나눴습니다. 여기에 MariaDB(마리아디비, 관계형 데이터베이스), RabbitMQ(래빗엠큐, 메시지 큐), HAProxy(에이치에이프록시, 로드밸런서)를 조합하면 기본 뼈대는 갖춰집니다.

    배포 자동화는 도구마다 방식이 다르지만, 원칙은 비슷합니다.

    1. 호스트 이름과 DNS를 먼저 고정합니다.
    2. NTP 또는 Chrony로 시간 동기화를 맞춥니다.
    3. 관리망 IP와 서비스 엔드포인트(endpoint, 서비스 접속 주소)를 문서화합니다.
    4. 메시지 큐와 데이터베이스 상태를 먼저 확인합니다.
    5. 그다음 OpenStack 서비스 등록과 에이전트(agent, 백그라운드 작업 프로세스) 상태를 검증합니다.

    제가 자주 쓰던 점검 명령은 이런 식이었습니다.

    openstack service list
    openstack endpoint list
    openstack compute service list
    openstack network agent list
    openstack hypervisor list
    openstack server list --all-projects
    

    처음엔 서비스 목록만 보고 안심했었는데, 실제로는 에이전트가 살아 있어도 기능이 망가진 경우가 있더라고요. 그래서 저는 아래처럼 시스템 레벨도 꼭 같이 확인했습니다.

    systemctl --type=service | grep -E 'nova|neutron|cinder|glance|keystone'
    ss -lntp
    journalctl -u nova-compute -n 100
    journalctl -u neutron-server -n 100
    rabbitmqctl list_queues
    mysql -e 'show processlist;'
    

    여기서 핵심은 “OpenStack 명령 결과”와 “OS 레벨 상태”를 분리해서 보는 겁니다. 둘 중 하나만 보면 꼭 놓치는 구간이 생깁니다.

    OpenStack 멀티노드 운영 서비스 흐름 구성 이미지

    Keystone, Nova, Neutron, RabbitMQ, MariaDB가 어떤 흐름으로 연결되는지 설명하는 구성 다이어그램 위치입니다.

    실전 구현에서 효과 있었던 운영 습관

    프로덕션 OpenStack 회고 관점에서 보면, 기술보다 습관이 더 오래 남습니다. 제가 1년 동안 남긴 것 중 실제로 가장 도움이 됐던 건 아래 네 가지였습니다.

    1. 변경 작업 전 체크리스트 작성
      패키지 업데이트, 네트워크 설정 변경, 서비스 재시작 전후 확인 항목을 고정했습니다.
    2. 설정 파일 차이(diff, 변경점) 기록
      나중에 왜 바꿨는지 기억이 안 나는 순간이 오거든요.
    3. 장애 재현 메모
      증상, 원인 후보, 실제 원인, 해결 순서를 남겨두면 다음 장애 때 시간이 확 줄어듭니다.
    4. 작은 자동화라도 바로 적용
      반복 명령은 셸 스크립트(shell script, 명령 자동화)로 묶었습니다.

    예를 들면 컴퓨트 노드 상태 점검은 간단한 스크립트로 묶어두면 꽤 편합니다.

    #!/usr/bin/env bash
    set -eu
    
    echo '[1] hypervisor list'
    openstack hypervisor list
    
    echo '[2] compute services'
    openstack compute service list
    
    echo '[3] failed services'
    systemctl --failed
    
    echo '[4] recent nova-compute logs'
    journalctl -u nova-compute -n 50 --no-pager
    

    이런 건 거창하지 않아도 됩니다. 중요한 건 사람 손을 덜 타게 만드는 것입니다. 제가 직접 해보니 OpenStack 배포 실패 사례 중 꽤 많은 비율이 설치 자체보다, 설치 후 운영 절차 부재에서 시작됐습니다.

    ⚠️ 실제로 크게 데였던 장애와 해결 과정

    1. 메시지 큐 지연으로 인한 인스턴스 생성 실패

    증상은 단순했습니다. VM 생성 요청은 들어가는데 완료가 안 되는 겁니다. 처음엔 Nova 스케줄러를 의심했는데, 로그를 따라가 보니 RabbitMQ 큐 적체가 원인이었습니다. 관리망 지연이 누적되면서 RPC(Remote Procedure Call, 원격 호출) 응답이 늦어졌고, 결국 타임아웃이 연쇄적으로 터졌습니다.

    • 배운 점: API 장애처럼 보여도 메시지 경로를 꼭 봐야 합니다.
    • 해결 방법: 큐 상태 확인, 관리망 상태 점검, 재시작 순서 표준화

    2. Neutron 포트 생성은 되는데 통신이 안 되는 문제

    이건 정말 오래 잡았습니다. 보안 그룹(security group, 가상 방화벽) 문제처럼 보였는데, 실제로는 브리지 매핑(bridge mapping, 네트워크 연결 규칙)과 물리 NIC 연결 정의가 어긋나 있었습니다. 로그상 큰 에러가 안 보여서 더 헷갈렸고요. 저도 처음엔 헷갈렸는데, 결국 에이전트 설정과 호스트 네트워크 구성이 서로 맞아야 한다는 너무 당연한 사실을 다시 배웠습니다.

    • 배운 점: Neutron 문제는 논리 설정과 물리 연결을 같이 봐야 합니다.
    • 해결 방법: 브리지 이름, 인터페이스 매핑, 에이전트 상태를 한 번에 점검

    3. 스토리지 연결은 되는데 성능이 들쭉날쭉한 상황

    이건 더 무서운 유형입니다. 완전히 죽는 게 아니라 “어제는 괜찮았는데 오늘은 왜 느리지?”가 반복되거든요. 결국 원인은 백엔드 스토리지 경로 경쟁, 작업 몰림, 그리고 이미지 캐시 처리 타이밍이 겹친 문제였습니다. 숫자를 괜히 지어내고 싶진 않아서 구체 수치는 빼겠지만, 체감 성능 차이는 꽤 컸습니다.

    • 배운 점: 스토리지는 붙어 있는지만 보지 말고 패턴을 봐야 합니다.
    • 해결 방법: 작업 시간대 분산, 캐시 정책 점검, 백엔드 모니터링 강화

    4. 데이터베이스는 살아 있는데 API가 간헐적으로 느린 문제

    이건 딱 “다 살아 있는데 왜 느리지?” 케이스였네요. DB 연결 수, 느린 쿼리(slow query, 지연 질의), 서비스 재시도 패턴이 겹치면서 간헐 지연이 생겼습니다. 이런 문제는 재시작으로 잠깐 가려질 수 있어서 더 위험합니다. 드디어 됐다! 싶었는데 다음날 다시 터지더라고요.

    정리하면, OpenStack 멀티노드 운영에서 가장 위험한 장애는 완전 다운보다 반쯤 되는 장애입니다. 운영자가 방심하기 쉽거든요.

    OpenStack 멀티노드 운영 장애 분석 관제 화면

    로그 추적, 큐 적체 확인, 네트워크 흐름 분석을 한 번에 보여주는 운영 관제 이미지 위치입니다.

    문제 줄이기 위해 정착시킨 검증 절차

    문제가 생긴 뒤 고치는 것도 중요하지만, 더 중요한 건 변경 후 검증입니다. 저는 아래 순서로 체크했습니다.

    1. 인증 확인: 토큰 발급과 서비스 카탈로그(service catalog, 서비스 목록) 확인
    2. 컴퓨트 확인: 하이퍼바이저 목록과 서비스 up/down 상태 확인
    3. 네트워크 확인: 네트워크 생성, 서브넷 연결, 포트 생성 테스트
    4. 부팅 확인: 테스트 인스턴스 생성 후 콘솔 접속 확인
    5. 삭제 확인: 인스턴스 삭제, 볼륨 정리, 포트 잔존 여부 확인

    간단한 검증 흐름 예시는 이렇습니다.

    openstack token issue
    openstack network create lab-net
    openstack subnet create --network lab-net --subnet-range 192.168.50.0/24 lab-subnet
    openstack server create --flavor m1.small --image test-image --network lab-net test-vm
    openstack server list
    openstack console url show test-vm
    

    여기서 중요한 건 생성만 보는 게 아니라 삭제와 정리까지 확인하는 겁니다. 리소스 찌꺼기(resource orphan, 고아 리소스)가 쌓이기 시작하면 나중에 장애 분석이 훨씬 더 어려워집니다.

    1년 운영 후 남은 성과와 아쉬움

    🎉 성과부터 말하면, 운영 초반보다 장애 대응 시간이 눈에 띄게 줄었습니다. 원인은 대단한 튜닝이 아니라, 로그 보는 순서와 점검 절차가 정리됐기 때문이었습니다. OpenStack 클러스터 후기를 한 줄로 줄이면 이겁니다. 복잡성은 줄이지 못해도, 복잡성을 다루는 방법은 개선할 수 있다.

    반대로 아쉬움도 분명했습니다.

    • 초기 아키텍처 문서를 너무 늦게 정리했습니다.
    • 네트워크 변경 이력을 더 일찍 표준화했어야 했습니다.
    • 테스트 환경과 운영 환경 차이를 가볍게 보면 안 됐습니다.
    • “지금 되니까 괜찮다”는 판단이 가장 위험했습니다.

    특히 프로덕션 OpenStack 회고를 하면서 느낀 건, 운영자는 문제를 해결하는 사람인 동시에 문제가 다시 생기지 않게 만드는 사람이어야 한다는 점이었습니다. 근데 이게 말처럼 쉽진 않죠. 문서화는 귀찮고, 자동화는 미루기 쉽고, 장애는 꼭 바쁠 때 옵니다.

    OpenStack 멀티노드 운영 안정화 결과 요약 인포그래픽

    운영 절차 정리 전후의 안정화 흐름과 핵심 교훈을 비교하는 요약 시각화 이미지 위치입니다.

    OpenStack 멀티노드 운영 정리: 지금 다시 시작한다면

    💡 제가 지금 다시 처음부터 OpenStack 멀티노드 운영을 구성한다면 아래 순서로 갑니다.

    1. 네트워크 분리 설계부터 문서화합니다.
    2. 배포 자동화를 처음부터 전제로 둡니다.
    3. 공통 로그와 모니터링을 설치 초기에 붙입니다.
    4. 테스트 VM 생성/삭제 검증을 표준 절차로 만듭니다.
    5. 장애 기록 템플릿을 운영 첫날부터 사용합니다.

    이 다섯 개만 지켜도 OpenStack 배포 실패 사례의 상당수를 예방할 수 있습니다. 물론 환경마다 디테일은 다를 겁니다. 그래도 뼈대는 비슷하더라고요. 특히 OpenStack 멀티노드 운영은 “한 번 설치 성공”보다 “열 번 재현 가능”이 훨씬 값집니다.

    자주 묻는 질문

    Q1. 홈랩에서도 멀티노드가 의미가 있나요?

    있습니다. 오히려 작은 환경에서 역할 분리와 장애 흐름을 이해하기 좋습니다. 다만 과한 고가용성(HA, 고장 대비 이중화)보다는 기본 동작과 복구 절차부터 익히는 게 낫습니다.

    Q2. 가장 먼저 모니터링해야 할 것은 뭔가요?

    CPU나 메모리보다 먼저 API 응답 지연, 메시지 큐 적체, 데이터베이스 연결 상태, 네트워크 에이전트 상태를 보시는 걸 권합니다.

    Q3. 설치 도구보다 중요한 건 뭔가요?

    운영 문서, 변경 이력, 검증 절차입니다. 도구는 바꿀 수 있지만 운영 습관은 쉽게 안 바뀌거든요.

    마무리

    1년 동안 OpenStack 멀티노드 클러스터를 운영하면서 느낀 건, OpenStack은 화려한 기능보다 기본기가 훨씬 중요하다는 점이었습니다. 서비스 간 관계를 이해하고, 장애를 추적하는 순서를 만들고, 변경을 기록하는 것. 이 세 가지가 결국 운영 품질을 갈랐습니다. 저도 처음엔 “왜 이렇게 복잡하지?” 싶었는데, 하나씩 뜯어보니 결국 시스템은 거짓말을 안 하더라고요.

    혹시 지금 OpenStack 멀티노드 운영을 준비 중이시라면, 설치 성공 화면에서 끝났다고 생각하지 마시고 검증 절차부터 붙여보세요. 그게 나중에 가장 큰 차이를 만듭니다. 다음 글에서는 스토리지 연동과 백업 전략 쪽을 더 현실적으로 풀어보겠습니다. ✅

  • [Cloud] FinOps 클라우드 비용 관리 베스트 프랙티스 체크리스트 10가지

    [Cloud] FinOps 클라우드 비용 관리 베스트 프랙티스 체크리스트 10가지

    [Cloud] FinOps 클라우드 비용 관리 베스트 프랙티스 체크리스트 10가지

    FinOps 클라우드 비용 최적화 이야기를 하면 아직도 많은 팀이 “일단 쓰고 나중에 정산하자” 모드로 들어가더라고요. 저도 처음엔 그랬습니다. 서비스는 잘 돌아가는데 월말 청구서를 보면 식은땀이 나는 거죠. 특히 멀티 클라우드나 Kubernetes(쿠버네티스, 컨테이너 오케스트레이션) 환경까지 섞이면 누가 왜 돈을 쓰는지 한눈에 안 보입니다. 그래서 오늘은 제가 홈랩과 실무에서 계속 다듬어 온 클라우드 비용 관리 기준을 체크리스트 형태로 정리해보겠습니다. 운영팀, 플랫폼팀, 개발팀이 같이 볼 수 있게 최대한 실전형으로 풀어볼게요.

    이 글은 거창한 이론보다 바로 적용 가능한 FinOps 전략에 집중했습니다. 쉽게 말해, 비용을 줄이는 것만이 아니라 비용 거버넌스를 만들어서 팀이 반복적으로 같은 실수를 하지 않게 만드는 방법이죠. 혹시 청구서가 예측보다 자꾸 커지거나, Reserved Instances(예약 인스턴스)나 Savings Plans(절감 약정) 같은 약정형 할인은 들어봤는데 어디서부터 손대야 할지 막막하셨다면 딱 이 순서대로 보시면 됩니다.

    FinOps 클라우드 비용 최적화 전체 운영 흐름 다이어그램

    비용 데이터 수집, 태깅, 예산, 알림, 최적화, 리뷰까지 이어지는 FinOps 운영 흐름을 한눈에 보여주는 이미지입니다.

    FinOps를 쉽게 말하면 무엇인가

    FinOps(Financial Operations, 재무 중심 클라우드 운영)는 클라우드 사용량과 비용을 기술팀이 직접 이해하고, 재무팀과 함께 최적화하는 운영 방식이에요. 쉽게 말해 “누가 얼마나 쓰는지 보이게 만들고, 그걸 근거로 빠르게 행동하는 문화”에 가까워요. 여기서 중요한 건 단순 절감이 아니라는 거죠. 돈을 덜 쓰는 게 아니라, 필요한 곳에는 제대로 쓰고 낭비는 줄이는 것이 진짜 핵심이거든요.

    제가 직접 해보니 FinOps는 툴 하나 깔면 끝나는 일이 아니었어요. Cost Explorer(비용 탐색), Budgets(예산), 태그 정책, 대시보드, 리뷰 회의까지 다 이어져야 효과가 나더라고요. 처음엔 이게 뭔가 싶었는데, 한 번 체계가 잡히면 “이번 달 왜 20% 늘었지?”를 감으로 추측하지 않아도 돼요. 이거 진짜 편합니다.

    FinOps 클라우드 비용 최적화 체크리스트 10가지

    아래 10가지는 제가 실제로 우선순위를 두는 항목들이에요. 한 번에 다 하려고 하면 지칩니다. 그래서 가시성 확보 → 거버넌스 정착 → 구매 최적화 → 지속 점검 순서로 가는 걸 추천드려요.

    체크 항목 핵심 질문 우선순위
    1. 태그 표준화 누가 어떤 비용을 쓰는지 구분 가능한가? 매우 높음
    2. 계정/프로젝트 분리 환경별 비용이 섞이지 않는가? 매우 높음
    3. 예산과 알림 월말 전에 이상 징후를 잡는가? 매우 높음
    4. 유휴 자원 정리 안 쓰는 리소스가 계속 과금되는가? 높음
    5. 권한/사이즈 적정화 과한 스펙을 기본값처럼 쓰고 있지 않은가? 높음
    6. 약정형 할인 검토 상시 부하는 할인 구매 대상으로 관리하는가? 높음
    7. 스토리지 수명주기 오래된 데이터 보관 정책이 있는가? 중간
    8. Kubernetes 비용 배분 네임스페이스 단위 비용 추적이 되는가? 중간
    9. 대시보드와 리뷰 루틴 숫자를 정기적으로 함께 보는가? 매우 높음
    10. 자동화된 정책 집행 규칙 위반을 자동으로 막는가? 높음

    1. 태그(Tag, 리소스 분류용 메타데이터) 표준을 먼저 만드세요

    비용 최적화의 시작은 거의 항상 태그였어요. 태그가 없으면 비용 배분이 안 되고, 비용 배분이 안 되면 책임 소재도 흐려지죠. 최소한 owner, service, environment, cost-center 정도는 강제하는 편이 좋아요. 저도 예전엔 태그를 권장만 했었는데, 결과는 뻔했습니다. 아무도 안 넣어요 ㅎㅎ 그래서 지금은 생성 단계에서 빠지면 경고가 뜨거나 배포 파이프라인에서 막히게 해둬요.

    2. 계정(Account, 클라우드 계정)과 프로젝트를 용도별로 분리하세요

    개발, 스테이징, 운영을 한 계정에 다 넣어두면 비용이 섞여서 해석이 어려워져요. 특히 운영 이슈 대응 중 임시 리소스를 만들었다가 그대로 남아버리는 경우가 많거든요. 환경 분리는 보안에도 좋고, 클라우드 비용 관리에도 바로 도움이 돼요. 청구서를 볼 때 “이 증가는 운영 때문인가, 테스트 때문인가”가 바로 보여야 합니다.

    3. 예산(Budget, 목표 지출 한도)과 알림을 월초에 설정하세요

    월말에 놀라는 구조를 끊어야 해요. 예산은 금액 기준만 보지 말고, 예측 비용(forecast)과 전월 대비 증가율도 같이 보면 좋아요. 제 경험상 50%, 80%, 100% 세 구간 알림이 실무에서 제일 쓸 만했습니다.

    4. 유휴 자원(Idle Resource) 정리를 정기 작업으로 돌리세요

    안 붙은 EBS 볼륨, 멈춘 줄 알았는데 스냅샷이 계속 쌓이는 디스크, 더 이상 안 쓰는 로드밸런서, 오래된 퍼블릭 IP 같은 것들이 생각보다 커요. 한 건은 작아 보여도 쌓이면 월 비용을 계속 갉아먹어요. 제가 홈랩에서 제일 많이 삽질한 것도 이 부분이었어요. “이 정도야 얼마 안 하겠지” 했는데, 그런 게 제일 무섭더라고요.

    5. Right-sizing(라이트사이징, 적정 사양 조정)을 습관으로 만드세요

    CPU와 메모리를 넉넉하게 주는 건 마음은 편하지만 비용은 절대 안 편해요. 실제 사용량 기반으로 인스턴스 타입과 데이터베이스 스펙을 줄이는 게 중요합니다. 여기서 중요한 포인트! 평균값만 보지 말고 피크 시간대와 주간 패턴도 같이 봐야 해요. 평균 10% 사용률만 보고 줄였다가 월요일 오전에 장애 나는 경우, 생각보다 흔하니까요.

    6. 약정형 할인은 상시 부하에만 적용하세요

    Reserved Instances(예약 인스턴스), Savings Plans(절감 약정) 같은 할인 도구는 강력해요. 다만 변동성이 큰 워크로드에 무턱대고 적용하면 오히려 관리가 꼬여요. 저는 최소 2~3개월 이상 안정적으로 유지되는 상시 부하를 먼저 분류하고, 그중에서 베이스라인 사용량만 할인 대상으로 잡는 편이에요. 공격적으로 사기보다 보수적으로 시작하는 게 덜 아파요.

    7. 스토리지 수명주기(Lifecycle, 데이터 보관 단계)를 정의하세요

    오브젝트 스토리지(Object Storage, 객체 스토리지)는 싸 보이지만, 오래된 로그와 백업이 쌓이면 또 얘기가 달라져요. 접근 빈도에 따라 Standard, Infrequent Access, Archive 계층으로 나누고, 자동 전환 정책을 두면 좋아요. 특히 로그 보존 기간은 법적 요구사항과 운영 현실을 같이 봐야 해요.

    8. Kubernetes 비용은 네임스페이스 단위로 보세요

    Kubernetes 환경에서는 노드 비용만 보면 감이 안 와요. 네임스페이스(namespace), 팀, 서비스 기준으로 비용을 나눠 봐야 누가 비효율적인 요청(requests)과 제한(limits)을 잡고 있는지 드러나거든요. 실제로 써보니까 클러스터 전체 비용만 보는 팀은 최적화가 잘 안 되더라고요. 공용 리소스처럼 느껴져서 책임감이 흐려져요.

    9. 대시보드와 주간 리뷰를 운영 루틴에 넣으세요

    FinOps는 보고서로 끝나면 실패할 확률이 높아요. 비용 대시보드를 만들어도 아무도 안 보면 의미가 없거든요. 그래서 저는 주간 운영 회의에 비용 변화 5분 슬롯을 꼭 넣어요. 전주 대비 급증 서비스, 미태깅 리소스, 예상 초과 예산만 짧게 확인해도 효과가 꽤 커요.

    10. 정책 위반은 자동화로 막으세요

    태그 없는 리소스 생성 금지, 특정 리전(region) 제한, 고가 인스턴스 승인 절차 같은 건 사람이 매번 체크하기 어려워요. Policy as Code(정책의 코드화)나 IaC(코드형 인프라) 파이프라인 검증을 붙이면 비용 거버넌스가 훨씬 안정돼요. 사람이 기억해서 지키는 규칙은 오래 못 가요. 자동화가 진짜 답이에요.

    실전 구현: 바로 적용하는 FinOps 전략

    이제 체크리스트를 실제 운영으로 옮겨보겠습니다. 아래 예시는 AWS 기준 명령을 포함하지만, 구조 자체는 다른 클라우드에도 그대로 응용할 수 있어요. 제가 직접 해보니 처음부터 완벽한 대시보드보다 태그, 예산, 미사용 자원 탐지 세 가지만 먼저 굴리는 게 효과가 가장 빨랐습니다.

    1. 필수 태그 사전 정의: owner, service, environment, cost-center
    2. 주요 계정 또는 프로젝트별 예산 생성: 운영/개발 분리
    3. 일일 비용 수집 자동화: API 또는 비용 리포트 기반
    4. 주간 리뷰 루틴 고정: 증가 원인과 조치 확인
    5. 약정형 할인 검토: 상시 부하만 선별
    # 최근 7일 비용을 서비스 단위로 확인하는 예시
    aws ce get-cost-and-usage \
      --time-period Start=2026-06-23,End=2026-06-30 \
      --granularity DAILY \
      --metrics UnblendedCost \
      --group-by Type=DIMENSION,Key=SERVICE

    위 명령은 가장 단순한 출발점이에요. 서비스 단위 비용 추이를 보고, 급증한 항목이 있으면 거기서 다시 태그나 계정 기준으로 파고드는 식이죠. 처음엔 이 숫자를 어디에 써야 하나 싶었는데, 막상 주간 리포트에 붙여보면 팀 대화가 달라집니다.

    requiredTags:
      - owner
      - service
      - environment
      - cost-center
    rules:
      denyUntaggedResources: true
      blockHighCostInstanceTypes: false
      allowedEnvironments:
        - dev
        - staging
        - prod

    이 YAML은 개념 예시예요. 실제 구현은 Terraform(테라폼, IaC 도구), OPA(Open Policy Agent, 정책 엔진), 클라우드 정책 서비스 등 팀 환경에 맞게 바꾸시면 돼요. 핵심은 “태그는 권장”이 아니라 “태그 없으면 불편하거나 생성 불가” 상태로 만드는 거예요.

    FinOps 클라우드 비용 관리 태그 정책과 예산 알림 설정 이미지

    필수 태그 정책, 예산 임계치, 알림 연결 구조를 함께 보여주는 설정 예시 이미지입니다.

    import csv
    from collections import defaultdict
    
    cost_by_service = defaultdict(float)
    
    with open("cost_report.csv", newline="", encoding="utf-8") as f:
        reader = csv.DictReader(f)
        for row in reader:
            service = row.get("service", "unknown")
            amount = float(row.get("cost", 0) or 0)
            cost_by_service[service] += amount
    
    for service, amount in sorted(cost_by_service.items(), key=lambda x: x[1], reverse=True):
        print(f"{service}: {amount:.2f}")

    비용 리포트 CSV만 있어도 이런 식으로 빠르게 합계를 낼 수 있어요. 고급 BI 도구가 없어도 돼요. 작은 팀일수록 이런 단순 자동화가 오히려 오래 가더라고요.

    Kubernetes와 IaC에서 자주 놓치는 포인트

    Kubernetes에서는 requests/limits를 과하게 잡아놓고 실제 사용률은 낮은 경우가 많아요. HPA(Horizontal Pod Autoscaler, 수평 자동 확장)만 믿고 requests는 크게 유지하면 노드가 비효율적으로 채워지거든요. 여기서 꼭 같이 봐야 하는 게 네임스페이스별 비용, 미사용 PersistentVolume(영구 볼륨), 과도한 로그 적재량이에요.

    # 네임스페이스 라벨과 리소스 현황 확인 예시
    kubectl get ns --show-labels
    kubectl top pod -A
    kubectl get pvc -A

    IaC 관점에서는 기본 태그(default tags)를 모듈 레벨에서 강제하는 게 가장 편했어요. 서비스마다 직접 넣게 하면 결국 빠져요. 이전 글에서 다뤘던 IaC 표준화 내용과도 연결되는데, 이건 다음 글에서 Terraform 모듈 기준으로 더 깊게 다뤄볼 예정이에요.

    ⚠️ 실제로 자주 겪는 문제와 트러블슈팅

    여기서부터는 제가 진짜 많이 부딪힌 부분이에요. 삽질 좀 했습니다 ㅎㅎ 미리 알고 가시면 시간 꽤 아끼실 거예요.

    • 태그는 있는데 비용 배분이 이상한 경우: 생성 이후에 태그를 붙인 리소스는 비용 반영 시점이 늦을 수 있어요. 그래서 태그는 생성 시점 강제가 가장 안전해요.
    • 예산 알림이 너무 많이 오는 경우: 계정 전체 예산만 두면 잡음이 커요. 환경 또는 제품군 기준으로 쪼개야 의미 있는 알림이 돼요.
    • 개발용 리소스가 밤새 계속 켜져 있는 경우: 스케줄 기반 종료 자동화를 붙이는 편이 훨씬 나아요. 사람은 자주 잊거든요.
    • 약정형 할인 적용 후 체감이 없는 경우: 실제 상시 사용량보다 많이 구매했을 수 있어요. 온디맨드 사용 패턴과 베이스라인을 먼저 다시 봐야 합니다.
    • Kubernetes 비용이 팀별로 안 보이는 경우: 네임스페이스, 라벨, 클러스터 공용 비용 배분 기준이 먼저 정리되어야 해요.

    특히 비용 알림은 너무 많이 오면 아무도 안 보게 돼요. 보안 알림이든 비용 알림이든 마찬가지더라고요. 그래서 신호 대 잡음비를 높이는 게 중요해요. 진짜 대응해야 할 것만 오게 만들어야 하거든요.

    검증: 무엇을 보면 잘되고 있다고 판단할까

    FinOps 클라우드 비용 최적화가 잘 굴러가는지는 생각보다 간단한 지표로 확인할 수 있어요. 제가 보는 핵심은 네 가지예요. 첫째, 미태깅 리소스 비율이 줄어드는가. 둘째, 예산 초과를 월말이 아니라 중간에 잡는가. 셋째, 유휴 자원 정리 주기가 실제로 돌고 있는가. 넷째, 상시 부하에 대한 할인 적용률이 안정적으로 유지되는가입니다.

    1. 미태깅 리소스 비율 감소
    2. 주간 비용 증가 원인 파악 시간 단축
    3. 개발/운영 환경별 비용 분리 정확도 향상
    4. 유휴 자원 정리 후 재발 방지 자동화 적용
    FinOps 클라우드 비용 최적화 결과 대시보드 이미지

    서비스별 비용 증감, 예산 임계치, 미태깅 리소스 현황을 함께 보여주는 결과 대시보드 이미지입니다.

    실제로 써보니까 대시보드가 화려할 필요는 없었어요. 오히려 이번 주 뭐가 늘었는지, 왜 늘었는지, 누가 액션할지가 바로 보이는 구성이 제일 좋더라고요. 드디어 됐다! 싶은 순간이 이때 와요. 숫자가 회의용 장식이 아니라 운영 도구가 되는 거죠.

    비교로 보는 우선 적용 순서

    영역 빠른 효과 구현 난이도 추천 시점
    태그 표준화 높음 중간 가장 먼저
    예산/알림 높음 낮음 즉시
    유휴 자원 정리 높음 낮음 즉시
    라이트사이징 중간 중간 데이터 확보 후
    약정형 할인 중간~높음 중간 패턴 안정화 후
    정책 자동화 장기적으로 매우 높음 중간~높음 기본 체계 수립 후

    정리와 다음 단계

    오늘 정리한 체크리스트의 핵심은 하나예요. 클라우드 비용 관리는 절감 이벤트가 아니라 운영 체계라는 거예요. 태그, 예산, 유휴 자원 정리, 리뷰 루틴 이 네 가지만 먼저 제대로 굴려도 팀 분위기가 달라져요. 그리고 그 위에 약정형 할인, Kubernetes 비용 배분, 정책 자동화를 차근차근 얹으면 돼요.

    저도 처음엔 FinOps를 재무팀이 보는 숫자 정도로만 생각했었는데, 실제로는 인프라 운영 성숙도를 보여주는 지표에 더 가깝더라고요. 그래서 FinOps 클라우드 비용 최적화는 비용을 아끼는 기술이면서 동시에 운영을 더 예측 가능하게 만드는 기술이에요. 혹시 지금 바로 하나만 시작하신다면, 오늘 안에 예산 알림부터 걸어보세요. 가장 빨리 체감된답니다.

    FinOps 클라우드 비용 관리 체크리스트 10가지 요약 인포그래픽

    태그, 예산, 유휴 자원, 라이트사이징, 할인 전략까지 10가지 체크리스트를 한 장으로 요약한 이미지입니다.

    자주 묻는 질문

    Q1. 작은 팀도 FinOps 전략이 필요한가요?

    필요해요. 오히려 작은 팀일수록 한두 번의 비용 급증이 크게 느껴져요. 복잡한 조직 체계보다 보이는 대시보드와 간단한 규칙이 더 중요합니다.

    Q2. 멀티 클라우드가 아니어도 비용 거버넌스가 필요한가요?

    네. 단일 클라우드라도 서비스가 늘어나면 비용 구조가 금방 복잡해져요. 비용 거버넌스는 규모보다 습관의 문제에 가까워요.

    Q3. 가장 먼저 줄이기 쉬운 비용은 무엇인가요?

    보통은 유휴 자원과 과한 사양이에요. 안 쓰는 디스크, 오래된 스냅샷, 과도한 인스턴스 크기부터 보시면 성과가 빨리 나더라고요.

    이전 글에서 다룬 모니터링 표준화 내용과 함께 보시면 더 연결이 잘 돼요. 다음 글에서는 Terraform 기준으로 태그 강제와 비용 검증 파이프라인을 정리해보겠습니다.

  • [인프라] Knative 성능 벤치마크, 실제 트래픽 증가에 따른 서빙 체크 포인트

    [인프라] Knative 성능 벤치마크, 실제 트래픽 증가에 따른 서빙 체크 포인트

    [인프라] Knative 성능 벤치마크, 실제 트래픽 증가에 따른 서빙 체크 포인트

    Knative 성능 벤치마크를 직접 해보려는 분들은 대개 비슷한 고민을 하더라고요. 평소엔 조용한 서비스인데, 특정 시간에 요청이 몰리면 Knative Serving이 어디까지 버텨주는지, 그리고 서버리스(Serverless)의 자동 확장이 정말 실전에 맞게 움직이는지 확인하고 싶은 거죠. 저도 홈랩에서 처음 테스트했을 때는 “오토스케일링이 알아서 되겠지” 하고 가볍게 봤다가, 콜드 스타트와 동시성 때문에 삽질 좀 했습니다 ㅎㅎ

    특히 운영 입장에서 중요한 건 숫자 하나가 아니라 트래픽 증가 구간에서 어떤 컴포넌트가 먼저 흔들리는지를 아는 겁니다. CPU가 먼저 차는지, Activator가 병목이 되는지, Ingress 레이어에서 지연이 생기는지 봐야 하거든요. 이번 글에서는 제가 실제로 자주 쓰는 방식대로, 과장된 수치 없이 Knative 성능 벤치마크를 어떻게 설계하고 해석하면 되는지 정리해보겠습니다.

    Knative 성능 벤치마크를 위한 Knative Serving 아키텍처와 트래픽 흐름 다이어그램

    Knative Serving의 요청 흐름과 오토스케일링 관련 컴포넌트를 한눈에 보는 구성도입니다.

    1. 왜 Knative Serving 성능 테스트가 까다로운가

    쉽게 말해 Knative는 단순한 Deployment 하나를 때리는 구조가 아닙니다. 요청은 보통 Route, Revision, Queue-Proxy, 그리고 상황에 따라 Activator를 거치게 됩니다. 그래서 같은 애플리케이션 코드를 올려도 일반 Kubernetes Deployment와 응답 패턴이 꽤 다르게 나옵니다.

    • Scale to Zero: 유휴 상태에선 파드를 0으로 줄였다가 다시 띄웁니다.
    • Concurrency 기반 확장: CPU만 보는 게 아니라 요청 동시성도 핵심 기준입니다.
    • Revision 단위 배포: 새 설정이 들어가면 새 리비전이 생기므로 비교 테스트가 편합니다.
    • 네트워크 경로 증가: 인그레스와 프록시 홉이 늘어나면 지연 해석이 달라집니다.

    여기서 중요한 포인트! Knative 성능 벤치마크는 “최대 RPS가 얼마냐”만 보는 테스트가 아닙니다. 트래픽이 늘어날 때 응답 시간이 어떻게 변하는지, 그리고 자동 확장이 몇 초 안에 따라붙는지를 함께 봐야 의미가 있습니다.

    2. 벤치마크 전에 잡아야 할 기준

    제가 직접 해보니, 테스트 전에 기준을 안 잡으면 결과가 거의 쓸모가 없더라고요. 처음엔 저도 그냥 부하 도구부터 돌렸었는데, 나중에 보니까 어떤 값이 애플리케이션 때문인지, 어떤 값이 플랫폼 때문인지 분리가 안 되더라고요.

    2-1. 최소한 이 네 가지는 고정하세요

    1. 애플리케이션 응답 형태: CPU 바운드인지, I/O 바운드인지 구분합니다.
    2. 동시성 목표: containerConcurrency를 명시할지 결정합니다.
    3. 오토스케일 기준: target concurrency, min/max scale 범위를 정합니다.
    4. 측정 구간: 콜드 스타트 포함 여부와 워밍 상태를 분리합니다.

    실무에서는 보통 두 번 봅니다. 한 번은 콜드 스타트 포함 시나리오, 한 번은 이미 파드가 떠 있는 상태죠. 이 둘을 섞으면 해석이 틀어집니다.

    2-2. 어떤 지표를 보면 되나

    지표 왜 중요한가 해석 팁
    RPS/Throughput 전체 처리량 확인 상승하다가 평평해지면 병목 가능성이 큽니다.
    P95, P99 Latency 꼬리 지연 확인 평균보다 훨씬 중요할 때가 많습니다.
    Pod Count 확장 반응 확인 요청 증가와 함께 자연스럽게 늘어나는지 봅니다.
    Error Rate 품질 저하 감지 5xx가 생기면 네트워크/백엔드 구간을 같이 확인합니다.

    3. 실전용 테스트 환경 구성

    이 글에서는 가장 단순한 HTTP echo 계열 서비스 대신, 약간의 대기 시간을 줄 수 있는 애플리케이션을 두고 확인하는 방식을 권장합니다. 이유는 간단합니다. 너무 가벼운 앱은 네트워크 오버헤드만 보이고, 너무 무거운 앱은 앱 병목만 보여서 Knative 특성이 잘 안 드러나거든요.

    아래 예시는 Knative Service 리소스입니다. 실제 테스트에선 여러분이 보유한 검증된 컨테이너 이미지를 넣으시면 됩니다.

    apiVersion: serving.knative.dev/v1
    kind: Service
    metadata:
      name: benchmark-app
    spec:
      template:
        metadata:
          annotations:
            autoscaling.knative.dev/min-scale: "0"
            autoscaling.knative.dev/max-scale: "10"
            autoscaling.knative.dev/target: "10"
        spec:
          containerConcurrency: 10
          containers:
            - image: gcr.io/knative-samples/helloworld-go:latest
              ports:
                - containerPort: 8080
              env:
                - name: TARGET
                  value: "knative-benchmark"

    배포는 일반적인 kubectl 흐름으로 진행하면 됩니다.

    kubectl apply -f knative-service.yaml
    kubectl get ksvc benchmark-app
    kubectl get revision
    kubectl get pods -w

    테스트 전에는 라우트 URL을 먼저 확인해 두세요.

    kubectl get ksvc benchmark-app -o jsonpath='{.status.url}'
    Knative 성능 벤치마크 설정에서 오토스케일링 파라미터를 설명하는 구성 이미지

    서비스 정의에서 동시성, 최소/최대 스케일, 타깃 값을 어떻게 잡는지 보여주는 이미지입니다.

    4. 트래픽 증가 시나리오를 이렇게 나누면 해석이 쉬워집니다

    제가 실제로 써보니까 한 번에 큰 부하를 주는 것보다, 단계형(step load)으로 올리는 편이 훨씬 유용했습니다. 트래픽 증가 구간에서 어느 시점부터 지연이 튀는지 보여주기 좋거든요.

    1. 기본 응답 확인: 단일 요청으로 정상 동작과 헤더를 확인합니다.
    2. 저부하 구간: 낮은 동시성으로 워밍 상태 지연을 봅니다.
    3. 중간 부하 구간: 오토스케일이 개입하기 시작하는지 봅니다.
    4. 고부하 구간: P95/P99 지연과 에러율 변화를 봅니다.
    5. 유휴 복귀: 다시 요청을 끊고 scale to zero 동작을 확인합니다.

    간단한 부하 테스트는 hey 같은 도구로도 충분합니다. 특별히 복잡한 시나리오가 아니라면 시작은 이걸로 해보세요.

    URL=$(kubectl get ksvc benchmark-app -o jsonpath='{.status.url}')
    hey -z 30s -c 10 "$URL"
    hey -z 30s -c 30 "$URL"
    hey -z 30s -c 50 "$URL"

    좀 더 긴 시나리오를 만들고 싶다면 k6 같은 도구를 쓰는 것도 좋습니다. 아래는 단계적으로 가상 사용자 수를 올리는 예시입니다.

    import http from 'k6/http';
    import { sleep } from 'k6';
    
    export const options = {
      stages: [
        { duration: '30s', target: 5 },
        { duration: '30s', target: 20 },
        { duration: '30s', target: 50 },
        { duration: '30s', target: 0 }
      ]
    };
    
    export default function () {
      http.get(__ENV.TARGET_URL);
      sleep(1);
    }
    k6 run -e TARGET_URL="$URL" load-test.js

    여기서 핵심은 숫자를 크게 만드는 게 아닙니다. 같은 서비스 정의로 트래픽 증가 패턴을 반복 가능하게 재현하는 게 훨씬 더 중요합니다.

    5. ⚠️ 제가 자주 겪었던 문제와 해결 방법

    이 부분이 사실 제일 중요합니다. 테스트는 돌렸는데 결과가 이상하게 튀는 경우가 많거든요. 저도 처음엔 앱 코드 문제인 줄 알았는데, 실제로는 Knative 레이어나 클러스터 리소스 설정이 원인이었던 적이 꽤 있었습니다.

    5-1. 콜드 스타트와 워밍 테스트를 섞어버린 경우

    가장 흔한 실수입니다. 첫 요청 지연이 큰데 그걸 전체 성능 저하로 오해하는 거죠. 해결은 단순합니다.

    • 콜드 스타트 측정은 유휴 상태 이후 첫 요청만 따로 봅니다.
    • 워밍 성능은 미리 몇 번 호출한 뒤 별도 구간에서 측정합니다.
    • Knative 성능 벤치마크 결과표도 두 항목으로 나누는 편이 좋습니다.

    5-2. containerConcurrency를 기본값에만 맡긴 경우

    애플리케이션이 요청당 메모리를 많이 쓰거나, 반대로 가벼운 API인데 너무 보수적으로 잡혀 있으면 확장 패턴이 왜곡됩니다. 특히 Queue-Proxy를 거치는 구조에서는 동시성 설정이 생각보다 체감에 크게 들어옵니다.

    5-3. 클러스터 노드 자원이 먼저 부족한 경우

    이건 홈랩에서 진짜 자주 나옵니다. Knative가 못 버틴 게 아니라, 노드가 새 파드를 올릴 여유가 없는 겁니다. CPU 요청량(requests)과 제한(limits), 이미지 풀링 시간, 스토리지 성능을 같이 봐야 합니다.

    5-4. Ingress 레이어의 영향

    Ingress 설정에 따라 지연 차이가 보일 수 있습니다. 그래서 가능하면 애플리케이션 로그만 보지 말고, 인그레스 컨트롤러와 Knative 관련 컨트롤 플레인 상태도 같이 체크하세요.

    kubectl get pods -A
    kubectl top pods -A
    kubectl describe ksvc benchmark-app
    kubectl logs -l serving.knative.dev/service=benchmark-app --all-containers=true
    Knative 성능 벤치마크 결과에서 파드 수 증가와 지연 시간 변화를 보는 대시보드 이미지

    트래픽 상승에 따라 파드 수와 지연 시간이 어떻게 변하는지 같이 보는 대시보드 예시입니다.

    6. 결과는 어떻게 읽어야 하나

    벤치마크 결과를 볼 때 제가 제일 먼저 보는 건 평균이 아니라 P95/P99 Latency입니다. 평균은 멀쩡한데 꼬리 지연만 확 튀는 경우가 꽤 많거든요. 사용자는 그 느린 요청을 체감합니다.

    보통 해석은 이렇게 가져가면 됩니다.

    관찰 현상 의심 지점 다음 액션
    RPS는 유지되는데 P95만 상승 오토스케일 반응 지연 또는 큐잉 증가 target concurrency와 min scale 검토
    고부하에서 5xx 발생 앱 리소스 부족, 인그레스, 백엔드 의존성 애플리케이션 로그와 노드 상태 확인
    첫 요청만 매우 느림 콜드 스타트 scale to zero 정책과 워밍 전략 분리 검토
    파드 수가 기대보다 안 늘어남 오토스케일 설정 또는 클러스터 자원 한계 autoscaler 설정과 스케줄링 상태 확인

    제가 직접 해보니 좋은 결과란 “숫자가 무조건 높은 상태”가 아니라, 트래픽 증가에 따라 파드 수와 지연이 예측 가능하게 움직이는 상태더라고요. 운영은 재현성과 설명 가능성이 정말 중요하거든요.

    7. 검증 체크리스트와 운영 관점 팁

    실전 반영 전에 아래 체크리스트를 한 번 돌려보시면 좋습니다. 여기서 중요한 포인트! Knative 성능 벤치마크는 한 번 하고 끝내는 문서가 아니라, 리비전이 바뀔 때마다 비교 기준으로 남겨야 합니다.

    • ✅ 동일한 이미지와 동일한 요청 패턴으로 반복 테스트했는가
    • ✅ 콜드 스타트와 워밍 상태를 분리했는가
    • ✅ P95/P99, 에러율, 파드 수를 함께 기록했는가
    • ✅ 노드 자원 부족과 애플리케이션 병목을 구분했는가
    • ✅ Revision 단위로 결과를 보관했는가

    추가로, 이전 글에서 다뤘던 Kubernetes 리소스 요청량 설계와 함께 보시면 훨씬 이해가 빠릅니다. 다음 글에서는 Knative Serving에서 min scale과 scale to zero를 운영 비용 관점에서 어떻게 조정하는지 이어서 다뤄볼 예정입니다.

    8. 자주 묻는 질문

    Q1. 부하 도구는 무엇을 써야 하나요?

    가볍게 시작할 땐 hey면 충분합니다. 요청 패턴을 더 세밀하게 만들고 싶으면 k6가 편하더라고요.

    Q2. Scale to Zero는 벤치마크에서 꺼야 하나요?

    목적에 따라 다릅니다. 운영 현실을 보고 싶다면 켠 상태도 꼭 측정해야 합니다. 다만 워밍 성능과 섞지는 마세요.

    Q3. 수치가 환경마다 너무 다르게 나오는데 정상인가요?

    네, 정상입니다. 클러스터 크기, 네트워크, 인그레스 종류, 이미지 크기, 앱 특성이 모두 영향을 줍니다. 그래서 절대값보다 비교 기준이 중요합니다.

    Knative 성능 벤치마크 결과 해석 체크리스트와 비교 요약 인포그래픽

    콜드 스타트, 워밍 성능, 파드 확장, 지연 구간을 한 번에 정리한 요약 인포그래픽입니다.

    9. 마무리

    이번 글에서는 실전 기준으로 Knative 성능 벤치마크를 어떻게 설계하고, 트래픽 증가 상황에서 무엇을 봐야 하는지 정리해봤습니다. 처음엔 저도 “오토스케일이 되니까 그냥 잘 되겠지” 싶었는데, 실제로 써보니까 동시성 설정, 콜드 스타트 분리, 인그레스 영향, 클러스터 자원 상태를 같이 봐야 결과가 말이 되더라고요.

    결국 중요한 건 화려한 숫자보다 반복 가능한 테스트 절차입니다. 여러분 환경에서도 먼저 작은 단계형 테스트부터 시작해 보세요. 드디어 됐다! 싶은 순간이 오면, 그다음엔 리비전 비교와 비용 최적화까지 연결하시면 됩니다. 운영 관점에서 보면 이 흐름이 제일 오래 갑니다. 혹시 비슷한 삽질 하신 적 있으신가요? 그런 경험이 오히려 제일 좋은 기준이 되더라고요.

  • [Proxmox] Proxmox Datacenter Manager 활용, 다중 노드 관리 베스트 프랙티스 체크리스트

    [Proxmox] Proxmox Datacenter Manager 활용, 다중 노드 관리 베스트 프랙티스 체크리스트

    Proxmox Datacenter Manager 활용, 다중 노드 관리 베스트 프랙티스 체크리스트

    Proxmox Datacenter Manager를 찾는 분들은 대개 비슷한 시점에 도달합니다. 노드(node, 물리 호스트) 한두 대일 때는 괜찮았는데, 어느 순간 VM(가상 머신)과 LXC(Container, 리눅스 컨테이너)가 늘어나고, 클러스터(cluster, 여러 노드의 묶음)도 둘 이상으로 쪼개지면서 운영 피로도가 확 올라가거든요. 저도 홈랩과 업무 환경에서 비슷한 구간을 여러 번 지나왔습니다. 처음엔 “중앙에서 한 번에 보면 끝 아닌가?” 싶었는데, 실제로 써보니까 화면 하나로 끝나는 문제가 아니더라고요. 결국 핵심은 중앙 관리 도구를 붙이기 전에 운영 기준을 먼저 통일하는 것입니다.

    이번 글은 제품 소개보다는 체크리스트에 집중해보겠습니다. 특히 다중 Proxmox 노드를 중앙에서 관리할 때, 어떤 순서로 점검해야 덜 삽질하는지, 제가 직접 해보며 정리한 Proxmox 클러스터 관리 관점의 베스트 프랙티스를 담았습니다.

    Proxmox Datacenter Manager 기반 다중 노드 전체 아키텍처 다이어그램

    여러 Proxmox VE 노드와 클러스터를 중앙에서 바라보는 구성 예시입니다.

    1. 왜 다중 노드 중앙 관리가 중요해졌을까

    쉽게 말해, Proxmox VE 자체는 원래도 웹 UI(Web User Interface, 웹 관리 화면)가 잘 되어 있습니다. 단일 클러스터 안에서는 노드 상태, 스토리지(storage, 저장소), 네트워크(network), 백업 작업까지 꽤 편하게 볼 수 있죠. 문제는 클러스터가 여러 개가 되거나, 성격이 다른 노드가 섞일 때입니다.

    • 개발용 클러스터와 운영용 클러스터가 분리되어 있음
    • CPU 세대나 스토리지 구성이 다른 노드가 섞여 있음
    • 백업 서버, VLAN, 인증 체계가 제각각임
    • 장애가 나면 “어느 노드부터 봐야 하지?”가 바로 안 잡힘

    여기서 다중 노드를 중앙에서 관리하는 체계가 필요해집니다. 다만 중요한 포인트가 하나 있습니다. 중앙 관리 도구는 운영 품질을 대신 만들어주지 않습니다. 이미 꼬여 있는 노드들을 한 화면에 모아 보여줄 뿐이거든요. 저도 처음엔 중앙 화면만 있으면 정리될 줄 알았는데, 오히려 경고가 더 잘 보여서 스트레스만 커진 적이 있었습니다 ㅎㅎ

    2. 개념부터 정리: 다중 노드 관리에서 뭘 묶어야 하는가

    헷갈리기 쉬워서 먼저 선을 그어보겠습니다. Proxmox VE는 KVM(커널 기반 가상머신)과 LXC를 관리하는 가상화 플랫폼이고, Proxmox 클러스터 관리는 보통 pvecm, corosync, shared storage(공유 스토리지) 같은 요소와 함께 움직입니다. 반면 여러 노드나 여러 클러스터를 중앙에서 통합 관리하는 접근은 더 넓은 시야에서 운영 체계를 바라보는 운영 계층으로 이해하면 편합니다.

    구분 단일 Proxmox VE 클러스터 다중 노드/다중 클러스터 운영
    주요 관심사 VM 생성, 마이그레이션, 스토리지 연결 표준화, 상태 가시성, 운영 일관성
    문제 발생 지점 개별 VM 또는 노드 이슈 구성 드리프트(configuration drift, 설정 불일치)
    중요 지표 CPU, RAM, 디스크 사용량 클러스터 간 정책 차이, 백업 누락, 네트워크 불일치
    운영 포인트 기능 사용법 체크리스트와 표준 운영 절차

    여기서 중요한 포인트! 다중 노드 관리를 잘 하려면 먼저 “모든 노드가 비슷한 기준으로 관리되고 있는가?”를 확인해야 합니다. 이게 안 되어 있으면 중앙 관리가 아니라 중앙 혼란이 됩니다.

    3. 사전 체크리스트: 통합 관리를 붙이기 전에 꼭 맞춰야 할 항목

    제가 직접 해보니 이 단계가 제일 중요했습니다. 귀찮아서 건너뛰면 나중에 더 오래 잡아먹습니다. 정말입니다.

    3-1. 노드 기본 정보 표준화

    1. 호스트명(hostname) 규칙 통일: 예) pve-prod-01, pve-prod-02, pve-lab-01
    2. DNS(도메인 이름 해석)와 역방향 조회 확인
    3. NTP(시간 동기화) 상태 통일
    4. 관리용 IP 대역과 스토리지용 IP 대역 분리 여부 확인
    5. 각 노드의 리포지토리(repository, 패키지 저장소) 정책 통일

    시간 동기화가 어긋나면 인증, 클러스터 통신, 로그 분석이 한 번에 꼬입니다. 별거 아닌 것 같아도 장애 분석할 때 진짜 크게 느껴지더라고요.

    hostnamectl
    ip -br addr
    timedatectl status
    cat /etc/hosts
    pvesm status
    pvecm status

    3-2. 스토리지와 백업 정책 점검

    • 로컬 디스크(local disk)와 공유 스토리지(shared storage)의 역할을 분리합니다.
    • VM 디스크가 어디에 올라가는지 팀 내 규칙을 정합니다.
    • 백업 저장 위치와 보존 기간(retention, 보관 정책)을 문서화합니다.
    • 가능하면 Proxmox Backup Server와 작업 스케줄을 함께 표준화합니다.

    저는 예전에 운영 VM은 공유 스토리지, 테스트 VM은 로컬 스토리지로 대충 나눠 썼었는데요. 나중에 정리하려고 보니 마이그레이션 전략이 꼬여서 삽질 좀 했습니다. 처음부터 역할을 나눠두는 게 훨씬 낫습니다.

    3-3. 권한과 접근 경로 정리

    • 관리자 계정 공유를 줄이고 역할 기반 접근 제어(RBAC, 역할 기반 권한 관리)를 씁니다.
    • LDAP, Active Directory, OIDC 같은 외부 인증 연동을 쓴다면 클러스터별 정책 차이를 줄입니다.
    • SSH 접근 정책과 웹 UI 접근 정책을 분리해서 관리합니다.
    Proxmox Datacenter Manager 도입 전 노드 관리 체크리스트 구성 이미지

    중앙 관리 전에 반드시 맞춰야 하는 네트워크, 스토리지, 백업 표준화 항목입니다.

    4. 실전 구현: 다중 노드 관리용 운영 점검 루틴

    이제 실전입니다. 여기서는 특정 버전의 세부 메뉴 이름보다, 가상화 베스트 프랙티스 관점의 운영 루틴을 기준으로 설명드리겠습니다. 이유는 간단합니다. 제품 UI는 바뀔 수 있어도 운영 원칙은 오래 가거든요.

    4-1. 1차 점검: 노드 상태를 CLI로 먼저 본다

    중앙 화면만 믿지 말고, 먼저 각 노드의 기본 상태를 CLI(Command Line Interface, 명령줄)로 확인해보세요. 실제로 써보니까 GUI에서 “느리다” 정도로만 보이던 문제가 CLI에서는 훨씬 빨리 드러나는 경우가 많았습니다.

    # 노드 자원 확인
    uptime
    free -h
    df -h
    
    # Proxmox 클러스터 상태
    pvecm status
    
    # VM / 컨테이너 목록
    qm list
    pct list
    
    # 작업 이력과 서비스 상태 확인
    systemctl --failed
    journalctl -p err -b

    4-2. 2차 점검: 네트워크 브리지와 VLAN 일관성 확인

    다중 노드 운영에서 가장 자주 터지는 문제 중 하나가 브리지(bridge) 이름 불일치입니다. 예를 들어 어떤 노드는 vmbr0에 운영망이 붙어 있고, 다른 노드는 vmbr1에 붙어 있으면 마이그레이션이나 템플릿 재배치 때 계속 발목을 잡습니다.

    # 네트워크 인터페이스 요약
    ip -br link
    ip -br addr
    
    # 브리지 설정 확인
    cat /etc/network/interfaces

    제가 추천하는 방식은 이렇습니다.

    1. 관리망, 스토리지망, 서비스망을 역할별로 구분합니다.
    2. 브리지 이름 규칙을 고정합니다. 예) vmbr0=관리, vmbr1=서비스
    3. VLAN ID 사용 기준을 문서화합니다.
    4. 새 노드 투입 시 네트워크 템플릿부터 맞춥니다.

    4-3. 3차 점검: 업데이트와 재부팅 순서를 표준화

    여기서 많이들 급하게 갑니다. 근데 다중 노드에서는 업데이트(update, 패키지 갱신)보다 순서가 더 중요합니다. 특히 HA(High Availability, 고가용성)나 스토리지 종속성이 있으면 더 그렇고요.

    apt update
    apt list --upgradable
    pveversion -v
    • 한 번에 전체 노드를 올리지 않습니다.
    • 여유 자원이 있는 노드부터 순차적으로 진행합니다.
    • 재부팅 전에 마이그레이션 가능한 VM을 먼저 옮깁니다.
    • 업데이트 후 pvecm status와 스토리지 상태를 다시 확인합니다.

    처음엔 이게 뭔가 싶었는데, 실제 장애는 업데이트 자체보다 “A 노드를 먼저 내리면 B 스토리지 경로가 잠깐 흔들리는 구조” 같은 데서 나오더라고요.

    5. 제가 쓰는 운영 체크리스트: 중앙 관리 관점에서 보면 더 잘 보이는 것들

    아래 항목은 제가 노드 관리할 때 거의 습관처럼 보는 것들입니다. 이건 한 번 템플릿으로 만들어두면 진짜 편합니다.

    1. 노드 상태: CPU steal, 메모리 압박, 디스크 사용률
    2. 클러스터 상태: quorum(정족수) 문제, 통신 지연, 분리 여부
    3. 스토리지 상태: 마운트 누락, 지연 증가, 용량 임계치
    4. 백업 상태: 전날 작업 성공 여부, 증분 백업 체인 무결성
    5. 네트워크 상태: 브리지 누락, VLAN mismatch, MTU 차이
    6. 권한 상태: 만료된 계정, 과한 관리자 권한, 공유 계정 사용
    7. 구성 드리프트: 어떤 노드만 다른 리포지토리, 커널, 방화벽 정책 사용

    특히 다중 노드 중앙 관리 같은 접근의 장점은 “개별 장애”보다 “운영 방식의 불균형”을 더 빨리 발견하게 해준다는 점입니다. 예를 들어 노드 하나가 자꾸 문제를 일으키는 게 아니라, 사실은 그 노드만 시간 동기화가 안 되어 있거나 백업 정책이 빠져 있는 경우가 있거든요.

    Proxmox Datacenter Manager로 보는 다중 노드 모니터링 대시보드 이미지

    노드 상태, 스토리지, 백업, 네트워크를 한눈에 보는 운영 대시보드 예시입니다.

    6. ⚠️ 주의사항과 트러블슈팅: 제가 실제로 자주 만난 문제

    6-1. 클러스터는 멀쩡한데 마이그레이션이 안 되는 경우

    이건 대개 네트워크 이름 불일치나 스토리지 접근 경로 차이였습니다. 증상만 보면 “왜 저 노드만 안 되지?” 싶은데, 하나씩 뜯어보면 브리지 이름이나 스토리지 ID가 다르더라고요.

    • 해결: 브리지 이름, VLAN, 스토리지 ID를 표준화합니다.
    • 검증: 테스트 VM 하나를 만들어 노드 간 이동을 반복해봅니다.

    6-2. 백업은 돌았는데 복원이 불안한 경우

    백업 성공 로그만 보고 안심하면 안 됩니다. 저도 예전에 “백업 성공”만 믿고 있다가 복원 시점에 권한이나 네트워크 연결 문제를 발견한 적이 있습니다. 드디어 됐다 싶었는데 복원 VM이 부팅 후 네트워크를 못 잡아서 다시 손봤네요.

    • 해결: 월 1회라도 복원 테스트를 합니다.
    • 검증: 임시 네트워크에서 실제 부팅과 서비스 확인까지 해봅니다.

    6-3. 특정 노드만 유독 느린 경우

    이럴 때는 무조건 Proxmox 문제로 보지 마세요. BIOS 전원 정책, 디스크 상태, CPU 세대 차이, RAID 캐시 설정, 심지어 펌웨어 차이도 봐야 합니다. 중앙 관리 화면은 증상을 보여주지만, 원인까지 대신 찾아주진 않거든요.

    dmesg | tail -n 50
    lsblk
    smartctl -a /dev/sda
    journalctl -xe

    6-4. 알림이 너무 많아서 오히려 못 보는 경우

    처음 중앙 관리 체계를 붙이면 경고가 확 늘어납니다. 사실 환경이 갑자기 나빠진 게 아니라, 원래 있던 문제를 이제야 한곳에서 보게 된 경우가 많습니다. 이럴 땐 경고를 끄기보다 우선순위를 나누는 게 맞습니다.

    • 즉시 대응: quorum, 스토리지 분리, 백업 실패
    • 당일 대응: 용량 임계치, 업데이트 불일치
    • 정기 점검: 이름 규칙, 문서화 누락, 권한 정리

    7. 검증과 결과: 잘 구축됐는지 어떻게 확인할까

    완성 여부는 “중앙에서 보인다”가 아니라 “운영 판단이 빨라진다”로 확인해야 합니다. 저는 아래 기준으로 봅니다.

    1. 새 노드 추가 시 30분 안에 기본 표준에 편입되는가
    2. 장애 발생 시 어느 노드, 어느 스토리지, 어느 네트워크를 먼저 볼지 바로 정해지는가
    3. 백업 실패와 업데이트 누락을 주간 단위로 추적할 수 있는가
    4. 운영자마다 보는 화면과 체크 순서가 크게 다르지 않은가

    이 기준이 맞으면 다중 노드 중앙 관리 체계를 붙였을 때 체감 효율이 확 올라갑니다. 반대로 이 기준이 없으면 화면만 중앙화되고 운영은 여전히 개인기 중심으로 흘러갑니다.

    # 최종 점검 예시
    pvecm status
    pvesm status
    qm list
    pct list
    systemctl --failed
    journalctl -p warning -b

    🎉 결과적으로 제가 얻은 가장 큰 변화는 “문제가 생겼을 때 감으로 뛰어들지 않게 됐다”는 점입니다. 노드 관리가 체계로 바뀌면 운영 스트레스가 확 줄어듭니다.

    Proxmox Datacenter Manager 운영 체크리스트 적용 전후 비교 인포그래픽

    체크리스트 적용 전후의 운영 흐름과 점검 효율 변화를 비교한 요약 이미지입니다.

    8. 정리와 다음 단계

    오늘 핵심만 다시 정리해보겠습니다. Proxmox 다중 노드 관리는 분명 체계적인 접근의 가치가 있습니다. 하지만 진짜 성과는 도구 자체보다 노드 관리 표준화, 백업 검증, 네트워크 일관성, 업데이트 순서 관리에서 나옵니다. 제가 직접 해보니, 결국 잘 되는 환경은 화려한 기능보다 기본기가 탄탄한 환경이었습니다.

    • ✅ 호스트명, DNS, 시간 동기화부터 맞춥니다.
    • ✅ 스토리지와 백업 정책을 문서화합니다.
    • ✅ 브리지와 VLAN 규칙을 노드 전체에 통일합니다.
    • ✅ 업데이트와 재부팅 순서를 운영 절차로 고정합니다.
    • ✅ 복원 테스트를 반드시 정기적으로 합니다.

    혹시 지금도 클러스터는 늘어나는데 운영 기준은 사람마다 다른 상태이신가요? 그렇다면 중앙 관리 화면을 열기 전에 먼저 체크리스트부터 만들어보세요. 그게 제일 빨랐습니다. 다음 글에서는 Proxmox Backup Server 백업 검증 루틴이나 Ceph 스토리지 운영 체크포인트를 이어서 다뤄보겠습니다. 이전 글에서 다룬 VLAN 설계나 홈랩 네트워크 분리 방법이 있다면 함께 보셔도 흐름이 잘 이어질 겁니다.

    자주 묻는 질문

    Q1. 단일 클러스터만 있어도 다중 노드 관리 체계가 필요할까요?

    반드시 그렇진 않습니다. 노드 수가 적고 운영자가 한 명이면 기본 Proxmox VE UI만으로도 충분한 경우가 많습니다. 다만 앞으로 노드가 늘어날 계획이라면 운영 체크리스트를 먼저 준비해두는 게 좋습니다.

    Q2. 다중 노드 관리에서 가장 먼저 표준화할 항목은 뭔가요?

    저는 호스트명, 시간 동기화, 네트워크 브리지 이름 이 세 가지를 가장 먼저 봅니다. 이 셋이 흔들리면 나머지도 줄줄이 흔들리더라고요.

    Q3. 가상화 베스트 프랙티스에서 제일 많이 놓치는 부분은요?

    백업 성공 여부만 보고 복원 테스트를 안 하는 부분입니다. 운영에서 진짜 중요한 건 백업 파일 존재가 아니라 복원 가능성입니다.

  • [클라우드] VMware ESXi에서 OpenStack으로 전환한 실제 사례

    [클라우드] VMware ESXi에서 OpenStack으로 전환한 실제 사례

    [클라우드] VMware ESXi에서 OpenStack으로 전환한 실제 사례

    VMware OpenStack 마이그레이션을 고민하는 분들이 요즘 정말 많으시죠. 라이선스 정책 변화나 비용 구조, 그리고 운영 자동화 수준을 다시 점검해야 하는 시점이 오면 결국 한 번은 ESXi OpenStack 전환을 검토하게 되더라고요. 저도 처음엔 “하이퍼바이저(Hypervisor, 가상화 실행 계층)만 바꾸면 끝나는 거 아닌가?” 싶었는데, 실제로 해보니 전혀 아니었습니다. 컴퓨트(Compute), 네트워크(Network), 스토리지(Storage), 이미지(Image) 관리 방식이 다 바뀌거든요. 그래서 오늘은 제가 홈랩과 내부 테스트 환경에서 진행했던 흐름을 바탕으로, VMware 대안 OpenStack을 검토할 때 어디서 막히고 어떻게 풀어야 하는지 경험 위주로 정리해보겠습니다.

    특히 이 글은 “OpenStack이 좋아 보이는데 실제 전환은 어떻게 하지?”, “클라우드 마이그레이션 사례를 봐도 다 추상적이던데 실무 감각이 있는 글이 없네” 하셨던 분들께 맞춰 썼습니다. 숫자 뻥튀기나 과장 없이, 제가 직접 부딪히며 정리한 포인트만 담아볼게요.

    VMware OpenStack 마이그레이션 전체 아키텍처 다이어그램

    기존 ESXi 가상머신이 이미지 변환과 네트워크 재설계를 거쳐 OpenStack으로 이동하는 전체 흐름을 보여주는 개요 이미지입니다.

    왜 VMware ESXi에서 OpenStack으로 옮기게 될까요

    쉽게 말해서 ESXi는 가상화 플랫폼 중심의 운영 경험을 주고, OpenStack은 클라우드 운영체계에 가깝습니다. 둘 다 가상머신(VM, Virtual Machine)을 띄운다는 점은 같지만, 운영 철학이 꽤 다릅니다. VMware 환경은 관리 콘솔이 잘 정리되어 있고 초기 안정화가 쉬운 편이죠. 반면 OpenStack은 구성 요소가 많아서 처음엔 복잡해 보이지만, 자동화와 API(Application Programming Interface, 프로그램 제어 인터페이스) 중심 운영으로 넘어가면 확실히 강점이 있습니다.

    제가 전환을 결심했던 이유도 단순했습니다.

    • 비용 구조를 장기적으로 통제하고 싶었습니다.
    • API 기반 자동화를 더 강하게 가져가고 싶었습니다.
    • 네트워크를 더 세밀하게 분리하고 싶었습니다.
    • 벤더 종속성(Vendor lock-in, 특정 벤더 의존)을 줄이고 싶었습니다.

    다만 여기서 중요한 게 하나 있어요. VMware OpenStack 마이그레이션은 제품 교체가 아니라 운영 모델 전환이라는 점입니다. 이거 무시하면 중간에 꼭 한 번 크게 흔들려요. 저도 처음엔 VM만 잘 옮기면 될 줄 알았는데, 보안그룹(Security Group, 가상 방화벽), 네트워크 세그먼트, 스토리지 타입 설계에서 삽질 좀 했습니다 ㅎㅎ

    핵심 개념 정리: ESXi와 OpenStack은 무엇이 다를까

    이 부분은 꼭 짚고 넘어가야 해요. 독자분들이 제일 많이 헷갈려 하시는 부분이거든요.

    영역 VMware ESXi 중심 OpenStack 중심
    가상화 실행 ESXi 보통 KVM(Kernel-based Virtual Machine)
    관리 계층 vCenter OpenStack API와 Horizon
    이미지 관리 템플릿, OVA/OVF Glance(글랜스, 이미지 서비스)
    컴퓨트 제어 클러스터/호스트 중심 Nova(노바, 컴퓨트 서비스)
    네트워크 vSwitch, 포트 그룹 Neutron(뉴트론, 네트워크 서비스)
    블록 스토리지 데이터스토어 중심 Cinder(신더, 블록 스토리지)
    인증 vCenter 계정/연동 Keystone(키스톤, 인증 서비스)

    쉽게 말해서 VMware에서는 사람이 콘솔에서 정리해주는 느낌이 강했다면 OpenStack은 “정책과 API로 자원을 선언적으로 다룬다”는 느낌이 더 강합니다. 그래서 클라우드 마이그레이션 사례를 볼 때도 VM 파일 이동만 보면 안 되고, 네트워크와 접근제어를 같이 봐야 합니다.

    전환 전에 꼭 분류해야 할 워크로드

    1. 상태 저장형(Stateful)인지 확인합니다. 데이터베이스처럼 디스크 의존도가 높으면 더 신중해야 합니다.
    2. 정적 IP, MAC 의존성이 있는지 봅니다. 방화벽이나 라이선스 서버가 여기서 많이 걸립니다.
    3. 운영체제 부팅 방식이 BIOS인지 UEFI인지 점검합니다.
    4. 게스트 OS 안에 VMware Tools 의존 설정이 있는지 확인합니다.
    5. 백업/복구 체계가 OpenStack 쪽에서도 유지되는지 따져봅니다.

    제가 직접 해보니 이 분류 작업이 귀찮아 보여도 가장 중요했습니다. 이걸 대충 하면 나중에 전환 일정이 아니라 장애 대응 일정이 되어버립니다.

    사전 준비: VMware OpenStack 마이그레이션 체크리스트

    실전 들어가기 전에 제가 잡았던 기준은 아래와 같았습니다. 여기서 절반이 결정된다고 봐도 됩니다.

    • 대상 VM 목록: 운영, 스테이징, 개발을 분리합니다.
    • 종속성 매핑: DB, 외부 API, DNS, NTP, 라이선스 서버 연결을 정리합니다.
    • 네트워크 설계: OpenStack 테넌트 네트워크와 외부 네트워크를 미리 정의합니다.
    • 이미지 변환 절차: VMDK에서 QCOW2 또는 RAW로 갈지 정합니다.
    • 전환 방식: 빅뱅(Big Bang)보다 단계적 전환을 권장합니다.
    • 롤백 계획: 문제 생기면 다시 ESXi에서 기동할 수 있게 둡니다.

    저는 처음에 네트워크를 나중에 맞추면 되겠지 하고 넘어갔다가, OpenStack의 포트(Port)와 보안그룹 정책 때문에 통신 확인에 시간을 꽤 썼습니다. VM 부팅보다 통신 성공이 더 어렵더라고요.

    실전 구현 1: ESXi VM 추출과 디스크 변환

    이제 본론입니다. 제가 많이 썼던 흐름은 VM 종료 – 디스크 추출 – 이미지 변환 – OpenStack 업로드 – 테스트 부팅 순서였습니다. 무중단 전환이 절대적으로 필요한 서비스가 아니라면, 이 방식이 가장 단순하고 예측 가능했습니다.

    1. VMware 쪽 VM 상태 확인

    govc vm.info -vm /Datacenter/vm/app-server-01
    

    govc는 VMware vSphere 환경을 CLI(Command Line Interface, 명령행 인터페이스)로 다룰 때 꽤 유용합니다. 환경에 따라 vCenter를 쓰지 않고 직접 ESXi에서 파일을 꺼낼 수도 있습니다.

    2. OVF 또는 VMDK 형태로 추출

    ovftool vi://[email protected]@vcenter.example.local/Datacenter/vm/app-server-01 ./app-server-01
    

    환경에 따라 OVA/OVF 패키지로 받거나 VMDK만 직접 확보해도 됩니다. 저는 처음엔 OVA가 편해 보여서 그렇게 했는데, 실제로는 디스크 변환만 필요할 때 VMDK 직취득이 더 단순한 경우도 있었습니다.

    3. VMDK를 QCOW2로 변환

    qemu-img convert -p -f vmdk -O qcow2 app-server-01-disk1.vmdk app-server-01.qcow2
    qemu-img info app-server-01.qcow2
    

    여기서 qemu-img는 거의 필수 도구라고 보시면 됩니다. 변환 후 qemu-img info로 포맷과 가상 크기를 꼭 확인하세요. 저는 한 번은 스냅샷 체인이 남은 VMDK를 잘못 잡아서 이미지가 이상하게 올라간 적이 있었습니다.

    VMware OpenStack 마이그레이션에서 VMDK를 QCOW2로 변환하는 작업 흐름 이미지

    VMDK 추출, qemu-img 변환, Glance 업로드로 이어지는 실제 작업 흐름을 설명하는 이미지입니다.

    실전 구현 2: OpenStack 이미지 업로드와 네트워크 구성

    OpenStack으로 넘어오면 이제부터는 이미지와 네트워크가 핵심입니다. 이 구간에서 “드디어 됐다!” 싶다가도 보안그룹 하나 빠뜨리면 SSH도 안 붙고, 웹도 안 열리고, 괜히 이미지 탓하게 됩니다.

    1. 이미지 등록

    openstack image create "app-server-01" \
      --file app-server-01.qcow2 \
      --disk-format qcow2 \
      --container-format bare \
      --private
    

    OpenStack의 Glance는 이미지 저장소 역할을 합니다. 템플릿 개념과 비슷하지만, API 중심 운영에 더 잘 녹아 있습니다.

    2. 네트워크와 서브넷 준비

    openstack network create prod-net
    openstack subnet create prod-subnet \
      --network prod-net \
      --subnet-range 192.168.100.0/24 \
      --dns-nameserver 8.8.8.8
    

    물론 실무에서는 외부 DNS를 그대로 넣기보다 내부 DNS 체계를 맞추는 경우가 많습니다. 여기서는 예시만 단순하게 보여드리는 거예요.

    3. 보안그룹 생성

    openstack security group create web-sec
    openstack security group rule create --protocol tcp --dst-port 22 web-sec
    openstack security group rule create --protocol tcp --dst-port 80 web-sec
    openstack security group rule create --protocol tcp --dst-port 443 web-sec
    

    여기서 중요한 포인트! VMware 쪽에서는 포트 그룹과 상위 방화벽 정책으로 어느 정도 익숙하게 처리되던 것이, OpenStack에서는 인스턴스 단위 정책으로 체감될 때가 있습니다. 처음엔 이게 뭔가 싶었는데, 익숙해지면 오히려 훨씬 명확합니다.

    4. 인스턴스 기동

    openstack server create app-server-01 \
      --flavor m1.medium \
      --image app-server-01 \
      --network prod-net \
      --security-group web-sec
    

    이후 Floating IP(Floating IP, 외부 접근용 유동 IP)가 필요한 구조라면 외부 네트워크에 붙여줘야 합니다.

    openstack floating ip create public-net
    openstack server add floating ip app-server-01 203.0.113.10
    

    ⚠️ 실제로 많이 막히는 문제들: ESXi OpenStack 전환 트러블슈팅

    여기가 제일 중요합니다. 성공 사례는 대부분 결과만 보여주는데, 실무에서는 이 구간이 진짜 본게임입니다.

    1. 부팅은 되는데 네트워크가 안 붙는 경우

    원인은 보통 세 가지였습니다.

    • 게스트 OS 안에 VMware 네트워크 인터페이스 설정이 남아 있는 경우
    • udev 규칙 때문에 NIC 이름이 바뀌는 경우
    • OpenStack 보안그룹에서 필요한 포트가 안 열린 경우

    리눅스는 부팅 후 인터페이스 이름을 먼저 확인했습니다.

    ip addr
    ip route
    journalctl -b | grep -i network
    

    특히 CentOS나 Ubuntu 구버전 계열은 예전 NIC 정보 때문에 인터페이스가 달라지는 일이 종종 있었습니다. 저는 이 문제를 몇 번 겪고 나서는 이미지 올리기 전에 네트워크 설정 파일을 먼저 정리하는 습관이 생겼습니다.

    2. 디스크는 붙었는데 부팅이 불안정한 경우

    이건 VirtIO(Virtual I/O, 가상 장치 고속 드라이버) 드라이버나 부팅 로더 문제일 때가 많았습니다. 윈도우 게스트는 VirtIO 드라이버 준비 여부를 꼭 점검하셔야 하고, 리눅스는 initramfs 안에 필요한 드라이버가 포함됐는지 보는 게 좋습니다.

    3. 시간이 틀어지거나 애플리케이션이 이상 동작하는 경우

    NTP(Network Time Protocol, 시간 동기화)와 DNS는 가볍게 보면 안 됩니다. OpenStack 쪽 인스턴스가 올라오고 서비스는 떠 있는데, 인증이나 토큰 검증이 계속 실패하면 시간 동기화부터 보셔야 합니다. 이거 진짜 자주 놓칩니다.

    4. 스냅샷 의존 운영 습관

    VMware에서 스냅샷을 임시 안전장치처럼 쓰던 습관이 있으면 OpenStack으로 넘어와서 운영 방식 자체를 다시 잡아야 합니다. 인스턴스 스냅샷, 볼륨 스냅샷, 이미지 버전 관리, 백업 정책을 분리해서 생각해야 하거든요. 저도 처음엔 “스냅샷 느낌이 왜 다르지?” 싶었는데, 클라우드식 운영으로 사고방식을 바꾸니까 정리가 되더라고요.

    ESXi OpenStack 전환 시 OpenStack 네트워크와 보안그룹 구성 다이어그램

    테넌트 네트워크, 라우터, 보안그룹, 플로팅 IP 관계와 함께 통신 장애 포인트를 표시하는 설명 이미지입니다.

    검증 방법: 클라우드 마이그레이션 사례에서 놓치면 안 되는 체크

    전환이 끝났다고 바로 운영으로 넘기면 안 됩니다. 저는 아래 순서로 검증했습니다.

    1. 인스턴스 상태 확인: ACTIVE 상태인지, 콘솔 로그에 에러가 없는지 봅니다.
    2. 네트워크 점검: 내부 통신, 외부 통신, DNS 해석을 확인합니다.
    3. 애플리케이션 점검: 웹, API, 배치 작업, 데이터 연결을 확인합니다.
    4. 성능 비교: 최소한 부팅 시간, 응답성, 디스크 지연 체감은 체크합니다.
    5. 운영 도구 점검: 백업, 모니터링, 로그 수집이 붙는지 확인합니다.
    openstack server list
    openstack console log show app-server-01
    ping -c 4 192.168.100.10
    curl -I http://192.168.100.10
    

    여기서 제가 제일 강조하고 싶은 건, VM이 떠 있는 것과 서비스가 정상인 것은 다르다는 점입니다. 실제로는 애플리케이션 레벨 체크가 마지막 문턱이었습니다.

    클라우드 마이그레이션 사례 검증을 위한 OpenStack 인스턴스 상태 대시보드

    마이그레이션 이후 인스턴스 상태, 네트워크 연결, 서비스 응답을 한눈에 확인하는 검증 대시보드 이미지입니다.

    전환 결과: 제가 얻은 것과 예상 밖의 변화

    결론부터 말씀드리면, 제 경우엔 VMware OpenStack 마이그레이션 자체는 성공이었습니다. 특히 개발/스테이징 계열 워크로드에서는 OpenStack의 장점이 빨리 보였습니다. API로 인스턴스를 만들고, 네트워크를 분리하고, 이미지 기반으로 재현 가능한 환경을 만드는 흐름이 아주 좋았거든요.

    반대로 예상보다 시간이 더 걸린 부분도 있었습니다.

    • 운영팀의 사고방식 전환: 가상머신 관리에서 클라우드 자원 관리로 바뀝니다.
    • 네트워크 설계: OpenStack Neutron 이해도가 없으면 초반에 막힙니다.
    • 표준 이미지 전략: 아무 VM이나 옮기는 방식은 오래 못 갑니다.

    즉, VMware 대안 OpenStack은 충분히 현실적인 선택지이지만, “기존 VM을 그냥 다른 데 올린다”는 접근으로는 만족도가 떨어질 수 있습니다. 반대로 이미지 표준화, 자동화, 셀프서비스 포털, IaC(Infrastructure as Code, 코드형 인프라)까지 연결하면 진가가 나옵니다.

    정리와 다음 단계: 이런 순서로 접근하면 덜 흔들립니다

    혹시 지금 전환을 검토 중이시라면, 제가 추천하는 순서는 이렇습니다.

    1. 가장 덜 중요한 개발 VM부터 파일럿으로 옮깁니다.
    2. 이미지 변환 절차를 문서화합니다.
    3. 네트워크와 보안그룹 템플릿을 먼저 만듭니다.
    4. 백업, 모니터링, 로그 수집을 붙인 뒤 운영계로 확장합니다.
    5. 마지막에 표준 이미지와 자동 배포 흐름까지 정리합니다.

    사실 저도 처음엔 OpenStack이 너무 많은 조각으로 보였는데, 하나씩 이해하고 나니 왜 다들 클라우드 운영체계라고 부르는지 알겠더라고요. 반대로 VMware에서 익숙했던 편의 기능이 사라진 듯 느껴지는 순간도 있었는데, 그건 “없다”기보다 “다른 방식으로 설계해야 한다”에 가까웠습니다.

    이전 글에서 다뤘던 가상화 스토리지 설계 내용과도 연결되는 부분이 있고, 다음 글에서는 OpenStack에서 표준 이미지와 cloud-init(cloud-init, 초기 부팅 자동 설정)를 묶어 운영하는 방법도 다뤄볼 예정입니다. 여기까지 정리해보니, 결국 성공 포인트는 기술 하나가 아니라 운영 모델의 재설계였습니다.

    VMware 대안 OpenStack 전환 포인트 비교 인포그래픽

    운영 모델, 네트워크, 스토리지, 자동화 관점에서 VMware와 OpenStack의 차이를 요약한 마무리 인포그래픽입니다.

    자주 묻는 질문

    Q1. ESXi에서 OpenStack으로 무중단 전환이 가능한가요?

    가능 여부는 애플리케이션 구조에 달려 있습니다. 일반적인 단일 VM 서비스는 점검 시간을 잡고 이미지 기반으로 옮기는 편이 더 현실적이었습니다.

    Q2. 모든 VMware VM이 그대로 OpenStack에서 잘 동작하나요?

    아닙니다. 네트워크 설정, 드라이버, 부팅 방식, 에이전트 의존성에 따라 손봐야 할 부분이 꽤 있습니다. 특히 오래된 VM일수록 사전 점검이 중요합니다.

    Q3. OpenStack이 무조건 비용 절감으로 이어지나요?

    단순히 플랫폼만 바꾼다고 바로 그렇진 않습니다. 운영 역량, 자동화 수준, 표준화 정도가 함께 따라와야 의미 있는 효과가 납니다.

    Q4. 가장 먼저 테스트할 워크로드는 무엇이 좋을까요?

    개발 또는 스테이징 환경의 웹 애플리케이션부터 권장합니다. 네트워크와 이미지 변환 절차를 검증하기에 적당하고, 실패했을 때 영향도 상대적으로 적습니다.

  • [k8s] ArgoCD 도입 실패 사례 분석: GitOps 전환 시 흔한 실수와 방지 전략

    [k8s] ArgoCD 도입 실패 사례 분석: GitOps 전환 시 흔한 실수와 방지 전략

    [DevOps] ArgoCD 도입 실패 사례 분석과 GitOps 실수 방지

    ArgoCD 도입 실패 이야기는 생각보다 흔합니다. 저도 처음엔 GitOps(깃옵스, Git을 단일 진실 공급원으로 삼는 운영 방식)만 붙이면 배포가 깔끔해질 줄 알았거든요. 그런데 실제로 해보니, ArgoCD(아르고CD, Kubernetes 선언형 배포 도구)를 넣는 순간 오히려 배포가 더 복잡해지는 팀도 많았습니다. 특히 CI/CD 전환 사례를 보면, 기술 문제가 아니라 역할 분리, 저장소 구조, 승인 흐름 같은 운영 설계에서 먼저 무너지는 경우가 많더라고요. 이번 글은 제가 현업과 홈랩에서 반복해서 본 ArgoCD 도입 실패 패턴을 중심으로, 왜 그런 일이 생기는지와 어떻게 피해야 하는지를 정리해보겠습니다.

    혹시 이런 경험 있으신가요? 배포 자동화는 넣었는데 누가 어떤 값을 바꿨는지 더 헷갈리고, 장애가 나면 Git이 문제인지 클러스터가 문제인지부터 추적하게 되는 상황 말입니다. 여기서 중요한 포인트는, ArgoCD 자체가 문제라기보다 GitOps 실수가 누적되면서 운영 복잡도가 폭발한다는 점입니다.

    ArgoCD 도입 실패와 GitOps 전환 흐름을 설명하는 아키텍처 이미지

    Git 저장소, CI 파이프라인, ArgoCD, Kubernetes 클러스터 사이의 흐름과 실패 포인트를 한눈에 보여주는 개요 이미지입니다.

    1. 왜 ArgoCD 도입 실패가 반복될까요?

    쉽게 말해 ArgoCD는 배포 버튼을 없애는 도구가 아니라, 변경 관리 방식 자체를 바꾸는 도구입니다. 그래서 예전 CI/CD에서는 잘 통하던 습관이 GitOps로 오면 바로 문제를 만듭니다. 예를 들면 이런 식입니다.

    • 운영값을 Git이 아니라 사람 손으로 클러스터에서 직접 수정함
    • 애플리케이션 코드 저장소와 배포 매니페스트 저장소의 책임이 불명확함
    • 자동 동기화(auto-sync)를 켰는데 승인 절차는 그대로 수동 운영을 기대함
    • Helm(헬름, Kubernetes 패키지 관리 도구) 값 파일이 환경별로 제멋대로 늘어남
    • 장애가 나도 누가 마지막 변경을 만들었는지 추적이 어려움

    저도 처음엔 이게 뭔가 싶었는데, 결국 핵심은 하나였습니다. ArgoCD는 배포 도구이면서 동시에 운영 규율을 강제하는 도구라는 점입니다. 팀이 그 규율을 합의하지 않은 상태에서 도입하면, ArgoCD 문제점처럼 보이는 현상이 사실은 프로세스 문제로 터집니다.

    2. GitOps와 ArgoCD를 아주 쉽게 설명해보면

    GitOps는 “실제 운영 상태는 Git에 적힌 선언대로 맞춘다”는 철학입니다. ArgoCD는 그 선언과 클러스터 상태를 계속 비교해서 drift(드리프트, 선언과 실제 상태가 어긋난 상태)를 감지하고 맞춰주는 역할을 하죠.

    예전 방식은 대체로 이랬습니다. CI 서버가 빌드하고, 누군가 kubectl(쿠버네티스 CLI)이나 Helm으로 운영 클러스터에 직접 배포합니다. 반면 GitOps 방식은 배포 변경도 Pull Request(PR, 변경 제안 요청)로 남고, 승인 후 Git이 바뀌면 ArgoCD가 그걸 따라갑니다. 감사 추적(audit trail, 변경 이력 추적)이 되는 대신, 우회 수정이 어려워집니다. 이 점이 장점이자 초반 저항 포인트입니다.

    항목 기존 CI/CD GitOps + ArgoCD
    배포 트리거 파이프라인 또는 운영자 수동 실행 Git 변경 반영
    변경 이력 파이프라인 로그 중심 Git 커밋과 PR 중심
    긴급 수정 클러스터에서 직접 수정 가능 직접 수정 시 drift 발생
    권한 통제 클러스터 권한 중심 저장소 권한과 승인 흐름 중요
    실패 원인 스크립트 불안정, 환경 차이 저장소 구조, 책임 분리 실패

    그래서 ArgoCD 도입 실패를 줄이려면 설치보다 운영 모델을 먼저 설계해야 합니다. 이걸 건너뛰면 나중에 진짜 많이 돌아갑니다. 저도 삽질 좀 했습니다 ㅎㅎ

    3. 실제로 많이 본 실패 사례 4가지

    3-1. 저장소 구조를 너무 늦게 정한 경우

    가장 흔한 실수입니다. 앱 소스와 배포 설정이 한 저장소에 섞여 있거나, 반대로 너무 잘게 쪼개져서 어디를 기준으로 봐야 하는지 모호한 경우죠. 처음엔 편해 보였는데, 팀이 커질수록 충돌이 심해집니다. 누가 이미지 태그를 관리하고, 누가 replica 수를 바꾸고, 누가 Ingress(인그레스, 외부 트래픽 진입점)를 수정하는지 경계가 안 잡히거든요.

    3-2. 자동 동기화만 켜고 승인 체계를 안 만든 경우

    auto-sync는 정말 편합니다. 드디어 됐다! 싶은 순간이 오거든요. 근데 여기서 바로 사고가 납니다. 운영 반영 전 검토가 필요한 팀인데도 자동 배포를 먼저 켜버리면, 잘못된 값 하나가 바로 프로덕션으로 갑니다. 도구는 빨라졌는데 프로세스는 그대로인 상태죠.

    3-3. Secret 관리 방식을 정하지 않은 경우

    GitOps 실수에서 빠지지 않는 항목입니다. 민감 정보(Secret)를 평문으로 저장하면 안 되고, 그렇다고 운영자가 클러스터에만 몰래 만들어두면 Git과 실제 상태가 분리됩니다. 저는 이 부분에서 팀마다 가장 오래 멈추는 걸 많이 봤습니다. Sealed Secrets(시일드 시크릿)나 External Secrets Operator 같은 접근을 검토하되, 핵심은 “Git에 무엇을 남기고 실제 값은 어디서 주입할지”를 팀 단위로 합의하는 겁니다.

    3-4. Drift를 장애로 볼지, 운영 유연성으로 볼지 합의가 없는 경우

    운영자가 급한 패치를 직접 넣는 문화가 남아 있으면 ArgoCD는 계속 OutOfSync(아웃오브싱크) 상태를 만들 겁니다. 이걸 경고로 볼지, 바로 되돌릴지, 특정 리소스는 예외로 둘지 정하지 않으면 경보만 쌓이고 신뢰가 깨집니다. 이 지점이 대표적인 ArgoCD 문제점처럼 보이는데, 사실은 정책 부재에 가깝습니다.

    4. 실전 구현: 실패 확률을 낮추는 최소 전환 절차

    제가 직접 해보니, 처음부터 전 서비스에 GitOps를 거는 것보다 작은 서비스 하나로 운영 규칙을 검증하는 게 훨씬 낫더라고요. 아래는 많이 무리하지 않는 최소 절차입니다.

    1. 배포 대상 네임스페이스(namespace) 하나를 파일럿으로 고릅니다.
    2. 애플리케이션 코드 저장소와 배포 매니페스트 저장소의 책임을 분리합니다.
    3. ArgoCD 프로젝트(AppProject)로 허용 대상 클러스터/네임스페이스를 제한합니다.
    4. 자동 동기화는 바로 켜지 말고, 먼저 수동 sync로 운영 흐름을 익힙니다.
    5. 변경 승인 기준을 PR 템플릿과 리뷰 규칙으로 문서화합니다.
    6. Drift 발생 시 대응 절차를 정합니다.

    예시로는 아래처럼 시작하면 무난합니다.

    kubectl create namespace argocd
    kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
    kubectl get pods -n argocd

    설치 자체보다 더 중요한 건 프로젝트 경계를 먼저 두는 일입니다.

    apiVersion: argoproj.io/v1alpha1
    kind: AppProject
    metadata:
      name: sample-project
      namespace: argocd
    spec:
      description: sample project for controlled GitOps rollout
      sourceRepos:
        - 'https://github.com/example/platform-manifests.git'
      destinations:
        - namespace: sample-app
          server: 'https://kubernetes.default.svc'
      clusterResourceWhitelist:
        - group: '*'
          kind: '*'

    그 다음 애플리케이션은 이렇게 붙일 수 있습니다.

    apiVersion: argoproj.io/v1alpha1
    kind: Application
    metadata:
      name: sample-app
      namespace: argocd
    spec:
      project: sample-project
      source:
        repoURL: 'https://github.com/example/platform-manifests.git'
        targetRevision: main
        path: apps/sample-app/overlays/prod
      destination:
        server: 'https://kubernetes.default.svc'
        namespace: sample-app
      syncPolicy: {}

    여기서 일부러 자동 동기화 설정을 비워둔 것이 포인트입니다. 처음엔 수동 sync로 팀이 변경 흐름을 이해하게 만드는 게 좋습니다. 자동화는 익숙해진 뒤에 켜도 늦지 않습니다.

    ArgoCD 도입 실패를 줄이기 위한 AppProject와 저장소 구조 구성 이미지

    AppProject 경계, Application 연결, PR 승인 후 반영되는 흐름을 시각적으로 설명하는 이미지입니다.

    5. CI/CD 전환 사례에서 특히 조심해야 할 체크포인트

    기존 파이프라인에서 이미지 빌드까지는 잘 돌아가는데 GitOps로 넘기면서 꼬이는 경우가 많습니다. 보통 CI는 artifact(아티팩트, 배포 가능한 결과물)를 만들고, CD는 배포를 실행합니다. GitOps에선 이 경계가 바뀝니다. CI가 직접 배포하지 않고, 이미지 태그나 차트 값을 Git에 반영하는 식으로 역할이 이동하죠.

    예를 들면 이런 방식입니다.

    # CI job example
    export IMAGE_TAG=${GIT_COMMIT_SHA}
    sed -i "s/tag: .*/tag: ${IMAGE_TAG}/" apps/sample-app/overlays/prod/values.yaml
    git add apps/sample-app/overlays/prod/values.yaml
    git commit -m "chore: deploy sample-app ${IMAGE_TAG}"
    git push origin main

    이 방식은 단순하지만, 바로 main 브랜치에 반영하면 위험합니다. 제가 추천하는 건 별도 배포 브랜치나 PR 자동 생성 방식입니다. 사람이 마지막으로 한 번 더 보고 머지하는 흐름이 초반 안정화에 꽤 도움이 됩니다.

    • 프로덕션 반영은 PR 승인 후에만 가능하게 설정
    • 리뷰어를 플랫폼 담당자와 서비스 담당자로 분리
    • 롤백 기준을 Git revert 중심으로 문서화
    • 수동 kubectl 적용은 예외 상황에서만 허용

    이런 기본선만 있어도 CI/CD 전환 사례에서 실패 확률이 꽤 내려갑니다.

    6. ⚠️ 트러블슈팅: 제가 실제로 많이 본 문제와 해결법

    여기서부터는 정말 많이 부딪히는 부분들입니다. 처음엔 저도 “왜 sync는 성공인데 앱은 안 뜨지?” 같은 상황을 자주 만났거든요.

    증상 원인 해결 방향
    OutOfSync가 계속 발생 운영자가 클러스터에서 직접 수정 직접 수정 금지 원칙 정리, 예외 리소스만 ignore 설정 검토
    Sync 성공인데 서비스 장애 매니페스트 문법은 맞지만 런타임 의존성 누락 readinessProbe, Secret 참조, ConfigMap 값 검증 강화
    배포가 너무 자주 일어남 이미지 태그나 공통 값 파일이 과도하게 변경됨 환경별 경로 분리, 변경 범위 최소화
    리뷰 병목 발생 모든 변경이 한 저장소에 몰림 팀 단위 경계 재설계, CODEOWNERS 활용
    롤백이 헷갈림 Git revert와 수동 핫픽스가 섞임 롤백 절차를 Git 기준으로 단일화

    6-1. ignoreDifferences 남용

    ArgoCD에는 특정 필드 차이를 무시하는 기능이 있습니다. 편하긴 한데, 이걸 남용하면 drift 감지 의미가 사라집니다. 정말 컨트롤러가 자동으로 바꾸는 필드처럼 불가피한 경우에만 제한적으로 쓰는 게 맞습니다.

    6-2. Helm 값 파일 난립

    환경이 늘수록 values 파일이 너무 많아집니다. dev, stage, prod는 그렇다 쳐도 팀별 패치, 긴급 패치, 지역별 패치가 늘어나면 나중에 아무도 구조를 설명 못 합니다. 저도 홈랩에서 비슷하게 풀었다가, 결국 Kustomize(커스터마이즈, 오버레이 기반 설정 관리)와 역할을 분리하면서 정리했었습니다.

    6-3. 알림 없이 운영

    Sync 실패나 Health degraded(헬스 저하) 이벤트를 아무도 못 받으면, ArgoCD UI를 매번 열어보기 전까지 장애를 놓치게 됩니다. 알림 체계는 초반부터 붙이는 게 좋습니다. 최소한 운영 채널로 실패 이벤트는 전달되게 구성해두세요.

    7. 검증: 전환이 잘 되고 있는지 어떻게 확인할까

    성공 기준도 미리 정의해야 합니다. 그냥 “ArgoCD가 떴다”로 끝내면 안 됩니다. 저는 보통 아래 항목으로 봅니다.

    1. 배포 변경이 모두 PR과 커밋으로 추적되는가
    2. 직접 클러스터 수정 비율이 줄고 있는가
    3. 장애 시 마지막 변경점 확인 시간이 짧아졌는가
    4. 롤백 절차가 Git revert 기준으로 일관되게 동작하는가
    5. 서비스별 소유권(owner)이 저장소 구조와 일치하는가

    ArgoCD UI에서 Health, Sync 상태를 보는 것도 좋지만, 그것만으론 부족합니다. 진짜 중요한 건 운영팀과 개발팀이 같은 변경 이력을 보고 같은 언어로 이야기하게 됐는지입니다. 이게 되면 도입이 절반은 성공한 겁니다. 실제로 써보니까 배포 속도보다 커뮤니케이션 비용이 더 크게 줄더라고요.

    ArgoCD 도입 실패 검증을 위한 Sync와 Health 상태 대시보드 이미지

    배포 상태 확인, 이상 징후 탐지, 롤백 판단 포인트를 한눈에 보여주는 결과 검증 이미지입니다.

    8. 정리 FAQ: 많이 받는 질문

    Q1. ArgoCD는 무조건 자동 동기화로 써야 하나요?

    아닙니다. 초반에는 수동 sync가 오히려 안전합니다. 팀이 GitOps 흐름에 익숙해지고 승인 절차가 자리 잡으면 그때 auto-sync를 검토해도 됩니다.

    Q2. 기존 CI/CD를 전부 버려야 하나요?

    그건 아닙니다. 빌드와 테스트는 CI가 계속 담당하고, 배포 실행만 Git 기반으로 넘기는 식이 일반적입니다.

    Q3. ArgoCD 문제점은 결국 도구 한계 아닌가요?

    일부는 맞지만, 현장에서 보이는 대부분은 정책과 구조 문제였습니다. 특히 저장소 책임 분리와 승인 체계가 약하면 같은 문제가 반복됩니다.

    Q4. 작은 팀도 GitOps가 필요할까요?

    작은 팀도 필요할 수 있습니다. 다만 처음부터 무겁게 가지 말고, 단일 서비스와 단순한 저장소 구조로 시작하는 편이 좋습니다.

    ArgoCD 도입 실패 방지 전략과 GitOps 실수 비교 요약 이미지

    도입 전후 비교, 실패 패턴, 예방 전략을 요약한 인포그래픽 형태의 정리 이미지입니다.

    9. 마무리: ArgoCD 도입 실패를 줄이는 진짜 핵심

    ArgoCD 도입 실패는 대개 설치 실패가 아니라 운영 모델 설계 실패입니다. GitOps는 도구를 붙이는 프로젝트가 아니라, 변경을 기록하고 승인하고 되돌리는 방식을 다시 정의하는 작업이거든요. 저도 처음엔 UI가 예쁘고 sync가 자동으로 돌아가니까 금방 안정화될 줄 알았는데, 실제론 저장소 구조와 팀 규칙을 먼저 잡아야 효과가 났습니다.

    정리하면 이렇습니다. GitOps 실수를 줄이려면 작은 범위로 시작하고, 수동 sync로 흐름을 익히고, 저장소 책임과 승인 규칙을 먼저 고정해야 합니다. 그리고 drift, Secret, 롤백 기준을 문서로 남겨야 합니다. 이 4가지만 해도 현장에서 체감 차이가 큽니다.

    다음 글에서는 App of Apps 패턴과 멀티 클러스터 운영에서 어디까지 표준화해야 하는지 다뤄볼 예정입니다. 이전 글에서 다뤘던 Kubernetes 배포 기본기와 함께 보시면 흐름이 더 잘 잡히실 겁니다. 혹시 지금 ArgoCD 도입 실패를 겪고 계시다면, 설치 로그보다 먼저 운영 규칙부터 점검해보세요. 그게 생각보다 훨씬 빠른 지름길입니다. 🎉