K3s + Multus CNI 插件使用 Macvlan
目录
K3s 是一个轻量的 Kubernetes 集群,Multus 是一个用于给 Pod 创建多个网络接口的 CNI (Container Network Interface) 插件,其创建的接口支持 macvlan。
啥是 Macvlan
字面意思,根据 MAC 地址划分的虚拟子网 (Vlan) 就是 macvlan,网上能搜到很多有关 Macvlan 的介绍,这里不再过多描述。
与之相对应的还有一个叫 ipvlan,是通过 IP 地址划分的虚拟子网。
Macvlan 和 ipvlan 都是 Linux 系统的特性,其他系统不支持这个功能。
Prerequisites
可以用 modinfo macvlan 检查系统是否有安装 macvlan 模块,根据 Docker 文档 中描述的建议是使用 Linux 3.9 或 4.0 及更新的内核版本。
可以用以下指令检查系统是否支持 Macvlan(这里使用桥接模式):
sudo ip link add macvlan0 link enp1s0 type macvlan mode bridge # 这里替换 enp1s0 为网卡接口名称
sudo ip address add 192.168.122.205/24 broadcast 192.168.122.255 dev macvlan0 # 注意 IP 地址冲突
之后可尝试使用其他处于同一个网络(CIDR)的设备 ping 这个 192.168.122.205 IP 地址,能 Ping 通就说明你的防火墙没有屏蔽不同设备之间的二层数据转发。
安装 K3s
根据 Multus 的 QuickStart 手册,准备一个新版本的 Kubernetes 集群(这里用的是 v1.27.8+k3s2),K3s 默认的 CNI 插件使用的是 Flannel。
在国内的话需要先创建 /etc/rancher/k3s/registries.yaml 配置 Registry Mirror:
mirrors:
docker.io:
endpoint:
- "https://docker.nju.edu.cn"
ghcr.io:
endpoint:
- "https://ghcr.nju.edu.cn"
之后使用国内源一键安装 K3s:
#!/bin/bash
curl -sfL https://rancher-mirror.oss-cn-beijing.aliyuncs.com/k3s/k3s-install.sh | \
INSTALL_K3S_VERSION=v1.27.8+k3s2 \
INSTALL_K3S_MIRROR=cn \
sh -s - server \
--cluster-init \
--system-default-registry "docker.nju.edu.cn"
安装 Multus CNI
接下来安装 Multus CNI 插件,下载 multus-daemonset.yml 配置,需要编辑 kube-multus-ds DaemonSet hostPath 的路径到 K3s 对应的路径上去。
wget 'https://raw.githubusercontent.com/k8snetworkplumbingwg/multus-cni/master/deployments/multus-daemonset.yml'
编辑 kube-multus-ds DaemonSet 的 hostPath 的配置为 K3s 的路径。
...
volumes:
- name: cni
hostPath:
path: /var/lib/rancher/k3s/agent/etc/cni/net.d
- name: cnibin
hostPath:
path: /var/lib/rancher/k3s/data/current/bin
...
还要编辑 kube-multus-ds DaemonSet 的 Container 配置,增添一条 command arg:
...
containers:
- name: kube-multus
image: ghcr.io/k8snetworkplumbingwg/multus-cni:snapshot
command: ["/thin_entrypoint"]
args:
- "--multus-conf-file=auto"
- "--multus-autoconfig-dir=/host/etc/cni/net.d"
- "--cni-conf-dir=/host/etc/cni/net.d"
# ADD THIS LINE:
- "--multus-kubeconfig-file-host=/var/lib/rancher/k3s/agent/etc/cni/net.d/multus.d/multus.kubeconfig"
...
之后 kubectl apply 上面的 Multus Daemonset 配置,等待 kube-multus-ds DaemonSet 跑起来后,可以看到 /var/lib/rancher/k3s/data/current/bin 目录下有新增 multus 可执行文件。
$ sudo ls /var/lib/rancher/k3s/data/current/bin | grep multus
multus
自定义 Multus CNI 配置文件
新建一个名为 macvlan-conf 的 NetworkAttachmentDefinition Custom Resource,自定义 multus 配置文件:
这里需要注意 config 中的 master 网卡接口要设置为物理机上对应的网卡接口名。
咱把 K3s Server 安装在了 QEMU 虚拟机中,虚拟机使用的是 libvirt 创建的默认网卡,CIDR 编址为 192.168.122.0/24,网关 192.168.122.1。
为了能在其他虚拟机 / 物理机上也能访问到虚拟机中使用了 macvlan 的 pod,multus macvlan 配置文件也使用 libvirt 网卡的 CIDR。
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
name: macvlan-conf
spec:
config: '{
"cniVersion": "0.3.1",
"type": "macvlan",
"master": "enp1s0",
"mode": "bridge",
"ipam": {
"type": "host-local",
"subnet": "192.168.122.0/24",
"rangeStart": "192.168.122.200",
"rangeEnd": "192.168.122.210",
"routes": [
{ "dst": "0.0.0.0/0" }
],
"gateway": "192.168.122.1"
}
}'
$ kubectl apply -f macvlan-conf.yaml
$ kubectl get net-attach-def
NAME AGE
macvlan-conf 59s
创建 Macvlan Pod
K3s 将安装包体积做了精简移除了 macvlan CNI 插件,所以创建 Pod 之前需要手动下载 macvlan CNI 插件放到 K3s 的 data bin 目录。
$ mkdir -p cni-plugin && cd cni-plugin
$ wget https://github.com/containernetworking/plugins/releases/download/v1.4.0/cni-plugins-linux-amd64-v1.4.0.tgz
$ tar -zxvf cni-plugins-linux-amd64-v1.4.0.tgz
$ sudo cp ./macvlan /var/lib/rancher/k3s/data/current/bin/
之后创建 Pod,使用 Annotation 指定网络的配置文件,并让 Pod 被 Multus CNI 识别。
apiVersion: v1
kind: Pod
metadata:
name: nginx-macvlan
annotations:
k8s.v1.cni.cncf.io/networks: macvlan-conf
spec:
containers:
- name: nginx
image: nginx
如果一切顺利的话,kubectl describe pod nginx-macvlan 能看到以下的 Events:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 2s default-scheduler Successfully assigned default/nginx-macvlan to archlinux-k3s-1
Normal AddedInterface 2s multus Add eth0 [10.42.0.26/24] from cbr0
Normal AddedInterface 2s multus Add net1 [192.168.122.200/24] from default/macvlan-conf
因为 K3s 服务器跑在了 QEMU KVM 虚拟机里面,libvirt 默认网卡 CIDR 是 192.168.122.0/24。所以咱在物理机上访问虚拟机内的 Macvlan Pod IP 192.168.122.200,是能正常访问的。
$ curl 192.168.122.200
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
然后因为 Macvlan 的子接口 (sub interface) 无法与父接口 (parent interface) 直接访问,所以在节点的主机上访问运行在这个节点内的 macvlan pod 是访问不通的,也就是说无法通过节点主机的接口访问到 macvlan pod 的子接口,除非使用 ipvlan,可以参考以下这几篇讨论:




评论