美文网首页
Peer netns reference is invalid.

Peer netns reference is invalid.

作者: cloudFans | 来源:发表于2022-12-19 16:25 被阅读0次

    在容器里面创建宿主机级别可操作的ns,在容器内部可正常使用,但是宿主机上会提示该错误。

    正确方式,在host级别创建该ns,在daemonset容器内部去用即可

    实际上我的pod的daemonset(kube-ovn-cni),而且是host network 模式

    如下代码在宿主机命名空间上,操作ns是没有问题的。

    
    package main
    
    import (
        "fmt"
        "log"
        "os"
        "path"
    
        "github.com/containernetworking/plugins/pkg/ns"
        "golang.org/x/sys/unix"
    )
    
    const (
        bindMountPath = "/run/netns" /* Bind mount path for named netns */
    )
    
    // NsHandle is a handle to a network namespace. It can be cast directly
    // to an int and used as a file descriptor.
    type NsHandle int
    
    // None gets an empty (closed) NsHandle.
    func ClosedNs() NsHandle {
        return NsHandle(-1)
    }
    
    // GetFromPath gets a handle to a network namespace
    // identified by the path
    func GetNsFromPath(path string) (NsHandle, error) {
        fd, err := unix.Open(path, unix.O_RDONLY|unix.O_CLOEXEC, 0)
        if err != nil {
            return -1, err
        }
        return NsHandle(fd), nil
    }
    
    // GetFromThread gets a handle to the network namespace of a given pid and tid.
    func GetNsFromThread(pid, tid int) (NsHandle, error) {
        return GetNsFromPath(fmt.Sprintf("/proc/%d/task/%d/ns/net", pid, tid))
    }
    
    // Get gets a handle to the current threads network namespace.
    func GetNs() (NsHandle, error) {
        return GetNsFromThread(os.Getpid(), unix.Gettid())
    }
    
    // New creates a new network namespace, sets it as current and returns
    // a handle to it.
    func newNs() (ns NsHandle, err error) {
        if err := unix.Unshare(unix.CLONE_NEWNET); err != nil {
            return -1, err
        }
        return GetNs()
    }
    
    // NewNamed creates a new named network namespace, sets it as current,
    // and returns a handle to it
    func NewNamedNs(name string) (NsHandle, error) {
        if _, err := os.Stat(bindMountPath); os.IsNotExist(err) {
            err = os.MkdirAll(bindMountPath, 0755)
            if err != nil {
                return ClosedNs(), err
            }
        }
    
        newNs, err := newNs()
        if err != nil {
            return ClosedNs(), err
        }
    
        namedPath := path.Join(bindMountPath, name)
    
        f, err := os.OpenFile(namedPath, os.O_CREATE|os.O_EXCL, 0444)
        if err != nil {
            return ClosedNs(), err
        }
        f.Close()
    
        nsPath := fmt.Sprintf("/proc/%d/task/%d/ns/net", os.Getpid(), unix.Gettid())
        err = unix.Mount(nsPath, namedPath, "bind", unix.MS_BIND, "")
        if err != nil {
            return ClosedNs(), err
        }
    
        return newNs, nil
    }
    
    // DeleteNamed deletes a named network namespace
    func DeleteNamedNs(name string) error {
        namedPath := path.Join(bindMountPath, name)
    
        err := unix.Unmount(namedPath, unix.MNT_DETACH)
        if err != nil {
            return err
        }
    
        return os.Remove(namedPath)
    }
    
    // GetFromName gets a handle to a named network namespace such as one
    // created by `ip netns add`.
    func GetNsFromName(name string) (NsHandle, error) {
        return GetNsFromPath(fmt.Sprintf("/var/run/netns/%s", name))
    }
    
    const (
        NodeGwNic    = "ovnext0"
        NodeGwNs     = "ovnext"
        NodeGwNsPath = "/var/run/netns/ovnext"
    )
    
    func Error(e error) {
        if e != nil {
            log.Fatalln(e)
        }
    }
    
    func SetupNetNamespace() *NsHandle {
        // runtime.LockOSThread()
        // defer runtime.UnlockOSThread()
        log.Println("SetupNetNamespace...running")
        // _, err := GetNsFromName(NSName)
        // if err == nil {
        //  log.Printf("%s net ns is exists. Delete netns %s\n", NSName, NSName)
        // }
        // newns, err := NewNamedNs(NSName)
        // Error(err)
        // log.Println("SetupNetNamespace...done")
    
        // create netns
        if _, err := GetNsFromName(NodeGwNs); err != nil {
            // net ns not exist
            if _, err := NewNamedNs(NodeGwNs); err != nil {
                Error(fmt.Errorf("failed to create node gw ns %q, %v", NodeGwNs, err))
            }
        }
    
        podNS, err := ns.GetNS(NodeGwNsPath)
        Error(err)
        log.Println("PodNs: ", podNS)
        ns, err := GetNsFromName(NodeGwNs)
        if err != nil {
            Error(fmt.Errorf("failed to locate node gw ns %q, %v", NodeGwNs, err))
        }
        log.Println("SetupNetNamespace...done")
        return &ns
    }
    
    func main() {
        ns := SetupNetNamespace()
        log.Println("added ns: ", ns)
    }
    
    

    但在pod 或者容器内部应该都不行,即使是hostnetwork 模式也不行

    package daemon
    
    import (
        "fmt"
        "os"
        "path"
    
        "golang.org/x/sys/unix"
    )
    
    const (
        bindMountPath = "/run/netns" /* Bind mount path for named netns */
    )
    
    // NsHandle is a handle to a network namespace. It can be cast directly
    // to an int and used as a file descriptor.
    type NsHandle int
    
    // None gets an empty (closed) NsHandle.
    func ClosedNs() NsHandle {
        return NsHandle(-1)
    }
    
    // GetFromPath gets a handle to a network namespace
    // identified by the path
    func GetNsFromPath(path string) (NsHandle, error) {
        fd, err := unix.Open(path, unix.O_RDONLY|unix.O_CLOEXEC, 0)
        if err != nil {
            return -1, err
        }
        return NsHandle(fd), nil
    }
    
    // GetFromThread gets a handle to the network namespace of a given pid and tid.
    func GetNsFromThread(pid, tid int) (NsHandle, error) {
        return GetNsFromPath(fmt.Sprintf("/proc/%d/task/%d/ns/net", pid, tid))
    }
    
    // Get gets a handle to the current threads network namespace.
    func GetNs() (NsHandle, error) {
        return GetNsFromThread(os.Getpid(), unix.Gettid())
    }
    
    // New creates a new network namespace, sets it as current and returns
    // a handle to it.
    func newNs() (ns NsHandle, err error) {
        if err := unix.Unshare(unix.CLONE_NEWNET); err != nil {
            return -1, err
        }
        return GetNs()
    }
    
    // NewNamed creates a new named network namespace, sets it as current,
    // and returns a handle to it
    func NewNamedNs(name string) (NsHandle, error) {
        if _, err := os.Stat(bindMountPath); os.IsNotExist(err) {
            err = os.MkdirAll(bindMountPath, 0755)
            if err != nil {
                return ClosedNs(), err
            }
        }
    
        newNs, err := newNs()
        if err != nil {
            return ClosedNs(), err
        }
    
        namedPath := path.Join(bindMountPath, name)
    
        f, err := os.OpenFile(namedPath, os.O_CREATE|os.O_EXCL, 0444)
        if err != nil {
            return ClosedNs(), err
        }
        f.Close()
    
        nsPath := fmt.Sprintf("/proc/%d/task/%d/ns/net", os.Getpid(), unix.Gettid())
        err = unix.Mount(nsPath, namedPath, "bind", unix.MS_BIND, "")
        if err != nil {
            return ClosedNs(), err
        }
    
        return newNs, nil
    }
    
    // DeleteNamed deletes a named network namespace
    func DeleteNamedNs(name string) error {
        namedPath := path.Join(bindMountPath, name)
    
        err := unix.Unmount(namedPath, unix.MNT_DETACH)
        if err != nil {
            return err
        }
    
        return os.Remove(namedPath)
    }
    
    // GetFromName gets a handle to a named network namespace such as one
    // created by `ip netns add`.
    func GetNsFromName(name string) (NsHandle, error) {
        return GetNsFromPath(fmt.Sprintf("/var/run/netns/%s", name))
    }
    
    
    

    参考: https://serverfault.com/questions/961504/cannot-create-nested-network-namespace

    参考项目: https://github.com/vishvananda/netns

    但是neutron ovn metadata 就是host network 模式的docker内部创建的ns,可能跟容器的其他ns相关的配置还有点关系,可以再分析下kolla neutron metadata相关的docker build内容或者挂载目录。

    [root@compute028 ~]# ip netns
    ovnmeta-8569c79c-4184-406a-ad55-19bf6d47d549 (id: 0)
    ovnmeta-1e8d676f-5d0a-4371-aa3d-a0029598e27a (id: 2)
    ovnmeta-fcfd0f86-989f-47c3-9830-cd40e75ba873 (id: 1)
    ovnmeta-b052976f-29e0-4a3c-ad66-fa23b058427b (id: 10)
    [root@compute028 ~]#
    [root@compute028 ~]#
    
    [root@compute028 ~]# docker ps -a | grep neutron
    f8d24cbde993        registry.yealinkops.com/third_party/kolla/centos-source-neutron-metadata-agent:victoria       "dumb-init --single-…"   11 months ago       Up 8 weeks (healthy)                        neutron_ovn_metadata_agent
    [root@compute028 ~]#
    
    
    
    

    相关文章

      网友评论

          本文标题:Peer netns reference is invalid.

          本文链接:https://www.haomeiwen.com/subject/ceeeqdtx.html