# client-go库使用token连接Apiserver ## 基本准备 ``` # 创建sa、绑定角色 [root@Jenkins-master01 ~]# kubectl create serviceaccount dashboard-admin -n kube-system [root@Jenkins-master01 ~]# kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin #dashboard-admin 绑定为集群账户 # 获取此sa的token值 [root@Jenkins-master01 ~]# kubectl describe secrets -n kube-system $(kubectl -n kube-system get secret | awk '/dashboard-admin/{print $1}') | awk '/token:/{print $2}' eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkYXNoYm9hcmQtYWRtaW4tdG9rZW4tZDQyNWoiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGFzaGJvYXJkLWFkbWluIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiYzQyNDJmODItZDUzNi0xMWVhLWIxOGEtMDAwYzI5M2FkNzkyIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmRhc2hib2FyZC1hZG1pbiJ9.DJCDQXqvzc13HFuP56-qtaS1i5p956Q1AsJp9RPBaAMAf7iXgkuRSlB04WaoFKe22oHayrOgvJOmM9AL4glWhTC0Ueh-2_SKlM9qJrTwtVjMcZzh53wZn20Qr1iQYyw2k6kOilSSJjEQ-zKKGwz7CaJRhHN9YJmq8LdmcYDDtTyHJrYy_csddzDrb6WntO5VBPmiEMB7JS5eZFTeQyyQg3X8Q4bFRgXafpadXEz2InxbLYchVrxBV4TnG_HXw8gl0ethKFRCW1pF1DCI8DrEYVoY7NaKtWBEchUXpT88Al5-kRblRPIjxsvSp7x0scw0F-6nXIPabtG8gzPNuFyg5w ``` ## 根据上面的token创建kubeconfig文件 ``` #设置认证信息 [root@Jenkins-master01 ~]# kubectl config set-credentials tf-admin --token=eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkYXNoYm9hcmQtYWRtaW4tdG9rZW4tZDQyNWoiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGFzaGJvYXJkLWFkbWluIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiYzQyNDJmODItZDUzNi0xMWVhLWIxOGEtMDAwYzI5M2FkNzkyIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmRhc2hib2FyZC1hZG1pbiJ9.DJCDQXqvzc13HFuP56-qtaS1i5p956Q1AsJp9RPBaAMAf7iXgkuRSlB04WaoFKe22oHayrOgvJOmM9AL4glWhTC0Ueh-2_SKlM9qJrTwtVjMcZzh53wZn20Qr1iQYyw2k6kOilSSJjEQ-zKKGwz7CaJRhHN9YJmq8LdmcYDDtTyHJrYy_csddzDrb6WntO5VBPmiEMB7JS5eZFTeQyyQg3X8Q4bFRgXafpadXEz2InxbLYchVrxBV4TnG_HXw8gl0ethKFRCW1pF1DCI8DrEYVoY7NaKtWBEchUXpT88Al5-kRblRPIjxsvSp7x0scw0F-6nXIPabtG8gzPNuFyg5w --kubeconfig=tf-admin User "tf-admin" set. #设置集群信息 [root@Jenkins-master01 ~]# kubectl config set-cluster tf-cluster --insecure-skip-tls-verify=true --server=https://192.168.1.92:6443 --kubeconfig=tf-admin Cluster "tf-cluster" set. #设置上下文信息 [root@Jenkins-master01 ~]# kubectl config set-context tf-system --cluster=tf-cluster --user=tf-admin --kubeconfig=tf-admin #设置当前配置上下文 [root@Jenkins-master01 ~]# kubectl config use-context tf-system --kubeconfig=tf-admin #查看生成的配置文件 [root@Jenkins-master01 ~]# cat tf-admin apiVersion: v1 clusters: - cluster: insecure-skip-tls-verify: true server: https://192.168.1.92:6443 name: tf-cluster contexts: - context: cluster: tf-cluster user: tf-admin name: tf-system current-context: tf-system kind: Config preferences: {} users: - name: tf-admin user: token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkYXNoYm9hcmQtYWRtaW4tdG9rZW4tZDQyNWoiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGFzaGJvYXJkLWFkbWluIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiYzQyNDJmODItZDUzNi0xMWVhLWIxOGEtMDAwYzI5M2FkNzkyIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmRhc2hib2FyZC1hZG1pbiJ9.DJCDQXqvzc13HFuP56-qtaS1i5p956Q1AsJp9RPBaAMAf7iXgkuRSlB04WaoFKe22oHayrOgvJOmM9AL4glWhTC0Ueh-2_SKlM9qJrTwtVjMcZzh53wZn20Qr1iQYyw2k6kOilSSJjEQ-zKKGwz7CaJRhHN9YJmq8LdmcYDDtTyHJrYy_csddzDrb6WntO5VBPmiEMB7JS5eZFTeQyyQg3X8Q4bFRgXafpadXEz2InxbLYchVrxBV4TnG_HXw8gl0ethKFRCW1pF1DCI8DrEYVoY7NaKtWBEchUXpT88Al5-kRblRPIjxsvSp7x0scw0F-6nXIPabtG8gzPNuFyg5w 可以看出这个文件完全可以由程序生成 ``` ## 使用程序生成配置文件 > 获取dev名称空间所有的pod ``` package main import ( "context" "flag" "fmt" "github.com/olekukonko/tablewriter" "gopkg.in/yaml.v2" "io/ioutil" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/clientcmd" "os" "strconv" "time" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) type ClusterInfo struct { InsecureSkipTlsVerify bool `yaml:"insecure-skip-tls-verify,omitempty"` CertificateAuthorityData string `yaml:"certificate-authority-data,omitempty" ` Server string } type Cluster struct { Cluster ClusterInfo `yaml:"cluster"` Name string `yaml:"name"` } type ClusterList []Cluster type ContextInfo struct { Cluster string `yaml:"cluster"` User string `yaml:"user"` } type Context struct { Context ContextInfo `yaml:"context"` Name string `yaml:"name"` } type ContextList []Context type UserInfo struct { Token string `yaml:"token,omitempty"` ClientCertificateData string `yaml:"client-certificate-data,omitempty"` ClientKeyData string `yaml:"client-key-data,omitempty"` } type User struct { Name string `yaml:"name"` User UserInfo `yaml:"user"` } type UserList []User type Config struct { ApiVersion string `yaml:"apiVersion"` Clusters ClusterList `yaml:"clusters,flow"` Contexts ContextList `yaml:"contexts,flow"` CurrentContext string `yaml:"current-context"` Kind string `yaml:"kind"` Users UserList `yaml:"users,flow"` } func NewTokenConfig(apiServer,token string)*Config{ return &Config{ ApiVersion: "v1", Clusters: ClusterList{ { Name: "tmp-cluster", Cluster: ClusterInfo{ InsecureSkipTlsVerify: true, Server: apiServer, }, }, }, Kind: "Config", Users: UserList{ { Name: "tmp-user", User: UserInfo{ Token: token, }, }, }, Contexts: ContextList{ { Context: ContextInfo{ Cluster: "tmp-cluster", User: "tmp-user", }, Name: "tmp-system", }, }, CurrentContext: "tmp-system", } } func main(){ var token,apiserver *string apiserver = flag.String("apiserver","","apiserver path") token = flag.String("token","","token string") flag.Parse() yamlConfig := NewTokenConfig(*apiserver,*token) configResult,err := yaml.Marshal(yamlConfig) if err != nil{ panic(err.Error()) } file,err := ioutil.TempFile(".","tmp") if err != nil{ panic(err.Error()) } defer func() { file.Close() os.RemoveAll(file.Name()) }() file.WriteString(string(configResult)) //从本机加载kubeconfig配置文件,因此第一个参数为空字符串 config , err := clientcmd.BuildConfigFromFlags("",file.Name()) if err != nil{ fmt.Println("load kubeconfig failed!err:",err) panic(err.Error()) } //实例化一个clientset对象 clientset,err := kubernetes.NewForConfig(config) if err != nil{ fmt.Println("init clientset failed ! err: ",err) panic(err.Error()) } //获取podClient客户端,corev1.NamespaceAll 为空字符串,实际如果为空字符串,那么拿到的是所有名称空间的pod资源 //podClient := clientset.CoreV1().Pods(corev1.NamespaceAll) podClient := clientset.CoreV1().Pods("dev") //使用podclient客户端,列出名称空间内所有pod资源 result,err := podClient.List(context.TODO(),metav1.ListOptions{}) if err != nil{ fmt.Println("podclient get pods failed! err: ",err) panic(err.Error()) } data := make([][]string,0,len(result.Items)) for i,_ := range result.Items{ var count int for _,v := range result.Items[i].Status.ContainerStatuses{ if v.Ready{ count ++ } } var avg string subHoure := time.Now().Sub(result.Items[i].ObjectMeta.CreationTimestamp.Time).Hours() if subHoure < 24{ avg = fmt.Sprintf("%dh", subHoure) }else{ hours := int(subHoure) days := hours/24 if (hours % 24)>0{ days += 1 } avg = fmt.Sprintf("%dd", days) } data = append(data, []string{result.Items[i].Namespace,result.Items[i].Name,fmt.Sprintf("%d/%d",count,len(result.Items[i].Status.ContainerStatuses)), string(result.Items[i].Status.Phase),strconv.Itoa(int(result.Items[i].Status.ContainerStatuses[0].RestartCount)),avg}) } table := tablewriter.NewWriter(os.Stdout) table.SetHeader([]string{"NAMESPACE", "NAME", "READY", "STATUS","RESTART","AGE"}) table.SetAutoWrapText(false) table.SetAutoFormatHeaders(true) table.SetHeaderAlignment(tablewriter.ALIGN_LEFT) table.SetAlignment(tablewriter.ALIGN_LEFT) table.SetCenterSeparator("") table.SetColumnSeparator("") table.SetRowSeparator("") table.SetHeaderLine(false) table.SetBorder(false) table.SetTablePadding("\t") // pad with tabs table.SetNoWhiteSpace(true) table.AppendBulk(data) // Add Bulk Data table.Render() } 运行程序: C:\Users\xx\Desktop\git\client>go run main.go --apiserver https://192.168.1.92:6443 --token eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJ lLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkYXNoYm9hcmQtYWRtaW4tdG9rZW4tZDQyNWoiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGFzaGJvYXJkLWFkbWluIiwia3ViZXJuZXRlcy5pby9zZXJ2aWN lYWNjb3VudC9zZXJ2aWNlLWFjY291bnQudWlkIjoiYzQyNDJmODItZDUzNi0xMWVhLWIxOGEtMDAwYzI5M2FkNzkyIiwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50Omt1YmUtc3lzdGVtOmRhc2hib2FyZC1hZG1pbiJ9.DJCDQXqvzc13HFuP56-qtaS1i5p956Q1AsJp9RPBaAMAf7iXgkuRSlB04WaoFK e22oHayrOgvJOmM9AL4glWhTC0Ueh-2_SKlM9qJrTwtVjMcZzh53wZn20Qr1iQYyw2k6kOilSSJjEQ-zKKGwz7CaJRhHN9YJmq8LdmcYDDtTyHJrYy_csddzDrb6WntO5VBPmiEMB7JS5eZFTeQyyQg3X8Q4bFRgXafpadXEz2InxbLYchVrxBV4TnG_HXw8gl0ethKFRCW1pF1DCI8DrEYVoY7NaKtWBEchUXpT 88Al5-kRblRPIjxsvSp7x0scw0F-6nXIPabtG8gzPNuFyg5w NAMESPACE NAME READY STATUS RESTART AGE dev chat-cloud-apis-chtapp-app-recipient-server-deployment-5b45hxkb 1/1 Running 0 12d dev chat-cloud-apis-chtapp-chat-server-deployment-774f598bb5-2g4lm 1/1 Running 0 12d dev chat-cloud-apis-chtapp-chat-server-deployment-774f598bb5-4dcxx 1/1 Running 0 12d dev chat-cloud-apis-chtapp-chat-server-deployment-774f598bb5-5gwbs 1/1 Running 0 12d dev chat-cloud-apis-chtapp-chat-server-deployment-774f598bb5-7qmnj 1/1 Running 0 12d dev chat-cloud-apis-chtapp-chat-server-deployment-774f598bb5-7zgfd 1/1 Running 0 12d dev chat-cloud-apis-chtapp-chat-server-deployment-774f598bb5-c76dn 1/1 Running 0 12d dev chat-cloud-apis-chtapp-chat-server-deployment-774f598bb5-s85kz 1/1 Running 0 12d ...... ```