Let’s Encrypt in Kubernetes Cluster
Let’s Encrypt with a DNS Challenge to Cloudflare
The following is a startup guide to deploying cert-manager on a Kubernetes cluster. The key takeaway in this solution is that Eupraxia Labs uses the DNS Challenge capability to avoid exposing port 80, of the NGNIX Kubernetes Ingress Controller (KIC) to the Internet.
Although step-by-step manual instructions appear here, to allow for some experimentation in a development environment, this does not need to be performed manually. This is automatically provisioned with Helm Charts, in a CI/CD Codefresh pipeline, provided by Eupraxia Labs.
Base Install
[centos@vm-controller ~]$ kubectl create namespace cert-manager
[centos@vm-controller ~]$ kubectl label namespace cert-manager certmanager.k8s.io/disable-validation=true
[centos@vm-controller ~]$ kubectl apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.7.1/deploy/manifests/00-crds.yaml
[centos@vm-controller ~]$ kubectl apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.7.1/deploy/manifests/cert-manager.yaml --validate=false
You can confirm it is configured correctly.
-
Pods are running
[centos@vm-controller ~]$ kubectl get pods -n cert-manager
will return results that are similar to:
[centos@vm-controller ~]$ kubectl get po -n cert-manager NAME READY STATUS RESTARTS AGE cert-manager-5586f99bcb-zw6gj 1/1 Running 0 2d cert-manager-cainjector-859b594f4d-w9zjk 1/1 Running 1 2d cert-manager-webhook-7ffdc67f8f-x4sws 1/1 Running 0 2d
-
Credentials installed
[centos@vm-controller ~]$ kubectl get crd | grep certmanager
will return results that are similar to:
[centos@vm-controller ~]$ kubectl get crd | grep certmanager certificates.certmanager.k8s.io 2019-01-19T21:54:29Z challenges.certmanager.k8s.io 2019-08-06T14:15:48Z clusterissuers.certmanager.k8s.io 2019-01-19T21:54:29Z issuers.certmanager.k8s.io 2019-01-19T21:54:30Z orders.certmanager.k8s.io 2019-08-06T14:15:48Z
-
Certificates and Issuers installed
[centos@vm-controller ~]$ kubectl get issuercertificate -n cert-manager
will return results that are similar to
NAME AGE issuer.certmanager.k8s.io/cert-manager-webhook-ca 3m issuer.certmanager.k8s.io/cert-manager-webhook-selfsign 3m NAME AGE certificate.certmanager.k8s.io/cert-manager-webhook-ca 3m certificate.certmanager.k8s.io/cert-manager-webhook-webhook-tls 3m
Create the CloudFlare DNS issuer
- Get your CloudFlare Global API Key from the CloudFlare Dashboard
- https://dash.cloudflare.com/
- Select Overview
- Click
Get your API key
link - Click
View
next toGlobal API Key
- Enter your details and pass the I am not a robot challenge and click
View
- Copy the API Key Secret
- Issue the following to generate your CloudFlare API Key Secret
API_KEY=$(echo xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | base64 -)
cat <<EOF | kubectl apply -f -
---
apiVersion: v1
kind: Secret
metadata:
name: cloudflare-api-key
namespace: cert-manager
type: Opaque
data:
api-key.txt: ${API_KEY}
EOF
- Create the
ClusterIssuer
configuration
EMAIL_ADDRESS="xxxx@xxxx.xxx"
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}
apiKeySecretRef:
name: cloudflare-api-key
key: api-key.txt
EOF
- Create the Certificate
DOMAIN_NAME="xxxxx.xxxxx.xxx"
cat <<EOF | kubectl apply -f -
---
apiVersion: certmanager.k8s.io/v1alpha1
kind: Certificate
metadata:
name: $(echo $DOMAIN_NAME | tr . -)
namespace: cert-manager
spec:
secretName: $(echo $DOMAIN_NAME | tr . -)
issuerRef:
name: letsencrypt-staging
kind: ClusterIssuer
commonName: '${DOMAIN_NAME}'
dnsNames:
- ${DOMAIN_NAME}
acme:
config:
- dns01:
provider: cf-dns
domains:
- ${DOMAIN_NAME}
EOF
-
Confirm it has been created (may take a minute or 2 to generate) by issuing
[centos@vm-controller ~]$ kubectl describe certificate $(echo $DOMAIN_NAME | tr . -) -n cert-manager
will return results that are similar to
Name: xxxx-xxxx-xxx Namespace: cert-manager Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"certmanager.k8s.io/v1alpha1","kind":"Certificate","metadata":{"annotations":{},"name":"xxxx-xxxx-xxx","namespace":"cert-... API Version: certmanager.k8s.io/v1alpha1 Kind: Certificate Metadata: Cluster Name: Creation Timestamp: 2019-02-16T22:44:17Z Generation: 1 Resource Version: 3053428 Self Link: /apis/certmanager.k8s.io/v1alpha1/namespaces/cert-manager/certificates/xxxx-xxxx-xxx UID: 649849bf-323c-11e9-9371-00237d495614 Spec: Acme: Config: Dns 01: Provider: cf-dns Domains: xxxx.xxxx.xxx Common Name: xxxx.xxxx.xxx Dns Names: xxxx.xxxx.xxx Issuer Ref: Kind: ClusterIssuer Name: letsencrypt-staging Secret Name: xxxx-xxxx-xxx Status: Conditions: Last Transition Time: 2019-02-16T22:45:37Z Message: Certificate is up to date and has not expired Reason: Ready Status: True Type: Ready Not After: 2019-05-17T21:45:36Z Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal OrderCreated 43m cert-manager Created Order resource "xxxx-xxxx-xxx-2862881673" Normal OrderComplete 42m cert-manager Order "xxxx-xxxx-xxx-2862881673" completed successfully Normal CertIssued 42m cert-manager Certificate issued successfully Warning BadConfig 10m (x2 over 10m) cert-manager Resource validation failed: spec: Invalid value: "no issuer specified for Issuer '/letsencrypt-staging'": no issuer specified for Issuer '/letsencrypt-staging'
Remove
[centos@vm-controller ~]$ kubectl delete -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.6/deploy/manifests/cert-manager.yaml
[centos@vm-controller ~]$ kubectl delete -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.6/deploy/manifests/00-crds.yaml
[centos@vm-controller ~]$ kubectl delete namespace cert-manager