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
}