k8s之CRD--为自定义资源生成代码

CRD简介和使用姿式

CustomResourceDefinition(CRD)是 v1.7 + 新增的无需改变代码就能够扩展 Kubernetes API 的机制,用来管理自定义对象。它其实是 ThirdPartyResources(TPR) 的升级版本,而 TPR 已经在 v1.8 中删除。git

一些使用场景:

  • 提供/管理外部数据存储/数据库(例如 CloudSQL/RDS 实例)
  • 对k8s基础资源进行更高层次的抽象(好比定义一个etcd集群)

其实crd在不少k8s周边开源项目中有使用,好比ingress-controller和众多的operator。github

CRD 控制器

在使用 CRD 扩展 Kubernetes API 时,一般还须要实现一个新建资源的控制器,监听改资源的变化状况,并做进一步的处理。官方提供的示例项目sample-controller
这个例子主要讲述了如下几个方面:golang

  • 如何使用自定义资源定义注册Foo类型的新自定义资源(自定义资源类型)
  • 如何建立/获取/列出新资源类型Foo实例
  • 如何在资源处理建立/更新/删除事件上设置控制器

编写crd controller以前,必定要使用k8s官方提供的代码生成工具k8s.io/code-generator 去生成 client, informers, listers and deep-copy函数.不只代码风格符合k8s,并且减小出错和减小工做量都是有很大的帮助。shell

在项目中使用代码生成器

下面展现了代码生成工具是如何工做的以及如何使用最少的代码行将它们应用到本身的项目中,从而为您生成 deepcopy 函数/typed clients/listers/informer,全部这些的生成仅须要一个 shell 脚本调用和部分代码注释。
不要以为代码生成有多么复杂,其实官方已经作了不少工做了,提供了 generator-group.sh。看过client-go的gopher应该都知道项目中有大量代码工具生成的代码。
执行./hack/update-codegen.sh,即数据库

#!/usr/bin/env bash

# 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.

set -o errexit
set -o nounset
set -o pipefail

SCRIPT_ROOT=$(dirname ${BASH_SOURCE})/..
CODEGEN_PKG=${CODEGEN_PKG:-$(cd ${SCRIPT_ROOT}; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)}

# generate the code with:
# --output-base    because this script should also be able to run inside the vendor dir of
#                  k8s.io/kubernetes. The output-base is needed for the generators to output into the vendor dir
#                  instead of the $GOPATH directly. For normal projects this can be dropped.
${CODEGEN_PKG}/generate-groups.sh "deepcopy,client,informer,lister" \
  k8s.io/canary-controller/pkg/client k8s.io/canary-controller/pkg/apis \
  canarycontroller:v1alpha1 \
  --output-base "$(dirname ${BASH_SOURCE})/../../.." \
  --go-header-file ${SCRIPT_ROOT}/hack/boilerplate.go.txt

# To use your own boilerplate text use:
#   --go-header-file ${SCRIPT_ROOT}/hack/custom-boilerplate.go.txt

update-codegen脚本将自动生成下面的文件和路径express

  • pkg/apis/canarycontroller/v1alpha1/zz_generated.deepcopy.go
  • pkg/client/

脚本运行后大致会创建以下的包管理结构:
图片描述
是否是很简单?pkg/client 代码是被彻底生成的,就像包含咱们的 CustomResource golang语言类型的 types.go 文件下面的 zz_generated.deepcopy.go 文件同样,而后你就能够基于生成的代码写本身的controller了。
不过并非不须要本身写一点代码,毕竟机器没有智能到你定义了什么样子的crd。全部如下几个文件须要本身来定义和实现,均是和你本身的业务逻辑相关。
pkg/apis如下的除zz_generated.deepcopy.go之外的全部文件。
好比:
types.goapache

/*
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.
*/

package v1alpha1

import (
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// Canary is a specification for a Foo resource
type Canary struct {
    metav1.TypeMeta   `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`

    Spec   CanarySpec   `json:"spec"`
    Status CanaryStatus `json:"status"`
}

// CanarySpec is the spec for a Foo resource
type CanarySpec struct {
    DeploymentName string `json:"deploymentName"`
    Replicas       *int32 `json:"replicas"`
}

// CanaryStatus is the status for a Foo resource
type CanaryStatus struct {
    AvailableReplicas int32 `json:"availableReplicas"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// CanaryList is a list of Foo resources
type CanaryList struct {
    metav1.TypeMeta `json:",inline"`
    metav1.ListMeta `json:"metadata"`

    Items []Canary `json:"items"`
}

registry.gojson

/*
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.
*/

package v1alpha1

import (
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/apimachinery/pkg/runtime"
    "k8s.io/apimachinery/pkg/runtime/schema"

    canarycontroller "k8s.io/canary-controller/pkg/apis/canarycontroller"
)

// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{Group: canarycontroller.GroupName, Version: "v1alpha1"}

// Kind takes an unqualified kind and returns back a Group qualified GroupKind
func Kind(kind string) schema.GroupKind {
    return SchemeGroupVersion.WithKind(kind).GroupKind()
}

// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
    return SchemeGroupVersion.WithResource(resource).GroupResource()
}

var (
    SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
    AddToScheme   = SchemeBuilder.AddToScheme
)

// Adds the list of known types to Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
    scheme.AddKnownTypes(SchemeGroupVersion,
        &Canary{},
        &CanaryList{},
    )
    metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
    return nil
}

更多相关细节

Kubernetes Deep Dive: Code Generation for CustomResources给出了具体的步骤和关于tag的标注。api

总结

基于crd以及crd controller能够抽象不少业务场景。接下我司准备实现一个部署策略相关的项目。bash

相关文章
相关标签/搜索