🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

Chaos Engineering 실전 가이드 - 장애 주입과 자동 복구 - 슬라이드 1/7
A

AI Generated

2025. 12. 10. · 17 Views

Chaos Engineering 실전 가이드 - 장애 주입과 자동 복구

카오스 엔지니어링의 핵심 원칙부터 chaos-toolkit을 활용한 실전 장애 주입 실험까지, 시스템의 복원력을 높이는 방법을 단계별로 학습합니다. Prometheus와 연동한 자동 복구 시스템 구축까지 한 번에 익힙니다.


목차

  1. Chaos Engineering 원칙과 목표
  2. chaos-toolkit 설치와 실험 정의
  3. 네트워크 장애 주입 실험
  4. 디스크 풀 시나리오 테스트
  5. Prometheus alert firing 확인
  6. 자동 복구 스크립트 트리거

1. Chaos Engineering 원칙과 목표

어느 날 박시니어 개발자는 새벽 3시에 긴급 호출을 받았습니다. "서버가 다운됐어요!" 급히 복구했지만, 왜 다운됐는지 정확히 알 수 없었습니다.

다음 날 아침, 팀장님이 물었습니다. "우리 시스템이 정말 안정적인가요?"

카오스 엔지니어링은 시스템의 약점을 미리 찾아내기 위해 의도적으로 장애를 일으키는 방법론입니다. 마치 건물의 내진 설계를 테스트하듯, 프로덕션 환경에서 통제된 실험을 통해 복원력을 검증합니다.

이를 통해 예상치 못한 장애 상황에서도 시스템이 견딜 수 있는지 확인할 수 있습니다.

다음 코드를 살펴봅시다.

# chaos_principles.py
# Chaos Engineering의 핵심 4대 원칙

class ChaosExperiment:
    def __init__(self, system_name):
        self.system_name = system_name
        self.baseline_metrics = {}

    def define_steady_state(self):
        # 원칙 1: 정상 상태 정의 - 시스템이 건강할 때의 기준선
        self.baseline_metrics = {
            'response_time': 200,  # ms
            'success_rate': 99.5,  # %
            'cpu_usage': 60        # %
        }
        return self.baseline_metrics

    def hypothesize_steady_state(self, chaos_event):
        # 원칙 2: 가설 수립 - 장애 주입 후에도 정상 상태 유지를 가정
        print(f"가설: {chaos_event} 발생 시에도 성공률 95% 이상 유지")
        return True

    def vary_real_world_events(self):
        # 원칙 3: 실제 세계의 다양한 이벤트 시뮬레이션
        chaos_scenarios = [
            'network_latency',      # 네트워크 지연
            'server_crash',         # 서버 크래시
            'disk_full',           # 디스크 풀
            'high_cpu_load'        # CPU 과부하
        ]
        return chaos_scenarios

    def run_in_production(self):
        # 원칙 4: 프로덕션 환경에서 실험 (통제된 범위 내에서)
        print(f"⚠️  {self.system_name}에 실험 시작 (영향 범위: 5% 트래픽)")
        return {'experiment_started': True, 'blast_radius': '5%'}

박시니어 개발자는 새벽 장애 이후 고민에 빠졌습니다. "우리 시스템이 정말 안정적일까?

다음 장애는 언제 올까?" 개발팀은 열심히 테스트 코드를 작성하고 있었지만, 실제 프로덕션 환경에서 발생하는 예상치 못한 상황까지는 커버하기 어려웠습니다. 그때 SRE 팀의 이엔지니어 님이 제안했습니다.

"카오스 엔지니어링을 도입해보는 건 어떨까요?" 카오스 엔지니어링이란 무엇일까요? 쉽게 비유하자면, 카오스 엔지니어링은 마치 소방 훈련과 같습니다.

실제 화재가 발생하기 전에 비상벨을 울려보고, 대피 경로를 확인하고, 소화기 사용법을 연습합니다. 마찬가지로 카오스 엔지니어링도 실제 장애가 발생하기 전에 인위적으로 문제를 일으켜서 시스템이 어떻게 반응하는지 확인합니다.

왜 필요한가? 전통적인 테스트의 한계 전통적인 테스트 방법은 알려진 시나리오만 검증합니다.

단위 테스트는 개별 함수를 테스트하고, 통합 테스트는 컴포넌트 간 연동을 확인합니다. 하지만 실제 프로덕션 환경은 훨씬 복잡합니다.

네트워크가 갑자기 느려지거나, 데이터베이스 연결이 끊어지거나, 특정 서버의 메모리가 부족해지는 등 예상치 못한 일들이 발생합니다. 더 큰 문제는 이런 문제들이 동시에 발생할 때입니다.

단일 장애는 괜찮지만, 여러 문제가 겹치면 시스템이 무너질 수 있습니다. 카오스 엔지니어링의 4대 원칙 넷플릭스가 정립한 카오스 엔지니어링의 핵심 원칙은 4가지입니다.

첫 번째는 정상 상태를 정의하는 것입니다. 시스템이 건강할 때 어떤 상태인지 명확히 해야 합니다.

응답 시간이 200ms 이하이고, 성공률이 99.5% 이상이며, CPU 사용률이 60% 정도라면 이것이 우리 시스템의 정상 상태입니다. 두 번째는 가설을 수립하는 것입니다.

"네트워크 지연이 500ms 발생해도 우리 시스템은 95% 이상의 성공률을 유지할 것이다"처럼 구체적인 가설을 세웁니다. 이 가설이 맞는지 실험으로 검증합니다.

세 번째는 실제 세계의 다양한 이벤트를 시뮬레이션하는 것입니다. 서버 크래시, 네트워크 장애, 디스크 용량 부족, 메모리 누수 등 실제로 발생할 수 있는 모든 상황을 재현합니다.

네 번째는 프로덕션 환경에서 실험하는 것입니다. 테스트 환경과 프로덕션 환경은 다릅니다.

진짜 복원력을 검증하려면 실제 사용자가 있는 프로덕션에서 실험해야 합니다. 물론 전체 트래픽의 5% 정도만 영향받도록 통제된 범위 내에서 진행합니다.

실무에서의 적용 박시니어 개발자의 팀은 쇼핑몰 서비스를 운영합니다. 블랙프라이데이 같은 대목을 앞두고, 시스템이 갑작스러운 트래픽 증가와 예상치 못한 장애를 견딜 수 있는지 확인하고 싶었습니다.

팀은 먼저 정상 상태를 정의했습니다. 주문 API의 응답 시간은 평균 150ms, 성공률은 99.8%였습니다.

그리고 가설을 세웠습니다. "데이터베이스 연결이 3초 지연되어도 캐시를 통해 95% 이상의 요청을 처리할 수 있을 것이다" 실험 결과는 놀라웠습니다.

캐시가 예상대로 작동하지 않았고, 성공률이 70%까지 떨어졌습니다. 이 문제를 미리 발견했기에, 블랙프라이데이 전에 캐시 로직을 개선할 수 있었습니다.

주의사항과 폭발 반경 카오스 엔지니어링을 시작할 때 가장 중요한 것은 폭발 반경을 제한하는 것입니다. 전체 시스템을 한꺼번에 망가뜨리면 안 됩니다.

처음에는 개발 환경이나 스테이징 환경에서 시작합니다. 충분히 익숙해진 후 프로덕션에서 진행하되, 전체 트래픽의 1-5% 정도만 영향받도록 합니다.

또한 실험 중 언제든 중단할 수 있는 킬 스위치를 준비해야 합니다. 정리 이엔지니어 님의 설명을 들은 박시니어 개발자는 눈이 반짝였습니다.

"그래서 넷플릭스가 그렇게 안정적이었군요!" 카오스 엔지니어링은 시스템의 약점을 미리 찾아내어 더 강한 시스템을 만드는 강력한 도구입니다. 처음에는 두렵게 느껴질 수 있지만, 통제된 환경에서 차근차근 시작하면 큰 자신감을 얻을 수 있습니다.

실전 팁

💡 - 작게 시작하세요. 처음부터 프로덕션에서 하지 말고, 개발 환경에서 충분히 연습하세요

  • 모니터링을 먼저 갖추세요. 실험 결과를 측정할 수 없다면 의미가 없습니다
  • 팀원들과 공유하세요. 카오스 실험은 팀 전체가 알고 준비해야 합니다

2. chaos-toolkit 설치와 실험 정의

박시니어 개발자는 카오스 엔지니어링의 개념은 이해했지만, 실제로 어떻게 시작해야 할지 막막했습니다. "직접 스크립트를 작성해야 하나?" 그때 이엔지니어 님이 추천했습니다.

"chaos-toolkit이라는 오픈소스 도구가 있어요!"

chaos-toolkit은 카오스 엔지니어링 실험을 쉽게 정의하고 실행할 수 있는 Python 기반 오픈소스 도구입니다. YAML이나 JSON 형식으로 실험을 선언적으로 정의할 수 있으며, 다양한 확장 기능을 통해 AWS, Kubernetes, Docker 등 여러 플랫폼에서 장애를 주입할 수 있습니다.

다음 코드를 살펴봅시다.

# chaos-toolkit 설치 및 첫 실험 설정
# install_chaos.sh

# 1. chaos-toolkit 설치
pip install chaostoolkit

# 2. 확장 기능 설치 (필요한 것만)
pip install chaostoolkit-kubernetes    # K8s용
pip install chaostoolkit-aws           # AWS용
pip install chaostoolkit-prometheus    # Prometheus 연동

# 3. 실험 정의 파일 생성
cat > experiment.json <<EOF
{
  "title": "서비스 복원력 테스트",
  "description": "API 서버가 네트워크 장애를 견딜 수 있는지 확인",
  "steady-state-hypothesis": {
    "title": "API 응답 성공률 95% 이상",
    "probes": [
      {
        "type": "probe",
        "name": "api-health-check",
        "tolerance": 95,
        "provider": {
          "type": "http",
          "url": "http://localhost:8080/health",
          "timeout": 3
        }
      }
    ]
  },
  "method": [
    {
      "type": "action",
      "name": "네트워크 지연 주입",
      "provider": {
        "type": "process",
        "path": "tc",
        "arguments": ["qdisc", "add", "dev", "eth0", "root", "netem", "delay", "300ms"]
      },
      "pauses": {
        "after": 30
      }
    }
  ],
  "rollbacks": [
    {
      "type": "action",
      "name": "네트워크 복구",
      "provider": {
        "type": "process",
        "path": "tc",
        "arguments": ["qdisc", "del", "dev", "eth0", "root"]
      }
    }
  ]
}
EOF

# 4. 실험 실행
chaos run experiment.json

박시니어 개발자는 카오스 엔지니어링을 시작하려고 했지만, 막막했습니다. "네트워크 장애를 어떻게 일으키지?

iptables로 직접 설정해야 하나?" 복잡한 스크립트를 작성해야 할 것 같았습니다. 이엔지니어 님이 노트북을 열어 보여주었습니다.

"이렇게 간단해요. JSON 파일 하나면 됩니다" chaos-toolkit이란 무엇인가 chaos-toolkit은 마치 요리 레시피와 같습니다.

재료와 조리 순서를 적어두면, 누구나 같은 요리를 만들 수 있습니다. 마찬가지로 chaos-toolkit도 실험의 단계를 JSON이나 YAML 파일에 적어두면, 도구가 자동으로 실행해줍니다.

이 도구는 Python으로 작성되어 있고, 플러그인 구조로 되어 있습니다. 기본 기능만으로도 HTTP 헬스체크나 프로세스 제어가 가능하고, 추가 플러그인을 설치하면 Kubernetes 파드를 죽이거나 AWS 인스턴스를 종료하는 등 다양한 작업이 가능합니다.

설치는 간단합니다 chaos-toolkit은 pip로 설치할 수 있습니다. 기본 패키지만 설치하면 HTTP 기반 실험은 바로 시작할 수 있습니다.

Kubernetes 환경에서 실험하려면 chaostoolkit-kubernetes 플러그인을 추가로 설치하면 됩니다. 박시니어 개발자는 터미널을 열고 명령어를 입력했습니다.

10초도 안 걸려 설치가 완료되었습니다. "이렇게 쉬워요?" 실험 정의 파일의 구조 chaos-toolkit의 실험 정의 파일은 크게 4개 섹션으로 구성됩니다.

첫 번째는 메타데이터입니다. 실험의 제목과 설명을 적습니다.

"서비스 복원력 테스트"처럼 팀원들이 이해하기 쉬운 이름을 붙입니다. 두 번째는 정상 상태 가설입니다.

steady-state-hypothesis라는 이름으로, 시스템이 정상일 때의 기준을 정의합니다. "API 응답 성공률이 95% 이상이어야 한다"처럼 측정 가능한 기준을 세웁니다.

chaos-toolkit은 실험 전후로 이 조건을 검증합니다. 세 번째는 실험 방법입니다.

method 섹션에 실제로 무슨 장애를 일으킬지 적습니다. "네트워크에 300ms 지연을 추가한다"처럼 구체적으로 명시합니다.

여러 단계를 순서대로 실행할 수도 있습니다. 네 번째는 롤백입니다.

실험이 끝난 후 시스템을 원래 상태로 되돌리는 작업입니다. 네트워크 지연을 추가했다면, 반드시 그 설정을 제거해야 합니다.

롤백을 정의하지 않으면 시스템이 망가진 채로 남을 수 있습니다. 프로브와 액션의 차이 chaos-toolkit에는 두 가지 기본 개념이 있습니다.

프로브액션입니다. 프로브는 관찰하는 것입니다.

시스템의 상태를 확인하고 측정합니다. "헬스체크 API를 호출해서 응답을 확인한다"처럼 읽기 전용 작업입니다.

프로브는 시스템을 변경하지 않습니다. 액션은 변경하는 것입니다.

시스템에 무언가를 일으킵니다. "파드를 삭제한다", "네트워크 지연을 추가한다"처럼 시스템의 상태를 바꿉니다.

카오스를 일으키는 핵심 부분입니다. 실험 실행 흐름 chaos-toolkit은 실험을 실행할 때 정해진 순서를 따릅니다.

먼저 정상 상태 가설을 검증합니다. 실험을 시작하기 전에 시스템이 정말 정상인지 확인합니다.

만약 이미 문제가 있다면 실험을 중단합니다. 다음으로 method에 정의된 액션들을 순서대로 실행합니다.

네트워크 지연을 추가하고, 30초 기다립니다. 이 과정에서 시스템이 어떻게 반응하는지 관찰합니다.

실험이 끝나면 다시 정상 상태 가설을 검증합니다. 장애를 일으킨 후에도 시스템이 정상 기준을 만족하는지 확인합니다.

만족하지 못하면 실험은 실패로 기록됩니다. 마지막으로 롤백을 실행합니다.

실험 성공 여부와 관계없이 반드시 실행되어 시스템을 원래 상태로 되돌립니다. 실무 적용 사례 박시니어 개발자의 팀은 주문 API 서비스를 운영합니다.

이 서비스가 데이터베이스 연결 장애에도 견딜 수 있는지 확인하고 싶었습니다. 팀은 experiment.json 파일을 작성했습니다.

정상 상태는 "주문 API 응답시간 500ms 이하"로 정의했습니다. 실험 방법은 "데이터베이스 컨테이너를 30초간 중지"했습니다.

롤백은 "데이터베이스 컨테이너 재시작"이었습니다. 실험을 실행한 결과, 놀랍게도 API가 견뎠습니다.

캐시 덕분에 데이터베이스가 없어도 대부분의 요청을 처리했습니다. 하지만 새로운 주문 생성은 실패했다는 것도 발견했습니다.

이 정보를 바탕으로 주문 큐 시스템을 도입하기로 결정했습니다. 주의사항 chaos-toolkit을 사용할 때 가장 조심해야 할 점은 롤백을 반드시 정의하는 것입니다.

실험 중 문제가 생기면 수동으로 복구해야 하는데, 새벽 3시에 그런 상황이 오면 정말 힘듭니다. 또한 프로덕션 환경에서 실험할 때는 반드시 팀원들에게 알려야 합니다.

갑자기 장애가 발생하면 다른 팀원이 놀라서 불필요한 조치를 취할 수 있습니다. 정리 이엔지니어 님의 데모를 본 박시니어 개발자는 안도했습니다.

"생각보다 간단하네요!" chaos-toolkit은 카오스 엔지니어링을 코드로 정의하고 반복 실행할 수 있게 해줍니다. 실험을 Git으로 관리하고, CI/CD 파이프라인에 통합할 수도 있습니다.

여러분도 간단한 실험부터 시작해보세요.

실전 팁

💡 - 실험 파일은 Git으로 관리하세요. 실험도 코드입니다

  • 롤백을 반드시 정의하세요. 안 그러면 시스템이 망가진 채로 남습니다
  • 처음에는 로컬 환경에서 실험해보고, 익숙해지면 스테이징으로 넘어가세요

3. 네트워크 장애 주입 실험

첫 실험을 앞둔 박시니어 개발자는 긴장했습니다. "진짜 서버 네트워크를 끊어도 되는 건가요?" 이엔지니어 님이 웃으며 말했습니다.

"걱정 마세요. 스테이징 환경에서 시작할 거니까요.

그리고 완전히 끊는 게 아니라 지연만 줄 겁니다"

네트워크 장애 주입은 카오스 엔지니어링에서 가장 흔한 실험입니다. 실제 환경에서 네트워크는 언제든 느려지거나 끊길 수 있습니다.

패킷 지연, 패킷 손실, 대역폭 제한 등을 시뮬레이션하여 서비스가 네트워크 품질 저하에 어떻게 대응하는지 확인합니다.

다음 코드를 살펴봅시다.

# network_chaos_experiment.json
{
  "title": "네트워크 지연 장애 실험",
  "description": "API 서비스가 300ms 네트워크 지연을 견딜 수 있는지 검증",
  "steady-state-hypothesis": {
    "title": "서비스 응답 시간 1초 이하 유지",
    "probes": [
      {
        "type": "probe",
        "name": "check-api-response-time",
        "tolerance": {
          "type": "range",
          "range": [0, 1000],
          "target": "response_time_ms"
        },
        "provider": {
          "type": "python",
          "module": "chaoslib.http",
          "func": "call_http",
          "arguments": {
            "url": "http://api-server:8080/orders",
            "method": "GET",
            "timeout": 5
          }
        }
      }
    ]
  },
  "method": [
    {
      "type": "action",
      "name": "inject-network-latency",
      "provider": {
        "type": "process",
        "path": "tc",
        "arguments": [
          "qdisc", "add", "dev", "eth0", "root", "netem",
          "delay", "300ms", "100ms",
          "loss", "5%"
        ]
      },
      "pauses": {"after": 60}
    },
    {
      "type": "probe",
      "name": "measure-degraded-performance",
      "provider": {
        "type": "python",
        "module": "chaoslib.http",
        "func": "call_http",
        "arguments": {
          "url": "http://api-server:8080/orders",
          "method": "GET",
          "timeout": 5
        }
      }
    }
  ],
  "rollbacks": [
    {
      "type": "action",
      "name": "remove-network-latency",
      "provider": {
        "type": "process",
        "path": "tc",
        "arguments": ["qdisc", "del", "dev", "eth0", "root"]
      }
    }
  ]
}

박시니어 개발자는 스테이징 환경에 접속했습니다. 손에 땀이 났습니다.

"정말 괜찮을까?" 하지만 이엔지니어 님의 자신감 있는 표정을 보니 조금 안심이 되었습니다. 네트워크 장애가 가장 흔한 이유 실제 프로덕션 환경에서 가장 자주 발생하는 문제는 네트워크 장애입니다.

서버 크래시나 디스크 장애는 드물지만, 네트워크는 매일 수십 번씩 미묘하게 불안정해집니다. 아마존 웹 서비스의 여러 가용 영역 사이에서도 가끔 지연이 발생합니다.

사용자가 느린 3G 네트워크를 사용할 수도 있습니다. 데이터센터의 네트워크 스위치가 일시적으로 과부하 상태가 될 수도 있습니다.

tc 명령어로 네트워크 제어하기 Linux에는 tc라는 강력한 도구가 있습니다. Traffic Control의 약자로, 네트워크 트래픽을 세밀하게 제어할 수 있습니다.

위의 실험 코드를 보면 tc 명령어에 여러 옵션이 있습니다. delay 300ms는 모든 패킷에 300밀리초의 지연을 추가합니다.

100ms는 지연의 편차입니다. 실제로는 200ms에서 400ms 사이로 무작위로 지연됩니다.

loss 5%는 패킷의 5%를 무작위로 버립니다. 실제 네트워크에서도 패킷 손실은 발생합니다.

TCP는 손실된 패킷을 재전송하지만, 이 과정에서 추가 지연이 생깁니다. 실험 단계별 분석 이 실험은 세 단계로 진행됩니다.

첫 번째 단계는 정상 상태 검증입니다. API 서버에 GET 요청을 보내서 응답 시간이 1초 이하인지 확인합니다.

정상적인 환경에서는 보통 50-100ms 정도 걸립니다. 두 번째 단계는 장애 주입입니다.

tc 명령어로 eth0 네트워크 인터페이스에 지연과 손실을 추가합니다. 그리고 60초 동안 기다립니다.

이 시간 동안 모든 네트워크 트래픽이 영향을 받습니다. 세 번째 단계는 성능 측정입니다.

60초 후에 다시 API를 호출해서 응답 시간을 측정합니다. 네트워크가 느린 상황에서 API가 어떻게 동작하는지 확인합니다.

마지막으로 롤백입니다. tc qdisc del 명령어로 추가했던 지연과 손실 설정을 제거합니다.

네트워크가 원래대로 돌아옵니다. 예상되는 결과와 해석 박시니어 개발자가 실험을 실행했습니다.

터미널에 로그가 쏟아져 나왔습니다. 정상 상태 검증은 통과했습니다.

응답 시간 87ms. 장애를 주입하고 60초 기다렸습니다.

다시 API를 호출했습니다. 응답 시간 423ms.

여전히 1초 이하였습니다. 실험은 성공이었습니다.

하지만 박시니어 개발자는 뭔가 이상했습니다. "300ms 지연을 추가했는데 왜 423ms만 늘어났죠?" 이엔지니어 님이 설명했습니다.

"API 서버가 로컬 캐시를 사용하고 있거든요. 데이터베이스까지 왕복하지 않았어요.

실제로 데이터베이스 조회가 필요한 요청은 훨씬 느려질 겁니다" 다양한 네트워크 장애 시나리오 네트워크 장애는 지연만 있는 게 아닙니다. 패킷 손실을 테스트할 수도 있습니다.

loss 10%로 설정하면 10개 중 1개 패킷이 사라집니다. TCP 재전송이 얼마나 빠르게 일어나는지 확인할 수 있습니다.

대역폭 제한도 중요합니다. rate 1mbit으로 설정하면 초당 1메가비트로 제한됩니다.

느린 네트워크에서 큰 JSON 응답을 전송할 때 얼마나 걸리는지 확인할 수 있습니다. 완전한 네트워크 단절도 테스트해야 합니다.

iptables로 특정 IP나 포트로의 연결을 완전히 차단할 수 있습니다. 타임아웃 처리가 제대로 되는지 확인합니다.

실무 적용 사례 박시니어 개발자의 팀은 흥미로운 문제를 발견했습니다. 주문 API는 네트워크 지연을 잘 견뎠지만, 결제 API는 그렇지 못했습니다.

결제 API는 외부 PG사 API를 호출했는데, 타임아웃이 30초로 설정되어 있었습니다. 네트워크가 느려지면 사용자는 30초 동안 기다려야 했습니다.

이는 너무 깁니다. 팀은 타임아웃을 5초로 줄이고, 실패 시 재시도 로직을 추가했습니다.

그리고 사용자에게 "결제 처리 중입니다. 잠시만 기다려주세요" 메시지를 즉시 보여주도록 개선했습니다.

주의사항 네트워크 장애 주입은 강력하지만 위험할 수 있습니다. tc 명령어는 전체 네트워크 인터페이스에 영향을 줍니다.

eth0에 지연을 추가하면 SSH 연결도 느려집니다. 실수로 롤백을 실행하지 않으면 서버가 계속 느린 상태로 남습니다.

반드시 롤백을 정의하고, 실험 실행 전에 롤백이 제대로 작동하는지 테스트해야 합니다. 또한 Docker나 Kubernetes를 사용한다면, 컨테이너 네트워크만 영향받도록 설정할 수 있습니다.

호스트 전체가 아닌 특정 파드만 느리게 만들 수 있습니다. 정리 실험을 마친 박시니어 개발자는 뿌듯했습니다.

"우리 시스템이 생각보다 견고하네요!" 네트워크 장애 주입은 가장 실용적인 카오스 실험입니다. 실제로 자주 발생하는 문제이고, 재현하기도 쉽습니다.

여러분도 오늘 당장 스테이징 환경에서 시도해보세요.

실전 팁

💡 - 처음에는 짧은 시간(10-30초)으로 테스트하세요

  • SSH 접속이 끊길 수 있으니 자동 롤백 스크립트를 준비하세요
  • Docker/K8s 환경이라면 pumba나 chaos-mesh 같은 전용 도구를 사용하세요

4. 디스크 풀 시나리오 테스트

다음 날, 박시니어 개발자는 더 자신감이 생겼습니다. "네트워크 장애는 해봤으니, 이번엔 디스크 장애를 테스트해볼까요?" 이엔지니어 님이 고개를 끄덕였습니다.

"좋아요. 디스크가 꽉 차는 시나리오는 실제로도 자주 발생하거든요"

디스크 풀 시나리오는 디스크 공간이 100% 차는 상황을 시뮬레이션합니다. 로그 파일이 무한정 쌓이거나, 임시 파일이 삭제되지 않거나, 데이터베이스가 계속 커지는 등의 이유로 실제로도 자주 발생합니다.

이 상황에서 애플리케이션이 graceful하게 실패하는지, 아니면 크래시하는지 확인합니다.

다음 코드를 살펴봅시다.

# disk_full_experiment.json
{
  "title": "디스크 풀 복원력 테스트",
  "description": "디스크가 가득 찼을 때 애플리케이션이 정상적으로 대응하는지 검증",
  "steady-state-hypothesis": {
    "title": "애플리케이션이 정상 실행 중",
    "probes": [
      {
        "type": "probe",
        "name": "check-app-health",
        "tolerance": 200,
        "provider": {
          "type": "http",
          "url": "http://localhost:8080/health",
          "timeout": 3
        }
      }
    ]
  },
  "method": [
    {
      "type": "action",
      "name": "fill-disk-to-95-percent",
      "provider": {
        "type": "process",
        "path": "dd",
        "arguments": [
          "if=/dev/zero",
          "of=/var/log/chaos-filler.img",
          "bs=1M",
          "count=10240"
        ]
      }
    },
    {
      "type": "probe",
      "name": "check-disk-usage",
      "provider": {
        "type": "process",
        "path": "df",
        "arguments": ["-h", "/var/log"]
      },
      "pauses": {"after": 30}
    },
    {
      "type": "probe",
      "name": "verify-app-still-responds",
      "tolerance": [200, 503],
      "provider": {
        "type": "http",
        "url": "http://localhost:8080/health"
      }
    }
  ],
  "rollbacks": [
    {
      "type": "action",
      "name": "remove-filler-file",
      "provider": {
        "type": "process",
        "path": "rm",
        "arguments": ["-f", "/var/log/chaos-filler.img"]
      }
    }
  ]
}

박시니어 개발자는 지난주에 겪었던 사건을 떠올렸습니다. 갑자기 API 서버가 응답을 멈췄습니다.

확인해보니 로그 파일이 50GB까지 커져서 디스크를 가득 채웠습니다. "이런 상황을 미리 테스트할 수 있다니!" 디스크가 가득 차면 무슨 일이 벌어질까 디스크 공간이 부족한 상황은 예상보다 심각합니다.

먼저 쓰기 작업이 모두 실패합니다. 로그를 기록할 수 없고, 데이터베이스에 새 데이터를 저장할 수 없고, 임시 파일을 생성할 수 없습니다.

애플리케이션은 오류를 뱉지만, 때로는 조용히 실패하기도 합니다. 더 심각한 것은 운영 체제 자체가 불안정해진다는 점입니다.

스왑 공간이 없어지면 프로세스가 강제 종료될 수 있습니다. 심지어 SSH 로그인조차 안 될 수 있습니다.

dd 명령어로 디스크 채우기 위의 실험 코드는 dd 명령어를 사용합니다. dd는 데이터를 복사하는 저수준 유틸리티입니다.

if=/dev/zero는 입력 소스로 /dev/zero를 사용합니다. 이것은 무한히 0바이트를 생성하는 특수 장치입니다.

of=/var/log/chaos-filler.img는 출력 파일입니다. 이 파일에 데이터를 씁니다.

bs=1M은 블록 크기를 1메가바이트로 설정합니다. count=10240은 10,240개의 블록을 쓰라는 의미입니다.

즉, 10GB 파일을 생성합니다. 이 명령어를 실행하면 /var/log 디렉토리에 10GB짜리 더미 파일이 생깁니다.

디스크 사용률이 급격히 올라갑니다. 실험의 흐름 이 실험은 네 단계로 진행됩니다.

첫 번째는 정상 상태 확인입니다. 헬스체크 API를 호출해서 200 OK를 받는지 확인합니다.

애플리케이션이 정상 동작 중이어야 합니다. 두 번째는 디스크 채우기입니다.

dd 명령어로 10GB 파일을 생성합니다. 이 과정은 몇 초 안에 완료됩니다.

세 번째는 디스크 상태 확인입니다. df -h 명령어로 디스크 사용률을 출력합니다.

실제로 디스크가 거의 차 있는지 확인합니다. 그리고 30초 기다립니다.

네 번째는 애플리케이션 반응 확인입니다. 다시 헬스체크 API를 호출합니다.

이번에는 200 OK 또는 503 Service Unavailable을 허용합니다. 애플리케이션이 디스크 부족을 인지하고 적절한 응답을 보내면 성공입니다.

예상되는 결과 박시니어 개발자가 실험을 실행했습니다. 첫 번째 헬스체크는 통과했습니다.

dd 명령어가 실행되었습니다. 10초 후, 디스크 사용률이 95%로 올라갔습니다.

30초를 기다린 후 다시 헬스체크를 호출했습니다. 그런데 응답이 오지 않았습니다.

타임아웃이 발생했습니다. "어?

왜 응답이 없죠?" 박시니어 개발자가 당황했습니다. 이엔지니어 님이 로그를 확인했습니다.

애플리케이션이 로그를 쓰려다가 예외가 발생하고, 예외 처리 중에 또 로그를 쓰려다가 무한 루프에 빠졌습니다. "이게 바로 카오스 실험의 가치예요.

이런 버그를 미리 발견했으니까요" 개선된 애플리케이션 코드 팀은 애플리케이션을 개선했습니다. 디스크 공간을 주기적으로 체크하는 헬스체크를 추가했습니다.

python import shutil def check_disk_space(): usage = shutil.disk_usage('/') free_percent = (usage.free / usage.total) * 100 if free_percent < 10: return {'status': 'unhealthy', 'reason': 'low_disk_space'} return {'status': 'healthy'} 또한 로그 라이브러리를 설정해서, 로그 쓰기가 실패해도 애플리케이션이 크래시하지 않도록 했습니다. 실무 적용 사례 박시니어 개발자의 팀은 데이터 파이프라인 서비스를 운영합니다.

이 서비스는 대용량 파일을 처리하고 임시 디렉토리에 저장합니다. 디스크 풀 실험을 통해 큰 문제를 발견했습니다.

디스크가 가득 차면 파일 처리가 멈추지만, 사용자에게는 "처리 중"이라고 계속 표시되었습니다. 사용자는 몇 시간을 기다렸지만 결과를 받지 못했습니다.

팀은 디스크 공간을 확인하는 로직을 추가했습니다. 디스크 사용률이 90%를 넘으면 새 작업을 받지 않고, 사용자에게 명확한 에러 메시지를 보냅니다.

또한 오래된 임시 파일을 자동으로 삭제하는 크론 작업도 추가했습니다. 주의사항 디스크 풀 실험은 조심해야 합니다.

잘못하면 운영 체제 전체를 먹통으로 만들 수 있습니다. 반드시 특정 디렉토리만 채워야 합니다.

루트 파티션 전체를 가득 채우면 SSH 접속조차 안 될 수 있습니다. 가능하면 /var나 /tmp처럼 별도 파티션이 있는 경로를 사용하세요.

또한 롤백을 반드시 실행해야 합니다. 더미 파일을 삭제하지 않으면 디스크가 계속 가득 찬 상태로 남습니다.

실험 후에는 반드시 df 명령어로 디스크가 복구되었는지 확인하세요. Docker나 Kubernetes 환경이라면 더 안전합니다.

컨테이너에 디스크 할당량을 설정할 수 있고, 컨테이너가 망가져도 호스트는 안전합니다. 정리 실험을 통해 버그를 발견한 박시니어 개발자는 보람을 느꼈습니다.

"프로덕션에서 이런 일이 발생했다면 큰일 날 뻔했네요" 디스크 풀 시나리오는 반드시 테스트해야 할 중요한 장애입니다. 로그가 쌓이고, 데이터가 늘어나는 건 자연스러운 일입니다.

여러분의 시스템도 이 상황을 견딜 수 있는지 확인해보세요.

실전 팁

💡 - 프로덕션 전에 디스크 모니터링 알림을 설정하세요 (80% 이상 시 알림)

  • 로그 로테이션을 반드시 설정하세요 (logrotate 사용)
  • 임시 파일 정리를 자동화하세요 (크론 작업 또는 TTL)

5. Prometheus alert firing 확인

실험을 몇 차례 진행한 박시니어 개발자는 궁금해졌습니다. "이렇게 장애를 일으키는 건 좋은데, 매번 수동으로 확인해야 하나요?" 이엔지니어 님이 화면을 가리켰습니다.

"아니요. Prometheus와 연동하면 자동으로 감지할 수 있어요"

Prometheus 연동은 카오스 실험을 자동화하는 핵심입니다. Prometheus는 메트릭을 수집하고 알림 규칙을 평가합니다.

카오스 실험 중에 특정 alert가 firing되는지 확인하여, 모니터링 시스템이 제대로 작동하는지 검증할 수 있습니다. 이는 단순한 장애 주입을 넘어 전체 관찰성 스택을 테스트합니다.

다음 코드를 살펴봅시다.

# prometheus_alert_experiment.json
{
  "title": "Prometheus 알림 발화 검증",
  "description": "장애 발생 시 Prometheus 알림이 제대로 발화되는지 확인",
  "configuration": {
    "prometheus_url": "http://prometheus:9090"
  },
  "steady-state-hypothesis": {
    "title": "알림이 발화되지 않은 정상 상태",
    "probes": [
      {
        "type": "probe",
        "name": "no-alerts-firing",
        "tolerance": 0,
        "provider": {
          "type": "python",
          "module": "chaosprom.probes",
          "func": "query_prometheus",
          "arguments": {
            "query": "ALERTS{alertstate='firing',alertname='HighErrorRate'}"
          }
        }
      }
    ]
  },
  "method": [
    {
      "type": "action",
      "name": "inject-errors",
      "provider": {
        "type": "http",
        "url": "http://chaos-controller:8080/inject/errors",
        "method": "POST",
        "headers": {
          "Content-Type": "application/json"
        },
        "arguments": {
          "error_rate": 0.5,
          "duration_seconds": 120
        }
      }
    },
    {
      "type": "probe",
      "name": "wait-for-alert",
      "tolerance": {
        "type": "range",
        "range": [1, 999]
      },
      "provider": {
        "type": "python",
        "module": "chaosprom.probes",
        "func": "query_prometheus",
        "arguments": {
          "query": "ALERTS{alertstate='firing',alertname='HighErrorRate'}"
        }
      },
      "pauses": {"before": 60}
    }
  ],
  "rollbacks": [
    {
      "type": "action",
      "name": "stop-error-injection",
      "provider": {
        "type": "http",
        "url": "http://chaos-controller:8080/inject/stop",
        "method": "POST"
      }
    }
  ]
}

박시니어 개발자의 팀은 Prometheus로 모니터링하고 있었습니다. 에러율이 10%를 넘으면 알림이 발화되도록 설정했습니다.

"하지만 이 알림이 정말 작동할까요?" 이엔지니어 님이 웃었습니다. "설정은 해뒀지만 실제로 테스트해본 적은 없죠?

막상 장애가 발생하면 알림이 안 올 수도 있어요" 왜 모니터링을 테스트해야 하나 모니터링 시스템을 설정하는 것과 실제로 작동하는 것은 다릅니다. 많은 팀이 Prometheus 알림 규칙을 작성하지만, 실제로 테스트하지 않습니다.

YAML 파일의 문법은 맞지만, 쿼리가 잘못되었을 수 있습니다. 또는 임계값이 너무 높아서 실제 장애가 발생해도 알림이 발화되지 않을 수 있습니다.

더 심각한 것은 알림 라우팅 설정입니다. Prometheus에서 Alertmanager로, 그리고 Slack이나 PagerDuty로 연결되는 전체 체인이 제대로 작동해야 합니다.

어느 한 곳이라도 문제가 있으면 알림을 받지 못합니다. Prometheus 알림 규칙 예시 먼저 Prometheus 알림 규칙이 어떻게 생겼는지 보겠습니다.

yaml groups: - name: application_alerts interval: 30s rules: - alert: HighErrorRate expr: | rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) > 0.1 for: 2m labels: severity: critical annotations: summary: "높은 에러율 감지" description: "에러율이 10%를 초과했습니다" 이 규칙은 5분 동안 5xx 에러가 전체 요청의 10%를 넘으면, 2분 동안 지속될 경우 알림을 발화합니다. chaosprom 플러그인 사용하기 chaos-toolkit에는 chaosprom이라는 Prometheus 전용 플러그인이 있습니다.

이 플러그인을 설치하면 Prometheus를 직접 쿼리할 수 있습니다. 위의 실험 코드를 보면 query_prometheus 함수를 사용합니다.

이 함수는 Prometheus API를 호출해서 PromQL 쿼리 결과를 가져옵니다. ALERTS는 특수한 메트릭입니다.

Prometheus가 자동으로 생성하며, 모든 알림의 현재 상태를 나타냅니다. alertstate='firing'은 현재 발화 중인 알림만 필터링합니다.

실험의 단계별 분석 이 실험은 의도적으로 에러를 발생시켜 알림을 유도합니다. 첫 번째 단계는 정상 상태 확인입니다.

HighErrorRate 알림이 발화되지 않은 상태를 확인합니다. 쿼리 결과가 0이어야 합니다.

두 번째 단계는 에러 주입입니다. chaos-controller라는 별도 서비스에 HTTP 요청을 보냅니다.

이 서비스는 애플리케이션이 50%의 요청에 대해 500 에러를 반환하도록 만듭니다. 120초 동안 지속됩니다.

세 번째 단계는 알림 대기입니다. 60초를 기다린 후 다시 Prometheus를 쿼리합니다.

이번에는 쿼리 결과가 1 이상이어야 합니다. 즉, 알림이 발화되었다는 의미입니다.

만약 알림이 발화되지 않았다면 실험은 실패합니다. 모니터링 시스템에 문제가 있다는 신호입니다.

실제로 발견되는 문제들 박시니어 개발자가 실험을 실행했습니다. 에러를 주입하고 60초를 기다렸습니다.

하지만 알림이 발화되지 않았습니다. "왜죠?" 팀은 Prometheus 설정을 다시 확인했습니다.

알림 규칙의 for: 2m이 문제였습니다. 조건이 2분 동안 지속되어야 알림이 발화되는데, 60초만 기다렸던 것입니다.

실험 코드를 수정해서 120초를 기다리도록 했습니다. 다시 실행했습니다.

이번에도 알림이 발화되지 않았습니다. 더 깊이 파고들자, 메트릭 자체가 잘못되었습니다.

애플리케이션이 http_requests_total 메트릭을 제대로 내보내지 않고 있었습니다. Prometheus가 아무리 올바르게 설정되어 있어도, 메트릭이 없으면 알림을 발화할 수 없습니다.

전체 관찰성 스택 테스트 Prometheus 알림만 테스트하는 게 아닙니다. 전체 체인을 테스트해야 합니다.

알림이 Alertmanager로 전달되는지 확인해야 합니다. Alertmanager가 Slack으로 메시지를 보내는지 확인해야 합니다.

온콜 엔지니어가 실제로 알림을 받는지 확인해야 합니다. chaostoolkit으로 이 전체 흐름을 자동화할 수 있습니다.

Slack API를 호출해서 메시지가 도착했는지 확인하는 프로브를 추가할 수 있습니다. 실무 적용 사례 박시니어 개발자의 팀은 결제 시스템을 운영합니다.

결제 실패율이 5%를 넘으면 즉시 온콜 엔지니어에게 알림이 가야 합니다. 팀은 매주 금요일 오후에 카오스 실험을 실행합니다.

의도적으로 결제 실패를 일으키고, 알림이 제대로 발화되는지 확인합니다. 이 과정에서 Alertmanager 설정 오류, Slack 웹훅 만료, 온콜 로테이션 업데이트 누락 등 다양한 문제를 발견했습니다.

이제 팀은 자신 있게 말할 수 있습니다. "우리 모니터링은 실제로 작동합니다" 주의사항 Prometheus 알림 실험은 조심해야 합니다.

실제로 알림이 발화되면 온콜 엔지니어가 알림을 받습니다. 실험을 진행할 때는 팀원들에게 미리 알려야 합니다.

또는 테스트 전용 Alertmanager를 사용하거나, 알림 라우팅 규칙에서 테스트 알림을 필터링해야 합니다. 또한 실험 후 반드시 롤백해야 합니다.

에러 주입을 멈추지 않으면 계속 알림이 발화됩니다. 정리 이엔지니어 님이 정리했습니다.

"모니터링을 설정하는 것만으로는 부족해요. 실제로 작동하는지 정기적으로 테스트해야 합니다" Prometheus 알림 실험은 관찰성 스택의 신뢰성을 높이는 강력한 방법입니다.

여러분도 모니터링 시스템을 정기적으로 테스트해보세요.

실전 팁

💡 - 알림 규칙의 for 시간을 고려해서 충분히 기다리세요

  • 테스트 전용 알림 채널을 만들어서 실제 온콜을 방해하지 마세요
  • 메트릭이 제대로 수집되는지 먼저 확인하세요 (Prometheus UI에서 쿼리 테스트)

6. 자동 복구 스크립트 트리거

마지막 단계입니다. 박시니어 개발자가 물었습니다.

"장애를 감지하는 것까지는 이해했어요. 그런데 감지한 후에 자동으로 복구할 수는 없나요?" 이엔지니어 님이 환하게 웃었습니다.

"바로 그거예요! 그게 진짜 목표죠"

자동 복구는 카오스 엔지니어링의 궁극적인 목표입니다. 장애를 감지하면 사람이 개입하지 않고 시스템이 스스로 복구됩니다.

Prometheus 알림과 연동하여 특정 조건이 발생하면 복구 스크립트를 자동 실행합니다. 이를 통해 MTTR(평균 복구 시간)을 대폭 단축할 수 있습니다.

다음 코드를 살펴봅시다.

# auto_recovery_experiment.json
{
  "title": "자동 복구 시스템 검증",
  "description": "장애 감지 시 자동 복구 스크립트가 실행되고 시스템이 정상화되는지 확인",
  "configuration": {
    "prometheus_url": "http://prometheus:9090",
    "recovery_webhook": "http://recovery-service:8080/trigger"
  },
  "steady-state-hypothesis": {
    "title": "서비스 정상 운영 중",
    "probes": [
      {
        "type": "probe",
        "name": "check-service-health",
        "tolerance": 200,
        "provider": {
          "type": "http",
          "url": "http://api-server:8080/health"
        }
      }
    ]
  },
  "method": [
    {
      "type": "action",
      "name": "kill-service-pods",
      "provider": {
        "type": "python",
        "module": "chaosk8s.pod.actions",
        "func": "terminate_pods",
        "arguments": {
          "label_selector": "app=api-server",
          "qty": 2,
          "ns": "production"
        }
      }
    },
    {
      "type": "probe",
      "name": "verify-prometheus-alert",
      "tolerance": {"type": "range", "range": [1, 999]},
      "provider": {
        "type": "python",
        "module": "chaosprom.probes",
        "func": "query_prometheus",
        "arguments": {
          "query": "ALERTS{alertstate='firing',alertname='ServiceDown'}"
        }
      },
      "pauses": {"before": 30}
    },
    {
      "type": "probe",
      "name": "check-auto-recovery-triggered",
      "provider": {
        "type": "http",
        "url": "http://recovery-service:8080/status",
        "method": "GET",
        "timeout": 5
      },
      "pauses": {"before": 10}
    },
    {
      "type": "probe",
      "name": "verify-service-recovered",
      "tolerance": 200,
      "provider": {
        "type": "http",
        "url": "http://api-server:8080/health"
      },
      "pauses": {"before": 60}
    }
  ],
  "rollbacks": []
}

박시니어 개발자는 지난 몇 주 동안 여러 차례 새벽 호출을 받았습니다. 매번 같은 문제였습니다.

파드가 죽으면 수동으로 재시작해야 했습니다. "이걸 자동화할 수는 없을까?" 이엔지니어 님이 고개를 끄덕였습니다.

"당연히 할 수 있죠. 그게 바로 자동 복구 시스템이에요" 자동 복구가 필요한 이유 사람은 느립니다.

알림을 받고, 상황을 파악하고, 복구 명령어를 실행하기까지 최소 5-10분이 걸립니다. 새벽이면 더 오래 걸립니다.

자동 복구 시스템은 초 단위로 반응합니다. 알림이 발화되는 즉시 복구 작업을 시작합니다.

MTTR이 10분에서 30초로 줄어듭니다. 사용자는 장애를 거의 인지하지 못할 수도 있습니다.

또한 사람의 실수를 줄입니다. 새벽 3시에 졸린 상태로 프로덕션 서버에 명령어를 입력하면 실수하기 쉽습니다.

자동화된 스크립트는 항상 같은 방식으로 정확하게 실행됩니다. Kubernetes의 자가 치유 Kubernetes는 기본적으로 자가 치유 기능을 제공합니다.

Deployment로 파드를 관리하면, ReplicaSet이 항상 원하는 개수의 파드를 유지합니다. 파드가 죽으면 자동으로 새 파드를 생성합니다.

리부팅이 필요하지 않습니다. Liveness Probe를 설정하면, 파드가 응답하지 않을 때 자동으로 재시작합니다.

Readiness Probe를 설정하면, 준비되지 않은 파드로는 트래픽을 보내지 않습니다. 하지만 Kubernetes만으로는 부족한 경우가 많습니다.

더 복잡한 복구 로직이 필요합니다. 복구 서비스 구축하기 위의 실험 코드는 recovery-service라는 별도 서비스를 사용합니다.

이 서비스는 Prometheus Alertmanager의 웹훅을 받아 복구 스크립트를 실행합니다. 복구 서비스의 기본 구조는 간단합니다.

python from flask import Flask, request import subprocess app = Flask(__name__) @app.route('/trigger', methods=['POST']) def trigger_recovery(): alert_data = request.json alert_name = alert_data['alerts'][0]['labels']['alertname'] if alert_name == 'ServiceDown': # 파드 재시작 subprocess.run(['kubectl', 'rollout', 'restart', 'deployment/api-server', '-n', 'production']) return {'status': 'recovery_triggered'}, 200 elif alert_name == 'HighMemoryUsage': # 메모리 정리 subprocess.run(['kubectl', 'exec', 'deployment/api-server', '--', 'kill', '-SIGUSR1', '1']) return {'status': 'memory_cleanup_triggered'}, 200 return {'status': 'no_action'}, 200 if __name__ == '__main__': app.run(host='0.0.0.0', port=8080) Alertmanager 설정에서 이 서비스로 웹훅을 보내도록 합니다. 실험의 전체 흐름 이 실험은 장애 발생부터 자동 복구까지 전체 과정을 검증합니다.

첫 번째로 서비스가 정상인지 확인합니다. 헬스체크가 성공해야 합니다.

두 번째로 장애를 일으킵니다. Kubernetes 파드 2개를 강제로 종료합니다.

서비스가 다운됩니다. 세 번째로 30초 기다린 후 Prometheus를 확인합니다.

ServiceDown 알림이 발화되었는지 검증합니다. 네 번째로 10초 더 기다린 후 복구 서비스를 확인합니다.

복구 스크립트가 트리거되었는지 상태 API를 호출합니다. 다섯 번째로 60초 기다린 후 서비스가 복구되었는지 확인합니다.

헬스체크가 다시 성공하면 자동 복구가 완료된 것입니다. 실제 발견되는 문제들 박시니어 개발자가 실험을 실행했습니다.

파드를 죽였습니다. Prometheus 알림이 발화되었습니다.

하지만 복구 서비스가 동작하지 않았습니다. 팀은 Alertmanager 로그를 확인했습니다.

웹훅 요청이 타임아웃으로 실패했습니다. 복구 서비스가 응답하지 않았던 것입니다.

원인을 찾았습니다. 복구 서비스도 같은 Kubernetes 클러스터에 있었는데, 네트워크 정책 때문에 kubectl 명령어를 실행할 권한이 없었습니다.

ServiceAccount 설정이 빠져 있었습니다. 팀은 적절한 RBAC 권한을 추가했습니다.

다시 실험을 실행했습니다. 이번에는 성공했습니다.

파드가 죽고, 알림이 발화되고, 복구 스크립트가 실행되고, 60초 안에 서비스가 정상으로 돌아왔습니다. 더 고급 복구 전략 단순히 재시작하는 것 이상의 복구 전략이 있습니다.

Graceful Degradation입니다. 서비스가 완전히 죽는 대신, 기능을 축소해서 계속 동작합니다.

예를 들어 추천 시스템이 다운되면 기본 추천 목록을 보여줍니다. Circuit Breaker도 유용합니다.

외부 API가 응답하지 않으면 일시적으로 호출을 중단하고, 일정 시간 후 다시 시도합니다. Auto Scaling도 복구 전략입니다.

CPU나 메모리 사용률이 높으면 자동으로 파드를 추가합니다. 부하가 줄면 다시 축소합니다.

실무 적용 사례 박시니어 개발자의 팀은 이미지 처리 서비스를 운영합니다. 이 서비스는 간혹 메모리 누수로 인해 OOM(Out of Memory)으로 죽습니다.

팀은 자동 복구 시스템을 구축했습니다. HighMemoryUsage 알림이 발화되면, 복구 서비스가 해당 파드에 SIGUSR1 시그널을 보냅니다.

애플리케이션은 이 시그널을 받으면 캐시를 비우고 메모리를 정리합니다. 이 시스템 덕분에 OOM으로 인한 다운타임이 90% 감소했습니다.

대부분의 경우 메모리 정리만으로 문제가 해결되고, 재시작이 필요하지 않습니다. 주의사항과 책임 자동 복구는 강력하지만 위험할 수 있습니다.

잘못 설계된 복구 스크립트는 상황을 더 악화시킬 수 있습니다. 예를 들어 무한 재시작 루프에 빠질 수 있습니다.

파드가 죽고, 재시작되고, 즉시 또 죽고, 다시 재시작되는 상황입니다. 따라서 복구 시도 횟수를 제한해야 합니다.

3번 재시작해도 안 되면 사람에게 알림을 보내야 합니다. 또한 복구 작업도 로깅하고 모니터링해야 합니다.

무엇보다 팀 전체가 자동 복구 시스템의 존재를 알아야 합니다. 누군가 수동으로 개입하는 동시에 자동 복구가 실행되면 충돌할 수 있습니다.

정리 실험을 완료한 박시니어 개발자는 뿌듯했습니다. "이제 새벽에 깨지 않아도 되겠네요!" 이엔지니어 님이 미소지었습니다.

"그렇죠. 하지만 자동 복구 시스템 자체도 정기적으로 테스트해야 해요.

오늘 배운 카오스 실험을 매주 돌리면서 검증하세요" 자동 복구는 카오스 엔지니어링의 최종 목표입니다. 장애를 찾아내고, 감지하고, 자동으로 복구하는 전체 흐름이 완성되면 진정한 복원력 있는 시스템을 만들 수 있습니다.

실전 팁

💡 - 복구 스크립트에 재시도 횟수 제한을 반드시 넣으세요 (무한 루프 방지)

  • 복구 작업도 로깅하고 메트릭으로 수집하세요
  • 자동 복구와 수동 개입이 충돌하지 않도록 락 메커니즘을 고려하세요

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#ChaosEngineering#chaos-toolkit#Prometheus#SRE#AutoRecovery#DevOps,Chaos,SRE

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.