The Manual Approach: Using Kubernetes Secrets
Before automating, it’s crucial to understand how Kubernetes handles certificates natively. Kubernetes stores TLS certificates as a specific type of Secret (kubernetes.io/tls).
Step 1: Create the TLS Secret
If you already have a certificate (tls.crt) and a private key (tls.key), you can store them in your cluster using kubectl:
kubectl create secret tls my-website-tls \
--cert=path/to/tls.crt \
--key=path/to/tls.key \
-n my-namespace
Step 2: Configure the Ingress Resource
Once the secret exists, you reference it in your Ingress manifest under the tls section:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-website-ingress
namespace: my-namespace
spec:
ingressClassName: nginx
tls:
- hosts:
- www.mywebsite.com
secretName: my-website-tls # Matches the secret created above
rules:
- host: www.mywebsite.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-website-service
port:
number: 80
The Automated Approach: Mastering cert-manager
To truly master certificate management in Kubernetes, you must automate it. cert-manager is the industry-standard Kubernetes add-on that automates the issuance and renewal of TLS certificates.
Core Components of cert-manager
- Issuer / ClusterIssuer: Resources that represent certificate authorities (CAs) like Let’s Encrypt. An
Issueris scoped to a single namespace, while aClusterIssuerworks across the entire cluster. - Certificate: A resource that requests a certificate from an Issuer and ensures it is kept up to date.
- CertificateRequest: Used internally by
cert-managerto request the actual signed certificate.
Step 1: Install cert-manager
The easiest way to install it is via Helm:
Bash
helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--set installCRDs=true
Step 2: Create a Let’s Encrypt ClusterIssuer
We’ll use Let’s Encrypt with an HTTP-01 challenge. This tells Let’s Encrypt to verify your domain ownership by placing a specific file on your web server.
YAML
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
# The ACME server URL
server: https://acme-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: admin@mywebsite.com
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt-prod-account-key
# Enable the HTTP-01 challenge provider
solvers:
- http01:
ingress:
class: nginx
Step 3: Automate the Ingress
Now, simply add an annotation to your Ingress resource. cert-manager will automatically detect it, talk to Let’s Encrypt, complete the challenge, create the secret, and keep it renewed!
YAML
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-website-ingress
namespace: my-namespace
annotations:
# This triggers cert-manager to use our ClusterIssuer
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
ingressClassName: nginx
tls:
- hosts:
- www.mywebsite.com
secretName: my-website-tls-auto # cert-manager creates this secret for you
rules:
- host: www.mywebsite.com
http:
# ... backend service config ...