Change:
<!-- This form is for bug reports and feature requests ONLY! If you're looking for help check and the . If the matter is security related, please disclose it privately via --Is this a BUG REPORT or FEATURE REQUEST?: /kind bug What happened: The code creates a pod directly, without waiting for the service account secret to be available. Depending on timing, this can fail with a error. What you expected to happen: It should use a DaemonSet instead, then the daemon set controller will ensure that the pod gets created eventually. [Edit: when implementing the fix, I found it easier and less intrusive to just retry pod creation.] How to reproduce it (as minimally and precisely as possible): It's not possible to trigger the failing race condition reliably. I've seen it a few times on my own cluster. Anything else we need to know?: Originally discussed in and in the CSI working group meeting on Monday, September 17th ().
/sig storage

Discussion:
return p } <ins> // CreateEventually retries pod creation for a while before failing // the test with the most recent error. This mimicks the behavior // of a controller (like the one for DaemonSet) and is necessary // because pod creation can fail while its service account is still // getting provisioned // (https://github.com/kubernetes/kubernetes/issues/68776). // // Both the timeout and polling interval are configurable as optional // arguments: // - The first optional argument is the timeout. // - The second optional argument is the polling interval. // // Both intervals can either be specified as time.Duration, parsable // duration strings or as floats/integers. In the last case they are // interpreted as seconds. func (c *PodClient) CreateEventually(pod *v1.Pod, opts ...interface{}) *v1.Pod { c.mungeSpec(pod) var ret *v1.Pod Eventually(func() error { p, err := c.PodInterface.Create(pod) ret = p return err }, opts...).ShouldNot(HaveOccurred(), "Failed to create %q pod", pod.GetName()) return ret } </ins> // CreateSync creates a new pod according to the framework specifications in the given namespace, and waits for it to start. func (c *PodClient) CreateSyncInNamespace(pod *v1.Pod, namespace string) *v1.Pod { p := c.Create(pod)

f *framework.Framework, sa *v1.ServiceAccount, ) *v1.Pod { <del> podClient := client.CoreV1().Pods(config.Namespace) </del> priv := true mountPropagation := v1.MountPropagationBidirectional hostPathType := v1.HostPathDirectoryOrCreate

return nil } <del> ret, err := podClient.Create(pod) if err != nil { framework.ExpectNoError(err, "Failed to create %q pod: %v", pod.GetName(), err) } </del> <ins> // Creating the pod can fail initially while the service // account's secret isn't provisioned yet ('No API token found // for service account "csi-service-account", retry after the // token is automatically created and added to the service // account', see https://github.com/kubernetes/kubernetes/issues/68776). // We could use a DaemonSet, but then the name of the csi-pod changes // during each test run. It's simpler to just try for a while here. podClient := f.PodClient() ret := podClient.CreateEventually(pod) </ins> // Wait for pod to come up framework.ExpectNoError(framework.WaitForPodRunningInNamespace(client, ret))