diff --git a/cri/v1alpha2/cri.go b/cri/v1alpha2/cri.go index 4f58405932..5a4a5ec321 100644 --- a/cri/v1alpha2/cri.go +++ b/cri/v1alpha2/cri.go @@ -251,30 +251,9 @@ func (c *CriManager) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox } // Step 4: Setup networking for the sandbox. - var netnsPath string - securityContext := config.GetLinux().GetSecurityContext() - hostNet := securityContext.GetNamespaceOptions().GetNetwork() == runtime.NamespaceMode_NODE - // If it is in host network, no need to configure the network of sandbox. - if !hostNet { - container, err := c.ContainerMgr.Get(ctx, id) - if err != nil { - return nil, err - } - netnsPath = containerNetns(container) - if netnsPath == "" { - return nil, fmt.Errorf("failed to find network namespace path for sandbox %q", id) - } - - err = c.CniMgr.SetUpPodNetwork(&ocicni.PodNetwork{ - Name: config.GetMetadata().GetName(), - Namespace: config.GetMetadata().GetNamespace(), - ID: id, - NetNS: netnsPath, - PortMappings: toCNIPortMappings(config.GetPortMappings()), - }) - if err != nil { - return nil, err - } + netnsPath, err := c.setupPodNetwork(ctx, id, config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetNetwork(), config) + if err != nil { + return nil, err } sandboxMeta := &SandboxMeta{ @@ -303,7 +282,44 @@ func (c *CriManager) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox // and we should reconfigure it with network plugin which will make sure it reacquire its original network configuration, // like IP address. func (c *CriManager) StartPodSandbox(ctx context.Context, r *runtime.StartPodSandboxRequest) (*runtime.StartPodSandboxResponse, error) { - // TODO Complete the details of function. + var err error + podSandboxID := r.GetPodSandboxId() + + // start PodSandbox. + startErr := c.ContainerMgr.Start(ctx, podSandboxID, &apitypes.ContainerStartOptions{}) + if startErr != nil { + return nil, fmt.Errorf("failed to start podSandbox %q: %v", podSandboxID, startErr) + } + + defer func() { + if err != nil { + stopErr := c.ContainerMgr.Stop(ctx, podSandboxID, defaultStopTimeout) + if stopErr != nil { + logrus.Errorf("failed to stop sandbox %q: %v", podSandboxID, stopErr) + } + } + }() + + // get the sandbox's meta data. + res, err := c.SandboxStore.Get(podSandboxID) + if err != nil { + return nil, fmt.Errorf("failed to get metadata of %q from SandboxStore: %v", podSandboxID, err) + } + sandboxMeta := res.(*SandboxMeta) + + // setup networking for the sandbox. + netnsPath, err := c.setupPodNetwork(ctx, podSandboxID, sandboxMeta.Config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetNetwork(), sandboxMeta.Config) + if err != nil { + return nil, err + } + + // update sandboxMeta + sandboxMeta.NetNSPath = netnsPath + err = c.SandboxStore.Put(sandboxMeta) + if err != nil { + return nil, err + } + return &runtime.StartPodSandboxResponse{}, nil } diff --git a/cri/v1alpha2/cri_utils.go b/cri/v1alpha2/cri_utils.go index 2b6d0013d5..95cdd3d759 100644 --- a/cri/v1alpha2/cri_utils.go +++ b/cri/v1alpha2/cri_utils.go @@ -448,6 +448,50 @@ func setupSandboxFiles(sandboxRootDir string, config *runtime.PodSandboxConfig) return nil } +// setupPodNetwork sets up the network of PodSandbox and return the netnsPath of PodSandbox +// and do nothing when networkNamespaceMode equals runtime.NamespaceMode_NODE. +func (c *CriManager) setupPodNetwork(ctx context.Context, id string, networkNamespaceMode runtime.NamespaceMode, config *runtime.PodSandboxConfig) (string, error) { + var netnsPath string + hostNet := networkNamespaceMode == runtime.NamespaceMode_NODE + // If it is in host network, no need to configure the network of sandbox. + if hostNet { + return netnsPath, nil + } + + container, err := c.ContainerMgr.Get(ctx, id) + if err != nil { + return "", err + } + netnsPath = containerNetns(container) + if netnsPath == "" { + return "", fmt.Errorf("failed to find network namespace path for sandbox %q", id) + } + + retErr := c.CniMgr.SetUpPodNetwork(&ocicni.PodNetwork{ + Name: config.GetMetadata().GetName(), + Namespace: config.GetMetadata().GetNamespace(), + ID: id, + NetNS: netnsPath, + PortMappings: toCNIPortMappings(config.GetPortMappings()), + }) + if retErr == nil { + return netnsPath, nil + } + + // Teardown network if an error is returned. + err = c.CniMgr.TearDownPodNetwork(&ocicni.PodNetwork{ + Name: config.GetMetadata().GetName(), + Namespace: config.GetMetadata().GetNamespace(), + ID: id, + NetNS: netnsPath, + PortMappings: toCNIPortMappings(config.GetPortMappings()), + }) + if err != nil { + logrus.Errorf("failed to destroy network for sandbox %q", id) + } + return "", retErr +} + // Container related tool functions. func makeContainerName(s *runtime.PodSandboxConfig, c *runtime.ContainerConfig) string { diff --git a/docs/kubernetes/pouch_cri_api_changelog.md b/docs/kubernetes/pouch_cri_api_changelog.md index d258871c9b..d5c412b53a 100644 --- a/docs/kubernetes/pouch_cri_api_changelog.md +++ b/docs/kubernetes/pouch_cri_api_changelog.md @@ -30,7 +30,10 @@ Kubernetes Version: V1.10.0+ 4. Support to the ability to acquire the envs of the Container. - Scenario: - In the Upgrade process, the env of the new container needs to remain consistent with that of the old container, so the envs of the old container needs to be read. - +5. Support to the ability to start the PodSandbox specified and setup the network. + - Scenario: + - It will fail to get IP after PodSandbox restarts because of the external factors such as shutdown the host. + # The Changes Of CRI API ## UpdateContainerResources @@ -278,7 +281,8 @@ message ContainerConfig { + Provides an interface for removing volume. + The containerstatus interface supports querying volume by name. -+ The changes need to be made in the proto file are as follows: + +The changes need to be made in the proto file are as follows: ``` service VolumeService { @@ -306,6 +310,35 @@ message Mount { ``` +## StartPodSandbox + +### What To Solve? + ++ StartPodSandbox restarts a sandbox pod which was stopped by accident and setup the network with network plugin. + +### Modification + ++ Provides an interface for starting PodSandbox specified. + +The changes need to be made in the proto file are as follows: + +``` +service RuntimeService { +... + // Start a sandbox pod which was forced to stop by external factors. + // Network plugin returns same IPs when input same pod names and namespaces + rpc StartPodSandbox(StartPodSandboxRequest) returns (StartPodSandboxResponse) {} +... +} + +message StartPodSandboxRequest { + // ID of the PodSandbox to start. + string pod_sandbox_id = 1; +} + +message StartPodSandboxResponse {} +``` + ## Pull Request + feature: extend cri apis for special needs [#1617](https://github.com/alibaba/pouch/pull/1617)