sandbox: Create a symbolic link to the networking namespace
In order to workaround a bug introduced with runc commit bc84f833, we create a symbolic link to our permanent networking namespace so that runC realizes that this is not the host namespace. Although this bug is now fixed upstream (See commit f33de5ab4), this patch works with pre rc3 runC versions. We may want to revert that patch once runC 1.0.0 is released. Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
parent
a9724c2c9c
commit
0df8200e12
3 changed files with 106 additions and 10 deletions
|
@ -1,8 +1,11 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rand"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
|
@ -16,20 +19,97 @@ import (
|
||||||
type sandboxNetNs struct {
|
type sandboxNetNs struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
ns ns.NetNS
|
ns ns.NetNS
|
||||||
|
symlink *os.File
|
||||||
closed bool
|
closed bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func netNsGet(nspath string) (*sandboxNetNs, error) {
|
func (ns *sandboxNetNs) symlinkCreate(name string) error {
|
||||||
|
b := make([]byte, 4)
|
||||||
|
_, randErr := rand.Reader.Read(b)
|
||||||
|
if randErr != nil {
|
||||||
|
return randErr
|
||||||
|
}
|
||||||
|
|
||||||
|
nsName := fmt.Sprintf("%s-%x", name, b)
|
||||||
|
symlinkPath := filepath.Join(nsRunDir, nsName)
|
||||||
|
|
||||||
|
if err := os.Symlink(ns.ns.Path(), symlinkPath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fd, err := os.Open(symlinkPath)
|
||||||
|
if err != nil {
|
||||||
|
if removeErr := os.RemoveAll(symlinkPath); removeErr != nil {
|
||||||
|
return removeErr
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ns.symlink = fd
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ns *sandboxNetNs) symlinkRemove() error {
|
||||||
|
if err := ns.symlink.Close(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.RemoveAll(ns.symlink.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
func isSymbolicLink(path string) (bool, error) {
|
||||||
|
fi, err := os.Lstat(path)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return fi.Mode()&os.ModeSymlink == os.ModeSymlink, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func netNsGet(nspath, name string) (*sandboxNetNs, error) {
|
||||||
if err := ns.IsNSorErr(nspath); err != nil {
|
if err := ns.IsNSorErr(nspath); err != nil {
|
||||||
return nil, errSandboxClosedNetNS
|
return nil, errSandboxClosedNetNS
|
||||||
}
|
}
|
||||||
|
|
||||||
netNS, err := ns.GetNS(nspath)
|
symlink, symlinkErr := isSymbolicLink(nspath)
|
||||||
|
if symlinkErr != nil {
|
||||||
|
return nil, symlinkErr
|
||||||
|
}
|
||||||
|
|
||||||
|
var resolvedNsPath string
|
||||||
|
if symlink {
|
||||||
|
path, err := os.Readlink(nspath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resolvedNsPath = path
|
||||||
|
} else {
|
||||||
|
resolvedNsPath = nspath
|
||||||
|
}
|
||||||
|
|
||||||
|
netNS, err := ns.GetNS(resolvedNsPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &sandboxNetNs{ns: netNS, closed: false,}, nil
|
netNs := &sandboxNetNs{ns: netNS, closed: false,}
|
||||||
|
|
||||||
|
if symlink {
|
||||||
|
fd, err := os.Open(nspath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
netNs.symlink = fd
|
||||||
|
} else {
|
||||||
|
if err := netNs.symlinkCreate(name); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return netNs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func hostNetNsPath() (string, error) {
|
func hostNetNsPath() (string, error) {
|
||||||
|
@ -61,6 +141,7 @@ type sandbox struct {
|
||||||
const (
|
const (
|
||||||
podDefaultNamespace = "default"
|
podDefaultNamespace = "default"
|
||||||
defaultShmSize = 64 * 1024 * 1024
|
defaultShmSize = 64 * 1024 * 1024
|
||||||
|
nsRunDir = "/var/run/netns"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -93,7 +174,7 @@ func (s *sandbox) netNsPath() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.netns.ns.Path()
|
return s.netns.symlink.Name()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *sandbox) netNsCreate() error {
|
func (s *sandbox) netNsCreate() error {
|
||||||
|
@ -111,6 +192,16 @@ func (s *sandbox) netNsCreate() error {
|
||||||
closed: false,
|
closed: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := s.netns.symlinkCreate(s.name); err != nil {
|
||||||
|
logrus.Warnf("Could not create nentns symlink %v", err)
|
||||||
|
|
||||||
|
if err := s.netns.ns.Close(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,6 +220,10 @@ func (s *sandbox) netNsRemove() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := s.netns.symlinkRemove(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if err := s.netns.ns.Close(); err != nil {
|
if err := s.netns.ns.Close(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,14 +73,15 @@ func (s *Server) RemovePodSandbox(ctx context.Context, req *pb.RemovePodSandboxR
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := sb.netNsRemove(); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to remove networking namespace for sandbox %s: %v", sb.id, err)
|
||||||
|
}
|
||||||
|
|
||||||
// Remove the files related to the sandbox
|
// Remove the files related to the sandbox
|
||||||
podSandboxDir := filepath.Join(s.config.SandboxDir, sb.id)
|
podSandboxDir := filepath.Join(s.config.SandboxDir, sb.id)
|
||||||
if err := os.RemoveAll(podSandboxDir); err != nil {
|
if err := os.RemoveAll(podSandboxDir); err != nil {
|
||||||
return nil, fmt.Errorf("failed to remove sandbox %s directory: %v", sb.id, err)
|
return nil, fmt.Errorf("failed to remove sandbox %s directory: %v", sb.id, err)
|
||||||
}
|
}
|
||||||
if err := sb.netNsRemove(); err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to remove networking namespace for sandbox %s: %v", sb.id, err)
|
|
||||||
}
|
|
||||||
s.releaseContainerName(podInfraContainer.Name())
|
s.releaseContainerName(podInfraContainer.Name())
|
||||||
s.removeContainer(podInfraContainer)
|
s.removeContainer(podInfraContainer)
|
||||||
sb.infraContainer = nil
|
sb.infraContainer = nil
|
||||||
|
|
|
@ -172,7 +172,7 @@ func (s *Server) loadSandbox(id string) error {
|
||||||
// Otherwise, the sandbox will live in the host namespace.
|
// Otherwise, the sandbox will live in the host namespace.
|
||||||
netNsPath, err := configNetNsPath(m)
|
netNsPath, err := configNetNsPath(m)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
netNS, nsErr := netNsGet(netNsPath)
|
netNS, nsErr := netNsGet(netNsPath, sb.name)
|
||||||
// If we can't load the networking namespace
|
// If we can't load the networking namespace
|
||||||
// because it's closed, we just set the sb netns
|
// because it's closed, we just set the sb netns
|
||||||
// pointer to nil. Otherwise we return an error.
|
// pointer to nil. Otherwise we return an error.
|
||||||
|
|
Loading…
Reference in a new issue