使用 Go 程序调用 Kubernetes API”

在前面的章节中,我们介绍了快速部署 Kubernetes 和应用程序的方法,接下来在本章节中我们将对 Kubernetes 的 API 进行了解,并且进行调用,这是开发人员最关注的一环之一。

因为不论是 DevOps、基础架构,又或是自愈,都需要与 Kubernetes API 直接/间接接触,因此即使在你不懂 Kubernetes 的情况下,Kubernetes API 的知识点仍然属于必知必会,API 总得会调。

查看 Kubernetes API

kube-apiserver 架构图

image

(图来自 kubernetes.io)

在 Kubernetes 的架构中,由 kube-apiserver 组件在主节点上提供 Kubernetes API 服务,kube-apiserver 是 Kubernetes 所有控制的前端,对外提供大量的 RESTful API。

最常见的就是 kubelet 命令,实际上也是在调用 kube-apiserver 所提供的的 API。

访问 API 和查看列表

在了解 Kubernetes 的基本架构和提供 API 的方式后,接下来我们需要知道 Kubernetes 到底提供了哪些 API。为了方便调试,首先我们需要在本地运行 kubectl proxy 命令,kube-apiserver 就会在本地的 8001 端口上进行监听,也就是提供了一个 Kubernetes API 服务的 HTTP 代理。

这个时候我们可以访问:

  1. $ curl http://localhost:8001/api/v1/

查看所提供的对应 API‘s:

  1. {
  2. "kind": "APIResourceList",
  3. "groupVersion": "v1",
  4. "resources": [
  5. {
  6. "name": "bindings",
  7. "singularName": "",
  8. "namespaced": true,
  9. "kind": "Binding",
  10. "verbs": [
  11. "create"
  12. ]
  13. },
  14. {
  15. "name": "componentstatuses",
  16. "singularName": "",
  17. "namespaced": false,
  18. "kind": "ComponentStatus",
  19. "verbs": [
  20. "get",
  21. "list"
  22. ],
  23. "shortNames": [
  24. "cs"
  25. ]
  26. },
  27. ...
  28. ]
  29. }

访问 api/v1/pods 路径,获取所有 Pods

  1. $ curl http://127.0.0.1:8001/api/v1/pods

访问结果:

  1. {
  2. "kind": "PodList",
  3. "apiVersion": "v1",
  4. "metadata": {
  5. "selfLink": "/api/v1/pods",
  6. "resourceVersion": "614376"
  7. },
  8. "items": [
  9. {
  10. "metadata": {
  11. "name": "awesome-project-76788db95b-7ztwr",
  12. "generateName": "awesome-project-76788db95b-",
  13. "namespace": "default",
  14. "selfLink": "/api/v1/namespaces/default/pods/awesome-project-76788db95b-7ztwr",
  15. "uid": "4fdb6661-edbd-4fc6-bf71-1d2dadb3ffc1",
  16. "resourceVersion": "608545",
  17. "creationTimestamp": "2020-05-03T02:29:32Z",
  18. "labels": {
  19. "app": "awesome-project",
  20. "pod-template-hash": "76788db95b"
  21. },
  22. ...
  23. ]
  24. },
  25. ]

更多的 API 列表和介绍可查看官方文档

Go 程序调用 Kubernetes API

接下来进入在本章的重点,也就是在程序中调用 Kubernetes API,Kubernetes 官方提供了 Go 语言的 Client SDK,也就是kubernetes/client-go,我们借助上一章节的 Go 程序,对其进行改造。

Demo

首先写入如下方法:

  1. func NewK8sInCluster() error {
  2. config, err := rest.InClusterConfig()
  3. if err != nil {
  4. return err
  5. }
  6. k8sClient, err = kubernetes.NewForConfig(config)
  7. if err != nil {
  8. return err
  9. }
  10. return nil
  11. }

编写获取 K8S Pod 列表的方法:

  1. func GetPodList(pod Pod) ([]v1.Pod, error) {
  2. podList, err := k8sClient.CoreV1().Pods(pod.Namespace).List(metav1.ListOptions{})
  3. if err != nil {
  4. return nil, err
  5. }
  6. pods := podList.Items
  7. if pod.Name != "" {
  8. filterPods := make([]v1.Pod, 0, len(pods))
  9. for _, p := range pods {
  10. if strings.HasPrefix(p.Name, pod.Name) {
  11. filterPods = append(filterPods, p)
  12. }
  13. }
  14. pods = filterPods
  15. }
  16. return pods, nil
  17. }

修改 main 方法中的路由:

  1. func main() {
  2. r := gin.Default()
  3. r.GET("/ping", func(c *gin.Context) {
  4. c.String(http.StatusOK, "pong")
  5. })
  6. r.GET("/k8s/pods", func(c *gin.Context) {
  7. err := NewK8sInCluster()
  8. if err != nil {
  9. c.String(http.StatusInternalServerError, "NewK8sInCluster err: %v", err)
  10. }
  11. pods, err := GetPodList(Pod{Namespace: "default"})
  12. if err != nil {
  13. c.String(http.StatusInternalServerError, "GetPodList err: %v", err)
  14. }
  15. c.JSON(http.StatusOK, pods)
  16. })
  17. err := r.Run(":9001")
  18. if err != nil {
  19. log.Fatalf("r.Run err: %v", err)
  20. }
  21. }

在确定程序正常后,我们重新编译并打标签:

  1. $ docker build -t eddycjy/awesome-project:v0.0.2 .
  2. $ docker login
  3. $ docker push eddycjy/awesome-project:v0.0.2

部署并验证

修改 go-deployment.yaml 文件:

  1. containers:
  2. - name: awesome-project
  3. image: eddycjy/awesome-project:v0.0.2

将其应用到 Kubernetes:

  1. $ kubectl apply -f go-deployment.yaml
  2. deployment.extensions/awesome-project configured

访问刚刚所编写的接口,如下:

  1. $ curl http://website-ingress.local/k8s/pods
  2. [{"metadata":{"name":"awesome-project-64979bcbd9-rm957","generateName":"awesome-project-64979bcbd9-","namespace":"default","selfLink":"/api/v1/namespaces/default/pods/awesome-project-64979bcbd9-rm957","uid":"b0a83787-c547-4d74-9bc4-c930b2188e84","resourceVersion":"...