AKS(Azure Kubernetes Service) 클러스터의 Windows Server 노드에 대해 GMSA(그룹 관리 서비스 계정) 사용

GMSA(그룹 관리 서비스 계정)는 자동 암호 관리, 간소화된 SPN(서비스 사용자 이름) 관리 및 다른 관리자에게 관리를 위임하는 기능을 제공하는 관리되는 도메인 계정입니다. AKS(Azure Kubernetes Service)를 사용하면 Windows 서버 노드에서 GMSA를 사용하도록 설정하는 기능을 제공하므로 Windows 서버 노드에서 실행되는 컨테이너를 GMSA와 통합하고 관리할 수 있습니다.

필수 조건

  • Kubernetes 1.19 이상. 버전을 확인하려면 사용 가능한 업그레이드 확인을 참조하세요. 버전을 업그레이드하려면 AKS 클러스터 업그레이드를 참조하세요.
  • Azure CLI 버전 2.35.0 이상 az --version을 실행하여 버전을 찾습니다. 설치 또는 업그레이드해야 하는 경우 Azure CLI 설치를 참조하세요.
  • AKS 클러스터에서 사용되는 관리 ID입니다.
  • Azure Key Vault를 만들거나 업데이트할 수 있는 권한입니다.
  • Active Directory 도메인 서비스 또는 온-프레미스 Active Directory에서 GMSA를 구성할 수 있는 권한입니다.
  • 도메인 컨트롤러는 Active Directory 웹 서비스를 사용하도록 설정해야 하며 AKS 클러스터에서 포트 9389에서 연결할 수 있어야 합니다.

참고 항목

Microsoft는 AKS에서 gMSA를 구성하기 위한 특별히 빌드된 PowerShell 모듈도 제공합니다. 자세한 내용은 Azure Container Service에 대한 gMSA를 참조하세요.

Active Directory 도메인 컨트롤러에서 GMSA 구성

AKS에서 GMSA를 사용하려면 도메인 컨트롤러에 구성된 GMSA 자격 증명에 액세스하려면 표준 도메인 사용자 자격 증명이 필요합니다. 도메인 컨트롤러에서 GMSA를 구성하려면 그룹 관리 서비스 계정 시작을 참조하세요. 표준 도메인 사용자 자격 증명의 경우 GMSA 자격 증명에 대한 액세스 권한이 있는 한 기존 사용자를 사용하거나 새 사용자를 만들 수 있습니다.

Important

Active Directory 도메인 서비스 또는 온-프레미스 Active Directory를 사용해야 합니다. 현재는 Microsoft Entra ID를 사용하여 AKS 클러스터가 포함된 GMSA를 구성할 수 없습니다.

Azure Key Vault에 표준 도메인 사용자 자격 증명 저장

AKS 클러스터는 표준 도메인 사용자 자격 증명을 사용하여 도메인 컨트롤러에서 GMSA 자격 증명에 액세스합니다. AKS 클러스터 자격 증명에 대한 보안 액세스를 제공하려면 해당 자격 증명을 Azure Key Vault에 저장해야 합니다.

  1. Azure Key Vault가 아직 없는 경우 az keyvault create 명령을 사용하여 만듭니다.

    az keyvault create --resource-group myResourceGroup --name myGMSAVault
    
  2. az keyvault secret set 명령을 사용하여 표준 도메인 사용자 자격 증명을 키 자격 증명 모음에 비밀로 저장합니다. 다음 예제에서는 myGMSAVault 키 자격 증명 모음에 키 GMSADomainUserCred를 사용하여 도메인 사용자 자격 증명을 저장합니다.

    az keyvault secret set --vault-name myGMSAVault --name "GMSADomainUserCred" --value "$Domain\\$DomainUsername:$DomainUserPassword"
    

    참고 항목

    도메인에 대해 정규화된 도메인 이름을 사용해야 합니다.

선택 사항: 사용자 지정 DNS와 함께 사용자 지정 VNet 사용

AKS 클러스터에서 연결할 수 있도록 DNS를 통해 도메인 컨트롤러를 구성해야 합니다. 클러스터가 도메인 컨트롤러에 액세스할 수 있도록 AKS 클러스터 외부에서 네트워크 및 DNS를 구성할 수 있습니다. 또는 AKS 클러스터에서 Azure CNI를 사용하여 사용자 지정 DNS로 사용자 지정 VNET을 구성하여 도메인 컨트롤러에 대한 액세스를 제공할 수 있습니다. 자세한 내용은 AKS(Azure Kubernetes Service)에서 Azure CNI 네트워킹 구성을 참조하세요.

선택 사항: 둘 이상의 DNS 서버 구성

AKS 클러스터에서 Windows GMSA에 대해 둘 이상의 DNS 서버를 구성하려면 --gmsa-dns-server 또는 v--gmsa-root-domain-name을(를) 지정하지 마세요. 대신 사용자 지정 DNS를 선택하고 DNS 서버를 추가하여 VNet에 여러 DNS 서버를 추가할 수 있습니다.

선택 사항: 클러스터에 고유한 kubelet ID 사용

키 자격 증명 모음에 대한 AKS 클러스터 액세스를 제공하려면 클러스터 kubelet ID가 키 자격 증명 모음에 액세스해야 합니다. 기본값으로 관리 ID를 사용하도록 설정된 클러스터를 만들면 kubelet ID가 자동으로 만들어집니다.

다음 단계를 사용하여 클러스터를 만든 후 ID 키 자격 증명 모음에 대한 액세스 권한을 부여하거나 클러스터를 만들기 전에 사용할 고유한 ID를 만들 수 있습니다.

  1. az identity create 명령을 사용하여 kubelet ID를 만듭니다.

    az identity create --name myIdentity --resource-group myResourceGroup
    
  2. az identity list 명령을 사용하여 ID의 ID를 가져와서 MANAGED_ID 변수로 설정합니다.

    MANAGED_ID=$(az identity list --query "[].id" -o tsv)
    
  3. az keyvault set-policy 명령을 사용하여 키 자격 증명 모음에 대한 ID 액세스 권한을 부여합니다.

    az keyvault set-policy --name "myGMSAVault" --object-id $MANAGED_ID --secret-permissions get
    

새 AKS 클러스터에서 GMSA 사용

  1. 클러스터를 만드는 동안 사용할 관리자 자격 증명을 만듭니다. 다음 명령은 사용자 이름을 입력하라는 메시지를 표시하며 WINDOWS_USERNAME으로 설정한 후 이후 명령에서 사용합니다.

    echo "Please enter the username to use as administrator credentials for Windows Server nodes on your cluster: " && read WINDOWS_USERNAME 
    
  2. 다음 매개 변수와 함께 az aks create 명령을 사용하여 AKS 클러스터를 만듭니다.

    • --enable-managed-identity: 클러스터에 대한 관리 ID를 사용하도록 설정합니다.
    • --enable-windows-gmsa: 클러스터에 대해 GMSA를 사용하도록 설정합니다.
    • --gmsa-dns-server: DNS 서버의 IP 주소입니다.
    • --gmsa-root-domain-name: DNS 서버의 루트 도메인 이름입니다.
    DNS_SERVER=<IP address of DNS server>
    ROOT_DOMAIN_NAME="contoso.com"
    
    az aks create \
        --resource-group myResourceGroup \
        --name myAKSCluster \
        --vm-set-type VirtualMachineScaleSets \
        --network-plugin azure \
        --load-balancer-sku standard \
        --windows-admin-username $WINDOWS_USERNAME \
        --enable-managed-identity \
        --enable-windows-gmsa \
        --gmsa-dns-server $DNS_SERVER \
        --gmsa-root-domain-name $ROOT_DOMAIN_NAME
    

    참고 항목

    • 사용자 지정 VNet을 사용하는 경우 vnet-subnet-id 매개 변수를 사용하여 VNet ID를 지정해야 하며 구성에 따라 docker-bridge-address, dns-service-ipservice-cidr 매개 변수도 추가해야 할 수 있습니다.

    • kubelet ID에 고유한 ID를 만들었으면 assign-kubelet-identity 매개 변수를 사용하여 ID를 지정합니다.

    • --gmsa-dns-server--gmsa-root-domain-name 매개 변수를 지정하면 DNS 전달 규칙이 kube-system/coredns ConfigMap에 추가됩니다. 이 규칙은 $ROOT_DOMAIN_NAME의 DNS 요청을 Pod에서 $DNS_SERVER로 전달합니다.

      $ROOT_DOMAIN_NAME:53 {
          errors
          cache 30
          log
          forward . $DNS_SERVER
      }
      
  3. az aks nodepool add 명령을 사용하여 Windows Server 노드 풀을 추가합니다.

    az aks nodepool add \
        --resource-group myResourceGroup \
        --cluster-name myAKSCluster \
        --os-type Windows \
        --name npwin \
        --node-count 1
    

기존 클러스터에서 GMSA 사용

  • az aks update 명령을 사용하여 Windows Server 노드 및 관리 ID를 사용하도록 설정된 기존 클러스터에서 GMSA를 사용하도록 설정합니다.

    az aks update \
        --resource-group myResourceGroup \
        --name myAKSCluster \
        --enable-windows-gmsa \
        --gmsa-dns-server $DNS_SERVER \
        --gmsa-root-domain-name $ROOT_DOMAIN_NAME
    

kubelet ID의 키 자격 증명 모음에 대한 액세스 권한 부여

참고 항목

kubelet ID로 고유한 ID를 제공한 경우 이 단계를 건너뜁니다.

  • az keyvault set-policy 명령을 사용하여 kubelet ID의 키 자격 증명 모음에 대한 액세스 권한을 부여합니다.

    MANAGED_ID=$(az aks show -g myResourceGroup -n myAKSCluster --query "identityProfile.kubeletidentity.objectId" -o tsv)
    az keyvault set-policy --name "myGMSAVault" --object-id $MANAGED_ID --secret-permissions get
    

GMSA 자격 증명 사양 설치

  1. az aks get-credentials 명령을 사용하여 Kubernetes 클러스터에 연결하도록 kubectl을 구성합니다.

    az aks get-credentials --resource-group myResourceGroup --name myAKSCluster
    
  2. gmsa-spec.yaml이라는 새 YAML을 만들고 다음 YAML에 붙여넣습니다. 자리 표시자를 사용자의 값으로 바꿔야 합니다.

    apiVersion: windows.k8s.io/v1
    kind: GMSACredentialSpec
    metadata:
      name: aks-gmsa-spec  # This name can be changed, but it will be used as a reference in the pod spec
    credspec:
      ActiveDirectoryConfig:
        GroupManagedServiceAccounts:
        - Name: $GMSA_ACCOUNT_USERNAME
          Scope: $NETBIOS_DOMAIN_NAME
        - Name: $GMSA_ACCOUNT_USERNAME
          Scope: $DNS_DOMAIN_NAME
        HostAccountConfig:
          PluginGUID: '{CCC2A336-D7F3-4818-A213-272B7924213E}'
          PortableCcgVersion: "1"
          PluginInput: "ObjectId=$MANAGED_ID;SecretUri=$SECRET_URI"  # SECRET_URI takes the form https://$akvName.vault.azure.net/secrets/$akvSecretName
      CmsPlugins:
     - ActiveDirectory
      DomainJoinConfig:
        DnsName: $DNS_DOMAIN_NAME
        DnsTreeName: $DNS_ROOT_DOMAIN_NAME
        Guid:  $AD_DOMAIN_OBJECT_GUID
        MachineAccountName: $GMSA_ACCOUNT_USERNAME
        NetBiosName: $NETBIOS_DOMAIN_NAME
        Sid: $GMSA_SID
    

참고 항목

AKS는 릴리스 v20230903에서 GMSACredentialSpecapiVersion을(를) windows.k8s.io/v1alpha1에서 windows.k8s.io/v1(으)로 업그레이드했습니다.

  1. gmsa-role.yaml이라는 새 YAML을 만들고 다음 YAML에 붙여넣습니다.

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: aks-gmsa-role
    rules:
    - apiGroups: ["windows.k8s.io"]
      resources: ["gmsacredentialspecs"]
      verbs: ["use"]
      resourceNames: ["aks-gmsa-spec"]
    
  2. gmsa-role-binding.yaml이라는 새 YAML을 만들고 다음 YAML에 붙여넣습니다.

    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: allow-default-svc-account-read-on-aks-gmsa-spec
      namespace: default
    subjects:
    - kind: ServiceAccount
      name: default
      namespace: default
    roleRef:
      kind: ClusterRole
      name: aks-gmsa-role
      apiGroup: rbac.authorization.k8s.io
    
  3. kubectl apply 명령을 사용하여 gmsa-spec.yaml, gmsa-role.yamlgmsa-role-binding.yaml의 변경 내용을 적용합니다.

    kubectl apply -f gmsa-spec.yaml
    kubectl apply -f gmsa-role.yaml
    kubectl apply -f gmsa-role-binding.yaml
    

GMSA 설치 확인

  1. gmsa-demo.yaml이라는 새 YAML을 만들고 다음 YAML에 붙여넣습니다.

    ---
    kind: ConfigMap
    apiVersion: v1
    metadata:
      labels:
       app: gmsa-demo
      name: gmsa-demo
      namespace: default
    data:
      run.ps1: |
       $ErrorActionPreference = "Stop"
    
       Write-Output "Configuring IIS with authentication."
    
       # Add required Windows features, since they are not installed by default.
       Install-WindowsFeature "Web-Windows-Auth", "Web-Asp-Net45"
    
       # Create simple ASP.NET page.
       New-Item -Force -ItemType Directory -Path 'C:\inetpub\wwwroot\app'
       Set-Content -Path 'C:\inetpub\wwwroot\app\default.aspx' -Value 'Authenticated as <B><%=User.Identity.Name%></B>, Type of Authentication: <B><%=User.Identity.AuthenticationType%></B>'
    
       # Configure IIS with authentication.
       Import-Module IISAdministration
       Start-IISCommitDelay
       (Get-IISConfigSection -SectionPath 'system.webServer/security/authentication/windowsAuthentication').Attributes['enabled'].value = $true
       (Get-IISConfigSection -SectionPath 'system.webServer/security/authentication/anonymousAuthentication').Attributes['enabled'].value = $false
       (Get-IISServerManager).Sites[0].Applications[0].VirtualDirectories[0].PhysicalPath = 'C:\inetpub\wwwroot\app'
       Stop-IISCommitDelay
    
       Write-Output "IIS with authentication is ready."
    
       C:\ServiceMonitor.exe w3svc
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: gmsa-demo
      name: gmsa-demo
      namespace: default
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: gmsa-demo
      template:
        metadata:
          labels:
            app: gmsa-demo
        spec:
          securityContext:
            windowsOptions:
              gmsaCredentialSpecName: aks-gmsa-spec
          containers:
          - name: iis
            image: mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019
            imagePullPolicy: IfNotPresent
            command:
             - powershell
            args:
              - -File
              - /gmsa-demo/run.ps1
            volumeMounts:
              - name: gmsa-demo
                mountPath: /gmsa-demo
          volumes:
          - configMap:
              defaultMode: 420
              name: gmsa-demo
            name: gmsa-demo
          nodeSelector:
            kubernetes.io/os: windows
    ---
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        app: gmsa-demo
      name: gmsa-demo
      namespace: default
    spec:
      ports:
      - port: 80
        targetPort: 80
      selector:
        app: gmsa-demo
      type: LoadBalancer
    
  2. kubectl apply 명령을 사용하여 gmsa-demo.yaml 의 변경 내용을 적용합니다.

    kubectl apply -f gmsa-demo.yaml
    
  3. kubectl get service 명령을 사용하여 샘플 애플리케이션의 IP 주소를 가져옵니다.

    kubectl get service gmsa-demo --watch
    

    처음에 gmsa-demo 서비스의 EXTERNAL-IP은(는) 보류 중으로 표시됩니다.

    NAME               TYPE           CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
    gmsa-demo          LoadBalancer   10.0.37.27   <pending>     80:30572/TCP   6s
    
  4. EXTERNAL-IP 주소가 pending에서 실제 공용 IP 주소로 변경되면 CTRL-C를 사용하여 kubectl 감시 프로세스를 중지합니다.

    다음 예제 출력은 서비스에 할당된 유효한 공용 IP 주소를 보여줍니다.

    gmsa-demo  LoadBalancer   10.0.37.27   EXTERNAL-IP   80:30572/TCP   2m
    
  5. gmsa-demo 서비스의 외부 IP 주소로 웹 브라우저를 엽니다.

  6. $NETBIOS_DOMAIN_NAME\$AD_USERNAME 및 암호를 사용하여 인증하고 Authenticated as $NETBIOS_DOMAIN_NAME\$AD_USERNAME, Type of Authentication: Negotiate이(가) 표시되는지 확인합니다.

기존 클러스터에서 GMSA 사용 안 함

  • az aks update 명령을 사용하여 Windows Server 노드가 있는 기존 클러스터에서 GMSA를 사용하지 않도록 설정합니다.

    az aks update \
        --resource-group myResourceGroup \
        --name myAKSCluster \
        --disable-windows-gmsa 
    

참고 항목

az aks update 명령을 사용하여 기존 클러스터에서 GMSA를 다시 사용하도록 설정할 수 있습니다.

문제 해결

페이지를 로드할 때 인증 메시지가 표시되지 않습니다

페이지가 로드되지만 인증하라는 메시지가 표시되지 않으면 kubectl logs POD_NAME 명령을 사용하여 Pod의 로그를 표시하고 인증이 있는 IIS가 준비되었는지 확인합니다.

참고 항목

Windows 컨테이너는 기본적으로 kubectl에 로그를 표시하지 않습니다. Windows 컨테이너가 로그를 표시할 수 있도록 하려면 Windows 이미지에 로그 모니터 도구를 포함해야 합니다. 자세한 내용은 Windows 컨테이너 도구를 참조하세요.

페이지를 로드하려고 할 때 연결 시간 제한

페이지를 로드하려고 할 때 연결 시간 제한이 수신되면 샘플 앱이 kubectl get pods --watch 명령을 사용하여 실행 중인지 확인합니다. 샘플 앱 Pod가 실행되기 전에 샘플 앱 서비스에 대한 외부 IP 주소를 사용할 수 있는 경우가 있습니다.

Pod를 시작하지 못하고 Pod 이벤트에 winapi 오류가 표시됩니다

kubectl get pods --watch 명령을 실행하고 몇 분을 기다린 후 Pod가 시작되지 않으면 kubectl describe pod POD_NAME 명령을 사용합니다. Pod 이벤트에 winapi 오류가 표시되는 경우 GMSA 자격 증명 사양 구성에서 오류가 발생할 수 있습니다. gmsa-spec.yaml의 모든 대체 값이 올바른지 확인하고, kubectl apply -f gmsa-spec.yaml을(를) 다시 실행하고, 응용 프로그램 예제를 다시 배포합니다.

다음 단계