Installing Cert Manager

We want to issue free SSL certificates for ingress https resources.

Treafik has a build in integration with Letsencrypt but unfourtunatelly its is not compatible with a HA setup where you have more than one instance of the ingress running (Deployment with replicas > 1 or DaemonSet). Instead of using it, we will use a separate installation of cert-manager

We will also use the DNS chanllenge type with Cloudflare DNS provider.

Instalation

Is simple with helm:

helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install cert-manager jetstack/cert-manager --namespace cert-manager --create-namespace --version v1.5.4 --set installCRDs=true

Now lets create the token for the DNS challenge:

Go to your domain and select "Get your API token"

Got to "Create token" then select Edit zone DNS template

In "Zone Resources" select the DNS zone you want

In "Permissions" select the following

  • Zone - DNS - Edit
  • Zone - Zone - Read

Click on generate token

Configuration and Test

Create the cloudflare token:

apiVersion: v1
 kind: Secret
 metadata:
   name: cloudflare-api-token-secret
   namespace: cert-manager
 type: Opaque
 stringData:
   api-token: token-generate

Apply with kubectl apply -f cloudflare-dns-api-secret.yml of course change the file name to your secret file.

Create the cluster issues for staging and production, files

staging-cluster-issuer.yml

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
  namespace: cert-manager
spec:
  acme:
      # You must replace this email address with your own.
      # Let's Encrypt will use this to contact you about expiring
      # certificates, and issues related to your account.
      email: youremail
      server: https://acme-staging-v02.api.letsencrypt.org/directory
      privateKeySecretRef:
        name: staging-issuer-account-key
      solvers:
      - dns01:
          cloudflare:
            email: yourcloudflareemail
            apiTokenSecretRef:
              name: cloudflare-api-token-secret
              key: api-token

prod-cluster-issuer.yml

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
  namespace: cert-manager
spec:
  acme:
      # You must replace this email address with your own.
      # Let's Encrypt will use this to contact you about expiring
      # certificates, and issues related to your account.
      email: youremail
      server: https://acme-v02.api.letsencrypt.org/directory
      privateKeySecretRef:
        name: prod-issuer-account-key
      solvers:
      - dns01:
          cloudflare:
            email: yourcloudflareemail
            apiTokenSecretRef:
              name: cloudflare-api-token-secret
              key: api-token

Apply this yaml:

kubectl apply -f staging-cluster-issuer.yml
kubectl apply -f prod-cluster-issuer.yml

Lets test the certification issuer:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: test-domain-com
  namespace: cert-manager
spec:
  secretName: test-domain-com
  issuerRef:
    name: letsencrypt-staging
    kind: ClusterIssuer
  commonName: test.domain.com
  dnsNames:
  - test.domain.com

Edit test.domain.com and test-domain-com with your domain

Apply with kubectl apply -f test-certificate.yml

See if its ready:

kubectl -n cert-manager get certificate

When the certificate gets ready (it should take a minute or two), describe it:

kubectl -n cert-manager describe certificate test-domain-com

Should have something like:

Name:         test-domain-com
Namespace:    cert-manager
Labels:       <none>
Annotations:  <none>
API Version:  cert-manager.io/v1
Kind:         Certificate
Metadata:
  Creation Timestamp:  2021-10-25T17:08:36Z
  Generation:          1
  Managed Fields:
    API Version:  cert-manager.io/v1
    Fields Type:  FieldsV1
    fieldsV1:
      f:metadata:
        f:annotations:
          .:
          f:kubectl.kubernetes.io/last-applied-configuration:
      f:spec:
        .:
        f:commonName:
        f:dnsNames:
        f:issuerRef:
          .:
          f:kind:
          f:name:
        f:secretName:
    Manager:      kubectl-client-side-apply
    Operation:    Update
    Time:         2021-10-25T17:08:36Z
    API Version:  cert-manager.io/v1
    Fields Type:  FieldsV1
    fieldsV1:
      f:status:
        .:
        f:conditions:
        f:notAfter:
        f:notBefore:
        f:renewalTime:
        f:revision:
    Manager:         controller
    Operation:       Update
    Time:            2021-10-25T17:10:03Z
  Resource Version:  1002607
  UID:               8646cd17-50fa-4419-9dcf-184ea2340bb5
Spec:
  Common Name:  test.doamin.com
  Dns Names:
    test.domain.com
  Issuer Ref:
    Kind:       ClusterIssuer
    Name:       letsencrypt-staging
  Secret Name:  test-domain-com
Status:
  Conditions:
    Last Transition Time:  2021-10-25T17:10:03Z
    Message:               Certificate is up to date and has not expired
    Observed Generation:   1
    Reason:                Ready
    Status:                True
    Type:                  Ready
  Not After:               2022-01-23T16:10:01Z
  Not Before:              2021-10-25T16:10:02Z
  Renewal Time:            2021-12-24T16:10:01Z
  Revision:                1
Events:
  Type    Reason     Age   From          Message
  ----    ------     ----  ----          -------
  Normal  Issuing    3m6s  cert-manager  Issuing certificate as Secret does not exist
  Normal  Generated  3m6s  cert-manager  Stored new private key in temporary Secret resource "test-domain-com-zgtqd"
  Normal  Requested  3m6s  cert-manager  Created new CertificateRequest resource "test-domain-com-r78kp"
  Normal  Issuing    99s   cert-manager  The certificate has been successfully issued

Cleaning up:

kubectl delete -f test-certificate.yml
kubectl -n cert-manager delete secret test-domain-com

For more information on how to issue certificates for your ingress resources see the official documentation https://cert-manager.io/next-docs/usage/ingress/

A tip is when using traefik IngressRoute we need to issue the certificate outside the ingress, you can see a example in this post https://www.padok.fr/en/blog/traefik-kubernetes-certmanager

Congratulations, you have a automated, free SSL certification issuer. K8S is awesome!