通过Go SDK访问多集群资源

更新时间:2025-02-06 09:36:07

若您希望在平台中集成ACK One舰队以访问各子集群资源,可以利用Go SDK进行操作。本文介绍如何使用Go SDK通过舰队KubeConfig管理多集群的Kubernetes资源。

多集群资源访问原理

image

ACK One采用开源社区的Cluster Gateway,通过舰队的KubeConfig实现对多集群的Kubernetes资源的统一访问,并通过User impersonation来控制用户对子集群RBAC权限的访问。

  1. 使用阿里云账号(主账号)或者RAM User登录舰队后,获取舰队KubeConfig。

    对于RAM User,可预先配置其对子集群的RBAC权限。

  2. 在舰队中获取OCM ManagedCluster资源,Cluster Gateway通过ManagedCluster的名称来切换集群,以访问子集群的Kubernetes资源。

User impersonation

Cluster Gateway支持通过伪装(user impersonation)来控制访问子集群Kubernetes资源权限,具体步骤如下。

  1. 使用阿里云账号(主账号)登录ACK One控制台,在左侧导航栏选择舰队 > 权限管理进入关联集群页签,为RAM User授予每个子集群的RBAC权限。

  2. 使用RAM User登录ACK One控制台,在左侧导航栏选择舰队 > 舰队信息进入连接舰队页签获取KubeConfig。

  3. 使用该KubeConfig通过Cluster Gateway访问各子集群的Kubernetes资源。具体操作,请参见示例代码

    若无某个资源的操作权限,Cluster Gateway会报类似如下错误信息。

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

示例代码

以下示例代码基于OCM v0.14.0版本,通过舰队KubeConfig访问多集群Kubernetes资源,打印所有子集群的kube-system namespaceUID。主要步骤如下。

  1. 通过KubeConfig获取关联集群对应的OCM ManagedCluster资源。

  2. 通过Cluster Gateway为每个子集群构建kubeClient。

  3. 打印所有子集群的kube-system namespaceUID。

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"
)

// 打印子集群kube-system namespace的UID。
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))
	}
}

// 生成子集群KubeClient。
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配置

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
)
  • 本页导读 (1)
  • 多集群资源访问原理
  • User impersonation
  • 示例代码
  • go.mod配置