All Products
Search
Document Center

Container Service for Kubernetes:Access multi-cluster resources by using the SDK for Go

Last Updated:Feb 25, 2025

If you want to integrate Distributed Cloud Container Platform for Kubernetes (ACK One) Fleet instances into the platform to access the resources of each cluster, you can use the SDK for Go. This topic describes how to use the SDK for Go to manage Kubernetes resources in multiple clusters by using the kubeconfig files of Fleet instances.

Principle of multi-cluster resource access

image

ACK One uses the Cluster Gateway of the open source community to implement centralized access to Kubernetes resources in multiple clusters by using the kubeconfig files of Fleet instances. ACK One also uses user impersonation to manage user access to the Role-Based Access Control (RBAC) permissions of clusters.

  1. Log on to the Fleet by using your Alibaba Cloud account or a RAM user. Then, obtain the kubeconfig file.

    You can grant RBAC permissions on the cluster to the RAM user in advance.

  2. Obtain the Open Cluster Management (OCM) ManagedCluster resources in the Fleet. Cluster Gateway changes the cluster by using the name of ManagedCluster to access the Kubernetes resources of the cluster.

User impersonation

Cluster Gateway allows you to use user impersonation to manage access to Kubernetes resources in clusters. The following section describes the detailed steps:

  1. Log on to the ACK console by using an Alibaba Cloud account. In the left-side navigation pane, choose Fleet > Permissions. Click the Associated Clusters tab and grant the RAM user the RBAC permissions on each cluster.

  2. Log on to the ACK One console. In the left-side navigation pane, choose Fleet > Fleet Information. Click the Connect to Fleet tab to obtain the kubeconfig file.

  3. Use the kubeconfig file to access the Kubernetes resources of each cluster by using Cluster Gateway. For more information, see Sample code.

    If you do not have the permissions to perform operations on a resource, Cluster Gateway reports an error message similar to the following contents:

    stream error: stream ID 3; INTERNAL_ERROR; received from peer

Sample code

The following sample code is based on the OCM v0.14.0. The sample provides an example on how to access multi-cluster Kubernetes resources by using the kubeconfig files of the Fleet instance and print the kube-system namespace UIDs of all clusters. Perform the following steps:

  1. Obtain the OCM ManagedCluster resource that corresponds to the associated cluster by using the kubeconfig file.

  2. You can use Cluster Gateway to configure the kubeClient parameter for each cluster.

  3. Print the UIDs of the kube-system namespace of all clusters.

package main

import (
	"context"
	"fmt"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/errors"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
	ocmcluster "open-cluster-management.io/api/client/cluster/clientset/versioned"
)

// Print the UID of the kube-system namespace of the cluster. 
func main() {
	fleetKubeconfigPath := "<your fleet kubeconifg path>"
	memberClients, err := GenerateMemberClusterKubeClients(fleetKubeconfigPath)
	if err != nil {
		panic(err.Error())
	}

	for cluster, kubeClient := range memberClients {
		ns, err := kubeClient.CoreV1().Namespaces().Get(context.TODO(), "kube-system", metav1.GetOptions{})
		if err != nil {
			fmt.Println(fmt.Sprintf("failed to get kube-system for member cluster %s: %v", cluster, err))
			continue
		}
		fmt.Println(fmt.Sprintf("Cluster %s kube-system namespace UID: %s", cluster, ns.UID))
	}
}

// Generate a KubeClient for the cluster. 
func GenerateMemberClusterKubeClients(fleetKubeconfigPath string) (map[string]kubernetes.Interface, error) {
	fleetConfig, err := clientcmd.BuildConfigFromFlags("", fleetKubeconfigPath)
	if err != nil {
		return nil, err
	}

	// get managedclusters by ocmClusterClient
	ocmClusterClient, err := ocmcluster.NewForConfig(fleetConfig)
	if err != nil {
		return nil, fmt.Errorf("failed to create ocm cluster client: %v", err)
	}
	managedClusters, err := ocmClusterClient.ClusterV1().ManagedClusters().List(context.Background(), metav1.ListOptions{})
	if err != nil {
		return nil, err
	}

	var errs []error
	memberClients := make(map[string]kubernetes.Interface)
	for _, cluster := range managedClusters.Items {
		configCopy := *fleetConfig
		configCopy.Host = fmt.Sprintf("%s/apis/cluster.core.oam.dev/v1alpha1/clustergateways/%s/proxy", fleetConfig.Host, cluster.Name)
		kubeClient, err := kubernetes.NewForConfig(&configCopy)
		if err != nil {
			errs = append(errs, fmt.Errorf("failed to create kube client for cluster %s: %v", cluster.Name, err))
			continue
		}
		memberClients[cluster.Name] = kubeClient
	}

	return memberClients, errors.NewAggregate(errs)
}

go.mod configurations

go 1.21.0


require (
	k8s.io/apimachinery v0.29.0
	k8s.io/client-go v0.29.0
	open-cluster-management.io/api v0.14.0
)

require (
	github.com/davecgh/go-spew v1.1.1 // indirect
	github.com/emicklei/go-restful/v3 v3.11.0 // indirect
	github.com/go-logr/logr v1.4.1 // indirect
	github.com/go-openapi/jsonpointer v0.19.6 // indirect
	github.com/go-openapi/jsonreference v0.20.2 // indirect
	github.com/go-openapi/swag v0.22.3 // indirect
	github.com/gogo/protobuf v1.3.2 // indirect
	github.com/golang/protobuf v1.5.4 // indirect
	github.com/google/gnostic-models v0.6.8 // indirect
	github.com/google/gofuzz v1.2.0 // indirect
	github.com/google/uuid v1.3.0 // indirect
	github.com/imdario/mergo v0.3.6 // indirect
	github.com/josharian/intern v1.0.0 // indirect
	github.com/json-iterator/go v1.1.12 // indirect
	github.com/mailru/easyjson v0.7.7 // indirect
	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
	github.com/modern-go/reflect2 v1.0.2 // indirect
	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
	github.com/spf13/pflag v1.0.5 // indirect
	golang.org/x/net v0.23.0 // indirect
	golang.org/x/oauth2 v0.12.0 // indirect
	golang.org/x/sys v0.18.0 // indirect
	golang.org/x/term v0.18.0 // indirect
	golang.org/x/text v0.14.0 // indirect
	golang.org/x/time v0.3.0 // indirect
	google.golang.org/appengine v1.6.7 // indirect
	google.golang.org/protobuf v1.33.0 // indirect
	gopkg.in/inf.v0 v0.9.1 // indirect
	gopkg.in/yaml.v2 v2.4.0 // indirect
	gopkg.in/yaml.v3 v3.0.1 // indirect
	k8s.io/api v0.30.0 // indirect
	k8s.io/klog/v2 v2.120.1 // indirect
	k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
	k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
	sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
	sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
	sigs.k8s.io/yaml v1.4.0 // indirect
)