【Sigma敏捷版系列文章】如何利用apiserver-builder自定义Kubernetes API

简介: apiserver-builder提供了一套标准的k8s API构建规范,构建的API可以通过k8s汇聚层实现对k8s API的扩展,另外我们可以看到通过apiserver-builder来构建出来的项目完全可以作为一个独立系统运行。

背景知识

了解一下k8s API

k8s中的API可以抽象为两个阶段:存储和调和。
存储(Storage):
Kubernetes API公开了用于存储声明期望集群状态的资源对象的操作
调和(Reconciliation):
通常称为控制器(controller)的进程集合监视写入资源的对象进行调和
如图:
undefined
API具有如下特征:
1、Declarative(声明式)
Kubernetes API被设计为:对象的期望状态被发送到API服务器,该服务器集群用于协调实际状态与期望的状态
2、Level based (基于等级)
基于等级的实现会依据当前最新的状态,而忽略先前的期望状态。例如执行Deployment更新镜像的时候,如果当前设置的是镜像A没有更新完成时,这时候又更新Deployment设置为镜像B,则会按照最新的B进行更新。
3、Asynchronous (异步)
API是按照异步方式执行,在按照期望值进行调和的过程中,已经返回了请求的结果信息。这就意味着用户请求时候不会返回错误的信息。如果调和的过程中发生错误(如镜像版本错误),则会设置到状态的信息字段上面。

K8s中自定义资源

Kubernetes提供了两种向群集添加自定义资源的方法:
1、自定义资源定义(CRD):更易于使用,在某些情况下,它们不需要任何编程。
自定义资源定义(CRDS)允许用户创建新类型的资源而无需添加其他API服务器。您不需要了解API Aggregation就可以使用CRD。
2、API聚合:需要编程,但允许更多的API行为控制,如数据如何存储以及API版本之间的转换。
Kubernetes提供了这两种选择来满足不同用户的需求,从而既不易于使用又不会降低灵活性。

无论是通过CRD还是API聚合安装,新资源都称为“自定义资源”,以将它们与内置Kubernetes资源(如Pod)区分开来。
今天我们介绍就是汇聚层API的构建方案:apiserver-builder。同时也是一种可以独立部署k8s式API服务的自动构建方式

概述

apiserver-builder基于k8s中的api-machinery之上开发全功能Kubernetes API,同时具备项目独立部署的特点。 这意味着允许扩展API在Kubernetes之外开发,并作为一个包单独安装。
功能特点:
1、可以作为新资源的类型定义,控制器,测试和文档的工具
2、可以作为独立构建和运行扩展控制平面的工具。
3、从控制器轻松list-watch和更新Kubernetes API类型
4、轻松添加新资源和子资源
5、为大多数接口属性提供了默认值,并且可以被覆盖

开发实践

安装apiserver构建工具

1.下载最新的alpha版本:
https://github.com/kubernetes-incubator/apiserver-builder/releases/download/v1.9-alpha.4/apiserver-builder-v1.9-alpha.4-linux-amd64.tar.gz
2.export PATH=$PATH:/root/apiserver-builder/bin
3.创建一个Go工程(demo)在GOPATH/src/目录下
4.创建copyright
在GOPATH/src/demo工程目录下创建文件boilerplate.go.txt
内容:

/*
Copyright 2017 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

初始化工程

初始化工程中将会设置apiserver最初的代码结构,包括go vendor库,这个是从下载的apiserver-builder二进制tar包复制过来的。
1.设置domin作为api group

#apiserver-boot init repo --domain demo.alibaba.com

我们可以看到生成的代码结构:
undefined

2.开始创建API资源:
API 资源定义包括group (类似package),version (版本:v1alpha1, v1beta1, v1),和Kind (资源类型)
运行“apiserver-boot create group version resource” 命令进行创建

#apiserver-boot create group version resource --group demo --version v1alpha1  --kind Bird

注意:资源类型需要首字母大写
undefined
3.本地可以运行apiserver和controller:

#apiserver-boot run local

undefined
4.通过kubectl验证:

kubectl --kubeconfig=kubeconfig api-versions

undefined

5.创建示例资源

kubectl --kubeconfig=kubeconfig create -f sample/bird.yaml

undefined

这样我们通过apiserver-builder轻松的扩展了k8s资源接口

扩展资源说明

资源定义

资源定义主要包括3部分
1、Metadata:元数据信息
Name (唯一key值)
Annotations (描述信息key-value键值对)
Labels (用于查询的key-value键值对)
2、Spec: 期望的状态信息
用来设置期望的状态字段,调和器(controller)依据这些期望的属性更新集群内部或外部的对象
3、Status: 结果状态信息
用来设置结果属性的状态字段
构建代码如下:

// Bird
// +k8s:openapi-gen=true
// +resource:path=birds,strategy=BirdStrategy
type Bird struct {
    metav1.TypeMeta   `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`

    Spec   BirdSpec   `json:"spec,omitempty"`
    Status BirdStatus `json:"status,omitempty"`
}

// BirdSpec defines the desired state of Bird
type BirdSpec struct {
}

// BirdStatus defines the observed state of Bird
type BirdStatus struct {
}

资源存储

在资源存储操作执行期间,我们可以通过如下几种方式验证或者修改存储的对象。
undefined

创建操作

1.DefaultingFunction:可以设置默认值

// DefaultingFunction sets default Bird field values
func (BirdSchemeFns) DefaultingFunction(o interface{}) {
    obj := o.(*Bird)
    // set default field values here
    log.Printf("Defaulting fields for Bird %s\n", obj.Name)
}

2.PrepareForCreate:修改对象属性,设置初始化或者资源回收
如下面的代码展示了k8s中pod资源通过PrepareForCreate方法设置Pending状态

// PrepareForCreate clears fields that are not allowed to be set by end users on creation.
func (podStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) {
    pod := obj.(*api.Pod)
    pod.Status = api.PodStatus{
        Phase:    api.PodPending,
        QOSClass: qos.GetPodQOS(pod),
    }

    podutil.DropDisabledAlphaFields(&pod.Spec)
}

如果代码中没有显示的定义PrepareForCreate方法,会默认执行apiserver-builder的该方法

func (DefaultStorageStrategy) PrepareForCreate(ctx request.Context, obj runtime.Object) {
    switch t := obj.(type) {
    default:
    case HasObjectMetaSpecStatus:
        // Clear the status if the resource has a Status
        t.GetObjectMeta().Generation = 1
        t.SetStatus(t.NewStatus())
    }
}

3.Validate:验证值的合法性,如果不合法可以直接拒绝创建请求

// Validate checks that an instance of Bird is well formed
func (BirdStrategy) Validate(ctx request.Context, obj runtime.Object) field.ErrorList {
    o := obj.(*demo.Bird)
    log.Printf("Validating fields for Bird %s\n", o.Name)
    errors := field.ErrorList{}
    // perform validation here and add to errors using field.Invalid
    return errors
}

4.Canonicalize(规范化):对象存储前最后一道修改的入口,用于将存储对象进行规范化,如将一些无序的数据进行排列以利于分析预测。

func (DefaultStorageStrategy) Canonicalize(obj runtime.Object) {}

更新操作:

包括ValidateUpdate和PrepareForUpdate,分别用于更新是的验证和预处理

删除操作

Finalizers: 需要通过Controller手动回收下游资源.
如果在对象上指定了回收器(例如PrepareForCreate),则删除对象将使用宽限期设置对象上的DeletionTimestamp字段。 控制器接收到该对象已被删除信息后,对创建的资源进行清理。
OwnerReference:通过apiserver自动回收下游资源

资源调和(Reconciliation)

undefined
通过控制器,实现调和

控制器初始化

在controller.go中我们可以看到初始化方法


// Init initializes the controller and is called by the generated code
// Register watches for additional resource types here.
func (c *BirdControllerImpl) Init(arguments sharedinformers.ControllerInitArguments) {
    // Use the lister for indexing birds labels
    c.lister = arguments.GetSharedInformers().Factory.Demo().V1alpha1().Birds().Lister()
}

调和

通过watch资源变化,对资源进行调和操作

// Reconcile handles enqueued messages
func (c *BirdControllerImpl) Reconcile(u *v1alpha1.Bird) error {
    // Implement controller logic here
    log.Printf("Running reconcile Bird for %s\n", u.Name)
    return nil
}

调和操作包括:
1.更新对象属性metadata, spec or status
2.创建、更新、删除k8s中其它资源(如pod)
3.创建、更新、删除k8s外的其它资源(如cloudprovider提供的云盘存储等)

总结

apiserver-builder提供了一套标准的k8s API构建规范,构建的API可以通过k8s汇聚层实现对k8s API的扩展,另外我们可以看到通过apiserver-builder来构建出来的项目完全可以作为一个独立系统运行。试想一下当你可以自动构建一个拥有面向终态的设计模式加上支持k8s生态组件(kubectl等)的工程的时候,it's amazing!
在近期的项目中我们也是采用了apiserver-builder构建了一套独立的系统,为用户提供了k8s式的服务访问模式,有兴趣的欢迎一起交流。

参考

1、https://github.com/kubernetes-incubator/apiserver-builder/blob/master/docs/concepts/api_building_overview.md
2、https://kubernetes.io/docs/concepts/api-extension/custom-resources/
3、https://github.com/kubernetes-incubator/apiserver-builder/blob/master/docs/tools_user_guide.md

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
目录
相关文章
|
2月前
|
Kubernetes 网络协议 数据安全/隐私保护
WireGuard 系列文章(八):基于 WireGuard 的 K8S CNI Kilo 简介
WireGuard 系列文章(八):基于 WireGuard 的 K8S CNI Kilo 简介
|
4月前
|
敏捷开发 API
【sgCreateAPI】自定义小工具:敏捷开发→自动化生成API接口脚本(接口代码生成工具)
【sgCreateAPI】自定义小工具:敏捷开发→自动化生成API接口脚本(接口代码生成工具)
|
5月前
|
Kubernetes 应用服务中间件 API
5 分钟了解 Kubernetes Ingress 和 Gateway API
5 分钟了解 Kubernetes Ingress 和 Gateway API
109 0
|
6月前
|
Kubernetes 应用服务中间件 API
kubernetes系列文章第二篇-kubectl
kubernetes系列文章第二篇-kubectl
|
24天前
|
人工智能 关系型数据库 Serverless
Serverless 应用引擎常见问题之API生成的函数镜像改为自定义的镜像如何解决
Serverless 应用引擎(Serverless Application Engine, SAE)是一种完全托管的应用平台,它允许开发者无需管理服务器即可构建和部署应用。以下是Serverless 应用引擎使用过程中的一些常见问题及其答案的汇总:
37 3
|
24天前
|
Kubernetes JavaScript API
云效常见问题之appstack连接自定义k8s连不上如何解决
云效(CloudEfficiency)是阿里云提供的一套软件研发效能平台,旨在通过工程效能、项目管理、质量保障等工具与服务,帮助企业提高软件研发的效率和质量。本合集是云效使用中可能遇到的一些常见问题及其答案的汇总。
259 1
|
2月前
|
JSON Kubernetes 数据格式
Grafana 系列文章(十三):如何用 Loki 收集查看 Kubernetes Events
Grafana 系列文章(十三):如何用 Loki 收集查看 Kubernetes Events
|
2月前
|
Kubernetes 网络协议 网络虚拟化
WireGuard 系列文章(九):基于 K3S+WireGuard+Kilo 搭建跨多云的统一 K8S 集群
WireGuard 系列文章(九):基于 K3S+WireGuard+Kilo 搭建跨多云的统一 K8S 集群
|
3月前
|
Kubernetes 容器
Kubernetes高可用集群二进制部署(三)部署api-server
Kubernetes高可用集群二进制部署(三)部署api-server
|
4月前
|
Kubernetes Cloud Native 开发工具
云原生|kubernetes|helm3 自定义离线安装部署ingress-nginx
云原生|kubernetes|helm3 自定义离线安装部署ingress-nginx
128 0

推荐镜像

更多