Reverse Proxy¶
Since we only have a single public IP, if we want to set up multiple public services we will need a reverse proxy to redirect the requests to the correct services. Our proxy will also handle the ssl termination, to simplify the set up of the services.
For managing our certificates we will be using cert-manager
and as a proxy we
will be using Traefik
.
Note
Traefik is the default proxy from k3s, but to have more granular control we are disabling it and we are going to deploy it as Helm chart
Traefik¶
Similarly, to deploy Traefik we have to execute:
kubectl create namespace proxy
helm repo add traefik https://helm.traefik.io/traefik
helm repo update
helm install -n proxy traefik traefik/traefik -f traefik-values.yaml --version 32.1.1
Note
In the logs we might have a warning and we might have to increase the rmeem_max
ansible all -b -m shell -a "sysctl -w net.core.rmem_max=2500000"
. To retrieve
the logs do kubectl -n proxy logs -f -l "app.kubernetes.io/name=traefik"
# https://github.com/traefik/traefik-helm-chart/blob/master/traefik/values.yaml
image:
#tag: "v2.11.0"
pullPolicy: IfNotPresent
deployment:
enabled: true
kind: Deployment
replicas: 2
ingressClass:
enabled: true
isDefaultClass: true
# We will create our IngressRoute for the dashboard
ingressRoute:
dashboard:
enabled: False
providers:
kubernetesCRD:
enabled: true
allowCrossNamespace: true
allowExternalNameServices: true
kubernetesIngress:
enabled: true
additionalArguments:
# Used for the generation of the certificates
- "--providers.kubernetesIngress.ingressClass=traefik-cert-manager"
- "--providers.kubernetesingress.allowexternalnameservices=true"
logs:
general:
level: INFO
format: json
access:
enabled: true
format: json
metrics:
prometheus:
entryPoint: metrics
addEntryPointsLabels: true
addRoutersLabels: true
addServicesLabels: true
manualRouting: false
service:
enabled: false
# TLS Options are created as TLSOption CRDs
# https://doc.traefik.io/traefik/https/tls/#tls-options
# Example:
tlsOptions:
default:
sniStrict: true
preferServerCipherSuites: true
cipherSuites:
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
curvePreferences:
- CurveP521
- CurveP384
ports:
websecure:
http3:
enabled: true
metrics:
# It has to be the same with the traefik-dashboard-service.yaml in monitoring
port: 9100
service:
enabled: true
type: LoadBalancer
spec:
externalTrafficPolicy: Local
loadBalancerIP: "192.168.179.240"
resources:
requests:
cpu: "250m"
memory: "100Mi"
autoscaling:
enabled: true
minReplicas: 1
maxReplicas: 5
Now that our proxy is running we can define some Middlewares to simplify the deployment of services:
kubectl apply -f https_redirect.yaml
kubectl apply -f security_headers.yaml
Traefik will be my main proxy that will forward requests to other services. So we also deploy these requirements:
kubectl apply -f grigoris_proxy.yaml
kubectl apply -f box_proxy.yaml
kubectl apply -f traefik-dashboard.yaml
Cert-manager¶
Since we want high availability, we need also to handle our certificates in a way that can be hanlded from traefik. Traefik offers this support in the enteprise version, but since I am cheap, I will use an another manager (i.e. cert-manager)
kubectl create namespace cert-manager
helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install cert-manager jetstack/cert-manager --namespace cert-manager -f cert-values.yaml --version v1.16.1
kubectl apply -f cert-vpa.yaml
With cert-values.yaml
:
#https://github.com/jetstack/cert-manager/blob/master/deploy/charts/cert-manager/values.yaml
crds:
enabled: true
replicaCount: 1
#https://github.com/jetstack/cert-manager/issues/959
podDnsPolicy: "Default"
prometheus:
enabled: true
servicemonitor:
enabled: true
Note
Initially the prometheus monitoring should not be activate until we deploy the monitoring stack. Afterwards we can activate it.
Now that the cert-manager
is running we can create our certificate issuers:
kubectl apply -f self_signed.yaml
kubectl apply -f letenrcypt_stagging.yaml
kubectl apply -f letenrcypt.yaml
Note
We are using traefik-cert-manager
as name for the traefik ingress.
That we will have to specify it when we deploy the traefik
Let`s encrypt with wildcards¶
Cert manager has out of the box support for the basic HHTP01
challenge. This does not allow to
create certificates with wildcards. For that we have to use the DNS01
challenge. But we need an
extra plugin for that purpose.
# THESE INSTRUCTIONS DO NOT WORK. THEY ARE NOT READY
helm repo add bwolf https://bwolf.github.io/cert-manager-webhook-gandi
helm install webhook-gandi bwolf/cert-manager-webhook-gandi --namespace cert-manager --version v0.2.0 --set features.apiPriorityAndFairness=true --set logLevel=2
kubectl -n general annotate secret gandi kubed.appscode.com/sync="app=gandi-key" --overwrite
kubectl label namespace cert-manager app=gandi-key
Testing that everything works¶
To test that everything works, we can deploy a testing whoami service:
kubectl apply -f whoami.yaml
# Check that everything works and the delete the service
kubectl delete -f whoami.yaml
# Forcing renew. Good practice when updating the cert-manager to make sure that
# everything still works
kubectl cert-manager status certificate login.anagno.me -n authentication
kubectl cert-manager renew login.anagno.me -n authentication
Resources:
- https://medium.com/dev-genius/setup-traefik-v2-for-ha-on-kubernetes-20311204fa6f
- https://traefik.io/blog/install-and-configure-traefik-with-helm/
- https://kubernetes.github.io/ingress-nginx/deploy/baremetal/
- https://www.thebookofjoel.com/k3s-cert-manager-letsencrypt
- https://cert-manager.io/docs/usage/kubectl-plugin/