Opnsense
BGP
Instead of using Metallb for L2/L3 load balancer IPs I am using the Kubernetes Calico CNI with BGP which allows me to advertise load balancer IPs directly over BGP. This has some benefits like having equal cost multipath (ECMP) for scaled workloads in my cluster.
- Routing > BPG | General
enable
=true
BGP AS Number
=64512
Network
=192.168.42.0/24
(Subnet your Kubernetes nodes are on)- Save
- Routing > BGP | Neighbors
- Add a neighbor for each Kubernetes node
Enabled
=true
Peer-IP
=192.168.42.x
(Kubernetes Node IP)Remote AS
=64512
Update-Source Interface
=HOME_SERVER
(VLAN of Kubernetes nodes)- Save
- Continue adding neighbors until all your nodes are present
- Add a neighbor for each Kubernetes node
- Routing > General
Enable
=true
- Save
- System > Settings > Tunables
- Add
net.route.multipath
and set the value to1
- Save
- Add
- Reboot
- Verify
- Routing > Diagnostics | Summary
Without updating the configuration described in step 4 the routes from a client will only take a single path to your Kubernetes workloads even if they are scaled to more than one.
HAProxy
While kube-vip is very nice for having a API server ready to go and running in your cluster I had issues with mixing layer 2 and layer 3 between Calico in BGP and kube-vip using L2 ARP. You also cannot run Calico in BGP with kube-vip in BGP, they will fight and you will lose. Instead I choose to use Haproxy which you can install from the Opnsense Plugins.
- Services > HAProxy | Real Servers
- Add a server for each master node in your Kubernetes cluster
Enabled
=true
Name or Prefix
=k8s-apiserver-x
FQDN or IP
=192.168.42.x
Port
=6443
Verify SSL Certificate
=false
- Apply/Save
- Continue adding servers until all your master nodes are present
- Add a server for each master node in your Kubernetes cluster
- Services > HAProxy | Rules & Checks > Health Monitors
Name
=k8s-apiserver-health
SSL preferences
=Force SSL for health checks
Port to check
=6443
HTTP method
=GET
Request URI
=/healthz
HTTP version
=HTTP/1.1
- Apply/Save
- Services > HAProxy | Virtual Services > Backend Pools
Enabled
=true
Name
=k8s-apiserver-be
Mode
=TCP (Layer 4)
Servers
=k8s-apiserver-x
... (Add one for each server you created. Use TAB key to complete typing each server)Source address
=192.168.1.1
(Your Opnsense IP address)Enable Health Checking
=true
Health Monitor
=k8s-apiserver-health
- Apply/Save
- Services > HAProxy | Virtual Services > Public Services
Enabled
=true
Name
=k8s-apiserver-fe
Listen Addresses
=192.168.1.1:6443
(Your Opnsense IP address. Use TAB key to complete typing a listen address)Type
=TCP
Default Backend Pool
=k8s-apiserver-be
- Apply/Save
- Services > HAProxy | Settings > Service
Enable HAProxy
=true
- Apply/Save
- Services > HAProxy | Settings > Global Parameters
Verify SSL Server Certificates
=disable-verify
- Apply/Save
- Services > HAProxy | Settings > Default Parameters
Client Timeout
=4h
Connection Timeout
=10s
Server Timeout
=4h
- Apply/Save
Receive Side Scaling (RSS)
RSS is used to distribute packets over CPU cores using a hashing function – either with support in the hardware which offloads the hashing for you, or in software. Click here to learn more about it.
- System > Settings > Tunables
- Add
net.inet.rss.enabled
and set the value to1
- Add
net.inet.rss.bits
and set to2
- Add
net.isr.dispatch
and set tohybrid
- Add
net.isr.bindthreads
and set to1
- Add
net.isr.maxthreads
and set to-1
- Save
- Add
- Reboot
- Verify with
sudo netstat -Q
Configuration: Setting Current Limit Thread count 8 8 Default queue limit 256 10240 Dispatch policy hybrid n/a Threads bound to CPUs enabled n/a
Syslog
Firewall logs are being sent to Vector which is running in my Kubernetes cluster. Vector is then shipping the logs to Loki which is also running in my cluster.
- System > Settings > Logging / targets
- Add new logging target
Enabled
=true
Transport
=UDP(4)
Applications
=filter (filterlog)
Hostname
=192.168.69.111
(Loki's Load Balancer IP)Port
=5140
rfc5424
=true
- Save
- Add new logging target
SMTP Relay
To ease the use of application configuration I have a SMTP Relay running on Opnsense using the Postfix plugin. From applications deployed in my Kubernetes cluster, to my nas, to my printer, all use the same configuration for SMTP without authentication.
- System > Services > Postfix > General
SMTP Client Security
=encrypt
Smart Host
=[smtp.fastmail.com]:465
Enable SMTP Authentication
=true
Authentication Username
=devin@<email-domain>
Authentication Password
=<app-password>
Permit SASL Authenticated
=false
- Save
- System > Services > Postfix > Domains
- Add new domain
Domainname
=<email-domain>
Destination
=[smtp.fastmail.com]:465
- Save
- Apply
- Add new domain
- System > Services > Postfix > Senders
- Add new sender
Enabled
=true
Sender Address
=admin@<email-domain>
- Save
- Apply
- Add new sender
- Verify
swaks --server opnsense.turbo.ac --port 25 --to <email-address> --from <email-address>