2025. 2. 26. 23:39ㆍSpring Microservice
더 빠른 릴리스 주기는 마이크로서비스 아키텍처의 주요 이점 중 하나입니다. 하지만 좋은 CI/CD 프로세스가 없으면 마이크로서비스가 약속하는 민첩성을 달성할 수 없습니다. 이 섹션에서는 문제점을 설명하고 문제에 대한 몇 가지 접근 방식을 권장합니다.
CI/CD란?
CI/CD는 지속적 통합(Continuous Integration), 지속적 전달(Continuous Delivery), 지속적 배포(Continuous Deployment) 를 포함하는 여러 관련 프로세스를 의미합니다.
📌 지속적 통합(Continuous Integration, CI)
- 코드 변경 사항이 자주(main 브랜치에) 병합됨
- 자동화된 빌드 및 테스트 프로세스를 통해 코드가 항상 프로덕션 품질을 유지
📌 지속적 전달(Continuous Delivery, CD)
- CI를 통과한 코드 변경 사항이 자동으로 프로덕션과 유사한 환경에 배포됨
- 실제 프로덕션 배포는 수동 승인(Manual Approval)을 요구할 수도 있음
- 목표: 코드가 항상 프로덕션 배포 준비 상태를 유지하는 것
📌 지속적 배포(Continuous Deployment, CD)
- 이전 두 단계를 통과한 코드 변경 사항이 자동으로 프로덕션 환경에 배포됨
📌 마이크로서비스 아키텍처에서 CI/CD의 목표
1️⃣ 각 팀이 독립적으로 서비스 빌드 및 배포 가능
- 다른 팀에 영향을 주지 않고 자체적으로 서비스를 관리할 수 있어야 함.
2️⃣ 새로운 서비스 버전은 프로덕션 배포 전에 개발(dev), 테스트(test), QA 환경에서 검증됨
- 각 단계에서 품질 게이트(Quality Gates)를 적용 하여 안정성을 확보.
3️⃣ 이전 버전과 새로운 버전이 동시에 배포될 수 있어야 함
- 서비스 간의 하위 호환성을 유지할 수 있도록 고려해야 함.
4️⃣ 적절한 접근 제어 정책(Access Control Policy)이 마련되어 있어야 함
5️⃣ 컨테이너화된 워크로드(Containerized Workloads)의 경우, 프로덕션에 배포되는 컨테이너 이미지를 신뢰할 수 있어야 함
- 보안 및 무결성을 유지하기 위해 서명된 이미지(Signed Images) 또는 신뢰할 수 있는 레지스트리(Trusted Registry)를 사용해야 함.
강력한 CI/CD 파이프라인이 중요한 이유
✅ 모놀리식 애플리케이션(Monolithic Application)에서의 문제점
- 전통적인 모놀리식 애플리케이션 은 단일 빌드 파이프라인을 가집니다.
- 모든 개발 작업이 이 하나의 빌드 파이프라인에 통합 됩니다.
- 높은 우선순위의 버그가 발견되면,
- 수정 사항을 통합하고, 테스트하고, 배포하는 과정에서 새로운 기능의 출시가 지연될 수 있습니다.
- 이러한 문제를 완화하려면
- 잘 분리된 모듈(Modularization)과 기능 브랜치(Feature Branches) 를 활용해야 합니다.
- 하지만 애플리케이션이 커지고 기능이 많아질수록,
- 모놀리식 아키텍처의 릴리스 프로세스는 점점 더 취약(Brittle)하고 깨지기 쉬운(Breaking) 상태가 됩니다.
✅ 마이크로서비스(Microservices)에서의 개선점
- 마이크로서비스 철학에 따르면,
- 하나의 긴 릴리스 과정(Release Train)에서 모든 팀이 줄을 서서 대기하는 상황이 없어야 합니다.
- 예를 들어,
- 서비스 "A"를 개발하는 팀은, 서비스 "B"의 변경 사항을 기다릴 필요 없이 독립적으로 업데이트를 배포할 수 있어야 합니다.
✅ 고속 릴리스를 위한 자동화된 파이프라인
- 높은 릴리스 속도(High Release Velocity)를 달성하려면,
- 릴리스 파이프라인이 자동화되고, 신뢰성이 높아야 합니다.
- 하루에도 여러 번 프로덕션에 배포 하려면
- 서비스 장애(Service Disruptions)나 회귀 버그(Regressions)가 거의 발생하지 않아야 합니다.
- 잘못된 업데이트가 배포되더라도,
- 빠르게 롤백(Rollback)하거나, 롤포워드(Roll Forward) 할 수 있는 신뢰할 수 있는 방법이 필요합니다.
도전 과제(Challenges)
1️⃣ 많은 독립적인 코드베이스 (Many small independent code bases)
- 각 팀은 자신의 서비스 개발 및 빌드 파이프라인을 독립적으로 관리 합니다.
- 일부 조직에서는 각 팀이 개별적인 코드 저장소(Repository)를 사용할 수도 있습니다.
- 각 팀만이 서비스 빌드 및 배포 방법을 알고 있다면, 조직 전체에서 애플리케이션을 배포하는 방법을 명확히 알기 어려울 수 있습니다.
- 예를 들어, 재해 복구(Disaster Recovery) 시나리오에서
- 빠르게 새로운 클러스터에 배포해야 할 경우,
- 조직 내 누구도 전체 애플리케이션을 배포하는 방법을 모를 위험이 있습니다.
✅ 해결책 (Mitigation):
- 서비스를 빌드하고 배포하는 단일화된 자동화된 파이프라인을 구축 합니다.
- 이를 통해 각 팀이 가진 지식이 숨겨지지 않고 공유될 수 있도록 합니다.
2️⃣ 다양한 언어 및 프레임워크 사용 (Multiple languages and frameworks)
- 각 팀이 자신만의 기술 스택(Language & Framework)을 사용할 경우,
- 조직 전체에서 단일 빌드 프로세스를 구성하는 것이 어려울 수 있습니다.
- 빌드 프로세스는 모든 팀이 자신이 선택한 언어와 프레임워크에 맞게 조정할 수 있도록 유연해야 합니다.
✅ 해결책 (Mitigation):
- 각 서비스의 빌드 프로세스를 컨테이너화(Containerize)합니다.
- 빌드 시스템은 컨테이너 실행만 지원하면 되므로, 서비스별 언어나 프레임워크에 대한 의존성이 줄어듭니다.
3️⃣ 통합 및 부하 테스트 (Integration and Load Testing)
- 각 팀이 독립적으로 업데이트를 배포 하면,
- 서비스 간의 종속성(Dependencies) 때문에 엔드 투 엔드(End-to-End) 테스트를 설계하는 것이 어려울 수 있습니다.
- 실제 프로덕션 환경과 동일한 규모의 클러스터에서 테스트하는 것은 비용이 많이 듭니다.
- 따라서 각 팀이 개별적으로 프로덕션과 같은 규모의 테스트 환경을 운영하는 것은 비현실적일 수 있습니다.
4️⃣ 릴리스 관리 (Release Management)
- 각 팀은 독립적으로 프로덕션 배포를 수행할 수 있어야 합니다.
- 하지만 모든 팀원이 프로덕션 배포 권한을 가져야 하는 것은 아닙니다.
- 중앙화된 릴리스 매니저(Release Manager) 역할이 배포 속도를 저하시킬 가능성이 있음.
✅ 해결책 (Mitigation):
- CI/CD 프로세스를 최대한 자동화하고 신뢰성을 높이면, 중앙 승인 없이도 배포가 가능해집니다.
- 단, 대형 기능 업데이트(Major Feature Updates)와 사소한 버그 수정(Minor Bug Fixes)에 대한 릴리스 정책을 다르게 운영할 수 있습니다.
- 탈중앙화(Decentralization)는 곧 "무질서(Zero Governance)"를 의미하는 것이 아닙니다.
5️⃣ 서비스 업데이트 (Service Updates)
- 새로운 버전의 서비스가 배포될 때, 기존 서비스의 기능을 깨뜨리지 않아야 합니다.
✅ 해결책 (Mitigation):
- Blue-Green 배포 또는 Canary 배포 같은 배포 기법을 활용하여,
- 기존 서비스가 중단되지 않는 방식으로 업데이트를 진행합니다.
- API의 호환성을 깨뜨리는 변경(Breaking API Changes) 가 필요한 경우:
- 기존 API 버전과 새로운 API 버전을 나란히 배포(Side-by-Side Deployment)하여
- 기존 API를 사용하는 서비스가 새로운 API로 안전하게 전환할 수 있도록 합니다.
- 자세한 내용은 아래 "Updating Services" 섹션에서 다룹니다.
모노레포(Monorepo) vs. 멀티레포(Multi-repo)
CI/CD 워크플로우를 생성하기 전에, 코드베이스(Codebase)의 구조와 관리 방식 을 결정해야 합니다.
✅ 고려할 질문
- 팀별로 각각의 코드 저장소(Repository)를 사용할 것인가, 아니면 단일 저장소(Monorepo)를 사용할 것인가?
- 브랜치 전략(Branching Strategy)은 어떻게 할 것인가?
- 누가 프로덕션에 코드를 푸시할 수 있는가? 릴리스 매니저(Release Manager) 역할이 필요한가?
최근 모노레포(Monorepo) 방식이 인기를 얻고 있지만, 두 방식 모두 장점과 단점이 존재 합니다.
🔹 모노레포(Monorepo) vs. 멀티레포(Multi-repo) 비교
모노레포 (Monorepo) | 멀티레포 (Multiple Repos) | |
---|---|---|
✅ 장점(Advantages) | 코드 공유(Code Sharing) 용이 | 팀별 코드 소유권 명확 (Clear ownership per team) |
코드 표준화(Standardization) 및 도구 통합 용이 | 병합 충돌(Merge Conflicts) 발생 가능성 감소 | |
리팩토링(Refactoring) 쉬움 | 마이크로서비스 간 결합도(Decoupling) 유지 용이 | |
코드 탐색성(Discoverability) 증가 - 코드 전체를 한눈에 볼 수 있음 | ||
⚠️ 도전 과제(Challenges) | 공유 코드 변경이 여러 마이크로서비스에 영향을 줄 수 있음 | 코드 공유(Dependency Management) 어려움 |
병합 충돌 가능성 증가 | 코딩 표준(Coding Standards) 강제 적용 어려움 | |
대규모 코드베이스에서 도구(빌드/테스트) 확장 필요 | 분산된 코드베이스(Diffuse Code Base)로 인해 코드 탐색 어려움 | |
액세스 제어(Access Control) 복잡 | 공유 인프라(Shared Infrastructure) 부족 | |
배포 프로세스(Deployment Process) 더 복잡할 수 있음 |
🔹 선택 기준
- 서비스 간 코드 공유가 많다면? → 모노레포(Monorepo) 추천
- 마이크로서비스 간 독립성이 중요하다면? → 멀티레포(Multi-repo) 추천
- 조직 내 표준화 및 도구 일관성이 필요하다면? → 모노레포(Monorepo) 추천
- 팀별 독립적인 배포를 원한다면? → 멀티레포(Multi-repo) 추천
서비스 업데이트(Updating Services)
운영 중인 서비스의 업데이트에는 여러 가지 전략이 있습니다.
여기서는 롤링 업데이트(Rolling Update), 블루-그린 배포(Blue-Green Deployment), 카나리 릴리스(Canary Release) 세 가지 일반적인 방법을 설명합니다.
1️⃣ 롤링 업데이트 (Rolling Updates)
- 새로운 인스턴스를 배포하면 즉시 요청을 받기 시작 합니다.
- 기존 인스턴스가 제거되면서 점진적으로 새 버전으로 교체됩니다.
✅ 예시
📌 Kubernetes
- 기본적으로 롤링 업데이트 방식을 사용합니다.
- 새로운 ReplicaSet 을 생성한 후,
- 새로운 인스턴스를 점진적으로 추가하고, 기존 인스턴스를 점진적으로 제거 합니다.
- 기존 Pod을 즉시 삭제하지 않고, 새 Pod이 준비될 때까지 유지 합니다.
- 업데이트 히스토리를 저장 하므로, 필요하면 롤백할 수도 있습니다.
📌 Azure Service Fabric
- 기본적으로 롤링 업데이트 전략을 사용합니다.
- 업그레이드 도메인(Update Domain) 단위로 점진적으로 업데이트 진행
- 만약 특정 업그레이드 도메인에서 실패하면,
- 이전 버전으로 롤백됨
- 애플리케이션 유형(Application Type) 내에서 여러 서비스가 동시에 업데이트될 경우,
- 한 서비스라도 실패하면 전체 애플리케이션이 이전 버전으로 롤백됨
⚠️ 롤링 업데이트의 단점
- 업데이트 중에 구버전과 신버전이 혼합되어 실행 됩니다.
- 이로 인해 같은 요청이 구버전과 신버전 중 어디로 갈지 예측하기 어려움
- API가 변경(Breaking API Change)되는 경우,
- 기존 API와 새로운 API를 동시에 지원해야 함
- → 자세한 내용은 API 버전 관리(API Versioning) 참고
2️⃣ 블루-그린 배포 (Blue-Green Deployment)
- 신규 버전을 기존 버전과 나란히 배포
- 신규 버전이 정상적으로 실행되는지 검증 후, 트래픽을 한 번에 전환(Switch)
- 문제가 발생하면 즉시 기존 버전으로 롤백 가능
✅ 예시
📌 전통적인 모놀리식 또는 N-Tier 애플리케이션에서의 블루-그린 배포
- 동일한 환경을 두 개(BLUE, GREEN) 운영
- 새로운 버전을 스테이징 환경에 배포한 후, VIP 주소를 스와핑하여 트래픽을 전환
📌 Kubernetes에서의 블루-그린 배포
- 별도의 클러스터를 생성하지 않고, 라벨(Labels)과 셀렉터(Selectors)를 활용
- 새로운 Deployment를 생성하고, 기존 Deployment는 유지
- 새 버전의 Pod이 준비되면, 서비스의 셀렉터를 새 Deployment로 업데이트하여 트래픽을 전환
⚠️ 블루-그린 배포의 단점
- 배포 중에 두 배의 리소스를 사용
- CPU 및 메모리 사용량이 높은 애플리케이션의 경우,
- 일시적으로 클러스터를 확장(Scale Out)해야 할 수도 있음
3️⃣ 카나리 릴리스 (Canary Release)
- 소수의 사용자(일부 트래픽)에게 먼저 새로운 버전을 제공
- 신규 버전의 동작을 관찰한 후, 이상이 없으면 전체 트래픽으로 확대
- 실제 트래픽 데이터를 기반으로 업데이트 안정성을 검증 가능
✅ 예시
📌 Kubernetes에서 카나리 릴리스 적용 방법
- 두 개의 ReplicaSet을 생성 (각각 구버전, 신버전용)
- Replica 개수를 조정하여 트래픽을 점진적으로 신버전으로 이동
- Kubernetes의 기본 로드 밸런싱 방식으로 인해,
- 트래픽 이동 비율을 10% 단위로 조정 가능
📌 서비스 메시(Service Mesh) 기반 카나리 릴리스
- Istio 같은 서비스 메시를 활용하면 더 정교한 트래픽 제어 가능
- 특정 사용자 그룹(예: 내부 사용자)에게만 신버전을 먼저 배포하는 방식 도 가능
⚠️ 카나리 릴리스의 단점
- 트래픽을 동적으로 신구 버전으로 라우팅해야 하므로 관리가 복잡
- 로드 밸런서 설정 및 서비스 메시 라우팅 규칙이 필요
📌 각 업데이트 방식 비교
배포 방식 | 트래픽 전환 방식 | 롤백 가능 여부 | 리소스 사용량 | 주요 단점 |
---|---|---|---|---|
롤링 업데이트 | 점진적으로 트래픽 이동 | 가능 | 낮음 | 업데이트 중 구버전과 신버전이 혼합됨 |
블루-그린 배포 | 트래픽을 한 번에 전환 | 가능 | 높음 (일시적으로 2배) | 추가 리소스 필요 |
카나리 릴리스 | 점진적으로 특정 사용자 그룹에 배포 | 가능 | 중간 | 라우팅 관리 복잡 |
✅ 롤링 업데이트 → API 변경이 없는 일반적인 업데이트에 적합
✅ 블루-그린 배포 → 안정성이 중요한 경우, 즉시 롤백이 필요할 때 적합
✅ 카나리 릴리스 → 대규모 트래픽을 대상으로 안정성을 점검해야 할 때 적합
출처 : https://learn.microsoft.com/en-us/azure/architecture/microservices/ci-cd
'Spring Microservice' 카테고리의 다른 글
1.Welcome to the Spring Cloud (0) | 2025.02.28 |
---|---|
Why use a microservices approach to building applications (0) | 2025.02.27 |
Microservices assessment and readiness (0) | 2025.02.26 |
Identify microservice boundaries (0) | 2025.02.26 |
Using tactical DDD to design microservices (0) | 2025.02.26 |