【问题标题】:Unable to obtain kubeconfig of an AWS EKS cluster in Go code无法在 Go 代码中获取 AWS EKS 集群的 kubeconfig
【发布时间】:2020-06-18 04:56:34
【问题描述】:

我创建了一个 AWS EKS 集群。为了获取它的kubeconfig,我通常使用shell运行aws eks update-kubeconfig --name cluster-name --region us-west-2

但是,我现在希望在 Go 中获取 kubeconfig,而不必在 shell 中运行任何东西(目标是在 Go 测试中创建并操作 EKS 集群)。我可以使用以下代码描述 EKS 集群:

package main

import (
    "fmt"

    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/eks"
)

func main() {
    sess := session.Must(session.NewSession(&aws.Config{
        Region: aws.String("us-west-2"),
    }))
    eksSvc := eks.New(sess, aws.NewConfig().WithRegion("us-west-2"))


    clusterOutput, err := eksSvc.DescribeCluster(&eks.DescribeClusterInput{
        Name: aws.String("cluster-name"),
    })
    if err != nil {
        panic(err)
    }
    fmt.Printf("%#v\n", clusterOutput)
}

在那之后,我目前不知道如何获取该集群的 kubeconfig,以便将其与 Kubernetes 的 Go 客户端一起使用,而无需单独使用 aws eks

到目前为止,我已经检查了 AWS 文档、AWS CLI 代码库和 eksctl 代码库,但没有成功。与 EKS 集群的连接仅记录在此网页中,它使用 shell:https://aws.amazon.com/premiumsupport/knowledge-center/eks-cluster-connection/

有什么想法吗?

【问题讨论】:

    标签: amazon-web-services amazon-eks aws-sdk-go


    【解决方案1】:

    一般流程是这样的:

    1. DescribeCluster(正如您所做的那样)并提取一些必要的数据
    2. 使用必要的数据,使用aws-iam-authenticatorpackage token获取令牌
    3. 使用该令牌,在client-go 的帮助下创建一个 Kubernetes 客户端集。
    package main
    
    import (
        "encoding/base64"
        "log"
    
        "github.com/aws/aws-sdk-go/aws"
        "github.com/aws/aws-sdk-go/aws/session"
    
        "github.com/aws/aws-sdk-go/service/eks"
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
        "k8s.io/client-go/kubernetes"
        "k8s.io/client-go/rest"
    
        "sigs.k8s.io/aws-iam-authenticator/pkg/token"
    )
    
    func newClientset(cluster *eks.Cluster) (*kubernetes.Clientset, error) {
        log.Printf("%+v", cluster)
        gen, err := token.NewGenerator(true, false)
        if err != nil {
            return nil, err
        }
        opts := &token.GetTokenOptions{
            ClusterID: aws.StringValue(cluster.Name),
        }
        tok, err := gen.GetWithOptions(opts)
        if err != nil {
            return nil, err
        }
        ca, err := base64.StdEncoding.DecodeString(aws.StringValue(cluster.CertificateAuthority.Data))
        if err != nil {
            return nil, err
        }
        clientset, err := kubernetes.NewForConfig(
            &rest.Config{
                Host:        aws.StringValue(cluster.Endpoint),
                BearerToken: tok.Token,
                TLSClientConfig: rest.TLSClientConfig{
                    CAData: ca,
                },
            },
        )
        if err != nil {
            return nil, err
        }
        return clientset, nil
    }
    
    func main() {
        name := "wonderful-outfit-1583362361"
        region := "us-east-2"
        sess := session.Must(session.NewSession(&aws.Config{
            Region: aws.String(region),
        }))
        eksSvc := eks.New(sess)
    
        input := &eks.DescribeClusterInput{
            Name: aws.String(name),
        }
        result, err := eksSvc.DescribeCluster(input)
        if err != nil {
            log.Fatalf("Error calling DescribeCluster: %v", err)
        }
        clientset, err := newClientset(result.Cluster)
        if err != nil {
            log.Fatalf("Error creating clientset: %v", err)
        }
        nodes, err := clientset.CoreV1().Nodes().List(metav1.ListOptions{})
        if err != nil {
            log.Fatalf("Error getting EKS nodes: %v", err)
        }
        log.Printf("There are %d nodes associated with cluster %s", len(nodes.Items), name)
    }
    

    这是我的 go.mod 版本:

    module github.com/swoldemi/sandbox
    
    go 1.14
    
    require (
        github.com/aws/aws-sdk-go v1.29.19
        k8s.io/apimachinery v0.0.0-20190612125636-6a5db36e93ad
        k8s.io/client-go v0.0.0-20190425172711-65184652c889
        sigs.k8s.io/aws-iam-authenticator v0.5.0
    )
    

    【讨论】:

    • 很好的答案!您可能还想在 GetTokenOptions 结构中传递会话。看我的回答。
    • @AndrésMejía 和 @Simon 有没有办法将 access_key_id 和 secret_access_key 传递给 session.NewSession(),而不需要查看 aws.config 文件或任何其他文件。
    • @SuryavanshiVirendrasingh 是的,有可能!您只需将 2 个密钥导出到您的环境,NewSession 将使用默认优先顺序从环境中找到它们 * 访问密钥 ID:AWS_ACCESS_KEY_ID 或 AWS_ACCESS_KEY * 秘密访问密钥:AWS_SECRET_ACCESS_KEY 或 AWS_SECRET_KEY
    • @Simon 您能否详细说明将 2 个密钥导出到环境中是什么意思?
    • @SuryavanshiVirendrasingh 假设您在 shell 中运行程序:AWS_ACCESS_KEY_ID=access_key_id AWS_SECRET_ACCESS_KEY=secret_access_key go run youprogram.go 请参阅此页面上的“如何设置环境变量”:docs.aws.amazon.com/cli/latest/userguide/…
    【解决方案2】:

    添加到Simon's great answer,您可能还想在GetTokenOptions 结构中传递会话,如下所示:

    opts := &token.GetTokenOptions{
            ClusterID: aws.StringValue(cluster.Name),
            Session: sess,
        }
        tok, err := gen.GetWithOptions(opts)
    

    否则gen.GetWithOptions(opts) 调用将尝试从本地来源(例如~/.aws/credentials)读取您的 AWS 凭证,并且可能会因以下错误而失败:

    NoCredentialProviders: no valid providers in chain. Deprecated.
        For verbose messaging see aws.Config.CredentialsChainVerboseErrors
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-14
      • 2020-07-19
      • 1970-01-01
      • 2019-04-08
      相关资源
      最近更新 更多