Пример #1
0
    def connect(self, vif, ifname, netns, container_id):
        # NOTE(vikasc): Ideally 'ifname' should be used here but instead a
        # temporary name is being used while creating the device for
        # container in host network namespace. This is because cni expects
        # only 'eth0' as interface name and if host already has an
        # interface named 'eth0', device creation will fail with 'already
        # exists' error.
        temp_name = vif.vif_name

        # First let's take a peek into the pod namespace and try to remove any
        # leftover interface in case we got restarted before CNI returned to
        # kubelet.
        with b_base.get_ipdb(netns) as c_ipdb:
            self._remove_ifaces(c_ipdb, (temp_name, ifname), netns)

        # We might also have leftover interface in the host netns, let's try to
        # remove it too. This is outside of the main host's IPDB context
        # manager to make sure removal is commited before starting next
        # transaction.
        with b_base.get_ipdb() as h_ipdb:
            self._remove_ifaces(h_ipdb, (temp_name, ))

        with b_base.get_ipdb() as h_ipdb:
            # TODO(vikasc): evaluate whether we should have stevedore
            #               driver for getting the link device.
            vm_iface_name = self._detect_iface_name(h_ipdb)
            mtu = h_ipdb.interfaces[vm_iface_name].mtu
            if mtu < vif.network.mtu:
                # NOTE(dulek): This might happen if Neutron and DHCP agent
                # have different MTU settings. See
                # https://bugs.launchpad.net/kuryr-kubernetes/+bug/1863212
                raise exceptions.CNIBindingFailure(
                    f'MTU of interface {vm_iface_name} ({mtu}) is smaller '
                    f'than MTU of pod network {vif.network.id} '
                    f'({vif.network.mtu}). Please make sure pod network '
                    f'has the same or smaller MTU as node (VM) network.')

            args = self._get_iface_create_args(vif)
            with h_ipdb.create(ifname=temp_name,
                               link=h_ipdb.interfaces[vm_iface_name],
                               **args) as iface:
                iface.net_ns_fd = utils.convert_netns(netns)

        with b_base.get_ipdb(netns) as c_ipdb:
            with c_ipdb.interfaces[temp_name] as iface:
                iface.ifname = ifname
                iface.mtu = vif.network.mtu
                iface.address = str(vif.address)
                iface.up()
Пример #2
0
    def _detect_iface_name(self, h_ipdb):
        # Let's try config first
        if config.CONF.binding.link_iface in h_ipdb.interfaces:
            LOG.debug(f'Using configured interface '
                      f'{config.CONF.binding.link_iface} as bridge interface.')
            return config.CONF.binding.link_iface

        # Then let's try choosing the one where kubelet listens to
        conns = [
            x for x in psutil.net_connections()
            if x.status == psutil.CONN_LISTEN and x.laddr.port == KUBELET_PORT
        ]
        if len(conns) == 1:
            lookup_addr = conns[0].laddr.ip
            for name, iface in h_ipdb.interfaces.items():
                if type(name) is int:  # Skip ones duplicated by id
                    continue

                for addr in iface['ipaddr']:
                    if addr[0] == lookup_addr:
                        LOG.debug(f'Using kubelet bind interface {name} as '
                                  f'bridge interface.')
                        return name

        # Alright, just try the first non-loopback interface
        for name, iface in h_ipdb.interfaces.items():
            if type(name) is int:  # Skip ones duplicated by id
                continue

            if iface['flags'] & pyroute_netlink.rtnl.ifinfmsg.IFF_LOOPBACK:
                continue  # Skip loopback

            LOG.debug(f'Using interface {name} as bridge interface.')
            return name

        raise exceptions.CNIBindingFailure('Cannot find bridge interface for '
                                           'nested driver to use. Please set '
                                           '[binding]link_iface option.')
Пример #3
0
    def connect(self, vif, ifname, netns, container_id):
        # NOTE(vikasc): Ideally 'ifname' should be used here but instead a
        # temporary name is being used while creating the device for
        # container in host network namespace. This is because cni expects
        # only 'eth0' as interface name and if host already has an
        # interface named 'eth0', device creation will fail with 'already
        # exists' error.
        temp_name = vif.vif_name

        # First let's take a peek into the pod namespace and try to remove any
        # leftover interface in case we got restarted before CNI returned to
        # kubelet.
        with b_base.get_ipdb(netns) as c_ipdb:
            self._remove_ifaces(c_ipdb, (temp_name, ifname), netns)

        # We might also have leftover interface in the host netns, let's try to
        # remove it too. This is outside of the main host's IPDB context
        # manager to make sure removal is commited before starting next
        # transaction.
        with b_base.get_ipdb() as h_ipdb:
            self._remove_ifaces(h_ipdb, (temp_name,))

        try:
            with b_base.get_ipdb() as h_ipdb:
                # TODO(vikasc): evaluate whether we should have stevedore
                #               driver for getting the link device.
                vm_iface_name = config.CONF.binding.link_iface
                mtu = h_ipdb.interfaces[vm_iface_name].mtu
                if mtu != vif.network.mtu:
                    # NOTE(dulek): This might happen if Neutron and DHCP agent
                    # have different MTU settings. See
                    # https://bugs.launchpad.net/kuryr-kubernetes/+bug/1863212
                    raise exceptions.CNIBindingFailure(
                        f'MTU of interface {vm_iface_name} ({mtu}) does not '
                        f'match MTU of pod network {vif.network.id} '
                        f'({vif.network.mtu}). Please make sure pod network '
                        f'has the same MTU as node (VM) network.')

                args = self._get_iface_create_args(vif)
                with h_ipdb.create(ifname=temp_name,
                                   link=h_ipdb.interfaces[vm_iface_name],
                                   **args) as iface:
                    iface.net_ns_fd = utils.convert_netns(netns)
        except pyroute2.NetlinkError as e:
            if e.code == errno.EEXIST:
                # NOTE(dulek): This is related to bug 1854928. It's super-rare,
                #              so aim of this piece is to gater any info useful
                #              for determining when it happens.
                LOG.exception('Creation of pod interface failed, most likely '
                              'due to duplicated VLAN id. This will probably '
                              'cause kuryr-daemon to crashloop. Trying to '
                              'gather debugging information.')

                with b_base.get_ipdb() as h_ipdb:
                    LOG.error('List of host interfaces: %s', h_ipdb.interfaces)

                with b_base.get_ipdb(netns) as c_ipdb:
                    LOG.error('List of pod namespace interfaces: %s',
                              c_ipdb.interfaces)
            raise

        with b_base.get_ipdb(netns) as c_ipdb:
            with c_ipdb.interfaces[temp_name] as iface:
                iface.ifname = ifname
                iface.mtu = vif.network.mtu
                iface.address = str(vif.address)
                iface.up()