Install K3S on Arch Linux with, firewalld, LetsEncrypt, and Traefik
These are the steps I use to set up k3s lightweight kubernetes for local development with Arch Linux.
This guide results in a deployment using LetsEncrypt via Traefik, HTTPS support, and a vanilla nginx web server.
Note that, with these instructions, LetsEncrypt will only generate a valid HTTPS certificate if the computer wherek3s
is being installed can be reached via HTTP on
port 80
over the public Internet using the domain
name we specify below.
Routing and Firewall
Enable IP forwarding.
sudo sysctl -w net.ipv4.ip_forward=1
Note that nftables
is not currently a supported
firewall backend for k8s
/k3s
.
- https://wiki.nftables.org/wiki-nftables/index.php/Adoption#virtualization_.2F_cloud_.2F_infrastructure
- https://v1-17.docs.kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#ensure-iptables-tooling-does-not-use-the-nftables-backend
- https://rancher.com/docs/k3s/latest/en/known-issues/
Here is an exaple of how to switch from running
nftables
to a firewall management application,
firewalld
, using the iptables
backend.
sudo pacman -Rs nftables \
&& sudo pacman -Sy firewalld \
&& sudo sed -i 's/FirewallBackend=.*/FirewallBackend=iptables/g' /etc/firewalld/firewalld.conf \
&& sudo systemctl restart firewalld \
&& sudo systemctl enable firewalld
Depending on your needs the necessary ports for HTTP and HTTPS traffic should be opened and port forwarding should have already been established upstream so the Internet can reach this machine.
sudo firewall-cmd --add-port=443/tcp --permanent \
&& sudo firewall-cmd --add-port=80/tcp --permanent \
&& sudo firewall-cmd --reload
Reboot (I find I have to do this) to ensure all firewall and
routing settings have taken effect. Otherwise, I encounter errors
with the k3s
installation.
sudo reboot
Install k3s
yay -Sy --needed k3s-1.22-bin kubectl \
&& sudo systemctl enable k3s \
&& sudo systemctl start k3s \
&& mkdir -p "${HOME}/.kube" \
&& sudo cp /etc/rancher/k3s/k3s.yaml "${HOME}/.kube/config" \
&& sudo chown $(id -u):$(id -g) "${HOME}/.kube/config"
Wait until the system looks healthy like so.
archlinux% kubectl -n kube-system get pods
NAME READY STATUS RESTARTS AGE
coredns-85cb69466-5xqkh 1/1 Running 0 64s
metrics-server-9cf544f65-4hb9j 1/1 Running 0 64s
local-path-provisioner-64ffb68fd-z4v7z 1/1 Running 0 64s
helm-install-traefik-crd--1-nq2vn 0/1 Completed 0 64s
helm-install-traefik--1-hpf5w 0/1 Completed 1 64s
svclb-traefik-hbz7l 2/2 Running 0 27s
traefik-74dd4975f9-prjqb 1/1 Running 0 28s
Configure Traefik and LetsEncrypt Support
Update the Traefik LetsEncrypt resolver configuration. Swap out
the email
below with your valid email address.
cat << 'EOF'| sudo tee /var/lib/rancher/k3s/server/manifests/traefik-config.yaml
kind: HelmChartConfig
apiVersion: helm.cattle.io/v1
metadata:
name: traefik
namespace: kube-system
spec:
valuesContent: |-
additionalArguments:
- --certificatesresolvers.traefikresolver.acme.email=me@myfakedomain.com
- --certificatesresolvers.traefikresolver.acme.storage=/data/acme.json
- --certificatesresolvers.traefikresolver.acme.httpchallenge.entrypoint=web
persistence:
enabled: true
path: /data
EOF
Create and Apply Nginx Config
Create a file at nginx.yaml
with these contents.
Replace wwww.myfakedomain.com
below with your domain.
kind: Namespace
apiVersion: v1
metadata:
name: nginx-namespace
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: nginx-deployment
namespace: nginx-namespace
labels:
app: traefiklabs
name: nginx
spec:
replicas: 2 # tells deployment to run 2 pods matching the template
selector:
matchLabels:
app: traefiklabs
task: nginx-task
template:
metadata:
labels:
app: traefiklabs
task: nginx-task
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
---
kind: Service
apiVersion: v1
metadata:
name: nginx-service
namespace: nginx-namespace
spec:
ports:
- name: http
port: 80
selector:
app: traefiklabs
task: nginx-task
---
kind: Middleware
apiVersion: traefik.containo.us/v1alpha1
metadata:
name: nginx-middleware
namespace: nginx-namespace
spec:
redirectScheme:
scheme: https
permanent: true
---
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
name: nginx-ingress
namespace: nginx-namespace
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: web, websecure
traefik.ingress.kubernetes.io/router.middlewares: nginx-namespace-nginx-middleware@kubernetescrd
traefik.ingress.kubernetes.io/router.tls.certresolver: traefikresolver
spec:
rules:
# Set an /etc/hosts entry to test this
- host: www.myfakedomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-service
port:
number: 80
Apply the configuration.
kubectl apply -f ./nginx.yaml
Wait until the nginx deployment looks healthy like so.
archlinux% kubectl -n nginx-namespace get pods
NAME READY STATUS RESTARTS AGE
nginx-deployment-75bd49fbcd-6f7bj 1/1 Running 0 18s
nginx-deployment-75bd49fbcd-lznb6 1/1 Running 0 18s
Test
Create an entry at /etc/hosts
to allow testing the
host
routing for the nginx deployment.
...
127.0.0.1 www.myfakedomain.com
Use -k
with bash to ignore SSL errors if LetsEncrypt
needs time or the server is not actually exposed to the Internet.
curl -k https://www.myfakedomain.com
Bonus: authenticated images from Google Artifact Registry
Assuming an image in us-central1
then a config file
at /etc/rancher/k3s/registries.yaml
could be used to
authenticate with a service key.
configs:
us-central1-docker.pkg.dev:
auth:
username: _json_key
password: '{"type":"service_account","project_id":"MY PROJECT", ... "}'
Bonus: Traefik Dashboard
The Traefik dashboard can be temporarily exposed for debugging
like so. Use ssh
or another tunneling/port-forwarding
tool as needed to access the dashboard on your network.
ssh -L 127.0.0.1:9000:192.168.0.123:9000 admin@192.168.0.123
kubectl --namespace kube-system port-forward --address 0.0.0.0 deployment/traefik 9000:9000
Then visit http://127.0.0.1:9000/dashboard/#/http/routers
Notes
- https://stackoverflow.com/a/72552873/1459103
- https://bryanbende.com/development/2021/05/08/k3s-raspberry-pi-ingress
- https://dnaeon.github.io/install-and-configure-k8s-on-arch-linux/
- https://www.tomas.io/articles/k3s-setup
- https://doc.traefik.io/traefik/middlewares/http/stripprefix/
- https://stackoverflow.com/questions/64563957/how-do-i-get-traefik-ingress-kubernetes-io-rule-type-pathprefixstrip-to-work
- https://github.com/k3s-io/k3s/issues/1019