2
votes

I am trying to use the kubernetes go-client with cloud.google.com/go/container. I create the cluster using the google cloud go container package, then I want to deploy on that cluster using go-client. The out of cluster example given by the go-client uses the kube config file to get the credentials for the cluster. But since I just created this cluster within my application I don’t have that config file.

How can I setup a “k8s.io/client-go/rest” config with a "google.golang.org/genproto/googleapis/container/v1" Cluster? What are the required fields? The code below is what I currently have (without showing the actual CA certificate).

func getConfig(cluster *containerproto.Cluster) *rest.Config {
    return &rest.Config{
        Host:     "https://" + cluster.GetEndpoint(),
        TLSClientConfig: rest.TLSClientConfig{
            Insecure: false,
            CAData: []byte(`-----BEGIN CERTIFICATE-----
                ...
                -----END CERTIFICATE-----`),
        },
    }

It results in this error: x509: certificate signed by unknown authority. So there is obviously something missing. Any other approach is more than welcome! Thanks in advance

2

2 Answers

4
votes

The ClientCertificate, ClientKey and ClusterCaCertificate need to be decoded as described here

func CreateK8sClientFromCluster(cluster *gkev1.Cluster) {
    decodedClientCertificate, err := base64.StdEncoding.DecodeString(cluster.MasterAuth.ClientCertificate)
    if err != nil {
        fmt.Println("decode client certificate error:", err)
        return
    }
    decodedClientKey, err := base64.StdEncoding.DecodeString(cluster.MasterAuth.ClientKey)
    if err != nil {
        fmt.Println("decode client key error:", err)
        return
    }
    decodedClusterCaCertificate, err := base64.StdEncoding.DecodeString(cluster.MasterAuth.ClusterCaCertificate)
    if err != nil {
        fmt.Println("decode cluster CA certificate error:", err)
        return
    }

    config := &rest.Config{
        Username: cluster.MasterAuth.Username,
        Password: cluster.MasterAuth.Password,
        Host:     "https://" + cluster.Endpoint,
        TLSClientConfig: rest.TLSClientConfig{
            Insecure: false,
            CertData: decodedClientCertificate,
            KeyData:  decodedClientKey,
            CAData:   decodedClusterCaCertificate,
        },
    }

    clientset, err := kubernetes.NewForConfig(config)
    if err != nil {
        fmt.Printf("failed to get k8s client set from config: %s\n", err)
        return
    }
}
1
votes

I've answered a very similar question here: Access Kubernetes GKE cluster outside of GKE cluster with client-go?.

Basically, in a nutshell, the recommended way to do this is to:

  1. Create a Google Cloud IAM service account + download its json key
  2. Set GOOGLE_APPLICATION_CREDENTIALS env var to that key.json
  3. Find IP address and CA cert of the cluster from gcloud container clusters describe (or simply get a .kube/config file from gcloud get-credentials
  4. Pass these values to client-go and run your program with the env var.