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

相關文章
相關標籤/搜索