클라우드에서의 운영 - 12요소 애플리케이션
in DEV on MSA(Spring), 12-factor, Twelve-factor
이 포스트는 클라우드에서 운영 가능한 애플리케이션에서 기대할 수 있는 12가지 특징을 기술한 방법론에 대한 설명이다.
12요소 애플리케이션은 마이크로서비스에도 똑같이 적용할 수 있기 때문에 아래 내용을 이해해두는 것이 좋다.
- 1. Codebase (단일 코드 베이스)
- 2. Dependencies (의존성 꾸러미)
- 3. Config (환경설정 외부화)
- 4. Backing services (백엔드 서비스 접근성)
- 5. Build, release, run (빌드, 릴리즈, 운영의 격리)
- 6. Processes (무상태, 비공유 프로세스)
- 7. Port binding (서비스를 포트에 바인딩하여 노출)
- 8. Concurrency (확장을 위한 동시성)
- 9. Disposability (폐기 영향 최소화)
- 10. Dev/prod parity (개발과 운영의 짝 맞춤)
- 11. Logs (로그 외부화)
- 12. Admin processes (관리자 프로세스 패키징)
- 참고 사이트 & 함께 보면 좋은 사이트
Heroku(허로쿠) 가 제시한 12 요소 애플리케이션 은 클라우드에서 애플리케이션 개발 시 매끄러운 운영을 할 수 있도록 12가지 방법을 제안한다.
즉, 아래와 같은 성격의 애플리케이션을 구축하기 위한 방법론이다.
- 설정 자동화를 통하여 새로운 개발자의 시간과 비용을 최소화
- 운영체제에 크게 영향받지 않고, 실행 환경 간 이식성 최대화
- 최신 클라우드 플랫폼에 배포하기에 적합하여 서버 및 시스템 관리가 필요하지 않음
- 개발툴, 아키텍처, 개발방법을 크게 변경하지 않고 확장 가능
12 요소 애플리케이션
- Codebase (단일 코드 베이스)
- Dependencies (의존성 꾸러미)
- Config (환경설정 외부화)
- Backing services (후방 지원 서비스 접근성)
- Build, release, run (빌드, 출시, 운영의 격리)
- Processes (무상태, 비공유 프로세스)
- Port binding (서비스를 포트에 바인딩하여 노출)
- Concurrency (확장을 위한 동시성)
- Disposability (폐기 영향 최소화)
- Dev/prod parity (개발과 운영의 짝 맞춤)
- Logs (로그 외부화)
- Admin processes (관리자 프로세스 패키징)
1. Codebase (단일 코드 베이스)
각 애플리케이션은 하나의 코드 베이스만을 가져야 한다.
개발 버전, 스테이징 버전, 운영 버전 등 여러 개의 인스턴스들은 동일한 하나의 코드 베이스를 기반으로 구성한다.
코드는 일반적으로 Git 이나 Subversion 과 같은 형상 관리 도구를 이용하여 관리된다.
위 내용을 마이크로서비스로 확장해보면 각 마이크로서비스는 자체적인 코드 베이스를 가져야하고, 이 코드 베이스는 다른 마이크로서비스와 공유되지 않는다.
즉, 하나의 마이크로서비스는 정확히 하나의 코드 베이스를 가진다는 것을 의미한다.
2. Dependencies (의존성 꾸러미)
모든 애플리케이션은 필요한 모든 의존성을 애플리케이션과 함께 하나의 꾸러미에 담아야 한다.
Maven 이나 Gradle 같은 의존성 관리 툴을 사용하면 pom.xml 이나 .gradle 같은 의존성 선언 파일에서 명시적으로 의존성을 관리할 수 있고,
Nexus 나 Archiva 같은 중앙 빌드저장소를 이용해서 가져올 수 있다.(=의존성 관리 도구와 의존성 선언 파일로 라이브러리 의존성 관리)
이를 통해 버전도 관리할 수 있으며, 최종 실행 파일은 war 파일이나 실행 가능한 jar 파일로 패키징된다.
3. Config (환경설정 외부화)
모든 환경설정 파라미터를 코드와 분리해서 외부화한다.
애플리케이션의 환경설정 파라미터는 이메일 아이디, 외부 시스템의 URL, 비밀번호와 같이 운영될 환경에 따라 달라진다.
이런 파라미터들은 개발, 테스팅, 운영 버전에 따라서도 달라진다.
모든 서비스 환경설정 정보는 외부화되어야 한다.
환경에 따라 달라지는 유일한 것은 환경설정 파라미터밖에 없기 때문에 배포 프로세스 자동화에 도움이 된다.
4. Backing services (백엔드 서비스 접근성)
모든 백엔드 서비스(backing services) 는 URL 을 통해 접근 가능해야 한다.
모든 서비스는 실행 주기동안 외부의 자원과 의사소통해야 한다.
에를 들어 메시징 시스템을 통해 메시지를 주고 받고, DB 에 저장하는 것 등이 외부 자원과의 의사소통에 해당한다.
이러한 의사 소통은 복잡한 절차없이 URL 로 접근 가능해야 한다.
5. Build, release, run (빌드, 릴리즈, 운영의 격리)
빌드, 출시, 운영의 단계를 명확하게 격리한다.
- 빌드 : 모든 필요한 자원을 포함해서 컴파일하고 바이너리를 만들어 내는 과정
- 릴리즈 : 바이너리를 환경설정 파라미터와 혼합하는 과정
- 운영 : 특정 실행 환경에서 애플리케이션을 운영하는 과정
기본적으로 특정 빌드를 출시 과정을 건너뛰고 바로 운영단계로 넘기는 일은 없어야 한다.
파이프라인을 이용하여 모두 통과하게 하는 것이 좋다.
6. Processes (무상태, 비공유 프로세스)
무상태 (stateless), 비공유 프로세스(shared nothing processes) 원칙은 프로세스들이 상태가 없어야 하고, 아무것도 공유하지 않는 것이 좋다고 한다.
애플리케이션이 상태가 없다면 장애 대응성이 좋고 쉽게 확장될 수 있다.
만일 상태를 저장해야 하는 요구 사항이 있다면 DB 나 인메모리 캐시 같은 백엔드 서비스에서 처리되어야 한다.
7. Port binding (서비스를 포트에 바인딩하여 노출)
12요소 애플리케이션은 자기 완비적이어야 한다.
전통적으로 애플리케이션은 웹서버가 아파치 톰캣과 같은 애플리케이션 서버에 배포되는데 12요소 애플리케이션은 외부의 웹서버에 의존하지 않는다.
톰캣이나 제티같은 HTTP 리스너는 서비스 자체에 내장되어야 한다.
포트 바인딩은 마이크로서비스가 자율적이고 자기 완비적인 특성을 유지하는데 필요한 기본적인 요구 사항 중 하나다.
마이크로서비스는 서비스 리스너를 서비스 자체의 일부로 내장한다.
예를 들어 Spring 은 톰캣이나 제우스 등에 배포하는 반면, Springboot 는 내장형 톰캣을 이용하여 스스로 포트바인딩 후 HTTP 를 Listen 함.
8. Concurrency (확장을 위한 동시성)
프로세스가 복제(replicating) 를 통해 확장될 수 있게 설계되어야 한다.
이것은 프로세스 내부에서 추가적인 스레드를 사용할 수 있게 되는 것을 의미한다.
MSA 에서는 서비스가 서버의 자원을 늘리는 scale-up 이 아닌 서버의 갯수를 늘리는 scale-out 방식으로 확장된다.
scale-out 확장은 주로 동일한 서비스 인스턴스를 추가해서 서비스를 확장하는데 사용된다.
9. Disposability (폐기 영향 최소화)
애플리케이션의 시작과 종료에 필요한 시간을 최소화하고, 서버가 종료될 대에는 필요한 처리가 모두 수행되는 gracefully shutdown 이 되어야 한다.
자동화된 배포 환경에서는 가능한 빠른 시간안에 인스턴스를 올리거나 내려야 한다.
재기동의 시간은 애플리케이션의 크기에 비례한다.
마이크로서비스에서는 완전 자동화를 달성하기 위해 최소한의 시작/종료 시간을 갖게 애플리케이션의 크기를 가능한 한 작게 유지하는 것이 매우 중요하다.
이를 위해 마이크로서비스에서는 객체와 데이터의 지연 로딩(lazy loading)에 대해서도 고려해보아야 한다.
지연로딩
특정 리소스를 애플리케이션 시작 시 무조건 로딩하는 것이 아니라 런타임에서 실제 필요로 하는 시점에 로딩하는 것
10. Dev/prod parity (개발과 운영의 짝 맞춤)
개발과 운영의 짝 맞춤은 개발 환경과 운영 환경을 가능한 한 동일하게 유지하는 것이 좋다는 의미이다.
예를 들어 작업 스케쥴러 서비스나 캐시 서비스, 일반 애플리케이션 서비스를 생각해보면 개발 환경에서는 모든 구성 요소를 하나의 장비에서 구동하지만, 운영 환경에서는 구성 요소 각각을 별도의 독립된 장비에서 운영하나다.
개발 환경과 운영 환경을 다르게 하는 것은 인프라 비용 절감에 주요 목적이 있지만 운영 환경에서 장애가 발생할 경우 장애 해결을 위해 동일한 문제를 재연할 수 있는 동일한 환경이 없다는 단점이 있다.
11. Logs (로그 외부화)
클라우드에서는 로컬 I/O 를 피해야 한다.
주어진 인프라에서 I/O 가 충분히 빠르지 않다면 병목현상이 발생할 가능성이 높다.
이를 방지하기 위한 방법은 중앙 집중식 로깅 프레임워크를 사용하는 것인데 Splunk, Greylog, Logstash, Logplex, Loggly 등은 로그를 쌓고 분석할 수 있는 도구들이다.
권장되는 접근 방식은 logback appender 를 통해 로그를 중앙 저장소에 적재하고,
적재 도구의 종단점에 로그를 쓰는 방법이다.
마이크로서비스에서는 시스템을 더 작은 서비스로 나누는데 이런 방식은 로그가 분산될 가능성이 높으므로 로그를 중앙 집중화하는 것이 매우 중요하다.
로그를 로컬 저장소에 저장하면 각 서비스 로그의 연관성을 찾는 것이 매우 어려워진다.
12. Admin processes (관리자 프로세스 패키징)
애플리케이션 서비스와 별개로 대부분의 애플리케이션은 관리자 태스크로 함께 제공한다.
패키지 관리자 프로세스는 애플리케이션 서비스와 관리자 태스크 모두에 대해 동일환 환경,동일한 출시 버전을 사용하는 것을 권장한다.
관리자 태스크를 위한 코드도 애플리케이션 코드와 함께 패키징되어야 한다.
참고 사이트 & 함께 보면 좋은 사이트
- THE TWELVE-FACTOR APP
- THE TWELVE-FACTOR APP(한글)
- 스프링 부트와 스프링 클라우드로 배우는 스프링 마이크로서비스
- [MSA] 12요소 어플리케이션; 클라우드 네이티브 어플리케이션