Logo faq-o-matic.net
Logo faq-o-matic.net

Active-Directory-Replikation im Detail

von veröffentlicht am31. August 2010, 10:19 Uhr Kurzlink und Zitatlink einblenden
Kategorie Kategorie: AD: Replikation, Videos   Translate with Google Translate Translate EN   Die angezeigte Seite drucken
Zuletzt aktualisiert: 7. Februar 2011

Dieser Artikel soll einen etwas tieferen Einblick in die Replikation zwischen Active-Directory-Domänencontrollern geben. Diese Replikation läuft immer dann ab, wenn sich Änderungen an Verzeichnisobjekten und deren Attributen ergeben haben. Grundsätzlich lassen sich über die AD-Replikation folgende wichtige Grundaussagen treffen:

  • Die Replikation wird im Multimasterbetrieb durchgeführt, d.h. Änderungen können von jedem Domänencontroller ausgelöst werden, der die betreffende Replica (z.B. den Inhalt einer AD-Domäne) im Read/Write-Modus speichert. Domänen-Controller, die nur eine Read-Only-Kopie von bestimmten Replicas haben, sind entweder Global Catalogs oder RODCs.
  • Domänencontroller benutzen für die Replication ein Store-And-Forward Prinzip: Wenn bei einer Replikation festgestellt wurde, dass die Daten der eigenen Replicas geändert werden müssen, so werden danach diese Änderungen den anderen Replikations-Partnern mitgeteilt.
  • Wer mit wem synchronisiert, wird durch die Replikationstopologie bestimmt – diese ergibt sich aus der Anordnung der AD-Sites, Site-Links und Platzierung der DCs innerhalb einer Site. Welche DCs tatsächlich miteinander Kontakt aufnehmen, kann manuell gesteuert werden oder auch automatisch ermittelt werden. Dies übernehmen dann die Module ISTG (Intersite Topology Generator) und KCC (Knowledge Consistency Checker).
  • Die Initiierung einer Replikation wird durch den empfangenden Domänencontroller ausgelöst („Pull Replikation“)
  • Die Replikation wird (seit Windows 2003) auf Attribut-Ebene durchgeführt, d.h. es werden bei Änderungen an Objekten nur die Daten der betroffenen Attribute repliziert und nicht ganze Objekte. Allerdings: Es werden stets ganze Attribute übertragen, auch wenn es sich dabei um ein Multivalue-Attribut mit sehr vielen Array-Werten handelt. Eine Ausnahme bilden so genannte Linked Values, verlinkte Atribute, die auf andere Objekte verweisen. Hier können bei Änderungen tatsächlich nur einzelne Array-Werte eines Attributes repliziert werden – zum Glück, denn Gruppenmitgliedschaften sind ein Beispiel für Linked Values, und so muss beim Hinzufügen eines neuen Mitglieds zu einer Gruppe mit 2500 Mitgliedern nur der Wert für das neue Mitglied übertragen werden und nicht das gesamte member-Attribut. Diese Technik wird Linked Value Replication (LVR) genannt, aber dazu später mehr.
  • Bei Replikationskonflikten (ein Attribut eines bestimmten Objektes wird auf zwei verschiedenen Domänencontrollern „relativ zeitgleich“ geändert) werden Konflikte zuverlässig aufgelöst, wobei mehrere Kriterien herangezogen werden. Diese spezielle Art der Konfliktauflösung sollten wir uns noch genauer anschauen, denn hier lauert die eine oder andere Überraschung. Für die Konflikt-Auflösung benötigen die Domänencontroller z.B. seltsamerweise meist nicht einmal eine Synchronisation Ihrer Systemzeit (wobei diese Zeitsynchronisation in gewissen Grenzen aus anderen Gründen wichtig ist und auch durchgeführt wird – z.B. wegen Kerberos!).

Gerade die letzten beiden Punkte sollen in diesem Artikel etwas näher geklärt werden: Wie schaffen es die Domänencontroller zu ermitteln, dass es im Kontakt zu anderen DCs etwas zu replizieren gibt, und wie finden sie heraus, welche Werte genau repliziert werden, auch wenn sich um einen turbulenten Multimasterbetrieb handelt?

Replikations-Vektoren und Metadaten

Dafür müssen wir zuerst einmal einen genauen Blick auf die wichtigsten LDAP-Attribute werfen, die im technischen AD-Betrieb für die Replikation verwendet werden. Dies wären zuerst einmal die zwei wichtigen Werte, die ein Domänencontroller für jede Replica speichert, die er verwaltet:

  • Der Highwatermark Vector
  • Der UpTo-Date Vector (oft auch „Up-To-Dateness-Vector“ genannt)

Außerdem werden für jedes einzelne Objekt folgende Daten gespeichert:

  • Die Update Sequence Nummer (USN) im Moment der Erzeugung des Objektes: uSNCreated
  • Die Update Sequence Nummer (USN) vom Moment der letzten Änderung des Objektes: uSNChanged
  • Diverse Metadaten für jedes Attribut, das zwischen DCs repliziert wird (das ist nicht bei allen Attributen der Fall!). Dies umfasst die Uhrzeit und USN, zu der das Attribut in der eigenen Datenbank erzeugt/geändert, und zusätzlich auch die ID und die entsprechende USN des DCs, an dem die Änderung ursprünglich ausgelöst wurde (dies ist der so genannte „Originating DC“). Außerdem wird eine Versionsnummer hochgezählt, die bei jeder Änderung des Attributes um eins erhöht wird. All dies zusammen wird oft auch als „Stamp“ bezeichnet.

Die Vektoren sind im Prinzip ebenfalls Long-Integer-Zähler, die hochgezählt werden und eine fortlaufende Nummerierung des AD-Datenbank-Zustandes darstellen. Diese Zähler werden dann bei Erzeugung oder Änderung von Objekten in deren USN-Nummern gespeichert. Im folgenden Video wird der Gebrauch dieser Werte genau sichtbar:

Video 1: http://www.youtube.com/watch?v=SDPJVMPAcDw

Deutlich wird: Jeder DC führt seine eigene Nummerierung der Vektoren und dementsprechend auch eigene USN-Werte für alle Objekte und Attribute in seiner Datenbank. Nicht deutlich wird hingegen, wie denn diese Werte nun verwendet werden, um diejenigen Attribute zu ermitteln, die tatsächlich zu replizieren sind. Dafür schauen wir uns den letzten Replikationsvorgang des Videos nochmals im Detail an: Auf DC2 wurden gerade die Attribute für Passwort und EMail-Adressierung geändert. DC1 löst nun die Replikation aus:

Video 2: http://www.youtube.com/watch?v=NVOdnVBAC00

Um das interne Entscheidungsverfahren für die inkrementelle Replikation noch mehr zu verdeutlichen, soll dem Szenario ein weiteres Detail hinzugefügt werden: Es wurde noch nicht zwischen DC1 und DC2 repliziert, auf DC2 wurden gerade die Attribute für Passwort und EMail-Adressierung geändert. Zusätzlich dazu wird nun ein Attribut auf einem anderen DC geändert. Die Änderung ist unseren beiden DCs bekannt. Wie merkt DC2 nun, dass genau diese Änderung in der nächsten Replikation NICHT zu DC1 gesendet werden muss? Schauen wir uns dafür wieder ein Video an.

Video 3: http://www.youtube.com/watch?v=bDFNoW2U03c

Eigentlich ganz simpel: Anhand der Tabellen mit den Up-To-Date-Vektoren aller DCs – und anhand der Metadaten für jedes Objekt. Diese werden im Attribut “ msDS-ReplAttributeMetaData“ gespeichert. Mit einem entsprechenden LDAP Browser (hier im Beispiel wird LEX – The LDAP Explorer verwendet) kann man sich diese Attribute anzeigen lassen, es handelt sich um einen Multivalue mit XML-Textinhalt:

clip_image002

Wie man in der Detailansicht des Stamps für das Attribut „displayName“ sehen kann, sind alle Metadaten aufgeführt: Die Version, der Zeitstempel der letzten Änderung, der Name und die GUID des DCs, der die letzte Änderung ausgelöst hat (der DC heißt in diesem Beispiel „KAILASH“) , die USNs der letzten Änderung, sowohl lokal als auch vom ändernden DC. Alles ein bisschen unübersichtlich, aber im Prinzip gut erkennbar. Wenn man genau hinschaut, sieht man etwa, dass die Metadaten nur für diejenigen Attribute vorhanden sind, die auch wirklich zwischen Domänencontrollern repliziert werden. Man wird z.B. keine Metadaten für das berühmte „lastLogon“-Attribut finden, das ja bekanntlich (? 🙂 ) nicht zwischen DCs repliziert wird. Bei der genauen Durchsicht der Metadaten für das Attribut „unicodePwd“ könnte man feststellen, wie oft bisher das Passwort des betreffenden Benutzers geändert wurde …

Wie schon vorher erwähnt, gibt es für Linked Values wie z.B. „member/memberOf“ eine Besonderheit, bei der alle Metadaten nicht nur für ganze Attribute, sondern für jeden einzelnen Wert im Attribut gespeichert werden. So braucht bei einer Änderung einer Gruppenmitgliedschaft nicht das gesamte „member“-Attribut mit evtl. hunderten oder tausenden Mitgliedern repliziert zu werden. Man sieht für solche Linked Values im LDAP-Browser ein eigenes Metadata-Attribut „msDS-ReplValueMetaData„, bei dem der Stamp noch etwas komplexer aufgebaut ist:

clip_image004

Auflösung von Replikationskonflikten

Replikationskonflikte können in folgenden Szenarien auftreten – wir schauen uns am besten auch gleich an, wie dann der entstehende Konflikt von der Active-Directory-Replikation gelöst wird:

1. Auf einem Domänencontroller wird ein Container (z.B. eine OU) gelöscht, während auf einem anderen Domänencontroller genau in diesem Container ein neues Objekt erstellt oder ein bestehendes dorthin verschoben wird.

In diesem Fall geht das neue Objekt in dem gelöschten Container nicht verloren, sondern wird im System-Container „LostAndFound“ gespeichert. Diesen Container sieht man beispielsweise, wenn man im „AD Users and Computers“ Tool die „Advanced View Option“ aktiviert.

Wenn Sie einen solchen Replikationskonflikt einmal selbst beobachten wollen, dann brauchen Sie zwei Domänencontroller in der gleichen Domäne und eine leere Test-OU. Dann können sie folgendes VBScript ausführen:

' hier die eigenen DCs eintragen:
dc1 = "192.168.0.66"
dc2 = "192.168.0.67"

'hier den Pfad zu einer vorhandenen leeren Test-OU eintragen:
ouPath = "ou=reptest,dc=ldapexplorer,dc=com" 

Set ou1 = GetObject("LDAP://" & dc1 & "/" & ouPath)
Set ou2 = GetObject("LDAP://" & dc2 & "/" & ouPath)

ou1.DeleteObject(0) 'OU wird auf DC1 gelöscht !

Set user = ou2.Create("user", "cn=repUser") 'User wird auf DC2 erstellt
user.sAMAccountName = "repUser"
user.SetInfo

Das Ergebnis: Der neu erstellte repUser erscheint im SystemContainer „LostandFound“, anhand seiner „lastKnownParent“-Eigenschaft sieht man sogar, dass er ursprünglich in einem Container namens „repTest“ erstellt werden sollte:

clip_image006

By the way: Der verwendete LDAP Browser ist auch hier LEX – The LDAP Explorer.

2. Auf zwei Domänencontrollern wird quasi gleichzeitig dasselbe Attribut eines Objektes in zwei verschiedene Werte geändert.

In diesem Fall müssen die Domänencontroller entscheiden, welche der beiden Änderungen „gewinnt“. Normalerweise würde man denken, dass die zeitlich zuletzt ausgelöste Attribut-Änderung sich durchsetzt, dies ist jedoch nicht immer der Fall. Die beiden DCs vergleichen nämlich die Attribut-Versionen im Metadaten-Stamp (diese Versionsnummer wird als Zähler bei jeder Änderung um eins erhöht). Bei einem vorliegenden Konflikt für ein bestimmtes Attribut setzt sich der DC durch, bei dem die höchste Attribut-Version vorhanden ist. Erst wenn die Attributversion auf beiden Seiten gleich ist, dann gewinnt der DC, der das Attribut zuletzt geändert hat. Sollte der Zeitstempel der Änderung ebenfalls bis auf die Sekunde gleich sein, dann gewinnt der DC, dessen GUID-String alphabetisch gesehen „kleiner“ ist (also bestimmt dann quasi der Zufall die Replikation).

Mit diesen Kenntnissen können wir einen seltsamen Fall konstruieren: Wir ändern auf DC1 sehr schnell hintereinander mehrmals ein Attribut eines Users. Dadurch erhöhen wir die Metadaten-Version für dieses Attribut um mehrere Schritte. Dann ändern wir das gleiche Attribut auf DC2, jedoch nur ein einziges Mal. Danach führen die beiden DCs eine normale AD-Replikation aus. Das Ergebnis: Obwohl die Änderung auf DC2 zeitlich die letzte Änderung war, besitzt danach das Attribut den Wert, der zuletzt auf DC1 geschrieben wurde!

Wenn Sie diesen Effekt selbst beobachten wollen, dann brauchen Sie zwei Domänencontroller in der gleichen Domäne und einen Test-User. Dann können sie folgendes VBScript ausführen:

' hier die eigenen DCs eintragen:
dc1 = "192.168.0.66"
dc2 = "192.168.0.67"
'hier den Pfad zu einem vorhandenen Test-User eintragen
testUser = "cn=repUser,dc=ldapexplorer,dc=com" 

Set user1 = GetObject("LDAP://" & dc1 & "/" & testUser)
Set user2 = GetObject("LDAP://" & dc2 & "/" & testUser)

value1 = "DC1 - " & now 'Attribut schreiben auf DC1 und etwas warten
user1.displayName = value1
user1.SetInfo
WScript.Sleep 1000

value2 = "DC1 - " & Now 'Attribut nochmal ändern auf DC1 und etwas warten
user1.displayName = value2
user1.SetInfo
WScript.Sleep 1000

value3 = "DC2 - " & now 'Attribut auf DC2 ändern
user2.displayName = value3
user2.SetInfo

WScript.Echo value1 'nochmals alle drei Werte anzeigen
WScript.Echo value2
WScript.Echo value3

Wenn Sie nun nach einer Weile das Attribut wieder überprüfen (nach einer erfolgten Replikation; sind beide DCs innerhalb einer Site, geschieht die Replikation sehr schnell, zwischen Sites anhand der konfigurierten Intervalle), werden sie feststellen, dass nicht der dritte Wert gewonnen hat, sondern der zweite! Durch die zweimalige Änderung haben wir auf dem ersten DC die Metadatenversion künstlich erhöht…. Dieser seltsame Effekt sollte jedoch in der Praxis selten eine Rolle spielen.

3. Auf zwei Domänencontrollern werden quasi gleichzeitig zwei Objekte mit gleichem Namen erzeugt, oder es werden zwei verschiedene Objekte in den gleichen Namen/LDAP-Pfad umbenannt – oder eine Mischung aus beiden.

Hier entscheiden die beteiligten DCs zuerst einmal, welche Seite sich durchsetzt. Es gelten hier einfach die gleichen Regeln wie bei einem Attribut-Konflikt, und das entscheidende Attribut für den Check ist das namensgebende, also bei Organizational Unit-Objekten ist es das „ou„-Attribut, bei den meisten anderen das „cn„-Attribut.

Wenn also zwei verschiedene Objekte auf den DCs entstehen, die jedoch den gleichen Distinguished Name haben, dann wird geprüft, welche Seite im „ou“/“cn“ Attribut eine höhere Versionsnummer hat, sind die Versionen gleich, entscheidet der Timestamp, danach das Los. Das Objekt, das bei diesem Wettkampf verloren hat, wird trotzdem erstellt, jedoch mit dem Zusatz „\0ACNF:<GUID>“ im Objektnamen (das \0A steht für ein Zeilenumbruchszeichen und kann meist nicht korrekt dargestellt werden …). Es gibt dann zwei Objekte, und man kann im Nachhinein noch entscheiden, welches Objekt tatsächlich das richtige war und weiterverwendet werden soll.

Wenn Sie einen solchen Replikationskonflikt einmal selbst beobachten wollen, dann brauchen Sie zwei Domänencontroller in der gleichen Domäne und eine leere Test-OU. Dann können sie folgendes VBScript ausführen:

' hier die eigenen DCs eintragen:
dc1 = "192.168.0.66"
dc2 = "192.168.0.67"
'hier den Pfad zu einer vorhandenen leeren Test-OU eintragen
ouPath = "ou=reptest,dc=ldapexplorer,dc=com" 

Set ou1 = GetObject("LDAP://" & dc1 & "/" & ouPath)
Set ou2 = GetObject("LDAP://" & dc2 & "/" & ouPath)

Set user1 = ou1.Create("user", "cn=repUser") 'User wird auf DC1 erstellt
user1.sAMAccountName = "repUser"
user1.description = "Erstellt auf DC1"
user1.SetInfo

Set user2 = ou2.Create("user", "cn=repUser") 'User wird auf DC2 erstellt
user2.sAMAccountName = "repUser"
user1.description = "Erstellt auf DC2"
user2.SetInfo

Das Ergebnis (warten Sie die nächste Replikation ab): Der neu erstellte repUser erscheint zweimal, eine Version ist mit dem „CNF“-Zusatz gekennzeichnet:

clip_image008

© 2005-2023 bei faq-o-matic.net. Alle Rechte an den Texten liegen bei deren Autorinnen und Autoren.

Jede Wiederveröffentlichung der Texte oder von Auszügen daraus - egal ob kommerziell oder nicht - bedarf der ausdrücklichen Genehmigung durch die jeweiligen Urheberinnen oder Urheber.

Das Impressum findet sich unter: http://www.faq-o-matic.net/impressum/

Danke, dass du faq-o-matic.net nutzt. Du hast ein einfaches Blog sehr glücklich gemacht!