As part of trying out Kubernetes: planning, we are going to set up the network and VMs!
Quick reminder that this will be virtualised Linux on a FreeBSD physical host. This part is FreeBSD-specific.
Given that bhyve(8)
‘s networking uses tap(4)
devices, which we can bridge
and route as needed, we will only need basic FreeBSD networking knowledge.
This actually is somewhat similar to the setup I use for IPv6-VNET jails.
That is, we will need a bridge and a tap device for each network segment:
# Adding following to /etc/rc.conf
# k8s testing
# Create tap and bridge interfaces
cloned_interface="${cloned_interfaces} tap0 bridge0 tap1 bridge1"
# Rename them
ifconfig_bridge0_name="etcdbridge"
ifconfig_tap0_name="etcdtap"
ifconfig_bridge1_name="k8sbridge"
ifconfig_tap1_name="k8stap"
# Save our network prefix data
_k8s_v6="2XXX:XXXX:XXXX"
_k8s_v4="10.2"
# Define etcd network
ifconfig_etcdtap="fib 1"
ifconfig_etcdbridge_descr="etcd cluster and k8s control-panel"
ifconfig_etcdbridge="inet ${_k8s_v4}.1.1/24 addm etcdtap up fib 1"
ifconfig_etcdbridge_ipv6="inet6 ${_k8s_v6}:1::/64 auto_linklocal"
# Define k8s network
ifconfig_k8stap="fib 1"
ifconfig_k8sbridge_descr="k8s nodes and control-panel"
ifconfig_k8sbridge="inet ${_k8s_v4}.2.1/24 addm k8stap up fib 1"
ifconfig_k8sbridge_ipv6="inet6 ${_k8s_v6}:2::/64 auto_linklocal"
Remarkable is that we are assigning /64
subnets for IPv6 and /24
for IPv4,
and that we will use static IP assignment since this is just a handful of
machines.
I am also using a different routing table (fib 1
) in order not to mix
traffic.
Note that besides valid IPv6 routing, there are NAT rules taking care of IPv4:
# k8s NAT
nat on $ext_if inet from {10.2.1.0/24, 10.2.2.0/24} to any -> ($ext_if:0)
We will perform static IP assignment due to the small scale:
VM | IPv4 | IPv6 |
---|---|---|
k8s-etcd-1 | 10.2.1.21 |
${_k8s_v6}:1::21 |
k8s-etcd-2 | 10.2.1.22 |
${_k8s_v6}:1::22 |
k8s-etcd-3 | 10.2.1.23 |
${_k8s_v6}:1::23 |
k8s-cp-1 | 10.2.1.11 |
${_k8s_v6}:1::11 |
10.2.2.11 |
${_k8s_v6}:2::11 |
|
k8s-node-N | 10.2.2.20+N |
${_k8s_v6}:2::20+N |
Now I should be able to create the Virtual Machines on each network bridge.
As mentioned before, the virtualisation will be done with bhyve(8)
,
particularly with vm-bhyve(8)
, as it is very lightweight and takes care of
lower level details for us.
vm-bhyve
switchesWe add following to VM_BHYVE/.config/system.conf
:
switch_list="etcdbridge k8sbridge"
type_etcdbridge="manual"
bridge_etcdbridge="etcdbridge"
type_k8sbridge="manual"
bridge_k8sbridge="k8sbridge"
Which makes sure that vm-bhyve
will add the network interfaces to the
appropriate bridges.
Then we create the vm-bhyve(8)
template:
# This lives in VM_BHYVE/.templates/k8s.conf
cat k8s.conf
loader="grub"
cpu=1
memory=1G
network0_type="virtio-net"
network0_switch="k8sbridge"
# We use sparse zvols for storage, which enables us to snapshot and clone the
# whole disk while only allocating space as we start using it.
disk0_name="disk0"
disk0_dev="sparse-zvol"
disk0_type="virtio-blk"
Since we will later clone this VM, we’ll add network adapters / change bridges.
We’ll use Debian’s latest release: bookworm
:
curl -L \
https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-12.2.0-amd64-netinst.iso > \
VM_BHYVE/.iso/debian-12.2.0-amd64-netinst.iso
vm create -t k8s -s 240G k8sbase
Now we install the OS using the serial console and the downloaded .iso
:
vm install -f k8sbase debian-12.2.0-amd64-netinst.iso
I use an unassigned IP for the base VM, so I can apply provisioning for the final touches.
Still over serial, we finish up basic things like enabling SSH but only with public keys, and installing my keys.
# In /etc/ssh/sshd_config
PermitRootLogin prohibit-password
PasswordAuthentication no
UsePAM no
KbdInteractiveAuthentication no
$ service sshd restart
$ mkdir .ssh
$ chmod 750 .ssh
$ wget https://evilham.com/ssh.pubkey -O .ssh/authorized_keys
$ chmod 640 .ssh/authorized_keys
# We create a snapshot first
$ vm snapshot -r k8sbase@clean
# And then actually clone it, we start with one VM of each type
$ vm clone k8sbase@clean k8s-etcd-1
$ vm clone k8sbase@clean k8s-cp-1
$ vm clone k8sbase@clean k8s-node-1
Now, we can edit each VM’s VM_BHYVE/VM/VM.conf
file in order to assign it to
the corresponding network(s):
# In VM_BHYVE/k8s-etcd-1/k8s-etcd-1.conf:
network0_type="virtio-net"
network0_switch="etcdbridge"
# In VM_BHYVE/k8s-cp-1/k8s-cp-1.conf:
network0_type="virtio-net"
network0_switch="etcdbridge"
network1_type="virtio-net"
network1_switch="k8sbridge"
# In VM_BHYVE/k8s-node-1/k8s-node-1.conf:
network0_type="virtio-net"
network0_switch="k8snode1"
And using provisioning against the unassigned IP one VM at a time, we:
hostid
so they are not shared (this is important
for etcd
)FreeBSD’s networking and virtualisation stack are great and it often surprises me how effortless it is to get things done.
Networking is set up, one of each VM type is set up with outgoing dual stack internet and two separated network segments.
Next up, setting up etcd
.
These were the steps according to the plan
etcd
cluster