doc-locale/fr-fr/administration/backup_restore/troubleshooting_backup_gitlab.md
Lorsque vous sauvegardez GitLab, vous pouvez rencontrer les problèmes suivants.
Si vous n'avez pas sauvegardé le fichier de secrets, vous devez effectuer plusieurs étapes pour que GitLab fonctionne à nouveau correctement.
Le fichier de secrets est responsable du stockage de la clé de chiffrement pour les colonnes contenant des informations requises et sensibles. Si la clé est perdue, GitLab ne peut pas déchiffrer ces colonnes, ce qui empêche l'accès aux éléments suivants :
Dans des cas tels que les variables CI/CD et l'authentification des runners, vous pouvez rencontrer des comportements inattendus, tels que :
Dans ce cas, vous devez réinitialiser tous les jetons pour les variables CI/CD et l'authentification des runners, ce qui est décrit plus en détail dans les sections suivantes. Après avoir réinitialisé les jetons, vous devriez pouvoir visiter votre projet et les jobs recommenceront à s'exécuter.
[!warning] Les étapes de cette section peuvent potentiellement entraîner une perte de données sur les éléments précédemment listés. Envisagez d'ouvrir une demande d'assistance si vous êtes un client Premium ou Ultimate.
Vous pouvez déterminer si votre base de données contient des valeurs qui ne peuvent pas être déchiffrées en utilisant une tâche Rake.
Vous devez modifier directement les données GitLab pour contourner le problème de votre fichier de secrets perdu.
[!warning] Assurez-vous de créer une sauvegarde complète de la base de données avant de tenter toute modification.
Les utilisateurs avec la uthentification à deux facteurs activée ne peuvent pas se connecter à GitLab. Dans ce cas, vous devez désactiver la 2FA pour tous les utilisateurs, après quoi les utilisateurs devront réactiver la 2FA.
Accédez à la console de base de données :
Pour le package Linux (Omnibus) :
sudo gitlab-rails dbconsole --database main
Pour les installations auto-compilées :
sudo -u git -H bundle exec rails dbconsole -e production --database main
Examinez les tables ci_group_variables et ci_variables :
SELECT * FROM public."ci_group_variables";
SELECT * FROM public."ci_variables";
Ce sont les variables que vous devez supprimer.
Supprimez toutes les variables :
DELETE FROM ci_group_variables;
DELETE FROM ci_variables;
Si vous connaissez le groupe ou le projet spécifique à partir duquel vous souhaitez supprimer des variables, vous pouvez inclure une instruction WHERE pour le préciser dans votre DELETE :
DELETE FROM ci_group_variables WHERE group_id = <GROUPID>;
DELETE FROM ci_variables WHERE project_id = <PROJECTID>;
Vous devrez peut-être reconfigurer ou redémarrer GitLab pour que les modifications prennent effet.
Accédez à la console de base de données :
Pour le package Linux (Omnibus) :
sudo gitlab-rails dbconsole --database main
Pour les installations auto-compilées :
sudo -u git -H bundle exec rails dbconsole -e production --database main
Effacez tous les jetons pour les projets, les groupes et l'instance entière :
[!warning] La dernière opération
UPDATEempêche les runners de pouvoir récupérer de nouveaux jobs. Vous devez enregistrer de nouveaux runners.
-- Clear project tokens
UPDATE projects SET runners_token = null, runners_token_encrypted = null;
-- Clear group tokens
UPDATE namespaces SET runners_token = null, runners_token_encrypted = null;
-- Clear instance tokens
UPDATE application_settings SET runners_registration_token_encrypted = null;
-- Clear key used for JWT authentication
-- This may break the $CI_JWT_TOKEN job variable:
-- https://gitlab.com/gitlab-org/gitlab/-/issues/325965
UPDATE application_settings SET encrypted_ci_jwt_signing_key = null;
-- Clear runner tokens
UPDATE ci_runners SET token = null, token_encrypted = null;
Accédez à la console de base de données :
Pour le package Linux (Omnibus) :
sudo gitlab-rails dbconsole --database main
Pour les installations auto-compilées :
sudo -u git -H bundle exec rails dbconsole -e production --database main
Effacez tous les jetons pour les jobs en attente :
-- Clear build tokens
UPDATE ci_builds SET token_encrypted = null;
Une stratégie similaire peut être employée pour les fonctionnalités restantes. En supprimant les données qui ne peuvent pas être déchiffrées, GitLab peut être remis en fonctionnement, et les données perdues peuvent être remplacées manuellement.
Si vous avez perdu vos secrets, les pages paramètres des intégrations et paramètres des webhooks peuvent afficher des messages d'erreur 500. Des secrets perdus peuvent également produire des erreurs 500 lorsque vous tentez d'accéder à un dépôt dans un projet avec une intégration ou un webhook précédemment configuré.
La solution consiste à tronquer les tables affectées (celles contenant des colonnes chiffrées). Cela supprime toutes vos intégrations configurées, vos webhooks et les métadonnées associées. Vous devez vérifier que les secrets sont la cause première avant de supprimer des données.
Accédez à la console de base de données :
Pour le package Linux (Omnibus) :
sudo gitlab-rails dbconsole --database main
Pour les installations auto-compilées :
sudo -u git -H bundle exec rails dbconsole -e production --database main
Tronquez les tables suivantes :
-- truncate web_hooks table
TRUNCATE integrations, chat_names, issue_tracker_data, jira_tracker_data, slack_integrations, web_hooks, zentao_tracker_data, web_hook_logs CASCADE;
Si vous restaurez une sauvegarde depuis un environnement qui utilise le registre de conteneurs vers un environnement nouvellement installé où le registre de conteneurs n'est pas activé, le registre de conteneurs n'est pas restauré.
Pour restaurer également le registre de conteneurs, vous devez l'activer dans le nouvel environnement avant de restaurer la sauvegarde.
Si vous utilisez le registre de conteneurs, les push vers le registre peuvent échouer après la restauration de votre sauvegarde sur une instance de package Linux (Omnibus) après la restauration des données du registre.
Ces échecs mentionnent des problèmes de permissions dans les journaux du registre, similaires à :
level=error
msg="response completed with error"
err.code=unknown
err.detail="filesystem: mkdir /var/opt/gitlab/gitlab-rails/shared/registry/docker/registry/v2/repositories/...: permission denied"
err.message="unknown error"
Ce problème est causé par la restauration s'exécutant en tant qu'utilisateur non privilégié git, qui est incapable d'attribuer la propriété correcte aux fichiers du registre pendant le processus de restauration (issue #62759).
Pour remettre votre registre en fonctionnement :
sudo chown -R registry:registry /var/opt/gitlab/gitlab-rails/shared/registry/docker
Si vous avez modifié l'emplacement par défaut du système de fichiers pour le registre, exécutez chown sur votre emplacement personnalisé, plutôt que /var/opt/gitlab/gitlab-rails/shared/registry/docker.
Lors de l'exécution de la sauvegarde, vous pouvez recevoir un message d'erreur Gzip :
sudo /opt/gitlab/bin/gitlab-backup create
...
Dumping ...
...
gzip: stdout: Input/output error
Backup failed
Si cela se produit, examinez les éléments suivants :
timeout est définie. La valeur par défaut est 600, et la réduire à des valeurs plus petites entraîne cette erreur.File name too long {#backup-fails-with-file-name-too-long-error}Pendant la sauvegarde, vous pouvez obtenir l'erreur File name too long (issue #354984). Par exemple :
Problem: <class 'OSError: [Errno 36] File name too long:
Ce problème empêche le script de sauvegarde de se terminer. Pour résoudre ce problème, vous devez tronquer les noms de fichiers à l'origine du problème. Un maximum de 246 caractères, extension de fichier incluse, est autorisé.
[!warning] Les étapes de cette section peuvent potentiellement entraîner une perte de données. Toutes les étapes doivent être suivies strictement dans l'ordre indiqué. Envisagez d'ouvrir une demande d'assistance si vous êtes un client Premium ou Ultimate.
La troncature des noms de fichiers pour résoudre l'erreur implique :
Un problème connu a entraîné la conservation des téléversements dans le stockage d'objets après la suppression d'une ressource parente. Ce problème a été résolu.
Pour corriger ces fichiers, vous devez nettoyer tous les fichiers téléversés à distance qui se trouvent dans le stockage mais ne sont pas suivis dans la table de base de données uploads.
Listez tous les fichiers de téléversement du stockage d'objets qui peuvent être déplacés vers un répertoire des objets trouvés s'ils n'existent pas dans la base de données GitLab :
bundle exec rake gitlab:cleanup:remote_upload_files RAILS_ENV=production
Si vous êtes sûr de vouloir supprimer ces fichiers et retirer tous les fichiers téléversés non référencés, exécutez :
[!warning] L'action suivante est irréversible.
bundle exec rake gitlab:cleanup:remote_upload_files RAILS_ENV=production DRY_RUN=false
Vous devez tronquer les fichiers référencés par la base de données qui causent le problème. Les noms de fichiers référencés par la base de données sont stockés :
uploads.Tronquez les noms de fichiers dans la table uploads :
Accédez à la console de base de données :
Pour le package Linux (Omnibus) :
sudo gitlab-rails dbconsole --database main
Pour les installations auto-compilées :
sudo -u git -H bundle exec rails dbconsole -e production --database main
Recherchez dans la table uploads les noms de fichiers de plus de 246 caractères :
La requête suivante sélectionne les enregistrements uploads dont les noms de fichiers dépassent 246 caractères par lots de 0 à 10000. Cela améliore les performances sur les grandes instances GitLab avec des tables contenant des milliers d'enregistrements.
CREATE TEMP TABLE uploads_with_long_filenames AS
SELECT ROW_NUMBER() OVER(ORDER BY id) row_id, id, path
FROM uploads AS u
WHERE LENGTH((regexp_match(u.path, '[^\\/:*?"<>|\r\n]+$'))[1]) > 246;
CREATE INDEX ON uploads_with_long_filenames(row_id);
SELECT
u.id,
u.path,
-- Current filename
(regexp_match(u.path, '[^\\/:*?"<>|\r\n]+$'))[1] AS current_filename,
-- New filename
CONCAT(
LEFT(SPLIT_PART((regexp_match(u.path, '[^\\/:*?"<>|\r\n]+$'))[1], '.', 1), 242),
COALESCE(SUBSTRING((regexp_match(u.path, '[^\\/:*?"<>|\r\n]+$'))[1] FROM '\.(?:.(?!\.))+$'))
) AS new_filename,
-- New path
CONCAT(
COALESCE((regexp_match(u.path, '(.*\/).*'))[1], ''),
CONCAT(
LEFT(SPLIT_PART((regexp_match(u.path, '[^\\/:*?"<>|\r\n]+$'))[1], '.', 1), 242),
COALESCE(SUBSTRING((regexp_match(u.path, '[^\\/:*?"<>|\r\n]+$'))[1] FROM '\.(?:.(?!\.))+$'))
)
) AS new_path
FROM uploads_with_long_filenames AS u
WHERE u.row_id > 0 AND u.row_id <= 10000;
Exemple de résultat :
-[ RECORD 1 ]----+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
id | 34
path | public/@hashed/loremipsumdolorsitametconsecteturadipiscingelitseddoeiusmodtemporincididuntutlaboreetdoloremagnaaliquaauctorelitsedvulputatemisitloremipsumdolorsitametconsecteturadipiscingelitseddoeiusmodtemporincididuntutlaboreetdoloremagnaaliquaauctorelitsedvulputatemisit.txt
current_filename | loremipsumdolorsitametconsecteturadipiscingelitseddoeiusmodtemporincididuntutlaboreetdoloremagnaaliquaauctorelitsedvulputatemisitloremipsumdolorsitametconsecteturadipiscingelitseddoeiusmodtemporincididuntutlaboreetdoloremagnaaliquaauctorelitsedvulputatemisit.txt
new_filename | loremipsumdolorsitametconsecteturadipiscingelitseddoeiusmodtemporincididuntutlaboreetdoloremagnaaliquaauctorelitsedvulputatemisitloremipsumdolorsitametconsecteturadipiscingelitseddoeiusmodtemporincididuntutlaboreetdoloremagnaaliquaauctorelits.txt
new_path | public/@hashed/loremipsumdolorsitametconsecteturadipiscingelitseddoeiusmodtemporincididuntutlaboreetdoloremagnaaliquaauctorelitsedvulputatemisitloremipsumdolorsitametconsecteturadipiscingelitseddoeiusmodtemporincididuntutlaboreetdoloremagnaaliquaauctorelits.txt
Où :
current_filename : un nom de fichier de plus de 246 caractères.new_filename : un nom de fichier tronqué à 246 caractères maximum.new_path : nouveau chemin tenant compte de new_filename (tronqué).Après avoir validé les résultats du lot, vous devez modifier la taille du lot (row_id) en utilisant la séquence de nombres suivante (10000 à 20000). Répétez ce processus jusqu'à atteindre le dernier enregistrement dans la table uploads.
Renommez les fichiers trouvés dans la table uploads des noms de fichiers longs vers les nouveaux noms de fichiers tronqués. La requête suivante annule la mise à jour afin que vous puissiez vérifier les résultats en toute sécurité dans un wrapper de transaction :
CREATE TEMP TABLE uploads_with_long_filenames AS
SELECT ROW_NUMBER() OVER(ORDER BY id) row_id, path, id
FROM uploads AS u
WHERE LENGTH((regexp_match(u.path, '[^\\/:*?"<>|\r\n]+$'))[1]) > 246;
CREATE INDEX ON uploads_with_long_filenames(row_id);
BEGIN;
WITH updated_uploads AS (
UPDATE uploads
SET
path =
CONCAT(
COALESCE((regexp_match(updatable_uploads.path, '(.*\/).*'))[1], ''),
CONCAT(
LEFT(SPLIT_PART((regexp_match(updatable_uploads.path, '[^\\/:*?"<>|\r\n]+$'))[1], '.', 1), 242),
COALESCE(SUBSTRING((regexp_match(updatable_uploads.path, '[^\\/:*?"<>|\r\n]+$'))[1] FROM '\.(?:.(?!\.))+$'))
)
)
FROM
uploads_with_long_filenames AS updatable_uploads
WHERE
uploads.id = updatable_uploads.id
AND updatable_uploads.row_id > 0 AND updatable_uploads.row_id <= 10000
RETURNING uploads.*
)
SELECT id, path FROM updated_uploads;
ROLLBACK;
Après avoir validé les résultats de la mise à jour du lot, vous devez modifier la taille du lot (row_id) en utilisant la séquence de nombres suivante (10000 à 20000). Répétez ce processus jusqu'à atteindre le dernier enregistrement dans la table uploads.
Validez que les nouveaux noms de fichiers issus de la requête précédente sont bien ceux attendus. Si vous êtes sûr de vouloir tronquer les enregistrements trouvés à l'étape précédente à 246 caractères, exécutez ce qui suit :
[!warning] L'action suivante est irréversible.
CREATE TEMP TABLE uploads_with_long_filenames AS
SELECT ROW_NUMBER() OVER(ORDER BY id) row_id, path, id
FROM uploads AS u
WHERE LENGTH((regexp_match(u.path, '[^\\/:*?"<>|\r\n]+$'))[1]) > 246;
CREATE INDEX ON uploads_with_long_filenames(row_id);
UPDATE uploads
SET
path =
CONCAT(
COALESCE((regexp_match(updatable_uploads.path, '(.*\/).*'))[1], ''),
CONCAT(
LEFT(SPLIT_PART((regexp_match(updatable_uploads.path, '[^\\/:*?"<>|\r\n]+$'))[1], '.', 1), 242),
COALESCE(SUBSTRING((regexp_match(updatable_uploads.path, '[^\\/:*?"<>|\r\n]+$'))[1] FROM '\.(?:.(?!\.))+$'))
)
)
FROM
uploads_with_long_filenames AS updatable_uploads
WHERE
uploads.id = updatable_uploads.id
AND updatable_uploads.row_id > 0 AND updatable_uploads.row_id <= 10000;
Après avoir terminé la mise à jour du lot, vous devez modifier la taille du lot (updatable_uploads.row_id) en utilisant la séquence de nombres suivante (10000 à 20000). Répétez ce processus jusqu'à atteindre le dernier enregistrement dans la table uploads.
Tronquez les noms de fichiers dans les références trouvées :
Vérifiez si ces enregistrements sont référencés quelque part. Une façon de procéder est de vider la base de données et de rechercher le nom du répertoire parent et le nom du fichier :
Pour vider votre base de données, vous pouvez utiliser la commande suivante comme exemple :
pg_dump -h /var/opt/gitlab/postgresql/ -d gitlabhq_production > gitlab-dump.tmp
Vous pouvez ensuite rechercher les références à l'aide de la commande grep. Combiner le répertoire parent et le nom du fichier peut être une bonne idée. Par exemple :
grep public/alongfilenamehere.txt gitlab-dump.tmp
Remplacez ces noms de fichiers longs par les nouveaux noms de fichiers obtenus en interrogeant la table uploads.
Tronquez les noms de fichiers sur le système de fichiers. Vous devez renommer manuellement les fichiers dans votre système de fichiers avec les nouveaux noms de fichiers obtenus en interrogeant la table uploads.
Après avoir suivi toutes les étapes précédentes, réexécutez la tâche de sauvegarde.
pg_stat_statements était précédemment activé {#restoring-database-backup-fails-when-pg_stat_statements-was-previously-enabled}La sauvegarde GitLab de la base de données PostgreSQL inclut toutes les instructions SQL nécessaires pour activer les extensions qui étaient précédemment activées dans la base de données.
L'extension pg_stat_statements ne peut être activée ou désactivée que par un utilisateur PostgreSQL ayant le rôle superuser. Étant donné que le processus de restauration utilise un utilisateur de base de données avec des permissions limitées, il ne peut pas exécuter les instructions SQL suivantes :
DROP EXTENSION IF EXISTS pg_stat_statements;
CREATE EXTENSION IF NOT EXISTS pg_stat_statements WITH SCHEMA public;
Lors de la tentative de restauration de la sauvegarde dans une instance PostgreSQL qui ne dispose pas de l'extension pg_stats_statements, le message d'erreur suivant s'affiche :
ERROR: permission denied to create extension "pg_stat_statements"
HINT: Must be superuser to create this extension.
ERROR: extension "pg_stat_statements" does not exist
Lors de la tentative de restauration dans une instance où l'extension pg_stats_statements est activée, l'étape de nettoyage échoue avec un message d'erreur similaire au suivant :
rake aborted!
ActiveRecord::StatementInvalid: PG::InsufficientPrivilege: ERROR: must be owner of view pg_stat_statements
/opt/gitlab/embedded/service/gitlab-rails/lib/tasks/gitlab/db.rake:42:in `block (4 levels) in <top (required)>'
/opt/gitlab/embedded/service/gitlab-rails/lib/tasks/gitlab/db.rake:41:in `each'
/opt/gitlab/embedded/service/gitlab-rails/lib/tasks/gitlab/db.rake:41:in `block (3 levels) in <top (required)>'
/opt/gitlab/embedded/service/gitlab-rails/lib/tasks/gitlab/backup.rake:71:in `block (3 levels) in <top (required)>'
/opt/gitlab/embedded/bin/bundle:23:in `load'
/opt/gitlab/embedded/bin/bundle:23:in `<main>'
Caused by:
PG::InsufficientPrivilege: ERROR: must be owner of view pg_stat_statements
/opt/gitlab/embedded/service/gitlab-rails/lib/tasks/gitlab/db.rake:42:in `block (4 levels) in <top (required)>'
/opt/gitlab/embedded/service/gitlab-rails/lib/tasks/gitlab/db.rake:41:in `each'
/opt/gitlab/embedded/service/gitlab-rails/lib/tasks/gitlab/db.rake:41:in `block (3 levels) in <top (required)>'
/opt/gitlab/embedded/service/gitlab-rails/lib/tasks/gitlab/backup.rake:71:in `block (3 levels) in <top (required)>'
/opt/gitlab/embedded/bin/bundle:23:in `load'
/opt/gitlab/embedded/bin/bundle:23:in `<main>'
Tasks: TOP => gitlab:db:drop_tables
(See full trace by running task with --trace)
pg_stat_statements {#prevent-the-dump-file-to-include-pg_stat_statements}Pour éviter l'inclusion de l'extension dans le fichier de dump PostgreSQL faisant partie du bundle de sauvegarde, activez l'extension dans tout schéma sauf le schéma public :
CREATE SCHEMA adm;
CREATE EXTENSION pg_stat_statements SCHEMA adm;
Si l'extension était précédemment activée dans le schéma public, déplacez-la vers un nouveau schéma :
CREATE SCHEMA adm;
ALTER EXTENSION pg_stat_statements SET SCHEMA adm;
Pour interroger les données pg_stat_statements après avoir modifié le schéma, préfixez le nom de la vue avec le nouveau schéma :
SELECT * FROM adm.pg_stat_statements limit 0;
Pour le rendre compatible avec des solutions de surveillance tierces qui s'attendent à ce qu'il soit activé dans le schéma public, vous devez l'inclure dans le search_path :
set search_path to public,adm;
pg_stat_statements {#fix-an-existing-dump-file-to-remove-references-to-pg_stat_statements}Pour corriger un fichier de sauvegarde existant, effectuez les modifications suivantes :
Extrayez de la sauvegarde le fichier suivant : db/database.sql.gz.
Décompressez le fichier ou utilisez un éditeur capable de le gérer compressé.
Supprimez les lignes suivantes, ou des lignes similaires :
CREATE EXTENSION IF NOT EXISTS pg_stat_statements WITH SCHEMA public;
COMMENT ON EXTENSION pg_stat_statements IS 'track planning and execution statistics of all SQL statements executed';
Enregistrez les modifications et recompressez le fichier.
Mettez à jour le fichier de sauvegarde avec le fichier modifié db/database.sql.gz.