利用kubernetes的go语言sdk,client-go 操作kubernetes集群

(1)采用minikube启动一个k8s集群

$minikube start
?  minikube v1.0.0 on darwin (amd64)
?  Downloading Kubernetes v1.14.0 images in the background ...
?  Creating virtualbox VM (CPUs=2, Memory=2048MB, Disk=20000MB) ...
?  "minikube" IP address is 192.168.99.103
?  Configuring Docker as the container runtime ...
?  Version of container runtime is 18.06.2-ce
⌛  Waiting for image downloads to complete ...
✨  Preparing Kubernetes environment ...
?  Pulling images required by Kubernetes v1.14.0 ...
?  Launching Kubernetes v1.14.0 using kubeadm ... 
⌛  Waiting for pods: apiserver proxy etcd scheduler controller dns
?  Configuring cluster permissions ...
?  Verifying component health .....
?  kubectl is now configured to use "minikube"
?  Done! Thank you for using minikube!


#确保集群处于运行状态
$minikube status
host: Running
kubelet: Running
apiserver: Running
kubectl: Correctly Configured: pointing to minikube-vm at 192.168.99.103

(2)在本地go环境配置好的情况下,拉取client-go的代码

go get -u k8s.io/client-go/...

(3)client-go的代码中,自带了example,一个是in-cluster的,一个是out-of-cluster的,后者需要访问k8s集群所需的配置文件,该配置文件一般位于:~/.kube/config

内容如下:

apiVersion: v1
clusters:
- cluster:
    certificate-authority: /Users/yuankewei/.minikube/ca.crt
    server: https://192.168.99.103:8443
  name: minikube
contexts:
- context:
    cluster: minikube
    user: minikube
  name: minikube
current-context: minikube
kind: Config
preferences: {}
users:
- name: minikube
  user:
    client-certificate: /Users/yuankewei/.minikube/client.crt
    client-key: /Users/yuankewei/.minikube/client.key

 

直接运行该out-cluster的示例代码,

$go run main.go 
There are 9 pods in the cluster
Pod example-xxxxx in namespace default not found
There are 9 pods in the cluster
Pod example-xxxxx in namespace default not found
There are 9 pods in the cluster
Pod example-xxxxx in namespace default not found
There are 9 pods in the cluster
Pod example-xxxxx in namespace default not found
There are 9 pods in the cluster
Pod example-xxxxx in namespace default not found
There are 9 pods in the cluster
Pod example-xxxxx in namespace default not found
There are 9 pods in the cluster
Pod example-xxxxx in namespace default not found

 

这里我们看下具体的代码

/*
Copyright 2016 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// Note: the example only works with the code within the same release/branch.
package main

import (
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"time"

	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
	//
	// Uncomment to load all auth plugins
	// _ "k8s.io/client-go/plugin/pkg/client/auth"
	//
	// Or uncomment to load specific auth plugins
	// _ "k8s.io/client-go/plugin/pkg/client/auth/azure"
	// _ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
	// _ "k8s.io/client-go/plugin/pkg/client/auth/oidc"
	// _ "k8s.io/client-go/plugin/pkg/client/auth/openstack"
)

func main() {
    #访问集群所需的配置文件,默认取~/.kube/config
    #flag是go语言中解析命令行参数的一个第三方模块
    #//定义一个字符串的变量
    #type string string
    #func String(name string, value string, usage string) *string
	var kubeconfig *string
	if home := homeDir(); home != "" {
		kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
	} else {
		kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
	}
	flag.Parse()

	// use the current context in kubeconfig
	config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
	if err != nil {
		panic(err.Error())
	}

	// create the clientset
	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		panic(err.Error())
	}

	for {
		pods, err := clientset.CoreV1().Pods("").List(metav1.ListOptions{})
		if err != nil {
			panic(err.Error())
		}
		fmt.Printf("There are %d pods in the cluster\n", len(pods.Items))

		// Examples for error handling:
		// - Use helper functions like e.g. errors.IsNotFound()
		// - And/or cast to StatusError and use its properties like e.g. ErrStatus.Message
		namespace := "default"
		pod := "example-xxxxx"
		_, err = clientset.CoreV1().Pods(namespace).Get(pod, metav1.GetOptions{})
		if errors.IsNotFound(err) {
			fmt.Printf("Pod %s in namespace %s not found\n", pod, namespace)
		} else if statusError, isStatus := err.(*errors.StatusError); isStatus {
			fmt.Printf("Error getting pod %s in namespace %s: %v\n",
				pod, namespace, statusError.ErrStatus.Message)
		} else if err != nil {
			panic(err.Error())
		} else {
			fmt.Printf("Found pod %s in namespace %s\n", pod, namespace)
		}

		time.Sleep(10 * time.Second)
	}
}

func homeDir() string {
	if h := os.Getenv("HOME"); h != "" {
		return h
	}
	return os.Getenv("USERPROFILE") // windows
}

除了上边简单的查看pod的示例,同样还有一个deployment操作的示例

$go run create-update-delete-deployment/main.go 
Creating deployment...
Created deployment "demo-deployment".
-> Press Return key to continue.

Updating deployment...
Updated deployment...
-> Press Return key to continue.

Listing deployments in namespace "default":
 * demo-deployment (1 replicas)
-> Press Return key to continue.

Deleting deployment...
Deleted deployment.

 

在看另外一个网上的代码

package main

import (
    "k8s.io/client-go/tools/clientcmd"
    "k8s.io/client-go/kubernetes"
    appsv1beta1 "k8s.io/api/apps/v1beta1"
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    apiv1 "k8s.io/api/core/v1"
    "k8s.io/client-go/kubernetes/typed/apps/v1beta1"
    "flag"
    "fmt"
    "encoding/json"
)

func main() {
    // 运行的时候,通过命令行指定配置文件路径,如go run xxx.go -kubeconfig ~/.kube/config
    kubeconfig := flag.String("kubeconfig", "", "(optional) absolute path to the kubeconfig file")
    flag.Parse()

    // 解析到config
    config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
    if err != nil {
        panic(err.Error())
    }

    // 创建连接
    clientset, err := kubernetes.NewForConfig(config)
    if err != nil {
        panic(err.Error())
    }
    deploymentsClient := clientset.AppsV1beta1().Deployments(apiv1.NamespaceDefault)

    //创建deployment 并行调用
    go createDeployment(deploymentsClient)

    //监听deployment
    startWatchDeployment(deploymentsClient)
}

//监听Deployment变化
func startWatchDeployment(deploymentsClient v1beta1.DeploymentInterface) {
    w, _ := deploymentsClient.Watch(metav1.ListOptions{})
    for {
        select {
        case e, _ := <-w.ResultChan():
            fmt.Println(e.Type, e.Object)
        }
    }
}

//创建deployemnt,需要谨慎按照部署的k8s版本来使用api接口
func createDeployment(deploymentsClient v1beta1.DeploymentInterface)  {
    var r apiv1.ResourceRequirements
    //资源分配会遇到无法设置值的问题,故采用json反解析
    j := `{"limits": {"cpu":"2000m", "memory": "1Gi"}, "requests": {"cpu":"2000m", "memory": "1Gi"}}`
    json.Unmarshal([]byte(j), &r)

    deployment := &appsv1beta1.Deployment{
        ObjectMeta: metav1.ObjectMeta{
            Name: "engine",
            Labels: map[string]string{
                "app": "engine",
            },
        },
        Spec: appsv1beta1.DeploymentSpec{
            Replicas: int32Ptr2(1),
            Template: apiv1.PodTemplateSpec{
                ObjectMeta: metav1.ObjectMeta{
                    Labels: map[string]string{
                        "app": "engine",
                    },
                },
                Spec: apiv1.PodSpec{
                    Containers: []apiv1.Container{
                        {   Name:               "engine",
                            Image:           "my.com/engine:v2",
                            Resources: r,
                        },
                    },
                },
            },
        },
    }

    fmt.Println("Creating deployment...")
    result, err := deploymentsClient.Create(deployment)
    if err != nil {
        panic(err)
    }
    fmt.Printf("Created deployment %q.\n", result.GetObjectMeta().GetName())
}

func int32Ptr2(i int32) *int32 { return &i }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章