In our previous blog post, we configured ingress to our Kubernetes cluster but were disappointed to discover that the TLS certificates were self-signed. In this post we’ll remedy that by installing cert-manager, the Cloud native certificate management tool.
Disclaimer: most of this blog post was lifted whole cloth from the most-excellent cert-manager documentation. We merely condensed it & made it more opinionated.
Installation
Let’s add the Jetstack Helm Repository:
helm repo add jetstack https://charts.jetstack.io
helm repo update
Let’s install cert-manager:
helm install \
cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.6.1 \
--set installCRDs=true
Verifying Installation
Do we see all three pods?
kubectl get pods --namespace cert-manager
Now let’s create an issuer to test the webhook:
cat <<EOF > test-resources.yaml
apiVersion: v1
kind: Namespace
metadata:
name: cert-manager-test
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: test-selfsigned
namespace: cert-manager-test
spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: selfsigned-cert
namespace: cert-manager-test
spec:
dnsNames:
- example.com
secretName: selfsigned-cert-tls
issuerRef:
name: test-selfsigned
EOF
And now let’s apply those resources:
kubectl apply -f test-resources.yaml
sleep 10
kubectl describe certificate -n cert-manager-test | grep "has been successfully"
kubectl delete -f test-resources.yaml
4. Deploy an Example Service
Let’s install the sample services to test the controller:
kubectl apply -f https://netlify.cert-manager.io/docs/tutorials/acme/example/deployment.yaml
kubectl apply -f https://netlify.cert-manager.io/docs/tutorials/acme/example/service.yaml
Let’s download and edit the Ingress (we’ve already configured gke.nono.io
to
point to the GCP/GKE load balancer at 34.135.26.144). Replace gke.nono.io
with the DNS record of your load balancer set up in the previous blog post:
curl -o ingress-kuard.yml -L https://netlify.cert-manager.io/docs/tutorials/acme/example/ingress.yaml
sed -i '' "s/example.example.com/gke.nono.io/g" ingress-kuard.yml
kubectl apply -f ingress-kuard.yml
Let’s use curl to check the GKE load balancer. Replace gke.nono.io
with the
DNS record of your load balancer set up in the previous blog post:
curl -kivL -H 'Host: gke.nono.io' https://gke.nono.io
You should see output similar to the following (note that the cert is still self-signed):
...
* Server certificate:
* subject: O=Acme Co; CN=Kubernetes Ingress Controller Fake Certificate
6. Configure Let’s Encrypt Issuer
Let’s deploy the staging & production issuers. Replace
brian.cunnie@gmail.com
with your email address:
kubectl apply -f <(
curl -o- https://cert-manager.io/docs/tutorials/acme/example/staging-issuer.yaml |
sed 's/user@example.com/brian.cunnie@gmail.com/')
kubectl apply -f <(
curl -o- https://cert-manager.io/docs/tutorials/acme/example/production-issuer.yaml |
sed 's/user@example.com/brian.cunnie@gmail.com/')
# check to make sure they were deployed:
kubectl describe issuer letsencrypt-staging
kubectl describe issuer letsencrypt-prod
7. Step 7 - Deploy a TLS Ingress Resource
Let’s deploy the ingress resource using annotations to obtain the certificate.
Replace gke.nono.io
with the DNS record of your load balancer set up in
the previous blog post:
kubectl apply -f <(
curl -o- https://cert-manager.io/docs/tutorials/acme/example/ingress-tls.yaml |
sed 's/example.example.com/gke.nono.io/')
kubectl get certificate # takes ~30s to become ready ("READY" == "True")
kubectl describe certificate quickstart-example-tls
kubectl describe secret quickstart-example-tls
Let’s use curl again to check the GKE load balancer’s certificate. Replace
gke.nono.io
with the DNS record of your load balancer set up in the previous
blog post:
curl -kivL -H 'Host: gke.nono.io' https://gke.nono.io
You should see output similar to the following:
...
* Server certificate:
* subject: CN=gke.nono.io
* start date: Sep 1 22:02:55 2021 GMT
* expire date: Nov 30 22:02:54 2021 GMT
* issuer: C=US; O=(STAGING) Let's Encrypt; CN=(STAGING) Artificial Apricot R3
Great! We have the staging cert, but that’s not quite good enough—we want a real
certificate. Let’s upgrade to the production certificate. As usual, Replace
gke.nono.io
with the DNS record of your load balancer set up in the previous
blog post:
kubectl apply -f <(
curl -o- https://cert-manager.io/docs/tutorials/acme/example/ingress-tls-final.yaml |
sed 's/example.example.com/gke.nono.io/')
kubectl delete secret quickstart-example-tls # triggers the process to get a new certificate
kubectl get certificate # takes ~30s to become ready ("READY" == "True")
kubectl describe certificate quickstart-example-tls
kubectl describe secret quickstart-example-tls
Let’s use curl one more time to check the GKE load balancer’s certificate.
Replace gke.nono.io
with the DNS record of your load balancer set up in
the previous blog post:
curl -kivL -H 'Host: gke.nono.io' https://gke.nono.io
You should see output similar to the following:
...
* Server certificate:
* subject: CN=gke.nono.io
* start date: Sep 1 22:11:36 2021 GMT
* expire date: Nov 30 22:11:35 2021 GMT
* issuer: C=US; O=Let's Encrypt; CN=R3
* SSL certificate verify ok.
And now browse (replacing gke.nono.io
with the DNS record of your load
balancer): https://gke.nono.io/. Yes, we get an HTTP 503 status, but our
certificate is valid!
Stay Tuned!
Stay tuned for our next installment, where we install Concourse CI on GKE.
References
- cert-manager documentation: https://cert-manager.io/docs/
Updates/Errata
2022-01-08 Bumped the cert-manager version 1.6.0 → 1.6.1; fixed scheme (was http
; now is https
)
2021-11-13 Bumped the cert-manager version 1.5.0 → 1.6.0