diff --git a/server/container_create.go b/server/container_create.go index c09f277b8f8..71734ac3468 100644 --- a/server/container_create.go +++ b/server/container_create.go @@ -476,50 +476,53 @@ func (s *Server) CreateContainer(ctx context.Context, req *pb.CreateContainerReq return nil, errors.Wrap(err, "setting container name and ID") } + cleanupFuncs := make([]func(), 0) + defer func() { + // no error, no need to cleanup + if retErr == nil { + return + } + for i := len(cleanupFuncs) - 1; i >= 0; i-- { + cleanupFuncs[i]() + } + }() + if _, err = s.ReserveContainerName(ctr.ID(), ctr.Name()); err != nil { return nil, errors.Wrap(err, "Kubelet may be retrying requests that are timing out in CRI-O due to system load") } - defer func() { - if retErr != nil { - log.Infof(ctx, "createCtr: releasing container name %s", ctr.Name()) - s.ReleaseContainerName(ctr.Name()) - } - }() + cleanupFuncs = append(cleanupFuncs, func() { + log.Infof(ctx, "createCtr: releasing container name %s", ctr.Name()) + s.ReleaseContainerName(ctr.Name()) + }) newContainer, err := s.createSandboxContainer(ctx, ctr, sb) if err != nil { return nil, err } - defer func() { - if retErr != nil { - log.Infof(ctx, "createCtr: deleting container %s from storage", ctr.ID()) - err2 := s.StorageRuntimeServer().DeleteContainer(ctr.ID()) - if err2 != nil { - log.Warnf(ctx, "Failed to cleanup container directory: %v", err2) - } + cleanupFuncs = append(cleanupFuncs, func() { + log.Infof(ctx, "createCtr: deleting container %s from storage", ctr.ID()) + err2 := s.StorageRuntimeServer().DeleteContainer(ctr.ID()) + if err2 != nil { + log.Warnf(ctx, "Failed to cleanup container storage: %v", err2) } - }() + }) s.addContainer(newContainer) - defer func() { - if retErr != nil { - log.Infof(ctx, "createCtr: removing container %s", newContainer.ID()) - s.removeContainer(newContainer) - } - }() + cleanupFuncs = append(cleanupFuncs, func() { + log.Infof(ctx, "createCtr: removing container %s", newContainer.ID()) + s.removeContainer(newContainer) + }) if err := s.CtrIDIndex().Add(ctr.ID()); err != nil { return nil, err } - defer func() { - if retErr != nil { - log.Infof(ctx, "createCtr: deleting container ID %s from idIndex", ctr.ID()) - if err := s.CtrIDIndex().Delete(ctr.ID()); err != nil { - log.Warnf(ctx, "couldn't delete ctr id %s from idIndex", ctr.ID()) - } + cleanupFuncs = append(cleanupFuncs, func() { + log.Infof(ctx, "createCtr: deleting container ID %s from idIndex", ctr.ID()) + if err := s.CtrIDIndex().Delete(ctr.ID()); err != nil { + log.Warnf(ctx, "couldn't delete ctr id %s from idIndex", ctr.ID()) } - }() + }) mappings, err := s.getSandboxIDMappings(sb) if err != nil { @@ -529,14 +532,14 @@ func (s *Server) CreateContainer(ctx context.Context, req *pb.CreateContainerReq if err := s.createContainerPlatform(newContainer, sb.CgroupParent(), mappings); err != nil { return nil, err } - defer func() { + cleanupFuncs = append(cleanupFuncs, func() { if retErr != nil { log.Infof(ctx, "createCtr: removing container ID %s from runtime", ctr.ID()) if err := s.Runtime().DeleteContainer(newContainer); err != nil { log.Warnf(ctx, "failed to delete container in runtime %s: %v", ctr.ID(), err) } } - }() + }) if err := s.ContainerStateToDisk(newContainer); err != nil { log.Warnf(ctx, "unable to write containers %s state to disk: %v", newContainer.ID(), err) diff --git a/server/sandbox_run_linux.go b/server/sandbox_run_linux.go index 26071e63cbc..6e759aabaab 100644 --- a/server/sandbox_run_linux.go +++ b/server/sandbox_run_linux.go @@ -285,7 +285,6 @@ func (s *Server) getSandboxIDMappings(sb *libsandbox.Sandbox) (*idtools.IDMappin return mappings, nil } -// nolint:gocyclo func (s *Server) runPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest) (resp *pb.RunPodSandboxResponse, retErr error) { s.updateLock.RLock() defer s.updateLock.RUnlock() @@ -308,16 +307,25 @@ func (s *Server) runPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest return nil, errors.Wrap(err, "setting pod sandbox name and id") } + cleanupFuncs := make([]func(), 0) + defer func() { + // no error, no need to cleanup + if retErr == nil { + return + } + for i := len(cleanupFuncs) - 1; i >= 0; i-- { + cleanupFuncs[i]() + } + }() + if _, err := s.ReservePodName(sbox.ID(), sbox.Name()); err != nil { return nil, errors.Wrap(err, "Kubelet may be retrying requests that are timing out in CRI-O due to system load") } - defer func() { - if retErr != nil { - log.Infof(ctx, "runSandbox: releasing pod sandbox name: %s", sbox.Name()) - s.ReleasePodName(sbox.Name()) - } - }() + cleanupFuncs = append(cleanupFuncs, func() { + log.Infof(ctx, "runSandbox: releasing pod sandbox name: %s", sbox.Name()) + s.ReleasePodName(sbox.Name()) + }) kubeAnnotations := sbox.Config().GetAnnotations() @@ -338,12 +346,10 @@ func (s *Server) runPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest if err != nil { return nil, err } - defer func() { - if retErr != nil { - log.Infof(ctx, "runSandbox: releasing container name: %s", containerName) - s.ReleaseContainerName(containerName) - } - }() + cleanupFuncs = append(cleanupFuncs, func() { + log.Infof(ctx, "runSandbox: releasing container name: %s", containerName) + s.ReleaseContainerName(containerName) + }) var labelOptions []string securityContext := sbox.Config().GetLinux().GetSecurityContext() @@ -378,14 +384,12 @@ func (s *Server) runPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest if err != nil { return nil, fmt.Errorf("error creating pod sandbox with name %q: %v", sbox.Name(), err) } - defer func() { - if retErr != nil { - log.Infof(ctx, "runSandbox: removing pod sandbox from storage: %s", sbox.ID()) - if err2 := s.StorageRuntimeServer().RemovePodSandbox(sbox.ID()); err2 != nil { - log.Warnf(ctx, "couldn't cleanup pod sandbox %q: %v", sbox.ID(), err2) - } + cleanupFuncs = append(cleanupFuncs, func() { + log.Infof(ctx, "runSandbox: removing pod sandbox from storage: %s", sbox.ID()) + if err2 := s.StorageRuntimeServer().RemovePodSandbox(sbox.ID()); err2 != nil { + log.Warnf(ctx, "could not cleanup pod sandbox %q: %v", sbox.ID(), err2) } - }() + }) // set log directory logDir := sbox.Config().GetLogDirectory() @@ -394,7 +398,7 @@ func (s *Server) runPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest } // This should always be absolute from k8s. if !filepath.IsAbs(logDir) { - return nil, fmt.Errorf("requested logDir for sbox id %s is a relative path: %s", sbox.ID(), logDir) + return nil, fmt.Errorf("requested logDir for sbox ID %s is a relative path: %s", sbox.ID(), logDir) } if err := os.MkdirAll(logDir, 0o700); err != nil { return nil, err @@ -535,14 +539,12 @@ func (s *Server) runPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest return nil, err } pathsToChown = append(pathsToChown, shmPath) - defer func() { - if retErr != nil { - log.Infof(ctx, "runSandbox: unmounting shmPath for sandbox %s", sbox.ID()) - if err2 := unix.Unmount(shmPath, unix.MNT_DETACH); err2 != nil { - log.Warnf(ctx, "failed to unmount shm for pod: %v", err2) - } + cleanupFuncs = append(cleanupFuncs, func() { + log.Infof(ctx, "runSandbox: unmounting shmPath for sandbox %s", sbox.ID()) + if err2 := unix.Unmount(shmPath, unix.MNT_DETACH); err2 != nil { + log.Warnf(ctx, "failed to unmount shm for sandbox: %v", err2) } - }() + }) } mnt := spec.Mount{ @@ -563,14 +565,12 @@ func (s *Server) runPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest return nil, err } - defer func() { - if retErr != nil { - log.Infof(ctx, "runSandbox: deleting container ID from idIndex for sandbox %s", sbox.ID()) - if err2 := s.CtrIDIndex().Delete(sbox.ID()); err2 != nil { - log.Warnf(ctx, "couldn't delete ctr id %s from idIndex", sbox.ID()) - } + cleanupFuncs = append(cleanupFuncs, func() { + log.Infof(ctx, "runSandbox: deleting container ID from idIndex for sandbox %s", sbox.ID()) + if err2 := s.CtrIDIndex().Delete(sbox.ID()); err2 != nil { + log.Warnf(ctx, "could not delete ctr id %s from idIndex", sbox.ID()) } - }() + }) // set log path inside log directory logPath := filepath.Join(logDir, sbox.ID()+".log") @@ -656,27 +656,23 @@ func (s *Server) runPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest if err := s.addSandbox(sb); err != nil { return nil, err } - defer func() { - if retErr != nil { - log.Infof(ctx, "runSandbox: removing pod sandbox %s", sbox.ID()) - if err := s.removeSandbox(sbox.ID()); err != nil { - log.Warnf(ctx, "could not remove pod sandbox: %v", err) - } + cleanupFuncs = append(cleanupFuncs, func() { + log.Infof(ctx, "runSandbox: removing pod sandbox %s", sbox.ID()) + if err := s.removeSandbox(sbox.ID()); err != nil { + log.Warnf(ctx, "could not remove pod sandbox: %v", err) } - }() + }) if err := s.PodIDIndex().Add(sbox.ID()); err != nil { return nil, err } - defer func() { - if retErr != nil { - log.Infof(ctx, "runSandbox: deleting pod ID %s from idIndex", sbox.ID()) - if err := s.PodIDIndex().Delete(sbox.ID()); err != nil { - log.Warnf(ctx, "couldn't delete pod id %s from idIndex", sbox.ID()) - } + cleanupFuncs = append(cleanupFuncs, func() { + log.Infof(ctx, "runSandbox: deleting pod ID %s from idIndex", sbox.ID()) + if err := s.PodIDIndex().Delete(sbox.ID()); err != nil { + log.Warnf(ctx, "could not delete pod id %s from idIndex", sbox.ID()) } - }() + }) for k, v := range kubeAnnotations { g.AddAnnotation(k, v) @@ -689,18 +685,16 @@ func (s *Server) runPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest sysctls := s.configureGeneratorForSysctls(ctx, g, hostNetwork, hostIPC, req.GetConfig().GetLinux().GetSysctls()) // set up namespaces - cleanupFuncs, err := s.configureGeneratorForSandboxNamespaces(hostNetwork, hostIPC, hostPID, sandboxIDMappings, sysctls, sb, g) + nsCleanupFuncs, err := s.configureGeneratorForSandboxNamespaces(hostNetwork, hostIPC, hostPID, sandboxIDMappings, sysctls, sb, g) // We want to cleanup after ourselves if we are managing any namespaces and fail in this function. - defer func() { - if retErr != nil { - log.Infof(ctx, "runSandbox: cleaning up namespaces after failing to run sandbox %s", sbox.ID()) - for idx := range cleanupFuncs { - if err2 := cleanupFuncs[idx](); err2 != nil { - log.Infof(ctx, "runSandbox: failed to cleanup namespace: %s", err2.Error()) - } + cleanupFuncs = append(cleanupFuncs, func() { + log.Infof(ctx, "runSandbox: cleaning up namespaces after failing to run sandbox %s", sbox.ID()) + for idx := range nsCleanupFuncs { + if err2 := nsCleanupFuncs[idx](); err2 != nil { + log.Infof(ctx, "runSandbox: failed to cleanup namespace: %s", err2.Error()) } } - }() + }) if err != nil { return nil, err } @@ -714,14 +708,12 @@ func (s *Server) runPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest if err != nil { return nil, err } - defer func() { - if retErr != nil { - log.Infof(ctx, "runSandbox: in manageNSLifecycle, stopping network for sandbox %s", sb.ID()) - if err2 := s.networkStop(ctx, sb); err2 != nil { - log.Errorf(ctx, "error stopping network on cleanup: %v", err2) - } + cleanupFuncs = append(cleanupFuncs, func() { + log.Infof(ctx, "runSandbox: in manageNSLifecycle, stopping network for sandbox %s", sb.ID()) + if err2 := s.networkStop(ctx, sb); err2 != nil { + log.Errorf(ctx, "error stopping network on cleanup: %v", err2) } - }() + }) if result != nil { resultCurrent, err := current.NewResultFromResult(result) if err != nil { @@ -746,14 +738,12 @@ func (s *Server) runPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest if err != nil { return nil, fmt.Errorf("failed to mount container %s in pod sandbox %s(%s): %v", containerName, sb.Name(), sbox.ID(), err) } - defer func() { - if retErr != nil { - log.Infof(ctx, "runSandbox: stopping storage container for sandbox %s", sbox.ID()) - if err2 := s.StorageRuntimeServer().StopContainer(sbox.ID()); err2 != nil { - log.Warnf(ctx, "couldn't stop storage container: %v: %v", sbox.ID(), err2) - } + cleanupFuncs = append(cleanupFuncs, func() { + log.Infof(ctx, "runSandbox: stopping storage container for sandbox %s", sbox.ID()) + if err2 := s.StorageRuntimeServer().StopContainer(sbox.ID()); err2 != nil { + log.Warnf(ctx, "could not stop storage container: %v: %v", sbox.ID(), err2) } - }() + }) g.AddAnnotation(annotations.MountPoint, mountPoint) hostnamePath := fmt.Sprintf("%s/hostname", podContainer.RunDir) @@ -881,12 +871,10 @@ func (s *Server) runPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest } s.addInfraContainer(container) - defer func() { - if retErr != nil { - log.Infof(ctx, "runSandbox: removing infra container %s", container.ID()) - s.removeInfraContainer(container) - } - }() + cleanupFuncs = append(cleanupFuncs, func() { + log.Infof(ctx, "runSandbox: removing infra container %s", container.ID()) + s.removeInfraContainer(container) + }) if sandboxIDMappings != nil { rootPair := sandboxIDMappings.RootPair() @@ -908,26 +896,24 @@ func (s *Server) runPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest return nil, err } - defer func() { - if retErr != nil { - // Clean-up steps from RemovePodSanbox - log.Infof(ctx, "runSandbox: stopping container %s", container.ID()) - if err2 := s.Runtime().StopContainer(ctx, container, int64(10)); err2 != nil { - log.Warnf(ctx, "failed to stop container %s: %v", container.Name(), err2) - } - if err2 := s.Runtime().WaitContainerStateStopped(ctx, container); err2 != nil { - log.Warnf(ctx, "failed to get container 'stopped' status %s in pod sandbox %s: %v", container.Name(), sb.ID(), err2) - } - log.Infof(ctx, "runSandbox: deleting container %s", container.ID()) - if err2 := s.Runtime().DeleteContainer(container); err2 != nil { - log.Warnf(ctx, "failed to delete container %s in pod sandbox %s: %v", container.Name(), sb.ID(), err2) - } - log.Infof(ctx, "runSandbox: writing container %s state to disk", container.ID()) - if err2 := s.ContainerStateToDisk(container); err2 != nil { - log.Warnf(ctx, "failed to write container state %s in pod sandbox %s: %v", container.Name(), sb.ID(), err2) - } + cleanupFuncs = append(cleanupFuncs, func() { + // Clean-up steps from RemovePodSanbox + log.Infof(ctx, "runSandbox: stopping container %s", container.ID()) + if err2 := s.Runtime().StopContainer(ctx, container, int64(10)); err2 != nil { + log.Warnf(ctx, "failed to stop container %s: %v", container.Name(), err2) } - }() + if err2 := s.Runtime().WaitContainerStateStopped(ctx, container); err2 != nil { + log.Warnf(ctx, "failed to get container 'stopped' status %s in pod sandbox %s: %v", container.Name(), sb.ID(), err2) + } + log.Infof(ctx, "runSandbox: deleting container %s", container.ID()) + if err2 := s.Runtime().DeleteContainer(container); err2 != nil { + log.Warnf(ctx, "failed to delete container %s in pod sandbox %s: %v", container.Name(), sb.ID(), err2) + } + log.Infof(ctx, "runSandbox: writing container %s state to disk", container.ID()) + if err2 := s.ContainerStateToDisk(container); err2 != nil { + log.Warnf(ctx, "failed to write container state %s in pod sandbox %s: %v", container.Name(), sb.ID(), err2) + } + }) if err := s.ContainerStateToDisk(container); err != nil { log.Warnf(ctx, "unable to write containers %s state to disk: %v", container.ID(), err) @@ -938,14 +924,12 @@ func (s *Server) runPodSandbox(ctx context.Context, req *pb.RunPodSandboxRequest if err != nil { return nil, err } - defer func() { - if retErr != nil { - log.Infof(ctx, "runSandbox: in not manageNSLifecycle, stopping network for sandbox %s", sb.ID()) - if err2 := s.networkStop(ctx, sb); err2 != nil { - log.Errorf(ctx, "error stopping network on cleanup: %v", err2) - } + cleanupFuncs = append(cleanupFuncs, func() { + log.Infof(ctx, "runSandbox: stopping network for sandbox %s when not manageNSLifecycle", sb.ID()) + if err2 := s.networkStop(ctx, sb); err2 != nil { + log.Errorf(ctx, "error stopping network on cleanup: %v", err2) } - }() + }) } for idx, ip := range ips {