Kubernetes通知者因未经授权而失败

xzlaal3s  于 2023-03-07  发布在  Kubernetes
关注(0)|答案(1)|浏览(98)

我尝试在EKS集群外构建Kubernetes informer,我使用aws-iam-authenticator插件为EKS集群提供基于exec的凭据。为了让插件工作,我假设了一个IAM角色,并将AWS IAM凭据作为环境变量传递。
问题是这些凭据在一小时后过期,并导致通知者失败
E0301 23:34:22.167817 582运行时间.go:79]观察到死机:错误。状态错误{ErrStatus:v1.Status{TypeMeta:v1.TypeMeta{种类:“",API版本:“"},ListMeta:v1.ListMeta{SelfLink:“",资源版本:“",继续:“",剩余项计数:(* int 64)(nil)},状态:“失败”,消息:“服务器已要求客户端提供凭据(获取pod)",原因:“未经授权”,详细信息:(*v1.StatusDetails)(0xc 0005 b 0300),代码:401}}(服务器已要求客户端提供凭据(获取pod))(& E)
是否有更好的方法让ClientConfigaws-iam-authenticator刷新凭据?
下面是我的代码的大致框架:

credentialsProvider := aws.NewCredentialsCache(stscreds.NewWebIdentityRoleProvider(...))
creds, err := credentialsProvider.Retrieve(ctx)

config := clientcmdapi.NewConfig()
// ...
config.AuthInfos["eks"] = &clientcmdapi.AuthInfo{
    Exec: &clientcmdapi.ExecConfig{
        Command: "aws-iam-authenticator",
        Args: []string{
            "token",
            "-i",
            clusterName,
        },
        // These env vars are static! :(
        Env: []clientcmdapi.ExecEnvVar{
            {
                Name:  "AWS_ACCESS_KEY_ID",
                Value: creds.AccessKeyID,
            },
            {
                Name:  "AWS_SECRET_ACCESS_KEY",
                Value: creds.SecretAccessKey,
            },
            {
                Name:  "AWS_SESSION_TOKEN",
                Value: creds.SessionToken,
            },
        },
        APIVersion:      "client.authentication.k8s.io/v1beta1",
        InteractiveMode: clientcmdapi.NeverExecInteractiveMode,
    },
}

restConfig, err := config.ClientConfig()
clientset, err = kubernetes.NewForConfig(restConfig)

informerFactory := informers.NewSharedInformerFactory(clientset, time.Second*30)
podInformer := cw.informerFactory.Core().V1().Pods().Informer()

下面是我发现的几个类似的线程:

shyt4zoc

shyt4zoc1#

我的解决方案是创建一个将凭据写入到文件中的命令,然后创建一个后台线程来刷新该文件,然后通过环境变量AWS_SHARED_CREDENTIALS_FILE传递tell aws-iam-authenticator从文件中读取凭据。
使用AWS_WEB_IDENTITY_TOKEN_FILE也可以保存一些步骤,但我没有进一步研究。
更新后的代码如下所示

func updateCredentials(ctx context.Context) {
    creds, err := c.credentialsProvider.Retrieve(ctx)
    s := fmt.Sprintf(`[default]
aws_access_key_id=%s
aws_secret_access_key=%s
aws_session_token=%s`, creds.AccessKeyID, creds.SecretAccessKey, creds.SessionToken)
    err = os.WriteFile(credentialsFile.Name(), []byte(s), 0666)
    return nil
}

func updateCredentialsLoop(ctx context.Context) {
    for {
        err := updateCredentials(ctx)
        time.Sleep(5*time.Minute)
    }
}

credentialsProvider := aws.NewCredentialsCache(stscreds.NewWebIdentityRoleProvider(...))

credentialsFile, err := os.CreateTemp("", "credentials")
updateCredentials(ctx)
go updateCredentialsLoop(ctx)

config := clientcmdapi.NewConfig()
// ...
config.AuthInfos["eks"] = &clientcmdapi.AuthInfo{
    Exec: &clientcmdapi.ExecConfig{
        Command: "aws-iam-authenticator",
        Args: []string{
            "token",
            "-i",
            clusterName,
        },
        Env: []clientcmdapi.ExecEnvVar{
            {
                Name:  "AWS_SHARED_CREDENTIALS_FILE",
                Value: credentialsFile.Name(),
            },
        },
        APIVersion:      "client.authentication.k8s.io/v1beta1",
        InteractiveMode: clientcmdapi.NeverExecInteractiveMode,
    },
}

restConfig, err := config.ClientConfig()
clientset, err = kubernetes.NewForConfig(restConfig)

informerFactory := informers.NewSharedInformerFactory(clientset, time.Second*30)
podInformer := cw.informerFactory.Core().V1().Pods().Informer()

相关问题