在kubernetes相关云原生程序的开发过程中,离不开的工具就是 client-go 这个库。目前,集群权限认证基本有两种方式,一是使用 kubeconfig 文件进行认证,另一个就是把服务运行到集群内,使用 InClusterConfig 进行认证(即 serviceaccount 拥有的集群权限),但是在实际的开发过程中,这两种方式都不够灵活。比如,需要对多个集群进行控制时,如果使用kubeconfig文件的方式,就必须指定配置文件,而InCluster只能对当前集群起作用,多个集群,势必需要在每个集群都运行一个程序
分析 InClusterConfig 函数,可以看到,实际上只需要构造一个 *rest.Config 结构体,然后返回,就可以了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
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进行多集群访问示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
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授权示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
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 |
转载请注明:轻风博客 » client-go使用token访问集群资源