Habilitar GMSA (Contas de Serviço Gerenciado de Grupo) para seus nós do Windows Server no cluster do AKS (Serviço de Kubernetes do Azure)
Uma GMSA (Conta de Serviço Gerenciado de Grupo) é uma conta de domínio gerenciado para vários servidores que fornece gerenciamento automático de senhas, gerenciamento de SPN (nome da entidade de serviço) simplificado e a capacidade de delegar o gerenciamento para outros administradores. O AKS fornece a capacidade de habilitar o GMSA em seus nós do Windows Server, o que permite que os contêineres em execução em nós do Windows Server se integrem e sejam gerenciados pelo GMSA.
Pré-requisitos
A habilitação do GMSA com nós do Windows Server no AKS exige:
- Kubernetes 1.19 ou posterior.
- CLI do Azure versão 2.35.0 ou superior
- Identidades gerenciadas com o seu cluster do AKS.
- Permissões para criar ou atualizar um Azure Key Vault.
- Permissões para configurar o GMSA no Domínio do Active Directory ou no Active Directory local.
- O controlador de domínio precisa ter os Serviços Web do Active Directory habilitados e precisa estar acessível na porta 9389 pelo cluster do AKS.
Configurar GMSA no controlador de domínio do Active Directory
Para usar o GMSA com o AKS, você precisa do GMSA e de uma credencial de usuário de domínio padrão para acessar a credencial de GMSA configurada no controlador de domínio. Para configurar o GMSA em seu controlador de domínio, confira Introdução a Contas de Serviço Gerenciado de Grupo. Para a credencial de usuário de domínio padrão, você pode usar um usuário existente ou criar um, desde que ele tenha acesso à credencial GMSA.
Importante
Você precisa usar o Domínio do Active Directory ou o Active Directory local. No momento, você não pode usar o Azure Active Directory para configurar o GMSA com um cluster do AKS.
Armazene as credenciais de usuário de domínio padrão no Azure Key Vault
O cluster do AKS usa as credenciais de usuário de domínio padrão para acessar as credenciais GMSA do controlador de domínio. Para fornecer acesso seguro a essas credenciais para o cluster do AKS, essas credenciais devem ser armazenadas no Azure Key Vault. Você pode criar um cofre de chaves ou usar um existente.
Use az keyvault secret set para armazenar a credencial de usuário de domínio padrão como um segredo em seu cofre de chaves. O exemplo a seguir armazena a credencial de usuário do domínio com a chave GMSADomainUserCred no cofre de chaves MyAKSGMSAVault. Você deve substituir os parâmetros por seu próprio cofre de chaves, chave e credencial de usuário de domínio.
az keyvault secret set --vault-name MyAKSGMSAVault --name "GMSADomainUserCred" --value "$Domain\\$DomainUsername:$DomainUserPassword"
Observação
Use o nome de domínio totalmente qualificado para o domínio em vez do nome de domínio parcialmente qualificado que pode ser usado em redes internas.
O comando acima faz o escape do parâmetro value para executar a CLI do Azure em um shell do Linux. Ao executar o comando da CLI do Azure no Windows PowerShell, você não precisa fazer o escape de caracteres no parâmetro value.
Opcional: usar uma VNET personalizada com DNS personalizado
O controlador de domínio precisa ser configurado por meio do DNS para que ele seja acessível pelo cluster do AKS. Você pode configurar a rede e o DNS fora do cluster do AKS para permitir que o cluster acesse o controlador de domínio. Como alternativa, você pode configurar uma VNET personalizada com um DNS personalizado usando a CNI do Azure com o cluster do AKS para fornecer acesso ao controlador de domínio. Para obter mais detalhes, confira Configurar rede a CNI do Azure no AKS (Serviço de Kubernetes do Azure).
Opcional: usar sua própria identidade de kubelet para o cluster
Para fornecer ao cluster do AKS acesso ao cofre de chaves, a identidade do kubelet do cluster precisa de acesso ao cofre de chaves. Por padrão, quando você cria um cluster com a identidade gerenciada habilitada, uma identidade de kubelet é criada automaticamente. Você pode permitir acesso ao cofre de chaves para essa identidade após a criação do cluster, o que é feito em uma etapa posterior.
Como alternativa, você pode criar uma identidade própria e usar essa identidade durante a criação do cluster em uma etapa posterior. Para obter mais detalhes sobre as identidades gerenciadas fornecidas, confira Resumo das identidades gerenciadas.
Para criar uma identidade própria, use az identity create. O exemplo a seguir cria uma identidade myIdentity no grupo de recursos myResourceGroup.
az identity create --name myIdentity --resource-group myResourceGroup
Você pode permitir ao seu kubelet acesso de identidade ao cofre de chaves antes ou depois de criar o cluster. O exemplo a seguir usa az identity list para obter a ID da identidade e defini-la como MANAGED_ID, depois usa az keyvault set-policy para conceder acesso de identidade ao cofre de chaves MyAKSGMSAVault.
MANAGED_ID=$(az identity list --query "[].id" -o tsv)
az keyvault set-policy --name "MyAKSGMSAVault" --object-id $MANAGED_ID --secret-permissions get
Criar cluster AKS
Para usar GMSA com o cluster do AKS, use os parâmetros enable-windows-gmsa, gmsa-dns-server, gmsa-root-domain-name e enable-managed-identity.
Observação
Ao criar um cluster com pools de nós do Windows Server, você precisa especificar as credenciais de administrador ao criar o cluster. Os comandos a seguir solicitam um nome de usuário e o definem como WINDOWS_USERNAME para uso em um comando posterior (lembre-se de que os comandos deste artigo são inseridos em um shell do BASH).
echo "Please enter the username to use as administrator credentials for Windows Server nodes on your cluster: " && read WINDOWS_USERNAME
Use az aks create para criar um cluster do AKS e, em seguida, az aks nodepool add para adicionar um pool de nós do Windows Server. O exemplo a seguir cria um cluster MyAKS no grupo de recursos MyResourceGroup, habilita o GMSA e adiciona um novo pool de nós chamado npwin.
Observação
Se você estiver usando uma vnet personalizada, também precisará especificar a ID da vnet usando vnet-subnet-id e talvez precise também adicionar docker-bridge-address, dns-service-ip e service-cidr dependendo da sua configuração.
Se você criou sua própria identidade para a identidade do kubelet, use o parâmetro assign-kubelet-identity para especificar sua identidade.
DNS_SERVER=<IP address of DNS server>
ROOT_DOMAIN_NAME="contoso.com"
az aks create \
--resource-group MyResourceGroup \
--name MyAKS \
--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
az aks nodepool add \
--resource-group myResourceGroup \
--cluster-name myAKS \
--os-type Windows \
--name npwin \
--node-count 1
Você também pode habilitar o GMSA em clusters existentes que já têm identidades gerenciadas e nós do Windows Server habilitados usando az aks update. Por exemplo:
az aks update \
--resource-group MyResourceGroup \
--name MyAKS \
--enable-windows-gmsa \
--gmsa-dns-server $DNS_SERVER \
--gmsa-root-domain-name $ROOT_DOMAIN_NAME
Depois de criar o cluster ou atualizá-lo, use az keyvault set-policy para permitir acesso de identidade ao cofre de chaves. O exemplo a seguir concede à identidade de kubelet criada pelo cluster acesso ao cofre de chaves MyAKSGMSAVault.
Observação
Se você forneceu sua identidade para a identidade do kubelet, ignore esta etapa.
MANAGED_ID=$(az aks show -g MyResourceGroup -n MyAKS --query "identityProfile.kubeletidentity.objectId" -o tsv)
az keyvault set-policy --name "MyAKSGMSAVault" --object-id $MANAGED_ID --secret-permissions get
Instalar a especificação de credenciais GMSA
Para configurar o kubectl para se conectar ao cluster do Kubernetes, use o comando az aks get-credentials. O seguinte exemplo obtém as credenciais para o cluster AKS chamado MyAKS no MyResourceGroup:
az aks get-credentials --resource-group MyResourceGroup --name MyAKS
Crie um gmsa-spec.yaml com o código a seguir, substituindo os espaço reservados por seus valores.
apiVersion: windows.k8s.io/v1alpha1
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
Crie um gmsa-role.yaml com o código a seguir.
#Create the Role to read the credspec
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"]
Crie um gmsa-role-binding.yaml com o código a seguir.
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
Use kubectl apply para aplicar as alterações de gmsa-spec.yaml, gmsa-role.yaml e gmsa-role-binding.yaml.
kubectl apply -f gmsa-spec.yaml
kubectl apply -f gmsa-role.yaml
kubectl apply -f gmsa-role-binding.yaml
Verifique se o GMSA está instalado e funcionando
Crie um gmsa-demo.yaml com o código a seguir.
---
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
Use kubectl apply para aplicar as alterações de gmsa-demo.yaml
kubectl apply -f gmsa-demo.yaml
Use kubectl get service para exibir o endereço IP do aplicativo de exemplo.
kubectl get service gmsa-demo --watch
Inicialmente, o EXTERNAL-IP para o serviço gmsa-demo é mostrado como pendente.
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
gmsa-demo LoadBalancer 10.0.37.27 <pending> 80:30572/TCP 6s
Quando o endereço EXTERNAL-IP for alterado de pendente para um endereço IP público real, use CTRL-C para interromper o processo de inspeção do kubectl. A seguinte saída de exemplo mostra um endereço IP público válido atribuído ao serviço:
gmsa-demo LoadBalancer 10.0.37.27 EXTERNAL-IP 80:30572/TCP 2m
Para verificar se o GMSA está funcionando e configurado corretamente, abra um navegador da Web para o endereço IP externo do serviço gmsa-demo. Autentique-se com $NETBIOS_DOMAIN_NAME\$AD_USERNAME e a senha e confirme se você vê Authenticated as $NETBIOS_DOMAIN_NAME\$AD_USERNAME, Type of Authentication: Negotiate.
Solução de problemas
Nenhuma autenticação é solicitada ao carregar a página
Se a página for carregada, mas você não for solicitado a autenticar, use kubelet logs POD_NAME para exibir os logs do pod e verificar se você vê a mensagem O IIS com autenticação está pronto.
Tempo limite da conexão atingido ao tentar carregar a página
Se você receber uma mensagem de tempo limite de conexão ao tentar carregar a página, verifique se o aplicativo de exemplo está em execução com kubectl get pods --watch. Às vezes, o endereço IP externo para o serviço de aplicativo de exemplo está disponível antes de o pod do aplicativo de exemplo ser executado.
O pod falha em iniciar e um erro winapi aparece nos eventos de pod
Depois de executar kubectl get pods --watch e aguardar vários minutos, se o pod não for iniciar, execute kubectl describe pod POD_NAME. Se você vir um erro winapi nos eventos de pod, provavelmente será um erro na configuração de especificação de credenciais GMSA. Verifique se todos os valores de substituição em gmsa-spec.yaml estão corretos, execute kubectl apply -f gmsa-spec.yaml novamente e reimplante o aplicativo de exemplo.