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
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.
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.
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:
Log on to the ACK console by using an Alibaba Cloud account. In the left-side navigation pane, choose . Click the Associated Clusters tab and grant the RAM user the RBAC permissions on each cluster.
Log on to the ACK One console. In the left-side navigation pane, choose . Click the Connect to Fleet tab to obtain the kubeconfig file.
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:
Obtain the OCM ManagedCluster resource that corresponds to the associated cluster by using the kubeconfig file.
You can use Cluster Gateway to configure the kubeClient parameter for each cluster.
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
)