Skip to main content

Issuing certificate with cert-manager

Preface

A few months ago, I set up a multi-cloud k3s cluster and installed cert-manager to issue certificates for the cluster. Unfortunately, the certificate expired because it did not auto-renew recently, so I had to issue a new one. This post will discuss the deployment process of cert-manager and how to issue certificates.

Manifests

Please make sure that all the manifests are applied in the same namespace.

cert-manager

kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.12.0/cert-manager.yaml

Configuring DNS01 Challenge Provider

The certificate is managed in Cloudflare, so I choose to use Cloudflare as the DNS01 challenge provider.

apiVersion: v1
kind: Secret
metadata:
  name: cloudflare-api-key-secret
  namespace: cert-manager
type: Opaque
stringData:
  api-key: <API Key>
---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
  namespace: cert-manager
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: [email protected]
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
    - dns01:
        cloudflare:
          email: [email protected]
          apiKeySecretRef:
            name: cloudflare-api-key-secret
            key: api-key

ClusterIssuer and traefik

Before issuing the certificate, please create the cluster issuer and default TLS store.

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: wildcard-example-com
  namespace: cert-manager
spec:
  secretName: wildcard-example-com-tls
  issuerRef:
    name: letsencrypt-prod
    kind: ClusterIssuer
  dnsNames:
    - "*.example.com"
---
apiVersion: traefik.containo.us/v1alpha1
kind: TLSStore
metadata:
  name: default
  namespace: cert-manager
spec:
  defaultCertificate:
    secretName: wildcard-example-com-tls

Service ingress

To configure the service ingress with HTTPS.

kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
  name: <service-name>-ing
  namespace: veda
  annotations:
    traefik.ingress.kubernetes.io/router.tls: "true"
spec:
  rules:
    - host: <service-name>.example.com # your hostname
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: <service-name>-svc
                port:
                  number: 80
  tls:
    - hosts:
      - <service-name>.example.com
      secretName: wildcard-example-com-tls

How it works

I copied the workflow from the official document.

(  +---------+  )
  (  | Ingress |  ) Optional                                              ACME Only!
  (  +---------+  )
         |                                                     |
         |   +-------------+      +--------------------+       |  +-------+       +-----------+
         |-> | Certificate |----> | CertificateRequest | ----> |  | Order | ----> | Challenge |
             +-------------+      +--------------------+       |  +-------+       +-----------+
                                                               |

Finally

I think you will enjoy the security of HTTPS with your services.

Reference