Nginx Ingress Controller + Cert-Manager + Let's Encrypt
- Prerequisites
- Kubernetes cluster
- A "real" domain
- An email address
- Reference
- Notes
- DO NOT create any ingress nginx
Install Nginx Ingress Controller
After installing Nginx Ingress Controller, point your domain to the external IP of the Nginx Ingress Controller.
Install Cert-Manager
helm install \
cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.16.2 \
--set crds.enabled=true
Let's Rock with Let's Encrypt
Deploy foo app
kubectl create deployment echo-server --image=mccutchen/go-httpbin
kubectl expose deployment echo-server --name=clusterip --port=80 --target-port=8080 --type=ClusterIP
Test with Staging
Create Issuer, change email in this yaml file.
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: letsencrypt-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
email: ______________________ # Change to your email
privateKeySecretRef:
name: letsencrypt-staging
solvers:
- http01:
ingress:
ingressClassName: nginx
Check Issuer created:
kubectl describe issuer letsencrypt-staging
It's conditions should look like this:
Status:
Acme:
Uri: https://acme-staging-v02.api.letsencrypt.org/acme/acct/7374163
Conditions:
Last Transition Time: ...
Message: The ACME account was registered with the ACME server
Reason: ACMEAccountRegistered
Status: True
Type: Ready
Deploy ingress, change domain in this yaml file.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: go-httpbin
annotations:
cert-manager.io/issuer: "letsencrypt-staging"
acme.cert-manager.io/http01-edit-in-place: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- ______________________ # Change to your domain
secretName: quickstart-example-tls
rules:
- host: ______________________ # Change to your domain
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: clusterip
port:
number: 80
Check certificate created:
kubectl get certificate
NAME READY SECRET AGE
quickstart-example-tls True quickstart-example-tls 16m # Ready should be True
Check certificate details:
kubectl describe certificate quickstart-example-tls
Name: quickstart-example-tls
Namespace: default
Labels: <none>
Annotations: <none>
API Version: cert-manager.io/v1
Kind: Certificate
Metadata:
Cluster Name:
Creation Timestamp: 2018-11-17T17:58:37Z
Generation: 0
Owner References:
API Version: networking.k8s.io/v1
Block Owner Deletion: true
Controller: true
Kind: Ingress
Name: kuard
UID: a3e9f935-ea87-11e8-82f8-42010a8a00b5
Resource Version: 9295
Self Link: /apis/cert-manager.io/v1/namespaces/default/certificates/quickstart-example-tls
UID: 68d43400-ea92-11e8-82f8-42010a8a00b5
Spec:
Dns Names:
www.example.com
Issuer Ref:
Kind: Issuer
Name: letsencrypt-staging
Secret Name: quickstart-example-tls
Status:
Acme:
Order:
URL: https://acme-staging-v02.api.letsencrypt.org/acme/order/7374163/13665676
Conditions:
Last Transition Time: 2018-11-17T18:05:57Z
Message: Certificate issued successfully
Reason: CertIssued
Status: True
Type: Ready
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal CreateOrder 9m cert-manager Created new ACME order, attempting validation...
Normal DomainVerified 8m cert-manager Domain "www.example.com" verified with "http-01" validation
Normal IssueCert 8m cert-manager Issuing certificate...
Normal CertObtained 7m cert-manager Obtained certificate from ACME server
Normal CertIssued 7m cert-manager Certificate issued Successfully
Try curl to your domain, it'll return cert are self-signed. It's OKAY because it's staging.
curl -kivL -H 'Host: ______DOMAIN______' 'http://_____IP_____'
Delete resources:
kubectl delete ingress go-httpbin
kubectl delete issuer letsencrypt-staging
kubectl delete secret quickstart-example-tls
kubectl delete secret letsencrypt-staging
Test with Production
Create Production Issuer, change email in this yaml file.
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: ______________________ # Change to your email
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
ingressClassName: nginx
Update Ingress annotation to use letsencrypt-prod.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: go-httpbin
annotations:
cert-manager.io/issuer: "letsencrypt-prod" # Change to letsencrypt-prod
acme.cert-manager.io/http01-edit-in-place: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- ______________________ # Change to your domain
secretName: quickstart-example-tls
rules:
- host: ______________________ # Change to your domain
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: clusterip
port:
number: 80