K8S 二次开发系列:1 client-go 使用

K8S 二次开发

我们在对一个东西进行二次开发的时候,我们需要有以下两点需要注意:

  • 知道各个组件的使用,这里我就不在介绍 K8S 和 docker 的一些使用
  • 熟悉对应的 api

在 K8S 中 api 也是对应的 http reset api ,这里使用的是 go-client

这里主要介绍的是开发 deployment+service

1 docker API 的 go 客户端

https://pkg.go.dev/github.com/docker/docker/client#section-readme

通过下面这个例子其实我们在二次开发一个东西的时候,需要对该服务本身的功能做了解,下面这个范例只是为了演示 go 的第三方包如何学习的一个过程

1.1 列出当前所有容器信息

可以通过 docker 的 sdk 实现对容器的列出

package main

import (
    "context"
    "fmt"

    "github.com/docker/docker/api/types"
    "github.com/docker/docker/client"
)

func main() {
    // 定义 docker 的 client
    cli, err := client.NewClientWithOpts(client.FromEnv)
    if err != nil {
        panic(err)
    }

    // 列出容器信息,返回一个切片
    containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{})
    if err != nil {
        panic(err)
    }

    // 遍历切片输出容器id 和使用的镜像
    for _, container := range containers {
        fmt.Printf("%s %s\n", container.ID[:10], container.Image)
    }
}

执行

[16:21:13 root@k8s-master ~]#./testdocker
container.ID=f14c5124c0,image=sha256:2297da0160d57032124efb335e38c52e20d252c5c494dbd8c88a9a2d02b41654
container.ID=aa0d42b638,image=sha256:181172b235b225c5644edae46296bd7c2305c05113e89a9b4274a952546743f4
container.ID=9202f8d8f9,image=sha256:296a6d5035e2d6919249e02709a488d680ddca91357602bd65e605eac967b899
container.ID=6d10a00ad5,image=registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.4.1
container.ID=63fee7086d,image=registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.4.1
container.ID=e6eadfccb8,image=sha256:296a6d5035e2d6919249e02709a488d680ddca91357602bd65e605eac967b899
container.ID=949870c1c0,image=sha256:ef4bce0a7569b4fa83a559717c608c076a2c9d30361eb059ea4e1b7a55424d68

1.2 创建容器

package main

import (
    "context"
    "fmt"

    "github.com/docker/docker/api/types"
    "github.com/docker/docker/api/types/container"
    "github.com/docker/docker/client"
    "github.com/docker/go-connections/nat"
)

func main() {
    cli, err := client.NewClientWithOpts(client.FromEnv)
    if err != nil {
        panic(err)
    }

    // 创建容器
    // context.TODO() 在我们不知道传递什么上下文的时候可以使用context.TODO()
    body, err := cli.ContainerCreate(context.TODO(), &container.Config{
        Tty:       true,
        OpenStdin: true,
        Image:     "nginx:1.16.1", // 该容器使用的镜像
    }, &container.HostConfig{
        // 容器端口 80 tcp 协议,暴露至宿主机的 8082,容器名为 testnginx
        PortBindings: nat.PortMap{nat.Port("80/tcp"): []nat.PortBinding{{"0.0.0.0", "8082"}}},
    }, nil, nil, "testnginx2")

    if err != nil {
        panic(err)
    }
    fmt.Println(boyd, err)

    // 通过 body 获取到容器 id
    containerID := body.ID

    // 启动容器
    err = cli.ContainerStart(context.TODO(), containerID, types.ContainerStartOptions{})
    fmt.Println(err)

}

执行程序

[10:09:34 root@k8s-master ~]#./testdocker 
{5aa50b5633a8c5fb510c687a94de29cced803f292cb5cb1495c4a806107e5edf []} <nil>

# 通过过滤查看该容器已经创建并启动
[10:09:39 root@k8s-master ~]#docker ps | grep testnginx
5aa50b5633a8   nginx:1.16.1                                                      "nginx -g 'daemon of…"   13 seconds ago   Up 11 seconds   127.0.0.1:8082->80/tcp   testnginx2

1.2.1 验证

浏览器验证该容器已经被创建

2 K8S client-go

这里使用的 client-go 是一个 K8S 的 SDK 工具

这里我使用的是 client-go 的 0.20.4 版本

https://pkg.go.dev/k8s.io/client-go@v0.20.4

进入到这个连接中找到我们需要使用的工具

client-go sdk 查看对应代码方法

1.kubectl api-resources 查看对应的 api 如 deployment 对应的 api 就是 apps.v1
2.然后 sdk 源码中找到对应的方法再点击到对应的方法或者接口
3.使用对应接口里面的方法实现创建
4.然后再我们的程序中编写代码

client-go 开发流程:

1.获取 K8S 配置文件
2.初始化配置文件
3.拿到 K8S 客户端
4.通过对于的资源类型进行编写代码

1.通过 kubectl api-resource 查看对应的 api

# 如果 apiversion 只有 v1 就是对应的 core.v1
[10:30:30 root@k8s-master ~]#kubectl api-resources 
NAME                              SHORTNAMES   APIVERSION                             NAMESPACED   KIND
bindings                                       v1                                     true         Binding
componentstatuses                 cs           v1                                     false        ComponentStatus
configmaps                        cm           v1                                     true         ConfigMap
endpoints                         ep           v1                                     true         Endpoints
events                            ev           v1                                     true         Event
limitranges                       limits       v1                                     true         LimitRange
namespaces                        ns           v1                                     false        Namespace
nodes                             no           v1                                     false        Node
persistentvolumeclaims            pvc          v1                                     true         PersistentVolumeClaim
persistentvolumes                 pv           v1                                     false        PersistentVolume
pods                              po           v1                                     true         Pod
podtemplates                                   v1                                     true         PodTemplate
replicationcontrollers            rc           v1                                     true         ReplicationController
resourcequotas                    quota        v1                                     true         ResourceQuota
secrets                                        v1                                     true         Secret
serviceaccounts                   sa           v1                                     true         ServiceAccount
services                          svc          v1                                     true         Service
mutatingwebhookconfigurations                  admissionregistration.k8s.io/v1        false        MutatingWebhookConfiguration
validatingwebhookconfigurations                admissionregistration.k8s.io/v1        false        ValidatingWebhookConfiguration
customresourcedefinitions         crd,crds     apiextensions.k8s.io/v1                false        CustomResourceDefinition
apiservices                                    apiregistration.k8s.io/v1              false        APIService
controllerrevisions                            apps/v1                                true         ControllerRevision
daemonsets                        ds           apps/v1                                true         DaemonSet
deployments                       deploy       apps/v1                                true         Deployment
replicasets                       rs           apps/v1                                true         ReplicaSet
statefulsets                      sts          apps/v1                                true         StatefulSet
tokenreviews                                   authentication.k8s.io/v1               false        TokenReview
localsubjectaccessreviews                      authorization.k8s.io/v1                true         LocalSubjectAccessReview
selfsubjectaccessreviews                       authorization.k8s.io/v1                false        SelfSubjectAccessReview
selfsubjectrulesreviews                        authorization.k8s.io/v1                false        SelfSubjectRulesReview
subjectaccessreviews                           authorization.k8s.io/v1                false        SubjectAccessReview
horizontalpodautoscalers          hpa          autoscaling/v1                         true         HorizontalPodAutoscaler
cronjobs                          cj           batch/v1                               true         CronJob
jobs                                           batch/v1                               true         Job
certificatesigningrequests        csr          certificates.k8s.io/v1                 false        CertificateSigningRequest
leases                                         coordination.k8s.io/v1                 true         Lease
endpointslices                                 discovery.k8s.io/v1                    true         EndpointSlice
events                            ev           events.k8s.io/v1                       true         Event
ingresses                         ing          extensions/v1beta1                     true         Ingress
flowschemas                                    flowcontrol.apiserver.k8s.io/v1beta1   false        FlowSchema
prioritylevelconfigurations                    flowcontrol.apiserver.k8s.io/v1beta1   false        PriorityLevelConfiguration
nodes                                          metrics.k8s.io/v1beta1                 false        NodeMetrics
pods                                           metrics.k8s.io/v1beta1                 true         PodMetrics
ingressclasses                                 networking.k8s.io/v1                   false        IngressClass
ingresses                         ing          networking.k8s.io/v1                   true         Ingress
networkpolicies                   netpol       networking.k8s.io/v1                   true         NetworkPolicy
runtimeclasses                                 node.k8s.io/v1                         false        RuntimeClass
poddisruptionbudgets              pdb          policy/v1                              true         PodDisruptionBudget
podsecuritypolicies               psp          policy/v1beta1                         false        PodSecurityPolicy
clusterrolebindings                            rbac.authorization.k8s.io/v1           false        ClusterRoleBinding
clusterroles                                   rbac.authorization.k8s.io/v1           false        ClusterRole
rolebindings                                   rbac.authorization.k8s.io/v1           true         RoleBinding
roles                                          rbac.authorization.k8s.io/v1           true         Role
priorityclasses                   pc           scheduling.k8s.io/v1                   false        PriorityClass
csidrivers                                     storage.k8s.io/v1                      false        CSIDriver
csinodes                                       storage.k8s.io/v1                      false        CSINode
csistoragecapacities                           storage.k8s.io/v1beta1                 true         CSIStorageCapacity
storageclasses                    sc           storage.k8s.io/v1                      false        StorageClass
volumeattachments                              storage.k8s.io/v1                      false        VolumeAttachment

我们都知道要创建这些资源的时候需要先创建 client,创建 client 需要使用一个 config 文件

2.1 获取到配置文件

因为我们都知道要创建这些资源的时候都需要看获取到 config 配置文件,因为这个请求需要去访问到我们的 api server

1.拷贝 config

# 这里我先将 K8S 集群中的配置文件拷贝至编写代码的服务器上
[10:32:15 root@k8s-master ~]#cd /root/.kube/

# 将配置文件拷贝至写代码的 K8S 项目中的 etc 文件中
[18:42:57 root@k8s-master .kube]#scp config 10.0.0.3:/root/project/testK8S/etc

2.在代码服务器上 get client-go@v0.20.4

[19:14:17 root@go testK8S]#go mod init testK8S 
[19:11:18 root@go testK8S]#go get k8s.io/client-go@v0.20.4
# 这样指定我的程序依赖这个包

[19:15:49 root@go testK8S]#go mod tidy

2.2 namespace

2.2.1 namespace 获取

通过代码实现获取 namespace 的列表,因为后续我们需要获取不同的 namespace 下的资源

// 初始化配置文件
func clientcmd.BuildConfigFromFlags(masterUrl string, kubeconfigPath string) (*rest.Config, error)
package main

import (
    "context"
    "fmt"
    "log"

    v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/tools/clientcmd"
)

func main() {
    // 配置文件路径
    kubeconfig := "etc/config"

    // 初始化配置文件拿到 config 结构体,因为我这里使用的 kubeconfig 所以不用写入 url
    config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
    if err != nil {
        panic(err)
    }

    // 通过 config 生成 client
    clientset, err := kubernetes.NewForConfig(config)
    if err != nil {
        log.Fatal(err)
    }

    // 争对不同的资源可以通过不同的 clientset api 获取
    // namespace 的 api 在 corev1 ,直接获取 namespace 接口
    namespaceClient := clientset.CoreV1().Namespaces()

    // 获取 namespace 列表
    namespaceList, err := namespaceClient.List(context.TODO(), v1.ListOptions{})
    if err != nil {
        log.Fatal(err)
    }

    // Items 是一个切片,Items是列表中命名空间对象的列表。
    for _, namespace := range namespaceList.Items {
        fmt.Println(namespace.Name)
    }
}

获取到对应的 namespace

[19:16:34 root@go testK8S]#go run main.go 
default
kube-node-lease
kube-public
kube-system
limits
mysql
role
web

2.2.2 namespace 删除

package main

import (
    "context"
    "log"

    v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/tools/clientcmd"
)

func main() {
    kubeconfig := "etc/config"

    // 初始化配置文件
    config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
    if err != nil {
        log.Fatal(err)
    }

    // 创建 K8S 客户端
    clientSet, err := kubernetes.NewForConfig(config)
    if err != nil {
        log.Fatal(err)
    }

    // 定义 namespaceclient
    namespaceClitn := clientSet.CoreV1().Namespaces()

    // 删除 web namespace
    err = namespaceClitn.Delete(context.TODO(), "web", v1.DeleteOptions{})
    if err != nil {
        log.Fatal(err)
    }
}

运行程序

[19:19:19 root@go testK8S]#go run main.go 

2.3 deployment

deployment 列表获取、创建、修改、删除

2.3.1 获取所有 namespace 下 deployment

package main

import (
    "context"
    "fmt"
    "log"

    v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/tools/clientcmd"
)

// K8S 配置初始化
func k8sConfig() *kubernetes.Clientset {
    kubeconfig := "etc/config"

    config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
    if err != nil {
        log.Fatal(err)
    }
    clientSet, err := kubernetes.NewForConfig(config)
    if err != nil {
        log.Fatal(err)
    }
    return clientSet
}

// namespace 获取
func Namespace() []string {
    namespaceClient := k8sConfig().CoreV1().Namespaces()
    namespaceList, err := namespaceClient.List(context.TODO(), v1.ListOptions{})
    if err != nil {
        log.Fatal(err)
    }

    namesapces := []string{}
    for _, namespace := range namespaceList.Items {
        namesapces = append(namesapces, namespace.Name)
    }

    return namesapces

}

// deployment 获取
func Deployment() {
    for _, namespaces := range Namespace() {
        deploymentClient := k8sConfig().AppsV1().Deployments(namespaces)
        deploymentList, err := deploymentClient.List(context.TODO(), v1.ListOptions{})
        if err != nil {
            log.Fatal(err)
        } else {
            for _, deployment := range deploymentList.Items {
                fmt.Printf("namespace:%s name:%s\n", deployment.Namespace, deployment.Name)
            }
        }
    }
}

func main() {
    // 调用函数
    Deployment()
}

# 获取到所有的 namespace 下的 deployment 
[21:50:40 root@go testK8S]#go run main.go 
namespace:kube-system name:calico-kube-controllers
namespace:kube-system name:coredns
namespace:kube-system name:metrics-server
namespace:web name:web-tomcat-app1-deployment

2.3.2 删除指定的 deployment

package main

import (
    "context"
    "fmt"
    "log"

    v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/tools/clientcmd"
)

// K8S 配置初始化
func k8sConfig() *kubernetes.Clientset {
    kubeconfig := "etc/config"

    config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
    if err != nil {
        log.Fatal(err)
    }
    clientSet, err := kubernetes.NewForConfig(config)
    if err != nil {
        log.Fatal(err)
    }
    return clientSet
}

// namespace 获取
func GetNamespace() []string {
    namespaceClient := k8sConfig().CoreV1().Namespaces()
    namespaceList, err := namespaceClient.List(context.TODO(), v1.ListOptions{})
    if err != nil {
        log.Fatal(err)
    }

    namesapces := []string{}
    for _, namespace := range namespaceList.Items {
        namesapces = append(namesapces, namespace.Name)
    }
    return namesapces

}

// deployment 获取
func GetDeployment() {
    for _, namespaces := range GetNamespace() {
        deploymentClient := k8sConfig().AppsV1().Deployments(namespaces)
        deploymentList, err := deploymentClient.List(context.TODO(), v1.ListOptions{})
        if err != nil {
            log.Fatal(err)
        } else {
            for _, deployment := range deploymentList.Items {
                fmt.Printf("namespace:%s name:%s\n", deployment.Namespace, deployment.Name)
            }
        }
    }

}

// deployment 删除 web namespace 下的 web-tomcat-app1-deployment 
func DelDeployment() {
    deploymentClient := k8sConfig().AppsV1().Deployments("web")
    err := deploymentClient.Delete(context.TODO(), "web-tomcat-app1-deployment", v1.DeleteOptions{})
    if err != nil {
        log.Fatal(err)
    } else {
        fmt.Println("web deployment delete success!")
    }

}

func main() {
    DelDeployment()
}

# 删除成功
[21:59:34 root@go testK8S]#go run main.go 
web deployment delete success!

2.3.3 创建 deployment

在创建 deployment 的时候就需要指定创建到那个 namespace 下,这里我将创建到默认的 namespace 下

package main

import (
    "context"
    "fmt"
    "log"

    appsv1 "k8s.io/api/apps/v1"
    corev1 "k8s.io/api/core/v1"
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/tools/clientcmd"
)

// K8S 配置初始化
func k8sConfig() *kubernetes.Clientset {
    kubeconfig := "etc/config"

    config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
    if err != nil {
        log.Fatal(err)
    }
    clientSet, err := kubernetes.NewForConfig(config)
    if err != nil {
        log.Fatal(err)
    }
    return clientSet
}

// 由于在创建 deployment 的时候需要指定副本集,而且是一个 int32 的指针类型
func Int32ptr(i int32) *int32 {
    return &i
}

// 创建 deployment
func CreateDeployment() {
    // 通过 config 生成 K8S Deployments.client
    deploymentClient := k8sConfig().AppsV1().Deployments("web")

    // 对 deployment 的操作是 create
    deployment, err := deploymentClient.Create(context.TODO(), &appsv1.Deployment{
        // meta 字段,定义这个 deployment 的 name 和所在的 namespace 以及标签
        ObjectMeta: metav1.ObjectMeta{
            Name:      "test-golang",
            Namespace: "web",
            Labels:    map[string]string{"app": "test-golang"},
        },

        // spec 字段,定义副本数等
        Spec: appsv1.DeploymentSpec{
            Replicas: Int32ptr(2),
            Selector: &metav1.LabelSelector{
                MatchLabels: map[string]string{"app": "test-golang"},
            },
            // template 字段
            Template: corev1.PodTemplateSpec{
                ObjectMeta: metav1.ObjectMeta{
                    Labels: map[string]string{"app": "test-golang"},
                },

                // template.spec 字段
                Spec: corev1.PodSpec{
                    Containers: []corev1.Container{
                        {
                            Name:            "test",
                            Image:           "nginx:1.16.1",
                            ImagePullPolicy: corev1.PullIfNotPresent,
                            Ports: []corev1.ContainerPort{
                                {
                                    Name:          "http",
                                    ContainerPort: 80,
                                    Protocol:      corev1.ProtocolTCP,
                                },
                            },
                        },
                    },
                },
            },
        },
    }, metav1.CreateOptions{})

    if err != nil {
        log.Fatal(err)
    } else {
        fmt.Printf("deployment Create success!\n%v\n", &deployment.Status)
    }

}

func main() {
    CreateDeployment()
}

执行:

[14:34:56 root@go testK8S]#go run main.go 
deployment Create success!
&DeploymentStatus{ObservedGeneration:0,Replicas:0,UpdatedReplicas:0,AvailableReplicas:0,UnavailableReplicas:0,Conditions:[]DeploymentCondition{},ReadyReplicas:0,CollisionCount:nil,}

在 K8S 上查看

# pod 已经创建成功,副本数为 2 
[16:03:04 root@k8s-master k8syaml]#kubectl get pod -n web 
NAME                           READY   STATUS    RESTARTS   AGE
test-golang-7f5b4bb549-57f58   1/1     Running   0          39m
test-golang-7f5b4bb549-rl4b6   1/1     Running   0          39m

# deployment 创建成功
[16:02:56 root@k8s-master k8syaml]#kubectl get deployments.apps -n web
NAME          READY   UP-TO-DATE   AVAILABLE   AGE
test-golang   2/2     2            2           37m

# 查看详细信息和程序中的一样
[16:04:38 root@k8s-master k8syaml]#kubectl describe deployments.apps -n web test-golang 
Name:                   test-golang
Namespace:              web
CreationTimestamp:      Tue, 09 Nov 2021 15:25:18 +0800
Labels:                 app=test-golang
Annotations:            deployment.kubernetes.io/revision: 1
Selector:               app=test-golang
Replicas:               2 desired | 2 updated | 2 total | 2 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=test-golang
  Containers:
   test:
    Image:        nginx:1.16.1
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Available      True    MinimumReplicasAvailable
  Progressing    True    NewReplicaSetAvailable
OldReplicaSets:  <none>
NewReplicaSet:   test-golang-7f5b4bb549 (2/2 replicas created)
Events:
  Type    Reason             Age   From                   Message
  ----    ------             ----  ----                   -------
  Normal  ScalingReplicaSet  39m   deployment-controller  Scaled up replica set test-golang-7f5b4bb549 to 2

2.3.4 修改 deployment

这里我就修改刚才上面创建的 web namespace 下的 deployment ,将副本集改为对应的,如果说想修改其他熟悉也是一样的

2.3.4.1 修改 deployment 副本集

package main

import (
    "context"
    "fmt"
    "log"

    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/tools/clientcmd"
)

// K8S 配置初始化
func k8sConfig() *kubernetes.Clientset {
    kubeconfig := "etc/config"

    config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
    if err != nil {
        log.Fatal(err)
    }
    clientSet, err := kubernetes.NewForConfig(config)
    if err != nil {
        log.Fatal(err)
    }
    return clientSet
}

// 由于在创建 deployment 的时候需要指定副本集,而且是一个 int32 的指针类型
func Int32ptr(i int32) *int32 {
    return &i
}


// deployment 修改
func EditDeployment() {
    deploymentClient := k8sConfig().AppsV1().Deployments("web")

    // 在修改 deployment 之前肯定需要先找到对应的 deployment,找到 test-golang 的 deployment
    deployment, err := deploymentClient.Get(context.TODO(), "test-golang", metav1.GetOptions{})
    if err != nil {
        log.Fatal(err)
    }

    // deployment.Spec.Replicas 获取的是一个指针,所以需要取地址
    // 如果副本大于 2 就 - 1 ,否则 + 1
    if *deployment.Spec.Replicas > 2 {
        deployment.Spec.Replicas = Int32ptr(*deployment.Spec.Replicas - 1)
    } else {
        deployment.Spec.Replicas = Int32ptr(*deployment.Spec.Replicas + 1)
    }

deployment, err = deploymentClient.Update(context.TODO(), deployment, metav1.UpdateOptions{})
    if err != nil {
        log.Fatal(err)
    } else {
        fmt.Printf("deployment : %s ,replocas=%d update success!\n", deployment.Name, *deployment.Spec.Replicas)
    }

}

执行

[16:46:43 root@go testK8S]#go run main.go 
deployment : test-golang ,replocas=2 update success!

K8S 节点查看

# 副本数以修改为 1
[16:49:16 root@k8s-master k8syaml]#kubectl get deployments.apps -n web test-golang 
NAME          READY   UP-TO-DATE   AVAILABLE   AGE
test-golang   2/2     2            2           84m

# pod 变为 1
[16:33:47 root@k8s-master k8syaml]#kubectl get pod -n web 
NAME                           READY   STATUS    RESTARTS   AGE
test-golang-7f5b4bb549-4n9vr   1/1     Running   0          8s
test-golang-7f5b4bb549-rl4b6   1/1     Running   0          83m


2.3.4.2 修改 deployment 镜像

这里修改容器的镜像

package main

import (
    "context"
    "fmt"
    "log"

    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/tools/clientcmd"
)

// K8S 配置初始化
func k8sConfig() *kubernetes.Clientset {
    kubeconfig := "etc/config"

    config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
    if err != nil {
        log.Fatal(err)
    }
    clientSet, err := kubernetes.NewForConfig(config)
    if err != nil {
        log.Fatal(err)
    }
    return clientSet
}

// deployment 修改容器镜像
func EditImage() {
    deploymentClient := k8sConfig().AppsV1().Deployments("web")
    // 在修改 deployment 之前肯定需要先找到对应的 deployment,找到 test-golang 的 deployment
    deployment, err := deploymentClient.Get(context.TODO(), "test-golang", metav1.GetOptions{})
    if err != nil {
        log.Fatal(err)
    }

    // 修改 deployment.Spec.Template.Spec.Containers.image 字段
    // 需要更新的镜像,这里改为 nginx:1.21.3
    deployment.Spec.Template.Spec.Containers[0].Image = "nginx:1.21.3"
    deployment, err = deploymentClient.Update(context.TODO(), deployment, metav1.UpdateOptions{})
    if err != nil {
        log.Fatal(err)
    } else {
        fmt.Printf("deployment : %s image update success!\n", deployment.Name)
    }
}

func main() {
    EditImage()
}
[17:26:34 root@go testK8S]#go run main.go 
deployment : test-golang ,image update success!

K8S 节点验证

# 通过 grep 过滤 nginx 镜像已经修改为了 nginx:1.21.3
[17:26:55 root@k8s-master k8syaml]#kubectl describe pod -n web test-golang-5ccbff5ff7- | grep image
  Normal  Pulled     24s   kubelet            Container image "nginx:1.21.3" already present on machine
  Normal  Pulled     22s   kubelet            Container image "nginx:1.21.3" already present on machine
  Normal  Pulled     20s   kubelet            Container image "nginx:1.21.3" already present on machine

2.4 service

service 获取、创建、修改、删除

2.4.1 service 获取

package main

import (
    "context"
    "fmt"
    "log"

    v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/tools/clientcmd"
)

// K8S 配置初始化
func k8sConfig() *kubernetes.Clientset {
    kubeconfig := "etc/config"

    config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
    if err != nil {
        log.Fatal(err)
    }
    clientSet, err := kubernetes.NewForConfig(config)
    if err != nil {
        log.Fatal(err)
    }
    return clientSet
}

// namespace 获取
func GetNamespace() []string {
    namespaceClient := k8sConfig().CoreV1().Namespaces()
    namespaceList, err := namespaceClient.List(context.TODO(), v1.ListOptions{})
    if err != nil {
        log.Fatal(err)
    }

    namesapces := []string{}
    for _, namespace := range namespaceList.Items {
        namesapces = append(namesapces, namespace.Name)
    }
    return namesapces

}

// deployment 获取
func GetDeployment() {
    for _, namespaces := range GetNamespace() {
        deploymentClient := k8sConfig().AppsV1().Deployments(namespaces)
        deploymentList, err := deploymentClient.List(context.TODO(), v1.ListOptions{})
        if err != nil {
            log.Fatal(err)
        } else {
            for _, deployment := range deploymentList.Items {
                fmt.Printf("namespace:%s name:%s\n", deployment.Namespace, deployment.Name)
            }
        }
    }

}

// deployment 删除
func DelDeployment() {
    deploymentClient := k8sConfig().AppsV1().Deployments("web")
    err := deploymentClient.Delete(context.TODO(), "web-tomcat-app1-deployment", v1.DeleteOptions{})
    if err != nil {
        log.Fatal(err)
    } else {
        fmt.Println("web deployment delete success!")
    }
}

// svc 获取
func GetSvc() {
    for _, namespace := range GetNamespace() {
        svcClient := k8sConfig().CoreV1().Services(namespace)
        svcList, err := svcClient.List(context.TODO(), v1.ListOptions{})
        if err != nil {
            log.Fatal(err)
        } else {
            // 获取 svc 基础信息
            for _, svc := range svcList.Items {
                fmt.Printf("\n-------------\nNameSpace:%s\nSvcName:%s\nClusterIP:%s\nLabels:%s\n",
                    svc.Namespace, svc.Name, svc.Spec.ClusterIP, svc.Labels)
                // 获取 svc port 信息
                for _, port := range svc.Spec.Ports {
                    fmt.Printf("Protocol:%s\nPodPort:%d\nNodePort:%d\n", port.Protocol, port.Port, port.NodePort)
                }
            }
        }
    }

}

func main() {
    GetSvc()
}

[22:20:21 root@go testK8S]#go run main.go 

-------------
NameSpace:default
SvcName:kubernetes
ClusterIP:172.30.0.1
Labels:map[component:apiserver provider:kubernetes]
Protocol:TCP
PodPort:443
NodePort:0

-------------
NameSpace:kube-system
SvcName:kube-dns
ClusterIP:172.30.0.10
Labels:map[k8s-app:kube-dns kubernetes.io/cluster-service:true kubernetes.io/name:CoreDNS]
Protocol:UDP
PodPort:53
NodePort:0
Protocol:TCP
PodPort:53
NodePort:0
Protocol:TCP
PodPort:9153
NodePort:0

-------------
NameSpace:kube-system
SvcName:metrics-server
ClusterIP:172.30.90.118
Labels:map[k8s-app:metrics-server]
Protocol:TCP
PodPort:443
NodePort:0

-------------
NameSpace:web
SvcName:web-tomcat-app1-service
ClusterIP:172.30.160.50
Labels:map[app:web-tomcat-app1-service-label]
Protocol:TCP
PodPort:80
NodePort:28080
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇