315 lines
8.5 KiB
Markdown
315 lines
8.5 KiB
Markdown
# cert-manager-stack
|
|
|
|
A wrapper Helm chart that bundles [cert-manager](https://cert-manager.io) with pre-configured Cloudflare DNS-01 solver and Let's Encrypt ClusterIssuer for GitOps deployments.
|
|
|
|
## 📋 Overview
|
|
|
|
This chart provides a production-ready cert-manager deployment by:
|
|
|
|
- **Using cert-manager as a dependency** (pristine upstream chart, easily upgradable)
|
|
- **Adding custom resources** (Cloudflare API Secret, Let's Encrypt ClusterIssuer)
|
|
- **Single configuration file** (`manifests/cert-manager-stack/values.yaml`)
|
|
- **GitOps-friendly** (works seamlessly with ArgoCD)
|
|
|
|
## 🏗️ Architecture
|
|
|
|
```
|
|
cert-manager-stack (wrapper chart)
|
|
├── Dependency: cert-manager (embedded in charts/cert-manager/)
|
|
│ ├── CRDs (Certificate, ClusterIssuer, etc.)
|
|
│ ├── cert-manager controller
|
|
│ ├── cert-manager webhook
|
|
│ └── cert-manager cainjector
|
|
└── Custom Resources (from wrapper templates)
|
|
├── Secret: cloudflare-api-token
|
|
└── ClusterIssuer: letsencrypt
|
|
```
|
|
|
|
## 📁 Files Structure
|
|
|
|
```
|
|
charts/cert-manager-stack/
|
|
├── Chart.yaml # Wrapper chart definition
|
|
├── values.yaml # Default values (DO NOT EDIT)
|
|
├── charts/ # Embedded dependencies
|
|
│ └── cert-manager/ # cert-manager chart
|
|
│ ├── Chart.yaml
|
|
│ ├── values.yaml
|
|
│ └── templates/
|
|
├── templates/
|
|
│ ├── _helpers.tpl # Template helpers
|
|
│ ├── cloudflare-api-token-secret.yaml # Cloudflare API Secret
|
|
│ ├── clusterissuer-letsencrypt.yaml # Let's Encrypt ClusterIssuer
|
|
│ └── NOTES.txt # Post-install notes
|
|
└── README.md # This file
|
|
|
|
manifests/cert-manager-stack/
|
|
└── values.yaml # ✏️ EDIT THIS FILE
|
|
```
|
|
|
|
## ⚙️ Configuration
|
|
|
|
### Single Source of Truth
|
|
|
|
**`manifests/cert-manager-stack/values.yaml`** is the only file you need to edit.
|
|
|
|
### Configuration Structure
|
|
|
|
```yaml
|
|
# cert-manager upstream chart values
|
|
certManager:
|
|
enabled: true
|
|
crds:
|
|
enabled: true
|
|
prometheus:
|
|
enabled: false
|
|
|
|
# Cloudflare DNS provider
|
|
cloudflare:
|
|
enabled: true
|
|
apiToken: "YOUR_CLOUDFLARE_API_TOKEN"
|
|
secretName: cloudflare-api-token
|
|
namespace: cert-manager
|
|
|
|
# Let's Encrypt ClusterIssuer
|
|
clusterIssuer:
|
|
enabled: true
|
|
name: letsencrypt
|
|
email: dvirlabs@gmail.com
|
|
server: https://acme-v02.api.letsencrypt.org/directory
|
|
```
|
|
|
|
## 🚀 ArgoCD Integration
|
|
|
|
Create an ArgoCD Application:
|
|
|
|
```yaml
|
|
# argocd-apps/cert-manager-stack.yaml
|
|
apiVersion: argoproj.io/v1alpha1
|
|
kind: Application
|
|
metadata:
|
|
name: cert-manager-stack
|
|
namespace: argocd
|
|
spec:
|
|
project: default
|
|
source:
|
|
repoURL: <your-git-repo>
|
|
targetRevision: HEAD
|
|
path: charts/cert-manager-stack
|
|
helm:
|
|
valueFiles:
|
|
- ../../manifests/cert-manager-stack/values.yaml
|
|
destination:
|
|
server: https://kubernetes.default.svc
|
|
namespace: cert-manager
|
|
syncPolicy:
|
|
automated:
|
|
prune: true
|
|
selfHeal: true
|
|
syncOptions:
|
|
- CreateNamespace=true
|
|
```
|
|
|
|
ArgoCD will:
|
|
1. Read the wrapper chart from `charts/cert-manager-stack/`
|
|
2. Load cert-manager dependency from embedded `charts/cert-manager-stack/charts/cert-manager/`
|
|
3. Apply values from `manifests/cert-manager-stack/values.yaml`
|
|
4. Deploy everything as a unified Helm release
|
|
|
|
## 📦 Installation
|
|
|
|
### Manual Installation (for testing)
|
|
|
|
```bash
|
|
# Navigate to chart directory
|
|
cd charts/cert-manager-stack
|
|
|
|
# Update dependencies
|
|
helm dependency update
|
|
|
|
# Install
|
|
helm install cert-manager-stack . \
|
|
--namespace cert-manager \
|
|
--create-namespace \
|
|
--values ../../manifests/cert-manager-stack/values.yaml
|
|
```
|
|
|
|
### GitOps Installation (recommended)
|
|
|
|
1. Update your Cloudflare API token in `manifests/cert-manager-stack/values.yaml`
|
|
2. Commit and push to Git
|
|
3. ArgoCD will automatically sync and deploy
|
|
|
|
## 🔄 Upgrading cert-manager
|
|
|
|
To upgrade to a newer cert-manager version:
|
|
|
|
1. Replace the embedded cert-manager chart in `charts/cert-manager-stack/charts/cert-manager/`
|
|
2. Edit `charts/cert-manager-stack/Chart.yaml`
|
|
3. Update the dependency version to match:
|
|
```yaml
|
|
dependencies:
|
|
- name: cert-manager
|
|
version: "v1.21.0" # Update this to match embedded chart version
|
|
alias: certManager
|
|
```
|
|
4. Commit and push
|
|
5. ArgoCD will handle the upgrade
|
|
|
|
## ✅ Why This Approach?
|
|
|
|
### ❌ What We're NOT Doing:
|
|
- Forking/modifying the upstream cert-manager chart
|
|
- Manual `kubectl apply` for Secret/ClusterIssuer
|
|
- Embedding resources in cert-manager's values
|
|
- Using hacks like `extraObjects`
|
|
|
|
### ✅ What We ARE Doing:
|
|
- **Clean dependency management** - cert-manager stays pristine
|
|
- **Single Helm release** - all resources managed together
|
|
- **GitOps native** - no manual steps
|
|
- **Helm best practices** - proper dependency and values structure
|
|
- **Easy upgrades** - just bump the version number
|
|
- **Migration-ready** - clean path to External Secrets/Vault
|
|
|
|
### Benefits Over Modifying Upstream Chart:
|
|
|
|
1. **Upgradability**: Can upgrade cert-manager without merge conflicts
|
|
2. **Clarity**: Separation between upstream and custom resources
|
|
3. **Maintainability**: Upstream chart bugs/fixes don't affect custom logic
|
|
4. **Reusability**: Can apply same pattern to other charts
|
|
5. **Audibility**: Clear distinction in Git history
|
|
|
|
## 📝 Usage Examples
|
|
|
|
### Create a Certificate
|
|
|
|
```yaml
|
|
apiVersion: cert-manager.io/v1
|
|
kind: Certificate
|
|
metadata:
|
|
name: my-app-tls
|
|
namespace: my-app
|
|
spec:
|
|
secretName: my-app-tls-secret
|
|
issuerRef:
|
|
name: letsencrypt
|
|
kind: ClusterIssuer
|
|
dnsNames:
|
|
- myapp.example.com
|
|
- "*.myapp.example.com"
|
|
```
|
|
|
|
### Use with Ingress
|
|
|
|
```yaml
|
|
apiVersion: networking.k8s.io/v1
|
|
kind: Ingress
|
|
metadata:
|
|
name: my-app-ingress
|
|
annotations:
|
|
cert-manager.io/cluster-issuer: letsencrypt
|
|
spec:
|
|
tls:
|
|
- hosts:
|
|
- myapp.example.com
|
|
secretName: my-app-tls
|
|
rules:
|
|
- host: myapp.example.com
|
|
http:
|
|
paths:
|
|
- path: /
|
|
pathType: Prefix
|
|
backend:
|
|
service:
|
|
name: my-app-service
|
|
port:
|
|
number: 80
|
|
```
|
|
|
|
## 🔐 Migrating to External Secrets
|
|
|
|
When ready to move from raw Secrets to External Secrets:
|
|
|
|
1. Create a new template `templates/cloudflare-external-secret.yaml`:
|
|
```yaml
|
|
{{- if .Values.cloudflare.useExternalSecret }}
|
|
apiVersion: external-secrets.io/v1beta1
|
|
kind: ExternalSecret
|
|
metadata:
|
|
name: cloudflare-api-token
|
|
namespace: cert-manager
|
|
spec:
|
|
secretStoreRef:
|
|
name: vault-backend
|
|
kind: ClusterSecretStore
|
|
target:
|
|
name: cloudflare-api-token
|
|
data:
|
|
- secretKey: api-token
|
|
remoteRef:
|
|
key: cloudflare/api-token
|
|
{{- end }}
|
|
```
|
|
|
|
2. Update `manifests/cert-manager-stack/values.yaml`:
|
|
```yaml
|
|
cloudflare:
|
|
enabled: false # Disable raw Secret
|
|
useExternalSecret: true # Enable ExternalSecret
|
|
secretName: cloudflare-api-token # Keep same name
|
|
```
|
|
|
|
3. No changes needed to ClusterIssuer (references same secret name)
|
|
|
|
## 🔍 Troubleshooting
|
|
|
|
### Check cert-manager logs
|
|
```bash
|
|
kubectl logs -n cert-manager deploy/cert-manager-stack-certManager
|
|
```
|
|
|
|
### Check ClusterIssuer status
|
|
```bash
|
|
kubectl describe clusterissuer letsencrypt
|
|
kubectl get clusterissuer letsencrypt -o yaml
|
|
```
|
|
|
|
### Check Certificate status
|
|
```bash
|
|
kubectl describe certificate my-app-tls -n my-app
|
|
kubectl get certificaterequest -n my-app
|
|
```
|
|
|
|
### Verify Cloudflare secret
|
|
```bash
|
|
kubectl get secret cloudflare-api-token -n cert-manager
|
|
kubectl describe secret cloudflare-api-token -n cert-manager
|
|
```
|
|
|
|
### Check ACME challenges
|
|
```bash
|
|
kubectl get challenges --all-namespaces
|
|
kubectl describe challenge <challenge-name> -n <namespace>
|
|
```
|
|
|
|
## 📚 References
|
|
|
|
- [cert-manager Documentation](https://cert-manager.io/docs/)
|
|
- [Cloudflare DNS-01 Challenge](https://cert-manager.io/docs/configuration/acme/dns01/cloudflare/)
|
|
- [Let's Encrypt Documentation](https://letsencrypt.org/docs/)
|
|
- [Helm Dependencies](https://helm.sh/docs/helm/helm_dependency/)
|
|
|
|
## 🤝 Contributing
|
|
|
|
To improve this wrapper chart:
|
|
|
|
1. Edit files in `charts/cert-manager-stack/`
|
|
2. Test with `helm template` or `helm install --dry-run`
|
|
3. Update `manifests/cert-manager-stack/values.yaml` if needed
|
|
4. Commit and create a PR
|
|
|
|
## 📄 License
|
|
|
|
This wrapper chart follows the same license as cert-manager (Apache 2.0).
|