GKE Windows 컨테이너에 Windows 인증으로 ASP.NET 앱 배포


이 튜토리얼에서는 통합 Windows 인증과 함께 IIS를 사용하는 ASP.NET 웹 애플리케이션을 만들고 Windows 컨테이너를 사용하여 도메인에 연결된 Windows 서버 노드가 있는 Google Kubernetes Engine(GKE) 클러스터에 이를 배포하는 방법을 보여줍니다. 이 구성은 애플리케이션이 다른 Windows 리소스에 인증할 수 있도록 Google Cloud에서 Windows 컨테이너에 ASP.NET 애플리케이션을 배포하는 데 유용합니다. 이 튜토리얼에서는 또한 Active Directory에서 그룹 관리형 서비스 계정(gMSA)을 만드는 방법과 이를 사용하도록 GKE에서 웹 애플리케이션 배포를 구성하는 방법을 보여줍니다.

이 튜토리얼은 시스템 관리자를 대상으로 합니다. 여기에서는 사용자가 Active Directory에 익숙하고 Google Kubernetes Engine(GKE) 작업 경험이 있다고 가정합니다.

목표

  • 도메인에 조인된 Windows Server 노드가 있는 GKE 클러스터를 만들고 Active Directory gMSA를 지원하도록 클러스터를 구성합니다.
  • 통합 Windows 인증으로 IIS를 사용하는 ASP.NET 웹 애플리케이션 컨테이너 이미지를 빌드하고 배포합니다.

비용

이 문서에서는 비용이 청구될 수 있는 다음과 같은 Google Cloud 구성요소를 사용합니다.

프로젝트 사용량을 기준으로 예상 비용을 산출하려면 가격 계산기를 사용하세요. Google Cloud를 처음 사용하는 사용자는 무료 체험판을 사용할 수 있습니다.

시작하기 전에

  1. VM이 도메인에 자동 조인되도록 Active Directory 구성 튜토리얼의 단계를 완료하여 Active Directory 도메인에 조인된 Cloud Run 서비스를 만듭니다.

  2. 자동 도메인 조인을 테스트하기 위해 VM을 만든 프로젝트와 다른 Google Cloud 프로젝트에서 이 튜토리얼을 실행하는 경우 해당 Google Cloud 프로젝트에서 자동 도메인 조인을 위한 프로젝트 사용 설정의 단계를 수행합니다.

    다른 튜토리얼을 완료할 때는 새로운 Cloud Run 서비스가 사용되고 해당 URL이 PowerShell 창에 표시됩니다($RegisterUrl 변수의 값). 이 튜토리얼에서도 사용되므로 서비스 주소를 기록해 둡니다.

  3. Compute Engine, GKE, Cloud Build, Artifact Registry, Cloud Resource Manager API에 대한 API를 사용 설정했는지 확인합니다.

    API 사용 설정

    이 튜토리얼을 완료한 후 계속 비용이 청구되지 않도록 하려면 만든 리소스를 삭제하면 됩니다. 자세한 내용은 삭제를 참조하세요.

아키텍처

도메인에 조인된 Windows Server에서 실행되는 Windows 기반 애플리케이션은 종종 Microsoft Active Directory(AD) ID를 사용하여 사용자 및 애플리케이션을 인증합니다. 이에 대한 일반적인 사용 사례는 다음과 같습니다.

  • 웹 애플리케이션에 로그인을 시도할 때 Active Directory를 인증하기 위해 통합 Windows 인증을 사용하는 ASP.NET 웹 애플리케이션을 만듭니다.
  • 네트워크를 통해 원격 SMB 공유 또는 원격 Microsoft SQL Server 인스턴스와 같은 리소스에 액세스하기 위해 서버의 Active Directory 컴퓨터 계정을 사용하는 애플리케이션을 만듭니다.

Windows 컨테이너는 도메인에 조인될 수 없으므로 Active Directory에 컴퓨터 계정이 없습니다. 따라서 Windows 컨테이너에서 실행되는 ASP.NET 웹 애플리케이션은 통합 Windows 인증을 통해 Active Directory 사용자를 인증할 수 없으며, 따라서 네트워크의 보안 리소스에 액세스할 수 없습니다. ASP.NET이 보안 리소스에 액세스하는 방법에 대한 자세한 내용은 Microsoft 문서의 애플리케이션 풀 ID를 참조하세요.

컴퓨터 계정을 사용하는 대신 Windows 컨테이너는 Active Directory 그룹 관리형 서비스 계정(gMSA) ID를 사용하여 Active Directory와 파일 공유 및 SQL Server 인스턴스와 같은 네트워크의 기타 보안 리소스에 액세스할 수 있습니다. 자세한 내용은 Microsoft 문서의 그룹 관리형 서비스 계정 개요를 참조하세요.

다음 아키텍처 다이어그램은 이 튜토리얼에서 사용되는 리소스를 보여줍니다.

GKE에서 활성 도메인에 조인된 Windows Server 컨테이너

이 다이어그램은 다음 요소들을 보여줍니다.

  • 개발 VM. 이 튜토리얼에서는 ASP.NET 웹 애플리케이션 컨테이너 이미지를 빌드하고 gMSA를 만들기 위해 사용하는 Windows VM을 만듭니다.
  • GKE 클러스터 및 노드. 이 튜토리얼의 GKE 클러스터에는 Linux 노드 풀과 Windows Server 노드 풀이 모두 포함됩니다. 이러한 노드 풀은 다음과 같은 방법으로 사용됩니다.
    • Linux 노드는 GKE 측정항목 서버와 같이 Linux 운영체제에서만 실행되는 시스템 구성요소를 실합니다.
    • Windows Server 노드는 Windows Server 컨테이너를 호스팅하기 위해 사용되며 Active Directory 도메인에 조인됩니다.
  • Active Directory 인프라. GKE Windows 노드를 도메인에 조인하기 위해서는 먼저 VM이 도메인에 자동 조인되도록 Active Directory 구성 튜토리얼을 수행해야 합니다. 이 튜토리얼에서는 Active Directory에서 새 컴퓨터(인스턴스)를 등록하고 인스턴스가 도메인 조인 프로세스를 완료하기 위해 사용하는 임시 비밀번호를 각각의 새로운 인스턴스에 제공하는 Cloud Run 서비스를 만듭니다. Windows Server 노드 풀에서 각각의 새로운 인스턴스는 자신을 Active Directory 도메인에 조인하기 위해 Cloud Run 서비스를 호출합니다.
  • 네트워크 부하 분산기. 온프레미스 사용자가 브라우저를 열고 ASP.NET 웹 애플리케이션으로 이동하면 트래픽이 네트워크 부하 분산기를 통과합니다. 부하 분산기는 웹 애플리케이션에 대해 GKE LoadBalancer 서비스를 만들 때 GKE에서 생성됩니다. 사용자는 또한 Active Directory 사용자 인증 정보를 웹 애플리케이션에 전달하여 웹 애플리케이션에 인증을 수행합니다.

인프라 만들기

관련 튜토리얼을 완료한 후 현재 튜토리얼의 인프라 구성요소를 만듭니다. 여기에는 다음 내용이 포함됩니다.

  • ASP.NET 웹 애플리케이션 컨테이너 이미지가 있는 Windows Server VM
  • Windows Server 노드 풀이 있는 GKE 클러스터
  • GKE Pod에 Active Directory에 대한 액세스 권한을 부여하는 방화벽 규칙
  • 배포에서 gMSA 리소스 구성 및 입력을 처리하는 GKE 클러스터의 웹훅

개발 VM 만들기

만들려는 Windows Server 컨테이너 이미지는 컨테이너 이미지를 빌드하는 VM의 Windows Server 버전과 일치해야 합니다. 이 버전은 또한 GKE Window Server 노드의 Windows Server 버전과 일치해야 합니다. 다른 버전의 Windows Server에서 컨테이너 이미지를 만들거나 컨테이너를 실행하면 오류가 발생합니다. Windows 컨테이너의 호환성 요구사항에 대한 자세한 내용은 컨테이너 호스트 버전과 컨테이너 이미지 버전 일치를 참조하세요.

이 튜토리얼에서는 VM, GKE의 Windows Server 노드, 컨테이너 이미지에 대해 Windows Server의 장기 서비스 채널(LTSC) 2022 버전을 사용합니다. 자세한 내용은 Windows Server 버전과 GKE 버전 간의 버전 매핑을 참조하세요.

  1. Google Cloud 콘솔에서 Cloud Shell을 활성화합니다.

    Cloud Shell 활성화

    Google Cloud 콘솔 하단에서 Cloud Shell 세션이 시작되고 명령줄 프롬프트가 표시됩니다. Cloud Shell은 Google Cloud CLI가 사전 설치된 셸 환경으로, 현재 프로젝트의 값이 이미 설정되어 있습니다. 세션이 초기화되는 데 몇 초 정도 걸릴 수 있습니다.

  2. PowerShell이 열려 있으면 exit를 입력하여 닫습니다.
  3. 네트워크 및 서브네트워크와 Active Directory 서비스 URL에 대한 환경 변수를 설정합니다.

    export NETWORK_NAME=NETWORK-NAME
    export SUBNETWORK_NAME=SUBNETWORK-NAME
    export AD_JOIN_SERVICE_URL=AD-JOIN-SERVICE-URL
    

    다음을 바꿉니다.

    • NETWORK-NAME: VM을 배포할 VPC 네트워크입니다.
    • SUBNETWORK-NAME: VM을 배포할 서브넷입니다.
    • AD-JOIN-SERVICE-URL: 시작하기 전에 섹션에서 배포한 Cloud Run 서비스의 URL입니다.
  4. 현재 환경에 대해 Google Cloud 프로젝트 ID 및 리전을 설정합니다.

    gcloud config set project PROJECT-ID
    gcloud config set compute/zone ZONE-NAME
    

    다음을 바꿉니다.

    • PROJECT-ID: Google Cloud 프로젝트 ID입니다.
    • ZONE-NAME: 모든 VM을 배포할 영역입니다. 지연 시간을 줄이려면 Active Directory 도메인-조인 Cloud Run 서비스를 배포한 것과 동일한 리전의 영역을 선택하는 것이 좋습니다.
  5. 개발 VM의 서비스 계정을 만듭니다.

    export SERVICE_ACCOUNT_NAME=dev-vm
    export SERVICE_ACCOUNT_EMAIL=$SERVICE_ACCOUNT_NAME@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com
    
    gcloud iam service-accounts create $SERVICE_ACCOUNT_NAME \
        --display-name="Development VM Service Account"
    
  6. 서비스 계정에 Artifact Registry에 대한 액세스 권한을 부여합니다.

    gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \
        --member="serviceAccount:$SERVICE_ACCOUNT_EMAIL" \
        --role="roles/artifactregistry.writer"
    
  7. 서비스 계정에 GKE에 대한 액세스 권한을 부여합니다.

    gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \
        --member="serviceAccount:$SERVICE_ACCOUNT_EMAIL" \
        --role="roles/container.admin"
    

    container.admin 역할은 프로젝트에서 GKE 클러스터 만들기 및 역할 기반 액세스 제어(RBAC) 리소스를 포함한 클러스터에서 리소스 관리를 위한 권한을 모두 포함하기 때문에 서비스 계정에 부여되었습니다. gMSA 사용이 허용되는 Pod를 제어하기 위해서는 RBAC 리소스가 필요합니다.

  8. 새 Windows Server 2022 VM을 만듭니다.

    gcloud compute instances create gmsa-dev-vm \
        --image-project windows-cloud \
        --image-family windows-2022-core \
        --machine-type n1-standard-2 \
        --boot-disk-type=pd-ssd \
        --boot-disk-size=100GB \
        --network $NETWORK_NAME \
        --subnet $SUBNETWORK_NAME \
        --service-account=$SERVICE_ACCOUNT_EMAIL \
        --scopes https://www.googleapis.com/auth/cloud-platform \
        --metadata sysprep-specialize-script-ps1="iex((New-Object System.Net.WebClient).DownloadString('$AD_JOIN_SERVICE_URL')); Add-WindowsFeature RSAT-AD-PowerShell"
    

    컨테이너화된 애플리케이션을 Windows Server 2019 컨테이너에 배포하려면 --image-family 매개변수 값을 windows-2019-core-for-containers로 변경합니다.

    https://www.googleapis.com/auth/cloud-platform 범위는 인스턴스의 서비스 계정에 정의된 IAM 역할에 따라 인스턴스가 모든 Google Cloud API에 액세스할 수 있게 해줍니다.

    인터넷과 통신할 수 있도록 VM이 외부 IP 주소로 생성됩니다. gitkubectl과 같은 여러 유틸리티를 다운로드할 수 있도록 인터넷 액세스를 이용하고 GitHub에서 ASP.NET 웹 애플리케이션을 다운로드하기 위해 VM이 필요합니다.

    sysprep 단계에서는 도메인 계정을 사용하여 인스턴스에 원격으로 액세스할 수 있도록 새 인스턴스가 Active Directory 도메인에 조인됩니다. 또한 sysprep 명령어의 스크립트는 Active Directory를 위한 PowerShell 모듈을 설치합니다.

Artifact Registry Docker 저장소 만들기

  1. Cloud Shell에서 새 Artifact Registry 저장소의 기본 위치를 설정합니다.

    gcloud config set artifacts/location LOCATION
    

    LOCATION을 Artifact Registry 저장소를 만들려는 리전으로 바꿉니다. 지연 시간을 줄이려면 개발 VM을 배포한 것과 동일한 리전을 선택하는 것이 좋습니다.

  2. Artifact Registry Docker 저장소를 만듭니다.

    gcloud artifacts repositories create windows-container-images \
        --repository-format=docker
    

GKE 클러스터 만들기

  1. Cloud Shell에서 GKE 클러스터의 이름에 대해 환경변수를 설정합니다.

    export GKE_CLUSTER_NAME=cluster-1
    
  2. GKE 클러스터를 만듭니다.

    gcloud container clusters create $GKE_CLUSTER_NAME \
        --release-channel rapid \
        --network $NETWORK_NAME \
        --subnetwork $SUBNETWORK_NAME \
        --enable-ip-alias
    

    --release-channel 매개변수rapid로 설정하면 최신 Kubernetes 버전으로 GKE 클러스터가 배포됩니다. --enable-ip-alias 매개변수는 별칭 IP를 사용 설정합니다. Windows Server 노드에는 별칭 IP가 필요합니다.

GKE에서 Windows Server 노드 풀 만들기

CLI를 통해 새 GKE 클러스터를 만들면 Linux 노드 풀과 함께 클러스터가 생성됩니다. GKE에서 Windows Server를 사용하려면 Windows Server 노드 풀을 만듭니다.

GKE 클러스터에는 클러스터의 내부(시스템) 컨테이너를 실행하기 위해 하나 이상의 Linux 노드가 있어야 합니다. GKE 클러스터는 Windows Server 노드 만으로 생성될 수 없습니다.

  1. Cloud Shell에서 Windows Server 노드 풀의 이름에 대해 환경변수를 설정합니다.

    export NODE_POOL_NAME=windows-server-pool
    
  2. GKE Windows Server 노드 풀을 만듭니다.

    gcloud container node-pools create $NODE_POOL_NAME \
        --cluster $GKE_CLUSTER_NAME \
        --machine-type n1-standard-2 \
        --image-type WINDOWS_LTSC_CONTAINERD \
        --windows-os-version=ltsc2022 \
        --num-nodes 2 \
        --no-enable-autoupgrade \
        --metadata sysprep-specialize-script-ps1="iex((New-Object System.Net.WebClient).DownloadString('$AD_JOIN_SERVICE_URL'))"
    

    컨테이너화된 애플리케이션을 Windows Server 2019 컨테이너에 배포하려면 --windows-os-version 매개변수를 ltsc2019로 변경합니다.

    sysprep-specialize-script-ps1 메타데이터 키는 인스턴스가 처음 부팅되기 전 GCESysprep 단계 중에 실행되는 PowerShell 스크립트를 가리키는 기본 제공 키입니다.

    iex cmdlet은 Cloud Run에 배포한 Active Directory 도메인-조인 서비스에서 PowerShell 스크립트를 다운로드합니다. 그런 후 Active Directory 도메인에 새 인스턴스를 조인하는 스크립트를 실행합니다.

    --no-enable-autoupgrade 매개변수는 풀의 모든 노드에 대해 노드 자동 업그레이드를 사용 중지합니다. 이렇게 하는 이유는 노드의 Windows 이미지를 업그레이드할 때 노드의 Windows Server 버전과 Pod의 Windows Server 버전 간에 비호환성이 발생할 수 있기 때문입니다. 자세한 내용은 Windows Server 노드 풀 업그레이드를 참조하세요.

    각 노드가 생성되면 domain-join PowerShell 스크립트가 노드를 도메인에 조인합니다.

  3. 노드 풀이 생성될 때까지 몇 분 정도 기다린 후 다음 명령어를 실행하여 모든 노드가 도메인에 조인되었는지 확인합니다.

    kubectl get node \
    -l cloud.google.com/gke-nodepool=$NODE_POOL_NAME \
    -o custom-columns=":metadata.name" --no-headers \
        | xargs -I{} gcloud compute instances get-serial-port-output {} --port 1 \
        | grep "sysprep-specialize-script-ps1:.*success" --ignore-case
    

    노드가 도메인에 조인되었으면 출력이 다음과 같이 표시됩니다.

    timestamp GCEMetadataScripts: sysprep-specialize-script-ps1: Successfully registered computer account.
    timestamp GCEMetadataScripts: sysprep-specialize-script-ps1: Computer successfully joined to domain
    
    Specify --start=152874 in the next get-serial-port-output invocation to get only the new output starting from here.
    

    전체 스크립트 출력을 보려면 grep 명령어에서 .*success를 삭제합니다.

GKE Pod에 Active Directory 액세스 권한 부여

다음 프로토콜을 사용하여 GKE 클러스터의 Pod가 도메인 컨트롤러에 액세스하도록 허용하는 방화벽 규칙을 만들어야 합니다.

  • Kerberos(UDP/88, TCP/88)
  • NTP(UDP/123)
  • RPC(TCP/135, TCP/49152-65535)
  • LDAP(UDP/389, TCP/389)
  • SMB(UDP/445, TCP/445)
  • LDAP GC(TCP/3268)
  • Active Directory 웹 서비스(TCP/9389)

도메인 컨트롤러에 할당한 서비스 계정을 기준으로 규칙을 적용하거나 이 튜토리얼에서 수행되는 대로 네트워크 태그를 사용하여 적용할 수 있습니다. Active Directory 관련 포트에 대해 자세히 알아보려면 Active Directory 포트 및 프로토콜 요구사항방화벽 간 Active Directory 사용에 대한 문서를 참조하세요.

Microsoft Active Directory용 관리형 서비스(관리형 Microsoft AD)를 사용하는 경우 이 절차를 건너뛸 수 있습니다.

  1. Cloud Shell에서 GKE 클러스터의 Pod IP 주소 범위를 가져옵니다.

    CLUSTER_IP_RANGE=`gcloud container clusters describe $GKE_CLUSTER_NAME --format="value(clusterIpv4Cidr)"`
    
  2. GKE Pod에 Active Directory 액세스 권한을 부여하도록 방화벽 규칙을 만듭니다.

    gcloud compute firewall-rules create allow-gke-pods-to-ad \
        --network $NETWORK_NAME \
        --allow udp:88,tcp:88,udp:123,tcp:135,tcp:49152-65535,udp:389,tcp:389,udp:445,tcp:445,tcp:3268,tcp:9389 \
        --source-ranges=$CLUSTER_IP_RANGE \
        --target-tags DC-TAG
    

    DC-TAG를 도메인 컨트롤러의 VM에 할당된 네트워크 태그로 바꿉니다.

gMSA 사용을 지원하도록 GKE 구성

Windows Server 노드에서 gMSA를 사용하려면 Active Directory에 gMSA 객체를 만들고, GKE에 일치하는 gMSA 리소스를 만들고, 해당 gMSA 사용자 인증 정보를 가져오도록 새로 만든 Pod를 사용 설정해야 합니다.

  1. Cloud Shell에서 gMSA 웹훅 스크립트를 다운로드하고 실행합니다.

    export K8S_GMSA_DEPLOY_DOWNLOAD_REV=b685a27adc40511bb5756dfb3ada2e8578ee72e1
    curl https://raw.githubusercontent.com/kubernetes-sigs/windows-gmsa/$K8S_GMSA_DEPLOY_DOWNLOAD_REV/admission-webhook/deploy/deploy-gmsa-webhook.sh -o deploy-gmsa-webhook.sh && chmod +x deploy-gmsa-webhook.sh
    
    ./deploy-gmsa-webhook.sh --file ./gmsa-webhook.yml --namespace gmsa-webhook --overwrite
    rm -drf gmsa-webhook-certs
    

    이 스크립트는 gMSA 커스텀 리소스 정의(CRD) 매니페스트를 GKE 클러스터에 추가하고 Pod에 gMSA 사양을 제공하는 웹훅을 배포합니다. 이제 클러스터에 gMSA 사양을 저장하고 Pod 및 컨테이너에 대해 gMSA를 구성할 수 있습니다.

    Kubernetes 및 gMSA에 대한 자세한 내용은 Windows Pod 및 컨테이너에 대해 gMSA 구성을 참조하세요.

이제 gMSA를 사용해야 하는 Windows 애플리케이션을 실행하도록 GKE 클러스터가 준비되었습니다. 예를 들어 Windows Server 노드에서 ASP.NET 웹 애플리케이션을 실행할 수 있습니다. Windows 인증으로 사용자가 로그인하도록 애플리케이션을 구성하거나 애플리케이션에서 Pod의 gMSA를 사용하여 원격 네트워크 공유 또는 SQL Server 데이터베이스에 액세스할 수 있습니다.

Active Directory와 통합

이제 Active Directory에서 ASP.NET 웹 애플리케이션에 대해 gMSA를 만들고, 사용 방법 및 사용 주체를 구성한 후 해당 구성을 GKE에 추가합니다.

PowerShell 로그인 및 시작

  1. gmsa-dev-vm VM에 연결합니다.
  2. gMSA 만들기가 허용되는 Active Directory 계정을 사용하여 Windows에 로그인합니다.

    계정이 Domain Admins 그룹의 구성원이거나 msDS-GroupManagedServiceAccount 객체를 만들 수 있어야 합니다. 자세한 내용은 그룹 관리형 서비스 계정 프로비저닝을 참조하세요.

    관리형 Microsoft AD를 사용하는 경우 계정이 Cloud Service Managed Service Account Administrators 그룹의 구성원이어야 합니다. 자세한 내용은 관리형 서비스 계정 관리 위임을 참조하세요.

  3. 15를 입력하여 메뉴를 명령줄(PowerShell)로 종료합니다.

컨테이너 런타임 설치

Windows Server 2022에서 Windows 컨테이너를 만들고 실행하려면 Docker Community Edition(CE)과 같은 컨테이너 런타임이 필요합니다. Windows Server에 컨테이너 런타임을 설치하는 방법에 대한 자세한 내용은 Microsoft 문서의 시작하기: 컨테이너용 Windows 준비를 참조하세요.

windows-2019-core-for-containers 이미지를 사용하여 개발 VM을 만든 경우 이미지에 이미 Docker가 설치되어 있으므로 다음 절차를 건너뛸 수 있습니다.

  1. Docker Community Edition(CE)을 설치합니다.

    Invoke-WebRequest -UseBasicParsing -o install-docker-ce.ps1 `
       "https://raw.githubusercontent.com/microsoft/Windows-Containers/Main/helpful_tools/Install-DockerCE/install-docker-ce.ps1"
    .\install-docker-ce.ps1
    

    설치 프로세스 중에 원격 데스크톱 연결이 닫히면 VM에 다시 연결합니다.

  2. 설치 프로세스가 완료될 때까지 기다린 후 exit를 입력하여 새 PowerShell 창을 닫습니다.

  3. 15를 입력하여 메뉴를 명령줄(PowerShell)로 종료합니다.

KDS 루트 키 만들기

gMSA를 만들기 전에 Active Directory 도메인 컨트롤러에 주 배포 서비스(KDS) 루트 키가 있는지 확인해야 합니다. Active Directory는 KDS 루트 키를 사용하여 gMSA에 대해 비밀번호를 생성합니다.

관리형 Microsoft AD를 사용하는 경우 도메인을 만들 때 관리형 Microsoft AD가 KDS 루트 키를 자동으로 만들기 때문에 다음 절차를 건너뛸 수 있습니다.

  1. gmsa-dev-vm에서 Active Directory에 이미 KDS 루트 키가 있는지 확인합니다.

    Get-KdsRootKey
    

    이 명령어는 키 ID가 존재할 경우 이를 표시합니다.

  2. 응답으로 키 ID가 표시되지 않으면 키를 만듭니다.

    Add-KdsRootKey -EffectiveTime ((get-date).addhours(-10))
    

gMSA 만들기

gMSA를 만들 때는 gMSA에 대해 액세스 권한을 갖는 컴퓨터 이름을 제공해야 합니다. 보안 권장사항에 따라 애플리케이션이 실행되는 인스턴스에만 gMSA에 대해 권한을 부여해야 합니다. 도메인에 조인된 Windows Server 노드 풀을 만들면 노드 풀의 컴퓨터에 대해 새로운 Active Directory 그룹이 생성됩니다. 그룹 이름은 GKE가 노드 풀에 대해 만드는 관리형 인스턴스 그룹(MIG)의 이름과 일치합니다.

  1. PowerShell에서 Google Cloud 프로젝트 ID, 클러스터이름, Windows 노드 풀 이름, gMSA 이름, AD 도메인 이름에 대한 변수를 설정합니다.

    $ProjectId = "PROJECT-ID"
    $GkeClusterName = "cluster-1"
    $PermittedNodePool = "windows-server-pool"
    $GmsaName = "WebApp-01"
    $AdDomain = (Get-ADDomain).DNSRoot
    

    PROJECT-ID를 Google Cloud 프로젝트 ID로 바꿉니다.

  2. gcloud 도구에 대해 클러스터 구성을 설정합니다.

    gcloud config set project $ProjectId
    gcloud config set compute/zone "ZONE-NAME"
    

    ZONE-NAME을 GKE 클러스터를 배포한 영역으로 바꿉니다.

  3. 노드 풀에 대해 생성된 Active Directory 그룹의 도메인 이름을 검색합니다.

    $InstanceGroupUri = gcloud container node-pools describe $PermittedNodePool `
        --cluster $GkeClusterName `
        --format="value(instanceGroupUrls)"
    $InstanceGroupName=([System.Uri]$instanceGroupUri).Segments[-1]
    $GroupDN=(Get-ADGroup -Filter "name -eq '$InstanceGroupName'")
    
    Write-Host $GroupDN.DistinguishedName
    
  4. gMSA를 만듭니다.

    New-ADServiceAccount -Name $GmsaName `
    -DNSHostName "$GmsaName.$AdDomain" `
    -PrincipalsAllowedToRetrieveManagedPassword $GroupDN
    
  5. gMSA가 생성되었는지 확인합니다.

    Get-ADServiceAccount -Identity $GmsaName
    

    gMSA가 생성되었으면 출력이 다음과 비슷합니다.

    DistinguishedName : CN=WebApp01,CN=Managed Service Accounts,DC=corp,DC=example,DC=com
    Enabled           : True
    Name              : WebApp01
    ObjectClass       : msDS-GroupManagedServiceAccount
    ObjectGUID        : 5afcff45-cf15-467d-aaeb-d65e53288253
    SamAccountName    : WebApp01$
    SID               : S-1-5-21-780151012-601164977-3226406772-2103
    UserPrincipalName :
    

GKE에 gMSA 추가

Kubernetes 클러스터에서 gMSA를 사용하려면 Kubernetes에서 gMSA 리소스를 만들고 이를 사용하도록 허용된 네임스페이스 및 계정을 구성해야 합니다.

  1. gmsa-dev-vm의 PowerShell에서 git 도구를 설치합니다.

    Install-Script -Name Install-Git -Force
    Install-Git.ps1
    $env:Path += ";c:\program files\git\bin"
    
  2. kubectl 도구를 설치합니다.

    $version = (Invoke-WebRequest -UseBasicParsing -Uri "https://dl.k8s.io/release/stable.txt").Content
    $uri = "https://dl.k8s.io/release/$version/bin/windows/amd64/kubectl.exe"
    New-Item -Type Directory $env:ProgramFiles\kubectl
    Start-BitsTransfer -Source $uri -Destination $env:ProgramFiles\kubectl\
    $env:Path += ";$env:ProgramFiles\kubectl"
    
  3. gke-gcloud-auth-plugin 바이너리를 설치합니다.

    gcloud components install gke-gcloud-auth-plugin
    

    설치 프로세스가 완료될 때까지 몇 분 정도 기다립니다.

  4. GKE 클러스터의 사용자 인증 정보로 kubectl 도구를 초기화합니다.

    gcloud container clusters get-credentials $GkeClusterName
    
  5. gMSA 사용자 인증 정보 사양 파일을 만듭니다.

    Install-Module CredentialSpec -Force
    $GmsaName = $GmsaName.ToLower()
    $CredSpecFile = Join-Path $env:TEMP "$GmsaName-credspec.json"
    New-CredentialSpec -AccountName $GmsaName -Path $CredSpecFile
    
    $CredentialsSpec=@{
    "apiVersion" = "windows.k8s.io/v1";
    "kind" = "GMSACredentialSpec";
    "metadata" = @{"name" = $GmsaName}
    "credspec" = (Get-Content $CredSpecFile | ConvertFrom-Json)
    }
    
    $CredentialsSpec | ConvertTo-Json -Depth 5 | Set-Content $CredSpecFile
    

    Kubernetes에서 GMSACredentialSpec 리소스 이름에는 소문자가 사용되어야 합니다.

    이 스크립트는 이 제한 사항을 준수하기 위해 $GmsaName 변수의 대소문자를 변경합니다.

    관리형 서비스 계정 테스트가 실패했다는 경고 메시지가 스크립트에 표시됩니다. 이것은 예상된 동작입니다. 개발 VM이 gMSA에 할당된 그룹의 구성원이 아니므로, VM에서 gMSA를 테스트할 수 없습니다. 이 경고 메시지는 명령어가 gMSA 사용자 인증 정보 사양을 생성하는 것을 방해하지 않습니다.

  6. GKE 클러스터에 gMSA 사용자 인증 정보 사양을 추가합니다.

    kubectl apply -f $CredSpecFile
    
  7. GitHub 저장소를 클론합니다.

    git clone https://github.com/GoogleCloudPlatform/gke-aspnet-gmsa.git
    cd gke-aspnet-gmsa
    
  8. 클러스터에 gMSA RBAC 객체를 추가합니다.

    kubectl apply -f gmsa-rbac-webapp-01.yaml
    

    gmsa-rbac-webapp-01.yaml은 gMSA에 대한 ClusterRole RBAC 객체를 만든 다음 default 네임스페이스의 기본 서비스 계정에 새 클러스터 역할을 바인딩합니다. 애플리케이션을 다른 네임스페이스에 배포하는 경우 gmsa-rbac-webapp-01.yaml 파일을 수정하고 역할 결합 및 서비스 계정의 네임스페이스를 변경합니다.

웹 애플리케이션 배포 및 사용

이제 웹 애플리케이션 및 컨테이너 이미지를 빌드하고, 새 컨테이너 이미지를 GKE 클러스터에 배포하고, 브라우저에서 웹 애플리케이션을 열어 웹 애플리케이션이 gMSA를 사용할 수 있는지 확인합니다.

ASP.NET 웹 애플리케이션 빌드 및 배포

  1. gmsa-dev-vm의 PowerShell에서 레지스트리 위치, 레지스트리 이름, 이미지 태그에 대한 변수를 설정합니다.

    $RegistryLocation = "LOCATION-docker.pkg.dev"
    $ProjectsRegistry = "$RegistryLocation/$ProjectId"
    $ImageTag = "$ProjectsRegistry/windows-container-images/test-gmsa:latest"
    

    LOCATION을 Artifact Registry 저장소를 만든 위치로 바꿉니다.

  2. 컨테이너 이미지를 빌드합니다.

    docker build -t $ImageTag -f Dockerfile-WINDOWS_LTSC2022 .
    

    Windows Server 2019의 컨테이너 이미지를 빌드하려면 -f 매개변수 값을 Dockerfile-WINDOWS_LTSC2019로 설정합니다.

  3. 컨테이너 이미지를 Artifact Registry에 푸시합니다.

    gcloud auth configure-docker $RegistryLocation --quiet
    docker push $ImageTag
    
  4. 애플리케이션의 YAML 파일을 다운로드하고 이를 gMSA 구성으로 업데이트합니다.

    $ApplicationYaml = Join-Path $env:TEMP "gmsa-test-webapp-01.yaml"
    
    (Get-Content gmsa-test-webapp-01.yaml.template) `
    -Replace '\${image_path}',$ImageTag | `
    Set-Content $ApplicationYaml
    

    GKE에서 Windows Server 2019 노드를 만드는 경우 애플리케이션의 YAML 파일을 수정하고 cloud.google.com/gke-windows-os-version 값을 2022에서 2019로 변경합니다.

  5. 웹 애플리케이션을 GKE 클러스터에 배포합니다.

    kubectl apply -f $ApplicationYaml
    

ASP.NET 웹 애플리케이션이 실행 중인지 확인

웹 애플리케이션은 LoadBalancer 서비스를 사용하여 인터넷에 노출됩니다. 웹 애플리케이션으로 브라우징하려면 먼저 Pod 및 서비스가 배포될 때까지 기다려야 합니다. Windows Server 핵심 컨테이너 이미지가 크고(웹 애플리케이션 이미지가 7GB보다 큼) 노드가 이미지를 다운로드하고 컨테이너를 만들려면 시간이 걸리기 때문에 Pod를 배포하는 데 몇 분 정도 걸릴 수 있습니다.

  1. Pod 상태를 확인합니다.

    kubectl get pods --selector=app=gmsa-test-webapp-01
    

    출력에 포드 상태가 Running으로 표시될 때까지 명령어를 반복합니다.

    NAME                                   READY     STATUS    RESTARTS   AGE
    gmsa-test-webapp-01-76c6d64975-zrtgq   1/1       Running   0          28s
    

    포드 상태가 Pending으로 유지되고 ContainerCreating 또는 Running으로 바뀌지 않으면 Windows 노드의 소스 이미지를 보고 Windows Server 2022인지 확인합니다. 또한 버전 매핑 테이블을 보고 Windows Server 버전에 대한 GKE 버전 매핑 방법을 확인할 수 있습니다. 버전이 일치하지 않으면 Dockerfile-WINDOWS_LTSC2022 파일을 복제하고, 새 파일의 기본 컨테이너 이미지를 노드의 Windows Server 버전과 일치하도록 설정합니다. 그런 다음 ASP.NET 웹 애플리케이션 빌드 및 배포 단계를 반복합니다.

  2. 서비스 상태를 확인합니다.

    kubectl get service --selector=app=gmsa-test-webapp-01
    

    서비스에 외부 IP 주소가 포함된 것이 결과로 표시될 때까지 명령어를 반복합니다.

    NAME                   TYPE           CLUSTER-IP    EXTERNAL-IP      PORT(S)        AGE
    gmsa-test-webapp-01    LoadBalancer   10.44.2.112   external-ip    80:32233/TCP   17s
    
  3. 출력의 external-ip 값을 기록해 둡니다. 이 값은 나중에 필요합니다.

ASP.NET 웹 애플리케이션에서 예비 테스트 실행

Pod가 이제 실행되고 네트워크 부하 분산기를 통해 인터넷에서 액세스될 수 있습니다. 이제 예비 테스트를 실행하여 컨테이너가 성공적으로 배포되었고 gMSA 사용 권한이 있는지 확인합니다.

  1. 브라우저에서 http://EXTERNAL-IP로 이동하여 gMSA 테스트 웹 애플리케이션을 확인합니다.

    EXTERNAL-IP를 이전 절차에서 가져온 IP 주소로 바꿉니다.

  2. 실행 전 검사 섹션으로 스크롤한 후 실행 전 검사 실행 버튼을 클릭하여 모든 테스트가 통과되었는지 확인합니다.

    테스트가 통과되면 출력이 다음과 같이 표시됩니다.

    [PASS]  Active Directory RSAT PowerShell Module Installed
    
    [PASS]  IIS Document Root found
            C:\inetpub\wwwroot\
    
    [PASS]  PowerShell Scripts Folder found
            C:\inetpub\wwwroot\Powershell\
    
    [PASS]  Container Diagnostic Script found
            C:\inetpub\wwwroot\Powershell\\containerDiag.ps1
    
    [PASS]  Domain Diagnostic Script found
            C:\inetpub\wwwroot\Powershell\\domainDiag.ps1
    
    [RES]   Result: PASS   All checks passed! Please proceed to run the different tests.
    
  3. 컨테이너 정보 섹션으로 스크롤한 후 스크립트 실행 버튼을 클릭합니다. 컨테이너 및 노드에 대한 정보가 표시되고 오류가 표시되지 않는지 확인합니다.

Windows 컨테이너에서 gMSA 사용

이제 웹 애플리케이션에서 여러 테스트를 실행하여 gMSA 설정이 올바르게 작동하는지 확인할 수 있습니다. 각 테스트는 서로 다른 목적에 따라 gMSA를 사용합니다. 모든 테스트가 성공하면 gMSA가 올바르게 구성된 것입니다.

gMSA 컨테이너 구성 검증

  • 도메인 연결 섹션으로 스크롤하고 계정 이름 상자에 gMSA(WebApp-01) 이름을 입력한 후 스크립트 실행을 클릭합니다. 테스트가 완료될 때까지 몇 초 정도 기다립니다.

    출력은 다음과 비슷합니다.

    *****   C O N T A I N E R   D I A G N O S T I C S   *****
    
    [INFO]  Starting script execution at 01-05-2021-13:53:11
    
    [INFO]  Using gMSA: WebApp-01
    
    [PASS]  gMSA Account found in Active Directory
            CN=WebApp01,CN=Managed Service Accounts,DC=corp,DC=example,DC=com
    
    [PASS]  This Container (gmsa-test-webapp01-5bc485b8d5-9lbb7) is running on a GKE Windows Node that is authorized to use WebApp01
    
    [INFO]  Script execution complete at 01-05-2021-13:53:12
    
    *****      E N D   O F   D I A G N O S T I C S      *****
    

    이 스크립트는 2개의 PowerShell cmdlet을 사용하여 gMSA에 대한 액세스를 테스트합니다.

    • Get-ADServiceAccount: 이 cmdlet은 gMSA에 대해 정보를 검색합니다. 이 cmdlt이 성공적으로 실행되면 컨테이너가 올바른 gMSA로 실행되고 있는 것입니다.
    • Test-ADServiceAccount: 이 cmdlet은 gMSA 사용자 인증 정보를 검색할 수 있는지 테스트합니다. cmdlt이 성공적으로 실행되면 컨테이너가 gMSA 사용자 인증 정보에 액세스하도록 허용된 Windows Server 노드에서 실행되고 있는 것입니다.

Windows 인증을 사용하여 사용자 로그인

  1. 페이지의 위쪽 탐색 메뉴에서 로그인을 클릭합니다.
  2. 사용자 인증 정보를 입력하라는 메시지가 표시되면 도메인 사용자 이름과 비밀번호를 입력합니다.
  3. 계정 정보가 포함된 보안 페이지가 표시되고 사용자 인증 정보를 묻는 메시지가 표시되지 않으면 브라우저에서 사용자의 현재 ID를 사용하여 사용자가 자동으로 로그인된 것입니다.

    인증된 후에는 보안 페이지가 표시됩니다. 다음 세 가지 섹션을 확인하세요.

    • 사용자 정보: 사용된 인증 유형 및 사용자 이름을 표시합니다.
    • 그룹: 사용자가 속한 그룹의 목록을 표시합니다. 목록의 그룹 이름은 Active Directory에서 검색됩니다.
    • 사용자 클레임: 로그인 중 Active Directory에서 제공된 사용자의 클레임 목록을 표시합니다. 그룹 멤버십 클레임은 해당 이름이 아닌 Active Directory 그룹 SID를 보여줍니다.

통합 Windows 인증 지원 외에도 ASP.NET 웹 애플리케이션은 원격 서버를 호출할 때 인증에 gMSA를 사용할 수 있습니다. 웹 애플리케이션 및 Windows 컨테이너에서 실행되는 모든 기타 애플리케이션은 gMSA를 사용하여 SQL Server 인스턴스 및 SMB 기반 네트워크 공유와 같이 Windows 인증이 필요한 네트워크의 리소스에 액세스할 수 있습니다.

문제 해결

설정 프로세스 중 또는 웹 애플리케이션을 테스트하는 동안 오류 메시지가 발생하면 다음 문제 해결 페이지를 참조하세요.

프로덕션 애플리케이션의 추가 고려사항

다음 안내는 이 튜토리얼의 목적에 맞게 최적의 경로를 제공하기 위해 작성되었습니다. 프로덕션 환경의 경우 다음 섹션에 설명된 것과 같이 더 강력한 결과를 얻을 수 있도록 일부 프로시져를 변경해야 할 수 있습니다.

Windows Server 노드 풀 고려사항

gMSA를 사용하는 고유 애플리케이션을 배포할 계획이고 애플리케이션이 클라이언트 세션을 지원할 경우, 노드 풀에서 최소 2개 이상의 노드를 만드는 것이 좋습니다. 노드가 여러 개 있으면 프로세스 외부 세션 스토리지를 사용하여 애플리케이션이 분산된 세션을 올바르게 처리할 수 있는지 확인할 수 있습니다.

이 튜토리얼에서는 애플리케이션을 호스팅하기 위해 단일 Windows Server 노드 풀을 만듭니다. 하지만 한 노드 풀에 HDD 영구 디스크(PD)가 있고 다른 노드 풀에 SSD PD가 있는 경우와 같이 클러스터에서 Windows Server 노드 풀을 여러 개 만들어야 할 수 있습니다. 애플리케이션을 여러 노드 풀에 배포해야 할 경우 New-ADServiceAccount cmdlet을 사용하여 gMSA를 만들 때 Active Directory 그룹 객체를 PrincipalsAllowedToRetrieveManagedPassword 매개변수에 제공합니다.

gMSA 및 보안 주체 이름(SPN) 고려사항

ID 위임 지원과 같이 애플리케이션에서 Kerberos를 사용하여 사용자를 인증해야 할 경우에는 커스텀 DNS를 사용하여 애플리케이션에 액세스하고 서비스 주체 이름(SPN)으로 gMSA를 구성해야 합니다. 예를 들어 부하 분산기가 https://my-web-app/을 통해 GKE에서 애플리케이션을 노출하는 경우 다음 방법 중 하나로 HTTP/my-web-app이라는 SPN을 만들어야 합니다.

  • 새 gMSA에 대해 필요한 SPN으로 gMSA를 만듭니다. 예를 들면 다음과 같습니다.

    New-ADServiceAccount -Name $GmsaName `
    -DNSHostName "$GmsaName.$AdDomain" `
    -PrincipalsAllowedToRetrieveManagedPassword $Groups `
    -ServicePrincipalNames "HTTP/my-web-app", "HTTP/my-web-app.$AdDomain"
    
  • 기존 gMSA의 경우 Set-ADServiceAccount를 호출하여 필요한 SPN을 gMSA에 추가합니다. 예를 들면 다음과 같습니다.

    Set-ADServiceAccount $GmsaName -ServicePrincipalNames @{Add="HTTP/my-web-app", "HTTP/my-web-app.$AdDomain"}
    

DNS 구성에 따라 HTTP/www.my-web-appHTTP/www.my-web-app.$AdDomain에 대해 SPN을 만들어야 할 수도 있습니다.

TCP 바인딩 및 Windows 인증으로 구성된 WCF 서비스와 같이 비HTTP 프로토콜의 경우 HOST/ SPN과 같은 다른 유형의 SPN을 만들어야 할 수 있습니다.

IIS 애플리케이션 풀 ID 선택

ASP.NET 웹 애플리케이션은 IIS 웹 서버의 Windows에서 실행됩니다. IIS에서 동일한 프로세스를 공유하는 웹 애플리케이션의 그룹을 구성합니다. 이 그룹을 애플리케이션 풀이라고 부릅니다. 각 애플리케이션 풀은 w3wp라는 전용 프로세스에서 호스팅됩니다. IIS 애플리케이션 풀은 프로세스가 32비트 또는 64비트 프로세스인지 여부와 같은 프로세스 구성을 제공하며, 프로세스의 ID를 제공합니다. Windows 컨테이너에서 웹 애플리케이션을 실행할 때 기본 제공되는 네트워크 서비스 계정을 사용하도록 애플리케이션 풀의 프로세스 ID를 설정합니다.

IIS에서도 지원되는 로컬 애플리케이션 풀 ID 계정은 Windows 컨테이너에 필요하지 않습니다. 애플리케이션 풀 ID 계정은 동일한 IIS 인스턴스에서 여러 웹 애플리케이션을 실행할 때 로컬 보안 경계를 강제 적용하기 위한 방법으로 IIS에서 생성되었습니다. 각 웹 애플리케이션이 개별 컨테이너에 호스팅되는 Windows 컨테이너가 있으면 컨테이너 자체가 보안 경계를 제공하기 때문에 컨테이너 내에서 보안 경계를 만들 필요가 없습니다.

애플리케이션 풀 ID가 네트워크 서비스 계정을 사용하도록 구성된 경우에도 애플리케이션이 인증이 필요한 외부 리소스를 요청하는 경우, 애플리케이션은 Windows 컨테이너에 대해 구성된 gMSA를 사용하여 인증을 수행합니다.

정리

이 가이드에서 사용된 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 리소스가 포함된 프로젝트를 삭제하거나 프로젝트를 유지하고 개별 리소스를 삭제하세요.

  1. Google Cloud 콘솔에서 리소스 관리 페이지로 이동합니다.

    리소스 관리로 이동

  2. 프로젝트 목록에서 삭제할 프로젝트를 선택하고 삭제를 클릭합니다.
  3. 대화상자에서 프로젝트 ID를 입력한 후 종료를 클릭하여 프로젝트를 삭제합니다.

개별 리소스 삭제

Google Cloud 프로젝트를 유지하지만 이 튜토리얼에서 만든 Google Cloud 리소스를 삭제하길 원하지 않으면 리소스를 개별적으로 삭제할 수 있습니다.

Active Directory 변경사항 되돌리기

  1. 개발 VM에 연결하고 Active Directory 도메인에 대해 관리 액세스 권한이 있는 사용자로 로그인합니다.
  2. gmsa-dev-vm VM에서 PowerShell이 아직 열려 있지 않으면 이를 엽니다.

    PowerShell
    
  3. gMSA를 삭제합니다.

    Remove-ADServiceAccount -Identity "WebApp-01" -Confirm:$false
    

클라우드 리소스 삭제

  1. Google Cloud 콘솔에서 Cloud Shell을 활성화합니다.

    Cloud Shell 활성화

  2. gcloud 환경을 초기화합니다.

    gcloud config set project PROJECT-ID
    gcloud config set compute/zone ZONE-NAME
    gcloud config set artifacts/location LOCATION
    

    다음을 바꿉니다.

    • PROJECT-ID: Google Cloud 프로젝트 ID입니다.
    • ZONE-NAME: GKE 클러스터 및 개발 VM을 배포한 영역입니다.
    • LOCATION: Artifact Registry 저장소를 배포한 리전입니다.
  3. 개발 VM을 삭제합니다.

    gcloud compute instances delete gmsa-dev-vm --quiet
    
  4. 서비스 계정을 삭제합니다.

    gcloud iam service-accounts delete dev-vm@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com --quiet
    
  5. GKE 클러스터를 삭제합니다.

    gcloud container clusters delete cluster-1 --quiet
    
  6. Active Directory 컨트롤러에 대해 방화벽 규칙을 만들었으면 이를 삭제합니다.

    gcloud compute firewall-rules delete allow-gke-pods-to-ad --quiet
    
  7. Artifact Registry Docker 저장소를 삭제합니다.

    gcloud artifacts repositories delete windows-container-images --quiet
    

완료하려면 VM이 도메인에 자동 조인되도록 Active Directory 구성의 삭제 단계를 수행합니다.

다음 단계