如何结合cert-manager与HAProxy-ingress部署Let's Encrypt证书?
Hey there! Let me walk you through how to get these three tools working together to automatically issue and renew Let's Encrypt SSL certificates for your Kubernetes services. I've set this up multiple times, so let's break it down step by step to make it straightforward.
Prerequisites
First, make sure you have:
- A running Kubernetes cluster (v1.24+ is recommended, but recent stable versions will work)
kubectlconfigured with admin-level access to your cluster- HAProxy Ingress Controller already installed (ensure its service is exposed via LoadBalancer or NodePort so external traffic can reach ports 80 and 443)
Step 1: Install cert-manager
cert-manager handles the full lifecycle of your SSL certificates—issuance, renewal, and rotation. We'll use Helm for the easiest installation:
# Add the cert-manager Helm repository helm repo add cert-manager https://charts.jetstack.io helm repo update # Install cert-manager along with its CRDs helm install cert-manager cert-manager/cert-manager \ --namespace cert-manager \ --create-namespace \ --version v1.13.0 \ --set installCRDs=true
Pro tip: Swap v1.13.0 for the latest stable version if needed. After installation, verify all pods are running:
kubectl get pods -n cert-manager
You should see three pods (cert-manager, cert-manager-webhook, cert-manager-cainjector) in the Running state.
Step 2: Configure HAProxy Ingress for ACME Challenges
Let's Encrypt uses HTTP-01 challenges by default (for wildcard certs, you'd use DNS-01, but we'll start with the simpler HTTP method). For this to work, HAProxy needs to forward requests to the .well-known/acme-challenge path to cert-manager's temporary challenge solver pods.
Most of the time, cert-manager auto-creates temporary Ingress resources for these challenges, but we need to ensure HAProxy doesn't block or rewrite these paths. If you have a custom HAProxy ConfigMap, add this setting:
apiVersion: v1 kind: ConfigMap metadata: name: haproxy-ingress namespace: haproxy-controller # Adjust to your HAProxy namespace data: http-request: "set-path /%[path,regsub(^/.well-known/acme-challenge/,/)]"
Apply the ConfigMap with kubectl apply -f <filename>.yaml, then restart the HAProxy Ingress Controller to pick up changes:
kubectl rollout restart deployment haproxy-ingress -n haproxy-controller
If you don't have a custom ConfigMap, don't stress—HAProxy Ingress usually handles these paths correctly out of the box, but keep this fix in mind if you hit issues.
Step 3: Create a Let's Encrypt Issuer/ClusterIssuer
Next, we'll tell cert-manager to use Let's Encrypt as our certificate authority. We'll start with the staging environment to avoid hitting rate limits while testing, then switch to production once things work.
Staging ClusterIssuer (Namespace-Agnostic)
apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-staging spec: acme: server: https://acme-staging-v02.api.letsencrypt.org/directory email: your-email@example.com # Use your real email for renewal alerts privateKeySecretRef: name: letsencrypt-staging solvers: - http01: ingress: class: haproxy # Important: Match your HAProxy Ingress class name
Apply this with kubectl apply -f <filename>.yaml. Once testing passes, use the production issuer:
Production ClusterIssuer
apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-prod spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: your-email@example.com privateKeySecretRef: name: letsencrypt-prod solvers: - http01: ingress: class: haproxy
Again, apply with kubectl apply -f <filename>.yaml.
Step 4: Update Your Ingress to Request a Certificate
Now, modify your existing Ingress (or create a new one) to request a certificate from cert-manager. Add the cert-manager annotation and define a TLS section:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: example-ingress namespace: your-app-namespace annotations: cert-manager.io/cluster-issuer: "letsencrypt-prod" # Use "letsencrypt-staging" for testing haproxy.org/ssl-redirect: "true" # Optional: Auto-redirect HTTP to HTTPS spec: ingressClassName: haproxy # Match your HAProxy Ingress class tls: - hosts: - your-domain.com # Replace with your actual domain secretName: your-domain-tls # cert-manager will create this secret automatically rules: - host: your-domain.com http: paths: - path: / pathType: Prefix backend: service: name: your-app-service # Replace with your service name port: number: 80
Apply this Ingress with kubectl apply -f <filename>.yaml.
Step 5: Verify the Setup
Wait a minute or two, then check if the certificate was issued successfully:
kubectl get certificates -n your-app-namespace
If the STATUS shows Ready, you're all set! You can also confirm the certificate is stored in the secret:
kubectl describe secret your-domain-tls -n your-app-namespace
Finally, test accessing your domain over HTTPS (https://your-domain.com) to ensure your browser recognizes the valid Let's Encrypt certificate.
Troubleshooting Tips
If things don't work right away, try these checks:
- Check certificate events: Run
kubectl describe certificate your-domain-tls -n your-app-namespaceto see if there are errors (like failed challenge attempts). - Inspect HAProxy logs: Look at the Ingress Controller logs to verify ACME challenge requests are being routed correctly:
kubectl logs -n haproxy-controller deployment/haproxy-ingress - Confirm domain resolution: Ensure your domain points to the external IP of your HAProxy Ingress service.
- Check firewall rules: Make sure ports 80 (for HTTP-01 challenges) and 443 (for HTTPS) are open to the internet.
内容的提问来源于stack exchange,提问作者PsySkeletor

