diff --git a/cri/v1alpha2/cri.go b/cri/v1alpha2/cri.go index 127ccd4ad8..4f6d390762 100644 --- a/cri/v1alpha2/cri.go +++ b/cri/v1alpha2/cri.go @@ -268,29 +268,28 @@ 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 + networkNamespaceMode := config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetNetwork() // 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 networkNamespaceMode != runtime.NamespaceMode_NODE { + netnsPath, err := c.setupPodNetwork(ctx, id, config) if err != nil { return nil, err } + defer func() { + // Teardown network if an error is returned. + if retErr != nil { + teardownNetErr := c.CniMgr.TearDownPodNetwork(&ocicni.PodNetwork{ + Name: config.GetMetadata().GetName(), + Namespace: config.GetMetadata().GetNamespace(), + ID: id, + NetNS: netnsPath, + PortMappings: toCNIPortMappings(config.GetPortMappings()), + }) + if teardownNetErr != nil { + logrus.Errorf("failed to destroy network for sandbox %q: %v", id, teardownNetErr) + } + } + }() } sandboxMeta := &SandboxMeta{ @@ -319,7 +318,64 @@ 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. + 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) + } + + var err error + 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. + var netnsPath string + networkNamespaceMode := sandboxMeta.Config.GetLinux().GetSecurityContext().GetNamespaceOptions().GetNetwork() + // If it is in host network, no need to configure the network of sandbox. + if networkNamespaceMode != runtime.NamespaceMode_NODE { + netnsPath, err := c.setupPodNetwork(ctx, podSandboxID, sandboxMeta.Config) + if err != nil { + return nil, err + } + defer func() { + // Teardown network if an error is returned. + if err != nil { + teardownNetErr := c.CniMgr.TearDownPodNetwork(&ocicni.PodNetwork{ + Name: sandboxMeta.Config.GetMetadata().GetName(), + Namespace: sandboxMeta.Config.GetMetadata().GetNamespace(), + ID: podSandboxID, + NetNS: netnsPath, + PortMappings: toCNIPortMappings(sandboxMeta.Config.GetPortMappings()), + }) + if teardownNetErr != nil { + logrus.Errorf("failed to destroy network for sandbox %q: %v", podSandboxID, teardownNetErr) + } + } + }() + } + + // 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..8d8cb1ef40 100644 --- a/cri/v1alpha2/cri_utils.go +++ b/cri/v1alpha2/cri_utils.go @@ -448,6 +448,32 @@ 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, config *runtime.PodSandboxConfig) (string, error) { + 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) + } + + 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 "", err + } + + return netnsPath, nil +} + // 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 90a7abf53d..d1465f4259 100644 --- a/docs/kubernetes/pouch_cri_api_changelog.md +++ b/docs/kubernetes/pouch_cri_api_changelog.md @@ -8,6 +8,7 @@ * [ImageStatus](#imagestatus "ImageStatus()") * [CreateContainer](#createcontainer "CreateContainer()") * [RemoveVolume](#removevolume "RemoveVolume()") + * [StartPodSandbox](#startpodsandbox "StartPodSandbox()") * [Pull Request](#pull-request) ## Overview @@ -30,7 +31,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 +282,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,9 +311,40 @@ 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) + feature: extend cri apis for remove volume [#2124](https://github.com/alibaba/pouch/pull/2124) + feature: extend cri apis for support quotaID [#2138](https://github.com/alibaba/pouch/pull/2138) + feature: extend cri apis for get envs [#2163](https://github.com/alibaba/pouch/pull/2163) ++ feature: extend cri apis for support StartPodSandbox [#2242](https://github.com/alibaba/pouch/pull/2242) +