(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 }