第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問(wèn)題,去搜搜看,總會(huì)有你想問(wèn)的

k8s controller watch other controller CR

k8s controller watch other controller CR

Go
慕俠2389804 2023-03-07 16:48:30
我有 k8s 操作員,它按預(yù)期工作,我需要向其他操作員 CRD(不是我的)添加一個(gè)“手表”,為了簡(jiǎn)單起見,讓我們調(diào)用它,extCR我們的操作員 cr 調(diào)用inCR,我嘗試了以下操作,但有一個(gè)問(wèn)題是它如何觸發(fā)協(xié)調(diào)。func (r *Insiconciler) SetupWithManager(mgr ctrl.Manager) error {                return ctrl.NewControllerManagedBy(mgr).                    For(&Inv1alpha1.Iget{}}).                    Watches(&source.Kind{Type: &ext.Se{}},  handler.EnqueueRequestsFromMapFunc(r.FWatch)).                    Complete(r)}    func (r *Insiconciler) FWatch(c client.Object) []reconcile.Request {        val := c.(*ivi.Srv)        req := reconcile.Request{NamespacedName: types.NamespacedName{Name: val.Name, Namespace: val.Namespace}}        return []reconcile.Request{req}}這里的問(wèn)題是我觸發(fā)了協(xié)調(diào)extCR,我想在里面FWatch更新inCR并開始協(xié)調(diào) inCR 而不是 extCR,我該怎么做?我的意思是,為了避免像下面的代碼這樣的事情,因?yàn)橛袝r(shí)協(xié)調(diào)是為 the 完成的inCR,有時(shí)是為 theextCR而不是我可以得到一些丑陋的 if'sfunc (r *Insiconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {        var inCR FOO        var extCR BAR            if err := r.Get(ctx, req.NamespacedName, &inCR); err != nil {            return ctrl.Result{}, err        }                if err := r.Get(ctx, req.NamespacedName, &extCR); err != nil {            return ctrl.Result{}, err        }我想知道處理這種情況的正確/干凈的方法是什么當(dāng)您需要收聽 externalCR(不是您的控制器的一部分)和 internalCR(來(lái)自您的控制器)時(shí)的情況。還有一件事——CR 是不同的 GVK,但是 exteranlCR 包含很多不需要的字段,只是其中的一些。但必填字段 在兩個(gè) cr 上具有相同的名稱更新type inCR struct {    metav1.TypeMeta   `json:",inline"`    metav1.ObjectMeta `json:"metadata,omitempty"`    Spec   inSpec  `json:"spec,omitempty"`  / / ————————here is the difference     Status InsightTargetStatus `json:"status,omitempty"`}//—————— 這是在不屬于我們的其他程序上定義的,因此不能“重用”type Bar struct {    metav1.TypeMeta   `json:",inline"`    metav1.ObjectMeta `json:"metadata,omitempty"`    Spec   extSpec  `json:"spec,omitempty"`    // ———————here is the difference     Status ServiceStatus `json:"status,omitempty"`}并且inSpec具有以下字段(extSpec 的子集)type inSpec struct {    name string    age  int}
查看完整描述

1 回答

?
HUWWW

TA貢獻(xiàn)1874條經(jīng)驗(yàn) 獲得超12個(gè)贊

請(qǐng)記住以下幾點(diǎn):

  • 每個(gè)控制器只負(fù)責(zé)一個(gè)資源。

  • 協(xié)調(diào)請(qǐng)求包含協(xié)調(diào) Kubernetes 對(duì)象所需的信息。這包括唯一標(biāo)識(shí)對(duì)象的信息 - 它的名稱和命名空間。它不包含有關(guān)任何特定事件或?qū)ο髢?nèi)容本身的信息。


您可以在沒有資源定義的情況下創(chuàng)建第二個(gè)控制器。在您的主文件中,兩個(gè)控制器都將被注冊(cè)。

如果 CRD 根本不相關(guān),或者如果外部資源引用內(nèi)部資源,這可能很有用,因此您可以在外部協(xié)調(diào)器中更改內(nèi)部資源。

kubebuilder create api --group other --version v2 --kind External \

 --resource=false --controller=true

這為您提供了一個(gè)控制器,其SetupWithManager方法如下所示。


func (r *ExternalReconciler) SetupWithManager(mgr ctrl.Manager) error {

    return ctrl.NewControllerManagedBy(mgr).

        // Uncomment the following line adding a pointer to an instance of the controlled resource as an argument

        // For().

        Complete(r)

}

請(qǐng)注意 For 方法是如何被注釋掉的,因?yàn)槟枰獙?dǎo)入資源以從其他地方觀看并引用它。


import (

    ...

    otherv2 "other.io/external/api/v2"

)

...

func (r *ExternalReconciler) SetupWithManager(mgr ctrl.Manager) error {

    return ctrl.NewControllerManagedBy(mgr).

        For(&otherv2.External{}).

        Complete(r)

}

如果您無(wú)法導(dǎo)入外部資源,您可以回過(guò)頭來(lái)自己模擬它,但這可能不是一種非常干凈的方法。您真的應(yīng)該嘗試從其他控制器項(xiàng)目中導(dǎo)入它。


kubebuilder edit --multigroup=true

kubebuilder create api --group=other --version v2 --kind External \

  --resource --controller

另一種方式是當(dāng)資源相互關(guān)聯(lián)時(shí),內(nèi)部資源在其規(guī)范中引用了外部資源,并且知道如何在其協(xié)調(diào)時(shí)獲取其規(guī)范中的外部資源。可以在這里找到一個(gè)例子https://book.kubebuilder.io/reference/watching-resources/externally-managed.html


type InternalSpec struct {

    // Name of an external resource

    ExternalResource string `json:"externalResource,omitempty"`

}

這意味著在每個(gè)協(xié)調(diào)循環(huán)中,控制器將查找外部資源并使用它來(lái)管理內(nèi)部資源。


func (r *InternalReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {

    _ = log.FromContext(ctx)


    internal := examplev1.Internal{}

    if err := r.Get(context.TODO(), types.NamespacedName{

        Name:      req.Name,

        Namespace: req.Namespace,

    }, &internal); err != nil {

        return ctrl.Result{}, err

    }


    external := otherv2.External{}

    if err := r.Get(context.TODO(), types.NamespacedName{

        // note how the name is taken from the internal spec

        Name:      internal.Spec.ExternalResource,

        Namespace: req.Namespace,

    }, &internal); err != nil {

        return ctrl.Result{}, err

    }


    // do something with internal and external here


    return ctrl.Result{}, nil

}

這樣做的問(wèn)題是,當(dāng)內(nèi)部資源沒有變化時(shí),即使外部資源發(fā)生變化,也不會(huì)觸發(fā)協(xié)調(diào)事件。為了解決這個(gè)問(wèn)題,我們可以通過(guò)觀察外部資源來(lái)觸發(fā)協(xié)調(diào)。注意Watches方法:


func (r *InternalReconciler) SetupWithManager(mgr ctrl.Manager) error {

    return ctrl.NewControllerManagedBy(mgr).

        For(&examplev1.Main{}).

        Watches(

            &source.Kind{Type: &otherv2.ExternalResource{}},

            handler.EnqueueRequestsFromMapFunc(r.triggerReconcileBecauseExternalHasChanged),

            builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}),

        ).

        Complete(r)

}

為了知道我們應(yīng)該為哪個(gè)內(nèi)部對(duì)象觸發(fā)事件,我們使用映射函數(shù)來(lái)查找所有引用外部資源的內(nèi)部對(duì)象。


func (r *InternalReconciler) triggerReconcileBecauseExternalHasChanged(o client.Object) []reconcile.Request {

    usedByInternals := &examplev1.InternalList{}

    listOps := &client.ListOptions{

        FieldSelector: fields.OneTermEqualSelector(".spec.ExternalResource", o.GetName()),

        Namespace:     o.GetNamespace(),

    }

    err := r.List(context.TODO(), usedByInternals, listOps)

    if err != nil {

        return []reconcile.Request{}

    }

    requests := make([]reconcile.Request, len(usedByInternals.Items))

    for i, item := range usedByInternals.Items {

        requests[i] = reconcile.Request{

            NamespacedName: types.NamespacedName{

                Name:      item.GetName(),

                Namespace: item.GetNamespace(),

            },

        }

    }

    return requests

}

由于您更新了問(wèn)題,我建議您執(zhí)行以下操作。


我正在創(chuàng)建一個(gè)新項(xiàng)目和 2 個(gè)控制器。注意第二個(gè)控制器命令沒有資源與控制器一起創(chuàng)建。這是因?yàn)榭刂破鲗⒈O(jiān)視外部資源。


mkdir demo && cd demo

go mod init example.io/demo

kubebuilder init --domain example.io --repo example.io/demo --plugins=go/v4-alpha

kubebuilder create api --group=demo --version v1 --kind Internal --controller --resource

kubebuilder create api --group=other --version v2 --kind External --controller --resource=false

$ tree controllers

controllers

├── external_controller.go

├── internal_controller.go

└── suite_test.go

現(xiàn)在我們需要一些共享邏輯,例如將其添加到控制器包中。我們將從兩個(gè)調(diào)解器中調(diào)用它。


// the interface may need tweaking

// depending on what you want to do with

// the reconiler

type reconciler interface {

 client.Reader

 client.Writer

 client.StatusClient

}


func sharedLogic(r reconciler, kobj *demov1.Internal) (ctrl.Result, error) {

 // do your shared logic here operating on the internal object struct

 // this works out because the external controller will call this passing the

 // internal object

 return ctrl.Result{}, nil

}

這是內(nèi)部協(xié)調(diào)器的示例。


func (r *InternalReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {

 _ = log.FromContext(ctx)

 obj := demov1.Internal{}

 if err := r.Get(ctx, req.NamespacedName, &obj); err != nil {

  return ctrl.Result{}, err

 }

 return sharedLogic(r, &obj)

}

在外部協(xié)調(diào)器中,我們也這樣做。


func (r *ExternalReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {

 _ = log.FromContext(ctx)

 // note, we can use the internal object here as long as the external object

 // does contain the same fields we want. That means when unmarshalling the extra

 // fields are dropped. If this cannot be done, you could first unmarshal into the external

 // resource and then assign the fields you need to the internal one, before passing it down

 obj := demov1.Internal{}

 if err := r.Get(ctx, req.NamespacedName, &obj); err != nil {

  return ctrl.Result{}, err

 }

 return sharedLogic(r, &obj)

}


func (r *ExternalReconciler) SetupWithManager(mgr ctrl.Manager) error {

 return ctrl.NewControllerManagedBy(mgr).

 // note the external resource is imported from another project

 // you may be able to watch this without import by creating a minimal

 // type with the right GKV

  For(otherv2.External{}).

  Complete(r)

}


查看完整回答
反對(duì) 回復(fù) 2023-03-07
  • 1 回答
  • 0 關(guān)注
  • 166 瀏覽
慕課專欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)