我们如何与 Kubernetes 进行交互
最常用的方式是使用一个名为 https://github.com/kubernetes/kubectl 的命令行工具。
有时我们需要开发应用程序来与 Kubernetes 集群进行交互。
client-go
client-go 是用于与 kubernetes 集群通信的 Go 客户端。在 client-go 中,我们可以使用 Pod API 与 Kubernetes 进行通信并与 Pod 进行交互。
Pod
Pod是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元。
// https://github1s.com/kubernetes/kubernetes/blob/master/pkg/apis/core/types.go#L3995-L4010
type Pod struct {
metav1.TypeMeta
// +optional
metav1.ObjectMeta
// Spec defines the behavior of a pod.
// +optional
Spec PodSpec
// Status represents the current information about a pod. This data may not be up
// to date.
// +optional
Status PodStatus
}
Pod(就像在鲸鱼荚或者豌豆荚中)是一组(一个或多个) 容器; 这些容器共享存储、网络、以及运行这些容器的声明。 Pod 中的内容总是一同调度,在共享的上下文中运行。 Pod构建了一个 “逻辑主机”,其中包含一个或多个应用容器, 这些容器相对紧密地耦合在一起。
我们通过client-go与Kubernetes交互对Pod进行管理,Pod相关的的API如下:
// https://github.com/kubernetes/client-go/blob/master/kubernetes/typed/core/v1/pod.go
// PodInterface has methods to work with Pod resources.
type PodInterface interface {
Create(ctx context.Context, pod *v1.Pod, opts metav1.CreateOptions) (*v1.Pod, error)
Update(ctx context.Context, pod *v1.Pod, opts metav1.UpdateOptions) (*v1.Pod, error)
UpdateStatus(ctx context.Context, pod *v1.Pod, opts metav1.UpdateOptions) (*v1.Pod, error)
Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error
DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error
Get(ctx context.Context, name string, opts metav1.GetOptions) (*v1.Pod, error)
List(ctx context.Context, opts metav1.ListOptions) (*v1.PodList, error)
Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error)
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.Pod, err error)
Apply(ctx context.Context, pod *corev1.PodApplyConfiguration, opts metav1.ApplyOptions) (result *v1.Pod, err error)
ApplyStatus(ctx context.Context, pod *corev1.PodApplyConfiguration, opts metav1.ApplyOptions) (result *v1.Pod, err error)
UpdateEphemeralContainers(ctx context.Context, podName string, pod *v1.Pod, opts metav1.UpdateOptions) (*v1.Pod, error)
}
可以看到除了常用的CRUD的操作外,还有Apply
、ApplyStatus
、Watch
等Kubernetes提供的API
编写程序读取pod信息
我们编写一个小程序,读取集群的pod信息
➜ golang mkdir -p client-go-app
➜ golang cd client-go-app
➜ client-go-app go mod init github.com/jxs1211/client-go-app
go: creating new go.mod: module github.com/jxs1211/client-go-app
➜ client-go-app code .
➜ client-go-app
从本地读取配置文件
package main
import (
"log"
"os/exec"
"os/user"
"strings"
)
func main() {
user, err := user.Current()
if err != nil {
log.Fatal(err)
}
cmd := exec.Command("echo", user.HomeDir+"/.kube/config")
output, err := cmd.Output()
if err != nil {
log.Fatal(err)
}
configPath := strings.TrimSpace(string(output))
log.Println("kube config file path: ", configPath)
}
加载配置文件
package main
import (
"log"
"os/exec"
"os/user"
"strings"
"k8s.io/client-go/tools/clientcmd"
)
func main() {
// read kube config path from homedir
user, err := user.Current()
if err != nil {
log.Fatal(err)
}
cmd := exec.Command("echo", user.HomeDir+"/.kube/config")
output, err := cmd.Output()
if err != nil {
log.Fatal(err)
}
configPath := strings.TrimSpace(string(output))
log.Println("kube config file path: ", configPath)
// load configuration
config, err := clientcmd.BuildConfigFromFlags("", configPath)
if err != nil {
log.Fatal(err)
}
log.Println(config)
}
安装依赖
➜ client-go-app go mod tidy
go: finding module for package k8s.io/client-go/tools/clientcmd
go: finding module for package k8s.io/client-go/rest
go: downloading k8s.io/client-go v0.29.3
go: found k8s.io/client-go/rest in k8s.io/client-go v0.29.3
go: found k8s.io/client-go/tools/clientcmd in k8s.io/client-go v0.29.3
go: downloading k8s.io/apimachinery v0.29.3
go: downloading k8s.io/api v0.29.3
go: downloading github.com/golang/protobuf v1.5.4
go: downloading google.golang.org/protobuf v1.33.0
go: downloading gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405
读取配置并创建client
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
log.Fatal(err)
}
log.Println(clientset)
通过client获取集群中pod的信息
// main.go
...
podList, err := clientset.CoreV1().Pods("kube-system").List(context.Background(), metav1.ListOptions{})
if err != nil {
log.Fatal(err)
}
for _, pod := range podList.Items {
log.Println(pod.Name)
}
...
启动程序
➜ client-go-app go run main.go
2024/03/22 18:12:41 kube config file path: /home/going/.kube/config
2024/03/22 18:12:41 &{0xc00049d320 0xc0003c92d0 0xc0003c92e0 0xc0003c92f0 0xc0003c9300 0xc0003c9310 0xc0003c9320 0xc0003c9330 0xc0003c9340 0xc0003c9350 0xc0003c9360 0xc0003c9370 0xc0003c9380 0xc0003c9390 0xc0003c93a0 0xc0003c93b0 0xc0003c93c0 0xc0003c93d0 0xc0003c93e0 0xc0003c93f0 0xc0003c9400 0xc0003c9410 0xc0003c9420 0xc0003c9430 0xc0003c9440 0xc0003c9450 0xc0003c9460 0xc0003c9470 0xc0003c9480 0xc0003c9490 0xc0003c94a0 0xc0003c94b0 0xc0003c94c0 0xc0003c94d0 0xc0003c94e0 0xc0003c94f0 0xc0003c9500 0xc0003c9510 0xc0003c9520 0xc0003c9530 0xc0003c9540 0xc0003c9550 0xc0003c9560 0xc0003c9570 0xc0003c9580 0xc0003c9590 0xc0003c95a0 0xc0003c95b0 0xc0003c95c0 0xc0003c95d0 0xc0003c95e0 0xc0003c95f0}
2024/03/22 18:12:41 coredns-76f75df574-2xpv8
2024/03/22 18:12:41 coredns-76f75df574-ncccv
2024/03/22 18:12:41 etcd-test-control-plane
2024/03/22 18:12:41 kindnet-cvbck
2024/03/22 18:12:41 kube-apiserver-test-control-plane
2024/03/22 18:12:41 kube-controller-manager-test-control-plane
2024/03/22 18:12:41 kube-proxy-9428x
2024/03/22 18:12:41 kube-scheduler-test-control-plane
创建一个deployment,通过client-go获取deployment的信息。
➜ client-go-app cat nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
创建deployment
➜ client-go-app ka -f nginx-deployment.yaml
deployment.apps/nginx-deployment created
➜ client-go-app kg pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-7c79c4bf97-4bgnf 1/1 Running 0 9s
nginx-deployment-7c79c4bf97-9qscr 1/1 Running 0 9s
nginx-deployment-7c79c4bf97-kzpb9 1/1 Running 0 9s
➜ client-go-app kg deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 111s
使用client获取特定namespace下的deployment
// create a deployment with nginx image
deploy, err := clientset.AppsV1().Deployments("default").Get(context.Background(), "nginx-deployment", metav1.GetOptions{})
if err != nil {
log.Fatal(err)
}
log.Println("deployment name: ", deploy.Name)
执行程序
➜ client-go-app go run main.go
...
2024/03/22 18:30:21 deployment name: nginx-deployment
client-go版本与Kubernetes的版本的兼容性
由于 Kubernetes 向后兼容客户端,旧版本的 client-go
可与许多不同版本的 Kubernetes 集群一起使用。我们在开发是最好保持client-go和Kubernetes的版本兼容性。
Compatibility matrix
Kubernetes 1.23 Kubernetes 1.24 Kubernetes 1.25 Kubernetes 1.26 Kubernetes 1.27 Kubernetes 1.28 kubernetes-1.23.0/v0.23.0 ✓ +- +- +- +- +- kubernetes-1.24.0/v0.24.0 +- ✓ +- +- +- +- kubernetes-1.25.0/v0.25.0 +- +- ✓ +- +- +- kubernetes-1.26.0/v0.26.0 +- +- +- ✓ +- +- kubernetes-1.27.0/v0.27.0 +- +- +- +- ✓ +- kubernetes-1.28.0/v0.28.0 +- +- +- +- +- ✓ HEAD +- +- +- +- +- +--
✓
代表client-go 和 Kubernetes 版本中的功能和 API 对象完全相同。 -
+
代表client-go 具有一些在 Kubernetes 集群中可能不存在的功能或 API 对象,这可能是因为 client-go 具有额外的新 API,或者服务器已删除了旧的 API。但是,它们共有的部分(即大多数 API)将正常工作。请注意,alpha API 可能会在单个版本中消失或发生重大变化。