K8s配置DHCP IPAM+Macvlan+Multus创建Pod附加接口方案与排障
Macvlan+Multus+DHCP IPAM 故障排查与可用配置参考
故障核心原因
当前出现DHCP服务器已发Offer但daemon收不到报文的问题,核心诱因有三点:
- DHCP daemon未运行在宿主机网络命名空间,且缺少raw socket监听、网络命名空间操作的相关权限
- Macvlan配置未指定桥接模式、未开启混杂模式,宿主机侧无法接收到目标MAC为Pod接口的DHCP回包
- DHCP daemon临时手动启动,未挂载CNI工作目录、网络命名空间目录,无法正常关联Pod侧接口
1. 正确的NetworkAttachmentDefinition配置
apiVersion: k8s.cni.cncf.io/v1 kind: NetworkAttachmentDefinition metadata: name: test1 # SR-IOV场景保留以下注解,普通Macvlan场景可直接删除 annotations: k8s.v1.cni.cncf.io/resourceName: intel.com/test_net_attach1 spec: config: | { "name": "test_net_attach1", "type": "macvlan", "master": "ens2f0", "mode": "bridge", "promiscMode": true, "ipam": { "type": "dhcp", "broadcast": true } }
配置说明:
- mode: bridge:Macvlan采用桥接模式,保证同一主接口下的Pod、宿主机二层互通
- promiscMode: true:开启主接口混杂模式,避免网卡直接丢弃目标MAC不属于宿主机的报文
- ipam.broadcast: true:强制DHCP请求以广播形式发送,兼容不支持单播回应的通用DHCP服务器
2. 测试Pod示例YAML
apiVersion: v1 kind: Pod metadata: name: dhcp-test1 annotations: # 同命名空间下NAD可直接写名称,跨命名空间格式为<namespace>/<nad-name> k8s.v1.cni.cncf.io/networks: test1 spec: nodeSelector: deploy: vm1 containers: - name: c1 image: centos:latest command: ["/bin/sh", "-c"] args: ["sleep infinity"]
验证方式:
- Pod创建10s后执行
kubectl exec -it dhcp-test1 -- ip a,查看net1接口是否获取到DHCP地址段IP - 执行
kubectl describe pod dhcp-test1,查看Annotations中k8s.v1.cni.cncf.io/network-status字段,确认Multus已正确上报附加接口的IP、MAC信息
3. DHCP Daemon正确运行方式
注意:手动在节点上直接执行dhcp二进制启动daemon的方式不可用,必须以DaemonSet形式在所有需要使用DHCP IPAM的节点上常驻运行
前置准备
将v1.1.1版本cni插件包中的dhcp二进制文件,上传到所有目标节点的/opt/cni/bin/目录,赋予755执行权限。
DaemonSet部署配置
apiVersion: apps/v1 kind: DaemonSet metadata: name: cni-dhcp-daemon namespace: kube-system labels: app: cni-dhcp spec: selector: matchLabels: app: cni-dhcp template: metadata: labels: app: cni-dhcp spec: hostNetwork: true nodeSelector: # 按需修改节点选择器,仅在需要DHCP IPAM的节点部署 deploy: vm1 tolerations: - operator: Exists containers: - name: cni-dhcp # 镜像内自带v1.1.1版本dhcp二进制,也可替换为自行构建的镜像 image: docker.io/rancher/hardened-cni-plugins:v1.1.1 command: ["/opt/cni/bin/dhcp"] args: ["daemon", "--broadcast=true"] securityContext: privileged: true volumeMounts: - name: cni-bin mountPath: /opt/cni/bin - name: cni-state mountPath: /var/lib/cni - name: netns mountPath: /var/run/netns volumes: - name: cni-bin hostPath: path: /opt/cni/bin - name: cni-state hostPath: path: /var/lib/cni - name: netns hostPath: path: /var/run/netns
运行要求说明:
- 必须配置
hostNetwork: true,让daemon运行在宿主机网络命名空间,才能直接监听物理网卡上的DHCP报文 - 必须开启特权模式,否则daemon无权限创建raw socket监听报文、无权限修改网络接口状态
- 必须挂载
/opt/cni/bin、/var/lib/cni、/var/run/netns三个宿主机目录,否则daemon无法读取CNI配置、无法找到Pod对应的网络命名空间 - 启动参数必须携带
--broadcast=true,和NAD中的DHCP广播配置保持一致 - 部署后执行
kubectl logs -n kube-system ds/cni-dhcp-daemon -f查看日志,正常获取租约时会打印acquired lease日志,不会再出现"no DHCP packet received"报错
最终验证
- 部署DHCP DaemonSet并确认运行正常后,删除之前创建的异常测试Pod重新创建
- 进入Pod验证附加接口IP,确认可正常ping通DHCP服务器、同网段其他地址
- DHCP服务器侧可看到完整的DHCP四步交互与地址租约记录
- 节点侧抓包主接口,可看到完整的DHCPDISCOVER、DHCPOFFER、DHCPREQUEST、DHCPACK报文交互
内容的提问来源于stack exchange,提问作者ddran
相关产品推荐
相关产品推荐

