func putExitFile()

in pkg/csi_driver/utils.go [313:374]


func putExitFile(pod *corev1.Pod, targetPath string) error {
	podIsTerminating := pod.DeletionTimestamp != nil
	podRestartPolicyIsNever := pod.Spec.RestartPolicy == corev1.RestartPolicyNever
	podRestartPolicyIsOnFailure := pod.Spec.RestartPolicy == corev1.RestartPolicyOnFailure

	// Check if all the containers besides the sidecar container exited
	if podRestartPolicyIsOnFailure || podRestartPolicyIsNever || podIsTerminating {
		if len(pod.Status.ContainerStatuses) == 0 {
			return nil
		}

		for _, cs := range pod.Status.ContainerStatuses {
			switch {
			// skip the sidecar container itself
			case cs.Name == webhook.GcsFuseSidecarName:
				continue

			// If the Pod is terminating, the container status from Kubernetes API is not reliable
			// because of the issue: https://github.com/kubernetes/kubernetes/issues/106896,
			// so container status checking is skipped.
			// Directly pulling the container status from CRI is not acceptable due to security concerns.
			// This will cause the issue https://github.com/GoogleCloudPlatform/gcs-fuse-csi-driver/issues/168.
			// The issue will be solved by the Kubernetes native sidecar container feature.
			case podIsTerminating:
				return nil

			// If any container is in Running or Waiting state,
			// do not terminate the gcsfuse sidecar container.
			case cs.State.Running != nil || cs.State.Waiting != nil:
				return nil

			// If the Pod RestartPolicy is OnFailure,
			// when the container terminated with a non-zero exit code,
			// the container may restart. Do not terminate the gcsfuse sidecar container.
			// When the Pod belongs to a Job, and the container restart count reaches the Job backoffLimit,
			// the Pod will be directly terminated, which goes to the first case.
			case podRestartPolicyIsOnFailure && cs.State.Terminated != nil && cs.State.Terminated.ExitCode != 0:
				return nil
			}
		}

		klog.V(4).Infof("[Pod %v/%v, UID %v] all the other containers terminated in the Pod, put the exit file.", pod.Namespace, pod.Name, pod.UID)
		emptyDirBasePath, err := util.PrepareEmptyDir(targetPath, false)
		if err != nil {
			return fmt.Errorf("failed to get emptyDir path: %w", err)
		}

		exitFilePath := filepath.Dir(emptyDirBasePath) + "/exit"
		f, err := os.Create(exitFilePath)
		if err != nil {
			return fmt.Errorf("failed to put the exit file: %w", err)
		}
		f.Close()

		err = os.Chown(exitFilePath, webhook.NobodyUID, webhook.NobodyGID)
		if err != nil {
			return fmt.Errorf("failed to change ownership on the exit file: %w", err)
		}
	}

	return nil
}