Aller au contenu principal

Navidrome sur GKE Autopilot

Navidrome sur GKE Autopilot

Navidrome est un serveur de streaming musical gratuit, open source et auto-hébergé, écrit en Go. Il expose une API compatible Subsonic/OpenSubsonic (de sorte que n'importe quel client Subsonic — DSub, Symfonium, Sublime Music, play:Sub, etc. — peut parcourir et diffuser votre bibliothèque) ainsi que sa propre interface web, et stocke son état dans une base de données SQLite embarquée plutôt que dans un backend SQL géré. Ce module déploie Navidrome sur GKE Autopilot en s'appuyant sur le socle App_GKE, qui provisionne et gère l'infrastructure Google Cloud et Kubernetes partagée.

Ce guide se concentre sur les services cloud qu'utilise Navidrome et sur la manière de les explorer et de les exploiter depuis la console Google Cloud et la ligne de commande. Pour les mécanismes communs à toutes les applications GKE — Workload Identity, ingress, autoscaling, CI/CD, Cloud Armor, IAP, Binary Authorization, VPC Service Controls, sauvegardes et cycle de vie du déploiement — reportez-vous au guide du socle App_GKE plutôt que de les répéter ici.


1. Vue d'ensemble​

Navidrome s'exécute sous la forme d'un unique binaire Go servant HTTP sur un seul port. Comme il n'a pas de base de données externe, le déploiement assemble un ensemble de services Google Cloud plus restreint qu'une application classique adossée à une base de données :

FonctionnalitéService Google CloudRemarques
CalculGKE AutopilotUn pod StatefulSet sur le port 4533, 1 vCPU / 1 GiB par défaut
Données applicativesPVC de stockage en mode bloc (Persistent Disk, via stateful_pvc_enabled)Sert de support à la base SQLite embarquée, au cache des pochettes et à l'index de recherche sous /data — pas Cloud SQL
Bibliothèque musicaleVolume GCS FUSE ou Cloud Filestore (NFS) fourni par l'opérateur sur /musicFichiers audio sources en lecture seule ; non provisionnés automatiquement
Stockage objetCloud StorageUn bucket storage est toujours créé mais reste non monté tant que le PVC en mode bloc par défaut gère /data
SecretsSecret ManagerUn mot de passe administrateur généré automatiquement (ND_DEVAUTOCREATEADMINPASSWORD), injecté sous forme de Secret Kubernetes natif
IngressKubernetes Gateway API / ClusterIPPas de LoadBalancer par défaut — accès interne uniquement tant qu'un domaine personnalisé ou une modification de service_type n'est pas configuré

Valeurs par défaut judicieuses à connaître d'emblée :

  • Pas de base de données SQL. database_type est fixé à NONE par Navidrome_Common ; chaque variable db_*/database_*/sql_instance_* de ce module est transmise au socle uniquement par compatibilité structurelle et n'a aucun effet.
  • SQLite a besoin d'un vrai PVC en mode bloc, pas de gcsfuse. Selon la convention de stockage de ce dépôt, gcsfuse ne peut pas servir de support fiable au modèle de verrouillage en écriture de SQLite. GKE donne ici à Navidrome un réel avantage sur la variante Cloud Run : stateful_pvc_enabled vaut true par défaut, ce qui provisionne un Persistent Disk par pod monté sur /data (ND_DATAFOLDER) contenant la base SQLite, le cache des pochettes et l'index de recherche. La charge de travail est alors résolue automatiquement en StatefulSet.
  • La classe de stockage du PVC est standard-rwo (SSD Balanced PD) par défaut. Elle consomme le quota régional SSD_TOTAL_GB, très limité, documenté dans les conventions de stockage de ce dépôt. Le répertoire de données de Navidrome a la taille de métadonnées/d'un index, pas celle de médias volumineux ; le SSD est donc raisonnable ici — mais sur un projet soumis à des contraintes de quota, envisagez -var stateful_pvc_storage_class=standard (HDD pd-standard) si vous rencontrez Quota 'SSD_TOTAL_GB' exceeded sur un ensemble plus large d'applications avec état.
  • La bibliothèque musicale n'est pas montée automatiquement. ND_MUSICFOLDER=/music est défini comme variable d'environnement, mais aucun volume n'est attaché à /music par défaut — vous devez ajouter un volume GCS FUSE en lecture seule (gcs_volumes) ou un montage NFS (enable_nfs = true, nfs_mount_path = "/music") pointant vers vos fichiers audio sources. Contrairement à /data, /music est en lecture seule et ne contient aucun état SQLite ; gcsfuse convient donc pour celui-ci.
  • Un seul réplica par défaut. min_instance_count = 1, max_instance_count = 1. Navidrome sert une unique bibliothèque SQLite partagée depuis un seul PVC ; il n'existe aucun mode multi-écrivain/cluster, ne dépassez donc pas 1.
  • Pas d'ingress externe par défaut. service_type = "ClusterIP" et enable_custom_domain = true mais avec une liste application_domains vide — par défaut, Navidrome n'est donc accessible qu'à l'intérieur du cluster/VPC. Définissez application_domains (Gateway + certificat géré) ou passez service_type à LoadBalancer pour l'exposer à l'extérieur.
  • Le compte administrateur est créé automatiquement. enable_admin_password = true génère un mot de passe aléatoire, le stocke dans Secret Manager et l'injecte sous ND_DEVAUTOCREATEADMINPASSWORD afin que Navidrome crée l'utilisateur admin au premier démarrage. Définissez-le à false pour utiliser plutôt l'assistant de configuration web du premier lancement.
  • Les sondes de santé interrogent le point de terminaison public GET /ping (renvoie {"status":"ok"}, aucune authentification requise).

2. Services Google Cloud et comment les explorer​

Toutes les commandes supposent que vous avez exécuté gcloud container clusters get-credentials <cluster> --region "$REGION" --project "$PROJECT" et que PROJECT, REGION et NAMESPACE sont définis. L'espace de noms et les autres identifiants sont indiqués dans les sorties du déploiement.

A. GKE Autopilot — le StatefulSet Navidrome​

Avec la valeur par défaut stateful_pvc_enabled = true, Navidrome est déployé en tant que StatefulSet (et non Deployment) afin que son unique pod conserve une identité stable et un PVC qui survit aux replanifications. Autopilot facture le CPU/la mémoire que le pod demande effectivement.

  • Console : Kubernetes Engine → Workloads → sélectionnez la charge de travail Navidrome pour voir les pods, les révisions et les événements. Vérifiez que le type de charge de travail indique StatefulSet.
  • CLI :
    kubectl get statefulset,pods,svc -n "$NAMESPACE"
    kubectl logs -n "$NAMESPACE" statefulset/<service-name> --tail=100
    kubectl describe pod -n "$NAMESPACE" -l app=<service-name>

Consultez App_GKE pour le fonctionnement général de la planification Autopilot et de la résolution automatique StatefulSet/Deployment.

B. PVC de stockage en mode bloc — le volume de données SQLite​

Le PersistentVolumeClaim par pod sur /data est l'unique source de vérité de Navidrome : la base SQLite, le cache de métadonnées/de pochettes, les fichiers temporaires de transcodage (s'il est activé) et l'index de recherche y résident tous. Perdre ce PVC fait perdre les métadonnées de votre bibliothèque, vos playlists, vos notes et vos utilisateurs (l'audio source lui-même n'est pas affecté, puisque /music est un montage distinct fourni par l'opérateur).

  • Console : Kubernetes Engine → Storage → PersistentVolumeClaims et PersistentVolumes ; Compute Engine → Disks pour voir le Persistent Disk sous-jacent.
  • CLI :
    kubectl get pvc -n "$NAMESPACE"
    kubectl describe pvc -n "$NAMESPACE" -l app=<service-name>
    gcloud compute disks list --project "$PROJECT" --filter="name~<service-name>"

Consultez le groupe 7 d'App_GKE pour l'ensemble des mécanismes stateful_pvc_* (classe de stockage, politique de gestion des pods, stratégie de mise à jour).

C. Stockage de la bibliothèque musicale (GCS FUSE ou NFS)​

/music est l'emplacement où Navidrome recherche les fichiers audio. Rien n'y est monté par défaut — configurez soit un volume GCS FUSE en lecture seule (gcs_volumes, reposant sur le pilote CSI, adapté ici puisque /music ne contient aucun état SQLite) pointant vers un bucket d'audio téléversé, soit un partage Cloud Filestore (NFS) (enable_nfs = true, nfs_mount_path = "/music") si vous avez besoin d'un accès en écriture depuis un autre hôte pour ajouter des fichiers. Un bucket GCS storage distinct, toujours créé, existe par compatibilité avec la variante Cloud Run mais reste non monté tant que le PVC en mode bloc sert /data.

  • Console : Cloud Storage → Buckets ; Filestore → Instances.
  • CLI :
    gcloud storage buckets list --project "$PROJECT" --filter="name~<service-name>"
    gcloud filestore instances list --project "$PROJECT"
    kubectl exec -n "$NAMESPACE" statefulset/<service-name> -- ls /music

Consultez les groupes 13–14 d'App_GKE pour les mécanismes des volumes NFS et GCS Fuse.

D. Secret Manager​

Un secret est généré automatiquement : le mot de passe administrateur, stocké sous secret-<prefix>-navidrome-admin-password et injecté dans le pod sous forme de Secret Kubernetes natif (et non via le pilote Secret Store CSI) pour la variable d'environnement ND_DEVAUTOCREATEADMINPASSWORD, que Navidrome lit au premier démarrage pour créer le compte admin.

  • Console : Security → Secret Manager.
  • CLI :
    gcloud secrets list --project "$PROJECT" --filter="name~navidrome-admin-password"
    gcloud secrets versions access latest --secret=<admin-password-secret-name> --project "$PROJECT"

Consultez App_GKE pour l'intégration générale Secret Manager / Secret Store CSI utilisée par les secrets des autres applications.

E. Réseau et entrée​

Par défaut, service_type = "ClusterIP" et application_domains est vide ; Navidrome n'est donc accessible que depuis l'intérieur du VPC/cluster (http://<service>.<namespace>.svc.cluster.local). Définissez application_domains (avec enable_custom_domain = true, déjà la valeur par défaut du module) pour provisionner une Kubernetes Gateway avec un certificat TLS géré, ou passez service_type à LoadBalancer pour obtenir une simple IP externe.

  • Console : Kubernetes Engine → Services & Ingress ; Network services → Load balancing ; VPC network → IP addresses.
  • CLI :
    kubectl get svc,gateway -n "$NAMESPACE"
    gcloud compute addresses list --project "$PROJECT"

Consultez le groupe 19 d'App_GKE pour les mécanismes de la Gateway API, de l'IP statique et du nom d'hôte nip.io par défaut.

F. Cloud Logging et Monitoring​

Les flux stdout/stderr des pods sont envoyés vers Cloud Logging ; les métriques GKE vers Cloud Monitoring. Des tests de disponibilité et des règles d'alerte facultatifs sont disponibles (uptime_check_config vaut false par défaut).

  • Console : Logging → Logs Explorer ; Monitoring → Dashboards / Alerting.
  • CLI :
    gcloud logging read 'resource.type="k8s_container" AND resource.labels.namespace_name="'"$NAMESPACE"'"' \
    --project "$PROJECT" --limit 50

3. Comportement de l'application Navidrome​

  • Pas de job d'initialisation/de migration. Navidrome n'a pas de base de données externe ; il n'y a donc aucun Job db-init ni de migration — le schéma SQLite est créé par le binaire lui-même au premier démarrage sur le PVC /data vide. initialization_jobs vaut [] par défaut et ne sert qu'à des tâches personnalisées fournies par l'opérateur.
  • Amorçage de l'administrateur. Avec enable_admin_password = true (valeur par défaut), le conteneur démarre avec ND_DEVAUTOCREATEADMINPASSWORD défini à partir du secret généré, et Navidrome crée automatiquement l'utilisateur admin avec ce mot de passe au premier démarrage. Avec enable_admin_password = false, la première personne qui ouvre l'interface web termine l'assistant de configuration et choisit ses propres identifiants administrateur — recommandé uniquement pour des déploiements internes au cluster, à accès de confiance.
  • Identité du PVC quasi immuable. Comme le pod est un StatefulSet, le PVC est lié à l'identité stable du pod (<service-name>-0) et survit aux replanifications/redémarrages du pod. Porter max_instance_count au-delà de 1 n'est pas pris en charge — Navidrome n'a aucun mode SQLite multi-écrivain.
  • Chemin de contrôle d'état. La sonde de démarrage et la sonde de vivacité sont toutes deux des requêtes HTTP GET /ping, un point de terminaison non authentifié qui renvoie {"status":"ok"}. Prévoyez quelques minutes au premier démarrage pendant l'analyse de la bibliothèque (les grandes bibliothèques prennent plus de temps).
  • Analyse de la bibliothèque. Navidrome analyse /music au démarrage puis selon une planification périodique ; la progression et les résultats de l'analyse sont visibles dans les journaux du pod et dans l'interface web.
  • Vérifiez la configuration en cours d'exécution et le montage de la bibliothèque :
    kubectl exec -n "$NAMESPACE" statefulset/<service-name> -- env | grep ^ND_
    kubectl exec -n "$NAMESPACE" statefulset/<service-name> -- ls /music
    kubectl logs -n "$NAMESPACE" statefulset/<service-name> --tail=50 | grep -i scan

4. Variables de configuration​

Les variables sont regroupées exactement comme elles apparaissent sur la plateforme de déploiement. Seuls les paramètres propres à Navidrome ou notables pour lui sont listés ; toutes les autres entrées sont héritées d'App_GKE avec leur comportement et leurs valeurs par défaut standard.

Groupe 3 — Identité de l'application​

VariableValeur par défautDescription
application_namenavidromeNom de base des ressources. Ne le modifiez pas après le premier déploiement.
application_versionlatestTag de l'image deluan/navidrome utilisé comme base du build personnalisé ; latest est fixé à un tag éprouvé (0.54.3) au moment du build.
application_display_nameNavidrome Music ServerNom lisible affiché dans l'interface de la plateforme.
enable_admin_passwordtrueGénère automatiquement le mot de passe administrateur et crée l'utilisateur admin au premier démarrage via ND_DEVAUTOCREATEADMINPASSWORD. Définissez false pour utiliser plutôt l'assistant web du premier lancement.

Groupe 4 — Exécution et mise à l'échelle​

VariableValeur par défautDescription
cpu_limit1000m1 vCPU ; augmentez-le pour le transcodage à la volée, qui sollicite fortement le CPU.
memory_limit1GiNavidrome conserve son index de recherche en mémoire ; dimensionnez selon la taille de la bibliothèque.
min_instance_count1Conservez 1 — évite les démarrages à froid pendant le chargement de l'index/de la bibliothèque.
max_instance_count1Conservez 1. Aucune prise en charge de SQLite multi-écrivain.
enable_cloudsql_volumefalseNavidrome n'a pas de base de données Cloud SQL — conservez false.

Groupe 6 — Backend GKE et cluster​

VariableValeur par défautDescription
workload_typenull → StatefulSetRésolu automatiquement en StatefulSet car stateful_pvc_enabled = true.
service_typeLoadBalancerAccessible depuis l'extérieur par défaut — une IP externe est provisionnée. Définissez ClusterIP pour un accès interne uniquement ; accédez-y alors via un domaine personnalisé ou kubectl port-forward.
session_affinityNoneAucun routage persistant nécessaire avec un seul réplica.

Groupe 7 — StatefulSet / PVC​

VariableValeur par défautDescription
stateful_pvc_enabledtrueProvisionne un vrai PVC en mode bloc sur /data — nécessaire pour que gcsfuse ne serve jamais de support à la base SQLite embarquée.
stateful_pvc_size20GiDimensionné pour la base SQLite, le cache de métadonnées et l'index de recherche (pas pour la bibliothèque musicale, montée séparément).
stateful_pvc_mount_path/dataDoit correspondre au ND_DATAFOLDER de Navidrome.
stateful_pvc_storage_classstandard-rwoSSD Balanced PD par défaut ; passez à standard (HDD) si le quota SSD_TOTAL_GB est contraint.
stateful_fs_group3000Correspond à la convention UID 1000/GID 2000 du chart Helm de Navidrome, garantissant que le PVC est accessible en écriture par le groupe.

Groupe 13 — Stockage NFS​

VariableValeur par défautDescription
enable_nfsfalseActivez-le et définissez nfs_mount_path = "/music" pour monter une bibliothèque musicale partagée, accessible en écriture, via Cloud Filestore.
nfs_mount_path/mnt/nfsPas /music par défaut — doit être remplacé si vous utilisez NFS pour la bibliothèque.

Groupe 14 — Cloud Storage​

VariableValeur par défautDescription
create_cloud_storagetrueCrée toujours le bucket storage ; il reste non monté tant que le PVC en mode bloc par défaut sert /data.
gcs_volumes[]Ajoutez une entrée en lecture seule avec mount_path = "/music" pour alimenter votre bibliothèque depuis GCS plutôt que NFS.

Groupe 16 — Configuration de la base de données​

VariableValeur par défautDescription
database_typeNONEFixé par Navidrome_Common — Navidrome n'a pas de base de données SQL ; toutes les autres variables database_*/sql_* sont sans effet.

Groupe 19 — Domaine personnalisé, IP statique et réseau​

VariableValeur par défautDescription
enable_custom_domaintrueProvisionne la ressource Gateway, mais n'a aucun effet tant que application_domains est vide.
application_domains[]À définir pour exposer Navidrome à l'extérieur via Gateway + certificat géré.
reserve_static_iptrueIP stable une fois l'ingress externe (LoadBalancer ou Gateway) configuré.

Toutes les autres entrées suivent le comportement standard d'App_GKE.


5. Sorties​

Ces valeurs sont renvoyées lors d'un déploiement réussi et constituent le moyen le plus rapide de localiser et d'explorer les ressources en cours d'exécution.

SortieDescription
service_nameNom du Service Kubernetes.
namespaceEspace de noms dans lequel s'exécute la charge de travail.
service_cluster_ipClusterIP interne au cluster.
stage_service_cluster_ipsTable des ClusterIP des services propres à chaque étape.
service_external_ipIP externe du LoadBalancer (lorsque service_type = LoadBalancer et qu'une IP statique est réservée).
service_urlURL pour accéder à Navidrome.
navidrome_admin_password_secret_idID du secret Secret Manager du mot de passe administrateur généré (vide lorsque enable_admin_password = false).
storage_bucketsBuckets Cloud Storage créés.
network_name / network_exists / regionsRéseau VPC, présence, régions disponibles.
container_image / container_registryImage déployée et dépôt Artifact Registry.
monitoring_enabled / monitoring_notification_channelsÉtat de la surveillance et canaux.
deployment_id / tenant_id / resource_prefixIdentifiants de nommage.
project_id / project_numberIdentifiants du projet.
initialization_jobsNoms des éventuels jobs d'initialisation fournis par l'opérateur.
statefulset_nameNom du StatefulSet.
cicd_enabled / cicd_configurationÉtat et détails de la CI/CD (dépôt, déclencheur, registre).
github_repository_url / github_repository_owner / github_repository_nameDétails GitHub de la CI/CD.
artifact_registry_repository / cloudbuild_trigger_name / cloudbuild_trigger_idRegistre et déclencheur de build.
kubernetes_readyIndique si le cluster/la charge de travail est prêt.
vpc_sc_enabled / vpc_sc_perimeter_name / vpc_sc_dry_run_modeÉtat de VPC-SC.
audit_logging_enabled / artifact_registry_cmek_enabledÉtat de la journalisation d'audit et de CMEK.

6. Pièges de configuration et valeurs par défaut judicieuses​

Risque : Critique (perte de données / panne / sécurité) — Élevé (service dégradé) — Moyen (coût ou dégradation partielle) — Faible (mineur).

Validation héritée au moment du plan. Ce module fait passer sa configuration par le moteur du socle App_GKE, qui valide les valeurs et leurs combinaisons au moment du plan — un StatefulSet forcé avec un paramètre sans état, IAP sans identité autorisée, des quota_memory_* donnés sous forme d'entiers nus, un container_port/backup_retention_days hors plage. Une configuration invalide fait échouer le plan avec une erreur claire et nommée avant la création de toute ressource ; la plupart des erreurs ci-dessous sont donc détectées en amont plutôt qu'à l'application ou à l'exécution.

ParamètreValeur judicieuseRisqueConséquence en cas d'erreur
stateful_pvc_enabledtrueCritiqueLe désactiver (ou faire reposer /data sur gcsfuse d'une autre manière) risque de corrompre le modèle de verrouillage en écriture de SQLite — corruption de la base, perte des métadonnées de la bibliothèque.
stateful_pvc_storage_classstandard-rwo (ou standard en cas de pression sur le quota)ÉlevéLe SSD consomme le quota régional SSD_TOTAL_GB, très limité ; un large ensemble d'applications avec état peut l'épuiser — passez alors au HDD standard.
max_instance_count1CritiqueNavidrome n'a aucun mode SQLite multi-écrivain ; dépasser 1 risque des écritures concurrentes sur le même PVC et une corruption de la base.
Volume /music (gcs_volumes ou enable_nfs)Configurer explicitementÉlevéRien n'est monté sur /music par défaut — l'analyse de la bibliothèque ne trouve aucun fichier et Navidrome sert un catalogue vide tant qu'aucun volume n'est ajouté.
enable_admin_passwordtrue pour tout déploiement accessible depuis l'extérieurÉlevéfalse laisse l'assistant du premier lancement exposé à la première personne qui atteint l'URL — elle devient administrateur.
application_domains / service_typeDéfinir l'un des deux pour exposer à l'extérieurMoyenLa combinaison par défaut ClusterIP + application_domains vide rend Navidrome accessible uniquement à l'intérieur du VPC — normal pour un usage interne, surprenant si vous vouliez un accès public.
stateful_pvc_size20Gi (à augmenter pour les très grandes bibliothèques)MoyenUn sous-dimensionnement risque que la base SQLite/le cache/l'index remplissent le PVC sur les grandes bibliothèques ; le pod n'étend pas automatiquement le stockage.
quota_cpu_requests / quota_memory_requests / etc.N/AFaibleCes variables quota_* sont déclarées mais non transmises au socle par ce module — les définir n'a aucun effet ; seul enable_resource_quota est relayé (en se rabattant sur les valeurs de quota par défaut d'App_GKE).
memory_limit1GiMoyenEn dessous d'environ 512Mi, le pod risque un OOM en conservant l'index de recherche en mémoire pendant l'analyse d'une grande bibliothèque.
stateful_fs_group3000MoyenUn fsGroup incohérent peut rendre le PVC non inscriptible par l'UID non root de Navidrome, bloquant les écritures de la base au démarrage.
backup_retention_days7 (à augmenter en production)FaibleTrop court pour une conservation conforme des sauvegardes de /data.

Pour le comportement du socle évoqué tout au long de ce guide — IAM et Workload Identity, autoscaling, ingress et certificats, CI/CD, Cloud Armor, IAP, Binary Authorization, VPC-SC, sauvegardes et mise en miroir des images — consultez App_GKE. La configuration applicative propre à Navidrome partagée avec la variante Cloud Run est décrite dans Navidrome_Common.

Need RAD to do something it does not do yet? Request it on the roadmap, or vote on what is already there.