利用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 }

 

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