CustomResourceDefinition(CRD)是 v1.7 + 新增的無需改變代碼就能夠擴展 Kubernetes API 的機制,用來管理自定義對象。它其實是 ThirdPartyResources(TPR) 的升級版本,而 TPR 已經在 v1.8 中刪除。git
其實crd在不少k8s周邊開源項目中有使用,好比ingress-controller和衆多的operator。github
在使用 CRD 擴展 Kubernetes API 時,一般還須要實現一個新建資源的控制器,監聽改資源的變化狀況,並做進一步的處理。官方提供的示例項目sample-controller。
這個例子主要講述瞭如下幾個方面:golang
編寫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/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