- Welcome to jaehong21! :tada:/
- Posts/
- [K3s-05] How to automate issuing TLS certificate in K3s ingress/
[K3s-05] How to automate issuing TLS certificate in K3s ingress
Table of Contents
Let’s encrypt + ACME dns-01 (Recommended) #
By using Let's encrypt
and cert-manager
we can attach some TLS certificate to our k3s cluster. Install cert-manager
using helm
. I won’t explain about how to install helm
and what is helm
in this post. If helm
is not installed, please refer to helm docs
helm repo add jetstack https://charts.jetstack.io
helm repo update
curl -L -o cert-manager.yaml https://github.com/cert-manager/cert-manager/releases/download/v1.8.0/cert-manager.crds.yaml
kubectl apply -f cert-manager.yaml
helm install cert-manager jetstack/cert-manager \
--namespace cert-manager \
--create-namespace \
--version v1.8.0
kubectl get pods -n cert-manager
First, create a ClusterIssuer (that can access through across the namespaces). Also, k3s secret that store cloudflare api token. This cloudflare api token must have access to edit DNS zones (in dns-01 challenges). If you are using Route53 in AWS, you can visit this blog (Medium about Wildcard certificates). So, the basic idea is to know what cloud provider you are using for your DNS. For detailed list that cert-manager
supports, visit cert-manager configuration on acme dns01
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-stg
spec:
acme:
email: [email protected]
# let's encrypt staging environment
server: https://acme-staging-v02.api.letsencrypt.org/directory
privateKeySecretRef:
# Secret resource that will store the account's private key.
name: le-issuer-acct-key
solvers:
- dns01:
cloudflare:
email: [email protected]
apiTokenSecretRef:
name: cloudflare-api-token-secret
key: api-token
selector:
dnsZones:
- 'jaehong21.com'
- '*.jaehong21.com'
---
apiVersion: v1
kind: Secret
metadata:
name: cloudflare-api-token-secret
namespace: cert-manager
type: Opaque
stringData:
api-token: <cloudflare-api-token>
Then, check if issuer’s status Ready
is True
by kubectl get clusterissuer -A
. It may take some time.
! IMPORTANT: https://letsencrypt.org/docs/staging-environment/
You must be aware above example with https://acme-staging-v02.api.letsencrypt.org/directory
is an staging environment for let’s encrypt, which doesn’t get bounded to rate limit issuing certificates. You must replace above URL to https://acme-v02.api.letsencrypt.org/directory
in production, when you want to get an trusted(valid) certificate for the browser.
Now, create a certificate with existing issuers. Even wildcards certificate is available when it is using dns-01 challenges. When it is using http-01, it is hard to achieve wildcard certificates, you should directly annotate the specific URL.
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: le-jaehong21-com
namespace: default
spec:
secretName: le-jaehong21-com
issuerRef:
name: letsencrypt-stg
kind: ClusterIssuer
commonName: '*.jaehong21.com'
dnsNames:
- "*.jaehong21.com"
# Check whether certificates are created
# Initially, the `Ready` status will be `False`
kubectl get certs -A
# issues are presented command below will show the progress
# when it is done, it won't show any resources
kubectl get challenges -A
# After, double-check whether certificate's `Ready` is also `True`
You can also, look at the progress by checking the (cloudflare) dashboard whether TXT records are added on the hosted zone (which is used with dns-01 challenges).
Finally, implement the tls secret that is created with certificate to the ingress.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: traefik-ingress
annotations:
traefik.ingress.kubernetes.io/router.tls: "true"
spec:
ingressClassName: traefik
rules:
- host: k3s.jaehong21.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-deployment
port:
number: 80
tls:
- hosts:
- k3s.jaehong21.com
secretName: le-jaehong21-com
Cloudflare Origin CA #
For me, I used to manage DNS records on Cloudflare. Which Cloudflare also provides to issue some certificate with much longer expiry date compare to let’s encrypt.
kubectl create secret generic k3s-tls-secret --from-file=tls.crt=./server.crt --from-file=tls.key=./server.key --namespace dev
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: traefik-ingress
annotations:
traefik.ingress.kubernetes.io/router.tls: "true"
spec:
ingressClassName: traefik
rules:
- host: k3s.jaehong21.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-deployment
port:
number: 80
tls:
- secretName: k3s-tls-secret
However, Origin CA is a self-signed certificate, which is valid only in Cloudflare Network itself. So, to do so the host must be proxied through Cloudflare Network like example below. In this case, as reqeusts are going through Cloudflare Network, it can be rerouted through LAX locations also.
resource "cloudflare_record" "k3s_test" {
zone_id = var.jaehong21_com.zone_id
name = "k3s"
value = "43.202.242.99"
proxied = true
type = "A"
ttl = 1
}
You should upgrade terraform cloudflare provider to the latest version (at least above version 4). As version 3 in cloudflare-go has bug on modifying and maintaining proxied
value to true
on terraform.