Tương tác với Kubernetes sử dụng Golang (P2)

Giới thiệu Link bài viết gốc trên blog của mình: https://ductn.info/controller-kubernetes-with-golang-2/ Nối tiếp phần 1 mình thực hiện tiếp 1 tool cho cụm kubernetes sử dụng thư viện client-go. Ở phần trước, mình đã demo in ra list tên của các pods trong cụm kubernetes, trong phần này mình sẽ làm 1 tool giúp chúng

Giới thiệu

Link bài viết gốc trên blog của mình: https://ductn.info/controller-kubernetes-with-golang-2/

Nối tiếp phần 1
mình thực hiện tiếp 1 tool cho cụm kubernetes sử dụng thư viện client-go.

Ở phần trước, mình đã demo in ra list tên của các pods trong cụm kubernetes,
trong phần này mình sẽ làm 1 tool giúp chúng có thể update phiên bản image
đang được sử dụng trong deployment và deploy lại container theo image mới.

Trông ứng dụng sẽ như thế này :3

Kugo

Link source code đây nha: https://github.com/ductnn/kugo

Start

Vẫn giống như phần trước,
để bắt đầu anh em cài đặt golang và set up cụm kubernetes, sau đó anh em có
thể xem lại bước 1-2 ở phần 1 để khởi tạo tool nhé :3.

package main

import (
	"context"
	"flag"
	"fmt"
	"os"

	"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"
	"k8s.io/client-go/util/homedir"
)

// Kube config path
func GetKubeConfigPath() string {
	var kubeConfigPath string
	homeDir := homedir.HomeDir()

	if _, err := os.Stat(homeDir + "/.kube/config"); err == nil {
		kubeConfigPath = homeDir + "/.kube/config"
	} else {
		fmt.Println("Enter kubernetes config directory: ")
		fmt.Scanf("%s", kubeConfigPath)
	}

	return kubeConfigPath
}

func main() {
	// Set Kube config
	kubeConfigPath := GetKubeConfigPath()
	fmt.Println(kubeConfigPath)

	// Build configuration from config file
	config, err := clientcmd.BuildConfigFromFlags("", kubeConfigPath)
	if err != nil {
		panic(err)
	}

	// Create clientser
	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		panic(err)
	}
}

Mình sử dụng flag là package nổi tiếng của golang
hỗ trợ chúng ta truyền vào các flagscommand. Ví dụ như demo ở bên trên
mình truyền vào 3 flags sau khi build file main.go.

-deployment test-app
-app test-app
-image ductn4/green-rain:v2

Chúng ta sẽ dùng flag để tạo những commad flags như ví dụ trên. Chúng ta có
thể sử dụng os.Args[] từ os package. Đối với cli tool nhỏ thì dùng os.Args[]
xong check. Còn không dùng flag sẽ tiện hơn. Ngoài ra, flag hỗ trợ luôn -h
cho chúng ta để show ra ý nghĩa của flag trong command:

➜  kugo git:(master) ✗ ./main -h
/Users/ductn/.kube/config
Usage of ./main:
  -app string
    	application name (default "app")
  -deployment string
    	deployment name
  -image string
    	new image name

OK!!! Bắt đầu tạo ra các flags:

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("The deployment name must be specify.")
    os.Exit(0)
}
if *imageName == "" {
    fmt.Println("The new image name must be specify.")
    os.Exit(0)
}

-deployment name:<string>: Tên của deployment đang chạy.

-app name:<string>: Tên của ứng dụng đang chạy.

-image name:<string>: Tên image mới cần deploy.

Sau khi tạo xong flag, chúng ta khởi tạo deployment, phần này giống như
khởi tạo pods trong phần trước:

// Create Deployment
deployment, err := clientset.AppsV1().Deployments("default").Get(context.TODO(), *deploymentName, metav1.GetOptions{})
if err != nil {
    panic(err)
}

Tiếp theo, chúng ta thực hiện check để kiểm tra trạng thái của deployment
xem có bị lỗi hoặc chưa deploy:

if errors.IsNotFound(err) {
    fmt.Printf("Deployment not foundn")
} else if statusError, isStatus := err.(*errors.StatusError); isStatus {
    fmt.Printf("Error getting deployment%vn", statusError.ErrStatus.Message)
} else if err != nil {
    panic(err)
} else {
    // Next step ...
}

Kiểm tra xong, chúng ta sẽ thực hiện thay thế image cũ thành image mới:

containers := &deployment.Spec.Template.Spec.Containers
found := false

for i := range *containers {
    c := *containers
    if c[i].Name == *appName {
        fmt.Println("Old Version Image: ", c[i].Image)
        fmt.Println("New Version Image: ", *imageName)
        c[i].Image = *imageName
        found = true
    }
}

Cuối cùng, chúng ta sẽ update lại deployment theo phiên bản mới của image

_, err := clientset.AppsV1().Deployments("default").Update(context.TODO(), deployment, metav1.UpdateOptions{})
if err != nil {
    panic(err)
}

Demo

Bước 1: Mình sẽ deploy 1 deployment cùng với service: NodePort, mình
có tạo sẵn 1 file deploymentđây
anh em có thể dùng luôn:

test git:(master) ✗ kubectl apply -f deployment.yml
service/app-service created
deployment.apps/test-app created
➜  test git:(master) ✗ kubectl get all
NAME                            READY   STATUS    RESTARTS   AGE
pod/test-app-64d48d75c7-ctztl   1/1     Running   0          51s

NAME                  TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
service/app-service   NodePort    10.99.148.96   <none>3000:32691/TCP   51s
service/kubernetes    ClusterIP   10.96.0.1      <none>443/TCP          3m31s

NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/test-app   1/1     11           51s

NAME                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/test-app-64d48d75c7   111       51s

Mình sử dụng image: ductn4/green-rain:v1.0.1 để build 1 hiệu ứng nhỏ, anh em
bật vô xem đẹp lắm :3

Bước 2: Build đống code vừa viết nào :3, sau khi build xong sẽ sinh ra 1
file main

➜  kugo git:(master) ✗ go build main.go
➜  kugo git:(master)ls
README.md go.mod    go.sum    main      main.go   test

Bước 3: Thực thi file main vừa tạo ra:

➜  kugo git:(master) ✗ ./main -deployment test-app -app test-app -image ductn4/green-rain:v2
/Users/ductn/.kube/config
Found deployment
Name deployment:  test-app
Old Version Image:  ductn4/green-rain:v1.0.1
New Version Image:  ductn4/green-rain:v2

Anh em thấy đã có thông báo thay đổi version của image, Check tý coi :3

➜  kugo git:(master) ✗ kubectl describe pods test-app-67c5b469d7-9k6lb
Name:         test-app-67c5b469d7-9k6lb
Namespace:    default
Priority:     0
Node:         minikube/192.168.49.2
Start Time:   Mon, 16 Aug 202123:58:39 +0700
Labels:       app=test-app
              pod-template-hash=67c5b469d7
Annotations:  <none>
Status:       Running
IP:           172.17.0.4
IPs:
  IP:           172.17.0.4
Controlled By:  ReplicaSet/test-app-67c5b469d7
Containers:
  test-app:
    Container ID:   docker://bd06a004dee744207fd955191ed1df2e204254b1a44a2e1f0cc8e7c9bef20a4d
    Image:          ductn4/green-rain:v2
    Image ID:       docker-pullable://ductn4/[email protected]:31ec7424010c546d7cc028bf0355ec9dd58e4818e8cc3e266ff44a9ff7a3c109
    Port:           3000/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Mon, 16 Aug 202123:58:48 +0700
    Ready:          True
    ...

Vậy là image đã được update và deploy thành công, anh em vô xem lại hiệu ứng
nha, ver 2 nhìn xịn hơn ver 1 ở trên :3.

Mình đã làm xong tiếp 1 cái tool nhỏ nữa, anh em nào còn có ý tưởng gì hay hay
chia sẻ để có thể cùng làm nha :3

Cảm ơn anh em đã đọc 😄😄😄.

Nguồn: viblo.asia

Bài viết liên quan

WebP là gì? Hướng dẫn cách để chuyển hình ảnh jpg, png qua webp

WebP là gì? WebP là một định dạng ảnh hiện đại, được phát triển bởi Google

Điểm khác biệt giữa IPv4 và IPv6 là gì?

IPv4 và IPv6 là hai phiên bản của hệ thống địa chỉ Giao thức Internet (IP). IP l

Check nameservers của tên miền xem website trỏ đúng chưa

Tìm hiểu cách check nameservers của tên miền để xác định tên miền đó đang dùn

Mình đang dùng Google Domains để check tên miền hàng ngày

Từ khi thông báo dịch vụ Google Domains bỏ mác Beta, mình mới để ý và bắt đầ