Civo's documentation on how to Secure your Kubernetes services with Let's Encrypt and cert-manager
Get a TLS Certificate For Your Application With JetStack's Cert-Manager
cd build
civo kubernetes applications add cert-manager --cluster cultivate-finance
kubectl get pods --namespace cert-manager # you should see 3 entries: # 1. cert-manager-cainjector-<uid> # 2. cert-manager-<uid> # 3. cert-manager-webhook-<uid>
We are going to use ClusterIssuers because we are going to be creating certificates in the 'default' namespace using issuers in the cert-manager namespace.
kubectl apply -f k8s/ssl-certificate/cert-issuer.yml
kubectl get secrets --namespace cert-manager # you should see 2 entries: # letsencrypt-prod # letsencrypt-staging
Civo's default DNS is a uuid followed by .k8s.civo.com, or looks something like 798a2f3d-a352-40aa-a882-ef5000d3653a.k8s.civo.com
. We need change the entries in k8s/certificates-staging.yml
and k8s/certificates-prod.yml
to match our DNS name.
civo kubernetes show cultivate-finance -o custom -f "DNSEntry" | sed "s/\..*//"
k8s/certificates-staging.yml
: apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: <UUID GOES HERE>-staging-cert namespace: default spec: commonName: '<UUID GOES HERE>.k8s.civo.com' dnsNames: - '<UUID GOES HERE>.k8s.civo.com' issuerRef: kind: ClusterIssuer name: letsencrypt-staging secretName: <UUID GOES HERE>-staging-cert ### EXAMPLE # apiVersion: cert-manager.io/v1 # kind: Certificate # metadata: # name: 798a2f3d-a352-40aa-a882-ef5000d3653a-staging-cert # namespace: default # spec: # commonName: '798a2f3d-a352-40aa-a882-ef5000d3653a.k8s.civo.com' # dnsNames: # - '798a2f3d-a352-40aa-a882-ef5000d3653a.k8s.civo.com' # issuerRef: # kind: ClusterIssuer # name: letsencrypt-staging # secretName: 798a2f3d-a352-40aa-a882-ef5000d3653a-staging-cert
k8s/certificates-prod.yml
: apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: <UUID GOES HERE>-prod-cert namespace: default spec: commonName: '<UUID GOES HERE>.k8s.civo.com' dnsNames: - '<UUID GOES HERE>.k8s.civo.com' issuerRef: kind: ClusterIssuer name: letsencrypt-prod secretName: <UUID GOES HERE>-prod-cert
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: cultivate-finance-ingress-base-dns namespace: default labels: name: cultivate-finance-ingress-base-dns annotations: kubernetes.io/ingress.class: traefik spec: tls: - hosts: - '<UUID GOES HERE>.k8s.civo.com' secretName: <UUID GOES HERE>-staging-cert rules: - host: '<UUID GOES HERE>.k8s.civo.com' http: paths: - path: "/" pathType: Prefix backend: service: name: webapp-service port: number: 8662
Staging certificates are not functional, but since we are using letsencrypt's api, we want to make sure our certificate creation is working as expected before creating real certificates.
kubectl apply -f k8s/ssl-certificate/certificates-staging.yml
kubectl get certificate --namespace default ## You should see 3 entries # cultivate-finance-staging-www-cert # cultivate-finance-staging-base-cert # <UUID from earlier>-staging-cert
READY
status is True
. You can repeat the command over and over again to check their ready status, but you can also check the event log in kubernetes dashboardREADY
Now that we have our test certificates, we need to smoke test them by confirming they are attached to our webapp. In order to do that, we must confirm our ingress and webapp pods are deployed by doing the following:
Once those are deployed you can confirm they are using our testing certificates from earlier:
openssl s_client -connect www.cultivatefinance.org:443 ## Confirm you see something along the lines of: # depth=1 C=US, O=(STAGING) Let's Encrypt, CN=(STAGING) Wannabe Watercress R11 # issuer=C=US, O=(STAGING) Let's Encrypt, CN=(STAGING) Wannabe Watercress R11 # # The important part is O=(STAGING) Let's Encrypt, CN=(STAGING)
openssl s_client -connect cultivatefinance.org:443
openssl s_client -connect $(civo kubernetes show cultivate-finance -o custom -f "DNSEntry"):443
* NOTE: ONLY CONTINUE TO THESE STEPS AFTER YOU HAVE SUCCESSFULLY COMPLETED THE PREVIOUS ONES WITHOUT ISSUE.
Now that we have confirmed our application is running with testing tls certificates, we can do the real thing.
kubectl apply -f k8s/ssl-certificate/certificates-prod.yml
kubectl get certificate --namespace default ## You should see 3 new entries # cultivate-finance-prod-www-cert # cultivate-finance-prod-base-cert # <UUID from earlier>-prod-cert
READY
state. It could take up to 30 minutes.kubectl delete -f k8s/ingress-traefik-staging.yml
kubectl apply -f k8s/ingress-traefik-prod.yml