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

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

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

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

Microsoft 릴리스 흐름

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

Branch

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

Push

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

끌어오기 요청

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

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

병합

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

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

GitHub Flow와의 차이점

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

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

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

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

구현 세부 정보

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

Git 리포지토리 전략

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

Screenshot showing a Git repository structure.

보조 리포지토리

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

Mono 리포지토리 또는 다중 리포지토리

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

릴리스 분기

Microsoft 릴리스 흐름은 기본 분기를 항상 빌드할 수 있게 유지합니다. 개발자는 병합되는 수명이 짧은 토픽 분기에서 작업합니다 main. 팀이 스프린트 종료 시 또는 주요 업데이트를 위해 배송할 준비가 되면 기본 분기에서 새 릴리스 분기를 시작합니다. 릴리스 분기는 기본 분기에 다시 병합되지 않으므로 중요한 변경 사항을 체리 따기해야 할 수 있습니다.

다음 다이어그램에서는 단명 분기를 파란색으로 표시하고 분기를 검은색으로 해제하는 방법을 보여 줍니다. 체리 따기가 필요한 커밋이 있는 한 분기가 빨간색으로 나타납니다.

Diagram showing Git release branch structure.

분기 정책 및 권한

Git 분기 정책은 릴리스 분기 구조를 적용하고 기본 분기 클린 유지하는 데 도움이 됩니다. 예를 들어 분기 정책은 기본 분기에 대한 직접 푸시를 방지할 수 있습니다.

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

Screenshot that shows branches.

Git 리포지토리 워크플로

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

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

새 기능 빌드

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

분기 정책 및 검사 사용

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

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

Screenshot showing the checks on a pull request.

Microsoft Teams와 통합

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

Screenshot showing Teams integration.

Screenshot showing Teams notification of a pull request.

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

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

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

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

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

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

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

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

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

릴리스 분기의 분기 후에는 개발자가 변경 내용을 병합할 수 있도록 기본 분기가 다시 열립니다기본. 이러한 변경 내용은 다음 스프린트 배포에서 3주 후에 배포됩니다.

Illustration of the release branch at sprint 129.

핫픽스 해제

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

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

또한 이 프로세스를 수행하면 변경 내용이 매우 중요합니다 main. 변경 사항을 다시 가져오지 않고 릴리스 분기의 버그를 main 수정하면 스프린트 130이 분기 main될 때 다음 배포 중에 버그가 다시 발생합니다. 중단 중에 발생할 수 있는 혼란과 스트레스 중에 업데이트 main 하는 것을 잊기 쉽습니다. 먼저 변경 내용을 main 가져오는 것은 항상 기본 분기와 릴리스 분기 모두에서 변경 내용을 갖는 것을 의미합니다.

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

Illustration of cherry-picking a hotfix commit into branch 129.

체리 선택 기능을 사용하면 끌어오기 요청이 빠르게 열리며 분기 정책의 추적 가능성과 안정성을 제공합니다. 체리 피킹은 로컬 컴퓨터에 릴리스 분기를 다운로드하지 않고도 서버에서 발생할 수 있습니다. 변경, 병합 충돌 수정 또는 두 분기 간의 차이로 인해 사소한 변경은 모두 서버에서 발생할 수 있습니다. Teams는 브라우저 기반 텍스트 편집기에서 직접 또는 끌어오기 요청 병합 충돌 확장을 통해 변경 내용을 편집하여 고급 환경을 제공할 수 있습니다.

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

다음 스프린트로 이동

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

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

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

모든 링이 배포되면 핫픽스로 스프린트 129 분기로 변경된 내용이 있으므로 이전 스프린트 129 분기가 중단됩니다 main. 따라서 이러한 변경 내용도 분기에 있습니다 releases/M130 .

Illustration of a release branch at sprint 130.

요약

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

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