- client-go示例
- kubernetes-client-go-sample
- kubernetes-client-go-sample
client-go示例
访问kubernetes集群有几下几种方式:
| 方式 | 特点 | 支持者 |
|---|---|---|
| Kubernetes dashboard | 直接通过Web UI进行操作,简单直接,可定制化程度低 | 官方支持 |
| kubectl | 命令行操作,功能最全,但是比较复杂,适合对其进行进一步的分装,定制功能,版本适配最好 | 官方支持 |
| client-go | 从kubernetes的代码中抽离出来的客户端包,简单易用,但需要小心区分kubernetes的API版本 | 官方支持 |
| client-python | python客户端,kubernetes-incubator | 官方支持 |
| Java client | fabric8中的一部分,kubernetes的java客户端 | redhat |
下面,我们基于client-go,对Deployment升级镜像的步骤进行了定制,通过命令行传递一个Deployment的名字、应用容器名和新image名字的方式来升级。代码和使用方式见 https://github.com/rootsongjc/kubernetes-client-go-sample 。
kubernetes-client-go-sample
代码如下:
package mainimport ("flag""fmt""os""path/filepath""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")func main() {var kubeconfig *stringif 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")}deploymentName := flag.String("deployment", "", "deployment name")imageName := flag.String("image", "", "new image name")appName := flag.String("app", "app", "application name")flag.Parse()if *deploymentName == "" {fmt.Println("You must specify the deployment name.")os.Exit(0)}if *imageName == "" {fmt.Println("You must specify the new image name.")os.Exit(0)}// use the current context in kubeconfigconfig, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)if err != nil {panic(err.Error())}// create the clientsetclientset, err := kubernetes.NewForConfig(config)if err != nil {panic(err.Error())}deployment, err := clientset.AppsV1beta1().Deployments("default").Get(*deploymentName, metav1.GetOptions{})if err != nil {panic(err.Error())}if errors.IsNotFound(err) {fmt.Printf("Deployment not found\n")} else if statusError, isStatus := err.(*errors.StatusError); isStatus {fmt.Printf("Error getting deployment%v\n", statusError.ErrStatus.Message)} else if err != nil {panic(err.Error())} else {fmt.Printf("Found deployment\n")name := deployment.GetName()fmt.Println("name ->", name)containers := &deployment.Spec.Template.Spec.Containersfound := falsefor i := range *containers {c := *containersif c[i].Name == *appName {found = truefmt.Println("Old image ->", c[i].Image)fmt.Println("New image ->", *imageName)c[i].Image = *imageName}}if found == false {fmt.Println("The application container not exist in the deployment pods.")os.Exit(0)}_, err := clientset.AppsV1beta1().Deployments("default").Update(deployment)if err != nil {panic(err.Error())}}}func homeDir() string {if h := os.Getenv("HOME"); h != "" {return h}return os.Getenv("USERPROFILE") // windows}
我们使用kubeconfig文件认证连接kubernetes集群,该文件默认的位置是$HOME/.kube/config。
该代码编译后可以直接在kubernetes集群之外,任何一个可以连接到API server的机器上运行。
编译运行
$ go get github.com/rootsongjc/kubernetes-client-go-sample$ cd $GOPATH/src/github.com/rootsongjc/kubernetes-client-go-sample$ make$ ./update-deployment-image -hUsage of ./update-deployment-image:-alsologtostderrlog to standard error as well as files-app stringapplication name (default "app")-deployment stringdeployment name-image stringnew image name-kubeconfig string(optional) absolute path to the kubeconfig file (default "/Users/jimmy/.kube/config")-log_backtrace_at valuewhen logging hits line file:N, emit a stack trace-log_dir stringIf non-empty, write log files in this directory-logtostderrlog to standard error instead of files-stderrthreshold valuelogs at or above this threshold go to stderr-v valuelog level for V logs-vmodule valuecomma-separated list of pattern=N settings for file-filtered logging
使用不存在的image更新
$ ./update-deployment-image -deployment filebeat-test -image harbor-001.jimmysong.io/library/analytics-docker-test:Build_9Found deploymentname -> filebeat-testOld image -> harbor-001.jimmysong.io/library/analytics-docker-test:Build_8New image -> harbor-001.jimmysong.io/library/analytics-docker-test:Build_9
查看Deployment的event。
$ kubectl describe deployment filebeat-testName: filebeat-testNamespace: defaultCreationTimestamp: Fri, 19 May 2017 15:12:28 +0800Labels: k8s-app=filebeat-testSelector: k8s-app=filebeat-testReplicas: 2 updated | 3 total | 2 available | 2 unavailableStrategyType: RollingUpdateMinReadySeconds: 0RollingUpdateStrategy: 1 max unavailable, 1 max surgeConditions:Type Status Reason---- ------ ------Available True MinimumReplicasAvailableProgressing True ReplicaSetUpdatedOldReplicaSets: filebeat-test-2365467882 (2/2 replicas created)NewReplicaSet: filebeat-test-2470325483 (2/2 replicas created)Events:FirstSeen LastSeen Count From SubObjectPath Type ReasoMessage--------- -------- ----- ---- ------------- -------- ------------2h 1m 3 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set filebeat-test-2365467882 to 21m 1m 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set filebeat-test-2470325483 to 11m 1m 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set filebeat-test-2470325483 to 2
可以看到老的ReplicaSet从3个replica减少到了2个,有2个使用新配置的replica不可用,目前可用的replica是2个。
这是因为我们指定的镜像不存在,查看Deployment的pod的状态。
$ kubectl get pods -l k8s-app=filebeat-testNAME READY STATUS RESTARTS AGEfilebeat-test-2365467882-4zwx8 2/2 Running 0 33dfilebeat-test-2365467882-rqskl 2/2 Running 0 33dfilebeat-test-2470325483-6vjbw 1/2 ImagePullBackOff 0 4mfilebeat-test-2470325483-gc14k 1/2 ImagePullBackOff 0 4m
我们可以看到有两个pod正在拉取image。
还原为原先的镜像
将image设置为原来的镜像。
$ ./update-deployment-image -deployment filebeat-test -image harbor-001.jimmysong.io/library/analytics-docker-test:Build_8Found deploymentname -> filebeat-testOld image -> harbor-001.jimmysong.io/library/analytics-docker-test:Build_9New image -> harbor-001.jimmysong.io/library/analytics-docker-test:Build_8
现在再查看Deployment的状态。
$ kubectl describe deployment filebeat-testName: filebeat-testNamespace: defaultCreationTimestamp: Fri, 19 May 2017 15:12:28 +0800Labels: k8s-app=filebeat-testSelector: k8s-app=filebeat-testReplicas: 3 updated | 3 total | 3 available | 0 unavailableStrategyType: RollingUpdateMinReadySeconds: 0RollingUpdateStrategy: 1 max unavailable, 1 max surgeConditions:Type Status Reason---- ------ ------Available True MinimumReplicasAvailableProgressing True NewReplicaSetAvailableOldReplicaSets: <none>NewReplicaSet: filebeat-test-2365467882 (3/3 replicas created)Events:FirstSeen LastSeen Count From SubObjectPath Type ReasoMessage--------- -------- ----- ---- ------------- -------- ------------2h 8m 3 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set filebeat-test-2365467882 to 28m 8m 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set filebeat-test-2470325483 to 18m 8m 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set filebeat-test-2470325483 to 22h 1m 3 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set filebeat-test-2365467882 to 31m 1m 1 {deployment-controller } Normal ScalingReplicaSet Scaled down replica set filebeat-test-2470325483 to 0
可以看到available的replica个数恢复成3了。
其实在使用该命令的过程中,通过kubernetes dashboard的页面上查看Deployment的状态更直观,更加方便故障排查。

这也是dashboard最大的优势,简单、直接、高效。
