Using Certmanager with Cloudflare and Kubernetes

How to configure certmanager for DNS challenges with Cloudflare and Kubernetes
What is Certmanager
Certmanager is a native Kubernetes cluster certificate manager. This article aims to outline the process of using Certmanager to manage SSL certificate creation and renewals via letsencrypt. Prior to certificate issuance, letsencrypt requires a challenge to verify ownership of a domain. In this article, we will configure Certmanager and letsencrypt to use a DNS-01
challenge against Cloudflare hosted DNS.
Requirements
- A working Kubernetes Cluster
- Kubectl connected to your cluster
- A valid domain name that you own
- DNS for said damain hosted by Cloudflare
Verify kubectl
is connected to your cluster
kubectl get nodes
You should see your Kubernetes nodes printed. If not, please configure your kubectl
to connect to your cluster
Cloudflare API Key
Let’s Encrypt offers several domain verification methods. The simplest solutions is their HTTP-01
challenge, which uses a file hosted on your website as verification. This method is not always useful, as our websites may not be publicly accessible. In our case, we are going to make use of the DNS-01
challenge. When using the DNS-01
challenge, Let’s Encrypt will require the creation of a TXT
record with a random code. Certmanager will automate the creation and deletion of these TXT
challenge DNS recrods. To do so, we will need give our certmanager install access to manage our DNS records. In our case, we’re using Cloudflare, which makes use of API keys.
Obtaining your API Key
Certmanager can now use a Zone Specific API Key
- Log into your Cloudflare Dashboard
- Click on your Account Icon (top right of page)
- Click "My Profile"
- Click on "API Tokens"
- Click "Create Token"
- Create a Token with the following permissions
- Token Name: cert-manager
- Zone - Zone - Read
- Zone - DNS - Edit
Install Certmanager
Pre-reqs
Create a namespace, install CRDs and Certmanager
Updated on March 17th, 2020. Update the version tag below to the newest release of cert-manager
CERT_MANAGER_VERSION=v0.14.0
kubectl create namespace cert-manager
kubectl label namespace cert-manager certmanager.k8s.io/disable-validation=true
# Kubernetes 1.15+
kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/$CERT_MANAGER_VERSION/cert-manager.yaml
#Kubernetes <1.15
kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/$CERT_MANAGER_VERSION/cert-manager-legacy.yaml
Verify that Cert Manager has Installed
kubectl get po -n cert-manager
NAME READY STATUS RESTARTS AGE
cert-manager-5d8d74bb4d-7n2qq 1/1 Running 0 15h
cert-manager-cainjector-5db54b6b45-5hrwt 1/1 Running 0 15h
cert-manager-webhook-7cd5d4fdd7-95smt 1/1 Running 0 15h
Cloudflare API Secret
You need your Cloudflare API Key
This will create a new Kuberentes secret with your Cloudflare API Key for Certmanager to reference.
API_KEY=$(echo YOUR-API-KEY-HERE | base64 -)
cat <<EOF | kubectl apply -f -
---
apiVersion: v1
kind: Secret
metadata:
name: cloudflare-api-key
namespace: cert-manager
type: Opaque
data:
api-key: ${API_KEY}
EOF
Create a Staging Issuer
Since Let's Encrypt imposes a limit of 50 certificates per domain per week, we should do all of our testing against their Staging
envrionment. Only use the Production
envrionment once you have finished your testing.
EMAIL_ADDRESS="[email protected]"
cat <<EOF | kubectl apply -f -
---
apiVersion: certmanager.k8s.io/v1alpha1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
server: https://acme-staging-v02.api.letsencrypt.org/directory
email: ${EMAIL_ADDRESS}
privateKeySecretRef:
name: letsencrypt-staging
dns01:
providers:
- name: cf-dns
cloudflare:
email: ${EMAIL_ADDRESS}
apiTokenSecretRef:
name: cloudflare-api-key
key: api-key
EOF
Create a Production Issuer
This will be used after your testing is complete
EMAIL_ADDRESS="[email protected]"
cat <<EOF | kubectl apply -f -
---
apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: ${EMAIL_ADDRESS}
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- dns01:
cloudflare:
email: ${EMAIL_ADDRESS}
apiTokenSecretRef:
name: cloudflare-api-key
key: api-key
EOF
Add Ingress Annotations
Now that Certmanager is configure, we need to add annotations to our ingress documents to make use of it. Add the following annotations
to your ingress documents
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
kubernetes.io/tls-acme: "true"
kubernetes.io/ssl-redirect: "true"
Then add the following to the spec
section of your ingress document. Replace domain.tld
with your domain name. Add additional entries here for subdomains or alias domains. You will also provide a secretName
name here, this is where certmanager will store your private key and certificate
tls:
- hosts:
- domain.tld
secretName: domain-tld-tls