service-account-issue

在配合使用高版本k8s和低版本k8s的时候遇到了serviceAccount报错的问题 No API token found for service account "default", retry after the token is automatically created and added to the service account

大概看了眼代码,k8s的apiserver在创建pod的时候会看这个pod有没有自己指定serviceaccount这个项目,如果没有的话就用默认的default serviceaccount ,然后mount到pod的/var/run/secrets/kubernetes.io/serviceaccount

其中有个步骤是去找这个serviceAccount的secret信息,但是很不幸的是我用的是高版本的apiserver和低版本的controller,没有自动创建这个出来。而且其实我也用不到这个功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

func (s *serviceAccount) mountServiceAccountToken(serviceAccount *api.ServiceAccount, pod *api.Pod) error {
// Find the name of a referenced ServiceAccountToken secret we can mount
serviceAccountToken, err := s.getReferencedServiceAccountToken(serviceAccount)
if err != nil {
return fmt.Errorf("Error looking up service account token for %s/%s: %v", serviceAccount.Namespace, serviceAccount.Name, err)
}
if len(serviceAccountToken) == 0 {
// We don't have an API token to mount, so return
if s.RequireAPIToken {
// If a token is required, this is considered an error
err := errors.NewServerTimeout(schema.GroupResource{Resource: "serviceaccounts"}, "create pod", 1)
err.ErrStatus.Message = fmt.Sprintf("No API token found for service account %q, retry after the token is automatically created and added to the service account", serviceAccount.Name)
return err
}
return nil
}

// Find the volume and volume name for the ServiceAccountTokenSecret if it already exists
tokenVolumeName := ""
hasTokenVolume := false
allVolumeNames := sets.NewString()
for _, volume := range pod.Spec.Volumes {
allVolumeNames.Insert(volume.Name)
if volume.Secret != nil && volume.Secret.SecretName == serviceAccountToken {
tokenVolumeName = volume.Name
hasTokenVolume = true
break
}

也看到有个方法
src/k8s.io/kubernetes/plugin/pkg/admission/serviceaccount/admission.go
可以给这个namespace下的serviceaccount加个

1
2
3
4
5
6
7
8
9
10
11
12
13

func shouldAutomount(sa *api.ServiceAccount, pod *api.Pod) bool {
// Pod's preference wins
if pod.Spec.AutomountServiceAccountToken != nil {
return *pod.Spec.AutomountServiceAccountToken
}
// Then service account's
if sa.AutomountServiceAccountToken != nil {
return *sa.AutomountServiceAccountToken
}
// Default to true for backwards compatibility
return true
}

https://tonybai.com/2017/03/03/access-api-server-from-a-pod-through-serviceaccount/