云原生开发中,client-go如何使用token访问集群资源

在kubernetes相关云原生程序的开发过程中,离不开的工具就是 client-go 这个库。目前,集群权限认证基本有两种方式,一是使用 kubeconfig 文件进行认证,另一个就是把服务运行到集群内,使用 InClusterConfig 进行认证(即 serviceaccount 拥有的集群权限),但是在实际的开发过程中,这两种方式都不够灵活。比如,需要对多个集群进行控制时,如果使用kubeconfig文件的方式,就必须指定配置文件,而InCluster只能对当前集群起作用,多个集群,势必需要在每个集群都运行一个程序

分析 InClusterConfig 函数,可以看到,实际上只需要构造一个 *rest.Config 结构体,然后返回,就可以了

func InClusterConfig() (*Config, error) {
	const (
		tokenFile  = "/var/run/secrets/kubernetes.io/serviceaccount/token"
		rootCAFile = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
	)
	host, port := os.Getenv("KUBERNETES_SERVICE_HOST"), os.Getenv("KUBERNETES_SERVICE_PORT")
	if len(host) == 0 || len(port) == 0 {
		return nil, ErrNotInCluster
	}

	token, err := ioutil.ReadFile(tokenFile)
	if err != nil {
		return nil, err
	}

	tlsClientConfig := TLSClientConfig{}

	if _, err := certutil.NewPool(rootCAFile); err != nil {
		klog.Errorf("Expected to load root CA config from %s, but got err: %v", rootCAFile, err)
	} else {
		tlsClientConfig.CAFile = rootCAFile
	}

	return &Config{
		// TODO: switch to using cluster DNS.
		Host:            "https://" + net.JoinHostPort(host, port),
		TLSClientConfig: tlsClientConfig,
		BearerToken:     string(token),
		BearerTokenFile: tokenFile,
	}, nil
}

那么, 这个Config中那些字段是必须的呢?

  • Host 用于提供需要访问的集群地址

  • Token 用于提供授权

  • TLSClientConfig 提供tls安全访问层的数据
    如果不考虑数据传输的安全性,可直接设置 Insecure 为 true ,此时不需要对证书进行验证,当然不建议这么做,如果要使用证书,在CAData 中放ca证书就可以了

利用serviceaccount进行多集群访问示例:

package main

import (
	"context"
	"log"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
)

type K8sConfig struct {
	Name  string // 集群名称
	Host  string // 集群地址 https://xxxx:8443
	Token string // Token
	CA    string // CA证书
}

var (
	testconfig K8sConfig = K8sConfig{
		Name:  "test",
		Host:  "https://172.16.10.10:6443",
		Token: "xxxxxxxx", // 存放 serviceaccount对应secret的token
		CA:    testCa,
	}
	prodconfig K8sConfig = K8sConfig{
		Name:  "prod",
		Host:  "https://172.16.20.10:6443",
		Token: "xxxxxxxx",
		CA:    prodCa,
	}
	// 可继续添加其他集群配置
)

const (
    testCa = `xxxxxx` // 存放 serviceaccount对应secret的ca
    prodCa = `xxxxxx`
)

func SelectClusterConfig(env string) (*rest.Config, error) {
	var c K8sConfig
	switch env { // 多集群支持
	case "test":
		c = testconfig
	case "prod":
		c = prodconfig
	default:
		log.Printf("环境: %s 不支持", env)
		return nil, fmt.Errorf("环境: %s 不支持", env)
	}

	return &rest.Config{
		Host:            c.Host,
		BearerToken:     c.Token,
		BearerTokenFile: "",
		TLSClientConfig: rest.TLSClientConfig{
			// Insecure: true,  // 设置为true时 不需要CA
			CAData: []byte(c.CA),
		},
	}, nil
}

// GetPodByName 获取pod信息
func GetPodByName(env, namespace, podname string) {
	config, err := SelectClusterConfig(env)
	//config, err := clientcmd.BuildConfigFromFlags("", "C:\\Users\\Admin\\.kube\\config")
	if err != nil {
		log.Println("BuildConfigFromFlags Err:", err)
		return
	}
	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		log.Println("NewForConfig Err:", err)
		return
	}
	pod, err := clientset.CoreV1().Pods(namespace).Get(context.Background(), podname, metav1.GetOptions{})
	if err != nil {
		log.Println("GetPod Err:", err)
		return
	}
	log.Println("获取到pod:", pod)
}

func main() {
    GetPodByName("test", "default", "nginx-xxxx-xxxxxxxx")
}

上面的示例中,集群的配置信息直接硬编码,在实际的应用中,这部分的数据可以从配置中心、配置文件中获取

以上配置和下面直接使用curl访问的方式类似

# 获取服务器地址及端口
APISERVER=$(kubectl config view | grep server | cut -f 2- -d ":" | tr -d " ")
# tr -d '\t' 可能会失败 可能是空格
# TOKEN=$(kubectl describe secret $(kubectl get secrets | grep default | cut -f1 -d ' ') | grep -E '^token' | cut -f2 -d':' | tr -d '\t')
TOKEN=$(kubectl describe secret $(kubectl get secrets | grep default | cut -f1 -d ' ') | grep -E '^token' | cut -f2 -d':' | tr -d ' ')
curl $APISERVER/api/v1/namespaces/default/pods/nginx-xxxx-xxxxxxxx --header "Authorization: Bearer $TOKEN" --insecure

因为集群通常为rbac认证,如果没有相应的权限,则不能访问对应的资源,所以还需要serviceaccount赋予对应的权限

serviceaccount授权示例:

apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    app: example
  name: sa-example
  namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  labels:
    app: example
  name: sa-example
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: sa-example
subjects:
  - kind: ServiceAccount
    name: sa-example
    namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  labels:
    app: example
  name: sa-example
rules:
  - apiGroups:
      - ""
    resources:
      - pods
    verbs:
      - get
      - list
      - delete
  - apiGroups:
      - ""
    resources:
      - namespaces
    verbs:
      - get
      - list

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值