다음을 통해 공유


Microsoft가 DevOps를 사용하여 개발하는 방법

Microsoft는 One Engineering System 을 사용하여 Git 분기 및 릴리스 흐름을 중심으로 하는 견고한 DevOps 프로세스를 사용하여 모든 Microsoft 제품을 빌드하고 배포하려고 합니다. 이 문서에서는 실제 구현, 시스템이 소규모 서비스에서 대규모 플랫폼 개발 요구 사항으로 확장되는 방식 및 다양한 Microsoft 팀에서 시스템을 사용하여 배운 교훈을 강조합니다.

표준화된 개발 프로세스를 채택하는 것은 야심찬 작업입니다. Microsoft 조직의 요구 사항은 매우 다양하며 조직 내의 다양한 팀의 요구 사항은 규모와 복잡성으로 확장됩니다. 이러한 다양한 요구를 해결하기 위해 Microsoft는 트렁크 기반 분기 전략을 사용하여 제품을 신속하게 개발하고, 정기적으로 배포하고, 프로덕션 환경에 안전하게 변경 내용을 제공할 수 있습니다.

또한 Microsoft는 One Engineering System의 일부로 플랫폼 엔지니어링 원칙을 사용합니다.

Microsoft 릴리스 흐름

모든 조직은 팀 간에 일관성을 보장하기 위해 표준 코드 릴리스 프로세스를 해결해야 합니다. Microsoft 릴리스 흐름은 개발에서 릴리스까지 DevOps 프로세스를 통합합니다. 릴리스 흐름의 기본 단계는 분기, 푸시, 끌어오기 요청 및 병합으로 구성됩니다.

지점

버그를 수정하거나 기능을 구현하기 위해 개발자는 주 통합 분기에서 새 분기를 만듭니다. Git 경량 분기 모델은 모든 코드 기여에 대해 이러한 수명이 짧은 토픽 분기를 만듭니다. 개발자는 기능 플래그를 사용하여 조기에 커밋하고 장기 실행 기능 분기를 방지합니다.

푸시

개발자가 팀의 나머지 부분에 변경 내용을 통합하고 제공할 준비가 되면 로컬 분기를 서버의 분기에 푸시하고 끌어오기 요청을 엽니다. 여러 분기에서 작업하는 수백 명의 개발자가 있는 리포지토리는 서버 분기에 대한 명명 규칙을 사용하여 혼란과 분기 확산을 완화합니다. 개발자는 일반적으로 자신의 계정 이름으로 명명된 users/<username>/feature 분기를 만듭니다.

끌어오기 요청

끌어오기 요청은 주 분기에 항목 분기 병합을 제어하고 분기 정책이 충족되는지 확인합니다. 끌어오기 요청 프로세스는 제안된 변경 내용을 빌드하고 빠른 테스트 패스를 실행합니다. 첫 번째 및 두 번째 수준 테스트 도구 모음은 5분 이내에 약 60,000개의 테스트를 실행합니다. 전체 Microsoft 테스트 매트릭스는 아니지만 끌어오기 요청에 대한 신뢰를 빠르게 제공하기에 충분합니다.

다음으로, 팀의 다른 구성원이 코드를 검토하고 변경 내용을 승인합니다. 코드 검토는 자동화된 테스트가 중단된 위치를 선택하며 아키텍처 문제를 발견하는 데 특히 유용합니다. 수동 코드 검토를 통해 팀의 다른 엔지니어가 변경 내용을 볼 수 있고 코드 품질이 높게 유지됩니다.

Merge

끌어오기 요청이 모든 빌드 정책을 충족하고 검토자가 로그오프하면 토픽 분기가 주 통합 분기에 병합되고 끌어오기 요청이 완료됩니다.

병합 후 완료하는 데 더 많은 시간이 걸리는 다른 승인 테스트가 실행됩니다. 이러한 기존의 검사 후 테스트는 보다 철저한 유효성 검사를 수행합니다. 이 테스트 프로세스는 끌어오기 요청 검토 중에 빠른 테스트를 수행하는 것과 릴리스 전에 전체 테스트 검사를 수행하는 것 사이의 균형을 잘 제공합니다.

GitHub Flow와의 차이점

GitHub Flow는 조직이 Git 에 확장 가능한 접근 방식을 구현하는 데 널리 사용되는 트렁크 기반 개발 릴리스 흐름입니다. 그러나 일부 조직에서는 요구 사항이 증가함에 따라 GitHub Flow의 일부에서 분리해야 한다는 것을 알게 됩니다.

예를 들어, GitHub Flow에서 종종 간과되는 부분은 끌어오기 요청이 메인 분기에 병합되기 전에 프로덕션 환경에서 테스트를 위해 배포되어야 한다는 것입니다. 이 프로세스는 모든 끌어오기 요청이 병합을 위해 배포 큐에서 대기한다는 것을 의미합니다.

일부 팀에는 단일 리포지토리에서 지속적으로 작업하는 수백 명의 개발자가 있으며, 하루에 200개가 넘는 끌어오기 요청을 주 브랜치로 완료할 수 있습니다. 각 끌어오기 요청에 테스트를 위해 전 세계 여러 Azure 데이터 센터에 배포해야 하는 경우 개발자는 소프트웨어를 작성하는 대신 분기가 병합될 때까지 기다리는 데 시간을 할애합니다.

대신 Microsoft 팀은 주 분기에서 계속 개발하고 배포를 시간 제한 릴리스로 일괄 처리하며, 일반적으로 3주 스프린트 주기에 맞춥니다.

구현 세부 정보

다음은 Microsoft 릴리스 흐름의 몇 가지 주요 구현 세부 정보입니다.

Git 리포지토리 전략

팀별로 Git 리포지토리를 관리하기 위한 전략이 다릅니다. 일부 팀은 대부분의 코드를 하나의 Git 리포지토리에 유지합니다. 코드는 각각 자체 루트 수준 폴더에 있는 구성 요소로 나뉩니다. 큰 구성 요소, 특히 이전 구성 요소에는 부모 구성 요소 내에 별도의 하위 폴더가 있는 여러 하위 구성 요소가 있을 수 있습니다.

Git 리포지토리 구조를 보여 주는 스크린샷

보조 리포지토리

일부 팀은 부속 리포지토리도 관리합니다. 예를 들어 빌드 및 릴리스 에이전트 및작업, VS Code 확장오픈 소스 프로젝트는 GitHub에서 개발됩니다. 구성 변경 내용은 별도의 리포지토리로 체크 인됩니다. 팀이 의존하는 다른 패키지는 다른 위치에서 제공되며 NuGet을 통해 소비됩니다.

모노 레포 또는 다중 레포

일부 팀은 단일 모놀리식 리포지토리, 모노 리포지토리를 선택하지만 다른 Microsoft 제품은 다중 리포지토리 접근 방식을 사용합니다. 예를 들어 Skype에는 다양한 클라이언트, 서비스 및 도구를 만들기 위해 다양한 조합으로 연결하는 수백 개의 작은 리포지토리가 있습니다. 특히 마이크로 서비스를 수용하는 팀의 경우 다중 리포지토리가 올바른 접근 방식일 수 있습니다. 일반적으로 모놀리식 구조에서 시작된 이전 제품은 Git으로 가장 쉽게 전환할 수 있는 방법으로 모노리포 접근 방식을 발견하며, 코드 조직은 이를 잘 반영합니다.

릴리스 브랜치

Microsoft 릴리스 흐름은 메인 브랜치를 언제나 빌드 가능 상태로 유지합니다. 개발자는 수명이 짧은 토픽 분기에서 작업하며, 이를 main에 병합합니다. 팀이 스프린트 종료 시 또는 주요 업데이트를 위해 준비가 되면, 메인 브랜치에서 새 릴리스 브랜치를 시작합니다. 릴리스 분기는 주 분기로 다시 병합되지 않으므로 중요한 변경 사항을 체리 피킹해야 할 수 있습니다.

다음 다이어그램에서는 단명 분기를 파란색으로, 출시 분기를 검은색으로 표시합니다. 체리 따기가 필요한 커밋이 있는 한 분기가 빨간색으로 나타납니다.

Git 릴리스 분기 구조를 보여 주는 다이어그램

브랜치 정책 및 권한

Git 분기 정책은 릴리스 분기 구조를 강화하고 메인 분기를 정리하는 데 도움이 됩니다. 예를 들어 브랜치 정책은 메인 브랜치에 대한 직접 푸시를 방지할 수 있습니다.

분기 계층 구조를 깔끔하게 유지하기 위해 팀은 권한을 사용하여 계층의 루트 수준에서 분기 만들기를 차단합니다. 다음 예제에서는 모든 사용자가 사용자/, 기능/및 teams/와 같은 폴더에 분기를 만들 수 있습니다. 릴리스 관리자만 릴리스/에서 분기를 만들 수 있는 권한이 있으며 일부 자동화 도구에는 통합/ 폴더에 대한 권한이 있습니다.

분기를 보여 주는 스크린샷

Git 리포지토리 워크플로

리포지토리 및 분기 구조 내에서 개발자는 일상적인 작업을 수행합니다. 작업 환경은 팀 및 개인별로 크게 다릅니다. 일부 개발자는 명령줄을 선호하고 Visual Studio와 같은 개발자는 다른 플랫폼에서 작업합니다. Microsoft 리포지토리에 있는 구조와 정책은 견고하고 일관된 기반을 보장합니다.

일반적인 워크플로에는 다음과 같은 일반적인 작업이 포함됩니다.

새 기능 빌드

새로운 기능을 구축하는 것은 소프트웨어 개발자의 작업의 핵심입니다. 프로세스의 비 Git 부분에는 원격 분석 데이터 보기, 디자인 및 사양 작성 및 실제 코드 작성이 포함됩니다. 그런 다음, 개발자는 main의 최신 커밋으로 동기화하여 리포지토리 작업을 시작합니다. 메인 브랜치는 항상 빌드 가능하므로, 좋은 출발점이 됩니다. 개발자는 새 기능 분기를 체크 아웃하고, 코드를 변경하고, 커밋하고, 서버에 푸시하고, 새 끌어오기 요청을 시작합니다.

브랜치 정책 및 확인 사용

끌어오기 요청을 만들 때 자동화된 시스템은 새 코드가 빌드되고, 중단되지 않으며, 보안 또는 규정 준수 정책을 위반하지 않는지 확인합니다. 이 프로세스는 다른 작업이 병렬로 수행되는 것을 차단하지 않습니다.

분기 정책 및 검사는 통과된 테스트, 터치된 코드 소유자의 사인오프 및 끌어오기 요청을 완료하기 전에 회사 정책을 확인하기 위한 몇 가지 외부 검사를 포함하여 성공적인 빌드가 필요할 수 있습니다.

끌어오기 요청에 대한 검사를 보여 주는 스크린샷

Microsoft Teams와 통합

많은 팀이 Microsoft Teams와의 통합을 구성하여 개발자의 팀 동료에게 새 끌어오기 요청을 발표합니다. 터치된 코드의 소유자는 검토자로 자동으로 추가됩니다. Microsoft 팀은 종종 REST 클라이언트 생성 및 공유 컨트롤과 같이 많은 사람들이 터치하는 코드에 대해 선택적 검토자를 사용하여 이러한 변경 내용을 전문가에게 확인합니다.

Teams 통합을 보여 주는 스크린샷

끌어오기 요청의 Teams 알림을 보여 주는 스크린샷

기능 플래그를 사용하여 배포

검토자, 코드 소유자 및 자동화가 충족되면 개발자는 끌어오기 요청을 완료할 수 있습니다. 병합 충돌이 있는 경우 개발자는 충돌과 동기화하고 수정한 후 변경 내용을 다시 푸시하는 방법에 대한 지침을 받습니다. 자동화는 고정 코드에서 다시 실행되지만 인간은 다시 로그오프할 필요가 없습니다.

브랜치가 main으로 병합되고 새 코드는 다음 스프린트 또는 대규모 릴리스에 배포됩니다. 그렇다고 해서 새 기능이 바로 표시되는 것은 아닙니다. Microsoft는 기능 플래그를 사용하여 새 기능의 배포 및 노출을 분리합니다.

기능이 과시할 준비가 되기 전에 조금 더 작업이 필요하더라도, 제품이 빌드되고 배포된다면 main로 안전하게 이동할 수 있습니다. main일단 로그인하면 코드는 공식 빌드의 일부가 되며, 여기서 다시 테스트되고, 정책을 충족하도록 확인되고, 디지털 서명됩니다.

문제를 조기에 감지하려면 왼쪽으로 이동

이 Git 워크플로는 몇 가지 이점을 제공합니다. 첫째, 단일 메인 브랜치에서 작업하면 병합 부채가 사실상 제거됩니다. 둘째, 끌어오기 요청 흐름은 파이프라인 초기에 테스트, 코드 검토 및 오류 검색을 적용하는 공통점을 제공합니다. 이러한 왼쪽 전환 전략은 몇 시간 또는 며칠이 아닌 몇 분 안에 오류를 감지할 수 있으므로 개발자에게 피드백 주기를 단축하는 데 도움이 됩니다. 이 전략은 모든 변경 내용이 지속적으로 테스트되기 때문에 리팩터링에 대한 신뢰도를 제공합니다.

현재 끌어오기 요청이 200개 이상인 제품은 하루에 300개 이상의 연속 통합 빌드를 생성할 수 있으며, 24시간마다 500개 이상의 테스트가 실행됩니다. 트렁크 기반 분기 및 릴리스 워크플로가 없으면 이 수준의 테스트가 불가능합니다.

스프린트 마일스톤에서 릴리스

각 스프린트의 끝에 팀은 메인 브랜치에서 릴리스 브랜치를 만듭니다. 예를 들어 스프린트 129의 끝에서 팀은 새 릴리스 분기 releases/M129를 만듭니다. 그런 다음, 팀은 스프린트 129 브랜치를 프로덕션에 배포합니다.

릴리스 브랜치가 생성된 후에는 개발자가 변경 내용을 병합할 수 있도록 메인 브랜치가 열려 있습니다. 이러한 변경 내용은 다음 스프린트 배포에서 3주 후에 배포됩니다.

스프린트 129의 릴리스 분기 다이어그램.

핫픽스 해제

경우에 따라 변경 내용을 신속하게 프로덕션으로 이동해야 합니다. Microsoft는 일반적으로 스프린트 중간에 새 기능을 추가하지 않지만, 경우에 따라 버그 수정을 신속하게 가져와 사용자의 차단을 해제하려고 합니다. 문제는 오타와 같은 사소한 문제이거나 가용성 문제 또는 라이브 사이트 인시던트를 일으킬 만큼 충분히 클 수 있습니다.

이러한 문제를 수정하는 것은 일반적인 워크플로에서 시작됩니다. 개발자는 main에서 분기(branch)를 생성하고, 코드 검토를 받으며, 풀 리퀘스트를 완료하여 병합합니다. 프로세스는 항상 main 에서 먼저 변경하는 것으로 시작됩니다. 이렇게 하면 릴리스 분기로 전환하지 않고도 수정 사항을 신속하게 만들고 로컬에서 유효성을 검사할 수 있습니다.

이 과정을 따르면 변경 사항이 main에 포함되는 것이 보장되며, 이는 매우 중요합니다. 릴리스 브랜치에서 버그를 수정한 후 변경 사항을 main에 다시 반영하지 않으면, 스프린트 130 릴리스가 main에서 분기할 때 bug가 다음 배포 중에 다시 발생하게 됩니다. 중단 중에 발생할 수 있는 혼란과 스트레스 중에 업데이트 main 하는 것을 잊기 쉽습니다. 먼저 변경 내용을 main 가져오는 것은 항상 주 분기와 릴리스 분기 모두에서 변경 내용을 갖는 것을 의미합니다.

Git 기능을 사용하면 이 워크플로를 사용할 수 있습니다. 개발자가 끌어오기 요청을 병합하면 즉시 변경 내용을 프로덕션으로 main가져오려면 끌어오기 요청 페이지를 사용하여 릴리스 분기에 변경 내용을 체리 선택할 수 있습니다. 이 프로세스는 릴리스 분기를 대상으로 하는 새 끌어오기 요청을 만들어 방금 병합된 main콘텐츠를 백포팅합니다.

핫픽스 커밋을 브랜치 129로 체리 픽한 그림.

체리픽 기능을 사용하면 끌어오기 요청을 빠르게 열 수 있으며 브랜치 정책의 추적 가능성과 신뢰성을 제공합니다. 체리 피킹은 릴리스 브랜치를 로컬 컴퓨터에 다운로드하지 않고 서버에서 수행할 수 있습니다. 변경, 병합 충돌 수정, 또는 두 분기 간의 차이로 인한 사소한 변경은 모두 서버에서 처리될 수 있습니다. Teams는 브라우저 기반 텍스트 편집기나 Pull Request 병합 충돌 확장 프로그램을 통해 변경 사항을 직접 편집할 수 있어 더욱 고급스러운 사용 환경을 제공합니다.

끌어오기 요청이 릴리스 분기를 대상으로 지정되면, 팀이 코드를 다시 검토하고, 분기 정책을 평가하며, 끌어오기 요청을 테스트한 후 병합합니다. 병합 후 수정 사항은 몇 분 안에 서버의 첫 번째 에 배포됩니다. 여기에서 팀은 배포 링을 사용하여 더 많은 계정에 수정 사항을 점진적으로 배포합니다. 변경 내용이 더 많은 사용자에게 배포됨에 따라 팀은 성공을 모니터링하고 결함이나 속도 저하를 도입하지 않으면서 변경 내용이 버그를 수정했는지 확인합니다. 이 수정 사항은 결국 모든 Azure 데이터 센터에 배포됩니다.

다음 스프린트로 이동

향후 3주 동안 팀은 스프린트 130에 기능 추가를 완료하고 이러한 변경 내용을 배포할 준비가 됩니다. 새 릴리스 분기 releases/M130main 에서 생성하고 해당 분기를 배포합니다.

실제로 현재 프로덕션 환경에는 두 개의 브랜치가 있습니다. 링 기반 배포 를 통해 프로덕션에 대한 변경 내용을 안전하게 가져오면 빠른 링이 스프린트 130 변경 내용을 가져오고, 느린 링 서버는 스프린트 129에 유지되고 새로운 변경 내용은 프로덕션에서 유효성을 검사합니다.

배포 중간에 변경 내용의 핫픽스를 지정하려면 스프린트 129 릴리스와 스프린트 130 릴리스의 두 가지 릴리스를 핫픽싱해야 할 수 있습니다. 팀은 핫픽스를 두 릴리스 브랜치에 이식하고 배포합니다. 130개 브랜치는 핫픽스를 사용하여 이미 업그레이드된 링에 재배포합니다. 129개 분기는 핫픽스를 사용하여 다음 스프린트 버전으로 아직 업그레이드되지 않은 외부 링에 다시 배포합니다.

모든 링이 배포되면 핫픽스의 변경 사항이 main에 반영되었기 때문에 이전 스프린트 129 분기는 중단됩니다. 따라서 이러한 변경 사항은 releases/M130 분기에도 적용됩니다.

스프린트 130의 릴리스 분기 그림.

요약

릴리스 흐름 모델은 Microsoft가 DevOps를 사용하여 개발하여 온라인 서비스를 제공하는 방법의 핵심입니다. 이 모델은 간단한 트렁크 기반 분기 전략을 사용합니다. 그러나 개발자가 배포 큐에 갇히지 않고 변경 내용 병합을 기다리는 대신 Microsoft 릴리스 흐름을 통해 개발자가 계속 작업할 수 있습니다.

또한 이 릴리스 모델을 사용하면 Microsoft 코드베이스의 크기와 작업 중인 개발자 수에도 불구하고 Azure 데이터 센터에 새로운 기능을 정기적으로 배포할 수 있습니다. 또한 이 모델을 사용하면 핫픽스를 빠르고 효율적으로 프로덕션에 적용할 수 있습니다.