今天小編給大家分享一下kuberenetes CRD開發(fā)方法是什么的相關知識點,內(nèi)容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

創(chuàng)新互聯(lián)主營拉薩網(wǎng)站建設的網(wǎng)絡公司,主營網(wǎng)站建設方案,app軟件開發(fā),拉薩h5成都小程序開發(fā)搭建,拉薩網(wǎng)站營銷推廣歡迎拉薩等地區(qū)企業(yè)咨詢
擴展kubernetes兩個最常用最需要掌握的東西:自定義資源CRD 和 adminsion webhook.
kubernetes允許用戶自定義自己的資源對象,就如同deployment statefulset一樣,這個應用非常廣泛,比如prometheus opterator就自定義Prometheus對象,再加上一個自定義的controller監(jiān)聽到kubectl create Prometheus時就去創(chuàng)建Pod組成一個pormetheus集群。rook等等同理。
我需要用kubernetes調(diào)度虛擬機,所以這里自定義一個 VirtualMachine 類型
kubebuilder能幫我們節(jié)省大量工作,讓開發(fā)CRD和adminsion webhook變得異常簡單。
通過源碼安裝:
git clone https://github.com/kubernetes-sigs/kubebuilder cd kubebuilder make build cp bin/kubebuilder $GOPATH/bin
或者下載二進制:
os=$(go env GOOS)
arch=$(go env GOARCH)
# download kubebuilder and extract it to tmp
curl -sL https://go.kubebuilder.io/dl/2.0.0-beta.0/${os}/${arch} | tar -xz -C /tmp/
# move to a long-term location and put it on your path
# (you'll need to set the KUBEBUILDER_ASSETS env var if you put it somewhere else)
sudo mv /tmp/kubebuilder_2.0.0-beta.0_${os}_${arch} /usr/local/kubebuilder
export PATH=$PATH:/usr/local/kubebuilder/bin還需要裝下kustomize 這可是個渲染yaml的神器,讓helm顫抖。
go install sigs.k8s.io/kustomize/v3/cmd/kustomize
注意你得先有個kubernetes集群,一步安裝走你
創(chuàng)建CRD
kubebuilder init --domain sealyun.com --license apache2 --owner "fanux" kubebuilder create api --group infra --version v1 --kind VirtulMachine
安裝CRD并啟動controller
make install # 安裝CRD make run # 啟動controller
然后我們就可以看到創(chuàng)建的CRD了
# kubectl get crd NAME AGE virtulmachines.infra.sealyun.com 52m
來創(chuàng)建一個虛擬機:
# kubectl apply -f config/samples/ # kubectl get virtulmachines.infra.sealyun.com NAME AGE virtulmachine-sample 49m
看一眼yaml文件:
# cat config/samples/infra_v1_virtulmachine.yaml apiVersion: infra.sealyun.com/v1 kind: VirtulMachine metadata: name: virtulmachine-sample spec: # Add fields here foo: bar
這里僅僅是把yaml存到etcd里了,我們controller監(jiān)聽到創(chuàng)建事件時啥事也沒干。
把controller部署到集群中
make docker-build docker-push IMG=fanux/infra-controller make deploy
我是連的遠端的kubenetes, make docker-build時test過不去,沒有etcd的bin文件,所以先把test關了。
修改Makefile:
# docker-build: test docker-build:
Dockerfile里的gcr.io/distroless/static:latest 這個鏡像你也可能拉不下來,隨意改改就行,我改成了golang:1.12.7
也有可能構建時有些代碼拉不下來,啟用一下go mod vendor 把依賴打包進去
go mod vendor 如果你本地有些代碼拉不下來,可以用proxy:
export GOPROXY=https://goproxy.io
再改下Dockerfile, 注釋掉download:
修改后:
# Build the manager binary FROM golang:1.12.7 as builder WORKDIR /go/src/github.com/fanux/sealvm # Copy the Go Modules manifests COPY . . # Build RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o manager main.go # Use distroless as minimal base image to package the manager binary # Refer to https://github.com/GoogleContainerTools/distroless for more details # FROM gcr.io/distroless/static:latest FROM golang:1.12.7 WORKDIR / COPY --from=builder /go/src/github.com/fanux/sealvm/manager . ENTRYPOINT ["/manager"]
make deploy 時報錯: Error: json: cannot unmarshal string into Go struct field Kustomization.patches of type types.Patch
把 config/default/kustomization.yaml 中的 patches: 改成 patchesStrategicMerge: 即可
kustomize build config/default 這個命令就渲染出了controller的yaml文件,可以體驗下
看 你的controller已經(jīng)跑起來了:
kubectl get deploy -n sealvm-system NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE sealvm-controller-manager 1 1 1 0 3m kubectl get svc -n sealvm-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE sealvm-controller-manager-metrics-service ClusterIP 10.98.71.199 <none> 8443/TCP 4m
看下config/samples下面的yaml文件:
apiVersion: infra.sealyun.com/v1 kind: VirtulMachine metadata: name: virtulmachine-sample spec: # Add fields here foo: bar
這里參數(shù)里有foo:bar, 那我們來加個虛擬CPU,內(nèi)存信息:
直接api/v1/virtulmachine_types.go即可
// VirtulMachineSpec defines the desired state of VirtulMachine
// 在這里加信息
type VirtulMachineSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file
CPU string `json:"cpu"` // 這是我增加的
Memory string `json:"memory"`
}
// VirtulMachineStatus defines the observed state of VirtulMachine
// 在這里加狀態(tài)信息,比如虛擬機是啟動狀態(tài),停止狀態(tài)啥的
type VirtulMachineStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
}然后make一下:
make && make install && make run
這時再去渲染一下controller的yaml就會發(fā)現(xiàn)CRD中已經(jīng)帶上CPU和內(nèi)存信息了:
kustomize build config/default
properties: cpu: description: 'INSERT ADDITIONAL SPEC FIELDS - desired state of cluster Important: Run "make" to regenerate code after modifying this file' type: string memory: type: string
修改一下yaml:
apiVersion: infra.sealyun.com/v1 kind: VirtulMachine metadata: name: virtulmachine-sample spec: cpu: "1" memory: "2G"
# kubectl apply -f config/samples
virtulmachine.infra.sealyun.com "virtulmachine-sample" configured
# kubectl get virtulmachines.infra.sealyun.com virtulmachine-sample -o yaml
apiVersion: infra.sealyun.com/v1
kind: VirtulMachine
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"infra.sealyun.com/v1","kind":"VirtulMachine","metadata":{"annotations":{},"name":"virtulmachine-sample","namespace":"default"},"spec":{"cpu":"1","memory":"2G"}}
creationTimestamp: 2019-07-26T08:47:34Z
generation: 2
name: virtulmachine-sample
namespace: default
resourceVersion: "14811698"
selfLink: /apis/infra.sealyun.com/v1/namespaces/default/virtulmachines/virtulmachine-sample
uid: 030e2b9a-af82-11e9-b63e-5254bc16e436
spec: # 新的CRD已生效
cpu: "1"
memory: 2GStatus 同理,就不再贅述了,比如我把status里加一個Create, 表示controller要去創(chuàng)建虛擬機了(主要一些控制層面的邏輯),創(chuàng)建完了把狀態(tài)改成Running
controller把輪訓與事件監(jiān)聽都封裝在這一個接口里了.你不需要關心怎么事件監(jiān)聽的.
func (r *VirtulMachineReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
ctx = context.Background()
_ = r.Log.WithValues("virtulmachine", req.NamespacedName)
vm := &v1.VirtulMachine{}
if err := r.Get(ctx, req.NamespacedName, vm); err != nil { # 獲取VM信息
log.Error(err, "unable to fetch vm")
} else {
fmt.Println(vm.Spec.CPU, vm.Spec.Memory) # 打印CPU內(nèi)存信息
}
return ctrl.Result{}, nil
}make && make install && make run這個時候去創(chuàng)建一個虛擬機kubectl apply -f config/samples,日志里就會輸出CPU內(nèi)存了. List接口同理,我就不贅述了
r.List(ctx, &vms, client.InNamespace(req.Namespace), client.MatchingField(vmkey, req.Name))
在status結構體中加入狀態(tài)字段:
type VirtulMachineStatus struct {
Status string `json:"status"`
}controller里去更新狀態(tài):
vm.Status.Status = "Running"
if err := r.Status().Update(ctx, vm); err != nil {
log.Error(err, "unable to update vm status")
}如果出現(xiàn):the server could not find the requested resource 這個錯誤,那么在CRD結構體上需要加個注釋 // +kubebuilder:subresource:status:
// +kubebuilder:subresource:status
// +kubebuilder:object:root=true
type VirtulMachine struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec VirtulMachineSpec `json:"spec,omitempty"`
Status VirtulMachineStatus `json:"status,omitempty"`
}這樣就好了
編譯啟動后再去apply發(fā)現(xiàn)狀態(tài)已經(jīng)變成running:
# kubectl get virtulmachines.infra.sealyun.com virtulmachine-sample -o yaml ... status: status: Running
time.Sleep(time.Second * 10)
if err := r.Delete(ctx, vm); err != nil {
log.Error(err, "unable to delete vm ", "vm", vm)
}10s之后我們將GET不到
如果不使用Finalizers,kubectl delete 時直接就刪了etcd數(shù)據(jù),controller再想去拿CRD時已經(jīng)拿不到了:
ERRO[0029] VirtulMachine.infra.sealyun.com "virtulmachine-sample" not foundunable to fetch vm source="virtulmachine_controller.go:48"
所以在創(chuàng)建時我們需要給CRD加上Finalizer:
vm.ObjectMeta.Finalizers = append(vm.ObjectMeta.Finalizers, "virtulmachine.infra.sealyun.com")
然后刪除時就只會給CRD打上一個刪除時間戳,供我們做后續(xù)處理, 處理完了我們刪除掉Finalizers:
如果 DeleteionTimestamp不存在 如果沒有Finalizers 加上Finalizers,并更新CRD 要不然,說明是要被刪除的 如果存在Finalizers,刪除Finalizers,并更新CRD
看個完整的代碼示例:
if cronJob.ObjectMeta.DeletionTimestamp.IsZero() {
if !containsString(cronJob.ObjectMeta.Finalizers, myFinalizerName) {
cronJob.ObjectMeta.Finalizers = append(cronJob.ObjectMeta.Finalizers, myFinalizerName)
if err := r.Update(context.Background(), cronJob); err != nil {
return ctrl.Result{}, err
}
}
} else {
if containsString(cronJob.ObjectMeta.Finalizers, myFinalizerName) {
if err := r.deleteExternalResources(cronJob); err != nil {
return ctrl.Result{}, err
}
cronJob.ObjectMeta.Finalizers = removeString(cronJob.ObjectMeta.Finalizers, myFinalizerName)
if err := r.Update(context.Background(), cronJob); err != nil {
return ctrl.Result{}, err
}
}
}kuberentes有三種webhook,admission webhook, authorization webhook and CRD conversion webhook.
這里比如我們要給CRD設置一些默認值,又或者是用戶創(chuàng)建時少填了一些參數(shù),那么我們得禁止創(chuàng)建等等這些事。
使用webhook也非常的簡單,只需給定義的結構體實現(xiàn) Defaulter 和 Validator接口即可.
Reconcile結構體聚合了Client接口,所以client的所有方法都是可以直接調(diào)用,大部分是對CRD object的相關操作
type Client interface {
Reader
Writer
StatusClient
}// Reader knows how to read and list Kubernetes objects.
type Reader interface {
// Get retrieves an obj for the given object key from the Kubernetes Cluster.
// obj must be a struct pointer so that obj can be updated with the response
// returned by the Server.
Get(ctx context.Context, key ObjectKey, obj runtime.Object) error
// List retrieves list of objects for a given namespace and list options. On a
// successful call, Items field in the list will be populated with the
// result returned from the server.
List(ctx context.Context, list runtime.Object, opts ...ListOptionFunc) error
}
// Writer knows how to create, delete, and update Kubernetes objects.
type Writer interface {
// Create saves the object obj in the Kubernetes cluster.
Create(ctx context.Context, obj runtime.Object, opts ...CreateOptionFunc) error
// Delete deletes the given obj from Kubernetes cluster.
Delete(ctx context.Context, obj runtime.Object, opts ...DeleteOptionFunc) error
// Update updates the given obj in the Kubernetes cluster. obj must be a
// struct pointer so that obj can be updated with the content returned by the Server.
Update(ctx context.Context, obj runtime.Object, opts ...UpdateOptionFunc) error
// Patch patches the given obj in the Kubernetes cluster. obj must be a
// struct pointer so that obj can be updated with the content returned by the Server.
Patch(ctx context.Context, obj runtime.Object, patch Patch, opts ...PatchOptionFunc) error
}
// StatusClient knows how to create a client which can update status subresource
// for kubernetes objects.
type StatusClient interface {
Status() StatusWriter
}以上就是“kuberenetes CRD開發(fā)方法是什么”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
分享文章:kuberenetesCRD開發(fā)方法是什么
文章地址:http://chinadenli.net/article26/jpcpcg.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設計、網(wǎng)站維護、用戶體驗、網(wǎng)站設計公司、網(wǎng)站收錄、手機網(wǎng)站建設
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)