ovn-networking的"Address set does not exist"错误排查记录

本文记录自己在OVN部署和测试中遇到的问题,以及排查过程

前世今生:

近期在调研OVN,因此就试着搭建了一套openstack/pike版本的OVN。使用OVN作为网络底层实现而替换neutron的各类plugin(L3,DHCP,L2,iptables)

问题出现:

当创建port时,执行neutron port-create [net-id] --name [port-name]命令时,执行失败,log报错如下:

File "/usr/lib/python2.7/site-packages/ovsdbapp/backend/ovs_idl/connection.py", line 97, in run
    txn.results.put(txn.do_commit())
  File "/usr/lib/python2.7/site-packages/ovsdbapp/backend/ovs_idl/transaction.py", line 86, in do_commit
    command.run_idl(txn)
  File "/usr/lib/python2.7/site-packages/networking_ovn/ovsdb/commands.py", line 725, in run_idl
    raise RuntimeError(msg)
RuntimeError: Address set as_ip4_b5dbdfe6_bcd3_4e39_b43a_0c37c66ccb54 does not exist. Can't update addresses

错误排查

1、根据报错,我们去看一下commands.py文件中run_idl函数,

在这里插入图片描述
根据函数之间的相互调用,我们发现起始调用该代码的地方在ovn-client.py中的create_port函数。

def create_port(self, port):
        if utils.is_lsp_ignored(port):
        return

        port_info = self._get_port_options(port)
        external_ids = {ovn_const.OVN_PORT_NAME_EXT_ID_KEY: port['name'],
                        ovn_const.OVN_DEVID_EXT_ID_KEY: port['device_id'],
                        ovn_const.OVN_PROJID_EXT_ID_KEY: port['project_id'],
                        ovn_const.OVN_CIDRS_EXT_ID_KEY: port_info.cidrs}
        lswitch_name = utils.ovn_name(port['network_id'])
        admin_context = n_context.get_admin_context()
        sg_cache = {}
        subnet_cache = {}

        # It's possible to have a network created on one controller and then a
        # port created on a different controller quickly enough that the second
        # controller does not yet see that network in its local cache of the
        # OVN northbound database.  Check if the logical switch is present
        # or not in the idl's local copy of the database before creating
        # the lswitch port.
        self._nb_idl.check_for_row_by_value_and_retry(
            'Logical_Switch', 'name', lswitch_name)

        with self._nb_idl.transaction(check_error=True) as txn:
            if not port_info.dhcpv4_options:
                dhcpv4_options = []
            elif 'cmd' in port_info.dhcpv4_options:
                dhcpv4_options = txn.add(port_info.dhcpv4_options['cmd'])
            else:
                dhcpv4_options = [port_info.dhcpv4_options['uuid']]
            if not port_info.dhcpv6_options:
                dhcpv6_options = []
            elif 'cmd' in port_info.dhcpv6_options:
                dhcpv6_options = txn.add(port_info.dhcpv6_options['cmd'])
            else:
                dhcpv6_options = [port_info.dhcpv6_options['uuid']]
            # The lport_name *must* be neutron port['id'].  It must match the
            # iface-id set in the Interfaces table of the Open_vSwitch
            # database which nova sets to be the port ID.
            txn.add(self._nb_idl.create_lswitch_port(
                    lport_name=port['id'],
                    lswitch_name=lswitch_name,
                    addresses=port_info.addresses,
                    external_ids=external_ids,
                    parent_name=port_info.parent_name,
                    tag=port_info.tag,
                    enabled=port.get('admin_state_up'),
                    options=port_info.options,
                    type=port_info.type,
                    port_security=port_info.port_security,
                    dhcpv4_options=dhcpv4_options,
                    dhcpv6_options=dhcpv6_options))

            acls_new = ovn_acl.add_acls(self._plugin, admin_context,
                                        port, sg_cache, subnet_cache)
            for acl in acls_new:
                txn.add(self._nb_idl.add_acl(**acl))

            sg_ids = utils.get_lsp_security_groups(port)
            if port.get('fixed_ips') and sg_ids:
                addresses = ovn_acl.acl_port_ips(port)
                # NOTE(rtheis): Fail port creation if the address set doesn't
                # exist. This prevents ports from being created on any security
                # groups out-of-sync between neutron and OVN.
                for sg_id in sg_ids:
                    for ip_version in addresses:
                        if addresses[ip_version]:
                            txn.add(self._nb_idl.update_address_set(
                                name=utils.ovn_addrset_name(sg_id,
                                                            ip_version),
                                addrs_add=addresses[ip_version],
                                addrs_remove=None,
                              
<think>我们正在解决一个特定的问题:Kubernetes Multus插件在添加容器到网络时出现'Link not found'错误,具体网络是ovn-vpc-external-network。这个错误通常与网络接口的创建或查找有关。 根据引用[1],我们知道Kube-OVN会通过注解为容器分配网卡并接入OVN网络。而Multus(引用[2][3][4])作为多网络插件,负责调用不同的CNI插件(如Kube-OVN)来为Pod添加多个网络接口。 错误信息“Link not found”通常意味着在主机上找不到预期的网络接口(Link)。这可能是由于: 1. 网络接口还没有被创建(例如,由另一个CNI插件创建)或者创建失败。 2. Multus在错误的网络命名空间中查找接口。 3. 网络接口名称与预期不符。 步骤分析: 1. 首先,我们需要确认这个错误是在哪个环节发生的。根据错误信息,它发生在将容器添加到网络`ovn-vpc-external-network`时。这个网络可能是由Kube-OVN提供的,并且通过Multus的NetworkAttachmentDefinition(NAD)定义。 2. 检查NetworkAttachmentDefinition(NAD)的配置,确保它指向正确的网络。例如,我们之前配置的`node-access-net`(在引用[2]中)就是一个Multus的NAD,它调用了Kube-OVN插件,并指定了子网`node-access`。 3. 在Pod的注解中,我们通过`k8s.v1.cni.cncf.io/networks`指定了要附加的网络(如引用[5]所示)。因此,我们需要检查Pod的注解是否指定了正确的NAD。 4. 另外,检查Kube-OVN子网的配置,特别是`underlayGateway`和`provider`设置。在引用[1]中,我们看到Pod的注解中有`ovn.kubernetes.io/logical_switch`,这对应一个子网。而我们在问题中使用的网络是`ovn-vpc-external-network`,所以我们需要确认这个网络对应的子网是否存在,并且配置正确。 5. 错误“Link not found”可能是由于Kube-OVN插件在创建网络接口时,接口还没有出现在Pod的网络命名空间中,或者Multus在调用Kube-OVN插件后,无法找到预期的接口名。 解决方案步骤: 步骤1:检查NetworkAttachmentDefinition(NAD)配置 确认名为`ovn-vpc-external-network`的NAD是否存在,并且其配置正确。例如: ```yaml apiVersion: k8s.cni.cncf.io/v1 kind: NetworkAttachmentDefinition metadata: name: ovn-vpc-external-network namespace: kube-system # 注意NAD的命名空间,通常与Pod所在命名空间无关,但Multus会从该命名空间查找NAD spec: config: |- { "cniVersion": "0.3.1", "type": "kube-ovn", "server_socket": "/run/openvswitch/kube-ovn-daemon.sock", "provider": "ovn-vpc-external-network" # 这里应该对应Kube-OVN中的子网名称 } ``` 步骤2:检查Kube-OVN子网配置 确保在Kube-OVN中存在一个名为`ovn-vpc-external-network`的子网(Subnet),并且该子网配置正确。特别注意: - 子网的`vpc`字段是否设置正确? - 如果使用underlay网络,`underlayGateway`是否设置为`true`? - 子网的CIDR和网关配置是否正确? 步骤3:检查Pod的注解 在Pod的注解中,应该指定使用这个NAD,例如: ```yaml annotations: k8s.v1.cni.cncf.io/networks: kube-system/ovn-vpc-external-network ``` 步骤4:检查主机上的网络接口 当Pod被调度到某个节点上时,登录该节点,检查: - 在主机上,OVS是否创建了对应的接口?可以使用`ovs-vsctl show`查看。 - 进入Pod的网络命名空间,检查接口是否存在。可以使用以下命令: ```bash # 获取Pod的容器ID crictl ps --name <pod_name> -o json # 获取容器的网络命名空间 crictl inspect <container_id> | grep netns # 进入网络命名空间 nsenter -t <PID> -n ip link show ``` 或者使用`kubectl exec`进入Pod,执行`ip link show`查看接口。 步骤5:检查Multus日志 查看Multus的日志,通常Multus会以DaemonSet形式运行,在每个节点上有一个Pod。查看对应节点上的Multus Pod日志: ```bash kubectl logs -n kube-system <multus_pod_name> --tail=100 ``` 在日志中搜索错误信息“Link not found”,看是否有更详细的上下文。 步骤6:检查Kube-OVN日志 同样,检查Kube-OVN的CNI插件日志(通常位于/var/log/kube-ovn目录)和kube-ovn-controller、kube-ovn-cni等组件的日志。 常见原因及解决方案: 1. **网络接口创建延迟**:可能是Kube-OVN创建接口需要时间,而Multus在创建接口之前就尝试查找它。这种情况下,可以尝试在Multus的配置中增加重试机制(如果CNI插件支持)。 2. **接口名称不匹配**:Multus默认会使用第一个网络接口(eth0)作为主网络接口,然后为附加网络接口分配名称(如net1)。但是,如果附加网络接口的名称与预期不符,可能会导致问题。在Multus的NAD配置中,可以通过`"interfaceRequest"`字段指定接口名称,例如: ```json { "cniVersion": "0.3.1", "type": "kube-ovn", "server_socket": "/run/openvswitch/kube-ovn-daemon.sock", "provider": "ovn-vpc-external-network", "interfaceRequest": "net1" // 指定接口名称 } ``` 3. **网络命名空间问题**:确保Multus在正确的网络命名空间中操作。这通常由容器运行时在调用CNI插件时指定,一般不会出错。 4. **Kube-OVN子网配置问题**:如果子网配置错误,Kube-OVN可能无法创建接口。检查子网的状态: ```bash kubectl get subnet ovn-vpc-external-network -o yaml ``` 确保状态为`Ready`。 5. **节点网络准备**:如果使用underlay网络,需要确保节点上的物理接口(如eth0)已经启动并配置了正确的IP地址。同时,节点可能需要配置允许转发等网络参数。 6. **权限问题**:Kube-OVN的CNI插件需要足够的权限来操作网络接口和OVS。检查其服务账户的权限。 如果以上步骤无法解决问题,可以尝试重新创建Multus的配置(如引用[3]所示),确保Multus的配置文件正确。 由于问题描述有限,以上步骤需要根据实际情况进行排查。 相关问题: 1. 如何诊断Multus CNI插件的网络附加失败问题? 2. Kube-OVN中子网配置错误会导致哪些常见问题? 3. 如何为Multus附加网络指定自定义接口名称? 4. 如何收集和查看Kube-OVN的日志以排查网络问题?</think>### 解决 Kubernetes Multus 插件 "Link not found" 错误 在 Kubernetes 中使用 Multus 插件添加容器到网络时出现 `Link not found` 错误(特别是 `ovn-vpc-external-network`),通常是由于网络接口配置问题导致的。以下是系统化的排查和解决方案: --- #### 1. **验证网络接口存在性** 错误表明 Multus 无法找到指定的网络接口(Link),首先检查主机上的物理/虚拟接口: ```bash # 在目标节点上执行 ip link show ovs-vsctl show # 检查 OVS 网桥 ``` - 确认 `ovn-vpc-external-network` 对应的接口(如 `eth1`、`veth*` 或 OVS 端口)存在且状态为 `UP` - **修复方案**:若接口缺失,重新创建 OVS 网桥: ```bash ovs-vsctl add-br br-external ovs-vsctl add-port br-external eth1 # 绑定物理接口 ``` --- #### 2. **检查 Multus NetworkAttachmentDefinition 配置** 验证 `ovn-vpc-external-network` 的 NetworkAttachmentDefinition (NAD) 是否正确引用底层接口[^4][^5]: ```yaml # 检查 NAD 配置 kubectl get network-attachment-definitions.k8s.cni.cncf.io ovn-vpc-external-network -o yaml ``` 关键配置项: ```yaml spec: config: |- { "cniVersion": "0.3.1", "type": "kube-ovn", "server_socket": "/run/openvswitch/kube-ovn-daemon.sock", "provider": "ovn-vpc-external-network", # 必须匹配子网名 "interfaceName": "net1" # 显式指定接口名 } ``` - **关键点**:`provider` 字段必须与 Kube-OVN 子网名称一致[^1] - **修复方案**:添加 `interfaceName` 明确指定接口名(如 `net1`) --- #### 3. **验证 Kube-OVN 子网配置** 确认子网 `ovn-vpc-external-network` 的 `underlayGateway` 已启用且绑定正确接口: ```yaml kubectl get subnet ovn-vpc-external-network -o yaml ``` 需包含: ```yaml spec: underlayGateway: true # 启用物理网络 gatewayNode: "node01" # 指定网关节点 vlan: vlan100 # 若使用 VLAN ``` --- #### 4. **检查 Pod 注解中的网络请求** Pod 注解必须正确请求目标网络[^5]: ```yaml apiVersion: v1 kind: Pod metadata: annotations: k8s.v1.cni.cncf.io/networks: kube-system/ovn-vpc-external-network@net1 # 显式指定接口 spec: ... ``` - **关键点**:通过 `@net1` 显式定义接口名,避免名称冲突 --- #### 5. **排查网络命名空间问题** 进入容器网络命名空间验证接口: ```bash # 获取容器 PID container_pid=$(docker inspect <container_id> --format '{{.State.Pid}}') # 进入网络命名空间 nsenter -t $container_pid -n ip link show ``` - 若接口未出现,检查 Kube-OVN 日志: ```bash kubectl logs -n kube-system -l app=kube-ovn-cni --tail=100 ``` --- #### 6. **修复路径:逐步操作** 1. **重新创建 OVS 网桥**: ```bash ovs-vsctl del-br br-external ovs-vsctl add-br br-external ovs-vsctl add-port br-external eth1 ``` 2. **更新 NAD 配置**: ```yaml spec: config: |- { "type": "kube-ovn", "server_socket": "/run/openvswitch/kube-ovn-daemon.sock", "provider": "ovn-vpc-external-network", "interfaceName": "net1" # 固定接口名 } ``` 3. **重建测试 Pod**: ```bash kubectl annotate pod test-pod k8s.v1.cni.cncf.io/networks- kubectl delete pod test-pod kubectl apply -f test-pod.yaml # 带新注解的YAML ``` --- #### 常见原因总结 | 原因 | 解决方案 | |---------------------|------------------------------| | 物理接口未绑定 OVS | `ovs-vsctl add-port br-external eth1` | | NAD 未指定接口名 | 添加 `"interfaceName": "net1"` | | 子网未启用 underlay | 设置 `underlayGateway: true` | | Pod 注解缺少接口声明 | 添加 `@net1` 后缀 | --- ### 相关问题 1. 如何诊断 Multus CNI 插件与 Kube-OVN 的集成故障? 2. 在 Kubernetes 中如何为 Multus 网络配置多 VLAN? 3. Kube-OVN 的 underlay 模式有哪些常见网络限制? 4. 如何监控 Multus 多网络接口的流量?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值