Le schéma d'installation problématique

Le LAB pour cette situation est très simple :
3 VMs :

  • Machine Z : Windows 2012R2 avec comme rôles : Active Directory + DNS
  • BasicAAGn1 : Windows 2012R2 avec le rôle FailoverCluster - IP : BasicAAGn1.lab.local=10.1.0.10
  • BasicAAGn2 (identique à BasicAAGn1) : Windows 2012R2 avec le rôle FailoverCluster - IP : BasicAAGn2.lab.local=10.1.0.11


Suivons en pas-à-pas la procédure d'installation d'un cluster Microsoft via les commandes powershell depuis le noeud 1:
PS C:\Users\administrator.LAB> Test-NetConnection basicaagn2

ComputerName : basicaagn2
RemoteAddress : 10.1.0.11
InterfaceAlias : Ethernet0
SourceAddress : 10.1.0.10
PingSucceeded : True
PingReplyDetails (RTT) : 0 ms
La connexion entre les 2 machines se fait correctement, on peut passer à la suite : la validation du cluster:

PS C:\Users\administrator.LAB> Test-Cluster -node basicaagn1,basicaagn2 -verbose
VERBOSE: Performing verification
VERBOSE: Storage - List Disks: The test passed..
VERBOSE: Storage - Validate CSV Network Bindings: The test passed..
WARNING: Storage - List Disks To Be Validated: The test reported some warnings..
VERBOSE: Storage - Validate CSV Settings: The test passed..
WARNING: Storage - Validate Disk Access Latency: The test reported some warnings..
WARNING: Storage - Validate Microsoft MPIO-based disks: The test reported some warnings..
WARNING: Storage - Validate SCSI device Vital Product Data (VPD): The test reported some warnings..
WARNING: Storage - Validate SCSI-3 Persistent Reservation: The test reported some warnings..
WARNING: Storage - Validate Storage Spaces Persistent Reservation: The test reported some warnings..
WARNING: Storage - Validate Disk Arbitration: The test reported some warnings..
WARNING: Storage - Validate Multiple Arbitration: The test reported some warnings..
WARNING: Storage - Validate Disk Failover: The test reported some warnings..
WARNING: Storage - Validate File System: The test reported some warnings..
WARNING: Storage - Validate Simultaneous Failover: The test reported some warnings..
VERBOSE: Inventory - List Fibre Channel Host Bus Adapters: The test passed..
VERBOSE: Inventory - List iSCSI Host Bus Adapters: The test passed..
VERBOSE: Inventory - List SAS Host Bus Adapters: The test passed..
VERBOSE: Inventory - List BIOS Information: The test passed..
VERBOSE: Inventory - List Environment Variables: The test passed..
VERBOSE: Inventory - List Memory Information: The test passed..
VERBOSE: Inventory - List Operating System Information: The test passed..
VERBOSE: Inventory - List Plug and Play Devices: The test passed..
VERBOSE: Inventory - List Running Processes: The test passed..
VERBOSE: Inventory - List Services Information: The test passed..
VERBOSE: Inventory - List Software Updates: The test passed..
VERBOSE: Inventory - List System Drivers: The test passed..
VERBOSE: Inventory - List System Information: The test passed..
VERBOSE: Inventory - List Unsigned Drivers: The test passed..
VERBOSE: System Configuration - Validate Active Directory Configuration: The test passed..
VERBOSE: System Configuration - Validate All Drivers Signed: The test passed..
VERBOSE: System Configuration - Validate Memory Dump Settings: The test passed..
VERBOSE: System Configuration - Validate Operating System Edition: The test passed..
VERBOSE: System Configuration - Validate Operating System Installation Option: The test passed..
VERBOSE: System Configuration - Validate Operating System Version: The test passed..
VERBOSE: System Configuration - Validate Required Services: The test passed..
VERBOSE: System Configuration - Validate Same Processor Architecture: The test passed..
VERBOSE: System Configuration - Validate Service Pack Levels: The test passed..
VERBOSE: System Configuration - Validate Software Update Levels: The test passed..
VERBOSE: Network - List Network Binding Order: The test passed..
VERBOSE: Network - Validate Cluster Network Configuration: The test passed..
VERBOSE: Network - Validate IP Configuration: The test passed..
WARNING: Network - Validate Network Communication: The test reported some warnings..
VERBOSE: Network - Validate Windows Firewall Configuration: The test passed..
WARNING:
Test Result:
ClusterConditionallyApproved
Testing has completed successfully. The configuration appears to be suitable for clustering. However, you should
review the report because it may contain warnings which you should address to attain the highest availability.
Test report file path: C:\Users\administrator.LAB\AppData\Local\Temp\Validation Report 2017.02.24 At 14.19.27.xml.mht

Les tests de clusters sont OK : "ClusterConditionallyApproved", on continue la création.
Le cluster aura comme nom : BasicAAGOS sur l'IP : 10.1.0.20
PS C:\Users\administrator.LAB> new-cluster basicaagos -node basicaagn1,basicaagn2 -staticaddress 10.1.0.20 -verbose
VERBOSE: Adding static network 10.0.0.0/8.
Report file location: C:\Windows\cluster\Reports\Create Cluster Wizard basicaagos on 2017.02.24 At 15.06.00.mht
VERBOSE: at Microsoft.FailoverClusters.PowerShell.RoleCmdletHelper.WaitForAction(ConfigurationBase config)
at Microsoft.FailoverClusters.PowerShell.RoleCmdletHelper.PerformRoleAction(ConfigurationBase config)
at Microsoft.FailoverClusters.PowerShell.RoleCmdletHelper.CreateRole(ConfigurationBase config, ClusterclusterObject, FCCmdlet cmdletObject, String serverNameBase)
at Microsoft.FailoverClusters.PowerShell.NewClusterCommand.WrappedProcessRecord()
at Microsoft.FailoverClusters.PowerShell.FCCmdlet.ProcessRecord()
VERBOSE: at MS.Internal.ServerClusters.Configuration.CreateClusterConfigurationNoCno.InternalPerformAction(ActionArgs actionArgs)
at MS.Internal.ServerClusters.Configuration.ConfigurationBase.PerformActionWrapper(BackgroundOperationStatusbackgroundOperationStatus, BackgroundOperationArgs parameter)
at MS.Internal.ServerClusters.BackgroundOperation`2.BackgroundOperationProc(Object state)
VERBOSE: at MS.Internal.ServerClusters.Cluster.Create(String clusterName, StringCollection nodeNames, ICollection`1 ipAddresses, ClusterActionCallback callback, AdminAccessPoint managementAccessPoint)
at MS.Internal.ServerClusters.Configuration.CreateClusterConfigurationNoCno.PerformCreateCluster(ActionArgsactionArgs, ActionUpdateHelper updateHelper)
at MS.Internal.ServerClusters.Configuration.CreateClusterConfigurationNoCno.PerformAction(ActionArgs actionArgs)
at MS.Internal.ServerClusters.Configuration.CreateClusterConfigurationNoCno.InternalPerformAction(ActionArgsactionArgs)
VERBOSE:
new-cluster : An error occurred while performing the operation.
An error occurred while creating the cluster 'basicaagos'.
An error occurred creating cluster 'basicaagos'.
This operation returned because the timeout period expired
At line:1 char:1
+ new-cluster basicaagos -node basicaagn1,basicaagn2 -staticaddress 10.1.0.20 -ver ...
+
+ CategoryInfo : NotSpecified: (:) New-Cluster, ClusterCmdletException
+ FullyQualifiedErrorId : New-Cluster,Microsoft.FailoverClusters.PowerShell.NewClusterCommand


Donc échec. Au delà de devoir attende le timeout relativement important, cette erreur est déconcertante puisque la configuration est validée en amont par Powershell.

Limitons l'analyse

Pour tenter de comprendre où est le problème, nous pouvons faire un test simple : créer le cluster avec une seule machine. Une étape qui semble inutile mais pour notre cas de débug va largement limiter les recherches.
new-cluster basicaagos -node basicaagn1 -staticaddress 10.1.0.20 -verbose
new-cluster : An error occurred while performing the operation.
An error occurred while creating the cluster 'basicaagos'.
An error occurred creating cluster 'basicaagos'.
This operation returned because the timeout period expired

Le problème se reproduit de la même façon ! On peut donc exclure tout problème de liaison entre les 2 noeuds : pas de soucis firewall, routing.

Analyse de l'échec

Pour comprendre ce qui se passe sur le cluster, on arrive rapidement à regarder la log globale. Cette log cluster peut s'obtenir via la commande Powershell Get-ClusterLog mais sachez qu'elle est extrêmement verbeuse. Pour obtenir un fichier plus lisible, vous pouvez spécifier que vous ne souhaitez que les n dernières minutes via le paramètre -TimeSpan
Get-ClusterLog -cluster basicaagos -time 3 -dest .
Chose intéressante dans notre cas, puisque le cluster n'est pas encore créé, la log contient tout ce qui se passe lors d'une création (sauf si vous limitez via TimeSpan). Difficile de lire cette log tant il y a de modules pour la gestion du cluster. Généralement, on peut commencer par chercher les instructions qui sont en erreur (Find ERR).
Voici les premières occurrences :

  • ERR [DCM] DiskControlManager bitlocker load status 126
  • ERR [API] DmQueryString failed to retrieve the security descriptor status 2, default security descriptor will be used for authorizing client connections
  • ERR mscs::ConfigureHyperVRootReserveMemoryForCache: (2)' because of 'OpenSubKey( name, access, key, NOTHROW() )'(SOFTWARE\Microsoft\Windows NT\CurrentVersion\Virtualization)
  • ERR [RCM] rcm::DrainMgr::Cleanup: [DrainMgr] cleaup called without being initialized.
  • ERR [CAM] Error in creating first token: -1073741477
  • ERR mscs::QuorumAgent::FormLeaderWorker::operator (): (c0000008)' because of 'status'


Analysons-les une à une :
- La première référence l'utilisation de BitLocker. Les serveurs n'utilisent pas cette fonction. L'erreur ne devrait pas en être une mais plutôt : "BitLocker non installé".
- La suivante est moins claire. Elle indique un problème pour récupérer une propriété de sécurité ; le problème semble limité puisqu'il va utiliser le descripteur par défaut...
- Vient ensuite une erreur lors de la récupération de la mémoire réservée pour le cache sur HyperV. Les serveurs ne sont pas virtualisés en HyperV mais sur VMWare (Workstation sur mon LAB, vSphere chez le client). On peut donc ignorer.
- Puis un message qui indique que le noeud quitte le cluster (Drain) alors qu'il n'en a jamais fait partie.
- Une erreur lors de la génération d'un 1er token
- Et pour finir l'erreur qui indique que le quorum n'a pas pu être formé.

Error in creating first token: -107374147

C'est bien cette erreur qui provoque l'impossibilité de créer le cluster. Voyons quelques lignes autour de cette ligne:
[CAM] Setting CurrentUser CLIUSR, Dom BASICAAGN1 (Proc 2240)
[CAM] New Process, old 108
[CAM] Creating new token when CNL credentials are set
[CAM] LsaLogon: c000015b
[CAM] Error in creating first token: -1073741477
L'erreur est liée à un LsaLogon ; ce LsaLogon donne comme retour :c000015b. Le code retour est un message NTSTATUS qui correspond à "STATUS_LOGON_TYPE_NOT_GRANTED" selon la doc Microsoft. On retrouve cette erreur d'authentification dans l'event log Security...
Il y a donc un soucis avec une authentification. On peut voir le compte qui cherche à s'authentifier et là, ça devient intéressant : User CLIUSR, Domain BASICAAGN1. C'est un compte local qui tente de se connecter mais le login est refusé ! Ce compte CLIUSR est propre au cluster ; il est justement créé lorsqu'une machine rejoint (ou crée) un cluster. Pourquoi le cluster a-t-il besoin de ce compte ? Cette fois, je vous renvoie sur une doc AskTheCoreTeam de chez Microsoft pour l'ensemble de l'historique mais ce compte permet de démarrer le service cluster sans dépendre de l'authentification ActiveDirectory.
Le compte CLIUSR est un compte local sans droit admin et le cluster s'occupe de faire les changements de mot de passe en background.

Mais pourquoi cette erreur ?

Cette erreur de LsaLogon est tout simplement une policy en place sur la machine qui interdit les connexions locales. Sur Windows 2012 Server, il y a 2 policies qui peuvent boquer cela : - Access this computer from the network - Deny access to this computer from the network (arrivée avec Windows 2012)
La première policy contient pas défaut les groupes : Administrators, Backup Operators, Everyone et Users qui sont tous des groupes locaux. Windows va même ajouter un message d'avertissement "Modifying this setting may affect compatibility with clients, services and applications". C'est une policy très restrictive à utiliser donc avec attention.
La seconde policy est "le négatif" de la première.

Conclusion


Dans l'infrastructure de mon client, les policies étaient très restrictives pour éviter les connexions sur les serveurs à partir de comptes qui ne serait pas authentifiés pas l'Active Directory. L'idée de départ semble bien fondée mais dans la réalité, même des features Windows comme le Failover Cluster ont besoin de compte locaux. Pour garder un haut niveau de restriction, la solution la plus élégante est d'authoriser les groupes par défaut à se connecter mais d'utiliser la policy "Deny" pour ne pas donner le droit aux comptes admin de se connecter (Local account and member of Administrators group).
Le compte CLIUSR étant un compte basique sans droit admin, il pourra se connecter mais des comptes admin locaux qui seraient créés sans authorisation seraient eux bloqués.