편집

다음을 통해 공유


마이크로 서비스 아키텍처용 CI/CD

Azure

빠른 릴리스 주기는 마이크로 서비스 아키텍처의 주요 이점 중 하나입니다. 그러나 좋은 CI/CD 프로세스가 없으면 마이크로 서비스가 약속하는 민첩성을 달성할 수 없습니다. 이 문서에서는 문제를 설명하고 문제에 대한 몇 가지 방법을 권장합니다.

CI/CD란?

CI/CD에 대해 이야기할 때는 연속 통합, 지속적인 업데이트 및 지속적인 배포와 같은 몇 가지 관련 프로세스에 대해 설명합니다.

  • 연속 통합. 코드 변경 내용은 주 분기에 자주 병합됩니다. 자동화된 빌드 및 테스트 프로세스는 주 분기의 코드가 항상 프로덕션 품질인지 확인합니다.

  • 지속적인 업데이트. CI 프로세스를 통과하는 모든 코드 변경 내용은 프로덕션과 유사한 환경에 자동으로 게시됩니다. 라이브 프로덕션 환경에 배포하려면 수동 승인이 필요할 수 있지만 그렇지 않으면 자동화됩니다. 목표는 코드를 프로덕션 환경에 배포할 항상 준비해야 한다는 것입니다.

  • 연속 배포. 이전 두 단계를 통과하는 코드 변경 내용은 프로덕션자동으로 배포됩니다.

마이크로 서비스 아키텍처에 대한 강력한 CI/CD 프로세스의 몇 가지 목표는 다음과 같습니다.

  • 각 팀은 다른 팀에 영향을 미치거나 방해하지 않고 독립적으로 소유한 서비스를 빌드하고 배포할 수 있습니다.

  • 새 버전의 서비스를 프로덕션에 배포하기 전에 유효성 검사를 위해 개발/테스트/QA 환경에 배포됩니다. 품질 게이트는 각 단계에서 적용됩니다.

  • 새 버전의 서비스를 이전 버전과 함께 배포할 수 있습니다.

  • 충분한 액세스 제어 정책이 있습니다.

  • 컨테이너화된 워크로드의 경우 프로덕션에 배포된 컨테이너 이미지를 신뢰할 수 있습니다.

강력한 CI/CD 파이프라인이 중요한 이유

기존 모놀리식 애플리케이션에는 출력이 애플리케이션 실행 파일인 단일 빌드 파이프라인이 있습니다. 모든 개발 작업은 이 파이프라인에 피드됩니다. 우선 순위가 높은 버그가 발견되면 수정 사항을 통합, 테스트 및 게시해야 하므로 새 기능의 릴리스가 지연될 수 있습니다. 잘 구성된 모듈을 사용하고 기능 분기를 사용하여 코드 변경의 영향을 최소화하여 이러한 문제를 완화할 수 있습니다. 그러나 애플리케이션이 점점 더 복잡해지고 더 많은 기능이 추가됨에 따라 모놀리식에 대한 릴리스 프로세스가 더 취약해지고 중단될 가능성이 높아집니다.

마이크로 서비스 철학에 따라 모든 팀이 줄을 서야 하는 긴 릴리스 학습이 없어야 합니다. 서비스 "A"를 빌드하는 팀은 서비스 "B"의 변경 내용이 병합, 테스트 및 배포될 때까지 기다리지 않고 언제든지 업데이트를 릴리스할 수 있습니다.

CI/CD 모놀리식 다이어그램

높은 릴리스 속도를 달성하려면 위험을 최소화하기 위해 릴리스 파이프라인을 자동화하고 매우 안정적이어야 합니다. 매일 한 번 이상 프로덕션으로 릴리스하는 경우 회귀 또는 서비스 중단은 드물어야 합니다. 동시에 잘못된 업데이트가 배포되는 경우 이전 버전의 서비스로 신속하게 롤백하거나 롤백할 수 있는 신뢰할 수 있는 방법이 있어야 합니다.

도전

  • 많은 작은 독립 코드 베이스가. 각 팀은 자체 빌드 파이프라인을 사용하여 자체 서비스를 빌드할 책임이 있습니다. 일부 조직에서 팀은 별도의 코드 리포지토리를 사용할 수 있습니다. 별도의 리포지토리는 시스템을 빌드하는 방법에 대한 지식이 팀 전체에 분산되고 조직 내 아무도 전체 애플리케이션을 배포하는 방법을 알지 못하는 상황으로 이어질 수 있습니다. 예를 들어 새 클러스터에 신속하게 배포해야 하는 경우 재해 복구 시나리오에서 어떻게 되나요?

    완화: 통합되고 자동화된 파이프라인을 사용하여 서비스를 빌드하고 배포하므로 이 지식이 각 팀 내에서 "숨겨지지"않습니다.

  • 여러 언어 및 프레임워크. 각 팀이 자체 기술을 혼합하여 사용하는 경우 조직 전체에서 작동하는 단일 빌드 프로세스를 만들기가 어려울 수 있습니다. 빌드 프로세스는 모든 팀이 선택한 언어 또는 프레임워크에 맞게 조정할 수 있을 만큼 유연해야 합니다.

    완화: 각 서비스에 대한 빌드 프로세스를 컨테이너화합니다. 이렇게 하면 빌드 시스템에서 컨테이너를 실행할 수 있어야 합니다.

  • 통합 및 부하 테스트. 팀이 자체적으로 업데이트를 릴리스하는 경우 특히 서비스에 다른 서비스에 대한 종속성이 있는 경우 강력한 엔드 투 엔드 테스트를 설계하기가 어려울 수 있습니다. 또한 전체 프로덕션 클러스터를 실행하는 데 비용이 많이 들 수 있으므로 모든 팀이 테스트용으로만 프로덕션 규모에서 자체 전체 클러스터를 실행할 가능성은 낮습니다.

  • 릴리스 관리. 모든 팀은 프로덕션에 업데이트를 배포할 수 있어야 합니다. 그렇다고 해서 모든 팀 구성원이 그렇게 할 수 있는 권한이 있는 것은 아닙니다. 그러나 중앙 집중식 릴리스 관리자 역할을 사용하면 배포 속도를 줄일 수 있습니다.

    완화: CI/CD 프로세스가 자동화되고 안정적일수록 중앙 기관에 대한 필요성이 줄어듭니다. 즉, 주요 기능 업데이트와 사소한 버그 수정을 릴리스하기 위한 정책이 다를 수 있습니다. 탈중앙화되는 것은 제로 거버넌스를 의미하지 않는다.

  • 서비스는업데이트합니다. 서비스를 새 버전으로 업데이트하는 경우 해당 서비스에 의존하는 다른 서비스가 중단되어서는 안 됩니다.

    완화: 호환성이 손상되지 않는 변경에는 파란색-녹색 또는 카나리아 릴리스와 같은 배포 기술을 사용합니다. API 변경을 중단하려면 새 버전을 이전 버전과 나란히 배포합니다. 이렇게 하면 이전 API를 사용하는 서비스를 업데이트하고 새 API에 대해 테스트할 수 있습니다. 아래의 업데이트 서비스참조하세요.

Monorepo 및 다중 리포지토리

CI/CD 워크플로를 만들기 전에 코드 베이스가 어떻게 구조화되고 관리되는지 알고 있어야 합니다.

  • 팀은 별도의 리포지토리 또는 모노레포지토리(단일 리포지토리)에서 작업합니까?
  • 분기 전략은 무엇인가요?
  • 프로덕션에 코드를 푸시할 수 있는 사람은 누구인가요? 릴리스 관리자 역할이 있나요?

모노레포 접근 방식은 호의를 얻고 있지만 두 가지 모두에 장점과 단점이 있습니다.

  Monorepo 여러 리포지토리
장점 코드 공유
코드 및 도구를 표준화하기 쉽습니다.
코드 리팩터링하기 쉽습니다.
검색 가능성 - 코드의 단일 보기
팀당 소유권 지우기
잠재적으로 적은 병합 충돌
마이크로 서비스의 분리를 적용하는 데 도움이 됩니다.
챌린지 공유 코드를 변경하면 여러 마이크로 서비스에 영향을 줄 수 있습니다.
병합 충돌 가능성이 높아질 수 있습니다.
도구는 큰 코드 베이스로 확장해야 합니다.
액세스 제어
더 복잡한 배포 프로세스
코드를 공유하기가 더 어렵습니다.
코딩 표준을 적용하기가 더 어렵습니다.
종속성 관리
확산 코드 베이스, 잘못된 검색 가능성
공유 인프라 부족

서비스 업데이트

이미 프로덕션 상태인 서비스를 업데이트하기 위한 다양한 전략이 있습니다. 여기서는 롤링 업데이트, 파란색-녹색 배포 및 카나리아 릴리스의 세 가지 일반적인 옵션에 대해 설명합니다.

롤링 업데이트

롤링 업데이트에서는 서비스의 새 인스턴스를 배포하고 새 인스턴스는 즉시 요청을 받기 시작합니다. 새 인스턴스가 등장하면 이전 인스턴스가 제거됩니다.

본보기. Kubernetes에서 롤링 업데이트는 배포대한 Pod 사양을 업데이트할 때 기본 동작입니다. 배포 컨트롤러는 업데이트된 Pod에 대한 새 ReplicaSet을 만듭니다. 그런 다음, 원하는 복제본 수를 유지하기 위해 이전 복제본을 축소하는 동안 새 ReplicaSet을 확장합니다. 새 Pod가 준비될 때까지 이전 Pod는 삭제되지 않습니다. Kubernetes는 업데이트 기록을 유지하므로 필요한 경우 업데이트를 롤백할 수 있습니다.

본보기. Azure Service Fabric은 기본적으로 롤링 업데이트 전략을 사용합니다. 이 전략은 기존 API를 변경하지 않고 새 기능을 사용하여 서비스 버전을 배포하는 데 가장 적합합니다. Service Fabric은 애플리케이션 유형을 노드 또는 업데이트 도메인의 하위 집합으로 업데이트하여 업그레이드 배포를 시작합니다. 그런 다음 모든 도메인이 업그레이드될 때까지 다음 업데이트 도메인으로 롤업합니다. 업그레이드 도메인을 업데이트하지 못하면 애플리케이션 유형이 모든 도메인에서 이전 버전으로 롤백됩니다. 여러 서비스가 있는 애플리케이션 유형(그리고 모든 서비스가 하나의 업그레이드 배포의 일부로 업데이트되는 경우)은 오류가 발생하기 쉽습니다. 한 서비스를 업데이트하지 못하면 전체 애플리케이션이 이전 버전으로 롤백되고 다른 서비스는 업데이트되지 않습니다.

업데이트 롤링의 한 가지 과제는 업데이트 프로세스 중에 이전 버전과 새 버전이 혼합되어 실행되고 트래픽을 수신한다는 것입니다. 이 기간 동안 모든 요청은 두 버전 중 하나에 라우팅될 수 있습니다.

호환성이 손상되는 API 변경의 경우 이전 버전의 모든 클라이언트가 업데이트될 때까지 두 버전을 함께 지원하는 것이 좋습니다. API 버전 관리참조하세요.

파란색-녹색 배포

파란색-녹색 배포에서는 이전 버전과 함께 새 버전을 배포합니다. 새 버전의 유효성을 검사한 후 모든 트래픽을 이전 버전에서 새 버전으로 한 번에 전환합니다. 전환 후 애플리케이션에서 문제를 모니터링합니다. 문제가 발생하면 이전 버전으로 다시 교환할 수 있습니다. 문제가 없다고 가정하면 이전 버전을 삭제할 수 있습니다.

보다 전통적인 모놀리식 또는 N 계층 애플리케이션을 사용하는 파란색-녹색 배포는 일반적으로 두 개의 동일한 환경을 프로비전하는 것을 의미했습니다. 새 버전을 스테이징 환경에 배포한 다음 VIP 주소를 교환하여 클라이언트 트래픽을 스테이징 환경으로 리디렉션합니다. 마이크로 서비스 아키텍처에서 업데이트는 마이크로 서비스 수준에서 수행되므로 일반적으로 업데이트를 동일한 환경에 배포하고 서비스 검색 메커니즘을 사용하여 교환합니다.

예제. Kubernetes에서는 청록색 배포를 수행하도록 별도의 클러스터를 프로비전할 필요가 없습니다. 대신 선택기를 활용할 수 있습니다. 새 Pod 사양 및 다른 레이블 집합을 사용하여 새 배포 리소스를 만듭니다. 이전 배포를 삭제하거나 이를 가리키는 서비스를 수정하지 않고 이 배포를 만듭니다. 새 Pod가 실행되면 새 배포와 일치하도록 서비스의 선택기를 업데이트할 수 있습니다.

청록색 배포의 한 가지 단점은 업데이트 중에 서비스에 대해 두 배의 Pod(현재 및 다음)를 실행한다는 것입니다. Pod에 많은 CPU 또는 메모리 리소스가 필요한 경우 리소스 사용을 처리하기 위해 클러스터를 일시적으로 확장해야 할 수 있습니다.

카나리아 릴리스

카나리아 릴리스에서는 소수의 클라이언트에 업데이트된 버전을 롤아웃합니다. 그런 다음 모든 클라이언트에 배포하기 전에 새 서비스의 동작을 모니터링합니다. 이렇게 하면 제어된 방식으로 느린 롤아웃을 수행하고, 실제 데이터를 관찰하고, 모든 고객이 영향을 받기 전에 문제를 발견할 수 있습니다.

카나리아 릴리스는 요청을 다른 버전의 서비스로 동적으로 라우팅해야 하므로 청록색 또는 롤링 업데이트보다 관리가 더 복잡합니다.

예제. Kubernetes에서 서비스 구성하여 두 개의 복제본 집합(각 버전마다 하나씩)에 걸쳐 있고 복제본 수를 수동으로 조정할 수 있습니다. 그러나 Kubernetes가 Pod 간에 부하를 분산하는 방식 때문에 이 방법은 다소 세분화되어 있습니다. 예를 들어 총 10개의 복제본이 있는 경우 트래픽을 10개% 증분 단위로만 이동할 수 있습니다. 서비스 메시를 사용하는 경우 서비스 메시 라우팅 규칙을 사용하여 보다 정교한 카나리아 릴리스 전략을 구현할 수 있습니다.

다음 단계