팁 (조언)
이 콘텐츠는 eBook, Architecting Cloud Native .NET Applications for Azure에서 발췌한 것으로, .NET Docs 또는 오프라인에서 읽을 수 있는 다운로드 가능한 무료 PDF로 제공됩니다.
컨테이너 및 오케스트레이터는 모놀리식 배포 방법에 공통된 문제를 해결하도록 설계되었습니다.
모놀리식 배포에서의 어려움
일반적으로 대부분의 애플리케이션은 단일 단위로 배포되었습니다. 이러한 애플리케이션을 모놀리식이라고 합니다. 여러 모듈 또는 어셈블리로 구성된 경우에도 애플리케이션을 단일 단위로 배포하는 일반적인 접근 방식을 그림 3-1과 같이 모놀리식 아키텍처라고 합니다.
그림 3-1. 모놀리식 아키텍처.
단순성의 이점이 있지만 모놀리식 아키텍처는 다음과 같은 많은 문제에 직면해 있습니다.
배치
또한, 배포 시 무중단 기술이 적용되지 않을 경우 애플리케이션을 다시 시작해야 하며, 이는 일시적으로 가용성에 영향을 미칠 수 있습니다.
확장
모놀리식 애플리케이션은 단일 컴퓨터 인스턴스에서 전적으로 호스트되며 종종 고성능 하드웨어가 필요합니다. 모놀리식 부분에 크기 조정이 필요한 경우 전체 애플리케이션의 다른 복사본을 다른 컴퓨터에 배포해야 합니다. 모놀리식 아키텍처에서는 애플리케이션 구성 요소를 개별적으로 확장할 수 없으며, 모두 아니면 아무것도 아닙니다. 크기 조정이 필요하지 않은 구성 요소의 크기를 조정하면 비효율적이고 비용이 많이 드는 리소스 사용량이 발생합니다.
환경
모놀리식 애플리케이션은 일반적으로 사전 설치된 운영 체제, 런타임 및 라이브러리 종속성을 사용하여 호스팅 환경에 배포됩니다. 이 환경은 애플리케이션이 개발 또는 테스트된 환경과 일치하지 않을 수 있습니다. 애플리케이션 환경 간 불일치는 모놀리식 배포에 대한 일반적인 문제의 원인입니다.
커플링
모놀리식 애플리케이션은 기능 구성 요소 간에 높은 결합을 경험할 수 있습니다. 하드 경계가 없으면 시스템 변경으로 인해 의도하지 않고 비용이 많이 드는 부작용이 발생하는 경우가 많습니다. 새로운 기능/수정은 까다로워지고, 시간이 많이 걸리며, 구현하는 데 비용이 많이 듭니다. 업데이트에는 광범위한 테스트가 필요합니다. 또한 결합을 사용하면 구성 요소를 리팩터링하거나 대체 구현에서 교환하기가 어렵습니다. 철저하게 구조적 관심사를 분리하여 구축하더라도 끝없는 "특수 사례"로 인해 모놀리식 코드 베이스가 악화되면서 건축 침식이 전개됩니다.
플랫폼 잠금
모놀리식 애플리케이션은 단일 기술 스택으로 생성됩니다. 균일성을 제공하면서 이러한 약속은 혁신의 장벽이 될 수 있습니다. 최신 기술이 더 나은 선택이 될 수 있는 경우에도 애플리케이션의 현재 스택을 사용하여 새로운 기능과 구성 요소가 빌드됩니다. 장기적인 위험은 기술 스택이 낡고 더 이상 쓸모없거나 시대에 뒤떨어지는 것입니다. 전체 애플리케이션을 새롭고 최신 플랫폼으로 다시 설계하는 것은 비용이 많이 들고 위험합니다.
컨테이너 및 오케스트레이터의 이점은 무엇인가요?
1장에서 컨테이너를 도입했습니다. CNCF(클라우드 네이티브 컴퓨팅 재단)가 컨테이너화를 클라우드 네이티브 여정을 시작하는 기업에 대한 지침인 Cloud-Native 트레일 맵 의 첫 번째 단계로 순위를 지정하는 방법을 강조했습니다. 이 섹션에서는 컨테이너의 이점에 대해 설명합니다.
Docker는 가장 인기 있는 컨테이너 관리 플랫폼입니다. Linux 또는 Windows의 컨테이너에서 작동합니다. 컨테이너는 시스템에서 동일한 방식으로 실행되는 별도의 재현 가능한 애플리케이션 환경을 제공합니다. 이러한 측면은 클라우드 네이티브 서비스를 개발하고 호스팅하는 데 적합합니다. 컨테이너는 서로 격리됩니다. 동일한 호스트 하드웨어의 두 컨테이너는 충돌을 일으키지 않고 서로 다른 버전의 소프트웨어를 가질 수 있습니다.
컨테이너는 프로젝트 아티팩트가 되고 소스 제어에 체크 인되는 간단한 텍스트 기반 파일에 의해 정의됩니다. 전체 서버 및 가상 머신은 수동으로 업데이트해야 하지만 컨테이너는 쉽게 버전 제어할 수 있습니다. 컨테이너에서 실행되도록 빌드된 앱은 빌드 파이프라인의 일부로 자동화된 도구를 사용하여 개발, 테스트 및 배포할 수 있습니다.
컨테이너는 변경할 수 없습니다. 컨테이너를 정의한 후에는 정확히 동일한 방식으로 다시 만들고 실행할 수 있습니다. 이러한 불변성은 구성 요소 기반 디자인에 적합합니다. 애플리케이션의 일부 부분이 다른 부분과 다르게 진화하는 경우 가장 자주 변경되는 부분을 배포할 수 있을 때 전체 앱을 다시 배포하는 이유는 무엇인가요? 앱의 다양한 기능과 횡단 관심사는 별도의 단위로 나눌 수 있습니다. 그림 3-2는 모놀리식 앱이 특정 기능 또는 기능을 위임하여 컨테이너 및 마이크로 서비스를 활용하는 방법을 보여 줍니다. 앱 자체의 나머지 기능도 컨테이너화되었습니다.
그림 3-2. 마이크로 서비스를 수용하기 위해 모놀리식 앱을 분해합니다.
각 클라우드 네이티브 서비스는 별도의 컨테이너에 빌드되고 배포됩니다. 각각은 필요에 따라 업데이트할 수 있습니다. 개별 서비스는 각 서비스에 적합한 리소스가 있는 노드에서 호스트할 수 있습니다. 각 서비스가 실행되는 환경은 변경할 수 없으며 개발, 테스트 및 프로덕션 환경에서 공유되며 쉽게 버전 관리됩니다. 애플리케이션의 서로 다른 영역 간의 결합은 모놀리식 내에서 컴파일 시간 종속성이 아니라 서비스 간의 호출 또는 메시지로 명시적으로 발생합니다. 또한 앱의 나머지 부분을 변경하지 않고도 지정된 기능을 가장 잘 제공하는 기술을 선택할 수 있습니다.
컨테이너화된 서비스에는 자동화된 관리가 필요합니다. 독립적으로 배포된 대규모 컨테이너 집합을 수동으로 관리하는 것은 불가능합니다. 예를 들어 다음 작업을 고려합니다.
- 컨테이너 인스턴스는 여러 컴퓨터의 클러스터에서 어떻게 프로비전되나요?
- 배포된 컨테이너는 어떻게 서로 검색하고 통신하나요?
- 컨테이너는 어떻게 주문형으로 스케일 인 또는 스케일 아웃할 수 있나요?
- 각 컨테이너의 상태를 모니터링하려면 어떻게 해야 할까요?
- 하드웨어 및 소프트웨어 오류로부터 컨테이너를 보호하려면 어떻게 해야 할까요?
- 가동 중지 시간이 없는 라이브 애플리케이션에 대한 컨테이너를 업그레이드하려면 어떻게 해야 할까요?
컨테이너 오케스트레이터는 이러한 문제 및 기타 문제를 해결하고 자동화합니다.
클라우드 네이티브 에코 시스템에서 Kubernetes는 사실상 컨테이너 오케스트레이터가 되었습니다. CNCF(Cloud Native Computing Foundation)에서 관리하는 오픈 소스 플랫폼입니다. Kubernetes는 컴퓨터 클러스터 전체에서 컨테이너화된 워크로드의 배포, 크기 조정 및 운영 문제를 자동화합니다. 그러나 Kubernetes 설치 및 관리는 매우 복잡합니다.
훨씬 더 나은 방법은 클라우드 공급업체의 관리 서비스로 Kubernetes를 활용하는 것입니다. Azure 클라우드에는 AKS(Azure Kubernetes Service)라는 완전히 관리되는 Kubernetes 플랫폼이 있습니다. AKS는 Kubernetes 관리의 복잡성 및 운영 오버헤드를 추상화합니다. Kubernetes를 클라우드 서비스로 사용합니다. Microsoft는 관리 및 지원을 담당합니다. 또한 AKS는 다른 Azure 서비스 및 개발 도구와 긴밀하게 통합됩니다.
AKS는 클러스터 기반 기술입니다. 페더레이션된 가상 머신 또는 노드 풀이 Azure 클라우드에 배포됩니다. 이러한 환경은 함께 고가용성 환경 또는 클러스터를 형성합니다. 클러스터는 클라우드 네이티브 애플리케이션에 원활한 단일 엔터티로 나타납니다. 내부적으로 AKS는 부하를 균등하게 분산하는 미리 정의된 전략에 따라 이러한 노드에 컨테이너화된 서비스를 배포합니다.
크기 조정 이점은 무엇인가요?
컨테이너를 기반으로 하는 서비스는 Kubernetes와 같은 오케스트레이션 도구에서 제공하는 크기 조정 이점을 활용할 수 있습니다. 설계상 컨테이너는 자신에 대해서만 알고 있습니다. 함께 작업해야 하는 컨테이너가 여러 대 있으면 더 높은 수준에서 구성해야 합니다. 많은 수의 컨테이너와 네트워크 구성과 같은 공유 종속성을 구성하면 오케스트레이션 도구가 들어와 하루를 절약할 수 있습니다. Kubernetes는 컨테이너 그룹에 대해 추상화 계층을 만들고 Pod로 구성 합니다. Pod는 노드라고 하는 작업자 컴퓨터에서 실행됩니다. 이 구조체를 클러스터라고 합니다. 그림 3-3은 Kubernetes 클러스터의 다양한 구성 요소를 보여 줍니다.
그림 3-3. Kubernetes 클러스터 구성 요소입니다.
컨테이너화된 워크로드 크기 조정은 컨테이너 오케스트레이터의 주요 기능입니다. AKS는 컨테이너 인스턴스 및 컴퓨팅 노드의 두 차원에 걸쳐 자동 크기 조정을 지원합니다. 이를 통해 AKS는 수요 급증에 신속하고 효율적으로 대응하고 추가 리소스를 추가할 수 있습니다. 이 챕터의 뒷부분에서 AKS의 크기 조정에 대해 설명합니다.
선언적 및 명령적
Kubernetes는 선언적 구성과 명령적 구성을 모두 지원합니다. 명령적 접근 방식에는 Kubernetes에 각 단계를 수행할 작업을 알려주는 다양한 명령을 실행하는 것이 포함됩니다. 이 이미지를 실행합니다. 이 Pod를 삭제합니다. 이 포트를 노출합니다. 선언적 접근 방식을 사용하면 매니페스트라는 구성 파일을 만들어 수행할 작업 대신 원하는 작업을 설명합니다. Kubernetes는 매니페스트를 읽고 원하는 끝 상태를 실제 끝 상태로 변환합니다.
명령적 명령은 학습 및 대화형 실험에 적합합니다. 그러나 신뢰할 수 있고 반복 가능한 배포를 제공하는 코드 접근 방식으로 인프라를 수용하는 Kubernetes 매니페스트 파일을 선언적으로 만들려고 합니다. 매니페스트 파일은 프로젝트 아티팩트가 되며 Kubernetes 배포를 자동화하기 위해 CI/CD 파이프라인에서 사용됩니다.
명령적 명령을 사용하여 클러스터를 이미 구성한 경우 .를 사용하여 kubectl get svc SERVICENAME -o yaml > service.yaml선언적 매니페스트를 내보낼 수 있습니다. 이 명령은 아래 표시된 것과 유사한 매니페스트를 생성합니다.
apiVersion: v1
kind: Service
metadata:
creationTimestamp: "2019-09-13T13:58:47Z"
labels:
component: apiserver
provider: kubernetes
name: kubernetes
namespace: default
resourceVersion: "153"
selfLink: /api/v1/namespaces/default/services/kubernetes
uid: 9b1fac62-d62e-11e9-8968-00155d38010d
spec:
clusterIP: 10.96.0.1
ports:
- name: https
port: 443
protocol: TCP
targetPort: 6443
sessionAffinity: None
type: ClusterIP
status:
loadBalancer: {}
선언적 구성을 사용하는 경우 구성 파일이 있는 폴더에 대해 사용하여 kubectl diff -f FOLDERNAME 커밋하기 전에 수행할 변경 내용을 미리 볼 수 있습니다. 변경 내용을 적용하기로 확신이 서면 kubectl apply -f FOLDERNAME을 실행하십시오. 폴더 계층 구조를 재귀적으로 처리하기 위해 추가 -R 합니다.
배포 중 하나인 다른 Kubernetes 기능과 함께 선언적 구성을 사용할 수도 있습니다. 선언적 배포는 릴리스, 업데이트 및 크기 조정을 관리하는 데 도움이 됩니다. 새 변경 내용을 배포하거나 부하를 확장하거나 이전 수정 버전으로 롤백하는 방법에 대해 Kubernetes 배포 컨트롤러에 지시합니다. 클러스터가 불안정한 경우 선언적 배포는 클러스터를 원하는 상태로 자동으로 반환합니다. 예를 들어 노드가 충돌해야 하는 경우 배포 메커니즘은 원하는 상태를 달성하기 위해 대체를 다시 배포합니다.
선언적 구성을 사용하면 인프라를 애플리케이션 코드와 함께 체크 인 및 버전 관리될 수 있는 코드로 나타낼 수 있습니다. 빌드 및 배포 파이프라인을 사용하여 향상된 변경 제어 및 지속적인 배포에 대한 더 나은 지원을 제공합니다.
컨테이너 및 오케스트레이터에 이상적인 시나리오는 무엇인가요?
다음 시나리오는 컨테이너 및 오케스트레이터를 사용하는 데 적합합니다.
높은 가동 시간 및 확장성이 필요한 애플리케이션
가동 시간 및 확장성 요구 사항이 높은 개별 애플리케이션은 마이크로 서비스, 컨테이너 및 오케스트레이터를 사용하는 클라우드 네이티브 아키텍처에 이상적인 후보입니다. 컨테이너에서 개발되고, 버전이 지정된 환경에서 테스트하고, 가동 중지 시간이 0인 프로덕션 환경에 배포할 수 있습니다. Kubernetes 클러스터를 사용하면 이러한 앱이 필요에 따라 확장되고 노드 오류로부터 자동으로 복구할 수 있습니다.
많은 수의 애플리케이션
많은 수의 애플리케이션을 배포하고 유지 관리하는 조직은 컨테이너 및 오케스트레이터의 이점을 누릴 수 있습니다. 컨테이너화된 환경 및 Kubernetes 클러스터를 설정하는 선행 작업은 주로 고정 비용입니다. 개별 애플리케이션을 배포, 유지 관리 및 업데이트하는 데 드는 비용은 애플리케이션 수에 따라 달라집니다. 몇 가지 애플리케이션 외에도 사용자 지정 애플리케이션을 수동으로 유지 관리하는 복잡성은 컨테이너 및 오케스트레이터를 사용하여 솔루션을 구현하는 비용을 초과합니다.
컨테이너 및 오케스트레이터를 사용하지 않아야 하는 경우는 언제인가요?
Twelve-Factor 앱 원칙에 따라 애플리케이션을 빌드할 수 없는 경우 컨테이너 및 오케스트레이터를 사용하지 않는 것이 좋습니다. 이러한 경우 VM 기반 호스팅 플랫폼 또는 일부 하이브리드 시스템을 고려합니다. 이 기능을 사용하면 항상 특정 기능을 별도의 컨테이너 또는 서버리스 함수로 분리할 수 있습니다.
개발 리소스
이 섹션에서는 다음 애플리케이션에 컨테이너 및 오케스트레이터 사용을 시작하는 데 도움이 될 수 있는 개발 리소스의 짧은 목록을 보여 줍니다. 클라우드 네이티브 마이크로 서비스 아키텍처 앱을 디자인하는 방법에 대한 지침을 찾고 있는 경우 이 책의 도우미인 .NET 마이크로 서비스: 컨테이너화된 .NET 애플리케이션을 위한 아키텍처를 읽어보세요.
로컬 Kubernetes 개발
Kubernetes 배포는 프로덕션 환경에서 큰 가치를 제공하지만 개발 머신에서 로컬로 실행할 수도 있습니다. 개별 마이크로 서비스에서 독립적으로 작업할 수 있지만 프로덕션에 배포할 때 실행되는 것처럼 전체 시스템을 로컬로 실행해야 하는 경우가 있을 수 있습니다. Minikube 및 Docker Desktop과 같은 여러 도구가 도움이 될 수 있습니다. Visual Studio는 Docker 개발을 위한 도구도 제공합니다.
Minikube
Minikube란? Minikube 프로젝트에는 "Minikube는 macOS, Linux 및 Windows에서 로컬 Kubernetes 클러스터를 구현합니다." 주요 목표는 "로컬 Kubernetes 애플리케이션 개발을 위한 최상의 도구가 되고 적합한 모든 Kubernetes 기능을 지원하는 것"입니다. Minikube 설치는 Docker와는 별개이지만 Minikube는 Docker Desktop이 지원하는 것과 다른 하이퍼바이저를 지원합니다. 현재 Minikube에서 지원되는 Kubernetes 기능은 다음과 같습니다.
- 디엔에스 (DNS)
- NodePorts
- ConfigMaps 및 시크릿
- 계기판
- 컨테이너 런타임: Docker, rkt, CRI-O 및 컨테이너형
- CNI(컨테이너 네트워크 인터페이스) 활성화
- 수신
Minikube를 설치한 후 이미지를 다운로드하고 로컬 Kubernetes 클러스터를 minikube start 시작하는 명령을 실행하여 빠르게 사용할 수 있습니다. 클러스터가 시작되면 표준 Kubernetes kubectl 명령을 사용하여 상호 작용합니다.
Docker Desktop
Windows의 Docker Desktop에서 직접 Kubernetes로 작업할 수도 있습니다. Windows 컨테이너를 사용하는 경우 유일한 옵션이며 비 Windows 컨테이너에도 적합합니다. 그림 3-4에서는 Docker Desktop을 실행할 때 로컬 Kubernetes 지원을 사용하도록 설정하는 방법을 보여 줍니다.
그림 3-4. Docker Desktop에서 Kubernetes 구성
Docker Desktop은 컨테이너화된 앱을 로컬로 구성하고 실행하는 데 가장 인기 있는 도구입니다. Docker Desktop을 사용하는 경우 프로덕션에 배포할 동일한 Docker 컨테이너 이미지 집합에 대해 로컬로 개발할 수 있습니다. Docker Desktop은 컨테이너화된 앱을 로컬로 "빌드, 테스트 및 배송"하도록 설계되었습니다. Linux 및 Windows 컨테이너를 모두 지원합니다. Azure Container Registry 또는 Docker Hub와 같은 이미지 레지스트리에 이미지를 푸시하면 AKS에서 이미지를 끌어와 프로덕션에 배포할 수 있습니다.
Visual Studio Docker 도구
Visual Studio는 웹 기반 애플리케이션에 대한 Docker 개발을 지원합니다. 새 ASP.NET Core 애플리케이션을 만들 때 그림 3-5와 같이 Docker 지원을 사용하여 구성할 수 있는 옵션이 있습니다.
그림 3-5. Visual Studio에서 Docker 지원 활성화
이 옵션을 선택하면 루트에 Dockerfile가 생성되며, Docker 컨테이너에서 앱을 빌드하고 호스트하는 데 사용할 수 있습니다. 예제 Dockerfile은 그림 3-6에 나와 있습니다.
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /src
COPY ["eShopWeb/eShopWeb.csproj", "eShopWeb/"]
RUN dotnet restore "eShopWeb/eShopWeb.csproj"
COPY . .
WORKDIR "/src/eShopWeb"
RUN dotnet build "eShopWeb.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "eShopWeb.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "eShopWeb.dll"]
그림 3-6. Visual Studio에서 생성된 Dockerfile
지원이 추가되면 Visual Studio의 Docker 컨테이너에서 애플리케이션을 실행할 수 있습니다. 그림 3-7은 Docker 지원이 추가된 새 ASP.NET Core 프로젝트에서 사용할 수 있는 다양한 실행 옵션을 보여줍니다.
그림 3-7. Visual Studio Docker 실행 옵션
또한 언제든지 기존 ASP.NET Core 애플리케이션에 Docker 지원을 추가할 수 있습니다. Visual Studio 솔루션 탐색기에서 프로젝트를 마우스 오른쪽 단추로 클릭하고 그림 3-8과 같이Docker 지원>를 선택합니다.
그림 3-8. Visual Studio에 Docker 지원 추가
Visual Studio Code Docker 도구 및 기능
Docker 개발을 지원하는 Visual Studio Code에 사용할 수 있는 많은 확장이 있습니다.
Microsoft는 Visual Studio Code용 Docker 확장을 제공합니다. 이 확장은 애플리케이션에 컨테이너 지원을 추가하는 프로세스를 간소화합니다. 필요한 파일을 스캐폴드하고, Docker 이미지를 빌드하며, 컨테이너 내에서 앱을 디버그할 수 있습니다. 확장에는 컨테이너 및 이미지(예: 시작, 중지, 검사, 제거 등)에 대한 작업을 쉽게 수행할 수 있는 시각적 탐색기가 있습니다. 또한 이 확장은 여러 실행 중인 컨테이너를 단일 단위로 관리할 수 있도록 하는 Docker Compose를 지원합니다.
.NET