DevOps

이 콘텐츠는 Azure용 클라우드 네이티브 .NET 애플리케이션 설계 eBook 에서 발췌한 것으로, .NET 문서에서 제공되거나 오프라인 상태에서도 읽을 수 있는 PDF(무료 다운로드 가능)로 제공됩니다.

Cloud Native .NET apps for Azure eBook cover thumbnail.

소프트웨어 컨설턴트가 가장 좋아하는 만트라는 제기된 모든 질문에 “상황에 따라 다르다”라고 대답하는 것입니다. 이는 소프트웨어 컨설턴트가 자리를 차지하지 않는 것을 좋아하기 때문이 아닙니다. 소프트웨어의 모든 질문에 대한 정답은 없기 때문입니다. 절대적인 옳고 그름은 없으며, 오히려 반대의 균형이 있습니다.

예를 들어 웹 애플리케이션을 개발하는 두 가지 주요 학파인 SPA(단일 페이지 애플리케이션)와 서버 쪽 애플리케이션을 살펴보겠습니다. 한편, 사용자 환경은 SPA를 사용하는 것이 더 나은 경향이 있으며 웹 서버에 대한 트래픽 양을 최소화하여 정적 호스팅처럼 간단한 것으로 호스트할 수 있습니다. 반면, SPA는 개발 속도가 느리고 테스트하기가 더 어려운 경향이 있습니다. 어느 것이 올바른 선택일까요? 글쎄요, 그것은 당신의 상황에 따라 달라집니다.

클라우드 네이티브 애플리케이션은 동일한 이분법의 영향을 받지 않습니다. 개발 속도, 안정성, 스케일링 성능 측면에서 명확한 이점이 있지만 관리하기가 훨씬 더 어려울 수 있습니다.

몇 년 전만 해도 개발에서 프로덕션으로 애플리케이션을 이동하는 프로세스가 한 달 이상 걸리는 것은 드문 일이 아니었습니다. 회사는 6개월 또는 매년 주기로 소프트웨어를 출시했습니다. Windows 10이 사시장청하던 시대 이전에 수용 가능한 릴리스의 주기에 대한 아이디어를 얻으려면 Microsoft Windows보다 더 볼 필요가 없습니다. Windows XP와 Vista 사이에는 5년이 흘렀고, Vista와 Windows 7 사이에는 3년이 더 흘렀습니다.

소프트웨어를 빠르게 출시할 수 있다는 것은 빠르게 변화하는 회사에 게으름을 피우는 경쟁자보다 큰 시장 이점을 제공한다는 사실이 이제 상당히 확립되었습니다. 이러한 이유로 Windows 10의 주요 업데이트는 이제 약 6개월마다 이루어집니다.

더 빠르고 신뢰할 수 있는 릴리스를 통해 비즈니스에 가치를 제공할 수 있는 패턴과 사례를 DevOps라고 합니다. 이는 애플리케이션 지정부터 해당 애플리케이션 제공 및 운영까지 전체 소프트웨어 개발 수명 주기에 걸쳐 다양한 아이디어로 구성됩니다.

DevOps는 마이크로 서비스 이전에 등장했으며, DevOps가 프로덕션에서 하나뿐 아니라 많은 애플리케이션을 더 쉽게 릴리스하고 작동할 수 있도록 하기 위해 더 작고 목적에 더 적합한 서비스로의 이동은 불가능했을 것입니다.

Figure 10-1 Search trends show that the growth in microservices doesn't start until after DevOps is a fairly well-established idea.

그림 10-1 - DevOps 및 마이크로 서비스.

좋은 DevOps 사례를 통해 실제로 애플리케이션을 운영하는 산더미 같은 작업에 질식하지 않고 클라우드 네이티브 애플리케이션의 이점을 실현할 수 있습니다.

DevOps와 관련하여 황금 망치는 없습니다. 고품질 애플리케이션을 릴리스하고 운영하기 위한 완전하고 포괄적인 솔루션을 판매할 수 있는 사람은 아무도 없습니다. 이는 각 애플리케이션이 다른 모든 애플리케이션과 크게 다르기 때문입니다. 그러나 DevOps를 훨씬 덜 어려운 제안으로 만들 수 있는 도구가 있습니다. 이러한 도구 중 하나를 Azure DevOps라고 합니다.

Azure DevOps

Azure DevOps에는 긴 혈통이 있습니다. Team Foundation Server가 처음 온라인으로 이동한 시점과 다양한 이름 변경(Visual Studio Online 및 Visual Studio Team Services)을 통해 그 뿌리를 추적할 수 있습니다. 그러나 세월이 흐르면서 전임자보다 훨씬 더 많아졌습니다.

Azure DevOps는 다섯 가지 주요 구성 요소로 나뉩니다.

Figure 10-2 The five major areas of Azure DevOps

그림 10-2 - Azure DevOps.

Azure Repos - 유서 깊은 TFVC(Team Foundation 버전 제어)와 업계에서 가장 선호하는 Git을 지원하는 소스 코드 관리입니다. 끌어오기 요청은 변경 내용에 대한 논의를 촉진하여 소셜 코딩을 가능하게 하는 방법을 제공합니다.

Azure Boards - 사용자가 가장 적합한 워크플로를 선택할 수 있도록 하는 문제 및 작업 항목 추적 도구를 제공합니다. 이는 SCRUM 및 Kanban 스타일의 개발을 지원하는 템플릿을 포함하여 미리 구성된 여러 템플릿이 함께 제공됩니다.

Azure Pipelines - Azure와의 긴밀한 통합을 지원하는 빌드 및 릴리스 관리 시스템입니다. 빌드는 Windows에서 Linux, macOS에 이르는 다양한 플랫폼에서 실행할 수 있습니다. 빌드 에이전트는 클라우드 또는 온-프레미스에서 프로비저닝될 수 있습니다.

Azure Test Plans - 테스트 계획 기능이 제공하는 테스트 관리 및 예비 테스트 지원을 통해 QA 담당자가 남지 않습니다.

Azure Artifacts - 회사에서 자체 내부 버전의 NuGet, npm 등을 만들 수 있는 아티팩트 피드입니다. 중앙 집중식 리포지토리에 오류가 있는 경우 업스트림 패키지의 캐시 역할을 하는 이중 용도로 사용됩니다.

Azure DevOps의 최상위 조직 구성 단위를 프로젝트라고 합니다. 각 프로젝트 내에서 Azure Artifacts와 같은 다양한 구성 요소를 켜고 끌 수 있습니다. 이러한 각 구성 요소는 클라우드 네이티브 애플리케이션에 대해 서로 다른 이점을 제공합니다. 가장 유용한 세 가지는 리포지토리, 보드, 파이프라인입니다. 사용자가 GitHub와 같은 다른 리포지토리 스택에서 소스 코드를 관리하지만 여전히 Azure Pipelines 및 기타 구성 요소를 활용하려는 경우 완벽하게 가능합니다.

다행히 개발 팀에는 리포지토리를 선택할 때 많은 옵션이 있습니다. 그 중 하나는 GitHub입니다.

GitHub Actions

2009년에 설립된 GitHub는 호스팅 프로젝트, 설명서, 코드를 위한 널리 사용되는 웹 기반 리포지토리입니다. Apple, Amazon, Google 및 주류 기업과 같은 많은 대형 기술 회사에서 GitHub를 사용합니다. GitHub는 Git이라는 오픈 소스 분산 버전 제어 시스템을 기본으로 사용합니다. 그런 다음, 결함 추적, 기능 및 끌어오기 요청, 작업 관리, 각 코드 베이스에 대한 wiki를 비롯한 고유한 기능 집합을 추가합니다.

GitHub가 발전함에 따라 DevOps 기능도 추가되고 있습니다. 예를 들어 GitHub에는 GitHub Actions라는 자체 CI/CD(연속 통합/지속적인 업데이트) 파이프라인이 있습니다. GitHub Actions는 커뮤니티 기반 워크플로 자동화 도구입니다. 이를 통해 DevOps 팀은 기존 도구와 통합하고, 새 제품을 혼합 및 일치시키고, 기존 CI/CD 파트너를 비롯한 소프트웨어 수명 주기에 연결할 수 있습니다.”

GitHub에는 4,000만 명 이상의 사용자가 있어 세계에서 가장 큰 소스 코드 호스트입니다. 2018년 10월에 Microsoft는 GitHub를 구입했습니다. Microsoft는 모든 개발자가 연결하고 확장할 수 있는 개방형 플랫폼으로 GitHub를 유지하겠다고 약속했습니다. 이는 독립적인 회사로 계속 운영됩니다. GitHub는 엔터프라이즈, 팀, 전문가, 무료 계정에 대한 계획을 제공합니다.

소스 컨트롤

클라우드 네이티브 애플리케이션에 대한 코드를 구성하는 것은 어려울 수 있습니다. 단일 거대한 애플리케이션 대신 클라우드 네이티브 애플리케이션은 서로 통신하는 작은 애플리케이션의 웹으로 구성되는 경향이 있습니다. 컴퓨팅의 모든 항목과 마찬가지로 최상의 코드 배열은 여전히 ​​미해결 문제입니다. 다양한 종류의 레이아웃을 사용하는 성공적인 애플리케이션의 예가 있지만 두 가지 변형이 가장 많이 사용되는 것 같습니다.

실제 소스 제어 자체로 들어가기 전에 몇 개의 프로젝트가 적절한지 결정하는 것이 좋습니다. 단일 프로젝트 내에는 여러 리포지토리에 대한 지원과 빌드 파이프라인이 있습니다. 보드는 좀 더 복잡하지만, 단일 프로젝트 내에서 작업을 여러 팀에 쉽게 할당할 수 있습니다. 단일 Azure DevOps 프로젝트에서 수백, 심지어 수천 명의 개발자를 지원할 수 있습니다. 이렇게 하면 모든 개발자가 작업할 수 있는 단일 위치를 제공하고 개발자가 어느 프로젝트가 있는지 확실하지 않은 경우 하나의 애플리케이션을 찾는 혼동을 줄일 수 있으므로 가장 좋은 방법이 될 수 있습니다.

Azure DevOps 프로젝트 내에서 마이크로 서비스에 대한 코드를 분할하는 것이 약간 더 어려울 수 있습니다.

Figure 10-3 Single versus Multiple Repositories

그림 10-3 - 하나의 리포지토리와 많은 리포지토리.

마이크로 서비스당 리포지토리

언뜻 보기에 이 방법은 마이크로 서비스에 대한 소스 코드를 분할하는 가장 논리적인 방법처럼 보입니다. 각 리포지토리에는 하나의 마이크로 서비스를 빌드하는 데 필요한 코드가 포함될 수 있습니다. 이 방법의 장점은 쉽게 볼 수 있습니다.

  1. 애플리케이션을 빌드하고 유지 관리하기 위한 지침은 각 리포지토리의 루트에 있는 추가 정보 파일에 추가할 수 있습니다. 리포지토리를 뒤집을 때 이러한 지침을 쉽게 찾을 수 있으므로 개발자의 스핀업 시간이 줄어듭니다.
  2. 모든 서비스는 서비스의 이름을 알고 쉽게 찾을 수 있는 논리적 위치에 있습니다.
  3. 빌드는 소유 리포지토리를 변경할 때만 트리거되도록 쉽게 설정할 수 있습니다.
  4. 리포지토리로 들어오는 변경 횟수는 프로젝트에서 작업하는 소수의 개발자로 제한됩니다.
  5. 개발자에게 읽기 및 쓰기 권한이 있는 리포지토리를 제한하여 보안을 쉽게 설정할 수 있습니다.
  6. 리포지토리 수준 설정은 소유 팀에서 다른 사용자와 최소한의 논의를 통해 변경할 수 있습니다.

마이크로 서비스의 핵심 아이디어 중 하나는 서비스를 사일로화하고 서로 분리해야 한다는 것입니다. 도메인 기반 디자인을 사용하여 서비스의 경계를 결정할 때 서비스는 트랜잭션 경계 역할을 합니다. 데이터베이스 업데이트는 여러 서비스에 걸쳐서는 안 됩니다. 이 관련 데이터 컬렉션을 제한된 컨텍스트라고 합니다. 이 아이디어는 마이크로 서비스 데이터를 다른 서비스와 분리되고 자율적인 데이터베이스로 격리하여 반영됩니다. 소스 코드까지 이 아이디어를 전달하는 것이 좋습니다.

그러나 이 방법에 문제가 없는 것은 아닙니다. 우리 시대의 더 끔찍한 개발 문제 중 하나는 종속성을 관리하는 것입니다. 평균 node_modules 디렉터리를 구성하는 파일 수를 고려합니다. create-react-app과 같은 항목을 새로 설치하면 수천 개의 패키지가 함께 제공될 수 있습니다. 이러한 종속성을 관리하는 방법에 대한 질문은 어렵습니다.

종속성이 업데이트되면 다운스트림 패키지도 이 종속성을 업데이트해야 합니다. 아쉽게도 개발 작업이 필요하므로 node_modules 디렉터리가 단일 패키지의 여러 버전으로 끝나고 각각은 약간 다른 흐름으로 버전이 지정된 다른 패키지의 종속성으로 끝납니다. 애플리케이션을 배포할 때 어떤 버전의 종속성을 사용해야 하나요? 현재 프로덕션 중인 버전인가요? 현재 베타 버전이지만 소비자가 프로덕션으로 만들 때까지 프로덕션 중일 가능성이 높은 버전은 무엇인가요? 마이크로 서비스만 사용하여 해결되지 않는 어려운 문제입니다.

다양한 프로젝트에 따라 달라지는 라이브러리가 있습니다. 마이크로 서비스를 각 리포지토리에 하나씩 분할하면 내부 리포지토리인 Azure Artifacts를 사용하여 내부 종속성을 가장 잘 해결할 수 있습니다. 라이브러리용 빌드는 내부 사용을 위해 최신 버전을 Azure Artifacts로 푸시합니다. 새로 업데이트된 패키지에 종속되려면 다운스트림 프로젝트를 수동으로 업데이트해야 합니다.

서비스 간에 코드를 이동할 때 또 다른 단점이 있습니다. 애플리케이션을 마이크로 서비스로 나누는 첫 번째 분할이 100% 정확하다고 믿는 것이 좋겠지만, 현실은 우리가 서비스 부문에서 실수를 하지 않을 만큼 선견지명이 거의 없다는 것입니다. 따라서 이를 구동하는 기능과 코드는 서비스에서 서비스로, 리포지토리에서 리포지토리로 이동해야 합니다. 한 리포지토리에서 다른 리포지토리로 도약하면 코드의 기록이 손실됩니다. 특히 감사의 경우 코드 조각에 대한 전체 기록을 보유하는 것이 매우 중요한 경우가 많습니다.

최종적이고 가장 중요한 단점은 변화를 조정하는 것입니다. 실제 마이크로 서비스 애플리케이션에서는 서비스 간에 배포 종속성이 없어야 합니다. 서비스 A, B, C는 느슨한 결합이 있으므로 어떤 순서로든 배포할 수 있어야 합니다. 그러나 실제로는 여러 리포지토리를 동시에 교차하는 변경을 하는 것이 바람직한 경우가 있습니다. 몇 가지 예로는 보안 허점을 막기 위해 라이브러리를 업데이트하거나 모든 서비스에서 사용하는 통신 프로토콜을 변경하는 것이 포함됩니다.

리포지토리 간 변경을 수행하려면 각 리포지토리에 대한 커밋을 연속해서 수행해야 합니다. 각 리포지토리의 각 변경 내용은 끌어오기 요청을 받고 별도로 검토해야 합니다. 이 작업은 조정하기 어려울 수 있습니다.

많은 리포지토리를 사용하는 대안은 모든 소스 코드를 거대한 단일 리포지토리에 함께 배치하는 것입니다.

단일 리포지토리

모노리포지토리라고도 하는 이 방법에서는 모든 서비스에 대한 모든 소스 코드가 동일한 리포지토리에 배치됩니다. 처음에는 이 방법이 소스 코드를 다루기 어렵게 만드는 끔찍한 아이디어처럼 보입니다. 그러나 이러한 방식으로 작업할 때 몇 가지 현저한 이점이 있습니다.

첫 번째 장점은 프로젝트 간의 종속성을 보다 쉽게 관리할 수 있다는 것입니다. 프로젝트는 일부 외부 아티팩트 피드를 사용하는 대신 서로 직접 가져올 수 있습니다. 즉, 업데이트가 즉각적이고 충돌하는 버전은 개발자의 워크스테이션에서 컴파일 시간에 찾을 수 있습니다. 실제로 일부 통합 테스트는 왼쪽으로 이동합니다.

프로젝트 간에 코드를 이동할 때 파일이 다시 작성되지 않고 이동된 것으로 감지되므로 기록을 더 쉽게 보존할 수 있습니다.

또 다른 장점은 단일 커밋에서 서비스 경계를 넘나드는 광범위한 변경을 수행할 수 있다는 것입니다. 이 활동은 개별적으로 검토할 수 있는 잠재적으로 수십 개의 변경 내용이 있는 오버헤드를 줄입니다.

안전하지 않은 프로그래밍 방법 또는 문제가 있는 API 사용을 감지하기 위해 코드의 정적 분석을 수행할 수 있는 많은 도구가 있습니다. 다중 리포지토리 환경에서는 각 리포지토리를 반복하여 문제를 찾아야 합니다. 단일 리포지토리를 사용하면 모든 분석을 한 곳에서 실행할 수 있습니다.

또한 단일 리포지토리 접근 방식에는 많은 단점이 있습니다. 가장 걱정되는 것 중 하나는 단일 리포지토리가 있으면 보안 문제가 제기된다는 것입니다. 리포지토리의 내용이 서비스 모델당 리포지토리에서 유출되는 경우 손실된 코드의 양은 최소화됩니다. 단일 리포지토리를 사용하면 회사가 소유한 모든 것이 손실될 수 있습니다. 과거에는 이러한 일이 발생하고 전체 게임 개발 노력을 탈선시키는 많은 예가 있었습니다. 여러 리포지토리가 있으면 노출 영역이 적어지는데, 이는 대부분의 보안 사례에서 바람직한 특성입니다.

단일 리포지토리의 크기는 빠르게 관리가 불가능해질 수 있습니다. 이는 몇 가지 흥미로운 성능 영향을 제공합니다. 원래 Windows 팀의 개발자 환경을 개선하기 위해 설계된 Git용 가상 파일 시스템과 같은 특수 도구를 사용해야 할 수도 있습니다.

종종 단일 리포지토리를 사용하기 위한 인수는 Facebook 또는 Google이 소스 코드 정렬에 이 메서드를 사용한다는 인수로 귀결됩니다. 이러한 회사에 대한 접근 방식이 충분히 좋은 경우, 이는 확실히 모든 회사에 대한 올바른 접근 방식입니다. 문제의 진실은 Facebook이나 Google과 같은 규모로 운영되는 회사는 거의 없다는 것입니다. 이러한 규모에서 발생하는 문제는 대부분의 개발자가 직면하게 될 문제와 다릅니다. 암거위에게 유익한 것이 반드시 숫거위에게도 유익한 것은 아닐 수 있습니다.

결국 두 솔루션 중 하나를 사용하여 마이크로 서비스에 대한 소스 코드를 호스트할 수 있습니다. 그러나 대부분의 경우 단일 리포지토리에서 운영되는 관리 및 엔지니어링 오버헤드는 빈약한 이점의 가치가 없습니다. 여러 리포지토리를 통해 코드를 분할하면 문제를 더 잘 분리하고 개발 팀 간의 자율성을 장려할 수 있습니다.

표준 디렉터리 구조

단일 및 여러 리포지토리 논쟁에 관계없이 각 서비스에는 자체 디렉터리가 있습니다. 개발자가 프로젝트 간에 신속하게 이동할 수 있도록 하는 최고의 최적화 중 하나는 표준 디렉토리 구조를 유지하는 것입니다.

Figure 10-4 A standard directory structure for both the email and sign-in services

그림 10-4 - 표준 디렉터리 구조.

새 프로젝트를 만들 때마다 올바른 구조를 배치하는 템플릿을 사용해야 합니다. 이 템플릿에는 기본 추가 정보 파일 및 azure-pipelines.yml 같은 유용한 항목도 포함될 수 있습니다. 모든 마이크로 서비스 아키텍처에서 프로젝트 간에 높은 수준의 분산은 서비스에 대한 대량 작업을 더 어렵게 만듭니다.

여러 소스 코드 디렉터리를 포함하는 전체 디렉터리에 대한 템플릿을 제공할 수 있는 많은 도구가 있습니다. Yeoman은 JavaScript 세계에서 인기가 있으며 GitHub는 최근 동일한 기능을 많이 제공하는 리포지토리 템플릿을 출시했습니다.

작업 관리

모든 프로젝트에서 작업을 관리하는 것은 어려울 수 있습니다. 개발자 생산성을 최적화하기 위해 설정하는 워크플로 종류에 대한 수많은 질문에 답해야 합니다.

클라우드 네이티브 애플리케이션은 기존 소프트웨어 제품보다 작거나 적어도 더 작은 서비스로 나뉩니다. 이러한 서비스와 관련된 문제 또는 태스크 추적은 다른 소프트웨어 프로젝트와 마찬가지로 중요합니다. 일부 작업 항목을 추적하지 못하거나 문제가 제대로 기록되지 않았다고 고객에게 설명하고 싶은 사람은 아무도 없습니다. 보드는 프로젝트 수준에서 구성되지만 각 프로젝트 내에서 영역을 정의할 수 있습니다. 이를 통해 여러 구성 요소에서 문제를 분석할 수 있습니다. 전체 애플리케이션에 대한 모든 작업을 한 곳에 유지하는 이점은 작업 항목을 한 팀에서 다른 팀으로 쉽게 이동할 수 있다는 것입니다.

Azure DevOps에는 미리 구성된 여러 인기 있는 템플릿이 함께 제공됩니다. 가장 기본적인 구성에서 알아야 할 것은 백로그의 내용, 사람들이 작업하는 작업, 수행된 작업입니다. 작업 우선 순위를 지정하고 완료된 작업을 고객에게 보고할 수 있도록 소프트웨어 빌드 프로세스에 대한 가시성을 확보해야 합니다. 물론 to do, doing, done처럼 간단한 프로세스를 고수하는 소프트웨어 프로젝트는 거의 없습니다. 사람들이 QA 또는 Detailed Specification와 같은 단계를 프로세스에 추가하기 시작하는 데 오랜 시간이 걸리지 않습니다.

Agile 방법론의 가장 중요한 부분 중 하나는 정기적인 자기 성찰입니다. 이러한 검토는 팀이 직면하고 있는 문제와 개선할 수 있는 방법에 대한 인사이트를 제공하기 위한 것입니다. 이는 종종 개발 프로세스를 통해 문제 및 기능의 흐름을 변경하는 것을 의미합니다. 따라서 추가 스테이지로 보드의 레이아웃을 확장하는 것은 완벽하게 정상입니다.

보드의 단계만 조직 도구인 것은 아닙니다. 보드의 구성에 따라 작업 항목의 계층 구조가 있습니다. 보드에 표시할 수 있는 가장 세분화된 항목은 작업입니다. 우선 작업에는 제목, 설명, 우선 순위, 남은 작업량 예측, 다른 작업 항목 또는 개발 항목(분기, 커밋, 끌어오기 요청, 빌드 등)에 연결할 수 있는 기능이 포함됩니다. 작업 항목을 애플리케이션의 여러 영역과 다양한 반복(스프린트)으로 분류하여 쉽게 찾을 수 있습니다.

Figure 10-5 An example task in Azure DevOps

그림 10-5 - Azure DevOps의 작업.

설명 필드는 예상한 일반 스타일(굵게, 기울임꼴, 밑줄, 취소선)과 이미지를 삽입하는 기능을 지원합니다. 이렇게 하면 작업 또는 버그를 지정할 때 사용할 수 있는 강력한 도구가 됩니다.

작업은 더 큰 작업 단위를 정의하는 기능으로 롤업할 수 있습니다. 기능은 차례로 에픽으로 롤업할 수 있습니다. 이 계층 구조에서 작업을 분류하면 대규모 기능이 롤아웃하는 데 얼마나 가까운지 훨씬 쉽게 이해할 수 있습니다.

Figure 10-6 Work item types configured by default in the Basic process template

그림 10-6 - Azure DevOps의 작업 항목.

Azure Boards의 문제에 대한 다양한 종류의 보기가 있습니다. 아직 예약되지 않은 항목이 백로그에 표시됩니다. 여기에서 스프린트에 할당할 수 있습니다. 스프린트는 일정 수량의 작업이 완료될 것으로 예상되는 시간 상자입니다. 이 작업에는 작업뿐만 아니라 티켓 확인도 포함될 수 있습니다. 그런 다음, 스프린트 보드 섹션에서 전체 스프린트를 관리할 수 있습니다. 이 보기는 작업이 진행되는 방식을 보여 주며 스프린트가 성공할지 예측하는 번다운 차트를 포함합니다.

Figure 10-7 A board with a sprint defined

그림 10-7 - Azure DevOps의 보드.

지금쯤이면 Azure DevOps의 보드에 엄청난 힘이 있다는 것이 분명해져야 합니다. 개발자의 경우 작업 중인 내용을 쉽게 볼 수 있습니다. 프로젝트 관리자의 경우 예정된 작업과 기존 작업에 대한 개요를 볼 수 있습니다. 관리자의 경우 리소스 및 용량에 대한 보고서가 많이 있습니다. 아쉽게도 클라우드 네이티브 애플리케이션에 대해 작업을 추적할 필요가 없는 마법같은 것은 없습니다. 그러나 작업을 추적해야 하는 경우 Azure DevOps보다 환경이 더 나은 몇 가지 위치가 있습니다.

CI/CD 파이프라인

CI(연속 통합) 및 CD(지속적인 업데이트)의 출현으로 소프트웨어 개발 수명 주기가 거의 변하지 않았습니다. 변경 내용이 체크 인되는 즉시 프로젝트의 소스 코드에 대해 자동화된 테스트를 빌드하고 실행하면 실수를 조기에 catch할 수 있습니다. 연속 통합 빌드가 등장하기 전에는 리포지토리에서 코드를 가져와 테스트를 통과하지 못했거나 빌드할 수 없다는 사실을 알아내는 것이 드문 일이 아니었습니다. 이로 인해 중단의 원인을 추적할 수 있습니다.

일반적으로 프로덕션 환경에 소프트웨어를 배송하려면 광범위한 설명서와 단계 목록이 필요했습니다. 이러한 각 단계는 오류가 발생하기 쉬운 프로세스에서 수동으로 완료해야 했습니다.

Figure 10-8 A checklist

그림 10-8 - 검사 목록.

지속적인 통합의 자매는 새로 빌드된 패키지가 환경에 배포되는 지속적인 업데이트입니다. 수동 프로세스는 개발 속도에 맞게 스케일링할 수 없으므로 자동화가 더 중요해집니다. 검사 목록은 모든 사용자보다 더 빠르고 정확하게 동일한 작업을 실행할 수 있는 스크립트로 대체됩니다.

지속적인 업데이트가 제공되는 환경은 테스트 환경일 수도 있고, 많은 주요 기술 회사에서 수행하는 것처럼 프로덕션 환경일 수도 있습니다. 후자는 변경이 사용자의 프로덕션을 중단하지 않을 것이라는 확신을 줄 수 있는 고품질 테스트에 대한 투자가 필요합니다. 지속적인 통합이 코드에서 문제를 포착한 것과 동일한 방식으로 조기 지속적인 업데이트는 배포 프로세스의 문제를 조기에 catch합니다.

빌드 및 배달 프로세스 자동화의 중요성은 클라우드 네이티브 애플리케이션에 의해 강조됩니다. 배포는 더 자주 그리고 더 많은 환경에서 발생하므로 불가능한 경우 수동으로 테두리를 배포합니다.

Azure Builds

Azure DevOps는 그 어느 때보다 쉽게 연속 통합 및 배포를 수행할 수 있는 도구 집합을 제공합니다. 이러한 도구는 Azure Pipelines 아래에 있습니다. 그 중 첫 번째는 대규모 YAML 기반 빌드 정의를 실행하기 위한 도구인 Azure Builds입니다. 사용자는 자체 빌드 머신을 가져오거나(빌드에 꼼꼼하게 설정된 환경이 필요한 경우에 적합) Azure 호스팅 가상 머신의 지속적으로 새로 고쳐진 풀에서 머신을 사용할 수 있습니다. 이러한 호스트된 빌드 에이전트는 .NET 개발뿐만 아니라 Java에서 Python, iPhone 개발까지 모든 것을 위한 광범위한 개발 도구와 함께 미리 설치됩니다.

DevOps에는 모든 빌드에 맞게 사용자 지정할 수 있는 다양한 기본 빌드 정의가 포함되어 있습니다. 빌드 정의는 azure-pipelines.yml이라는 파일에 정의되며 소스 코드와 함께 버전을 지정할 수 있도록 리포지토리에 체크 인됩니다. 이렇게 하면 변경 내용을 해당 분기에만 체크 인할 수 있으므로 분기에서 빌드 파이프라인을 훨씬 쉽게 변경할 수 있습니다. 전체 프레임워크에서 ASP.NET 웹 애플리케이션을 빌드하는 예제 azure-pipelines.yml은 그림 10-9에 나와 있습니다.

name: $(rev:r)

variables:
  version: 9.2.0.$(Build.BuildNumber)
  solution: Portals.sln
  artifactName: drop
  buildPlatform: any cpu
  buildConfiguration: release

pool:
  name: Hosted VisualStudio
  demands:
  - msbuild
  - visualstudio
  - vstest

steps:
- task: NuGetToolInstaller@0
  displayName: 'Use NuGet 4.4.1'
  inputs:
    versionSpec: 4.4.1

- task: NuGetCommand@2
  displayName: 'NuGet restore'
  inputs:
    restoreSolution: '$(solution)'

- task: VSBuild@1
  displayName: 'Build solution'
  inputs:
    solution: '$(solution)'
    msbuildArgs: '-p:DeployOnBuild=true -p:WebPublishMethod=Package -p:PackageAsSingleFile=true -p:SkipInvalidConfigurations=true -p:PackageLocation="$(build.artifactstagingdirectory)\\"'
    platform: '$(buildPlatform)'
    configuration: '$(buildConfiguration)'

- task: VSTest@2
  displayName: 'Test Assemblies'
  inputs:
    testAssemblyVer2: |
     **\$(buildConfiguration)\**\*test*.dll
     !**\obj\**
     !**\*testadapter.dll
    platform: '$(buildPlatform)'
    configuration: '$(buildConfiguration)'

- task: CopyFiles@2
  displayName: 'Copy UI Test Files to: $(build.artifactstagingdirectory)'
  inputs:
    SourceFolder: UITests
    TargetFolder: '$(build.artifactstagingdirectory)/uitests'

- task: PublishBuildArtifacts@1
  displayName: 'Publish Artifact'
  inputs:
    PathtoPublish: '$(build.artifactstagingdirectory)'
    ArtifactName: '$(artifactName)'
  condition: succeededOrFailed()

그림 10-9 - 샘플 azure-pipelines.yml

이 빌드 정의는 레고 세트를 빌드하는 것만큼 간단하게 빌드를 만드는 여러 가지 기본 제공 작업을 사용합니다(거대한 밀레니엄 팔콘보다 간단). 예를 들어 NuGet 작업은 NuGet 패키지를 복원하고 VSBuild 작업은 Visual Studio 빌드 도구를 호출하여 실제 컴파일을 수행합니다. Azure DevOps에는 수백 가지 작업을 사용할 수 있으며, 커뮤니티에서 유지 관리하는 작업이 수천 개 더 있습니다. 실행하려는 빌드 작업에 관계없이 누군가가 이미 빌드한 것일 수 있습니다.

수동으로, 체크 인하거나, 일정에 따라 또는 다른 빌드를 완료하여 빌드를 트리거할 수 있습니다. 대부분의 경우 모든 체크 인을 빌드하는 것이 좋습니다. 다른 빌드가 리포지토리의 다른 부분이나 다른 분기에 대해 실행되도록 빌드를 필터링할 수 있습니다. 이를 통해 끌어오기 요청 시 테스트가 감소된 빠른 빌드를 실행하고 야간에 트렁크에 대해 전체 회귀 제품군을 실행하는 등의 시나리오를 수행할 수 있습니다.

빌드의 최종 결과는 빌드 아티팩트라고 하는 파일의 컬렉션입니다. 이러한 아티팩트를 빌드 프로세스의 다음 단계로 전달하거나 Azure Artifacts 피드에 추가하여 다른 빌드에서 사용할 수 있습니다.

Azure DevOps 릴리스

빌드는 소프트웨어를 배송 가능한 패키지로 컴파일하는 작업을 처리하지만, 지속적인 업데이트를 완료하려면 아티팩트가 테스트 환경으로 푸시되어야 합니다. 이를 위해 Azure DevOps는 릴리스라는 별도의 도구를 사용합니다. 릴리스 도구는 빌드에서 사용할 수 있었지만 “스테이지”라는 개념을 도입한 것과 동일한 작업 라이브러리를 사용합니다. 단계는 패키지가 설치된 격리된 환경입니다. 예를 들어 제품이 개발, QA, 프로덕션 환경을 사용할 수 있습니다. 코드는 자동화된 테스트를 실행할 수 있는 개발 환경으로 지속적으로 전달됩니다. 이러한 테스트가 통과되면 수동 테스트를 위해 릴리스가 QA 환경으로 이동합니다. 마지막으로, 코드는 모든 사용자에게 표시되는 프로덕션으로 푸시됩니다.

Figure 10-10 An example release pipeline with Develop, QA, and Production phases

그림 10-10 - 릴리스 파이프라인

빌드의 각 단계는 이전 단계가 완료되면 자동으로 트리거될 수 있습니다. 그러나 대부분의 경우 이는 바람직하지 않습니다. 코드를 프로덕션으로 이동하려면 다른 사람의 승인이 필요할 수 있습니다. 릴리스 도구는 릴리스 파이프라인의 각 단계에서 승인자를 허용하여 이를 지원합니다. 특정 사용자 또는 사용자 그룹이 프로덕션으로 전환하기 전에 릴리스에서 로그오프하도록 규칙을 설정할 수 있습니다. 이러한 게이트는 수동 품질 검사를 허용하고 프로덕션 환경에 들어가는 항목을 제어하는 것과 관련된 모든 규정 요구 사항을 준수할 수 있습니다.

모두가 빌드 파이프라인을 가져옵니다.

많은 빌드 파이프라인을 구성하는 데 비용이 들지 않으므로 마이크로 서비스당 하나 이상의 빌드 파이프라인을 사용하는 것이 유리합니다. 이상적으로 마이크로 서비스는 모든 환경에 독립적으로 배포할 수 있으므로 관련 없는 코드를 대량으로 릴리스하지 않고도 각 서비스를 자체 파이프라인을 통해 릴리스할 수 있게 하는 것이 완벽합니다. 각 파이프라인에는 각 서비스에 대한 빌드 프로세스의 변형을 허용하는 자체 승인 집합이 있을 수 있습니다.

버전 관리 릴리스

릴리스 기능을 사용하는 한 가지 단점은 체크 인된 azure-pipelines.yml 파일에서 정의할 수 없다는 것입니다. 분기별 릴리스 정의를 사용하는 것부터 프로젝트 템플릿에 릴리스 기본 구조를 포함하는 것까지 여러 가지 이유가 있습니다. 다행히 일부 단계 지원을 빌드 구성 요소로 전환하는 작업이 진행 중입니다. 이를 다단계 빌드라고 하며 이제 첫 번째 버전을 사용할 수 있습니다!