Skip to content

Files

Latest commit

cbff0a9 · Dec 29, 2021

History

History
294 lines (207 loc) · 10.5 KB

File metadata and controls

294 lines (207 loc) · 10.5 KB

十三、开发 Kubernetes

既然您已经了解了如何安装、交互和使用 Kubernetes 来部署和管理应用,我们将在本章重点介绍如何根据您的需求调整 Kubernetes 以及修复 Kubernetes 中的错误。为此,您需要安装 Go 并访问 GitHub 上托管的 Kubernetes 源代码。我们展示了如何编译 Kubernetes(作为一个整体),也展示了如何编译像客户端kubectl这样的特定组件。我们还演示了如何使用 Python 与 Kubernetes API 服务器对话,并展示了如何使用自定义资源定义来扩展 Kubernetes。

13.1 从源代码编译

问题

您希望从源代码中打包自己的 Kubernetes 二进制文件,而不是下载官方发布的二进制文件(参见食谱 2.4 )或第三方工件。

解决办法

克隆 Kubernetes Git 存储库并从源代码构建。

如果您在 Docker 主机上,您可以使用根 Makefilequick-release目标,如下所示:

$ git clone https://github.com/kubernetes/kubernetes
$ cd kubernetes
$ make quick-release

小费

这种基于 Docker 的构建需要至少 4 GB 的内存才能完成。确保您的 Docker 守护程序可以访问那么多内存。在 macOS 上,访问 Docker 获取 Mac 首选项并增加分配的内存。

二进制文件将位于输出/发布阶段目录中,完整的包将位于输出/发布阶段目录中。

或者,如果您已经正确设置了 Golang 环境,请使用根 Makefile : 的release目标

$ git clone https://github.com/kubernetes/Kubernetes
$ cd kubernetes
$ make

二进制文件将位于 _output/bin 目录中。

请参见

13.2 编译特定组件

问题

您希望从源代码中构建 Kubernetes 的特定组件,而不是所有组件——例如,您只希望构建客户端kubectl

解决办法

不用make quick-release或者简单的make,如食谱 13.1 所示,做make kubectl

Makefile 中有构建单个组件的目标。例如要编译kubectlkubeadmhyperkube,请执行以下操作:

$ make kubectl
$ make kubeadm
$ make hyperkube

二进制文件将位于 _output/bin 目录中。

13.3 使用 Python 客户端与 Kubernetes 应用编程接口交互

问题

你想用 Python 来编写使用 Kubernetes API 的脚本。

解决办法

安装 Python kubernetes模块。该模块目前正在 Kubernetes孵化器中开发。您可以从源代码或从 Python 包索引(PyPi)网站安装该模块:

$ pip install kubernetes

使用默认的kubectl上下文可以到达一个 Kubernetes 集群,现在可以使用这个 Python 模块与 Kubernetes API 进行对话了。例如,下面的 Python 脚本列出了所有的 pod 并打印了它们的名称:

from kubernetes import client, config

config.load_kube_config()

v1 = client.CoreV1Api()
res = v1.list_pod_for_all_namespaces(watch=False)
for pod in res.items:
    print(pod.metadata.name)

该脚本中的config.load_kube_config()调用将从您的kubectl配置文件中加载您的 Kubernetes 凭证和端点。默认情况下,它将加载当前上下文的集群端点和凭据。

讨论

Python 客户端是使用 Kubernetes 应用编程接口的 OpenAPI 规范构建的。它是最新的并且是自动生成的。所有的 API 都可以通过这个客户端获得。

每个 API 组对应一个特定的类,因此要调用属于/api/v1 API 组的 API 对象上的方法,需要实例化CoreV1Api类。要使用部署,您需要实例化extensionsV1beta1Api类。所有方法和对应的 API 组实例可以在自动生成的 自述文件 中找到。

请参见

13.4 使用自定义资源定义扩展应用编程接口

问题

您有一个自定义工作负载,而现有资源(如Deployment、一个Job或一个StatefulSet)都不适合。因此,您希望用代表您的工作负载的新资源来扩展 Kubernetes API,同时继续以通常的方式使用kubectl

解决办法

如[此处]所述,使用 CustomResourceDefinition (CRD)

假设您想要定义一种自定义资源Function。这代表了一种类似短期运行的资源,类似于 AWS Lambda 所提供的,那就是功能即服务(FaaS,或者有时被误称为“无服务器”)。

注意

有关在 Kubernetes 上运行的生产就绪型 FaaS 解决方案,请参见配方 14.7

首先,在名为函数-crd.yaml 的清单文件中定义 CRD:

apiVersion: apiextensions.k8s.io/v1beta1
kind:       CustomResourceDefinition
metadata:
  name:     function.example.com
spec:
  group:    example.com
  version:  v1
  names:
    kind:   Function
    plural: functions
    scope:  Namespaced

然后让 API 服务器知道您的新 CRD(注册可能需要几分钟时间):

$ kubectl create -f functions-crd.yaml
customresourcedefinition "functions.example.com" created

既然您已经定义了自定义资源Function,并且应用编程接口服务器知道它,您可以使用名为 myfaas.yaml 的清单来实例化它,其内容如下:

apiVersion: example.com/v1
kind:       Function
metadata:
  name:     myfaas
spec:
  code:     "http://src.example.com/myfaas.js"
  ram:      100Mi

并像往常一样创建类Functionmyfaas资源:

$ kubectl create -f myfaas.yaml
function "myfaas" created

$ kubectl get crd functions.example.com -o yaml
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  creationTimestamp: 2017-08-13T10:11:50Z
  name: functions.example.com
  resourceVersion: "458065"
  selfLink: /apis/apiextensions.k8s.io/v1beta1/customresourcedefinitions
            /functions.example.com
  uid: 278016fe-81a2-11e7-b58a-080027390640
spec:
  group: example.com
  names:
    kind: Function
    listKind: FunctionList
    plural: functions
    singular: function
  scope: Namespaced
  version: v1
status:
  acceptedNames:
    kind: Function
    listKind: FunctionList
    plural: functions
    singular: function
  conditions:
  - lastTransitionTime: null
    message: no conflicts found
    reason: NoConflicts
    status: "True"
    type: NamesAccepted
  - lastTransitionTime: 2017-08-13T10:11:50Z
    message: the initial names have been accepted
    reason: InitialNamesAccepted
    status: "True"
    type: Established

$ kubectl describe functions.example.com/myfaas
Name:           myfaas
Namespace:      default
Labels:         <none>
Annotations:    <none>
API Version:    example.com/v1
Kind:           Function
Metadata:
  Cluster Name:
  Creation Timestamp:                   2017-08-13T10:12:07Z
  Deletion Grace Period Seconds:        <nil>
  Deletion Timestamp:                   <nil>
  Resource Version:                     458086
  Self Link:                            /apis/example.com/v1/namespaces/default
                                        /functions/myfaas
  UID:                                  316f3e99-81a2-11e7-b58a-080027390640
Spec:
  Code: http://src.example.com/myfaas.js
  Ram:  100Mi
Events: <none>

要发现 CRD,只需访问 API 服务器。例如,使用kubectl proxy,可以在本地访问 API 服务器并查询键空间(在我们的例子中为example.com/v1):

$ curl 127.0.0.1:8001/apis/example.com/v1/ | jq .
{
  "kind": "APIResourceList",
  "apiVersion": "v1",
  "groupVersion": "example.com/v1",
  "resources": [
    {
      "name": "functions",
      "singularName": "function",
      "namespaced": true,
      "kind": "Function",
      "verbs": [
        "delete",
        "deletecollection",
        "get",
        "list",
        "patch",
        "create",
        "update",
        "watch"
      ]
    }
  ]
}

在这里,您可以看到资源以及允许的动词。

当您想要删除您的自定义资源实例myfaas时,只需将其删除即可:

$ kubectl delete functions.example.com/myfaas
function "myfaas" deleted

讨论

如您所见,创建 CRD 很简单。从最终用户的角度来看,CRD 提供了一个一致的 API,并且或多或少与本机资源(如 pod 或 jobs)无法区分。所有常用的命令,如kubectl getkubectl delete,都如预期的那样工作。

然而,创建一个 CRD 实际上还不到完全扩展 Kubernetes 应用编程接口所需工作的一半。CRDs 本身只允许您通过 etcd 中的 API 服务器存储和检索自定义数据。您还需要编写一个自定义控制器,解释表达用户意图的自定义数据,并建立一个控制循环,将当前状态与声明的状态进行比较,并尝试协调两者。

小费

直到 1.7 版本,现在所谓的 CRDs 被称为第三方资源(TPR)。如果你刚好有一个 TPR,强烈考虑现在就把它迁移到。

CRDs 的主要限制(以及在某些情况下您可能希望使用用户应用编程接口服务器的原因)是:

  • 每个 CRD 只支持一个版本,尽管每个 API 组可能有多个版本(这意味着您不能在您的 CRD 的不同表示之间转换)。

  • CRDS 不支持在 v1.7 或更早版本中为字段分配默认值。

  • 只有从 1.8 版开始,才能验证 CRD 规范中定义的字段

  • 无法定义子资源,如status资源。

请参见