Si vous ne savez pas ce qu’est Dependency Track, je vous invite à lire mon article d’introduction.
Voyons maintenant comment le déployer sur Kubernetes en GitOps avec ArgoCD, sans jamais lancer un helm install à la main.
Pré-requis
- Un cluster Kubernetes fonctionnel, managé (GKE, EKS, AKS) ou local (Kind, Minikube, K3s)
- Helm installé et configuré
- Une instance ArgoCD pour le déploiement en GitOps
Le pattern App of Apps
Le pattern App of Apps consiste à créer une application principale (l’“App of Apps”) qui référence d’autres applications (les “child apps”). Cela permet de regrouper plusieurs applications sous une même hiérarchie et de les gérer de manière centralisée.
root/
├── apps/
│ └── dependency-track.yaml
└── root-app.yaml
root-app.yaml est l’application principale, qui scrute le dossier apps/. Pour déployer une application supplémentaire par la suite, il suffit de créer une nouvelle ressource Application dans ce dossier : c’est tout l’intérêt du pattern, l’ajout d’un outil dans le cluster devient un simple fichier à commiter.
Configuration
root-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: root-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/votre-user/votre-repo
targetRevision: main
path: apps
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: true
apps/dependency-track.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: dependency-track
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/votre-user/votre-repo
targetRevision: main
path: dependency-track
helm:
valueFiles:
- values.yaml
destination:
server: https://kubernetes.default.svc
namespace: dependency-track
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
- ServerSideApply=true
Deux options de syncOptions méritent un mot :
CreateNamespace=trueévite de créer le namespacedependency-trackà la main en amont.ServerSideApply=truedélègue l’application des manifests à l’API server plutôt qu’au client ArgoCD, ce qui évite la limite de taille de l’annotationlast-applied-configurationsur les gros manifests.
Les valeurs Helm vivent dans un values.yaml versionné à côté, dans le dossier dependency-track du repo. C’est là que je fixe les tags d’image, la persistance et les ressources :
frontend:
image:
tag: "4.14.1"
apiServer:
image:
tag: "4.14.1"
persistentVolume:
enabled: true
size: 20Gi
resources:
requests:
cpu: "500m"
limits:
memory: 5Gi
Déploiement
On applique la configuration avec (seule étape manuelle) :
kubectl apply -f root-app.yaml
À ce stade la chart se déploie et après quelques minutes l’application apparaît en “Healthy” et “Synced” dans l’interface ArgoCD. On peut aussi le vérifier en ligne de commande :
kubectl get deployment -n dependency-track
# dependency-track-frontend 1/1 1 1 47h
kubectl get statefulset -n dependency-track
# dependency-track-api-server 1/1 47h
Accès au service
Un port forward sur le frontend et sur l’api server suffit pour un premier test :
kubectl port-forward -n dependency-track svc/dependency-track-api-server 8080:8080
# Dans un autre terminal
kubectl port-forward -n dependency-track svc/dependency-track-frontend 8081:8080
Je vous laisse constater le résultat (login : admin / password : admin).

Obstacle rencontré : les ressources de l’api server
J’ai toujours pour réflexe, lorsque je déploie un outil, de jeter un oeil aux ressources nécessaires pour le faire tourner. La chart officielle de Dependency Track réclame 2 CPU et 5Gi de RAM pour l’api server, ce qui me semblait énorme pour mon petit cluster.
J’ai donc commencé par réduire les ressources demandées à 500m de CPU et 1Gi de RAM pour les tests, mais cela a conduit à des lenteurs extrêmes et des timeouts dans les logs de l’api server.
La solution : laisser la configuration RAM par défaut (5Gi requested), 500m de CPU suffisent en revanche pour un cluster de test.
Le mot de la fin
Pour aller plus loin, vous pouvez configurer une HTTPRoute (ou un Ingress, déprécié) pour accéder à l’interface sans passer par un port forward, ou encore brancher une base de données externe pour la persistance des données.
