Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kubernetes连载之12 API and Plugin #19

Open
andy2046 opened this issue Apr 18, 2018 · 0 comments
Open

Kubernetes连载之12 API and Plugin #19

andy2046 opened this issue Apr 18, 2018 · 0 comments

Comments

@andy2046
Copy link
Owner

Working with the Kubernetes API

Understanding OpenAPI

OpenAPI允许API提供者定义他们的操作和模型,并使开发人员能够自动化他们的工具并生成他们最喜欢的语言的客户端来与该API服务器交谈。在Kubernetes 1.4中,通过升级当前的模型和操作,在OpenAPI规范(以前称为Swagger 2.0,之后将其捐献给OpenAPI Initiative)中添加了alpha支持。在Kubernetes 1.5中,通过直接从Kubernetes源代码自动生成规范来完成对OpenAPI规范的支持,这将使规范和文档与操作/模型中的未来更改保持同步。

新规范提供了更好的API文档。该规范是模块化的,并按组版本(group version)进行划分。这是面向未来的。你可以运行支持不同版本的多个API服务器。应用程序可以逐渐过渡到更新的版本。
规范的结构在OpenAPI规范定义中进行了详细说明。 Kubernetes团队使用该操作的标签来分离每个组版本,并尽可能多地填写有关路径/操作和模型的信息。对于特定的操作,所有参数,调用方法和响应都有记录。

Setting up a proxy

为了简化访问,你可以使用Kubectl来设置代理:

kubectl proxy --port 8080

现在,你可以访问http://localhost:8080上的API服务器,它将到达与Kubectl配置相同的Kubernetes API服务器。

Creating a pod via the Kubernetes API

根据以下pod配置文件,该API也可用于创建,更新和删除资源:

{
"kind": "Pod",
"apiVersion": "v1",
"metadata": {
  "name": "nginx",
  "namespace": "default",
  "labels": {
    "name": "nginx"
  }
},
"spec": {
  "containers": [{
    "name": "nginx",
    "image": "nginx",
    "ports": [{ "containerPort": 80 }]
  }]
} 
}
http POST http://localhost:8080/api/v1/namespaces/default/pods @nginx-pod.json

http http://localhost:8080/api/v1/namespaces/default/pods

Extending the Kubernetes API

Kubernetes是一个非常灵活和可扩展的平台。它甚至允许你使用称为第三方资源的新型资源扩展自己的API。你可以用第三方资源做什么?很多。你可以使用它们来管理在Kubernetes集群之外的与你的Pods通信的资源。通过添加这些外部资源作为第三方资源,你可以全面了解你的系统,并且你可以从许多Kubernetes API功能中获益,例如:

  • 自定义CRUD REST端点
  • 版本控制
  • Watches
  • 与通用Kubernetes工具自动集成

第三方资源的其他用例是自定义控制器和自动化程序的元数据。

Understanding the structure of a third-party-resource

为了配合Kubernetes API服务器,第三方资源必须符合一些基本要求。类似于内置的API对象,它们必须具有以下字段:

  • metadata:标准Kubernetes对象元数据
  • kind:第三方资源描述的资源种类
  • description:资源的自由文本描述
  • versions:资源版本的列表

kind字段需要一些解释。Kubernetes将CamelCase用于资源类型。kind字段的格式必须为. 单词之间的连字符应该全部小写。Kubernetes会将其转换为CamelCase资源。例如,awesome-resource将成为AwesomeResource。除了这些字段之外,你可以添加你想要的任何字段并存储任意的JSON来创建你喜欢的任何结构。

Developing third-party-resources

区分你定义的第三方资源(不绑定到命名空间)和你创建的实际对象(总是绑定到一个命名空间)很重要。目前,Kubernetes不支持基于第三方资源的无命名空间自定义对象。以下是第三方资源的示例:

apiVersion: extensions/v1beta1
kind: ThirdPartyResource
metadata:
  name: cron-tab.stable.example.com
description: A pod that runs on schedule
versions:
  name: v1
$ k create -f 3rd-party-resource.yaml
  thirdpartyresource "cron-tab.stable.example.com" created
$ kubectl get thirdpartyresources
  NAME                        DESCRIPTION                 VERSION(S)
  cron-tab.stable.example.com A pod that runs on schedule v1

Integrating third party resources

一旦创建了ThirdPartyResource对象,你就可以创建该资源种类的自定义对象,在此情况下是CronTab(cron-tab变为CamelCase CronTab)。CronTab对象可以包含任意JSON的任意字段。在以下示例中,cronSpec和image自定义字段在CronTab对象上设置。另外,stable.example.com API group来源于ThirdPartyResource的metadata.name:

apiVersion: stable.example.com/v1
kind: CronTab
metadata:
  name: new-cron-object
cronSpec: * * * * /5
image: my-awesome-cron-image
$ kubectl create -f crontab.yaml
  crontab "new-cron-object" created
$ kubectl get crontab
NAME                 LABELS    DATA
new-cron-object      <none>    {"apiVersion":"stable.example.com/v1","cronSpec":"...

Writing Kubernetes plugins

Writing a custom scheduler plugin

Kubernetes将自己定义为一个容器调度和管理系统。因此,调度器是Kubernetes最重要的组件。Kubernetes带有一个默认调度程序,但允许编写额外的调度程序。要编写自己的自定义调度程序,你需要了解调度程序执行的操作/方法,如何被打包,如何部署自定义调度程序,以及如何集成调度程序。调度程序源代码在此处可用:
https://github.com/kubernetes/kubernetes/blob/master/plugin/pkg/scheduler

Understanding the design of the Kubernetes scheduler

调度程序的任务是为新创建或重新启动的Pod创建节点,并在API服务器中创建绑定并在其中运行。如果调度程序无法为该容器找到合适的节点,它将保持pending状态。

调度程序的大部分工作非常通用,找出哪些pods需要进行调度,更新其状态,并在选定节点上运行它们。自定义部分是如何将Pod映射到节点。Kubernetes团队认识到自定义调度的需要,通用调度器可以配置不同的调度算法。主要的数据类型是scheduler struct,它包含一个具有许多属性的Config struct(这将很快被configurator interface取代):

type Scheduler struct {
    config *Config
}
type Config struct {
    SchedulerCache schedulercache.Cache
    NodeLister algorithm.NodeLister
    Algorithm algorithm.ScheduleAlgorithm
    Binder Binder
    PodConditionUpdater PodConditionUpdater
    NextPod func() *v1.Pod
    Error func(*v1.Pod, error)
    Recorder record.EventRecorder
    StopEverything chan struct{}
}

调度器具有算法提供者和算法的概念。它们一起使你可以使用内置调度程序的实质功能,并替换核心调度算法。算法提供者允许你在工厂注册新的算法提供者。已经有一个自定义提供程序注册名为ClusterAutoScalerProvider。稍后我们会看到调度程序如何知道使用哪个算法提供程序。关键文件如下:
/plugin/pkg/scheduler/algorithmprovider/defaults/defaults.go
以下是init()函数的相关部分,除了缺省和自动调节器提供程序外,你还应该扩展它以包含算法提供程序:

func init() {
    ...
    // Registers algorithm providers. By default we use
    // 'DefaultProvider', but user can specify one to be used by
    //specifying flag.
    factory.RegisterAlgorithmProvider(factory.DefaultProvider,
                                      defaultPredicates(),
                                      defaultPriorities())
    
    // Cluster autoscaler friendly scheduling algorithm.
    factory.RegisterAlgorithmProvider(
        ClusterAutoscalerProvider,
        defaultPredicates(),
        copyAndReplace(defaultPriorities(),
                       "LeastRequestedPriority",
                       "MostRequestedPriority"))
    ...

In addition to registering the provider, you also need to register a fit predicate and a priority function, which are used to actually perform the scheduling.
You can use the factory's RegisterFitPredicate() and RegisterPriorityFunction2() functions.

调度程序算法作为配置的一部分提供。自定义调度程序可以实现ScheduleAlgorithm接口:

type ScheduleAlgorithm interface {
    Schedule(*v1.Pod, NodeLister) (selectedMachine string, err error)
}

在运行调度程序时,可以提供自定义调度程序的名称或自定义算法提供程序作为命令行参数。如果没有提供,则将使用默认算法提供程序。调度程序的命令行参数是--algorithm-provider和--scheduler-name。

自定义的调度程序在它监视的同一个Kubernetes集群内运行。它需要被打包成一个容器镜像。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    component: scheduler
    tier: control-plane
  name: custom-scheduler
  namespace: kube-system
spec:
  replicas: 1
  template:
    metadata:
      labels:
        component: scheduler
        tier: control-plane
        version: second
    spec:
      containers:
      - command:
        - /usr/local/bin/kube-scheduler
        - --address=0.0.0.0
        - --leader-elect=false
        - --scheduler-name=custom-scheduler
        image: g1g1/custom-kube-scheduler:1.0
        livenessProbe:
          httpGet:
            path: /healthz
            port: 10251
          initialDelaySeconds: 15
        name: kube-second-scheduler
        readinessProbe:
          httpGet:
            path: /healthz
            port: 10251
        resources:
          requests:
            cpu: '0.1'
$ kubectl create -f custom-scheduler.yaml

自定义调度程序与默认调度程序一起运行。但是,如果Kobernetes需要调度,那么Kubernetes如何选择使用哪个调度程序?答案是该pod决定而不是Kubernetes。该pod规范具有可选的调度程序名称字段。如果缺失,则使用默认调度程序; 否则使用指定的调度程序。这是自定义调度程序名称必须唯一的原因。默认计划程序的名称是default-scheduler,以防你希望在你的pod规范中明确指定。

apiVersion: v1
kind: Pod
metadata:
  name: some-pod
  labels:
    name: some-pod
spec:
  schedulername: custom-scheduler
  containers:
  - name: some-container
    image: gcr.io/google_containers/pause:2.0

有两种主要方法可以验证由正确的调度程序调度的pod。首先,你可以在部署自定义调度程序之前创建需要由自定义调度程序调度的pod。该pod将保持pending状态。然后,部署自定义调度程序,挂起的pod将被调度并开始运行。另一种方法是检查事件日志并使用以下命令查找计划事件:

$ kubectl get events
@andy2046 andy2046 changed the title Kubernetes连载之12 Kubernetes连载之12 API and Plugin May 2, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant