Younjin Jeong's Blog

Get busy living, or get busy dying

스프링 부트와 카오스 몽키

새로운 스프링 드라이버와 카오스 툴킷을 사용한 애플리케이션 레벨의 카오스 엔지니어링 소개

Posted on by

Categories:   Chaos Toolkit    Spring Boot    Spring driver    Chaos Monkey    Micro Services   
Edit this post on GitHub.

오리지날 블로그 포스트

여기에 소개된 내용의 원문은 Russ Miles (@russmiles)에 의해 작성 되었으며, 원문 링크는 아래와 같다.

translated from Chaos Toolkit LOVES Chaos Monkey for Spring Boot

원문 링크

  • 오역 및 잘못된 내용은 언제든 (younjin.jeong@gmail.com)으로 보내주세얌.
  • 가장 자주 등장하는 assault는 공격으로, watcher는 감시자로 번역 합니다.

시작에 앞서, 카오스 엔지니어링 소개 및 본 포스팅의 취지

시작전 겁나 긴 역주:

카오스 엔지니어링은 일반적으로 서비스를 테스트의 목적으로 일부러 망가트려 보고, 이에 대한 시스템의 반응을 바탕으로 더 견고한 서비스를 만들기 위한 엔지니어링을 의미한다.

이 부분에서 가장 유명하다고 할 수 있는 넷플릭스는 자사가 개발한 다양한 카오스 엔지니어링 도구를 오픈 소스로 배포하고 있는데, 그들 중 가장 유명한 것이 바로 원숭이 군단(Simian Army)로 불리는 것들이다. 그 가운데에서도 잘 알려진 것은 바로 카오스 몽키로, 실 서비스에서 동작하는 인스턴스의 종류와 관계 없이 마구 서버를 죽이며 돌아다니는 도구다. 당연히 데이터베이스나 카프카 클러스터의 멤버, 웹 서비스나 스트리밍 서비스 멤버의 서버들을 마구 죽인다.

넷플릭스는 실 서비스에 배포를 위한 도구들에 이 테스트를 적용할 뿐만 아니라, 실제로 동작하는 서비스에도 적용하는 것으로 잘 알려져 있다. 카오스 몽키 뿐만 아니라 전체 가용 존(Availiablity Zone)을 죽이거나, 또는 하나의 AWS 리전(Region) 전체를 죽이는 테스트 역시 수행하는 것으로 알려져 있다.

이 포스팅에서는 스프링 부트용 카오스 몽키 도구를 소개하고, 간략하게 사용법을 알아본다. 기본적으로 애플리케이션 수준에서 동작하므로, 스프링 부트 애플리케이션의 설정을 사용하도록 구성 되었다.

언뜻 보기에 스프링 부트를 그냥 죽이거나 요청에 대한 응답을 모사하기 위한 간단한 도구로 보일 수 있지만, 테스트 자동화 도구등을 통해 서비스에 함께 구현된 서킷 브레이커나 리트라이(Retry)등의 패턴을 통해 의존 관계에 있는 다른 서비스에 문제가 생겼을때 어떻게 되는지에 대한 실험과 검증의 자동화 방법으로 사용할 수 있는 도구라는 점이 중요하다.

카오스 몽키 도구는 애플리케이션이 동작하는 서비스를 무작위로 종료하는 것으로 잘 알려져 있지만, 이는 애플리케이션 수준의 테스트라고 보기는 힘들기 때문에 이와 같은 도구의 사용을 통해 실제 서비스에 문제가 되더라도 장애를 극복할 수 있는 애플리케이션 테스트에 사용할 수 있다는 점에서 카오스 엔지니어링 부분에 상당히 중요한 도구라고 할 수 있겠다.

필요한 코드는 모두 공개 되었으므로 적용 방법을 수월하게 살펴볼 수 있을 것이다.

스프링 툴킷과 스프링 부트용 카오스 몽키

카오스 툴킷의 첫번째 릴리즈에서는 스프링 부트에서 카오스 몽키를 애플리케이션 레벨에서 지원하기 위해 chaostoolkit-spring driver를 제공한다.

chaostoolkit-spring 인큐베이터 프로젝트는 오픈 소스이므로 자유롭게 사용 가능하다.”

이 첫 릴리즈는 스프링 부트 애플리케이션과 서비스에 다양한 카오스 엔지니어링을 적용해 볼 수 있도록 스프링 부트 카오스 몽키 지원이 codecentric에 의해 포함되었다.

  • 특정 서비스의 런타임에서 카오스 몽키 기능을 켜거나 끌 수 있다. (카오스 엔지니어링 실험을 하는 동안만 사용하고 싶을때 매우 유용하다.)
  • 특정 서비스의 런터임에서 카오스 공격(assults) 설정과 활성화를 지원한다.
  • 카오스 몽키의 감시자(watcher)와 공격(assaults) 설정을 기록하고 감사할 수 있다. 이런 정보의 수집은 향후 분석을 위해 매우 유용하다.

몇가지 예제를 살펴보자.

여기에 소개된 예제들은 모두 깃헙 링크에서 찾아볼 수 있다.

실험 예제 1: “의존 관계에 있는 서비스가 죽으면 우리 서비스는 어떻게 되지?”

스프링 부트용 카오스 몽키에서 제공하는 가장 기본적인 기능은, 스프링 부트 애플리케이션이 스스로를 죽여 봄으로서 의존 관계에 있는 다른 서비스가 어떻게 대응하는지 실험해 보는 것이다. 이 기능을 통해 아래의 가설을 바탕으로 실험해 볼 수 있다.

“내 서비스가 의존하고 있는 다른 서비스가 의도치 않게 죽으면 어떻게 될 것인가?”

이 예제에서는 consumer와 producer, 2개의 서비스를 준비 한다. consumer는 별도의 장애에 대한 고려 없이 producer를 직접 호출하는 구조로 되어 있다.

예제에 정의된바와 같이 스프링 부트용 카오스 몽키 테스트를 위해 chaostoolkit-spring 드라이버를 사용하는 것은 실 서비스에서 취약점이 될 수 있는 점을 잊지 말자. (역주: 따라서 테스트 이외의 실 서비스 배포에 적용하는 것은 주의 하도록 하자.)

Github link

{
    "version": "1.0.0",
    "title": "Setting and triggering service dependency death",
    "description": "Uses the Spring Chaos Monkey to manipulate a service",
    "tags": [
        "service",
        "spring"
    ],
    "steady-state-hypothesis": {
        "probes": [
            {
                "name": "consumer-service-must-still-respond",
                "provider": {
                    "type": "http",
                    "url": "http://localhost:8080/invokeConsumedService"
                },
                "tolerance": 200,
                "type": "probe"
            }
        ],
        "title": "System is healthy"
    },
    "method": [
        {
            "name": "enable_chaosmonkey",
            "provider": {
                "arguments": {
                    "base_url": "http://localhost:8090/actuator"
                },
                "func": "enable_chaosmonkey",
                "module": "chaosspring.actions",
                "type": "python"
            },
            "type": "action"
        },
        {
            "name": "configure_assaults",
            "provider": {
                "arguments": {
                    "base_url": "http://localhost:8090/actuator",
                    "assaults_configuration": {
                        "level": 1,
                        "latencyRangeStart": 2000,
                        "latencyRangeEnd": 5000,
                        "latencyActive": false,
                        "exceptionsActive": false,
                        "killApplicationActive": true,
                        "restartApplicationActive": false
                    }
                },
                "func": "change_assaults_configuration",
                "module": "chaosspring.actions",
                "type": "python"
            },
            "type": "action"
        },
        {
            "name": "trigger-kill",
            "provider": {
                "type": "http",
                "url": "http://localhost:8080/"
            },
            "type": "probe"
        }
    ],
    "rollbacks": []
}

이 실험에서 첫째로 확인할 사항은 provider 서비스에서 enable_chaosmonkey를 명시해서 스프링 부트용 카오스 몽키를 활성화 하는 것이다. (라인 25 참고)

두번째는 서비스 호출 또는 요청이 발생 할때마다 killApplicationActive 공격 트리거가 동작하도록 활성화 해야 한다. (라인 37 참고)

마지막으로 정상 상태(steady-state-hypothesis)를 정의하고 (라인 9 참고), killApplicationActive 공격(라인 58)을 트리거 하자.

공격은 스프링 부트 애플리케이션 설정의 감시자(watcher)를 통해 트리거 된다. 이 설정은 스프링 부트용 카오스 몽키에서 제공되는 것이며, 런타임에서 변경할 수는 없다. 아래의 기본 설정의 내용은 provider 애플리케이션이 (@Service 사용으로 인해) 유입되는 모든 요청에 watcher를 적용하는 것을 보여준다. (라인 13 참고)

Github Link to Spring Boot application properties

spring.application.name=ChaosDemo
server.port=8090

spring.profiles.active=chaos-monkey
chaos.monkey.enabled=false

management.endpoint.chaosmonkey.enabled=true

management.endpoints.web.exposure.include=*

chaos.monkey.assaults.latencyActive=false
chaos.monkey.assaults.killApplicationActive=false
chaos.monkey.watcher.restController=true

chaos.monkey.assaults.level=1

이 예제를 바탕으로 provider 서비스에 문제가 발생했을때 consumer 서비스가 어떻게 장애에 대응할 수 있는지 실험해 볼 수 있다.

실험 예제 2. “의존 관계에 있는 서비스의 응답이 느려지면 어떻게 하지?”

스프링 부트용 카오스 몽키에는 서비스에 지연시간 설정을 적용할 수 있는 기능이 포함되어 있으며, 아래의 가정을 바탕으로 테스트 수행이 가능하다.

“provider 서비스의 응답이 갑자기 느려진 상황에서 consumer 서비스는 어떻게 대응하는가?”

Github link to Latecy configuration

{
    "version": "1.0.0",
    "title": "Exploring assumptions if a dependency starts responding slowly",
    "description": "Uses the Spring Chaos Monkey to manipulate a service",
    "tags": [
        "service",
        "spring"
    ],
    "steady-state-hypothesis": {
        "probes": [
            {
                "name": "consumer-service-must-still-respond",
                "provider": {
                    "type": "http",
                    "url": "http://localhost:8080/invokeConsumedService"
                },
                "tolerance": 200,
                "type": "probe"
            }
        ],
        "title": "System is healthy"
    },
    "method": [
        {
            "name": "enable_chaosmonkey",
            "provider": {
                "arguments": {
                    "base_url": "http://localhost:8090/actuator"
                },
                "func": "enable_chaosmonkey",
                "module": "chaosspring.actions",
                "type": "python"
            },
            "type": "action"
        },
        {
            "name": "configure_assaults",
            "provider": {
                "arguments": {
                    "base_url": "http://localhost:8090/actuator",
                    "assaults_configuration": {
                        "level": 1,
                        "latencyRangeStart": 10000,
                        "latencyRangeEnd": 10000,
                        "latencyActive": true,
                        "exceptionsActive": false,
                        "killApplicationActive": false,
                        "restartApplicationActive": false
                    }
                },
                "func": "change_assaults_configuration",
                "module": "chaosspring.actions",
                "type": "python"
            },
            "type": "action"
        }
    ],
    "rollbacks": []
}

지연 시간 설정이 적용된 부분은 라인 43-45에 있다. 이 부분에서 카오스 툴킷을 통해 서비스 요청에 대한 지연 시간을 적용 한다. 따라서 consumer 서비스가 아주 느리게 응답하도록 구성된 provider 서비스에 대해 어떻게 반응하는지를 실험해 볼 수 있다.

소개된 두가지의 간단한 예제를 바탕으로 카오스 툴킷을 사용해서 애플리케이션 레벨에서 발생할 수 있는 장애 발생시 취약점을 실험할 수 있다. 추가로 소개되는 데모 코드를 통해 어떤 기능을 더 사용할 수 있는지 살펴보자. 카오스 툴킷 개발팀은 개발자 여러분의 피드백을 언제나 환영한다.

오픈 소스와 확장

카오스 툴킷을 무료 오픈 소스로 공개하는 목적은 애플리케이션 수준에서 카오스 엔지니어링을 더 쉽고 빠르게 사용할 수 있도록 하는 것이며, 가능한 경우 새로운 오픈 소스 또는 상용 프로젝트로 손쉽게 발전할 수 있도록 하기 위해서이다.

카오스 툴킷 커뮤니티는 스프링 부트용 카오스 몽키 프로젝트의 발전과 더 많은 사용자들이 모든 기능을 사용할 수 있도록 노력할 것이다.

카오스 툴킷 프로젝트에 참여하기

카오스 툴킷은 커뮤니티가 주도하는 오픈 소스 프로젝트이며, 모든 사용자가 카오스 엔지니어링을 자동화를 통해 사용할 수 있는 것을 목표로 한다. 특정 벤더에 종속적이지 않은 자유로운 프로젝트이며, 카오스 엔지니어링에 대해 배울 수 있는 좋은 프로젝트인 동시에, 경험을 통한 학습 기반으로 사용할 수 있으며, 카오스 엔지니어링 경험과 아이디어를 프로젝트에 적용할 수도 있을 것이다.

프로젝트에 관심이 있는 분들은 언제든 이슈 및 새로운 기능을 제기하거나, 코드로 제공하거나, 슬랙 채널 가입을 통해 이 프로젝트에 기여할 수 있다.