Windows 파드와 컨테이너용 GMSA 구성하기
Windows 파드와 컨테이너용 GMSA 구성하기 (Configure GMSA for Windows Pods and containers)
이 페이지는 Windows 노드에서 실행될 파드와 컨테이너에 대해 그룹 관리 서비스 계정(GMSA, Group Managed Service Accounts)을 구성하는 방법을 보여줘요. GMSA는 자동 비밀번호 관리, 단순화된 SPN(서비스 사용자 이름) 관리, 그리고 여러 서버에 걸쳐 다른 관리자에게 관리를 위임할 수 있는 기능을 제공하는 특정 유형의 Active Directory 계정이에요.
Kubernetes에서 GMSA 자격 증명 사양(credential spec)은 커스텀 리소스(Custom Resource)로 클러스터 전체 범위에 구성돼요. Windows 파드와 파드 안의 개별 컨테이너는 다른 Windows 서비스와 상호작용할 때 도메인 기반 기능(예: Kerberos 인증)에 GMSA를 사용하도록 구성할 수 있어요.
출처: 문서
본문
시작하기 전에
Kubernetes 클러스터가 있어야 하고 kubectl 명령줄 도구가 클러스터와 통신하도록 구성되어 있어야 해요. 클러스터에 Windows 워커 노드가 있어야 해요. 이 섹션은 각 클러스터마다 한 번씩 필요한 초기 단계를 다뤄요.
GMSACredentialSpec CRD 설치
GMSA 자격 증명 사양 리소스용 CustomResourceDefinition(CRD)이 GMSACredentialSpec 커스텀 리소스 유형을 정의하도록 클러스터에 구성되어야 해요. GMSA CRD YAML을 다운로드해 gmsa-crd.yaml로 저장해요. 그런 다음 kubectl apply -f gmsa-crd.yaml로 CRD를 설치해요.
GMSA 사용자를 검증하는 웹훅 설치
Pod 또는 컨테이너 수준에서 GMSA 자격 증명 사양 참조를 채우고 검증하려면 두 개의 웹훅이 Kubernetes 클러스터에 구성되어야 해요.
- 파드 사양에서 GMSA 참조(이름으로)를 전체 자격 증명 사양으로 확장해 파드 사양 안에 JSON 형식으로 넣는 mutating 웹훅
- 모든 GMSA 참조가 파드 서비스 계정이 사용하도록 승인되었는지 확인하는 validating 웹훅
위 웹훅과 관련 객체를 설치하려면 아래 단계가 필요해요.
- 인증서 키 쌍 생성(웹훅 컨테이너가 클러스터와 통신할 수 있게 함)
- 위 인증서로 시크릿 설치
- 핵심 웹훅 로직용 디플로이먼트 생성
- 디플로이먼트를 가리키는 validating과 mutating 웹훅 구성 생성
스크립트를 사용하면 위에서 언급한 GMSA 웹훅과 관련 객체를 배포·구성할 수 있어요. 스크립트는 --dry-run=server 옵션으로 실행해 클러스터에 가해질 변경 사항을 검토할 수 있어요.
스크립트가 사용하는 YAML 템플릿을 수동으로(매개변수를 적절히 치환해) 웹훅과 관련 객체를 배포하는 데 사용할 수도 있어요.
Active Directory에서 GMSA와 Windows 노드 구성
Kubernetes의 파드가 GMSA를 사용하도록 구성되기 전에, 원하는 GMSA를 Windows GMSA 문서에 설명된 대로 Active Directory에 프로비저닝해야 해요. Kubernetes 클러스터의 일부인 Windows 워커 노드는 Windows GMSA 문서에 설명된 대로 원하는 GMSA와 관련된 시크릿 자격 증명에 접근하도록 Active Directory에서 구성해야 해요.
GMSA 자격 증명 사양 리소스 생성
(앞서 설명한 대로) GMSACredentialSpec CRD를 설치한 상태에서, GMSA 자격 증명 사양을 담은 커스텀 리소스를 구성할 수 있어요. GMSA 자격 증명 사양은 시크릿이나 민감 데이터를 포함하지 않아요. 컨테이너 런타임이 컨테이너의 원하는 GMSA를 Windows에 설명하는 데 사용할 수 있는 정보예요. GMSA 자격 증명 사양은 유틸리티 PowerShell 스크립트로 YAML 형식으로 생성할 수 있어요.
GMSA 자격 증명 사양 YAML을 JSON 형식으로 수동 생성한 다음 변환하는 단계는 다음과 같아요.
- CredentialSpec 모듈 가져오기:
ipmo CredentialSpec.psm1 New-CredentialSpec으로 JSON 형식의 자격 증명 사양 만들기.WebApp1이라는 GMSA 자격 증명 사양을 만들려면New-CredentialSpec -Name WebApp1 -AccountName WebApp1 -Domain $(Get-ADDomain -Current LocalComputer)를 호출해요.Get-CredentialSpec으로 JSON 파일의 경로 표시.- credspec 파일을 JSON에서 YAML 형식으로 변환하고 Kubernetes에 구성할 수 있는 GMSACredentialSpec 커스텀 리소스가 되도록
apiVersion,kind,metadata,credspec헤더 필드를 적용.
다음 YAML 구성은 gmsa-WebApp1이라는 GMSA 자격 증명 사양을 설명해요.
apiVersion: windows.k8s.io/v1
kind: GMSACredentialSpec
metadata:
name: gmsa-WebApp1 # This is an arbitrary name but it will be used as a reference
credspec:
ActiveDirectoryConfig:
GroupManagedServiceAccounts:
- Name: WebApp1 # Username of the GMSA account
Scope: CONTOSO # NETBIOS Domain Name
- Name: WebApp1 # Username of the GMSA account
Scope: contoso.com # DNS Domain Name
CmsPlugins:
- ActiveDirectory
DomainJoinConfig:
DnsName: contoso.com # DNS Domain Name
DnsTreeName: contoso.com # DNS Domain Name Root
Guid: 244818ae-87ac-4fcd-92ec-e79e5252348a # GUID of the Domain
MachineAccountName: WebApp1 # Username of the GMSA account
NetBiosName: CONTOSO # NETBIOS Domain Name
Sid: S-1-5-21-2126449477-2524075714-3094792973 # SID of the Domain
위 자격 증명 사양 리소스는 gmsa-Webapp1-credspec.yaml로 저장하고 kubectl apply -f gmsa-Webapp1-credspec.yml로 클러스터에 적용할 수 있어요.
특정 GMSA 자격 증명 사양에 RBAC를 활성화하는 클러스터 역할 구성
각 GMSA 자격 증명 사양 리소스에 대해 클러스터 역할을 정의해야 해요. 이것은 보통 서비스 계정인 주체(subject)가 특정 GMSA 리소스에서 use 동사를 승인해요. 다음 예시는 위 gmsa-WebApp1 자격 증명 사양의 사용을 승인하는 클러스터 역할을 보여줘요. 파일을 gmsa-webapp1-role.yaml로 저장하고 kubectl apply -f gmsa-webapp1-role.yaml로 적용해요.
# Create the Role to read the credspec
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: webapp1-role
rules:
- apiGroups: ["windows.k8s.io"]
resources: ["gmsacredentialspecs"]
verbs: ["use"]
resourceNames: ["gmsa-WebApp1"]
특정 GMSA credspec을 사용하도록 서비스 계정에 역할 할당
파드가 구성될 서비스 계정을 위에서 만든 클러스터 역할에 바인딩해야 해요. 이렇게 하면 서비스 계정이 원하는 GMSA 자격 증명 사양 리소스를 사용할 수 있도록 승인돼요. 다음은 기본 서비스 계정을 webapp1-role 클러스터 역할에 바인딩해 위에서 만든 gmsa-WebApp1 자격 증명 사양을 사용하도록 하는 예시예요.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: allow-default-svc-account-read-on-gmsa-WebApp1
namespace: default
subjects:
- kind: ServiceAccount
name: default
namespace: default
roleRef:
kind: ClusterRole
name: webapp1-role
apiGroup: rbac.authorization.k8s.io
Pod 사양에서 GMSA 자격 증명 사양 참조 구성
securityContext.windowsOptions.gmsaCredentialSpecName Pod 사양 필드는 Pod 사양에서 원하는 GMSA 자격 증명 사양 커스텀 리소스에 대한 참조를 지정하는 데 사용돼요. 이것은 Pod 사양의 모든 컨테이너가 지정된 GMSA를 사용하도록 구성해요. gmsa-WebApp1을 참조하도록 어노테이션이 채워진 샘플 Pod 사양:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: with-creds
name: with-creds
namespace: default
spec:
replicas: 1
selector:
matchLabels:
run: with-creds
template:
metadata:
labels:
run: with-creds
spec:
securityContext:
windowsOptions:
gmsaCredentialSpecName: gmsa-webapp1
containers:
- image: mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019
imagePullPolicy: Always
name: iis
nodeSelector:
kubernetes.io/os: windows
Pod 사양의 개별 컨테이너도 컨테이너별 securityContext.windowsOptions.gmsaCredentialSpecName 필드로 원하는 GMSA credspec을 지정할 수 있어요. 예를 들어:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: with-creds
name: with-creds
namespace: default
spec:
replicas: 1
selector:
matchLabels:
run: with-creds
template:
metadata:
labels:
run: with-creds
spec:
containers:
- image: mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019
imagePullPolicy: Always
name: iis
securityContext:
windowsOptions:
gmsaCredentialSpecName: gmsa-Webapp1
nodeSelector:
kubernetes.io/os: windows
(위에 설명된 대로) GMSA 필드가 채워진 Pod 사양을 클러스터에 적용하면 다음 이벤트 순서가 일어나요.
- mutating 웹훅이 GMSA 자격 증명 사양 리소스에 대한 모든 참조를 GMSA 자격 증명 사양의 내용으로 해석·확장해요.
- validating 웹훅이 파드와 연결된 서비스 계정이 지정된 GMSA 자격 증명 사양에서
use동사에 대해 승인되었는지 확인해요. - 컨테이너 런타임이 각 Windows 컨테이너를 지정된 GMSA 자격 증명 사양으로 구성해, 컨테이너가 Active Directory에서 GMSA의 신원을 맡고 그 신원으로 도메인의 서비스에 접근할 수 있게 해요.
호스트 이름 또는 FQDN으로 네트워크 공유 인증
파드에서 호스트 이름 또는 FQDN으로 SMB 공유에 연결하는 데 문제가 있지만 IPv4 주소로는 공유에 접근할 수 있다면, Windows 노드에서 다음 레지스트리 키가 설정되어 있는지 확인해요.
reg add "HKLM\SYSTEM\CurrentControlSet\Services\hns\State" /v EnableCompartmentNamespace /t REG_DWORD /d 1
그런 다음 실행 중인 파드를 다시 생성해 동작 변경을 적용해야 해요. 이 레지스트리 키가 사용되는 방법에 대한 더 많은 정보는 여기에서 찾을 수 있어요.
문제 해결 (Troubleshooting)
환경에서 GMSA를 동작시키는 데 어려움이 있다면 몇 가지 문제 해결 단계를 수행할 수 있어요.
먼저 credspec이 파드에 전달되었는지 확인해요. 이렇게 하려면 파드 중 하나에 exec로 들어가 nltest.exe /parentdomain 명령의 출력을 확인해야 해요.
아래 예시에서 파드는 credspec을 올바르게 받지 못했어요.
kubectl exec -it iis-auth-7776966999-n5nzr powershell.exe
nltest.exe /parentdomain이 다음 오류를 나타내요.
Getting parent domain failed: Status = 1722 0x6ba RPC_S_SERVER_UNAVAILABLE
파드가 credspec을 올바르게 받았다면, 다음으로 도메인과의 통신을 확인해요. 먼저 파드 안에서 nslookup을 빠르게 해 도메인의 루트를 찾아요.
이것은 3가지를 알려줘요.
- 파드가 도메인 컨트롤러(DC)에 도달할 수 있음
- DC가 파드에 도달할 수 있음
- DNS가 올바르게 동작함
DNS와 통신 테스트를 통과했다면, 다음으로 파드가 도메인과 보안 채널(secure channel) 통신을 수립했는지 확인해야 해요. 이렇게 하려면 다시 파드에 exec로 들어가 nltest.exe /query 명령을 실행해요.
nltest.exe /query
다음 출력이 나와요.
I_NetLogonControl failed: Status = 1722 0x6ba RPC_S_SERVER_UNAVAILABLE
이것은 어떤 이유로 파드가 credspec에 지정된 계정으로 도메인에 로그온할 수 없었다는 것을 말해줘요. 다음 명령을 실행해 보안 채널을 복구할 수 있어요.
nltest /sc_reset:domain.example
명령이 성공하면 다음과 비슷한 출력을 보게 돼요.
Flags: 30 HAS_IP HAS_TIMESERV
Trusted DC Name \\dc10.domain.example
Trusted DC Connection Status Status = 0 0x0 NERR_Success
The command completed successfully
위 작업이 오류를 바로잡았다면, Pod 사양에 다음 라이프사이클 훅을 추가해 이 단계를 자동화할 수 있어요. 오류를 바로잡지 못했다면 credspec을 다시 살펴보고 정확하고 완전한지 확인해야 해요.
image: registry.domain.example/iis-auth:1809v1
lifecycle:
postStart:
exec:
command: ["powershell.exe","-command","do { Restart-Service -Name netlogon } while ( $($Result = (nltest.exe /query); if ($Result -like '*0x0 NERR_Success*') {return $true} else {return $false}) -eq $false)"]
imagePullPolicy: IfNotPresent
Pod 사양에 위 라이프사이클 섹션을 추가하면, 파드는 nltest.exe /query 명령이 오류 없이 종료될 때까지 나열된 명령을 실행해 netlogon 서비스를 재시작해요.