如何在 Go 中直接从 GCP 服务帐户 JSON 密钥文件创建 kubernetes.Clientset?
How can I create a kubernetes.Clientset directly from a GCP service account JSON key file in Go?
我正在寻找一种初始化 kubernetes.Clientset
for GKE in Go starting from a service account JSON key file. I found a few leads, such as this blog and this associated gist 的方法,但那里概述的方法似乎需要列出 GCP 项目中的所有集群以创建 kubeconfig 的内存中表示,这不是'太理想了。
以 GKE driver code from https://github.com/rancher/kontainer-engine 为灵感,我想出了以下方法(避免了对 k8s.io/client-go/tools/clientcmd
的依赖):
package main
import (
"context"
"encoding/base64"
"fmt"
"io/ioutil"
"log"
"net/http"
"strings"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
"google.golang.org/api/container/v1"
"google.golang.org/api/option"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
)
func getGKEClientset(cluster *container.Cluster, ts oauth2.TokenSource) (kubernetes.Interface, error) {
capem, err := base64.StdEncoding.DecodeString(cluster.MasterAuth.ClusterCaCertificate)
if err != nil {
return nil, fmt.Errorf("failed to decode cluster CA cert: %s", err)
}
config := &rest.Config{
Host: cluster.Endpoint,
TLSClientConfig: rest.TLSClientConfig{
CAData: capem,
},
}
config.Wrap(func(rt http.RoundTripper) http.RoundTripper {
return &oauth2.Transport{
Source: ts,
Base: rt,
}
})
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, fmt.Errorf("failed to initialise clientset from config: %s", err)
}
return clientset, nil
}
func main() {
gcpServiceAccountKeyFile := "gcp_service_account_key.json"
gkeLocation := "<GKE Project Location>" // i.e. us-east1
gkeClusterName := "<GKE Cluster Name>"
gkeNamespace := "<GKE Cluster Namespace>"
data, err := ioutil.ReadFile(gcpServiceAccountKeyFile)
if err != nil {
log.Fatalf("Failed to read GCP service account key file: %s", err)
}
ctx := context.Background()
creds, err := google.CredentialsFromJSON(ctx, data, container.CloudPlatformScope)
if err != nil {
log.Fatalf("Failed to load GCP service account credentials: %s", err)
}
gkeService, err := container.NewService(ctx, option.WithHTTPClient(oauth2.NewClient(ctx, creds.TokenSource)))
if err != nil {
log.Fatalf("Failed to initialise Kubernetes Engine service: %s", err)
}
name := fmt.Sprintf("projects/%s/locations/%s/clusters/%s", creds.ProjectID, gkeLocation, gkeClusterName)
cluster, err := container.NewProjectsLocationsClustersService(gkeService).Get(name).Do()
if err != nil {
log.Fatalf("Failed to load GKE cluster %q: %s", name, err)
}
clientset, err := getGKEClientset(cluster, creds.TokenSource)
if err != nil {
log.Fatalf("Failed to initialise Kubernetes clientset: %s", err)
}
pods, err := clientset.CoreV1().Pods(gkeNamespace).List(ctx, v1.ListOptions{})
if err != nil {
log.Fatalf("Failed to list pods: %s", err)
}
log.Printf("There are %d pods in the namespace", len(pods.Items))
}
我正在寻找一种初始化 kubernetes.Clientset
for GKE in Go starting from a service account JSON key file. I found a few leads, such as this blog and this associated gist 的方法,但那里概述的方法似乎需要列出 GCP 项目中的所有集群以创建 kubeconfig 的内存中表示,这不是'太理想了。
以 GKE driver code from https://github.com/rancher/kontainer-engine 为灵感,我想出了以下方法(避免了对 k8s.io/client-go/tools/clientcmd
的依赖):
package main
import (
"context"
"encoding/base64"
"fmt"
"io/ioutil"
"log"
"net/http"
"strings"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
"google.golang.org/api/container/v1"
"google.golang.org/api/option"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
)
func getGKEClientset(cluster *container.Cluster, ts oauth2.TokenSource) (kubernetes.Interface, error) {
capem, err := base64.StdEncoding.DecodeString(cluster.MasterAuth.ClusterCaCertificate)
if err != nil {
return nil, fmt.Errorf("failed to decode cluster CA cert: %s", err)
}
config := &rest.Config{
Host: cluster.Endpoint,
TLSClientConfig: rest.TLSClientConfig{
CAData: capem,
},
}
config.Wrap(func(rt http.RoundTripper) http.RoundTripper {
return &oauth2.Transport{
Source: ts,
Base: rt,
}
})
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, fmt.Errorf("failed to initialise clientset from config: %s", err)
}
return clientset, nil
}
func main() {
gcpServiceAccountKeyFile := "gcp_service_account_key.json"
gkeLocation := "<GKE Project Location>" // i.e. us-east1
gkeClusterName := "<GKE Cluster Name>"
gkeNamespace := "<GKE Cluster Namespace>"
data, err := ioutil.ReadFile(gcpServiceAccountKeyFile)
if err != nil {
log.Fatalf("Failed to read GCP service account key file: %s", err)
}
ctx := context.Background()
creds, err := google.CredentialsFromJSON(ctx, data, container.CloudPlatformScope)
if err != nil {
log.Fatalf("Failed to load GCP service account credentials: %s", err)
}
gkeService, err := container.NewService(ctx, option.WithHTTPClient(oauth2.NewClient(ctx, creds.TokenSource)))
if err != nil {
log.Fatalf("Failed to initialise Kubernetes Engine service: %s", err)
}
name := fmt.Sprintf("projects/%s/locations/%s/clusters/%s", creds.ProjectID, gkeLocation, gkeClusterName)
cluster, err := container.NewProjectsLocationsClustersService(gkeService).Get(name).Do()
if err != nil {
log.Fatalf("Failed to load GKE cluster %q: %s", name, err)
}
clientset, err := getGKEClientset(cluster, creds.TokenSource)
if err != nil {
log.Fatalf("Failed to initialise Kubernetes clientset: %s", err)
}
pods, err := clientset.CoreV1().Pods(gkeNamespace).List(ctx, v1.ListOptions{})
if err != nil {
log.Fatalf("Failed to list pods: %s", err)
}
log.Printf("There are %d pods in the namespace", len(pods.Items))
}