This blog post explains how to launch K3s as a single node using Ingress Nginx as the ingress controller to obtain the source IP address in the request headers (x-real-ip, x-forwarded-for). It is a suitable method for setting up a K8s environment on a Raspberry Pi or a similar single-board computer.
The challenges addressed here include: - Using Nginx instead of Traefik. - Retrieving the source IP address as headers.
K3s installs Traefik as the default ingress controller, which might not behave as expected if you are used to Nginx due to different configuration settings. By installing Ingress Nginx and configuring it to receive connections from the K3s load balancer (by default, Service LB), it becomes possible to handle the source IP address as request headers with Nginx. Consequently, apps cannot log the source IP address or use it for access control.
Related issue: Getting Real Client IP with k3s · k3s-io/k3s · Discussion #2997
This practice involves launching Ingress Nginx as a DaemonSet instead of Deployment + Service, binding ports to HostPort 80 and 443, so packets to the host machine are directly forwarded to Ingress Nginx. This approach is similar to the default Ingress Nginx of MicroK8s, resulting in similar usage. Note that this setup cannot make Ingress Nginx itself redundant and has permission-related issues. It is also unsuitable for multi-node operations. Ultimately, a single-node cluster reminiscent of a more compact version of MicroK8s is achieved.
$ cat /proc/cgroups
If the enabled
for memory
is not 1
, adjustments are needed. When starting a Raspberry Pi with Raspbian, it should default to 0
. In that case, add cgroup_memory=1 cgroup_enable=memory
to the end of /boot/firmware/cmdline.txt
and reboot the machine.
Reference: Quick Start Guide | K3s
$ curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--disable=traefik --disable=servicelb" sh -s - --write-kubeconfig-mode 644
Disabling traefik
and servicelb
, install K3s.
$ k3s kubectl get all --all-namespaces
Within about a minute, three pods will start up.
Visit https://github.com/kubernetes/ingress-nginx/releases to check the latest version.
Use the manifest of the version number checked earlier:
$ k3s kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.12.0/deploy/static/provider/baremetal/deploy.yaml
$ k3s kubectl get all --all-namespaces
The Service and Deployment for ingress-nginx will be created. Verify with:
$ curl https://127.0.0.1:32508 --insecure
It should return a 404 response, confirming the setup.
$ k3s kubectl delete service -n ingress-nginx ingress-nginx-controller
$ k3s kubectl delete deployment -n ingress-nginx ingress-nginx-controller
Modify the manifest to create a DaemonSet and save it.
kind
to DaemonSet.spec.strategy
.spec.template.spec.hostNetwork: true
.hostPort
to spec.template.spec.containers.ports
.$ sudo k3s kubectl apply -f ingress-nginx-daemonset.yaml
$ k3s kubectl get all --all-namespaces
Verify:
$ curl 'https://127.0.0.1' --insecure
It should now listen on :443.
This concludes the main topic. Testing with a simple echo server and sending an HTTP request will confirm that x-real-ip
and x-forwarded-for
contain the remote client IP address as expected.
$ cat /etc/rancher/k3s/k3s.yaml
If using remotely, change server: https://127.0.0.1:6443
to the external IP address.
$ /usr/local/bin/k3s-uninstall.sh
Be cautious as it removes everything without confirmation.
Comments