Syncing cert-manager certificate secret across Namespaces using kubed

- 2 mins

Introduction

cert-manager is a native Kubernetes certificate management controller. It can help with issuing certificates from a variety of sources, such as Let’s Encrypt.

A common use-case for cert-manager is requesting TLS signed certificates to secure your ingress resources. This can be done by simply adding this annotation cert-manager.io/cluster-issuer: nameOfClusterIssuer to your Ingress resources and cert-manager will facilitate creating the Certificate resource for you.

When you have multiple ingresses in separate namespaces, this annotation ends up creating certificate resources in each of the namespaces. If you use Let’s encrypt, the limit of Duplicate Certificates is 5 per week, and it is easy to hit this limit if you have a lot of namespaces. You can decide to create the TLS secret for the certificate in one namespace and copy manually across all namespaces, but that will be a pain to manage and maintain. cert-manager docs recommends using kubed with its secret syncing feature to solve this problem.

This article was written based on cert-manager v1.3 and kubed v0.12.0. This article does not address wildcard certificate usecase.

Sync ingress certificate secret across namespaces using kubed

In order for the target Secret to be synced, the Secret resource must first be created with the correct annotations before the creation of the Certificate, else the Secret will need to be edited instead. When I tried this out, I created the Certificate first and edited the secret annotation afterwards.

The example below creates a certificate resource in sandbox namespace. This in turn creates a secret cert-secret.

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: cert-secret
  namespace: sandbox
spec:
  secretName: cert-secret
  issuerRef:
    name: letsencrypt-prod
    kind: ClusterIssuer
  dnsNames:
  - domain.example.com

Now apply the kubed.appscode.com/sync: "" annotation to the cert-secret created by the cert-manager Certificate resource.

kubectl annotate secret cert-secret kubed.appscode.com/sync=""

This annotation will cause Kubed operator to copy the secret to all existing and new namespaces. If you want to synchronize this secret to some selected namespaces instead of all namespaces, you can do that by specifying namespace label-selector in the annotation. For example: kubed.appscode.com/sync: "app=kubed".

You can now create your ingress resources to use the copied secret and you will no longer need this cert-manager annotation cert-manager.io/cluster-issuer: nameOfClusterIssuer in your ingress.

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  tls:
  - hosts:
    -  domain.example.com
    secretName: cert-secret
  rules:
  ...
Kosy Anyanwu

Kosy Anyanwu

The lady who travels the world and loves karaoke

comments powered by Disqus
rss facebook twitter github gitlab youtube mail spotify lastfm instagram linkedin google google-plus pinterest medium vimeo stackoverflow reddit quora quora