Sauvegarde et restauration Ping Directory dans une topologie répliquée

Contexte

Lors d'une formation sur PingDirectory, le 'lab' sur la sauvegarde / restauration est très simple : on lance une sauvegarde avec l'utilitaire backup, puis une sauvegarde avec restore, sans avoir modifié les données. Trouvant l'exercice peut représentatif, j'ai testé la restauration en ayant au préalable supprimé des entrées. Et, ô surprise, les données n'ont pas été restaurées.

Il ne s'agit pas d'un problème sur le produit, mais d'un problème de processus.

Les tests réalisés et la marche à suivre sont décrits dans la suite de cet article.

Test sur un seul serveur

Installation

Sur le premier serveur, on installe l'annuaire :

/opt/ds/setup --acceptLicense --no-prompt --script-friendly \
   --localHostName $(hostname -f) \
   --ldapPort 1389 \
   --ldapsPort 1636 \
   --httpsPort 1443 \
   --rootUserDN cn=dmanager \
   --rootUserPassword MyStrongPassw0rd \
   --maxHeapSize 512m \
   --enableStartTLS \
   --generateSelfSignedCertificate \
   --baseDN dc=example,dc=com \
   --sampleData 2000

On peut chercher les entrées commençant par user.20 :

bin/ldapsearch -b dc=example,dc=com uid=user.20* dn

dn: uid=user.20,ou=People,dc=example,dc=com

dn: uid=user.200,ou=People,dc=example,dc=com

dn: uid=user.201,ou=People,dc=example,dc=com

dn: uid=user.204,ou=People,dc=example,dc=com

dn: uid=user.206,ou=People,dc=example,dc=com

dn: uid=user.205,ou=People,dc=example,dc=com

dn: uid=user.207,ou=People,dc=example,dc=com

dn: uid=user.202,ou=People,dc=example,dc=com

dn: uid=user.203,ou=People,dc=example,dc=com

dn: uid=user.208,ou=People,dc=example,dc=com

dn: uid=user.209,ou=People,dc=example,dc=com

dn: uid=user.2000,ou=People,dc=example,dc=com

# Result Code:  0 (success)
# Number of Entries Returned:  12

Lancement d'une sauvegarde

On lance ensuite une sauvegarde avec l'utilitaire backup :

mkdir /opt/dirbackups
/opt/ds/bin/backup --port 1389 --bindDN cn=dmanager --bindPassword MyStrongPassw0rd \
    --backupAll --backupDirectory /opt/dirbackups


[18/Mar/2018:11:28:36 +0000] severity="NOTICE" msgCount=0 msgID=10944792 message="Starting backup for backend schema"
[18/Mar/2018:11:28:36 +0000] severity="NOTICE" msgCount=1 msgID=10944792 message="Starting backup for backend encryption-settings"
[18/Mar/2018:11:28:36 +0000] severity="SEVERE_WARNING" msgCount=2 msgID=1880228562 message="The encryption settings database backup does not include the '/opt/ds/config/encryption-settings.pin' file that holds the key used to protect the encryption settings definitions.  This file should be backed up separately (e.g., by manually copying it to a safe place) to ensure that it will be available if it becomes necessary to restore the encryption settings database from a backup"
[18/Mar/2018:11:28:36 +0000] severity="NOTICE" msgCount=3 msgID=10944792 message="Starting backup for backend alarms"
[18/Mar/2018:11:28:36 +0000] severity="NOTICE" msgCount=4 msgID=10944792 message="Starting backup for backend ads-truststore"
[18/Mar/2018:11:28:36 +0000] severity="NOTICE" msgCount=5 msgID=10944792 message="Starting backup for backend alerts"
[18/Mar/2018:11:28:36 +0000] severity="NOTICE" msgCount=6 msgID=10944792 message="Starting backup for backend userRoot"
[18/Mar/2018:11:28:36 +0000] severity="NOTICE" msgCount=7 msgID=8847446 message="Archived: 00000000.jdb"
[18/Mar/2018:11:28:36 +0000] severity="NOTICE" msgCount=8 msgID=10944792 message="Starting backup for backend replicationChanges"
[18/Mar/2018:11:28:36 +0000] severity="NOTICE" msgCount=9 msgID=10944792 message="Starting backup for backend adminRoot"
[18/Mar/2018:11:28:36 +0000] severity="NOTICE" msgCount=10 msgID=10944792 message="Starting backup for backend config"
[18/Mar/2018:11:28:36 +0000] severity="NOTICE" msgCount=11 msgID=10944792 message="Starting backup for backend tasks"
[18/Mar/2018:11:28:36 +0000] severity="NOTICE" msgCount=12 msgID=10944795 message="The backup process completed successfully"
Backup task 2018031811283603 has been successfully completed

Suppression d'entrées

Pour vérifier que la restauration fonctionne, on se place dans le cas où l'on a supprimé des entrées.

On supprime donc les entrées de user.200 à user.209, via un fichier ldif

cat ldif/del.ldif 
uid=user.200,ou=People,dc=example,dc=com
uid=user.201,ou=People,dc=example,dc=com
uid=user.204,ou=People,dc=example,dc=com
uid=user.206,ou=People,dc=example,dc=com
uid=user.205,ou=People,dc=example,dc=com
uid=user.207,ou=People,dc=example,dc=com
uid=user.202,ou=People,dc=example,dc=com
uid=user.203,ou=People,dc=example,dc=com
uid=user.208,ou=People,dc=example,dc=com
uid=user.209,ou=People,dc=example,dc=com

/opt/ds/bin/ldapdelete -f ldif/del.ldif

On vérifie dans l'annuaire :

bin/ldapsearch -b dc=example,dc=com uid=user.20* dn

dn: uid=user.20,ou=People,dc=example,dc=com

dn: uid=user.2000,ou=People,dc=example,dc=com

# Result Code:  0 (success)
# Number of Entries Returned:  2

Restauration de la sauvegarde

Heureusement, nous avons une sauvegarde.

On va réaliser une restauration des données avec l'utilitaire restore, en mode offline.

On arrête l'annuaire :

bin/stop-server

Puis on restaure, à partir de la dernière sauvegarde, et du backend userRoot (celui qui contient les données) :

bin/restore --backupDirectory /opt/dirbackups/userRoot
[11:48:17]  The console logging output is also available in '/opt/ds/logs/tools/restore.log'
[11:48:17]  restore was run with the following arguments:  --configClass com.unboundid.directory.server.extensions.ConfigFileHandler --configFile /opt/ds/config/config.ldif --backupDirectory /opt/dirbackups/userRoot
[11:48:17]  Restored: .environment-online-backup (size 0)
[11:48:17]  Restored: 00000000.jdb (size 3708137)
[11:48:17]  Restored: 00000001.jdb (size 1545)
[11:48:17]  The restore process completed successfully

On redémarre ensuite l'annuaire :

bin/start-server

On vérifie dans l'annuaire que l'on a récupéré toutes les données :

bin/ldapsearch -b dc=example,dc=com uid=user.20* dn
dn: uid=user.20,ou=People,dc=example,dc=com

dn: uid=user.200,ou=People,dc=example,dc=com

dn: uid=user.201,ou=People,dc=example,dc=com

dn: uid=user.204,ou=People,dc=example,dc=com

dn: uid=user.206,ou=People,dc=example,dc=com

dn: uid=user.205,ou=People,dc=example,dc=com

dn: uid=user.207,ou=People,dc=example,dc=com

dn: uid=user.202,ou=People,dc=example,dc=com

dn: uid=user.203,ou=People,dc=example,dc=com

dn: uid=user.208,ou=People,dc=example,dc=com

dn: uid=user.209,ou=People,dc=example,dc=com

dn: uid=user.2000,ou=People,dc=example,dc=com

# Result Code:  0 (success)
# Number of Entries Returned:  12

Conclusion

En mode standalone, il est facile de récupérer des données

Au sein d'une topologie de réplication

Pour ce second test, nous allons ajouter une instance, et créer une topologie de réplication comprenant les 2 annuaires

Installation du second annuaire :

/opt/ds/setup --acceptLicense --no-prompt --script-friendly \
   --localHostName $(hostname -f) \
   --ldapPort 1389 \
   --ldapsPort 1636 \
   --httpsPort 1443 \
   --rootUserDN cn=dmanager \
   --rootUserPassword MyStrongPassw0rd \
   --maxHeapSize 512m \
   --enableStartTLS \
   --generateSelfSignedCertificate \
   --baseDN dc=example,dc=com \
    --addBaseEntry

Mise en place de la réplication entre les 2 annuaires

On va tout d'abord ajouter une "location" pour les annuaires, sur chaque machine :

bin/dsconfig create-location --location-name france 
bin/dsconfig set-global-configuration-prop --set location:france 

On crée ensuite l'agrément de réplication :

/opt/ds/bin/dsreplication enable \
    --host1 ping1.arciam.fr --port1 1389 \
    --bindDN1 "cn=dmanager" --bindPassword1 MyStrongPassw0rd \
    --replicationPort1 18989 \
    --host2 ping2.arciam.fr --port2 1389 \
    --bindDN2 "cn=dmanager" --bindPassword2 MyStrongPassw0rd \
    --replicationPort2 18989 \
    --baseDN dc=example,dc=com --adminUID admin \
    --adminPassword MyStrongPassw0rd --no-prompt --ignoreWarnings

Vérification de la réplication

On utilise dsreplication avec l'option status :

/opt/ds/bin/dsreplication status -h localhost -p 1389 --adminUID admin -w MyStrongPassw0rd --no-prompt --displayservertable

          --- Replication Servers: dc=example,dc=com ---
Server                : Location : Priority (1) : Status
----------------------:----------:--------------:----------
ping1.arciam.fr:18989 : france   : 5            : Available
ping2.arciam.fr:18989 : france   : 5 (*)        : Available


[1] WAN Gateway Priority.  WAN gateways are marked with a *. To minimize WAN utilization, the
server with the WAN Gateway role is the only server in a location that exchanges updates with
remote locations.

          --- Replication Status for dc=example,dc=com: Enabled ---
Server               : Location : Entries : Conflict Entries : Backlog (1) : Rate (2)
---------------------:----------:---------:------------------:-------------:---------
ping1.arciam.fr:1389 : france   : 2004    : 0                : 0           : 0
ping2.arciam.fr:1389 : france   : 3       : 0                : 0           : 0

On constate donc que le deuxième serveur est en retard. On va l'initialiser, en se connectant sur ce serveur.

bin/dsreplication initialize --adminUID admin \
  --adminPassword MyStrongPassw0rd --baseDN dc=example,dc=com  \
     --hostSource ping1.arciam.fr --portSource 1389 \
     --hostDestination ping2.arciam.fr --portDestination 1389  \
     --no-prompt

On peut alors vérifier le statut de la réplication :

/opt/ds/bin/dsreplication status -h localhost -p 1389 --adminUID admin -w MyStrongPassw0rd --no-prompt --displayservertable

          --- Replication Status for dc=example,dc=com: Enabled ---
Server               : Location : Entries : Conflict Entries : Backlog (1) : Rate (2)
---------------------:----------:---------:------------------:-------------:---------
ping1.arciam.fr:1389 : france   : 2004    : 0                : 0           : 0
ping2.arciam.fr:1389 : france   : 2004    : 0                : 0           : 0

Sauvegarde et suppression des entrées

Comme dans la première configuration, on lance une sauvegarde, puis on va supprimer les entrées user.200 à user.209.

Suite à la suppression, on peut constater que les entrées ont bien été supprimées sur les 2 serveurs :

/opt/ds/bin/dsreplication status -h localhost -p 1389 --adminUID admin -w MyStrongPassw0rd --no-prompt --displayservertable

          --- Replication Status for dc=example,dc=com: Enabled ---
Server               : Location : Entries : Conflict Entries : Backlog (1) : Rate (2)
---------------------:----------:---------:------------------:-------------:---------
ping1.arciam.fr:1389 : france   : 1994    : 0                : 0           : 0
ping2.arciam.fr:1389 : france   : 1994    : 0                : 0           : 0

Restauration sur le serveur 1

Nous allons procéder à la restauration, telle que l'on a fait lors de l'étape précédent, après arrêt de l'annuaire.

Une fois l'annuaire arrêté, on peut vérifier l'état de la réplication :

          --- Replication Status for dc=example,dc=com: Enabled ---
Server               : Location : Entries : Conflict Entries : Backlog (1) : Rate (2)
---------------------:----------:---------:------------------:-------------:---------
ping1.arciam.fr:1389 : N/A      : N/A     : N/A              : N/A         : 0
ping2.arciam.fr:1389 : france   : 1994    : 0                : 0           : 0

Le premier annuaire n'est pas disponible, l'autre contient toujours les données

bin/restore --backupDirectory /opt/dirbackups/userRoot
[13:39:05]  The console logging output is also available in '/opt/ds/logs/tools/restore.log'
[13:39:05]  restore was run with the following arguments:  --configClass com.unboundid.directory.server.extensions.ConfigFileHandler --configFile /opt/ds/config/config.ldif --backupDirectory /opt/dirbackups/userRoot
[13:39:05]  Restored: .environment-online-backup (size 0)
[13:39:05]  Restored: 00000002.jdb (size 2155059)
[13:39:05]  Restored: 00000003.jdb (size 6402)
[13:39:05]  The restore process completed successfully

On peut ensuite redémarrer l'annuaire, via bin/start-server, et vérifier si on a récupéré nos entrées :

bin/ldapsearch -b dc=example,dc=com uid=user.20* dn

dn: uid=user.20,ou=People,dc=example,dc=com

dn: uid=user.2000,ou=People,dc=example,dc=com

# Result Code:  0 (success)
# Number of Entries Returned:  2

Seules 2 entrées sont présentes. Est-ce que la restauration n'aurait pas fonctionné ?

Si on regarde l'état de la réplication, on a :

          --- Replication Status for dc=example,dc=com: Enabled ---
Server               : Location : Entries : Conflict Entries : Backlog (1) : Rate (2) : A.O.B.C. (3) : Generation ID : Server ID : Replica ID
---------------------:----------:---------:------------------:-------------:----------:--------------:---------------:-----------:-----------
ping1.arciam.fr:1389 : france   : 1994    : 0                : 0           : 0        : 0 seconds    : 2857013720    : 8488      : 11115
ping2.arciam.fr:1389 : france   : 1994    : 0                : 0           : 0        : 0 seconds    : 2857013720    : 14618     : 17447

En redémarrant, même après une sauvegarde, l'instance d'annuaire est allé récupérer les données auprès de l'annuaire ayant le dernier Generation ID.

En regardant le fichier de logs errors ou replication, on voit le message suivant :

[18/Mar/2018:13:40:25.235 +0000] instanceName="ping1.arciam.fr:1389" threadID=-1 category=REP
LICATION severity=NOTICE msgID=118947963 msg="Replica dc=example,dc=com detected that there a
re updates originating from this replica present in the replication topology that are missing
 from this replica. This can usually occur after a replica has been restored from backup. The
 replica will not accept updates from external clients until these updates have been applied 
locally. The change number of the last update at this replica: <>, and in the topology: 00000
162394BA3CE2B6B0000000A"

Conclusion

Si on doit restaurer les données dans une architecture répliquée, il est nécessaire d'arrêter la réplication, restaurer sur un des serveurs, puis remettre en route la réplication.

Procédure de sauvegarde dans une architecture répliquée

Comme vu ci-dessus, il est nécessaire de désactiver la réplication, en utilisant l'option pre-external-initialization de l'utilitaire dsreplication :

/opt/ds/bin/dsreplication pre-external-initialization --hostname ping1.arciam.fr \
--port 1389 --baseDN dc=example,dc=com --adminUID admin \
--adminPassword MyStrongPassw0rd --no-prompt

Ceci arrête la réplication pour le domaine.

On peut ensuite restaurer les données.

On va ensuite arrêter le premier serveur, lancer la restauration, puis redémarrer :

/opt/ds/bin/stop-server
/opt/ds/bin/restore --backupDirectory /opt/dirbackups/userRoot
/opt/ds/bin/start-server

Dans les messages de démarrage, on note :

[18/Mar/2018:14:04:03.841 +0000] category=REPLICATION severity=NOTICE msgID=15138895 msg="The following error has been received: <Replication server (23703) at ping1.arciam.fr:1389 is waiting for replicas in domain dc=example,dc=com to be reinitialized. Replication will not resume in this domain until the initialization is complete and dsreplication post-external-initialization has been executed>"

On vérifie que les données sont présentes :

bin/ldapsearch -b dc=example,dc=com uid=user.20* dn

dn: uid=user.20,ou=People,dc=example,dc=com

dn: uid=user.200,ou=People,dc=example,dc=com

dn: uid=user.201,ou=People,dc=example,dc=com

dn: uid=user.204,ou=People,dc=example,dc=com

dn: uid=user.206,ou=People,dc=example,dc=com

dn: uid=user.205,ou=People,dc=example,dc=com

dn: uid=user.207,ou=People,dc=example,dc=com

dn: uid=user.202,ou=People,dc=example,dc=com

dn: uid=user.203,ou=People,dc=example,dc=com

dn: uid=user.208,ou=People,dc=example,dc=com

dn: uid=user.209,ou=People,dc=example,dc=com

dn: uid=user.2000,ou=People,dc=example,dc=com

# Result Code:  0 (success)
# Number of Entries Returned:  12

Si on vérifie l'état de la réplication, on constate bien que notre serveur est à un niveau différent :

          --- Replication Status for dc=example,dc=com: Enabled (pending external initialization) ---
Server               : Location : Entries : Conflict Entries : Backlog : Recent Change Rate : Oldest Backlog Change Age : Generation ID : Server ID : Replica ID
---------------------:----------:---------:------------------:---------:--------------------:---------------------------:---------------:-----------:-----------
ping1.arciam.fr:1389 : france   : 2004    : 0                : 0       : 0                  : 0 seconds                 : 2857013720    : 900       : 23703
ping2.arciam.fr:1389 : france   : 1994    : 0                : 0       : 0                  : 0 seconds                 : 2320536041    : 614       : 1053

On peut alors remettre en route la réplication, en réinitialisant les serveurs du domaine.

/opt/ds/bin/dsreplication initialize --hostSource ping1.arciam.fr --portSource 1389 \
--hostDestination ping2.arciam.fr --portDestination 1389 \
--adminUID admin --adminPassword MyStrongPassw0rd --baseDN dc=example,dc=com --no-prompt

On vérifie l'état de la réplication :

          --- Replication Status for dc=example,dc=com: Enabled ---
Server               : Location : Entries : Conflict Entries : Backlog : Recent Change Rate : Oldest Backlog Change Age : Generation ID : Server ID : Replica ID
---------------------:----------:---------:------------------:---------:--------------------:---------------------------:---------------:-----------:-----------
ping1.arciam.fr:1389 : france   : 2004    : 0                : 0       : 0                  : 0 seconds                 : 2857013720    : 900       : 23703
ping2.arciam.fr:1389 : france   : 2004    : 0                : 0       : 0                  : 0 seconds                 : 2857013720    : 614       : 1053

Dernière étape, lancer l'utilitaire dsreplication avec l'option post-external-initialization :

bin/dsreplication post-external-initialization --hostname ping1.arciam.fr \
--port 1389 --baseDN dc=example,dc=com --adminUID admin \
--adminPassword MyStrongPassw0rd --no-prompt

Si on ajoute une entrée sur l'annuaire 2, on peut vérifier qu'elle est ajoutée sur l'annuaire 1 :

         --- Replication Status for dc=example,dc=com: Enabled ---
Server               : Location : Entries : Conflict Entries : Backlog : Recent Change Rate : Oldest Backlog Change Age : Generation ID : Server ID : Replica ID
---------------------:----------:---------:------------------:---------:--------------------:---------------------------:---------------:-----------:-----------
ping1.arciam.fr:1389 : france   : 2005    : 0                : 0       : 0                  : 0 seconds                 : 2857013720    : 900       : 23703
ping2.arciam.fr:1389 : france   : 2005    : 0                : 0       : 0                  : 0 seconds                 : 2857013720    : 614       : 1053

Synthèse

Si on veut restaurer une sauvegarde dans une architecture d'annuaires répliqués, il est nécessaire de suivre un processus spécifique.

Dans ce cas, il ne suffit pas de restaurer sur une machine, puisqu'au démarrage elle va reprendre ses données à partir des autres annuaires.

La démarche est donc la suivante :

  • lancer l'utilitaire dsreplication avec l'option pre-external-initialization pour stopper la réplication dans le domaine
  • arrêter l'annuaire qui doit être restauré
  • lancer la restauration
  • redémarrer l'annuaire
  • lancer l'initialisation de la réplication dans le domaine
  • lancer l'utilitaire dsreplication avec l'option post-external-initialization pour remettre en route la réplication dans le domaine
Catégorie