클라우드 네이티브 마이크로서비스를 만드는 어려움을 대처하고자 12 팩터 앱(twelve-factor app)이라는 헤로쿠(Heroku)의 모범 사례 지침을 확인한다. 12 팩터 앱을 사용하여 고품질의 클라우드 네이티브 애플리케이션을 구축할 수 있다. 이 방법 이론은 분산 서비스를 구축할 때 동적인 확장과 기본 사항에 관한 개발 및 설계 지침의 모음이다.
1. 코드베이스(codebase)
마이크로서비스는 소스 제어 가능한 단일 코드베이스를 가진다. 또한 코드베이스에 서버 프로비저닝 정보를 버전 관리한다고 강조하는 것도 중요하다. 버전 관리는 한 파일 및 파일들의 변경 사항을 관리한다는 것을 기억하자.
코드베이스는 여러 배포 환경(개발, 테스팅, 스테이징, 운영 환경 등)을 포함할 수 있지만 다른 마이크로서비스와 공유되지 않는다. 코드베이스가 모든 마이크로서비스와 공유되면 다른 환경에 속하는 많은 불변 릴리즈를 만들어 낼 수 있기 때문에 이 점은 중요한 지침이다.
2. 의존성
이 사례는 애플리케이션이 메이븐이나 그레이들 같은 자바용 빌드 도구로 사용되는 의존성을 선언한 것이다. 써드 파티 JAR 의존성은 특정 버전 번호를 명시하는데, 이것으로 항상 동일한 라이브러리 버전으로 마이크로서비스를 빌드할 수 있다.
3. 구성 정보
애플리케이션 구성 정보, 특히 환경별 구성 정보를 저장하는 방식에 관한 것이다. 절대로 소스 코드에 구성 정보를 추가하지 마라. 그리고 구성 정보를 배포할 마이크로서비스와 완전히 분리해서 관리하는 것이 최선이다.
100개로 확장된 특정 마이크로서비스의 구성 정보를 업데이트해야 하는 시나리오를 상상해 보자. 마이크로서비스 내 구성 정보가 포함되어 있다면 100개의 인스턴스를 모두 재배포해야 할 것이다. 하지만 마이크로서비스가 외부 구성 정보를 가져오거나 클라우드 서비스를 사용하면 마이크로서비스 재시작하지 않고 실행 중 구성 정보를 갱신할 수 있다.
4. 백엔드 서비스
마이크로서비스는 대개 데이터베이스나 API RESTful 서비스, 다른 서버, 메시징 시스템 등과 네트워크로 통신한다. 이 경우 애플리케이션 코드의 변경 없이 로컬 및 써드 파티와 연결하는 데 배포 구현체를 교체할 수 있는지 확인해야 한다.
5. 빌드, 릴리스, 실행
애플리케이션 배포 단계, 즉 빌드, 릴리스, 실행 단계가 철저히 분리되어야 한다는 점을 상기시킨다. 실행할 환경에 독립적으로 마이크로서비스를 구축해야 한다는 것이다. 코드가 빌드되면 런타임 변경 사항은 빌드 프로세스를 거쳐 재배포되어야 하고 빌드된 서비스는 변경될 수 없어야 한다.
릴리스 단계는 빌드된 서비스를 대상 환경 구성 정보와 결합하는 역할을 한다. 각 단계를 분리하지 않으면 아예 추적이 불가하거나 잘해야 어려운 정도의 코드상 문제를 겪게 된다. 예를 들어 운영 환경에 이미 배포된 서비스를 변경한다면, 이 변경 사항은 저장소에 기록되지 않아서 서비스의 새 버전에서 변경 사항이 누락되거나 새 버전에 변경 사항을 다시 복사해야 하는 두 가지 상황이 발생할 수 있다.
6. 프로세스
마이크로서비스는 항상 무상태(stateless)가 되어야 하며 요청받은 트랜잭션을 수행하는 데 필요한 정보만 포함되어야 한다. 마이크로서비스는 서비스 인스턴스 손실로 데이터가 손실될 것이라는 걱정 없이 언제든 중단되고 교체될 수 있다. 상태를 저장해야 하는 특별한 요구사항이 있다면 Redis 같은 메모리 캐시나 백업 데이터베이스를 사용하여 수행할 수 있다
7. 포트 바인딩
포트 바인딩은 특정 포트로 서비스를 게시하는 것을 의미한다. 마이크로서비스 아키텍처에서 마이크로서비스는 서비스 실행 파일로 패키징된 서비스용 런타임 엔진이 포함되어 완전히 독립적이다. 따라서 별도의 웹 서버나 애플리케이션 서버 없이 서비스를 실행할 수 있다. 서비스는 명령줄에서 시작되어야 하고 노출된 HTTP 포트를 사용하여 바로 액세스할 수 있다.
8. 동시성
동시성(concurrency)의 중요한 점은 클라우드 네이티브 애플리케이션 프로세스 모델을 사용해서 확장해야 한다. 중요한 프로세스 하나를 더 크게 만드는 대신 프로세스를 많이 생성하여 서비스 부하 또는 애플리케이션을 여러 프로세스에 분산한다고 생각하면 그 의미를 이해할 수 있을 것이다.
수직 확장(scale up)은 하드웨어 인프라스트럭처(CPU, RAM)를 늘리는 것이며, 수평 확장(scale out)은 애플리케이션 인스턴스를 더 추가하는 것이다. 확장이 필요하다면 수직 확장 대신 더 많은 인스턴스를 시작해서 수평 확장이 좋다.
- 수직 확장 (scale up) : 하나의 서버 성능을 높이는 방식(CPU, RAM, 디스크) 으로 관리가 쉽지만 물리적 한계와 단일 서버라는 단점이 있다.
- 수평 확장 (scale out) : 여러 서버를 추가해 동일 애플리케이션을 실행하는 방식이다.
9. 폐기 가능
마이크로서비스는 폐기 가능하며 탄력적을 확장을 유도하고 애플리케이션 코드나 구성 변경 사항을 신속하게 배포하고자 팔요에 따라 시작하고 중지할 수 있다. 이상적으로 시작은 시작 명령이 실행되는 순간부터 프로세스가 요청받을 준비가 될 때까지 며 초 동안 소요된다.
폐기 가능하다는 것은 다른 서비스에 영향을 주지 않고 새로운 인스턴스로, 실패한 인스턴스를 제거할 수 있다는 의미다. 얘를 들어 내부 하드웨어 고장으로 마이크로서비스 인스턴스 중 하나가 실패하더라도 다른 마이크로서비스에 영향을 주지 않고 해당 인스턴스를 종료한 채 필요한 경우 다른 인스터는를 시작할 수 있다
10. 개발 및 운영 환경 일치
이 사례는 가능한 유사한 여러 환경(개발, 스테이징, 운영 환경 등)을 갖게 된다는 것을 나타낸다. 환경에는 항상 유사한 버전의 인프라 및 서비스뿐 아니라 배포된 코드도 포함되어야 한다. 이는 배포 프로세스를 최대한 자동화하는 지속적 배포로 완성할 수 있어 마이크로서비스를 짧은 시간에 여러 환경에 배포할 수 있다.
코드가 커밋되는 즉시 테스트를 거쳐 개발 환경에서 운영 환경까지 가능한 신속하게 이동해야 한다. 배포 오류를 피하려면 이 지침은 필수적이다. 유사한 개발 및 운영 환경을 유지하면 애플리키이션을 배포하고 실행하는 동안 발생할 수 있는 모든 가능한 시나리오를 통제할 수 있다.
11. 로그
로그는 이벤트 스트림이다. 출력된 로그를 수집하고 중앙 저장소에 기록하는 로그스태시(Logstash)나 플루언트디(Fluentd)와 같은 도구로 관리해야 한다. 마이크로서비스는 이러한 내부 동작 매커니즘에 관여하지 않고 표준 출력(stdout)으로 로그를 기록하는 데만 집중해야한다. ELK 스택은 마이크로서비스 아키텍처에서 로깅의 작동 방식을 보여준다.
12. 관리 프로세스
개발자는 종종 데이터 이전이나 변호나 같은 서비스 관리 작업을 해야 한다. 이러한 작업은 임시변통해서는 안 되며 소스 코드 저장소에서 관리 및 유지되는 스크립트로 수행되어야 한다. 스크립트는 실행되는 모든 환경에서 반복 가능하고 변경되지 않아야 하며 각 환경에 따라 개별 수정되지 않는다. 마이크로서비스 실행 중 고려되어야 할 작업 유형을 정의하는 것이 중요한데, 스크립트와 관련된 여러 마이크로서비스가 있을 때는 수동 작업 없이도 모든 관리 작업을 실행 할 수 있다.
'마이크로서비스' 카테고리의 다른 글
Springboot 마이크로서비스 기본 개발 (0) | 2024.10.17 |
---|---|
마이크로서비시 아키텍처 설계 (0) | 2024.10.14 |
스프링 클라우드란? (1) | 2024.10.07 |
마이크로서비스 개발 패턴 (3) | 2024.09.10 |
마이크로서비스의 이해 (0) | 2024.09.09 |