add cert-manager
This commit is contained in:
56
apps/applicationset-cert-manager.yaml
Normal file
56
apps/applicationset-cert-manager.yaml
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: ApplicationSet
|
||||||
|
metadata:
|
||||||
|
name: cert-manager-apps
|
||||||
|
namespace: argocd-ops
|
||||||
|
spec:
|
||||||
|
generators:
|
||||||
|
# Utilise un générateur merge pour combiner :
|
||||||
|
# 1. Les répertoires Helm existants (détermine quels environnements sont disponibles pour cert-manager)
|
||||||
|
# 2. Les fichiers de config partagés (pour obtenir name et server)
|
||||||
|
- merge:
|
||||||
|
generators:
|
||||||
|
# Premier générateur : scanne uniquement les répertoires Helm qui existent pour cert-manager
|
||||||
|
- git:
|
||||||
|
repoURL: https://git.gkdomaine.fr/kubernetes/argocd.git
|
||||||
|
revision: main
|
||||||
|
directories:
|
||||||
|
- path: "helm/cert-manager/*"
|
||||||
|
# Deuxième générateur : lit les fichiers de config partagés
|
||||||
|
# ApplicationSet utilisera seulement les fichiers config.json dont le basename
|
||||||
|
# correspond à un répertoire Helm trouvé
|
||||||
|
- git:
|
||||||
|
repoURL: https://git.gkdomaine.fr/kubernetes/argocd.git
|
||||||
|
revision: main
|
||||||
|
files:
|
||||||
|
- path: "configs/*/config.json"
|
||||||
|
mergeKeys:
|
||||||
|
- path.basename
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
# Utilise path.basename qui vient du générateur git (plus fiable que environment du JSON)
|
||||||
|
name: 'cert-manager-{{path.basename}}'
|
||||||
|
spec:
|
||||||
|
# Utilise path.basename pour le projet (ou {{environment}} si disponible dans le JSON)
|
||||||
|
project: '{{path.basename}}'
|
||||||
|
source:
|
||||||
|
repoURL: '{{repository}}'
|
||||||
|
targetRevision: '{{targetRevision}}'
|
||||||
|
# Construit explicitement le chemin Helm à partir du basename
|
||||||
|
path: '{{helmPath}}/cert-manager/{{path.basename}}'
|
||||||
|
helm:
|
||||||
|
valueFiles:
|
||||||
|
- values.yaml
|
||||||
|
destination:
|
||||||
|
# Les variables {{name}} et {{server}} viennent du fichier config.json
|
||||||
|
# (deuxième générateur du merge)
|
||||||
|
name: '{{name}}'
|
||||||
|
# server: '{{server}}'
|
||||||
|
namespace: 'cert-manager'
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
|
|
||||||
226
docs/cert-manager-letsencrypt.md
Normal file
226
docs/cert-manager-letsencrypt.md
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
# Configuration Let's Encrypt avec cert-manager
|
||||||
|
|
||||||
|
Ce document explique comment générer et utiliser des certificats Let's Encrypt avec cert-manager dans votre cluster Kubernetes.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
- **cert-manager** : Opérateur Kubernetes qui gère automatiquement les certificats TLS
|
||||||
|
- **ClusterIssuer** : Ressource qui définit comment obtenir des certificats (Let's Encrypt Production ou Staging)
|
||||||
|
- **Certificate** : Ressource Kubernetes qui demande un certificat pour un domaine spécifique
|
||||||
|
- **Traefik** : Ingress Controller qui utilise les certificats générés
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### 1. Déployer cert-manager
|
||||||
|
|
||||||
|
cert-manager est déployé via ArgoCD via l'ApplicationSet `cert-manager-apps`.
|
||||||
|
|
||||||
|
Le chart inclut :
|
||||||
|
- cert-manager (controller, webhook, cainjector)
|
||||||
|
- ClusterIssuer pour Let's Encrypt Production (`letsencrypt-prod`)
|
||||||
|
- ClusterIssuer pour Let's Encrypt Staging (`letsencrypt-staging`)
|
||||||
|
|
||||||
|
### 2. Vérifier l'installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Vérifier que cert-manager est déployé
|
||||||
|
kubectl get pods -n cert-manager
|
||||||
|
|
||||||
|
# Vérifier les ClusterIssuers
|
||||||
|
kubectl get clusterissuers
|
||||||
|
|
||||||
|
# Vérifier le statut d'un ClusterIssuer
|
||||||
|
kubectl describe clusterissuer letsencrypt-prod
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### ClusterIssuers
|
||||||
|
|
||||||
|
Deux ClusterIssuers sont créés :
|
||||||
|
|
||||||
|
1. **letsencrypt-prod** : Pour les certificats de production
|
||||||
|
- Serveur : `https://acme-v02.api.letsencrypt.org/directory`
|
||||||
|
- Limite de taux : 50 certificats par semaine par domaine
|
||||||
|
|
||||||
|
2. **letsencrypt-staging** : Pour les tests
|
||||||
|
- Serveur : `https://acme-staging-v02.api.letsencrypt.org/directory`
|
||||||
|
- Limite de taux : 300 certificats par semaine par domaine
|
||||||
|
- ⚠️ Les certificats staging ne sont pas fiables par les navigateurs
|
||||||
|
|
||||||
|
### Modifier l'email
|
||||||
|
|
||||||
|
L'email utilisé pour l'enregistrement ACME est défini dans :
|
||||||
|
- `helm/cert-manager/dev/templates/cluster-issuer-letsencrypt-prod.yaml`
|
||||||
|
- `helm/cert-manager/dev/templates/cluster-issuer-letsencrypt-staging.yaml`
|
||||||
|
|
||||||
|
Modifiez la ligne `email: admin@gkdomaine.fr` avec votre email.
|
||||||
|
|
||||||
|
## Utilisation
|
||||||
|
|
||||||
|
### Méthode 1 : Via annotations Ingress (Recommandé)
|
||||||
|
|
||||||
|
Ajoutez les annotations suivantes à votre Ingress :
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
className: traefik
|
||||||
|
hosts:
|
||||||
|
- host: monapp.dev.gkdomaine.fr
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
tls:
|
||||||
|
- secretName: monapp-dev-tls
|
||||||
|
hosts:
|
||||||
|
- monapp.dev.gkdomaine.fr
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: "letsencrypt-prod" # ou "letsencrypt-staging" pour les tests
|
||||||
|
```
|
||||||
|
|
||||||
|
### Méthode 2 : Via ressource Certificate (Pour plus de contrôle)
|
||||||
|
|
||||||
|
Créez une ressource Certificate :
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: cert-manager.io/v1
|
||||||
|
kind: Certificate
|
||||||
|
metadata:
|
||||||
|
name: monapp-dev-tls
|
||||||
|
namespace: monapp-dev
|
||||||
|
spec:
|
||||||
|
secretName: monapp-dev-tls
|
||||||
|
issuerRef:
|
||||||
|
name: letsencrypt-prod
|
||||||
|
kind: ClusterIssuer
|
||||||
|
dnsNames:
|
||||||
|
- monapp.dev.gkdomaine.fr
|
||||||
|
```
|
||||||
|
|
||||||
|
Puis référencez le secret dans votre Ingress :
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
ingress:
|
||||||
|
tls:
|
||||||
|
- secretName: monapp-dev-tls
|
||||||
|
hosts:
|
||||||
|
- monapp.dev.gkdomaine.fr
|
||||||
|
```
|
||||||
|
|
||||||
|
## Validation HTTP-01
|
||||||
|
|
||||||
|
cert-manager utilise la méthode HTTP-01 pour valider la propriété du domaine :
|
||||||
|
|
||||||
|
1. cert-manager crée un challenge HTTP
|
||||||
|
2. Traefik expose le challenge sur `/.well-known/acme-challenge/`
|
||||||
|
3. Let's Encrypt vérifie que le challenge est accessible
|
||||||
|
4. Le certificat est émis et stocké dans un Secret Kubernetes
|
||||||
|
|
||||||
|
### Prérequis
|
||||||
|
|
||||||
|
- Le domaine doit pointer vers l'IP publique de Traefik (LoadBalancer)
|
||||||
|
- Le port 80 doit être accessible depuis Internet
|
||||||
|
- Traefik doit être configuré pour gérer les ingress avec la classe `traefik`
|
||||||
|
|
||||||
|
## Vérification
|
||||||
|
|
||||||
|
### Vérifier le statut d'un certificat
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Lister les certificats
|
||||||
|
kubectl get certificates --all-namespaces
|
||||||
|
|
||||||
|
# Détails d'un certificat
|
||||||
|
kubectl describe certificate monapp-dev-tls -n monapp-dev
|
||||||
|
|
||||||
|
# Vérifier les challenges ACME
|
||||||
|
kubectl get challenges --all-namespaces
|
||||||
|
```
|
||||||
|
|
||||||
|
### Vérifier le secret TLS
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Le secret est créé automatiquement quand le certificat est émis
|
||||||
|
kubectl get secret monapp-dev-tls -n monapp-dev
|
||||||
|
|
||||||
|
# Voir les détails du certificat
|
||||||
|
kubectl get secret monapp-dev-tls -n monapp-dev -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -text -noout
|
||||||
|
```
|
||||||
|
|
||||||
|
## Renouvellement automatique
|
||||||
|
|
||||||
|
cert-manager renouvelle automatiquement les certificats avant expiration (30 jours avant la date d'expiration).
|
||||||
|
|
||||||
|
Les certificats Let's Encrypt sont valides pendant 90 jours.
|
||||||
|
|
||||||
|
## Dépannage
|
||||||
|
|
||||||
|
### Le certificat n'est pas émis
|
||||||
|
|
||||||
|
1. Vérifier les logs de cert-manager :
|
||||||
|
```bash
|
||||||
|
kubectl logs -n cert-manager deployment/cert-manager
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Vérifier les challenges :
|
||||||
|
```bash
|
||||||
|
kubectl describe challenge -n monapp-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Vérifier que le domaine est accessible :
|
||||||
|
```bash
|
||||||
|
curl http://monapp.dev.gkdomaine.fr/.well-known/acme-challenge/test
|
||||||
|
```
|
||||||
|
|
||||||
|
### Erreur "rate limit exceeded"
|
||||||
|
|
||||||
|
Let's Encrypt a des limites de taux :
|
||||||
|
- Production : 50 certificats par semaine par domaine
|
||||||
|
- Staging : 300 certificats par semaine par domaine
|
||||||
|
|
||||||
|
Solution : Utilisez `letsencrypt-staging` pour les tests, ou attendez la fin de la période de limitation.
|
||||||
|
|
||||||
|
### Le certificat n'est pas utilisé par Traefik
|
||||||
|
|
||||||
|
Vérifiez que :
|
||||||
|
1. Le secret TLS existe dans le même namespace que l'Ingress
|
||||||
|
2. L'Ingress référence correctement le secret dans `spec.tls[].secretName`
|
||||||
|
3. Traefik peut accéder au secret (même namespace ou RBAC approprié)
|
||||||
|
|
||||||
|
## Exemples de configuration
|
||||||
|
|
||||||
|
### Homarr
|
||||||
|
|
||||||
|
Voir `helm/homarr/dev/values.yaml` pour un exemple complet avec annotations cert-manager.
|
||||||
|
|
||||||
|
### Traefik Dashboard
|
||||||
|
|
||||||
|
Pour sécuriser le dashboard Traefik, ajoutez TLS à l'IngressRoute :
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: traefik.io/v1alpha1
|
||||||
|
kind: IngressRoute
|
||||||
|
metadata:
|
||||||
|
name: traefik-dashboard
|
||||||
|
namespace: traefik-dev
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
||||||
|
spec:
|
||||||
|
entryPoints:
|
||||||
|
- websecure
|
||||||
|
routes:
|
||||||
|
- match: Host(`traefik.dev.gkdomaine.fr`)
|
||||||
|
kind: Rule
|
||||||
|
services:
|
||||||
|
- name: api@internal
|
||||||
|
kind: TraefikService
|
||||||
|
tls:
|
||||||
|
secretName: traefik-dashboard-tls
|
||||||
|
```
|
||||||
|
|
||||||
|
## Références
|
||||||
|
|
||||||
|
- [cert-manager Documentation](https://cert-manager.io/docs/)
|
||||||
|
- [Let's Encrypt Documentation](https://letsencrypt.org/docs/)
|
||||||
|
- [Traefik ACME Documentation](https://doc.traefik.io/traefik/https/acme/)
|
||||||
|
|
||||||
6
helm/cert-manager/dev/Chart.lock
Normal file
6
helm/cert-manager/dev/Chart.lock
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
dependencies:
|
||||||
|
- name: cert-manager
|
||||||
|
repository: https://charts.jetstack.io
|
||||||
|
version: v1.16.0
|
||||||
|
digest: sha256:59590787a7a7a4b4e15c20af04b03933ad00feff48bc38a8cdbf17a5f058e020
|
||||||
|
generated: "2026-01-18T19:50:49.317276+01:00"
|
||||||
11
helm/cert-manager/dev/Chart.yaml
Normal file
11
helm/cert-manager/dev/Chart.yaml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: v2
|
||||||
|
name: cert-manager-wrapper
|
||||||
|
description: Wrapper pour cert-manager avec ClusterIssuer Let's Encrypt
|
||||||
|
type: application
|
||||||
|
version: 1.0.0
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
- name: cert-manager
|
||||||
|
version: v1.19.2
|
||||||
|
repository: https://charts.jetstack.io
|
||||||
|
|
||||||
BIN
helm/cert-manager/dev/charts/cert-manager-v1.16.0.tgz
Normal file
BIN
helm/cert-manager/dev/charts/cert-manager-v1.16.0.tgz
Normal file
Binary file not shown.
@@ -0,0 +1,19 @@
|
|||||||
|
apiVersion: cert-manager.io/v1
|
||||||
|
kind: ClusterIssuer
|
||||||
|
metadata:
|
||||||
|
name: letsencrypt-prod
|
||||||
|
spec:
|
||||||
|
acme:
|
||||||
|
# URL du serveur Let's Encrypt Production
|
||||||
|
server: https://acme-v02.api.letsencrypt.org/directory
|
||||||
|
# Email utilisé pour l'enregistrement et les notifications de renouvellement
|
||||||
|
email: admin@gkdomaine.fr # ⚠️ À MODIFIER avec votre email
|
||||||
|
# Secret pour stocker la clé privée du compte ACME
|
||||||
|
privateKeySecretRef:
|
||||||
|
name: letsencrypt-prod
|
||||||
|
# Méthode de validation HTTP-01 (via Traefik)
|
||||||
|
solvers:
|
||||||
|
- http01:
|
||||||
|
ingress:
|
||||||
|
class: traefik
|
||||||
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
apiVersion: cert-manager.io/v1
|
||||||
|
kind: ClusterIssuer
|
||||||
|
metadata:
|
||||||
|
name: letsencrypt-staging
|
||||||
|
spec:
|
||||||
|
acme:
|
||||||
|
# URL du serveur Let's Encrypt Staging (pour les tests)
|
||||||
|
server: https://acme-staging-v02.api.letsencrypt.org/directory
|
||||||
|
# Email utilisé pour l'enregistrement et les notifications de renouvellement
|
||||||
|
email: admin@gkdomaine.fr # ⚠️ À MODIFIER avec votre email
|
||||||
|
# Secret pour stocker la clé privée du compte ACME
|
||||||
|
privateKeySecretRef:
|
||||||
|
name: letsencrypt-staging
|
||||||
|
# Méthode de validation HTTP-01 (via Traefik)
|
||||||
|
solvers:
|
||||||
|
- http01:
|
||||||
|
ingress:
|
||||||
|
class: traefik
|
||||||
|
|
||||||
33
helm/cert-manager/dev/values.yaml
Normal file
33
helm/cert-manager/dev/values.yaml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# Configuration pour cert-manager
|
||||||
|
cert-manager:
|
||||||
|
# Installation de cert-manager
|
||||||
|
installCRDs: true
|
||||||
|
|
||||||
|
# Configuration des images depuis Harbor
|
||||||
|
image:
|
||||||
|
registry: harbor.gkdomaine.local
|
||||||
|
repository: images/cert-manager-controller
|
||||||
|
tag: v1.19.2
|
||||||
|
|
||||||
|
webhook:
|
||||||
|
image:
|
||||||
|
registry: harbor.gkdomaine.local
|
||||||
|
repository: images/cert-manager-webhook
|
||||||
|
tag: v1.19.2
|
||||||
|
|
||||||
|
cainjector:
|
||||||
|
image:
|
||||||
|
registry: harbor.gkdomaine.local
|
||||||
|
repository: images/cert-manager-cainjector
|
||||||
|
tag: v1.19.2
|
||||||
|
|
||||||
|
# Configuration de sécurité
|
||||||
|
securityContext:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Prometheus metrics
|
||||||
|
prometheus:
|
||||||
|
enabled: true
|
||||||
|
servicemonitor:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
@@ -19,6 +19,14 @@ homarr:
|
|||||||
- host: homarr.dev.gkdomaine.fr
|
- host: homarr.dev.gkdomaine.fr
|
||||||
paths:
|
paths:
|
||||||
- path: /
|
- path: /
|
||||||
|
# Configuration TLS avec cert-manager pour Let's Encrypt
|
||||||
|
tls:
|
||||||
|
- secretName: homarr-dev-tls
|
||||||
|
hosts:
|
||||||
|
- homarr.dev.gkdomaine.fr
|
||||||
|
# Annotations pour cert-manager
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: "letsencrypt-staging" # Utilisez "letsencrypt-staging" pour les tests
|
||||||
|
|
||||||
persistence:
|
persistence:
|
||||||
homarrDatabase:
|
homarrDatabase:
|
||||||
|
|||||||
Reference in New Issue
Block a user