Cert-manager is een Kubernetes-tool die het beheer van TLS-certificaten in een Kubernetes-cluster automatiseert. Het kan certificaten uitgeven vanuit verschillende bronnen, zoals Let's Encrypt of self-signed certificaten.
Cert-manager verlengt automatisch deze certificaten wanneer twee derde van de geldigheidsperiode van het certificaat verlopen is.
In deze handleiding laten we zien hoe je Cert-manager installeert en configureert om Let's Encrypt-certificaten uit te geven op je Kubernetes-cluster.
Installeer voor je deze handleiding doorloopt:
- De Helm-package manager
- Traefik om als Gateway Controller te functioneren (vervangt de oude Nginx Ingress Controller).
Cert-manager installeren
Stap 1
Voeg de Jetstack-repository toe. Dit is de enige officiële bron van cert-manager Helm charts. Update vervolgens met het tweede commando je repositories om de Jetstack-repository te kunnen gebruiken.
helm repo add jetstack https://charts.jetstack.io
helm repo update
Stap 2
Installeer Cert-manager met het commando:
helm install \
cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.12.0 \
--set installCRDs=true- Je bent vrij een andere namespace-naam dan cert-manager te gebruiken, maar deze is makkelijk herkenbaar.
- Vervang hier v1.12.0 door de meest recente stabiele versie zoals te zien is hier op Github.
- De optie installCRDs is verplicht, maar je kunt alternatief de installCRDs-optie uitcommentariëren en de CRD's (simpel gezegd is een CRD code om de Kubernetes API uit te breiden met custom resources die niet aanwezig zijn in de core Kubernetes API) los installeren met het commando:
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.12.0/cert-manager.crds.yamlJe krijgt nu een output zoals hieronder te zien om te bevestigen dat de installatie geslaagd is:
NAME: cert-manager LAST DEPLOYED: Tue Jun 13 13:21:23 2023 NAMESPACE: cert-manager STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: cert-manager v1.11.0 has been deployed successfully! In order to begin issuing certificates, you will need to set up a ClusterIssuer or Issuer resource (for example, by creating a 'letsencrypt-staging' issuer). More information on the different types of issuers and how to configure them can be found in our documentation: https://cert-manager.io/docs/configuration/ For information on how to configure cert-manager to automatically provision Certificates for Ingress resources, take a look at the `ingress-shim` documentation: https://cert-manager.io/docs/usage/ingress/
De status van de Pods en Services die worden aangemaakt voor Cert-manager controleer je met respectievelijk de volgende commando's:
kubectl get pods -n cert-manager
kubectl get svc -n cert-manager
Een (Cluster)Issuer aanmaken
Om gebruik te kunnen maken van Cert-manager heb je een ClusterIssuer of Issuer nodig. Een ClusterIssuer definieert een certificaat uitgever (bijvoorbeeld Let's Encrypt) die gebruikt kan worden om TLS-certificaten voor je gehele Kubernetes-cluster te genereren. Een Issuer kan dat enkel voor een specifieke namespace.
Stap 1
Maak een .yaml bestand aan, bijvoorbeeld letsencrypt-issuer.yaml:
nano letsencrypt-issuer.yamlEr zijn twee opties voor het genereren van SSL-certificaten; HTTP-01 en DNS-01. Voor wildcard-certificaten (bijv. voor *.voorbeeld.nl) gebruik je de DNS-01 optie. Via onze API ondersteunen wij deze optie en we leggen het gebruik van DNS-01 uit aan de hand hiervan. Mocht je een andere provider kiezen, let dan wel dat die deze functionaliteit moet ondersteunen en dat de domeinen die je gebruikt zijn geregistreerd bij die provider in het account dat je voor deze handleiding gebruikt.
Gebruik je een extern domein? Gebruik dan de optie HTTP-01, maar houd er rekening mee dat je dan geen wildcard-certificaten kunt genereren.
DNS-01
Stap 1
Cert-manager ondersteunt enkele DNS-providers zoals CloudFlare, maar helaas niet TransIP. Om toch DNS-01 te kunnen gebruiken ondersteunt Cert-manager ‘webhooks’, wat je kunt zien als een soort plugin. In dit geval gebruik je een webhook om de TransIP-API te kunnen gebruiken met Cert-manager.
Installeer de webhook als volgt (vervang eventueel cert-manager door de naam van je namespace):
helm repo add cert-manager-webhook-transip https://demeester.dev/cert-manager-webhook-transip
helm install --namespace cert-manager cert-manager-webhook-transip cert-manager-webhook-transip/cert-manager-webhook-transip
Stap 2
Maak een directory aan waarin je je TransIP API key gaat opslaan, bijvoorbeeld:
mkdir transipMaak vervolgens een bestand in de zojuist aangemaakte directory met daarin een private key van jouw account voor de TransIP API, bijvoorbeeld:
cat << EOF > transip/transip.key
-----BEGIN PRIVATE KEY-----
MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDKoaYJtbVnJw58
PYGH8WIJ7ZjWd2lke0IbMV+dNGs=
-----END PRIVATE KEY-----
EOFIn dit voorbeeld is maar een klein fragment van een private key opgenomen. Jouw private key zal een stuk langer zijn.
Stap 3
Genereer een secret op basis van jouw API Private Key die door Cert-manager gebruikt kan worden om met de TransIP API te communiceren. Vervang hier eventueel de volgende gegevens:
- -n cert-manager: Gebruik de naam van de namespace die je in stap 2 van de vorige paragraaf hebt aangemaakt.
- transip/transip.key: Verander naar de directory en bestandsnaam die je in de vorige stap hebt aangemaakt.
kubectl create -n cert-manager secret generic transip-key --from-file transip/transip.key
Stap 4
Geef het bestand de volgende inhoud:
apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-issuer-dns01
spec:
acme:
email: <JE_MAILADRES>
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-issuer-dns01
solvers:
- dns01:
webhook:
groupName: acme.transip.nl
solverName: transip
config:
accountName: <JE_TRANSIPACCOUNTNAAM>
ttl: 300
privateKeySecretRef:
name: transip-key
key: privateKey
Pas <JE_MAILADRES> aan naar je eigen mailadres en <JE_TRANSIPACCOUNTNAAM> naar de naam van je TransIP-account. Sla tot slot je wijzigingen op en sluit het bestand (ctrl + x > y > enter).
HTTP-01
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-issuer
spec:
acme:
email: <JE_MAILADRES>
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-issuer
solvers:
- http01:
ingress:
class: traefik
Pas <JE_MAILADRES> aan naar je eigen mailadres. Sla tot slot je wijzigingen op en sluit het bestand (ctrl + x > y > enter).
Stap 2
Pas de configuratie van het .yaml bestand toe op je cluster:
kubectl apply -f letsencrypt-issuer.yaml Je krijgt nu een bevestiging te zien dat de configuratie succesvol is toegepast:
clusterissuer.cert-manager.io/letsencrypt-issuer created
Let op: Wanneer je een certificaat wil genereren (zie de volgende paragraaf) maak je een Ingress resource die precies de waarde hierboven moet gebruiken, oftewel clusterissuer.cert-manager.io/letsencrypt-issuer
Cert-manager gebruiken
Cert-manager is nu klaar voor gebruik. In plaats van een Nginx Ingress Controller gaan we in dit artikel uit van Traefik als Gateway Controller (Gateway API). Het gebruik van Cert-manager bestaat dan uit twee onderdelen:
- Je laat Cert-manager een TLS-certificaat uitgeven (als Kubernetes Secret).
- Je koppelt die Secret aan je
Gateway-listener viatls.certificateRefs.
Het is aan te raden om de applicatie (Deployment/Service) alvast te deployen voordat je het certificaat en de Gateway/HTTPRoute-resources aanmaakt.
Stap 1
Zorg dat je (sub)domein verwijst naar het publieke adres van Traefik (de LoadBalancer). Dit is het IP-adres of de *.haip.transip.net-hostname die je ziet met kubectl get svc -n traefik. Zonder deze DNS-verwijzing kan Let’s Encrypt (bij HTTP-01) je domein niet valideren.
Stap 2
Maak een Certificate-resource aan in dezelfde namespace als je Gateway (in dit voorbeeld demo-gateway). Cert-manager maakt vervolgens een TLS Secret aan (bijv. demo-gateway-tls) die je later in de Gateway gebruikt.
nano demo-certificate.yamlGeef het bestand bijvoorbeeld deze inhoud (pas domein/issuer/namespace naar wens aan):
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: demo-cert
namespace: demo-gateway
spec:
secretName: demo-gateway-tls
issuerRef:
name: letsencrypt-issuer
kind: ClusterIssuer
dnsNames:
- demo.voorbeeld.nl
Stap 3
Pas de resource toe op je Kubernetes-cluster met het commando:
kubectl apply -f demo-certificate.yaml
Stap 4
Controleer of het certificaat is uitgegeven. Onder READY hoort uiteindelijk True te staan en onder SECRET de Secret die je in spec.secretName hebt opgegeven.
kubectl get certificate -n demo-gateway
kubectl describe certificate demo-cert -n demo-gatewayZie je READY False? Bekijk dan ook de onderliggende challenge/order-resources om de oorzaak te vinden:
kubectl get challenge,order,certificaterequest -n demo-gateway
Stap 5
Koppel nu de uitgegeven TLS Secret aan je Gateway. In de HTTPS-listener verwijs je naar dezelfde Secret (demo-gateway-tls) via tls.certificateRefs. Let op: Traefik’s Helm chart gebruikt vaak entryPoints op 8000/8443 (extern nog steeds 80/443); zorg dat de listener-poorten overeenkomen met jouw Traefik entryPoints.
Maak een bestand/resource aan met bijvoorbeeld de naam demo-gateway.yaml en de volgende inhoud (pas hostnames/ports/namespace aan naar jouw setup):
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: demo-gateway
namespace: demo-gateway
spec:
gatewayClassName: traefik
listeners:
- name: web
protocol: HTTP
port: 8000
hostname: demo.voorbeeld.nl
allowedRoutes:
namespaces:
from: Same
- name: websecure
protocol: HTTPS
port: 8443
hostname: demo.voorbeeld.nl
tls:
mode: Terminate
certificateRefs:
- kind: Secret
name: demo-gateway-tls
allowedRoutes:
namespaces:
from: Same
Stap 6
Pas de configuratie opnieuw toe met een kubectl apply -f commando:
kubectl apply -f demo-gateway.yaml
Stap 7
Om HTTP automatisch naar HTTPS te redirecten zonder dubbele regels of redirect-loops, maak je twee aparte HTTPRoute-resources:
- Een route op de HTTP-listener (
sectionName: web) die alleen een redirect naarhttpsdoet. - Een route op de HTTPS-listener (
sectionName: websecure) die verkeer doorstuurt naar je backend Service.
Maak bijvoorbeeld eerst de HTTP->HTTPS redirect route aan in een bestand/resource met de naam demo-httproute-redirect.yaml:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: demo-route-redirect
namespace: demo-gateway
spec:
parentRefs:
- name: demo-gateway
sectionName: web
hostnames:
- demo.supporttest.nl
rules:
- matches:
- path:
type: PathPrefix
value: /
filters:
- type: RequestRedirect
requestRedirect:
scheme: https
statusCode: 301Maak daarna de HTTPS route aan die naar je applicatie verwijst in een bestand/resource met de naam demo-httproute.yaml:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: demo-route
namespace: demo-gateway
spec:
parentRefs:
- name: demo-gateway
sectionName: websecure
hostnames:
- demo.supporttest.nl
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: demo-app
port: 80
Stap 8
Pas beide routes toe en controleer de status:
kubectl apply -f demo-httproute-redirect.yaml
kubectl apply -f demo-httproute.yaml
kubectl describe gateway demo-gateway -n demo-gateway
kubectl describe httproute demo-route-redirect -n demo-gateway
kubectl describe httproute demo-route -n demo-gatewayThat's it! HTTP-verkeer naar http://demo.supporttest.nl wordt nu automatisch doorgestuurd naar https://demo.supporttest.nl, en HTTPS-verkeer wordt naar je backend Service gerouteerd.