Merge pull request #669 from 14rcole/sandbox-public

Refactor server sandbox
This commit is contained in:
Mrunal Patel 2017-07-19 12:42:13 -07:00 committed by GitHub
commit 093660ea68
6 changed files with 198 additions and 33 deletions

View file

@ -37,7 +37,7 @@ const (
seccompLocalhostPrefix = "localhost/" seccompLocalhostPrefix = "localhost/"
) )
func addOCIBindMounts(sb *sandbox, containerConfig *pb.ContainerConfig, specgen *generate.Generator) error { func addOCIBindMounts(sb *Sandbox, containerConfig *pb.ContainerConfig, specgen *generate.Generator) error {
mounts := containerConfig.GetMounts() mounts := containerConfig.GetMounts()
for _, mount := range mounts { for _, mount := range mounts {
dest := mount.ContainerPath dest := mount.ContainerPath
@ -109,7 +109,7 @@ func addImageVolumes(rootfs string, s *Server, containerInfo *storage.ContainerI
return nil return nil
} }
func addDevices(sb *sandbox, containerConfig *pb.ContainerConfig, specgen *generate.Generator) error { func addDevices(sb *Sandbox, containerConfig *pb.ContainerConfig, specgen *generate.Generator) error {
sp := specgen.Spec() sp := specgen.Spec()
for _, device := range containerConfig.GetDevices() { for _, device := range containerConfig.GetDevices() {
dev, err := devices.DeviceFromPath(device.HostPath, device.Permissions) dev, err := devices.DeviceFromPath(device.HostPath, device.Permissions)
@ -344,7 +344,7 @@ func (s *Server) CreateContainer(ctx context.Context, req *pb.CreateContainerReq
return resp, nil return resp, nil
} }
func (s *Server) createSandboxContainer(ctx context.Context, containerID string, containerName string, sb *sandbox, SandboxConfig *pb.PodSandboxConfig, containerConfig *pb.ContainerConfig) (*oci.Container, error) { func (s *Server) createSandboxContainer(ctx context.Context, containerID string, containerName string, sb *Sandbox, SandboxConfig *pb.PodSandboxConfig, containerConfig *pb.ContainerConfig) (*oci.Container, error) {
if sb == nil { if sb == nil {
return nil, errors.New("createSandboxContainer needs a sandbox") return nil, errors.New("createSandboxContainer needs a sandbox")
} }
@ -531,7 +531,7 @@ func (s *Server) createSandboxContainer(ctx context.Context, containerID string,
return nil, err return nil, err
} }
netNsPath := sb.netNsPath() netNsPath := sb.NetNsPath()
if netNsPath == "" { if netNsPath == "" {
// The sandbox does not have a permanent namespace, // The sandbox does not have a permanent namespace,
// it's on the host one. // it's on the host one.
@ -714,7 +714,7 @@ func (s *Server) createSandboxContainer(ctx context.Context, containerID string,
return nil, err return nil, err
} }
container, err := oci.NewContainer(containerID, containerName, containerInfo.RunDir, logPath, sb.netNs(), labels, kubeAnnotations, image, metadata, sb.id, containerConfig.Tty, containerConfig.Stdin, containerConfig.StdinOnce, sb.privileged, sb.trusted, containerInfo.Dir, created, containerImageConfig.Config.StopSignal) container, err := oci.NewContainer(containerID, containerName, containerInfo.RunDir, logPath, sb.NetNs(), labels, kubeAnnotations, image, metadata, sb.id, containerConfig.Tty, containerConfig.Stdin, containerConfig.StdinOnce, sb.privileged, sb.trusted, containerInfo.Dir, created, containerImageConfig.Config.StopSignal)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -126,7 +126,8 @@ func hostNetNsPath() (string, error) {
return netNS.Path(), nil return netNS.Path(), nil
} }
type sandbox struct { // Sandbox contains data surrounding kubernetes sandboxes on the server
type Sandbox struct {
id string id string
namespace string namespace string
// OCI pod name (eg "<namespace>-<name>-<attempt>") // OCI pod name (eg "<namespace>-<name>-<attempt>")
@ -162,19 +163,162 @@ var (
errSandboxClosedNetNS = errors.New("PodSandbox networking namespace is closed") errSandboxClosedNetNS = errors.New("PodSandbox networking namespace is closed")
) )
func (s *sandbox) addContainer(c *oci.Container) { // NewSandbox creates and populates a new pod sandbox
// New sandboxes have no containers, no infra container, and no network namespaces associated with them
// An infra container must be attached before the sandbox is added to the state
func NewSandbox(id, namespace, name, kubeName, logDir string, labels, annotations map[string]string, processLabel, mountLabel string, metadata *pb.PodSandboxMetadata, shmPath, cgroupParent string, privileged, trusted bool, resolvPath, hostname string, portMappings []*hostport.PortMapping) (*Sandbox, error) {
sb := new(Sandbox)
sb.id = id
sb.namespace = namespace
sb.name = name
sb.kubeName = kubeName
sb.logDir = logDir
sb.labels = labels
sb.annotations = annotations
sb.containers = oci.NewMemoryStore()
sb.processLabel = processLabel
sb.mountLabel = mountLabel
sb.metadata = metadata
sb.shmPath = shmPath
sb.cgroupParent = cgroupParent
sb.privileged = privileged
sb.trusted = trusted
sb.resolvPath = resolvPath
sb.hostname = hostname
sb.portMappings = portMappings
return sb, nil
}
// ID returns the id of the sandbox
func (s *Sandbox) ID() string {
return s.id
}
// Namespace returns the namespace for the sandbox
func (s *Sandbox) Namespace() string {
return s.namespace
}
// Name returns the name of the sandbox
func (s *Sandbox) Name() string {
return s.name
}
// KubeName returns the kubernetes name for the sandbox
func (s *Sandbox) KubeName() string {
return s.kubeName
}
// LogDir returns the location of the logging directory for the sandbox
func (s *Sandbox) LogDir() string {
return s.logDir
}
// Labels returns the labels associated with the sandbox
func (s *Sandbox) Labels() fields.Set {
return s.labels
}
// Annotations returns a list of annotations for the sandbox
func (s *Sandbox) Annotations() map[string]string {
return s.annotations
}
// InfraContainer returns the infrastructure container for the sandbox
func (s *Sandbox) InfraContainer() *oci.Container {
return s.infraContainer
}
// Containers returns the ContainerStorer that contains information on all
// of the containers in the sandbox
func (s *Sandbox) Containers() oci.ContainerStorer {
return s.containers
}
// ProcessLabel returns the process label for the sandbox
func (s *Sandbox) ProcessLabel() string {
return s.processLabel
}
// MountLabel returns the mount label for the sandbox
func (s *Sandbox) MountLabel() string {
return s.mountLabel
}
// Metadata returns a set of metadata about the sandbox
func (s *Sandbox) Metadata() *pb.PodSandboxMetadata {
return s.metadata
}
// ShmPath returns the shm path of the sandbox
func (s *Sandbox) ShmPath() string {
return s.shmPath
}
// CgroupParent returns the cgroup parent of the sandbox
func (s *Sandbox) CgroupParent() string {
return s.cgroupParent
}
// Privileged returns whether or not the containers in the sandbox are
// privileged containers
func (s *Sandbox) Privileged() bool {
return s.privileged
}
// Trusted returns whether or not the containers in the sandbox are trusted
func (s *Sandbox) Trusted() bool {
return s.trusted
}
// ResolvPath returns the resolv path for the sandbox
func (s *Sandbox) ResolvPath() string {
return s.resolvPath
}
// Hostname returns the hsotname of the sandbox
func (s *Sandbox) Hostname() string {
return s.hostname
}
// PortMappings returns a list of port mappings between the host and the sandbox
func (s *Sandbox) PortMappings() []*hostport.PortMapping {
return s.portMappings
}
// AddContainer adds a container to the sandbox
func (s *Sandbox) AddContainer(c *oci.Container) {
s.containers.Add(c.Name(), c) s.containers.Add(c.Name(), c)
} }
func (s *sandbox) getContainer(name string) *oci.Container { // GetContainer retrieves a container from the sandbox
func (s *Sandbox) GetContainer(name string) *oci.Container {
return s.containers.Get(name) return s.containers.Get(name)
} }
func (s *sandbox) removeContainer(c *oci.Container) { // RemoveContainer deletes a container from the sandbox
func (s *Sandbox) RemoveContainer(c *oci.Container) {
s.containers.Delete(c.Name()) s.containers.Delete(c.Name())
} }
func (s *sandbox) netNs() ns.NetNS { // SetInfraContainer sets the infrastructure container of a sandbox
// Attempts to set the infrastructure container after one is already present will throw an error
func (s *Sandbox) SetInfraContainer(infraCtr *oci.Container) error {
if s.infraContainer != nil {
return fmt.Errorf("sandbox already has an infra container")
} else if infraCtr == nil {
return fmt.Errorf("must provide non-nil infra container")
}
s.infraContainer = infraCtr
return nil
}
// NetNs retrieves the network namespace of the sandbox
// If the sandbox uses the host namespace, nil is returned
func (s *Sandbox) NetNs() ns.NetNS {
if s.netns == nil { if s.netns == nil {
return nil return nil
} }
@ -182,7 +326,9 @@ func (s *sandbox) netNs() ns.NetNS {
return s.netns.ns return s.netns.ns
} }
func (s *sandbox) netNsPath() string { // NetNsPath returns the path to the network namespace of the sandbox.
// If the sandbox uses the host namespace, nil is returned
func (s *Sandbox) NetNsPath() string {
if s.netns == nil { if s.netns == nil {
return "" return ""
} }
@ -190,7 +336,8 @@ func (s *sandbox) netNsPath() string {
return s.netns.symlink.Name() return s.netns.symlink.Name()
} }
func (s *sandbox) netNsCreate() error { // NetNsCreate creates a new network namespace for the sandbox
func (s *Sandbox) NetNsCreate() error {
if s.netns != nil { if s.netns != nil {
return fmt.Errorf("net NS already created") return fmt.Errorf("net NS already created")
} }
@ -218,7 +365,25 @@ func (s *sandbox) netNsCreate() error {
return nil return nil
} }
func (s *sandbox) netNsRemove() error { // NetNsJoin attempts to join the sandbox to an existing network namespace
// This will fail if the sandbox is already part of a network namespace
func (s *Sandbox) NetNsJoin(nspath, name string) error {
if s.netns != nil {
return fmt.Errorf("sandbox already has a network namespace, cannot join another")
}
netNS, err := netNsGet(nspath, name)
if err != nil {
return err
}
s.netns = netNS
return nil
}
// NetNsRemove removes the network namespace associated with the sandbox
func (s *Sandbox) NetNsRemove() error {
if s.netns == nil { if s.netns == nil {
logrus.Warn("no networking namespace") logrus.Warn("no networking namespace")
return nil return nil
@ -265,7 +430,7 @@ func (s *sandbox) netNsRemove() error {
return nil return nil
} }
func (s *Server) getPodSandboxFromRequest(podSandboxID string) (*sandbox, error) { func (s *Server) getPodSandboxFromRequest(podSandboxID string) (*Sandbox, error) {
if podSandboxID == "" { if podSandboxID == "" {
return nil, errSandboxIDEmpty return nil, errSandboxIDEmpty
} }

View file

@ -30,7 +30,7 @@ func filterSandbox(p *pb.PodSandbox, filter *pb.PodSandboxFilter) bool {
func (s *Server) ListPodSandbox(ctx context.Context, req *pb.ListPodSandboxRequest) (*pb.ListPodSandboxResponse, error) { func (s *Server) ListPodSandbox(ctx context.Context, req *pb.ListPodSandboxRequest) (*pb.ListPodSandboxResponse, error) {
logrus.Debugf("ListPodSandboxRequest %+v", req) logrus.Debugf("ListPodSandboxRequest %+v", req)
var pods []*pb.PodSandbox var pods []*pb.PodSandbox
var podList []*sandbox var podList []*Sandbox
for _, sb := range s.state.sandboxes { for _, sb := range s.state.sandboxes {
podList = append(podList, sb) podList = append(podList, sb)
} }
@ -45,9 +45,9 @@ func (s *Server) ListPodSandbox(ctx context.Context, req *pb.ListPodSandboxReque
} }
sb := s.getSandbox(id) sb := s.getSandbox(id)
if sb == nil { if sb == nil {
podList = []*sandbox{} podList = []*Sandbox{}
} else { } else {
podList = []*sandbox{sb} podList = []*Sandbox{sb}
} }
} }
} }

View file

@ -330,7 +330,7 @@ func (s *Server) RunPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest
portMappings := convertPortMappings(req.GetConfig().GetPortMappings()) portMappings := convertPortMappings(req.GetConfig().GetPortMappings())
sb := &sandbox{ sb := &Sandbox{
id: id, id: id,
namespace: namespace, namespace: namespace,
name: name, name: name,
@ -420,7 +420,7 @@ func (s *Server) RunPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest
} }
} else { } else {
// Create the sandbox network namespace // Create the sandbox network namespace
if err = sb.netNsCreate(); err != nil { if err = sb.NetNsCreate(); err != nil {
return nil, err return nil, err
} }
@ -429,18 +429,18 @@ func (s *Server) RunPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest
return return
} }
if netnsErr := sb.netNsRemove(); netnsErr != nil { if netnsErr := sb.NetNsRemove(); netnsErr != nil {
logrus.Warnf("Failed to remove networking namespace: %v", netnsErr) logrus.Warnf("Failed to remove networking namespace: %v", netnsErr)
} }
}() }()
// Pass the created namespace path to the runtime // Pass the created namespace path to the runtime
err = g.AddOrReplaceLinuxNamespace("network", sb.netNsPath()) err = g.AddOrReplaceLinuxNamespace("network", sb.NetNsPath())
if err != nil { if err != nil {
return nil, err return nil, err
} }
netNsPath = sb.netNsPath() netNsPath = sb.NetNsPath()
} }
if req.GetConfig().GetLinux().GetSecurityContext().GetNamespaceOptions().HostPid { if req.GetConfig().GetLinux().GetSecurityContext().GetNamespaceOptions().HostPid {
@ -475,7 +475,7 @@ func (s *Server) RunPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest
return nil, fmt.Errorf("failed to write runtime configuration for pod sandbox %s(%s): %v", sb.name, id, err) return nil, fmt.Errorf("failed to write runtime configuration for pod sandbox %s(%s): %v", sb.name, id, err)
} }
container, err := oci.NewContainer(id, containerName, podContainer.RunDir, logPath, sb.netNs(), labels, kubeAnnotations, "", nil, id, false, false, false, sb.privileged, sb.trusted, podContainer.Dir, created, podContainer.Config.Config.StopSignal) container, err := oci.NewContainer(id, containerName, podContainer.RunDir, logPath, sb.NetNs(), labels, kubeAnnotations, "", nil, id, false, false, false, sb.privileged, sb.trusted, podContainer.Dir, created, podContainer.Config.Config.StopSignal)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -60,7 +60,7 @@ func (s *Server) StopPodSandbox(ctx context.Context, req *pb.StopPodSandboxReque
} }
// Close the sandbox networking namespace. // Close the sandbox networking namespace.
if err := sb.netNsRemove(); err != nil { if err := sb.NetNsRemove(); err != nil {
return nil, err return nil, err
} }

View file

@ -151,7 +151,7 @@ func (s *Server) loadContainer(id string) error {
return err return err
} }
ctr, err := oci.NewContainer(id, name, containerPath, m.Annotations[annotations.LogPath], sb.netNs(), labels, kubeAnnotations, img, &metadata, sb.id, tty, stdin, stdinOnce, sb.privileged, sb.trusted, containerDir, created, m.Annotations["org.opencontainers.image.stopSignal"]) ctr, err := oci.NewContainer(id, name, containerPath, m.Annotations[annotations.LogPath], sb.NetNs(), labels, kubeAnnotations, img, &metadata, sb.id, tty, stdin, stdinOnce, sb.privileged, sb.trusted, containerDir, created, m.Annotations["org.opencontainers.image.stopSignal"])
if err != nil { if err != nil {
return err return err
} }
@ -244,7 +244,7 @@ func (s *Server) loadSandbox(id string) error {
privileged := isTrue(m.Annotations[annotations.PrivilegedRuntime]) privileged := isTrue(m.Annotations[annotations.PrivilegedRuntime])
trusted := isTrue(m.Annotations[annotations.TrustedSandbox]) trusted := isTrue(m.Annotations[annotations.TrustedSandbox])
sb := &sandbox{ sb := &Sandbox{
id: id, id: id,
name: name, name: name,
kubeName: m.Annotations[annotations.KubeName], kubeName: m.Annotations[annotations.KubeName],
@ -309,7 +309,7 @@ func (s *Server) loadSandbox(id string) error {
return err return err
} }
scontainer, err := oci.NewContainer(m.Annotations[annotations.ContainerID], cname, sandboxPath, m.Annotations[annotations.LogPath], sb.netNs(), labels, kubeAnnotations, "", nil, id, false, false, false, privileged, trusted, sandboxDir, created, m.Annotations["org.opencontainers.image.stopSignal"]) scontainer, err := oci.NewContainer(m.Annotations[annotations.ContainerID], cname, sandboxPath, m.Annotations[annotations.LogPath], sb.NetNs(), labels, kubeAnnotations, "", nil, id, false, false, false, privileged, trusted, sandboxDir, created, m.Annotations["org.opencontainers.image.stopSignal"])
if err != nil { if err != nil {
return err return err
} }
@ -568,7 +568,7 @@ func New(config *Config) (*Server, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
sandboxes := make(map[string]*sandbox) sandboxes := make(map[string]*Sandbox)
containers := oci.NewMemoryStore() containers := oci.NewMemoryStore()
netPlugin, err := ocicni.InitCNI(config.NetworkDir, config.PluginDir) netPlugin, err := ocicni.InitCNI(config.NetworkDir, config.PluginDir)
if err != nil { if err != nil {
@ -651,17 +651,17 @@ func New(config *Config) (*Server, error) {
} }
type serverState struct { type serverState struct {
sandboxes map[string]*sandbox sandboxes map[string]*Sandbox
containers oci.ContainerStorer containers oci.ContainerStorer
} }
func (s *Server) addSandbox(sb *sandbox) { func (s *Server) addSandbox(sb *Sandbox) {
s.stateLock.Lock() s.stateLock.Lock()
s.state.sandboxes[sb.id] = sb s.state.sandboxes[sb.id] = sb
s.stateLock.Unlock() s.stateLock.Unlock()
} }
func (s *Server) getSandbox(id string) *sandbox { func (s *Server) getSandbox(id string) *Sandbox {
s.stateLock.Lock() s.stateLock.Lock()
sb := s.state.sandboxes[id] sb := s.state.sandboxes[id]
s.stateLock.Unlock() s.stateLock.Unlock()
@ -685,7 +685,7 @@ func (s *Server) addContainer(c *oci.Container) {
s.stateLock.Lock() s.stateLock.Lock()
sandbox := s.state.sandboxes[c.Sandbox()] sandbox := s.state.sandboxes[c.Sandbox()]
// TODO(runcom): handle !ok above!!! otherwise it panics! // TODO(runcom): handle !ok above!!! otherwise it panics!
sandbox.addContainer(c) sandbox.AddContainer(c)
s.state.containers.Add(c.ID(), c) s.state.containers.Add(c.ID(), c)
s.stateLock.Unlock() s.stateLock.Unlock()
} }
@ -711,7 +711,7 @@ func (s *Server) GetContainer(id string) *oci.Container {
func (s *Server) removeContainer(c *oci.Container) { func (s *Server) removeContainer(c *oci.Container) {
s.stateLock.Lock() s.stateLock.Lock()
sandbox := s.state.sandboxes[c.Sandbox()] sandbox := s.state.sandboxes[c.Sandbox()]
sandbox.removeContainer(c) sandbox.RemoveContainer(c)
s.state.containers.Delete(c.ID()) s.state.containers.Delete(c.ID())
s.stateLock.Unlock() s.stateLock.Unlock()
} }